📄 diskusage.cpp
字号:
/*************************************************************************** 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 <qlayout.h>#include <klocale.h>#include <kpopupmenu.h>#include <kmimetype.h>#include <kmessagebox.h>#include <kglobalsettings.h>#include <kio/job.h>#include <qpushbutton.h>#include <qhbox.h>#include <qapplication.h>#include <qcursor.h>#include <qpixmapcache.h>#include <qgroupbox.h>#include <qguardedptr.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 100LoaderWidget::LoaderWidget( QWidget *parent, const char *name ) : QScrollView( parent, name ), cancelled( false ){ viewport()->setEraseColor( Qt::white ); widget = new QWidget( parent ); QGridLayout *loaderLayout = new QGridLayout( widget ); loaderLayout->setSpacing( 0 ); loaderLayout->setMargin( 0 ); QGroupBox *loaderBox = new QGroupBox( widget, "loaderGroupBox" ); loaderBox->setFrameShape( QGroupBox::Box ); loaderBox->setFrameShadow( QGroupBox::Sunken ); loaderBox->setColumnLayout(0, Qt::Vertical ); loaderBox->layout()->setSpacing( 0 ); loaderBox->layout()->setMargin( 0 ); loaderBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); loaderBox->setFrameStyle( QFrame::Panel + QFrame::Raised ); loaderBox->setLineWidth( 2 ); QGridLayout *synchGrid = new QGridLayout( loaderBox->layout() ); synchGrid->setSpacing( 6 ); synchGrid->setMargin( 11 ); QLabel *titleLabel = new QLabel( i18n( "Loading Usage Information" ), loaderBox, "titleLabel" ); titleLabel->setAlignment( Qt::AlignHCenter ); synchGrid->addMultiCellWidget( titleLabel, 0, 0, 0, 1 ); QLabel *filesLabel = new QLabel( i18n( "Files:" ), loaderBox, "filesLabel" ); filesLabel->setFrameShape( QLabel::StyledPanel ); filesLabel->setFrameShadow( QLabel::Sunken ); synchGrid->addWidget( filesLabel, 1, 0 ); QLabel *directoriesLabel = new QLabel( i18n( "Directories:" ), loaderBox, "directoriesLabel" ); directoriesLabel->setFrameShape( QLabel::StyledPanel ); directoriesLabel->setFrameShadow( QLabel::Sunken ); synchGrid->addWidget( directoriesLabel, 2, 0 ); QLabel *totalSizeLabel = new QLabel( i18n( "Total Size:" ), loaderBox, "totalSizeLabel" ); totalSizeLabel->setFrameShape( QLabel::StyledPanel ); totalSizeLabel->setFrameShadow( QLabel::Sunken ); synchGrid->addWidget( totalSizeLabel, 3, 0 ); files = new QLabel( loaderBox, "files" ); files->setFrameShape( QLabel::StyledPanel ); files->setFrameShadow( QLabel::Sunken ); files->setAlignment( Qt::AlignRight ); synchGrid->addWidget( files, 1, 1 ); directories = new QLabel( loaderBox, "directories" ); directories->setFrameShape( QLabel::StyledPanel ); directories->setFrameShadow( QLabel::Sunken ); directories->setAlignment( Qt::AlignRight ); synchGrid->addWidget( directories, 2, 1 ); totalSize = new QLabel( loaderBox, "totalSize" ); totalSize->setFrameShape( QLabel::StyledPanel ); totalSize->setFrameShadow( QLabel::Sunken ); totalSize->setAlignment( Qt::AlignRight ); synchGrid->addWidget( totalSize, 3, 1 ); int width; searchedDirectory = new KSqueezedTextLabel( loaderBox, "searchedDirectory" ); searchedDirectory->setFrameShape( QLabel::StyledPanel ); searchedDirectory->setFrameShadow( QLabel::Sunken ); searchedDirectory->setMinimumWidth( width = QFontMetrics(searchedDirectory->font()).width("W") * 30 ); searchedDirectory->setMaximumWidth( width ); synchGrid->addMultiCellWidget( searchedDirectory, 4, 4, 0, 1 ); QFrame *line = new QFrame( loaderBox, "duLine" ); line->setFrameStyle( QFrame::HLine | QFrame::Sunken ); synchGrid->addMultiCellWidget( line, 5, 5, 0, 1 ); QHBox *hbox = new QHBox( loaderBox, "hbox" ); QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); hbox->layout()->addItem( spacer ); QPushButton *cancelButton = new QPushButton( hbox, "cancelButton" ); cancelButton->setText( i18n( "Cancel" ) ); synchGrid->addWidget( hbox, 6, 1 ); loaderLayout->addWidget( loaderBox, 0, 0 ); addChild( widget ); connect( cancelButton, SIGNAL( clicked() ), this, SLOT( slotCancelled() ) );}void LoaderWidget::resizeEvent ( QResizeEvent *e ){ QScrollView::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, KIO::filesize_t total ){ files->setText( QString("%1").arg( fileNum ) ); directories->setText( QString("%1").arg( dirNum ) ); totalSize->setText( QString("%1").arg( KRpermHandler::parseSize( total ).stripWhiteSpace() ) );}void LoaderWidget::slotCancelled(){ cancelled = true;}DiskUsage::DiskUsage( QString confGroup, QWidget *parent, char *name ) : QWidgetStack( 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, SIGNAL( timeout() ), this, 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; QString 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( QString dir ){ while( dir.endsWith( "/" ) ) dir.truncate( dir.length() - 1 ); if( dir.isEmpty() ) return root; return contentMap.find( dir );}File * DiskUsage::getFile( QString path ){ if( path == "" ) return root; QString dir = path; int ndx = path.findRev( '/' ); QString 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; KIO::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(); } } KIO::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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -