From c53dbf95cb42a7bb22e8690bf699fda32e657845 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 14 Apr 2019 15:07:33 +0900 Subject: Improved code for trash bin management. 1. When size limit is used, a file bigger than the trash size can't be trashed anymore (a warning message is shown). 2. When size limit is used and warning policy selected, files can't be trashed anymore if the total size of the trash will exceed the set size (a warning message is shown). 3. When the trash size settings are modified, the content of the trash is adjusted based on the new settings. 4. Fixed load/saving of trash options when more than one trash folder exists. Signed-off-by: Michele Calgaro --- tdeioslave/trash/ktrashpropsdlgplugin.cpp | 13 ++- tdeioslave/trash/ktrashpropswidget.cpp | 58 +++++++------ tdeioslave/trash/trash_constant.h | 7 ++ tdeioslave/trash/trashimpl.cpp | 139 +++++++++++++++++++++++++++--- tdeioslave/trash/trashimpl.h | 3 + 5 files changed, 179 insertions(+), 41 deletions(-) (limited to 'tdeioslave') diff --git a/tdeioslave/trash/ktrashpropsdlgplugin.cpp b/tdeioslave/trash/ktrashpropsdlgplugin.cpp index 5147481bc..41c902b24 100644 --- a/tdeioslave/trash/ktrashpropsdlgplugin.cpp +++ b/tdeioslave/trash/ktrashpropsdlgplugin.cpp @@ -241,6 +241,13 @@ void KTrashPropsDlgPlugin::applyChanges() } writeConfig(); + + // Adjust trash size if necessary + TrashImpl::TrashDirMap trashDirs = mTrashImpl->trashDirectories(); + for (TrashImpl::TrashDirMap::ConstIterator it = trashDirs.begin(); it != trashDirs.end(); ++it) + { + mTrashImpl->resizeTrash(it.key()); + } } void KTrashPropsDlgPlugin::percentSizeChanged( double percent ) @@ -370,7 +377,7 @@ void KTrashPropsDlgPlugin::trashChanged( int value ) mUseTimeLimit->setChecked( entry.useTimeLimit ); mDays->setValue( entry.days ); mUseSizeLimit->setChecked( entry.useSizeLimit ); - if ( mSizeLimitType == SIZE_LIMIT_FIXED ) + if ( entry.sizeLimitType == SIZE_LIMIT_FIXED ) { mRbFixedSize->setChecked( true ); } @@ -414,13 +421,13 @@ void KTrashPropsDlgPlugin::readConfig() config.setGroup( groups[ i ] ); ConfigEntry entry; entry.useTimeLimit = config.readBoolEntry( "UseTimeLimit", false ); - entry.days = config.readNumEntry( "Days", 7 ); + entry.days = config.readNumEntry( "Days", 32000 ); entry.useSizeLimit = config.readBoolEntry( "UseSizeLimit", true ); entry.sizeLimitType = config.readNumEntry( "SizeLimitType", SIZE_LIMIT_PERCENT ); entry.percent = config.readDoubleNumEntry( "Percent", 10 ); entry.fixedSize = config.readDoubleNumEntry( "FixedSize", 500 ); entry.fixedSizeUnit = config.readNumEntry( "FixedSizeUnit", SIZE_ID_MB ); - entry.actionType = config.readNumEntry( "LimitReachedAction", 0 ); + entry.actionType = config.readNumEntry( "LimitReachedAction", TrashConstant::ACTION_WARNING ); mConfigMap.insert( groups[ i ], entry ); } } diff --git a/tdeioslave/trash/ktrashpropswidget.cpp b/tdeioslave/trash/ktrashpropswidget.cpp index b4f5c5e6f..40e12cb4f 100644 --- a/tdeioslave/trash/ktrashpropswidget.cpp +++ b/tdeioslave/trash/ktrashpropswidget.cpp @@ -62,7 +62,6 @@ KTrashPropsWidget::KTrashPropsWidget(TQWidget *parent, const char *name) inhibitChangedSignal = true; load(); - trashChanged(0); } KTrashPropsWidget::~KTrashPropsWidget() @@ -90,11 +89,8 @@ void KTrashPropsWidget::setupGui() mountPoints->setCurrentItem(0); connect(mountPoints, TQT_SIGNAL(highlighted(int)), TQT_SLOT(trashChanged(int))); } - else - { - mCurrentTrash = map[0]; - } + mCurrentTrash = map[0]; mUseTimeLimit = new TQCheckBox(i18n("Delete files older than:"), this); wlayout->addMultiCellWidget(mUseTimeLimit, multiTrashRow + 0, multiTrashRow + 0, 0, 1); mDays = new TQSpinBox(1, 365, 1, this); @@ -150,28 +146,36 @@ void KTrashPropsWidget::setDirty() void KTrashPropsWidget::load() { - readConfig(); + inhibitChangedSignal = true; - mUseTimeLimit->setChecked(mConfigMap[mCurrentTrash].useTimeLimit); - mUseSizeLimit->setChecked(mConfigMap[mCurrentTrash].useSizeLimit); - mSizeLimitType = mConfigMap[mCurrentTrash].sizeLimitType; - if (mSizeLimitType == SIZE_LIMIT_FIXED) + readConfig(); + if (mConfigMap.contains(mCurrentTrash)) { - mRbFixedSize->setChecked(true); + mUseTimeLimit->setChecked(mConfigMap[mCurrentTrash].useTimeLimit); + mUseSizeLimit->setChecked(mConfigMap[mCurrentTrash].useSizeLimit); + mSizeLimitType = mConfigMap[mCurrentTrash].sizeLimitType; + if (mSizeLimitType == SIZE_LIMIT_FIXED) + { + mRbFixedSize->setChecked(true); + } + else + { + mRbPercentSize->setChecked(true); + } + mDays->setValue(mConfigMap[mCurrentTrash].days); + mPercentSize->setValue(mConfigMap[mCurrentTrash].percent); + mFixedSize->setValue(mConfigMap[mCurrentTrash].fixedSize); + mFixedSizeUnit->setCurrentItem(mConfigMap[mCurrentTrash].fixedSizeUnit); + mLimitReachedAction->setCurrentItem(mConfigMap[mCurrentTrash].actionType); + percentSizeChanged(mPercentSize->value()); + fixedSizeChanged(mFixedSize->value()); } else { - mRbPercentSize->setChecked(true); + setDefaultValues(); } - mDays->setValue(mConfigMap[mCurrentTrash].days); - mPercentSize->setValue(mConfigMap[mCurrentTrash].percent); - mFixedSize->setValue(mConfigMap[mCurrentTrash].fixedSize); - mFixedSizeUnit->setCurrentItem(mConfigMap[mCurrentTrash].fixedSizeUnit); - mLimitReachedAction->setCurrentItem(mConfigMap[mCurrentTrash].actionType); - percentSizeChanged(mPercentSize->value()); - fixedSizeChanged(mFixedSize->value()); - useTypeChanged(); + useTypeChanged(); inhibitChangedSignal = false; } @@ -199,6 +203,13 @@ void KTrashPropsWidget::save() } writeConfig(); + + // Adjust trash size if necessary + TrashImpl::TrashDirMap trashDirs = mTrashImpl->trashDirectories(); + for (TrashImpl::TrashDirMap::ConstIterator it = trashDirs.begin(); it != trashDirs.end(); ++it) + { + mTrashImpl->resizeTrash(it.key()); + } } void KTrashPropsWidget::setDefaultValues() @@ -214,7 +225,6 @@ void KTrashPropsWidget::setDefaultValues() { mRbPercentSize->setChecked(true); } - mDays->setValue(mConfigMap[mCurrentTrash].days); mPercentSize->setValue(1); mFixedSize->setValue(500); @@ -363,7 +373,7 @@ void KTrashPropsWidget::trashChanged(int value) mUseTimeLimit->setChecked(entry.useTimeLimit); mDays->setValue(entry.days); mUseSizeLimit->setChecked(entry.useSizeLimit); - if (mSizeLimitType == SIZE_LIMIT_FIXED) + if (entry.sizeLimitType == SIZE_LIMIT_FIXED) { mRbFixedSize->setChecked(true); } @@ -419,13 +429,13 @@ void KTrashPropsWidget::readConfig() config.setGroup(groups[i]); ConfigEntry entry; entry.useTimeLimit = config.readBoolEntry("UseTimeLimit", false); - entry.days = config.readNumEntry("Days", 7); + entry.days = config.readNumEntry("Days", 32000); entry.useSizeLimit = config.readBoolEntry("UseSizeLimit", true); entry.sizeLimitType = config.readNumEntry("SizeLimitType", SIZE_LIMIT_PERCENT); entry.percent = config.readDoubleNumEntry("Percent", 10); entry.fixedSize = config.readDoubleNumEntry("FixedSize", 500); entry.fixedSizeUnit = config.readNumEntry("FixedSizeUnit", SIZE_ID_MB); - entry.actionType = config.readNumEntry("LimitReachedAction", 0); + entry.actionType = config.readNumEntry("LimitReachedAction", ACTION_WARNING); mConfigMap.insert(groups[i], entry); } } diff --git a/tdeioslave/trash/trash_constant.h b/tdeioslave/trash/trash_constant.h index a20dbcc24..1dfad9273 100644 --- a/tdeioslave/trash/trash_constant.h +++ b/tdeioslave/trash/trash_constant.h @@ -36,6 +36,13 @@ namespace TrashConstant SIZE_ID_GB = 3, SIZE_ID_TB = 4 }; + + enum + { + ACTION_WARNING = 0, + ACTION_DELETE_OLDEST = 1, + ACTION_DELETE_BIGGEST = 2 + }; } #endif diff --git a/tdeioslave/trash/trashimpl.cpp b/tdeioslave/trash/trashimpl.cpp index c7f9de72d..c2fc53352 100644 --- a/tdeioslave/trash/trashimpl.cpp +++ b/tdeioslave/trash/trashimpl.cpp @@ -19,6 +19,7 @@ #include "trashimpl.h" #include "discspaceutil.h" +#include "trash_constant.h" #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -48,8 +50,6 @@ #include #include -#include "trash_constant.h" - TrashImpl::TrashImpl() : TQObject(), m_lastErrorCode( 0 ), @@ -977,10 +977,10 @@ bool TrashImpl::adaptTrashSize( const TQString& origPath, int trashId ) double percent = config.readDoubleNumEntry( "Percent", 10 ); double fixedSize = config.readDoubleNumEntry( "FixedSize", 500 ); int fixedSizeUnit = config.readNumEntry( "FixedSizeUnit", TrashConstant::SIZE_ID_MB ); - int actionType = config.readNumEntry( "LimitReachedAction", 0 ); + int actionType = config.readNumEntry( "LimitReachedAction", TrashConstant::ACTION_WARNING ); if ( useTimeLimit ) { // delete all files in trash older than X days - const int maxDays = config.readNumEntry( "Days", 7 ); + const int maxDays = config.readNumEntry( "Days", 32000 ); const TQDateTime currentDate = TQDateTime::currentDateTime(); const TrashedFileInfoList trashedFiles = list(); @@ -992,9 +992,6 @@ bool TrashImpl::adaptTrashSize( const TQString& origPath, int trashId ) if ( info.deletionDate.daysTo( currentDate ) > maxDays ) del( info.trashId, info.fileId ); } - - return true; - } if ( useSizeLimit ) { // check if size limit exceeded @@ -1018,20 +1015,29 @@ bool TrashImpl::adaptTrashSize( const TQString& origPath, int trashId ) } trashLimit = (unsigned long)trashLimitTemp; } - if ( requiredTrashSpace > trashLimit ) { - if ( actionType == 0 ) { // warn the user only + if ( additionalSize > trashLimit ) { + m_lastErrorCode = TDEIO::ERR_SLAVE_DEFINED; + m_lastErrorMessage = i18n( "The file '%1' is bigger than the '%2' trash bin size.\n" + "It cannot be trashed." ).arg(origPath).arg(util.mountPoint()); + return false; + } else if ( requiredTrashSpace > trashLimit ) { + if ( actionType == TrashConstant::ACTION_WARNING ) { // warn the user only m_lastErrorCode = TDEIO::ERR_SLAVE_DEFINED; - m_lastErrorMessage = i18n( "The trash has reached its maximum size!\nClean the trash manually." ); + m_lastErrorMessage = i18n( "There is not enough space left in trash folder '%1'.\n" + "The file cannot be trashed. Clean the trash manually and try again.") + .arg(util.mountPoint()); return false; } else { TQDir dir( trashPath + "/files" ); const TQFileInfoList *infos = 0; - if ( actionType == 1 ) // delete oldest files first + if ( actionType == TrashConstant::ACTION_DELETE_OLDEST ) // delete oldest files first infos = dir.entryInfoList( TQDir::Files | TQDir::Dirs, TQDir::Time | TQDir::Reversed ); - else if ( actionType == 2 ) // delete biggest files first + else if ( actionType == TrashConstant::ACTION_DELETE_BIGGEST ) // delete biggest files first infos = dir.entryInfoList( TQDir::Files | TQDir::Dirs, TQDir::Size ); - else - tqWarning( "Should never happen!" ); + else { + tqWarning( " Should never happen!" ); + return false; + } TQFileInfoListIterator it( *infos ); TQFileInfo *info; @@ -1051,4 +1057,109 @@ bool TrashImpl::adaptTrashSize( const TQString& origPath, int trashId ) return true; } +void TrashImpl::resizeTrash(int trashId) +{ + TDEConfig config("trashrc"); + const TQString trashPath = trashDirectoryPath(trashId); + config.setGroup(trashPath); + + bool useTimeLimit = config.readBoolEntry("UseTimeLimit", false); + bool useSizeLimit = config.readBoolEntry("UseSizeLimit", true); + int sizeLimitType = config.readNumEntry("SizeLimitType", TrashConstant::SIZE_LIMIT_PERCENT); + double percent = config.readDoubleNumEntry("Percent", 10); + double fixedSize = config.readDoubleNumEntry("FixedSize", 500); + int fixedSizeUnit = config.readNumEntry("FixedSizeUnit", TrashConstant::SIZE_ID_MB); + int actionType = config.readNumEntry("LimitReachedAction", 0); + + if (useTimeLimit) + { + // delete all files in trash older than X days + const int maxDays = config.readNumEntry("Days", 32000); + const TQDateTime currentDate = TQDateTime::currentDateTime(); + const TrashedFileInfoList trashedFiles = list(); + for (uint i = 0; i < trashedFiles.count(); ++i) + { + struct TrashedFileInfo info = trashedFiles[ i ]; + if (info.trashId != trashId) + { + continue; + } + if (info.deletionDate.daysTo(currentDate) > maxDays) + { + del(info.trashId, info.fileId); + } + } + } + + if (useSizeLimit) + { + // check if size limit exceeded + TQString trashPathName = trashPath + "/files/"; + DiscSpaceUtil util(trashPathName); + unsigned long currTrashSize = util.sizeOfPath(trashPathName); + unsigned long trashLimit = 0; + if (sizeLimitType == TrashConstant::SIZE_LIMIT_PERCENT) + { + trashLimit = (unsigned long)(1024 * percent * util.size() / 100.0); + } + else if (sizeLimitType == TrashConstant::SIZE_LIMIT_FIXED) + { + double trashLimitTemp = fixedSize; + while (fixedSizeUnit > TrashConstant::SIZE_ID_B) + { + trashLimitTemp *= 1024; + --fixedSizeUnit; + } + trashLimit = (unsigned long)trashLimitTemp; + } + if (currTrashSize > trashLimit) + { + if (actionType == TrashConstant::ACTION_WARNING) + { + // warn the user only + KMessageBox::error(0, i18n("The current size of trash folder '%1' is bigger than the allowed size.\n" + "Clean the trash manually.").arg(util.mountPoint())); + return; + } + else + { + TQDir dir(trashPath + "/files"); + const TQFileInfoList *infos = 0; + if (actionType == TrashConstant::ACTION_DELETE_OLDEST) + { + // delete oldest files first + infos = dir.entryInfoList(TQDir::Files | TQDir::Dirs, TQDir::Time | TQDir::Reversed); + } + else if (actionType == TrashConstant::ACTION_DELETE_BIGGEST) + { + // delete biggest files first + infos = dir.entryInfoList(TQDir::Files | TQDir::Dirs, TQDir::Size); + } + else + { + tqWarning(" Should never happen!"); + return; + } + + TQFileInfoListIterator it(*infos); + TQFileInfo *info; + bool deleteFurther = true; + while (((info = it.current()) != 0) && deleteFurther) + { + if (info->fileName() != "." && info->fileName() != "..") + { + del(trashId, info->fileName()); // delete trashed file + if ((util.sizeOfPath(trashPathName)) < trashLimit) + { + // check whether we have enough space now + deleteFurther = false; + } + } + ++it; + } + } + } + } +} + #include "trashimpl.moc" diff --git a/tdeioslave/trash/trashimpl.h b/tdeioslave/trash/trashimpl.h index 6e7af2bad..571bbd353 100644 --- a/tdeioslave/trash/trashimpl.h +++ b/tdeioslave/trash/trashimpl.h @@ -95,6 +95,9 @@ public: /// Move data from the old trash system to the new one void migrateOldTrash(); + /// Resize the trash based on the current settings if necessary + void resizeTrash(int trashId); + /// TDEIO error code int lastErrorCode() const { return m_lastErrorCode; } TQString lastErrorMessage() const { return m_lastErrorMessage; } -- cgit v1.2.1