diff options
Diffstat (limited to 'src/app/DiskUsage/diskusage.cpp')
-rw-r--r-- | src/app/DiskUsage/diskusage.cpp | 1147 |
1 files changed, 1147 insertions, 0 deletions
diff --git a/src/app/DiskUsage/diskusage.cpp b/src/app/DiskUsage/diskusage.cpp new file mode 100644 index 0000000..c372e8c --- /dev/null +++ b/src/app/DiskUsage/diskusage.cpp @@ -0,0 +1,1147 @@ +/*************************************************************************** + 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" |