00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include <qevent.h>
00023
#include <qkeycode.h>
00024
#include <qheader.h>
00025
#include <qpainter.h>
00026
#include <qpixmap.h>
00027
00028
#include <kapplication.h>
00029
#include <kfileitem.h>
00030
#include <kglobal.h>
00031
#include <kglobalsettings.h>
00032
#include <kiconloader.h>
00033
#include <kicontheme.h>
00034
#include <klocale.h>
00035
#include <kdebug.h>
00036
#include <kurldrag.h>
00037
00038
#include "kfiledetailview.h"
00039
#include "config-kfile.h"
00040
00041
#define COL_NAME 0
00042
#define COL_SIZE 1
00043
#define COL_DATE 2
00044
#define COL_PERM 3
00045
#define COL_OWNER 4
00046
#define COL_GROUP 5
00047
00048
class KFileDetailView::KFileDetailViewPrivate
00049 {
00050
public:
00051 KFileDetailViewPrivate() : dropItem(0)
00052 { }
00053
00054
KFileListViewItem *dropItem;
00055
QTimer autoOpenTimer;
00056 };
00057
00058 KFileDetailView::KFileDetailView(
QWidget *parent,
const char *name)
00059 :
KListView(parent,
name),
KFileView(), d(new KFileDetailViewPrivate())
00060 {
00061
00062 m_sortingCol = COL_NAME;
00063 m_blockSortingSignal =
false;
00064 setViewName( i18n(
"Detailed View") );
00065
00066 addColumn( i18n(
"Name" ) );
00067 addColumn( i18n(
"Size" ) );
00068 addColumn( i18n(
"Date" ) );
00069 addColumn( i18n(
"Permissions" ) );
00070 addColumn( i18n(
"Owner" ) );
00071 addColumn( i18n(
"Group" ) );
00072 setShowSortIndicator(
true );
00073 setAllColumnsShowFocus(
true );
00074 setDragEnabled(
true);
00075
00076 connect( header(), SIGNAL( clicked(
int)),
00077 SLOT(slotSortingChanged(
int) ));
00078
00079
00080 connect(
this, SIGNAL( returnPressed(
QListViewItem *) ),
00081 SLOT( slotActivate(
QListViewItem *) ) );
00082
00083 connect(
this, SIGNAL( clicked(
QListViewItem *,
const QPoint&,
int)),
00084 SLOT( selected(
QListViewItem *) ) );
00085 connect(
this, SIGNAL( doubleClicked(
QListViewItem *,
const QPoint&,
int)),
00086 SLOT( slotActivate(
QListViewItem *) ) );
00087
00088 connect(
this, SIGNAL(contextMenuRequested(
QListViewItem *,
00089
const QPoint &,
int )),
00090
this, SLOT( slotActivateMenu(
QListViewItem *,
const QPoint& )));
00091
00092 KFile::SelectionMode sm = KFileView::selectionMode();
00093
switch ( sm ) {
00094
case KFile::Multi:
00095 QListView::setSelectionMode( QListView::Multi );
00096
break;
00097
case KFile::Extended:
00098 QListView::setSelectionMode( QListView::Extended );
00099
break;
00100
case KFile::NoSelection:
00101 QListView::setSelectionMode( QListView::NoSelection );
00102
break;
00103
default:
00104
case KFile::Single:
00105 QListView::setSelectionMode( QListView::Single );
00106
break;
00107 }
00108
00109
00110
if ( sm == KFile::Multi || sm == KFile::Extended )
00111 connect(
this, SIGNAL( selectionChanged() ),
00112 SLOT( slotSelectionChanged() ));
00113
else
00114 connect(
this, SIGNAL( selectionChanged(
QListViewItem * ) ),
00115 SLOT( highlighted(
QListViewItem * ) ));
00116
00117
00118 connect( &(d->autoOpenTimer), SIGNAL( timeout() ),
00119
this, SLOT( slotAutoOpen() ));
00120
00121 setSorting( sorting() );
00122
00123 m_resolver =
00124
new KMimeTypeResolver<KFileListViewItem,KFileDetailView>(
this );
00125 }
00126
00127 KFileDetailView::~KFileDetailView()
00128 {
00129
delete m_resolver;
00130
delete d;
00131 }
00132
00133
void KFileDetailView::readConfig(
KConfig *config,
const QString& group )
00134 {
00135
restoreLayout( config, group );
00136 }
00137
00138
void KFileDetailView::writeConfig(
KConfig *config,
const QString& group )
00139 {
00140
saveLayout( config, group );
00141 }
00142
00143 void KFileDetailView::setSelected(
const KFileItem *info,
bool enable )
00144 {
00145
if ( !info )
00146
return;
00147
00148
00149
KFileListViewItem *item = (
KFileListViewItem*)info->
extraData(
this );
00150
00151
if ( item )
00152 KListView::setSelected( item, enable );
00153 }
00154
00155 void KFileDetailView::setCurrentItem(
const KFileItem *item )
00156 {
00157
if ( !item )
00158
return;
00159
KFileListViewItem *it = (
KFileListViewItem*) item->
extraData(
this );
00160
if ( it )
00161 KListView::setCurrentItem( it );
00162 }
00163
00164 KFileItem *
KFileDetailView::currentFileItem()
const
00165
{
00166
KFileListViewItem *current = static_cast<KFileListViewItem*>( currentItem() );
00167
if ( current )
00168
return current->
fileInfo();
00169
00170
return 0L;
00171 }
00172
00173 void KFileDetailView::clearSelection()
00174 {
00175 KListView::clearSelection();
00176 }
00177
00178 void KFileDetailView::selectAll()
00179 {
00180
if (KFileView::selectionMode() == KFile::NoSelection ||
00181 KFileView::selectionMode() == KFile::Single)
00182
return;
00183
00184 KListView::selectAll(
true );
00185 }
00186
00187 void KFileDetailView::invertSelection()
00188 {
00189 KListView::invertSelection();
00190 }
00191
00192
void KFileDetailView::slotActivateMenu (
QListViewItem *item,
const QPoint& pos )
00193 {
00194
if ( !item ) {
00195 sig->
activateMenu( 0, pos );
00196
return;
00197 }
00198
KFileListViewItem *i = (
KFileListViewItem*) item;
00199 sig->
activateMenu( i->
fileInfo(), pos );
00200 }
00201
00202 void KFileDetailView::clearView()
00203 {
00204 m_resolver->
m_lstPendingMimeIconItems.clear();
00205 KListView::clear();
00206 }
00207
00208 void KFileDetailView::insertItem(
KFileItem *i )
00209 {
00210
KFileView::insertItem( i );
00211
00212
KFileListViewItem *item =
new KFileListViewItem( (
QListView*)
this, i );
00213
00214 setSortingKey( item, i );
00215
00216 i->
setExtraData(
this, item );
00217
00218
if ( !i->
isMimeTypeKnown() )
00219 m_resolver->
m_lstPendingMimeIconItems.append( item );
00220 }
00221
00222
void KFileDetailView::slotActivate(
QListViewItem *item )
00223 {
00224
if ( !item )
00225
return;
00226
00227
const KFileItem *fi = ( (
KFileListViewItem*)item )->fileInfo();
00228
if ( fi )
00229 sig->
activate( fi );
00230 }
00231
00232
void KFileDetailView::selected(
QListViewItem *item )
00233 {
00234
if ( !item )
00235
return;
00236
00237
if (
KGlobalSettings::singleClick() ) {
00238
const KFileItem *fi = ( (
KFileListViewItem*)item )->fileInfo();
00239
if ( fi && (fi->
isDir() || !
onlyDoubleClickSelectsFiles()) )
00240 sig->
activate( fi );
00241 }
00242 }
00243
00244
void KFileDetailView::highlighted(
QListViewItem *item )
00245 {
00246
if ( !item )
00247
return;
00248
00249
const KFileItem *fi = ( (
KFileListViewItem*)item )->fileInfo();
00250
if ( fi )
00251 sig->
highlightFile( fi );
00252 }
00253
00254
00255
void KFileDetailView::setSelectionMode( KFile::SelectionMode sm )
00256 {
00257 disconnect(
this, SIGNAL( selectionChanged() ));
00258 disconnect(
this, SIGNAL( selectionChanged(
QListViewItem * ) ));
00259
00260 KFileView::setSelectionMode( sm );
00261
00262
switch ( KFileView::selectionMode() ) {
00263
case KFile::Multi:
00264 QListView::setSelectionMode( QListView::Multi );
00265
break;
00266
case KFile::Extended:
00267 QListView::setSelectionMode( QListView::Extended );
00268
break;
00269
case KFile::NoSelection:
00270 QListView::setSelectionMode( QListView::NoSelection );
00271
break;
00272
default:
00273
case KFile::Single:
00274 QListView::setSelectionMode( QListView::Single );
00275
break;
00276 }
00277
00278
if ( sm == KFile::Multi || sm == KFile::Extended )
00279 connect(
this, SIGNAL( selectionChanged() ),
00280 SLOT( slotSelectionChanged() ));
00281
else
00282 connect(
this, SIGNAL( selectionChanged(
QListViewItem * )),
00283 SLOT( highlighted(
QListViewItem * )));
00284 }
00285
00286 bool KFileDetailView::isSelected(
const KFileItem *i )
const
00287
{
00288
if ( !i )
00289
return false;
00290
00291
KFileListViewItem *item = (
KFileListViewItem*) i->
extraData(
this );
00292
return (item && item->isSelected());
00293 }
00294
00295
00296 void KFileDetailView::updateView(
bool b )
00297 {
00298
if ( !b )
00299
return;
00300
00301
QListViewItemIterator it( (
QListView*)
this );
00302
for ( ; it.current(); ++it ) {
00303
KFileListViewItem *item=static_cast<KFileListViewItem *>(it.current());
00304 item->setPixmap( 0, item->
fileInfo()->
pixmap(KIcon::SizeSmall) );
00305 }
00306 }
00307
00308
void KFileDetailView::updateView(
const KFileItem *i )
00309 {
00310
if ( !i )
00311
return;
00312
00313
KFileListViewItem *item = (
KFileListViewItem*) i->
extraData(
this );
00314
if ( !item )
00315
return;
00316
00317 item->
init();
00318 setSortingKey( item, i );
00319
00320
00321 }
00322
00323
void KFileDetailView::setSortingKey(
KFileListViewItem *item,
00324
const KFileItem *i )
00325 {
00326
00327 QDir::SortSpec spec =
KFileView::sorting();
00328
00329
if ( spec & QDir::Time )
00330 item->
setKey(
sortingKey( i->
time( KIO::UDS_MODIFICATION_TIME ),
00331 i->
isDir(), spec ));
00332
else if ( spec & QDir::Size )
00333 item->
setKey(
sortingKey( i->
size(), i->
isDir(), spec ));
00334
00335
else
00336 item->
setKey(
sortingKey( i->
text(), i->
isDir(), spec ));
00337 }
00338
00339
00340 void KFileDetailView::removeItem(
const KFileItem *i )
00341 {
00342
if ( !i )
00343
return;
00344
00345
KFileListViewItem *item = (
KFileListViewItem*) i->
extraData(
this );
00346 m_resolver->
m_lstPendingMimeIconItems.remove( item );
00347
delete item;
00348
00349
KFileView::removeItem( i );
00350 }
00351
00352
void KFileDetailView::slotSortingChanged(
int col )
00353 {
00354
00355
00356 QDir::SortSpec sort =
sorting();
00357
int sortSpec = -1;
00358
bool reversed = (col == m_sortingCol) && (sort & QDir::Reversed) == 0;
00359 m_sortingCol = col;
00360
00361
switch( col ) {
00362
case COL_NAME:
00363 sortSpec = (sort & ~
QDir::SortByMask | QDir::Name);
00364
break;
00365
case COL_SIZE:
00366 sortSpec = (sort & ~
QDir::SortByMask | QDir::Size);
00367
break;
00368
case COL_DATE:
00369 sortSpec = (sort & ~
QDir::SortByMask | QDir::Time);
00370
break;
00371
00372
00373
00374
case COL_OWNER:
00375
case COL_GROUP:
00376
case COL_PERM:
00377
00378 sortSpec = (sort & ~
QDir::SortByMask);
00379
break;
00380
default:
00381
break;
00382 }
00383
00384
if ( reversed )
00385 sortSpec |= QDir::Reversed;
00386
else
00387 sortSpec &= ~
QDir::Reversed;
00388
00389
if ( sort & QDir::IgnoreCase )
00390 sortSpec |= QDir::IgnoreCase;
00391
else
00392 sortSpec &= ~
QDir::IgnoreCase;
00393
00394
00395
KFileView::setSorting( static_cast<QDir::SortSpec>( sortSpec ) );
00396
00397
KFileItem *item;
00398
KFileItemListIterator it( *
items() );
00399
00400
if ( sortSpec & QDir::Time ) {
00401
for ( ; (item = it.current()); ++it )
00402 viewItem(item)->
setKey(
sortingKey( item->
time( KIO::UDS_MODIFICATION_TIME ), item->
isDir(), sortSpec ));
00403 }
00404
00405
else if ( sortSpec & QDir::Size ) {
00406
for ( ; (item = it.current()); ++it )
00407 viewItem(item)->
setKey(
sortingKey( item->
size(), item->
isDir(),
00408 sortSpec ));
00409 }
00410
else {
00411
for ( ; (item = it.current()); ++it ) {
00412
KFileListViewItem *i = viewItem( item );
00413 i->
setKey(
sortingKey( i->text(m_sortingCol), item->
isDir(),
00414 sortSpec ));
00415 }
00416 }
00417
00418
KListView::setSorting( m_sortingCol, !reversed );
00419 KListView::sort();
00420
00421
if ( !m_blockSortingSignal )
00422 sig->
changeSorting( static_cast<QDir::SortSpec>( sortSpec ) );
00423 }
00424
00425
00426 void KFileDetailView::setSorting( QDir::SortSpec spec )
00427 {
00428
int col = 0;
00429
if ( spec & QDir::Time )
00430 col = COL_DATE;
00431
else if ( spec & QDir::Size )
00432 col = COL_SIZE;
00433
else if ( spec & QDir::Unsorted )
00434 col = m_sortingCol;
00435
else
00436 col = COL_NAME;
00437
00438
00439
if ( spec & QDir::Reversed )
00440 spec = (QDir::SortSpec) (spec & ~
QDir::Reversed);
00441
else
00442 spec = (QDir::SortSpec) (spec | QDir::Reversed);
00443
00444 m_sortingCol = col;
00445
KFileView::setSorting( (QDir::SortSpec) spec );
00446
00447
00448
00449 m_blockSortingSignal =
true;
00450 slotSortingChanged( col );
00451 m_blockSortingSignal =
false;
00452 }
00453
00454 void KFileDetailView::ensureItemVisible(
const KFileItem *i )
00455 {
00456
if ( !i )
00457
return;
00458
00459
KFileListViewItem *item = (
KFileListViewItem*) i->
extraData(
this );
00460
00461
if ( item )
00462 KListView::ensureItemVisible( item );
00463 }
00464
00465
00466
void KFileDetailView::slotSelectionChanged()
00467 {
00468 sig->
highlightFile( 0L );
00469 }
00470
00471
KFileItem * KFileDetailView::firstFileItem()
const
00472
{
00473
KFileListViewItem *item = static_cast<KFileListViewItem*>( firstChild() );
00474
if ( item )
00475
return item->
fileInfo();
00476
return 0L;
00477 }
00478
00479
KFileItem * KFileDetailView::nextItem(
const KFileItem *fileItem )
const
00480
{
00481
if ( fileItem ) {
00482
KFileListViewItem *item = viewItem( fileItem );
00483
if ( item && item->itemBelow() )
00484
return ((
KFileListViewItem*) item->itemBelow())->fileInfo();
00485
else
00486
return 0L;
00487 }
00488
else
00489
return firstFileItem();
00490 }
00491
00492
KFileItem * KFileDetailView::prevItem(
const KFileItem *fileItem )
const
00493
{
00494
if ( fileItem ) {
00495
KFileListViewItem *item = viewItem( fileItem );
00496
if ( item && item->itemAbove() )
00497
return ((
KFileListViewItem*) item->itemAbove())->fileInfo();
00498
else
00499
return 0L;
00500 }
00501
else
00502
return firstFileItem();
00503 }
00504
00505
void KFileDetailView::keyPressEvent(
QKeyEvent *e )
00506 {
00507
KListView::keyPressEvent( e );
00508
00509
if ( e->key() == Key_Return || e->key() == Key_Enter ) {
00510
if ( e->state() & ControlButton )
00511 e->ignore();
00512
else
00513 e->accept();
00514 }
00515 }
00516
00517
00518
00519
00520
void KFileDetailView::mimeTypeDeterminationFinished()
00521 {
00522
00523 }
00524
00525
void KFileDetailView::determineIcon(
KFileListViewItem *item )
00526 {
00527 (
void) item->
fileInfo()->
determineMimeType();
00528
updateView( item->
fileInfo() );
00529 }
00530
00531 void KFileDetailView::listingCompleted()
00532 {
00533 m_resolver->
start();
00534 }
00535
00536
QDragObject *
KFileDetailView::dragObject()
00537 {
00538
00539
KURL::List urls;
00540
KFileItemListIterator it( * KFileView::selectedItems() );
00541
for ( ; it.current(); ++it ){
00542 urls.append( (*it)->url() );
00543 }
00544
QPixmap pixmap;
00545
if( urls.count() > 1 )
00546 pixmap = DesktopIcon(
"kmultiple", KIcon::SizeSmall );
00547
if( pixmap.isNull() )
00548 pixmap =
currentFileItem()->
pixmap( KIcon::SizeSmall );
00549
00550
QPoint hotspot;
00551 hotspot.setX( pixmap.width() / 2 );
00552 hotspot.setY( pixmap.height() / 2 );
00553
QDragObject* myDragObject =
new KURLDrag( urls,
widget() );
00554 myDragObject->setPixmap( pixmap, hotspot );
00555
return myDragObject;
00556 }
00557
00558
void KFileDetailView::slotAutoOpen()
00559 {
00560 d->autoOpenTimer.stop();
00561
if( !d->dropItem )
00562
return;
00563
00564
KFileItem *fileItem = d->dropItem->fileInfo();
00565
if (!fileItem)
00566
return;
00567
00568
if( fileItem->
isFile() )
00569
return;
00570
00571
if ( fileItem->
isDir() || fileItem->
isLink())
00572 sig->
activate( fileItem );
00573 }
00574
00575
bool KFileDetailView::acceptDrag(
QDropEvent* e)
const
00576
{
00577
return KURLDrag::canDecode( e ) &&
00578 (e->source()!= const_cast<KFileDetailView*>(
this)) &&
00579 ( e->action() == QDropEvent::Copy
00580 || e->action() == QDropEvent::Move
00581 || e->action() == QDropEvent::Link );
00582 }
00583
00584
void KFileDetailView::contentsDragEnterEvent(
QDragEnterEvent *e )
00585 {
00586
if ( !
acceptDrag( e ) ) {
00587 e->ignore();
00588
return;
00589 }
00590 e->acceptAction();
00591
00592
if ((
dropOptions() & AutoOpenDirs) == 0)
00593
return;
00594
00595
KFileListViewItem *item = dynamic_cast<KFileListViewItem*>(itemAt( contentsToViewport( e->pos() ) ));
00596
if ( item ) {
00597 d->dropItem = item;
00598 d->autoOpenTimer.start( autoOpenDelay() );
00599 }
00600
else
00601 {
00602 d->dropItem = 0;
00603 d->autoOpenTimer.stop();
00604 }
00605 }
00606
00607
void KFileDetailView::contentsDragMoveEvent(
QDragMoveEvent *e )
00608 {
00609
if ( !
acceptDrag( e ) ) {
00610 e->ignore();
00611
return;
00612 }
00613 e->acceptAction();
00614
00615
if ((
dropOptions() & AutoOpenDirs) == 0)
00616
return;
00617
00618
KFileListViewItem *item = dynamic_cast<KFileListViewItem*>(itemAt( contentsToViewport( e->pos() ) ));
00619
if ( item ) {
00620
if (d->dropItem != item)
00621 {
00622 d->dropItem = item;
00623 d->autoOpenTimer.start( autoOpenDelay() );
00624 }
00625 }
00626
else
00627 {
00628 d->dropItem = 0;
00629 d->autoOpenTimer.stop();
00630 }
00631 }
00632
00633
void KFileDetailView::contentsDragLeaveEvent(
QDragLeaveEvent * )
00634 {
00635 d->dropItem = 0;
00636 d->autoOpenTimer.stop();
00637 }
00638
00639
void KFileDetailView::contentsDropEvent(
QDropEvent *e )
00640 {
00641 d->dropItem = 0;
00642 d->autoOpenTimer.stop();
00643
00644
if ( !
acceptDrag( e ) ) {
00645 e->ignore();
00646
return;
00647 }
00648 e->acceptAction();
00649
00650
KFileListViewItem *item = dynamic_cast<KFileListViewItem*>(itemAt( contentsToViewport( e->pos() ) ));
00651
KFileItem * fileItem = 0;
00652
if (item)
00653 fileItem = item->
fileInfo();
00654
00655 emit
dropped(e, fileItem);
00656
00657
KURL::List urls;
00658
if (
KURLDrag::decode( e, urls ) && !urls.isEmpty())
00659 {
00660 emit
dropped(e, urls, fileItem ? fileItem->
url() :
KURL());
00661 sig->
dropURLs(fileItem, e, urls);
00662 }
00663 }
00664
00665
00667
00668
00669 void KFileListViewItem::init()
00670 {
00671 KFileListViewItem::setPixmap( COL_NAME, inf->
pixmap(KIcon::SizeSmall));
00672
00673 setText( COL_NAME, inf->
text() );
00674 setText( COL_SIZE, KGlobal::locale()->formatNumber( inf->
size(), 0));
00675 setText( COL_DATE, inf->
timeString() );
00676 setText( COL_PERM, inf->
permissionsString() );
00677 setText( COL_OWNER, inf->
user() );
00678 setText( COL_GROUP, inf->
group() );
00679 }
00680
00681
00682
void KFileDetailView::virtual_hook(
int id,
void* data )
00683 {
KListView::virtual_hook(
id, data );
00684 KFileView::virtual_hook(
id, data ); }
00685
00686
#include "kfiledetailview.moc"