You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1148 lines
30 KiB
1148 lines
30 KiB
/***************************************************************************
|
|
diskusage.cpp - description
|
|
-------------------
|
|
copyright : (C) 2004 + by Csaba Karai
|
|
e-mail : krusader@users.sourceforge.net
|
|
web site : http://krusader.sourceforge.net
|
|
---------------------------------------------------------------------------
|
|
Description
|
|
***************************************************************************
|
|
|
|
A
|
|
|
|
db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
|
|
88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
|
|
88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
|
|
88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
|
|
88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
|
|
YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
|
|
|
|
S o u r c e F i l e
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <time.h>
|
|
#include <tqlayout.h>
|
|
#include <tdelocale.h>
|
|
#include <tdepopupmenu.h>
|
|
#include <kmimetype.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdeglobalsettings.h>
|
|
#include <tdeio/job.h>
|
|
#include <tqpushbutton.h>
|
|
#include <tqhbox.h>
|
|
#include <tqapplication.h>
|
|
#include <tqcursor.h>
|
|
#include <tqpixmapcache.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqguardedptr.h>
|
|
#include "diskusage.h"
|
|
#include "../VFS/krpermhandler.h"
|
|
#include "../VFS/krvfshandler.h"
|
|
#include "../kicons.h"
|
|
#include "../defaults.h"
|
|
#include "../krusader.h"
|
|
#include "../krusaderview.h"
|
|
#include "../Panel/listpanel.h"
|
|
#include "../Panel/panelfunc.h"
|
|
#include "filelightParts/Config.h"
|
|
|
|
#include "dulines.h"
|
|
#include "dulistview.h"
|
|
#include "dufilelight.h"
|
|
|
|
// these are the values that will exist in the menu
|
|
#define DELETE_ID 90
|
|
#define EXCLUDE_ID 91
|
|
#define PARENT_DIR_ID 92
|
|
#define NEW_SEARCH_ID 93
|
|
#define REFRESH_ID 94
|
|
#define STEP_INTO_ID 95
|
|
#define INCLUDE_ALL_ID 96
|
|
#define VIEW_POPUP_ID 97
|
|
#define LINES_VIEW_ID 98
|
|
#define DETAILED_VIEW_ID 99
|
|
#define FILELIGHT_VIEW_ID 100
|
|
#define NEXT_VIEW_ID 101
|
|
#define PREVIOUS_VIEW_ID 102
|
|
#define ADDITIONAL_POPUP_ID 103
|
|
|
|
#define MAX_FILENUM 100
|
|
|
|
LoaderWidget::LoaderWidget( TQWidget *parent, const char *name ) : TQScrollView( parent, name ), cancelled( false )
|
|
{
|
|
viewport()->setEraseColor( TQt::white );
|
|
widget = new TQWidget( parent );
|
|
|
|
TQGridLayout *loaderLayout = new TQGridLayout( widget );
|
|
loaderLayout->setSpacing( 0 );
|
|
loaderLayout->setMargin( 0 );
|
|
|
|
TQGroupBox *loaderBox = new TQGroupBox( widget, "loaderGroupBox" );
|
|
loaderBox->setFrameShape( TQGroupBox::Box );
|
|
loaderBox->setFrameShadow( TQGroupBox::Sunken );
|
|
loaderBox->setColumnLayout(0, TQt::Vertical );
|
|
loaderBox->layout()->setSpacing( 0 );
|
|
loaderBox->layout()->setMargin( 0 );
|
|
loaderBox->setSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
|
|
loaderBox->setFrameStyle( TQFrame::Panel + TQFrame::Raised );
|
|
loaderBox->setLineWidth( 2 );
|
|
|
|
TQGridLayout *synchGrid = new TQGridLayout( loaderBox->layout() );
|
|
synchGrid->setSpacing( 6 );
|
|
synchGrid->setMargin( 11 );
|
|
|
|
TQLabel *titleLabel = new TQLabel( i18n( "Loading Usage Information" ), loaderBox, "titleLabel" );
|
|
titleLabel->setAlignment( TQt::AlignHCenter );
|
|
synchGrid->addMultiCellWidget( titleLabel, 0, 0, 0, 1 );
|
|
|
|
TQLabel *filesLabel = new TQLabel( i18n( "Files:" ), loaderBox, "filesLabel" );
|
|
filesLabel->setFrameShape( TQLabel::StyledPanel );
|
|
filesLabel->setFrameShadow( TQLabel::Sunken );
|
|
synchGrid->addWidget( filesLabel, 1, 0 );
|
|
|
|
TQLabel *directoriesLabel = new TQLabel( i18n( "Directories:" ), loaderBox, "directoriesLabel" );
|
|
directoriesLabel->setFrameShape( TQLabel::StyledPanel );
|
|
directoriesLabel->setFrameShadow( TQLabel::Sunken );
|
|
synchGrid->addWidget( directoriesLabel, 2, 0 );
|
|
|
|
TQLabel *totalSizeLabel = new TQLabel( i18n( "Total Size:" ), loaderBox, "totalSizeLabel" );
|
|
totalSizeLabel->setFrameShape( TQLabel::StyledPanel );
|
|
totalSizeLabel->setFrameShadow( TQLabel::Sunken );
|
|
synchGrid->addWidget( totalSizeLabel, 3, 0 );
|
|
|
|
files = new TQLabel( loaderBox, "files" );
|
|
files->setFrameShape( TQLabel::StyledPanel );
|
|
files->setFrameShadow( TQLabel::Sunken );
|
|
files->setAlignment( TQt::AlignRight );
|
|
synchGrid->addWidget( files, 1, 1 );
|
|
|
|
directories = new TQLabel( loaderBox, "directories" );
|
|
directories->setFrameShape( TQLabel::StyledPanel );
|
|
directories->setFrameShadow( TQLabel::Sunken );
|
|
directories->setAlignment( TQt::AlignRight );
|
|
synchGrid->addWidget( directories, 2, 1 );
|
|
|
|
totalSize = new TQLabel( loaderBox, "totalSize" );
|
|
totalSize->setFrameShape( TQLabel::StyledPanel );
|
|
totalSize->setFrameShadow( TQLabel::Sunken );
|
|
totalSize->setAlignment( TQt::AlignRight );
|
|
synchGrid->addWidget( totalSize, 3, 1 );
|
|
|
|
int width;
|
|
searchedDirectory = new KSqueezedTextLabel( loaderBox, "searchedDirectory" );
|
|
searchedDirectory->setFrameShape( TQLabel::StyledPanel );
|
|
searchedDirectory->setFrameShadow( TQLabel::Sunken );
|
|
searchedDirectory->setMinimumWidth( width = TQFontMetrics(searchedDirectory->font()).width("W") * 30 );
|
|
searchedDirectory->setMaximumWidth( width );
|
|
synchGrid->addMultiCellWidget( searchedDirectory, 4, 4, 0, 1 );
|
|
|
|
TQFrame *line = new TQFrame( loaderBox, "duLine" );
|
|
line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
|
|
synchGrid->addMultiCellWidget( line, 5, 5, 0, 1 );
|
|
|
|
TQHBox *hbox = new TQHBox( loaderBox, "hbox" );
|
|
TQSpacerItem* spacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
|
|
hbox->layout()->addItem( spacer );
|
|
TQPushButton *cancelButton = new TQPushButton( hbox, "cancelButton" );
|
|
cancelButton->setText( i18n( "Cancel" ) );
|
|
synchGrid->addWidget( hbox, 6, 1 );
|
|
|
|
loaderLayout->addWidget( loaderBox, 0, 0 );
|
|
|
|
addChild( widget );
|
|
|
|
connect( cancelButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotCancelled() ) );
|
|
}
|
|
|
|
void LoaderWidget::resizeEvent ( TQResizeEvent *e )
|
|
{
|
|
TQScrollView::resizeEvent( e );
|
|
|
|
int x = ( viewport()->width() - widget->width() ) / 2;
|
|
int y = ( viewport()->height() - widget->height() ) / 2;
|
|
if( x < 0 ) x=0;
|
|
if( y < 0 ) y=0;
|
|
|
|
moveChild( widget, x, y );
|
|
}
|
|
|
|
void LoaderWidget::init()
|
|
{
|
|
cancelled = false;
|
|
}
|
|
|
|
void LoaderWidget::setCurrentURL( KURL url )
|
|
{
|
|
searchedDirectory->setText( vfs::pathOrURL( url, 1) );
|
|
}
|
|
|
|
void LoaderWidget::setValues( int fileNum, int dirNum, TDEIO::filesize_t total )
|
|
{
|
|
files->setText( TQString("%1").arg( fileNum ) );
|
|
directories->setText( TQString("%1").arg( dirNum ) );
|
|
totalSize->setText( TQString("%1").arg( KRpermHandler::parseSize( total ).stripWhiteSpace() ) );
|
|
}
|
|
|
|
void LoaderWidget::slotCancelled()
|
|
{
|
|
cancelled = true;
|
|
}
|
|
|
|
DiskUsage::DiskUsage( TQString confGroup, TQWidget *parent, char *name ) : TQWidgetStack( parent, name ),
|
|
currentDirectory( 0 ), root( 0 ), configGroup( confGroup ), loading( false ),
|
|
abortLoading( false ), clearAfterAbort( false ), deleting( false ), searchVfs( 0 )
|
|
{
|
|
listView = new DUListView( this, "DU ListView" );
|
|
lineView = new DULines( this, "DU LineView" );
|
|
filelightView = new DUFilelight( this, "Filelight canvas" );
|
|
loaderView = new LoaderWidget( this, "Loading view" );
|
|
|
|
addWidget( listView );
|
|
addWidget( lineView );
|
|
addWidget( filelightView );
|
|
addWidget( loaderView );
|
|
|
|
setView( VIEW_LINES );
|
|
|
|
Filelight::Config::read();
|
|
propertyMap.setAutoDelete( true );
|
|
|
|
connect( &loadingTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( slotLoadDirectory() ) );
|
|
}
|
|
|
|
DiskUsage::~DiskUsage()
|
|
{
|
|
if( root )
|
|
delete root;
|
|
|
|
if( listView ) // don't remove these lines. The module will crash at exit if removed
|
|
delete listView;
|
|
if( lineView )
|
|
delete lineView;
|
|
if( filelightView )
|
|
delete filelightView;
|
|
}
|
|
|
|
void DiskUsage::load( KURL baseDir )
|
|
{
|
|
if( searchVfs && !searchVfs->vfs_canDelete() ) {
|
|
return;
|
|
}
|
|
|
|
fileNum = dirNum = 0;
|
|
currentSize = 0;
|
|
|
|
emit status( i18n( "Loading the disk usage information..." ) );
|
|
|
|
clear();
|
|
|
|
baseURL = baseDir;
|
|
baseURL.setPath( baseDir.path( -1 ) );
|
|
|
|
root = new Directory( baseURL.fileName(), vfs::pathOrURL( baseDir ) );
|
|
|
|
directoryStack.clear();
|
|
parentStack.clear();
|
|
|
|
directoryStack.push( "" );
|
|
parentStack.push( root );
|
|
|
|
if( searchVfs )
|
|
{
|
|
delete searchVfs;
|
|
searchVfs = 0;
|
|
}
|
|
searchVfs = KrVfsHandler::getVfs( baseDir );
|
|
if( searchVfs == 0 )
|
|
{
|
|
loading = abortLoading = clearAfterAbort = false;
|
|
emit loadFinished( false );
|
|
return;
|
|
}
|
|
|
|
searchVfs->vfs_setQuiet( true );
|
|
currentVfile = 0;
|
|
|
|
if( !loading )
|
|
{
|
|
viewBeforeLoad = activeView;
|
|
setView( VIEW_LOADER );
|
|
}
|
|
|
|
loading = true;
|
|
|
|
loaderView->init();
|
|
loaderView->setCurrentURL( baseURL );
|
|
loaderView->setValues( fileNum, dirNum, currentSize );
|
|
|
|
loadingTimer.start( 0, true );
|
|
}
|
|
|
|
void DiskUsage::slotLoadDirectory()
|
|
{
|
|
if( searchVfs && !searchVfs->vfs_canDelete() ) { // recursive call from slotLoadDirectory?
|
|
loadingTimer.start( 100, true ); // as it can cause crash, ignore it and wait while
|
|
return; // the recursion finishes
|
|
}
|
|
if( ( currentVfile == 0 && directoryStack.isEmpty() ) || loaderView->wasCancelled() || abortLoading )
|
|
{
|
|
if( searchVfs )
|
|
delete searchVfs;
|
|
|
|
searchVfs = 0;
|
|
currentVfile = 0;
|
|
|
|
setView( viewBeforeLoad );
|
|
|
|
if( clearAfterAbort )
|
|
clear();
|
|
else {
|
|
calculateSizes();
|
|
changeDirectory( root );
|
|
}
|
|
|
|
emit loadFinished( !( loaderView->wasCancelled() || abortLoading ) );
|
|
|
|
loading = abortLoading = clearAfterAbort = false;
|
|
}
|
|
else if( loading )
|
|
{
|
|
for( int counter = 0; counter != MAX_FILENUM; counter ++ )
|
|
{
|
|
if( currentVfile == 0 )
|
|
{
|
|
if( directoryStack.isEmpty() )
|
|
break;
|
|
|
|
dirToCheck = directoryStack.pop();
|
|
currentParent = parentStack.pop();
|
|
|
|
contentMap.insert( dirToCheck, currentParent );
|
|
|
|
KURL url = baseURL;
|
|
|
|
if( !dirToCheck.isEmpty() )
|
|
url.addPath( dirToCheck );
|
|
|
|
#if defined(BSD)
|
|
if ( url.isLocalFile() && url.path().left( 7 ) == "/procfs" )
|
|
break;
|
|
#else
|
|
if ( url.isLocalFile() && url.path().left( 5 ) == "/proc" )
|
|
break;
|
|
#endif
|
|
|
|
loaderView->setCurrentURL( url );
|
|
|
|
if( !searchVfs->vfs_refresh( url ) )
|
|
break;
|
|
|
|
dirNum++;
|
|
|
|
currentVfile = searchVfs->vfs_getFirstFile();
|
|
}
|
|
else
|
|
{
|
|
fileNum++;
|
|
File *newItem = 0;
|
|
|
|
TQString mime = currentVfile->vfile_getMime(true); // fast == not using mimetype magic
|
|
|
|
if( currentVfile->vfile_isDir() && !currentVfile->vfile_isSymLink() )
|
|
{
|
|
newItem = new Directory( currentParent, currentVfile->vfile_getName(), dirToCheck, currentVfile->vfile_getSize(),
|
|
currentVfile->vfile_getMode(), currentVfile->vfile_getOwner(), currentVfile->vfile_getGroup(),
|
|
currentVfile->vfile_getPerm(), currentVfile->vfile_getTime_t(), currentVfile->vfile_isSymLink(),
|
|
mime );
|
|
directoryStack.push( (dirToCheck.isEmpty() ? "" : dirToCheck + "/" )+ currentVfile->vfile_getName() );
|
|
parentStack.push( dynamic_cast<Directory *>( newItem ) );
|
|
}
|
|
else
|
|
{
|
|
newItem = new File( currentParent, currentVfile->vfile_getName(), dirToCheck, currentVfile->vfile_getSize(),
|
|
currentVfile->vfile_getMode(), currentVfile->vfile_getOwner(), currentVfile->vfile_getGroup(),
|
|
currentVfile->vfile_getPerm(), currentVfile->vfile_getTime_t(), currentVfile->vfile_isSymLink(),
|
|
mime );
|
|
currentSize += currentVfile->vfile_getSize();
|
|
}
|
|
currentParent->append( newItem );
|
|
|
|
currentVfile = searchVfs->vfs_getNextFile();
|
|
}
|
|
}
|
|
|
|
loaderView->setValues( fileNum, dirNum, currentSize );
|
|
loadingTimer.start( 0, true );
|
|
}
|
|
}
|
|
|
|
void DiskUsage::stopLoad()
|
|
{
|
|
abortLoading = true;
|
|
}
|
|
|
|
void DiskUsage::close()
|
|
{
|
|
if( loading )
|
|
{
|
|
abortLoading = true;
|
|
clearAfterAbort = true;
|
|
}
|
|
}
|
|
|
|
void DiskUsage::dirUp()
|
|
{
|
|
if( currentDirectory != 0 )
|
|
{
|
|
if ( currentDirectory->parent() != 0 )
|
|
changeDirectory( (Directory *)(currentDirectory->parent()) );
|
|
else
|
|
{
|
|
KURL up = baseURL.upURL();
|
|
|
|
if( KMessageBox::questionYesNo( this, i18n( "Stepping into the parent directory requires "
|
|
"loading the content of the \"%1\" URL. Do you wish "
|
|
"to continue?" )
|
|
.arg( vfs::pathOrURL( up ) ),
|
|
i18n( "Krusader::DiskUsage" ), KStdGuiItem::yes(),
|
|
KStdGuiItem::no(), "DiskUsageLoadParentDir"
|
|
) == KMessageBox::Yes )
|
|
load( up );
|
|
}
|
|
}
|
|
}
|
|
|
|
Directory * DiskUsage::getDirectory( TQString dir )
|
|
{
|
|
while( dir.endsWith( "/" ) )
|
|
dir.truncate( dir.length() - 1 );
|
|
|
|
if( dir.isEmpty() )
|
|
return root;
|
|
|
|
return contentMap.find( dir );
|
|
}
|
|
|
|
File * DiskUsage::getFile( TQString path )
|
|
{
|
|
if( path == "" )
|
|
return root;
|
|
|
|
TQString dir = path;
|
|
|
|
int ndx = path.findRev( '/' );
|
|
TQString file = path.mid( ndx + 1 );
|
|
|
|
if( ndx == -1 )
|
|
dir = "";
|
|
else
|
|
dir.truncate( ndx );
|
|
|
|
Directory *dirEntry = getDirectory( dir );
|
|
if( dirEntry == 0 )
|
|
return 0;
|
|
|
|
for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
|
|
if( (*it)->name() == file )
|
|
return *it;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void DiskUsage::clear()
|
|
{
|
|
baseURL = KURL();
|
|
emit clearing();
|
|
propertyMap.clear();
|
|
contentMap.clear();
|
|
if( root )
|
|
delete root;
|
|
root = currentDirectory = 0;
|
|
}
|
|
|
|
int DiskUsage::calculateSizes( Directory *dirEntry, bool emitSig, int depth )
|
|
{
|
|
int changeNr = 0;
|
|
|
|
if( dirEntry == 0 )
|
|
dirEntry = root;
|
|
|
|
TDEIO::filesize_t own = 0, total = 0;
|
|
|
|
for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
|
|
{
|
|
File * item = *it;
|
|
|
|
if( !item->isExcluded() )
|
|
{
|
|
if( item->isDir() )
|
|
changeNr += calculateSizes( dynamic_cast<Directory *>( item ), emitSig, depth + 1 );
|
|
else
|
|
own += item->size();
|
|
|
|
total += item->size();
|
|
}
|
|
}
|
|
|
|
TDEIO::filesize_t oldOwn = dirEntry->ownSize(), oldTotal = dirEntry->size();
|
|
dirEntry->setSizes( total, own );
|
|
|
|
if( dirEntry == currentDirectory )
|
|
currentSize = total;
|
|
|
|
if( emitSig && ( own != oldOwn || total != oldTotal ) ) {
|
|
emit changed( dirEntry );
|
|
changeNr++;
|
|
}
|
|
|
|
if( depth == 0 && changeNr != 0 )
|
|
emit changeFinished();
|
|
return changeNr;
|
|
}
|
|
|
|
int DiskUsage::exclude( File *file, bool calcPercents, int depth )
|
|
{
|
|
int changeNr = 0;
|
|
|
|
if( !file->isExcluded() )
|
|
{
|
|
file->exclude( true );
|
|
emit changed( file );
|
|
changeNr++;
|
|
|
|
if( file->isDir() )
|
|
{
|
|
Directory *dir = dynamic_cast<Directory *>( file );
|
|
for( Iterator<File> it = dir->iterator(); it != dir->end(); ++it )
|
|
changeNr += exclude( *it, false, depth + 1 );
|
|
}
|
|
}
|
|
|
|
if( calcPercents )
|
|
{
|
|
calculateSizes( root, true );
|
|
calculatePercents( true );
|
|
createStatus();
|
|
}
|
|
|
|
if( depth == 0 && changeNr != 0 )
|
|
emit changeFinished();
|
|
|
|
return changeNr;
|
|
}
|
|
|
|
int DiskUsage::include( Directory *dir, int depth )
|
|
{
|
|
int changeNr = 0;
|
|
|
|
if( dir == 0 )
|
|
return 0;
|
|
|
|
for( Iterator<File> it = dir->iterator(); it != dir->end(); ++it )
|
|
{
|
|
File *item = *it;
|
|
|
|
if( item->isDir() )
|
|
changeNr += include( dynamic_cast<Directory *>( item ), depth + 1 );
|
|
|
|
if( item->isExcluded() )
|
|
{
|
|
item->exclude( false );
|
|
emit changed( item );
|
|
changeNr++;
|
|
}
|
|
}
|
|
|
|
if( depth == 0 && changeNr != 0 )
|
|
emit changeFinished();
|
|
|
|
return changeNr;
|
|
}
|
|
|
|
void DiskUsage::includeAll()
|
|
{
|
|
include( root );
|
|
calculateSizes( root, true );
|
|
calculatePercents( true );
|
|
createStatus();
|
|
}
|
|
|
|
int DiskUsage::del( File *file, bool calcPercents, int depth )
|
|
{
|
|
int deleteNr = 0;
|
|
|
|
if( file == root )
|
|
return 0;
|
|
|
|
krConfig->setGroup( "General" );
|
|
bool trash = krConfig->readBoolEntry( "Move To Trash", _MoveToTrash );
|
|
KURL url = vfs::fromPathOrURL( file->fullPath() );
|
|
|
|
if( calcPercents )
|
|
{
|
|
// now ask the user if he want to delete:
|
|
krConfig->setGroup( "Advanced" );
|
|
if ( krConfig->readBoolEntry( "Confirm Delete", _ConfirmDelete ) ) {
|
|
TQString s, b;
|
|
if ( trash && url.isLocalFile() ) {
|
|
s = i18n( "Do you really want to move this item to the trash?" );
|
|
b = i18n( "&Trash" );
|
|
} else {
|
|
s = i18n( "Do you really want to delete this item?" );
|
|
b = i18n( "&Delete" );
|
|
}
|
|
|
|
TQStringList name;
|
|
name.append( file->fullPath() );
|
|
// show message
|
|
// note: i'm using continue and not yes/no because the yes/no has cancel as default button
|
|
if ( KMessageBox::warningContinueCancelList( krApp, s, name, i18n( "Warning" ), b ) != KMessageBox::Continue )
|
|
return 0;
|
|
}
|
|
|
|
emit status( i18n( "Deleting %1..." ).arg( file->name() ) );
|
|
}
|
|
|
|
if( file == currentDirectory )
|
|
dirUp();
|
|
|
|
if( file->isDir() )
|
|
{
|
|
Directory *dir = dynamic_cast<Directory *>( file );
|
|
|
|
Iterator<File> it;
|
|
while( ( it = dir->iterator() ) != dir->end() )
|
|
deleteNr += del( *it, false, depth + 1 );
|
|
|
|
TQString path;
|
|
for( const Directory *d = (Directory*)file; d != root && d && d->parent() != 0; d = d->parent() )
|
|
{
|
|
if( !path.isEmpty() )
|
|
path = "/" + path;
|
|
|
|
path = d->name() + path;
|
|
}
|
|
|
|
contentMap.remove( path );
|
|
}
|
|
|
|
emit deleted( file );
|
|
deleteNr++;
|
|
|
|
TQGuardedPtr<TDEIO::Job> job;
|
|
|
|
if( trash )
|
|
{
|
|
#if KDE_IS_VERSION(3,4,0)
|
|
job = TDEIO::trash( url, true );
|
|
#else
|
|
job = new TDEIO::CopyJob( url,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
|
|
#endif
|
|
connect(job,TQ_SIGNAL(result(TDEIO::Job*)),krApp,TQ_SLOT(changeTrashIcon()));
|
|
}
|
|
else
|
|
{
|
|
job = new TDEIO::DeleteJob( vfs::fromPathOrURL( file->fullPath() ), false, false);
|
|
}
|
|
|
|
deleting = true; // during tqApp->processEvent strange things can occur
|
|
grabMouse(); // that's why we disable the mouse and keyboard events
|
|
grabKeyboard();
|
|
|
|
while( !job.isNull() )
|
|
tqApp->processEvents();
|
|
|
|
releaseMouse();
|
|
releaseKeyboard();
|
|
deleting = false;
|
|
|
|
((Directory *)(file->parent()))->remove( file );
|
|
delete file;
|
|
|
|
if( depth == 0 )
|
|
createStatus();
|
|
|
|
if( calcPercents )
|
|
{
|
|
calculateSizes( root, true );
|
|
calculatePercents( true );
|
|
createStatus();
|
|
emit enteringDirectory( currentDirectory );
|
|
}
|
|
|
|
if( depth == 0 && deleteNr != 0 )
|
|
emit deleteFinished();
|
|
|
|
return deleteNr;
|
|
}
|
|
|
|
void * DiskUsage::getProperty( File *item, TQString key )
|
|
{
|
|
Properties * props = propertyMap.find( item );
|
|
if( props == 0 )
|
|
return 0;
|
|
return props->find( key );
|
|
}
|
|
|
|
void DiskUsage::addProperty( File *item, TQString key, void * prop )
|
|
{
|
|
Properties * props = propertyMap.find( item );
|
|
if( props == 0 )
|
|
{
|
|
props = new Properties();
|
|
propertyMap.insert( item, props );
|
|
}
|
|
props->insert( key, prop );
|
|
}
|
|
|
|
void DiskUsage::removeProperty( File *item, TQString key )
|
|
{
|
|
Properties * props = propertyMap.find( item );
|
|
if( props == 0 )
|
|
return;
|
|
props->remove( key );
|
|
if( props->count() == 0 )
|
|
propertyMap.remove( item );
|
|
}
|
|
|
|
void DiskUsage::createStatus()
|
|
{
|
|
Directory *dirEntry = currentDirectory;
|
|
|
|
if( dirEntry == 0 )
|
|
return;
|
|
|
|
KURL url = baseURL;
|
|
if( dirEntry != root )
|
|
url.addPath( dirEntry->directory() );
|
|
|
|
emit status( i18n( "Current directory:%1, Total size:%2, Own size:%3" )
|
|
.arg( vfs::pathOrURL( url, -1 ) )
|
|
.arg( " "+KRpermHandler::parseSize( dirEntry->size() ) )
|
|
.arg( " "+KRpermHandler::parseSize( dirEntry->ownSize() ) ) );
|
|
}
|
|
|
|
void DiskUsage::changeDirectory( Directory *dir )
|
|
{
|
|
currentDirectory = dir;
|
|
|
|
currentSize = dir->size();
|
|
calculatePercents( true, dir );
|
|
|
|
createStatus();
|
|
emit enteringDirectory( dir );
|
|
}
|
|
|
|
Directory* DiskUsage::getCurrentDir()
|
|
{
|
|
return currentDirectory;
|
|
}
|
|
|
|
void DiskUsage::rightClickMenu( File *fileItem, TDEPopupMenu *addPopup, TQString addPopupName )
|
|
{
|
|
TDEPopupMenu popup( this );
|
|
|
|
popup.insertTitle( i18n("Disk Usage"));
|
|
|
|
if( fileItem != 0 )
|
|
{
|
|
popup.insertItem( i18n("Delete"), DELETE_ID);
|
|
popup.setAccel( Key_Delete, DELETE_ID );
|
|
popup.insertItem( i18n("Exclude"), EXCLUDE_ID);
|
|
popup.setAccel( CTRL + Key_E, EXCLUDE_ID );
|
|
popup.insertSeparator();
|
|
}
|
|
|
|
popup.insertItem( i18n("Up one directory"), PARENT_DIR_ID);
|
|
popup.setAccel( SHIFT + Key_Up, PARENT_DIR_ID );
|
|
popup.insertItem( i18n("New search"), NEW_SEARCH_ID);
|
|
popup.setAccel( CTRL + Key_N, NEW_SEARCH_ID );
|
|
popup.insertItem( i18n("Refresh"), REFRESH_ID);
|
|
popup.setAccel( CTRL + Key_R, REFRESH_ID );
|
|
popup.insertItem( i18n("Include all"), INCLUDE_ALL_ID);
|
|
popup.setAccel( CTRL + Key_I, INCLUDE_ALL_ID );
|
|
popup.insertItem( i18n("Step into"), STEP_INTO_ID);
|
|
popup.setAccel( SHIFT + Key_Down, STEP_INTO_ID );
|
|
popup.insertSeparator();
|
|
|
|
|
|
if( addPopup != 0 )
|
|
{
|
|
popup.insertItem( TQPixmap(), addPopup, ADDITIONAL_POPUP_ID );
|
|
popup.changeItem( ADDITIONAL_POPUP_ID, addPopupName );
|
|
}
|
|
|
|
TDEPopupMenu viewPopup;
|
|
viewPopup.insertItem(i18n("Lines"), LINES_VIEW_ID);
|
|
viewPopup.setAccel( CTRL + Key_L, LINES_VIEW_ID );
|
|
viewPopup.insertItem(i18n("Detailed"), DETAILED_VIEW_ID);
|
|
viewPopup.setAccel( CTRL + Key_D, DETAILED_VIEW_ID );
|
|
viewPopup.insertItem(i18n("Filelight"), FILELIGHT_VIEW_ID);
|
|
viewPopup.setAccel( CTRL + Key_F, FILELIGHT_VIEW_ID );
|
|
viewPopup.insertSeparator();
|
|
viewPopup.insertItem(i18n("Next"), NEXT_VIEW_ID);
|
|
viewPopup.setAccel( SHIFT + Key_Right, NEXT_VIEW_ID );
|
|
viewPopup.insertItem(i18n("Previous"), PREVIOUS_VIEW_ID);
|
|
viewPopup.setAccel( SHIFT + Key_Left, PREVIOUS_VIEW_ID );
|
|
|
|
popup.insertItem( TQPixmap(), &viewPopup, VIEW_POPUP_ID );
|
|
popup.changeItem( VIEW_POPUP_ID, i18n( "View" ) );
|
|
|
|
int result=popup.exec(TQCursor::pos());
|
|
|
|
executeAction( result, fileItem );
|
|
}
|
|
|
|
void DiskUsage::executeAction( int action, File * fileItem )
|
|
{
|
|
// check out the user's option
|
|
switch ( action )
|
|
{
|
|
case DELETE_ID:
|
|
if( fileItem )
|
|
del( fileItem );
|
|
break;
|
|
case EXCLUDE_ID:
|
|
if( fileItem )
|
|
exclude( fileItem );
|
|
break;
|
|
case PARENT_DIR_ID:
|
|
dirUp();
|
|
break;
|
|
case NEW_SEARCH_ID:
|
|
emit newSearch();
|
|
break;
|
|
case REFRESH_ID:
|
|
load( baseURL );
|
|
break;
|
|
case INCLUDE_ALL_ID:
|
|
includeAll();
|
|
break;
|
|
case STEP_INTO_ID:
|
|
{
|
|
TQString uri;
|
|
if( fileItem && fileItem->isDir() )
|
|
uri = fileItem->fullPath();
|
|
else
|
|
uri = currentDirectory->fullPath();
|
|
ACTIVE_FUNC->openUrl(vfs::fromPathOrURL( uri ));
|
|
}
|
|
break;
|
|
case LINES_VIEW_ID:
|
|
setView( VIEW_LINES );
|
|
break;
|
|
case DETAILED_VIEW_ID:
|
|
setView( VIEW_DETAILED );
|
|
break;
|
|
case FILELIGHT_VIEW_ID:
|
|
setView( VIEW_FILELIGHT );
|
|
break;
|
|
case NEXT_VIEW_ID:
|
|
setView( ( activeView + 1 ) % 3 );
|
|
break;
|
|
case PREVIOUS_VIEW_ID:
|
|
setView( ( activeView + 2 ) % 3 );
|
|
break;
|
|
}
|
|
visibleWidget()->setFocus();
|
|
}
|
|
|
|
void DiskUsage::keyPressEvent( TQKeyEvent *e )
|
|
{
|
|
if( activeView != VIEW_LOADER )
|
|
{
|
|
switch ( e->key() )
|
|
{
|
|
case Key_E:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( EXCLUDE_ID, getCurrentFile() );
|
|
return;
|
|
}
|
|
case Key_D:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( DETAILED_VIEW_ID );
|
|
return;
|
|
}
|
|
case Key_F:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( FILELIGHT_VIEW_ID );
|
|
return;
|
|
}
|
|
case Key_I:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( INCLUDE_ALL_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_L:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( LINES_VIEW_ID );
|
|
return;
|
|
}
|
|
case Key_N:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( NEW_SEARCH_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_R:
|
|
if( e->state() == ControlButton )
|
|
{
|
|
executeAction( REFRESH_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Up:
|
|
if( e->state() == ShiftButton )
|
|
{
|
|
executeAction( PARENT_DIR_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Down:
|
|
if( e->state() == ShiftButton )
|
|
{
|
|
executeAction( STEP_INTO_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Left:
|
|
if( e->state() == ShiftButton )
|
|
{
|
|
executeAction( PREVIOUS_VIEW_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Right:
|
|
if( e->state() == ShiftButton )
|
|
{
|
|
executeAction( NEXT_VIEW_ID );
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Delete:
|
|
if( !e->state() )
|
|
{
|
|
executeAction( DELETE_ID, getCurrentFile() );
|
|
return;
|
|
}
|
|
case Key_Plus:
|
|
if( activeView == VIEW_FILELIGHT )
|
|
{
|
|
filelightView->zoomIn();
|
|
return;
|
|
}
|
|
break;
|
|
case Key_Minus:
|
|
if( activeView == VIEW_FILELIGHT )
|
|
{
|
|
filelightView->zoomOut();
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
TQWidgetStack::keyPressEvent( e );
|
|
}
|
|
|
|
TQPixmap DiskUsage::getIcon( TQString mime )
|
|
{
|
|
TQPixmap icon;
|
|
|
|
if ( !TQPixmapCache::find( mime, icon ) )
|
|
{
|
|
// get the icon.
|
|
if ( mime == "Broken Link !" )
|
|
icon = FL_LOADICON( "file_broken" );
|
|
else
|
|
icon = FL_LOADICON( KMimeType::mimeType( mime ) ->icon( TQString(), true ) );
|
|
|
|
// insert it into the cache
|
|
TQPixmapCache::insert( mime, icon );
|
|
}
|
|
return icon;
|
|
}
|
|
|
|
int DiskUsage::calculatePercents( bool emitSig, Directory *dirEntry, int depth )
|
|
{
|
|
int changeNr = 0;
|
|
|
|
if( dirEntry == 0 )
|
|
dirEntry = root;
|
|
|
|
for( Iterator<File> it = dirEntry->iterator(); it != dirEntry->end(); ++it )
|
|
{
|
|
File *item = *it;
|
|
|
|
if( !item->isExcluded() )
|
|
{
|
|
int newPerc;
|
|
|
|
if( dirEntry->size() == 0 && item->size() == 0 )
|
|
newPerc = 0;
|
|
else if( dirEntry->size() == 0 )
|
|
newPerc = -1;
|
|
else
|
|
newPerc = (int)((double)item->size() / (double)currentSize * 10000. + 0.5);
|
|
|
|
int oldPerc = item->intPercent();
|
|
item->setPercent( newPerc );
|
|
|
|
if( emitSig && newPerc != oldPerc ) {
|
|
emit changed( item );
|
|
changeNr++;
|
|
}
|
|
|
|
if( item->isDir() )
|
|
changeNr += calculatePercents( emitSig, dynamic_cast<Directory *>( item ), depth + 1 );
|
|
}
|
|
}
|
|
|
|
if( depth == 0 && changeNr != 0 )
|
|
emit changeFinished();
|
|
return changeNr;
|
|
}
|
|
|
|
TQString DiskUsage::getToolTip( File *item )
|
|
{
|
|
KMimeType::Ptr mimePtr = KMimeType::mimeType( item->mime() );
|
|
TQString mime = mimePtr->comment();
|
|
|
|
time_t tma = item->time();
|
|
struct tm* t=localtime((time_t *)&tma);
|
|
TQDateTime tmp(TQDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday), TQTime(t->tm_hour, t->tm_min));
|
|
TQString date = TDEGlobal::locale()->formatDateTime(tmp);
|
|
|
|
TQString str = "<qt><h5><table><tr><td>" + i18n( "Name:" ) + "</td><td>" + item->name() + "</td></tr>"+
|
|
"<tr><td>" + i18n( "Type:" ) + "</td><td>" + mime + "</td></tr>"+
|
|
"<tr><td>" + i18n( "Size:" ) + "</td><td>" + KRpermHandler::parseSize( item->size() ) + "</td></tr>";
|
|
|
|
if( item->isDir() )
|
|
str += "<tr><td>" + i18n( "Own size:" ) + "</td><td>" + KRpermHandler::parseSize( item->ownSize() ) + "</td></tr>";
|
|
|
|
str += "<tr><td>" + i18n( "Last modified:" ) + "</td><td>" + date + "</td></tr>"+
|
|
"<tr><td>" + i18n( "Permissions:" ) + "</td><td>" + item->perm() + "</td></tr>"+
|
|
"<tr><td>" + i18n( "Owner:" ) + "</td><td>" + item->owner() + " - " + item->group() + "</td></tr>"+
|
|
"</table></h5></qt>";
|
|
str.replace( " ", " " );
|
|
return str;
|
|
}
|
|
|
|
void DiskUsage::setView( int view )
|
|
{
|
|
switch( view )
|
|
{
|
|
case VIEW_LINES:
|
|
raiseWidget( lineView );
|
|
break;
|
|
case VIEW_DETAILED:
|
|
raiseWidget( listView );
|
|
break;
|
|
case VIEW_FILELIGHT:
|
|
raiseWidget( filelightView );
|
|
break;
|
|
case VIEW_LOADER:
|
|
raiseWidget( loaderView );
|
|
break;
|
|
}
|
|
|
|
visibleWidget()->setFocus();
|
|
emit viewChanged( activeView = view );
|
|
}
|
|
|
|
File * DiskUsage::getCurrentFile()
|
|
{
|
|
File * file = 0;
|
|
|
|
switch( activeView )
|
|
{
|
|
case VIEW_LINES:
|
|
file = lineView->getCurrentFile();
|
|
break;
|
|
case VIEW_DETAILED:
|
|
file = listView->getCurrentFile();
|
|
break;
|
|
case VIEW_FILELIGHT:
|
|
file = filelightView->getCurrentFile();
|
|
break;
|
|
}
|
|
|
|
return file;
|
|
}
|
|
|
|
bool DiskUsage::event( TQEvent * e )
|
|
{
|
|
if( deleting ) { // if we are deleting, disable the mouse and
|
|
switch( e->type() ) { // keyboard events
|
|
case TQEvent::MouseButtonPress:
|
|
case TQEvent::MouseButtonRelease:
|
|
case TQEvent::MouseButtonDblClick:
|
|
case TQEvent::MouseMove:
|
|
case TQEvent::KeyPress:
|
|
case TQEvent::KeyRelease:
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( e->type() == TQEvent::AccelOverride )
|
|
{
|
|
TQKeyEvent* ke = (TQKeyEvent*) e;
|
|
|
|
if ( ke->state() == TQt::NoButton || ke->state() == Keypad )
|
|
{
|
|
switch ( ke->key() )
|
|
{
|
|
case Key_Delete:
|
|
case Key_Plus:
|
|
case Key_Minus:
|
|
ke->accept();
|
|
break;
|
|
}
|
|
}else if( ke->state() == ShiftButton )
|
|
{
|
|
switch ( ke->key() )
|
|
{
|
|
case Key_Left:
|
|
case Key_Right:
|
|
case Key_Up:
|
|
case Key_Down:
|
|
ke->accept();
|
|
break;
|
|
}
|
|
}else if ( ke->state() & ControlButton )
|
|
{
|
|
switch ( ke->key() )
|
|
{
|
|
case Key_D:
|
|
case Key_E:
|
|
case Key_F:
|
|
case Key_I:
|
|
case Key_L:
|
|
case Key_N:
|
|
case Key_R:
|
|
ke->accept();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return TQWidgetStack::event( e );
|
|
}
|
|
|
|
#include "diskusage.moc"
|