From ee3091bc41f5cae8be2ba5f8335e0b866edb4711 Mon Sep 17 00:00:00 2001
From: Emanoil Kotsev <deloptes@gmail.com>
Date: Wed, 12 Oct 2016 15:20:02 +0900
Subject: Added trash limit configuration option This work is based on original
 patch created by Tobias Koenig <tokoe@kde.org> for KDE 3.5.9 and later added
 to KDE 4.2, and available under GPL version 2 License, or any later version.
 See also http://tokoe-kde.blogspot.com/2008/08/size-limits-for-trash.html
 This relates to bug 1923.

Signed-off-by: Emanoil Kotsev <deloptes@gmail.com>
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
---
 tdeioslave/trash/CMakeLists.txt               |  19 +-
 tdeioslave/trash/Makefile.am                  |  13 +-
 tdeioslave/trash/discspaceutil.cpp            | 112 +++++++++
 tdeioslave/trash/discspaceutil.h              |  81 +++++++
 tdeioslave/trash/ktrashpropsdlgplugin.cpp     | 316 ++++++++++++++++++++++++++
 tdeioslave/trash/ktrashpropsdlgplugin.desktop |   6 +
 tdeioslave/trash/ktrashpropsdlgplugin.h       |  78 +++++++
 tdeioslave/trash/testtrash.cpp                |   2 +-
 tdeioslave/trash/trash.protocol               |   2 +-
 tdeioslave/trash/trashimpl.cpp                |  95 ++++++++
 tdeioslave/trash/trashimpl.h                  |   2 +
 11 files changed, 720 insertions(+), 6 deletions(-)
 create mode 100644 tdeioslave/trash/discspaceutil.cpp
 create mode 100644 tdeioslave/trash/discspaceutil.h
 create mode 100644 tdeioslave/trash/ktrashpropsdlgplugin.cpp
 create mode 100644 tdeioslave/trash/ktrashpropsdlgplugin.desktop
 create mode 100644 tdeioslave/trash/ktrashpropsdlgplugin.h

diff --git a/tdeioslave/trash/CMakeLists.txt b/tdeioslave/trash/CMakeLists.txt
index 1569d07ca..1082b57af 100644
--- a/tdeioslave/trash/CMakeLists.txt
+++ b/tdeioslave/trash/CMakeLists.txt
@@ -25,7 +25,7 @@ link_directories(
 
 ##### other data ################################
 
-install( FILES trash.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES ktrashpropsdlgplugin.desktop trash.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
 
 
 ##### trashcommon (static) ######################
@@ -33,7 +33,7 @@ install( FILES trash.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
 set( target trashcommon )
 
 tde_add_library( ${target} STATIC_PIC AUTOMOC
-  SOURCES trashimpl.cpp
+  SOURCES trashimpl.cpp discspaceutil.cpp 
 )
 
 
@@ -47,6 +47,15 @@ tde_add_kpart( ${target} AUTOMOC
   DESTINATION ${PLUGIN_INSTALL_DIR}
 )
 
+##### ktrashpropsdlgplugin (module) ########################
+
+set( target ktrashpropsdlgplugin )
+
+tde_add_kpart( ${target} AUTOMOC
+  SOURCES ktrashpropsdlgplugin.cpp
+  LINK trashcommon-static tdeio-shared
+  DESTINATION ${PLUGIN_INSTALL_DIR}
+)
 
 ##### ktrash (executable) #######################
 
@@ -57,3 +66,9 @@ tde_add_executable( ${target}
   LINK tdeio-shared
   DESTINATION ${BIN_INSTALL_DIR}
 )
+
+##### testtrash (executable) #######################
+tde_add_executable( testtrash
+  SOURCES testtrash.cpp AUTOMOC
+  LINK trashcommon-static tdeio-shared
+)
diff --git a/tdeioslave/trash/Makefile.am b/tdeioslave/trash/Makefile.am
index 02b43e90a..a3c8253e0 100644
--- a/tdeioslave/trash/Makefile.am
+++ b/tdeioslave/trash/Makefile.am
@@ -3,7 +3,7 @@ METASOURCES = AUTO
 
 SUBDIRS = . tdefile-plugin
 
-kde_module_LTLIBRARIES = tdeio_trash.la
+kde_module_LTLIBRARIES = tdeio_trash.la ktrashpropsdlgplugin.la
 
 tdeio_trash_la_SOURCES = tdeio_trash.cpp
 tdeio_trash_la_LIBADD  = libtrashcommon.la $(LIB_TDEIO)
@@ -17,7 +17,7 @@ ktrash_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $
 kde_services_DATA = trash.protocol
 
 noinst_LTLIBRARIES = libtrashcommon.la
-libtrashcommon_la_SOURCES = trashimpl.cpp
+libtrashcommon_la_SOURCES = trashimpl.cpp discspaceutil.cpp
 
 check_PROGRAMS = testtrash
 testtrash_SOURCES = testtrash.cpp
@@ -29,3 +29,12 @@ TESTS = testtrash
 messages:
 	$(XGETTEXT) `find . -name "*.cc" -o -name "*.cpp" -o -name "*.h"` -o $(podir)/tdeio_trash.pot
 
+# ktrashpropsdlgplugin target
+noinst_HEADERS = ktrashpropsdlgplugin.h discspaceutil.h
+
+ktrashpropsdlgplugin_la_SOURCES = ktrashpropsdlgplugin.cpp discspaceutil.cpp trashimpl.cpp
+ktrashpropsdlgplugin_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+ktrashpropsdlgplugin_la_LIBADD = $(LIB_TDEIO)
+
+services_DATA = ktrashpropsdlgplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/tdeioslave/trash/discspaceutil.cpp b/tdeioslave/trash/discspaceutil.cpp
new file mode 100644
index 000000000..a771638fc
--- /dev/null
+++ b/tdeioslave/trash/discspaceutil.cpp
@@ -0,0 +1,112 @@
+/*
+   This file is part of the KDE project
+
+   Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <tqapplication.h>
+#include <tqdir.h>
+#include <tqeventloop.h>
+#include <tqfileinfo.h>
+
+#include <kdiskfreesp.h>
+#include <kdebug.h>
+
+#include "discspaceutil.h"
+
+DiscSpaceUtil::DiscSpaceUtil( const TQString &directory, TQObject *parent )
+  : TQObject( parent ),
+    mDirectory( directory ),
+    mFullSize( 0 )
+{
+  calculateFullSize();
+}
+
+unsigned long DiscSpaceUtil::sizeOfPath( const TQString &path )
+{
+  TQFileInfo info( path );
+  if ( !info.exists() ) {
+    return 0;
+  }
+
+  if ( info.isFile() ) {
+    return info.size();
+  } else if ( info.isDir() ) {
+    TQDir dir( path );
+    const TQFileInfoList *infos = dir.entryInfoList( TQDir::Files | TQDir::Dirs | TQDir::NoSymLinks );
+    TQFileInfoListIterator it( *infos );
+
+    unsigned long sum = 0;
+    TQFileInfo *info = 0;
+    while ( (info = it.current()) != 0 ) {
+      if ( info->fileName() != "." && info->fileName() != ".." )
+      sum += sizeOfPath( info->absFilePath() );
+      ++it;
+    }
+
+    return sum;
+  } else {
+    return 0;
+  }
+}
+
+double DiscSpaceUtil::usage( unsigned long additional ) const
+{
+  if ( mFullSize == 0 )
+    return 0;
+
+  unsigned long sum = sizeOfPath( mDirectory );
+  sum += additional;
+
+  sum = sum/1024; // convert to kB
+
+  return (((double)sum*100)/(double)mFullSize);
+}
+
+unsigned long DiscSpaceUtil::size() const
+{
+  return mFullSize;
+}
+
+TQString DiscSpaceUtil::mountPoint() const
+{
+  return mMountPoint;
+}
+
+void DiscSpaceUtil::foundMountPoint( const TQString &mountPoint, unsigned long kbSize, unsigned long, unsigned long )
+{
+  mFullSize = kbSize;
+  mMountPoint = mountPoint;
+}
+
+void DiscSpaceUtil::done()
+{
+  tqApp->eventLoop()->exitLoop();
+}
+
+void DiscSpaceUtil::calculateFullSize()
+{
+  KDiskFreeSp *sp = KDiskFreeSp::findUsageInfo( mDirectory );
+  connect( sp, SIGNAL( foundMountPoint( const TQString&, unsigned long, unsigned long, unsigned long ) ),
+           this, SLOT( foundMountPoint( const TQString&, unsigned long, unsigned long, unsigned long ) ) );
+  connect( sp, SIGNAL( done() ), this, SLOT( done() ) );
+
+  tqApp->eventLoop()->enterLoop();
+}
+
+#include "discspaceutil.moc"
diff --git a/tdeioslave/trash/discspaceutil.h b/tdeioslave/trash/discspaceutil.h
new file mode 100644
index 000000000..a43b7b2cd
--- /dev/null
+++ b/tdeioslave/trash/discspaceutil.h
@@ -0,0 +1,81 @@
+/*
+   This file is part of the KDE project
+
+   Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DISCSPACEUTIL_H
+#define DISCSPACEUTIL_H
+
+#include <tqobject.h>
+#include <tqstring.h>
+
+/**
+ * A small utility class to access and calculate
+ * size and usage of mount points.
+ */
+class DiscSpaceUtil : public TQObject
+{
+  Q_OBJECT
+
+  public:
+    /**
+     * Creates a new disc space util.
+     *
+     * @param directory A directory the util shall work on.
+     * @param parent The parent object.
+     */
+    explicit DiscSpaceUtil( const TQString &directory, TQObject *parent = 0 );
+
+    /**
+     * Returns the usage of the directory pass in the constructor on this
+     * mount point in percent.
+     *
+     * @param additional An additional amount of bytes that is added to the
+     *                   directory size before the usage is calculated.
+     */
+    double usage( unsigned long additional = 0 ) const;
+
+    /**
+     * Returns the size of the partition in kilo bytes.
+     */
+    unsigned long size() const;
+
+    /**
+     * Returns the mount point of the directory.
+     */
+    TQString mountPoint() const;
+
+    /**
+     * Returns the size of the given path in bytes.
+     */
+    static unsigned long sizeOfPath( const TQString &path );
+
+  private slots:
+    void foundMountPoint( const TQString&, unsigned long, unsigned long, unsigned long );
+    void done();
+
+  private:
+    void calculateFullSize();
+
+    TQString mDirectory;
+    unsigned long mFullSize;
+    TQString mMountPoint;
+};
+
+#endif
diff --git a/tdeioslave/trash/ktrashpropsdlgplugin.cpp b/tdeioslave/trash/ktrashpropsdlgplugin.cpp
new file mode 100644
index 000000000..9d18f2acf
--- /dev/null
+++ b/tdeioslave/trash/ktrashpropsdlgplugin.cpp
@@ -0,0 +1,316 @@
+/*
+   This file is part of the KDE project
+
+   Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
+   Copyright (C) 2016 Emanoil Kotsev <deloptes@yahoo.com>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include "ktrashpropsdlgplugin.h"
+#include "discspaceutil.h"
+#include "trashimpl.h"
+
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqlistbox.h>
+#include <tqspinbox.h>
+
+#include <kdesktopfile.h>
+#include <kgenericfactory.h>
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+
+#include <kdebug.h>
+
+typedef KGenericFactory<KTrashPropsDlgPlugin, KPropertiesDialog> Factory;
+K_EXPORT_COMPONENT_FACTORY( ktrashpropsdlgplugin, Factory( "ktrashpropsdlgplugin" ) )
+
+KTrashPropsDlgPlugin::KTrashPropsDlgPlugin( KPropertiesDialog *dialog, const char*, const TQStringList& )
+  : KPropsDlgPlugin( dialog )
+{
+  kdDebug() << "KTrashPropsDlgPlugin::KTrashPropsDlgPlugin called" << endl;
+  if ( dialog->items().count() != 1 )
+    return;
+
+  KFileItem *item = dialog->items().first();
+
+  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
+    return;
+
+  kdDebug() << "KPropsDlgPlugin::isDesktopFile( item ) passed" << endl;
+  KDesktopFile deskFile( item->url().path(), true /* readonly */ );
+
+  if ( deskFile.readURL() != "trash:/" )
+    return;
+
+  kdDebug() << "deskFile.readURL() != \"trash:/\") passed" << endl;
+  TDEGlobal::locale()->insertCatalogue( "tdeio_trash" );
+
+  mTrashImpl = new TrashImpl();
+  mTrashImpl->init();
+
+  readConfig();
+
+  TQFrame *frame = dialog->addPage( i18n( "Size Limits" ) );
+  setupGui( frame );
+
+
+  mUseTimeLimit->setChecked( mConfigMap[ mCurrentTrash ].useTimeLimit );
+  mUseSizeLimit->setChecked( mConfigMap[ mCurrentTrash ].useSizeLimit );
+  mDays->setValue( mConfigMap[ mCurrentTrash ].days );
+  mPercent->setValue( mConfigMap[ mCurrentTrash ].percent );
+  mPercent->setPrecision(3);
+  mLimitReachedAction->setCurrentItem( mConfigMap[ mCurrentTrash ].actionType );
+  percentChanged(mPercent->value());
+
+  useTypeChanged();
+
+  connect( mUseTimeLimit, SIGNAL( toggled( bool ) ),
+           this, SLOT( setDirty() ) );
+  connect( mUseTimeLimit, SIGNAL( toggled( bool ) ),
+           this, SLOT( useTypeChanged() ) );
+  connect( mDays, SIGNAL( valueChanged( int ) ),
+           this, SLOT( setDirty() ) );
+  connect( mUseSizeLimit, SIGNAL( toggled( bool ) ),
+           this, SLOT( setDirty() ) );
+  connect( mUseSizeLimit, SIGNAL( toggled( bool ) ),
+           this, SLOT( useTypeChanged() ) );
+  connect( mPercent, SIGNAL( valueChanged( double ) ),
+           this, SLOT( percentChanged( double ) ) );
+  connect( mPercent, SIGNAL( valueChanged( double ) ),
+           this, SLOT( setDirty() ) );
+  connect( mLimitReachedAction, SIGNAL( activated( int ) ),
+           this, SLOT( setDirty() ) );
+
+ trashChanged( 0 );
+}
+
+KTrashPropsDlgPlugin::~KTrashPropsDlgPlugin()
+{
+}
+
+void KTrashPropsDlgPlugin::applyChanges()
+{
+  if ( !mCurrentTrash.isEmpty() ) {
+    ConfigEntry entry;
+    entry.useTimeLimit = mUseTimeLimit->isChecked();
+    entry.days = mDays->value();
+    entry.useSizeLimit = mUseSizeLimit->isChecked();
+    entry.percent = mPercent->value(),
+    entry.actionType = mLimitReachedAction->currentItem();
+    mConfigMap.insert( mCurrentTrash, entry );
+  }
+
+  writeConfig();
+}
+
+void KTrashPropsDlgPlugin::percentChanged( double percent )
+{
+  DiscSpaceUtil util( mCurrentTrash );
+
+  double partitionSize = util.size() * 1024.0; // convert to byte
+
+  double size = partitionSize*(percent/100.0);
+
+// Step should be depending on size
+// https://api.kde.org/3.5-api/kdelibs-apidocs/kdeui/html/classKDoubleSpinBox.html
+// https://api.kde.org/3.5-api/kdelibs-apidocs/kdeui/html/knuminput_8cpp_source.html
+  mPercent->setPrecision(3);
+
+  TQString unit = i18n( "Byte" );
+  if ( size > 1024 ) {
+    unit = i18n( "KByte" );
+    size = size/1024.0;
+    mPercent->setLineStep(0.001);
+  }
+  if ( size > 1024 ) {
+    unit = i18n( "MByte" );
+    size = size/1024.0;
+    mPercent->setLineStep(0.01);
+  }
+  if ( size > 1024 ) {
+    unit = i18n( "GByte" );
+    size = size/1024.0;
+    mPercent->setLineStep(0.1);
+  }
+  if ( size > 1024 ) {
+    unit = i18n( "TByte" );
+    size = size/1024.0;
+    mPercent->setLineStep(1);
+  }
+
+  mSizeLabel->setText( i18n( "(%1 %2)" ).arg( TQString::number( size, 'f', 2 ) ).arg( unit ) );
+
+}
+
+void KTrashPropsDlgPlugin::trashChanged( int value )
+{
+  const TrashImpl::TrashDirMap map = mTrashImpl->trashDirectories();
+
+  if ( !mCurrentTrash.isEmpty() ) {
+    ConfigEntry entry;
+    entry.useTimeLimit = mUseTimeLimit->isChecked();
+    entry.days = mDays->value();
+    entry.useSizeLimit = mUseSizeLimit->isChecked();
+    entry.percent = mPercent->value(),
+    entry.actionType = mLimitReachedAction->currentItem();
+    mConfigMap.insert( mCurrentTrash, entry );
+  }
+
+  mCurrentTrash = map[ value ];
+
+  if ( mConfigMap.contains( mCurrentTrash ) ) {
+    const ConfigEntry entry = mConfigMap[ mCurrentTrash ];
+    mUseTimeLimit->setChecked( entry.useTimeLimit );
+    mDays->setValue( entry.days );
+    mUseSizeLimit->setChecked( entry.useSizeLimit );
+    mPercent->setValue( entry.percent );
+    mLimitReachedAction->setCurrentItem( entry.actionType );
+  } else {
+    mUseTimeLimit->setChecked( false );
+    mDays->setValue( 7 );
+    mUseSizeLimit->setChecked( true );
+    mPercent->setValue( 10.0 );
+    mLimitReachedAction->setCurrentItem( 0 );
+  }
+
+  percentChanged( mPercent->value() );
+}
+
+void KTrashPropsDlgPlugin::useTypeChanged()
+{
+  mDays->setEnabled( mUseTimeLimit->isChecked() );
+  mSizeWidget->setEnabled( mUseSizeLimit->isChecked() );
+}
+
+void KTrashPropsDlgPlugin::readConfig()
+{
+  kdDebug() << "KTrashPropsDlgPlugin::readConfig() called" << endl;
+  TDEConfig config( "trashrc" );
+  mConfigMap.clear();
+
+  const TQStringList groups = config.groupList();
+  for ( uint i = 0; i < groups.count(); ++i ) {
+    if ( groups[ i ].startsWith( "/" ) ) {
+      config.setGroup( groups[ i ] );
+      ConfigEntry entry;
+      entry.useTimeLimit = config.readBoolEntry( "UseTimeLimit", false );
+      entry.days = config.readNumEntry( "Days", 7 );
+      entry.useSizeLimit = config.readBoolEntry( "UseSizeLimit", true );
+      entry.percent = config.readDoubleNumEntry( "Percent", 10 );
+      entry.actionType = config.readNumEntry( "LimitReachedAction", 0 );
+      mConfigMap.insert( groups[ i ], entry );
+    }
+  }
+}
+
+void KTrashPropsDlgPlugin::writeConfig()
+{
+  kdDebug() << "KTrashPropsDlgPlugin::writeConfig() called" << endl;
+  TDEConfig config( "trashrc" );
+
+  // first delete all existing groups
+  const TQStringList groups = config.groupList();
+  for ( uint i = 0; i < groups.count(); ++i )
+    if ( groups[ i ].startsWith( "/" ) )
+      config.deleteGroup( groups[ i ] );
+
+  TQMapConstIterator<TQString, ConfigEntry> it;
+  for ( it = mConfigMap.begin(); it != mConfigMap.end(); ++it ) {
+    config.setGroup( it.key() );
+    config.writeEntry( "UseTimeLimit", it.data().useTimeLimit );
+    config.writeEntry( "Days", it.data().days );
+    config.writeEntry( "UseSizeLimit", it.data().useSizeLimit );
+    config.writeEntry( "Percent", it.data().percent );
+    config.writeEntry( "LimitReachedAction", it.data().actionType );
+  }
+
+  config.sync();
+}
+
+void KTrashPropsDlgPlugin::setupGui( TQFrame *frame )
+{
+  kdDebug() << "KTrashPropsDlgPlugin::setupGui( TQFrame *frame )" << endl;
+  TQVBoxLayout *layout = new TQVBoxLayout( frame, 11, 6 );
+
+  TrashImpl::TrashDirMap map = mTrashImpl->trashDirectories();
+  if ( map.count() != 1 ) {
+    // If we have multiple trashes, we setup a widget to choose
+    // which trash to configure
+    TQListBox *mountPoints = new TQListBox( frame );
+    layout->addWidget( mountPoints );
+
+    const TQPixmap folderPixmap = TDEGlobal::iconLoader()->loadIcon( "folder", TDEIcon::Small );
+    TQMapConstIterator<int, TQString> it;
+    for ( it = map.begin(); it != map.end(); ++it ) {
+      DiscSpaceUtil util( it.data() );
+      mountPoints->insertItem( folderPixmap, util.mountPoint(), it.key() ); 
+    }
+
+    mountPoints->setCurrentItem( 0 );
+
+    connect( mountPoints, SIGNAL( highlighted( int ) ), SLOT( trashChanged( int ) ) );
+  } else {
+    mCurrentTrash = map[0];
+  }
+
+  TQHBoxLayout *daysLayout = new TQHBoxLayout( layout );
+
+  mUseTimeLimit = new TQCheckBox( i18n( "Delete files older than:" ), frame );
+  daysLayout->addWidget( mUseTimeLimit );
+  mDays = new TQSpinBox( 1, 365, 1, frame );
+  mDays->setSuffix( " days" );
+  daysLayout->addWidget( mDays );
+
+  TQGridLayout *sizeLayout = new TQGridLayout( layout, 2, 2 );
+  mUseSizeLimit = new TQCheckBox( i18n( "Limit to maximum size" ), frame );
+  sizeLayout->addMultiCellWidget( mUseSizeLimit, 0, 0, 0, 1 );
+
+  mSizeWidget = new TQWidget( frame );
+  sizeLayout->setColSpacing( 0, 30 );
+  sizeLayout->addWidget( mSizeWidget, 1, 1 );
+
+  TQGridLayout *sizeWidgetLayout = new TQGridLayout( mSizeWidget, 2, 3, 11, 6 );
+
+  TQLabel *label = new TQLabel( i18n( "Maximum Size:" ), mSizeWidget );
+  sizeWidgetLayout->addWidget( label, 0, 0 );
+
+  mPercent = new KDoubleSpinBox( 0.001, 100, 1, 10, 3, mSizeWidget );
+  mPercent->setSuffix( " %" );
+  sizeWidgetLayout->addWidget( mPercent, 0, 1 );
+
+  mSizeLabel = new TQLabel( mSizeWidget );
+  sizeWidgetLayout->addWidget( mSizeLabel, 0, 2 );
+
+  label = new TQLabel( i18n( "When limit reached:" ), mSizeWidget );
+  sizeWidgetLayout->addWidget( label, 1, 0 );
+
+  mLimitReachedAction = new TQComboBox( mSizeWidget );
+  mLimitReachedAction->insertItem( i18n( "Warn me" ) );
+  mLimitReachedAction->insertItem( i18n( "Delete oldest files from trash" ) );
+  mLimitReachedAction->insertItem( i18n( "Delete biggest files from trash" ) );
+  sizeWidgetLayout->addMultiCellWidget( mLimitReachedAction, 1, 1, 1, 2 );
+
+  layout->addStretch();
+
+}
+
+#include "ktrashpropsdlgplugin.moc"
diff --git a/tdeioslave/trash/ktrashpropsdlgplugin.desktop b/tdeioslave/trash/ktrashpropsdlgplugin.desktop
new file mode 100644
index 000000000..91f0632b0
--- /dev/null
+++ b/tdeioslave/trash/ktrashpropsdlgplugin.desktop
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=Service
+Name=Trash Properties Page
+Name[bg]=Свойства на кошчето
+X-TDE-Library=ktrashpropsdlgplugin
+X-TDE-ServiceTypes=KPropsDlg/Plugin,media/builtin-trash
diff --git a/tdeioslave/trash/ktrashpropsdlgplugin.h b/tdeioslave/trash/ktrashpropsdlgplugin.h
new file mode 100644
index 000000000..d47e75dd3
--- /dev/null
+++ b/tdeioslave/trash/ktrashpropsdlgplugin.h
@@ -0,0 +1,78 @@
+/*
+   This file is part of the KDE project
+
+   Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KTRASHPROPSDLGPLUGIN_H
+#define KTRASHPROPSDLGPLUGIN_H
+
+#include <kpropertiesdialog.h>
+
+class KDoubleSpinBox;
+class TQCheckBox;
+class TQComboBox;
+class TQFrame;
+class TQLabel;
+class TQSpinBox;
+class TrashImpl;
+
+class KTrashPropsDlgPlugin : public KPropsDlgPlugin
+{
+  Q_OBJECT
+
+  public:
+    KTrashPropsDlgPlugin( KPropertiesDialog *dialog, const char*, const TQStringList& );
+    ~KTrashPropsDlgPlugin();
+
+    virtual void applyChanges();
+
+  private slots:
+    void percentChanged( double );
+    void trashChanged( int );
+    void useTypeChanged();
+
+  private:
+    void readConfig();
+    void writeConfig();
+    void setupGui( TQFrame *frame );
+
+    TQCheckBox *mUseTimeLimit;
+    TQSpinBox *mDays;
+    TQCheckBox *mUseSizeLimit;
+    TQWidget *mSizeWidget;
+    KDoubleSpinBox *mPercent;
+    TQLabel *mSizeLabel;
+    TQComboBox *mLimitReachedAction;
+
+    TrashImpl *mTrashImpl;
+    TQString mCurrentTrash;
+
+    typedef struct {
+      bool useTimeLimit;
+      int days;
+      bool useSizeLimit;
+      double percent;
+      int actionType;
+    } ConfigEntry;
+
+    typedef TQMap<TQString, ConfigEntry> ConfigMap;
+    ConfigMap mConfigMap;
+};
+
+#endif
diff --git a/tdeioslave/trash/testtrash.cpp b/tdeioslave/trash/testtrash.cpp
index db2e73fb3..fc5b358af 100644
--- a/tdeioslave/trash/testtrash.cpp
+++ b/tdeioslave/trash/testtrash.cpp
@@ -24,7 +24,7 @@
 #include "tdeio_trash.h"
 #include "testtrash.h"
 
-#include <config.h>
+// #include <config.h>
 
 #include <kurl.h>
 #include <tdelocale.h>
diff --git a/tdeioslave/trash/trash.protocol b/tdeioslave/trash/trash.protocol
index ba3fd5dc7..e1029d038 100644
--- a/tdeioslave/trash/trash.protocol
+++ b/tdeioslave/trash/trash.protocol
@@ -86,4 +86,4 @@ ExtraNames[vi]=Đường dẫn Trước khi vứt,Ngày Vứt
 ExtraNames[wa]=Oridjinå tchmin,Date di disfaçaedje
 ExtraNames[zh_CN]=原始路径,删除日期
 ExtraNames[zh_TW]=原始路徑,刪除日期
-ExtraTypes=QString,QDateTime
+ExtraTypes=TQString,TQDateTime
diff --git a/tdeioslave/trash/trashimpl.cpp b/tdeioslave/trash/trashimpl.cpp
index c96d15d3a..1b67e5949 100644
--- a/tdeioslave/trash/trashimpl.cpp
+++ b/tdeioslave/trash/trashimpl.cpp
@@ -18,6 +18,8 @@
 */
 
 #include "trashimpl.h"
+#include "discspaceutil.h"
+
 #include <tdelocale.h>
 #include <klargefile.h>
 #include <tdeio/global.h>
@@ -322,6 +324,9 @@ bool TrashImpl::deleteInfo( int trashId, const TQString& fileId )
 bool TrashImpl::moveToTrash( const TQString& origPath, int trashId, const TQString& fileId )
 {
     kdDebug() << k_funcinfo << endl;
+    if ( !adaptTrashSize( origPath, trashId ) )
+        return false;
+
     const TQString dest = filesPath( trashId, fileId );
     if ( !move( origPath, dest ) ) {
         // Maybe the move failed due to no permissions to delete source.
@@ -387,6 +392,9 @@ void TrashImpl::jobFinished(TDEIO::Job* job)
 bool TrashImpl::copyToTrash( const TQString& origPath, int trashId, const TQString& fileId )
 {
     kdDebug() << k_funcinfo << endl;
+    if ( !adaptTrashSize( origPath, trashId ) )
+        return false;
+
     const TQString dest = filesPath( trashId, fileId );
     if ( !copy( origPath, dest ) )
         return false;
@@ -959,4 +967,91 @@ bool TrashImpl::parseURL( const KURL& url, int& trashId, TQString& fileId, TQStr
     return true;
 }
 
+bool TrashImpl::adaptTrashSize( const TQString& origPath, 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 );
+    double percent = config.readDoubleNumEntry( "Percent", 10 );
+    int actionType = config.readNumEntry( "LimitReachedAction", 0 );
+
+    if ( useTimeLimit ) { // delete all files in trash older than X days
+        const int maxDays = config.readNumEntry( "Days", 7 );
+        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 );
+        }
+
+        return true;
+
+    }
+
+    if ( useSizeLimit ) { // check if size limit exceeded
+
+        // calculate size of the files to be put into the trash
+        unsigned long additionalSize = DiscSpaceUtil::sizeOfPath( origPath );
+
+        DiscSpaceUtil util( trashPath + "/files/" );
+        if ( util.usage( additionalSize ) >= percent ) {
+            if ( actionType == 0 ) { // warn the user only
+                m_lastErrorCode = TDEIO::ERR_SLAVE_DEFINED;
+                m_lastErrorMessage = i18n( "The trash has reached its maximum size!\nClean the trash manually." );
+                return false;
+            } else {
+                // before we start to remove any files from the trash,
+                // check whether the new file will fit into the trash
+                // at all...
+
+                unsigned long partitionSize = util.size(); // in kB
+                unsigned long fileSize = additionalSize/1024; // convert to kB
+
+                if ( ((double)fileSize*100/(double)partitionSize) >= percent ) {
+                    m_lastErrorCode = TDEIO::ERR_SLAVE_DEFINED;
+                    m_lastErrorMessage = i18n( "The file is too large to be trashed." );
+                    return false;
+                }
+
+                // the size of the to be trashed file is ok, so lets start removing
+                // some other files from the trash
+
+                TQDir dir( trashPath + "/files" );
+                const TQFileInfoList *infos = 0;
+                if ( actionType == 1 )  // delete oldest files first
+                    infos = dir.entryInfoList( TQDir::Files | TQDir::Dirs, TQDir::Time | TQDir::Reversed );
+                else if ( actionType == 2 ) // delete biggest files first
+                    infos = dir.entryInfoList( TQDir::Files | TQDir::Dirs, TQDir::Size );
+                else
+                    tqWarning( "Should never happen!" );
+
+                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.usage( additionalSize ) < percent ) // check whether we have enough space now
+                            deleteFurther = false;
+                    }
+                    ++it;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
 #include "trashimpl.moc"
diff --git a/tdeioslave/trash/trashimpl.h b/tdeioslave/trash/trashimpl.h
index 3a06dd9e8..b02ae4709 100644
--- a/tdeioslave/trash/trashimpl.h
+++ b/tdeioslave/trash/trashimpl.h
@@ -123,6 +123,8 @@ private:
     void fileAdded();
     void fileRemoved();
 
+    bool adaptTrashSize( const TQString& origPath, int trashId );
+
     // Warning, returns error code, not a bool
     int testDir( const TQString& name ) const;
     void error( int e, const TQString& s );
-- 
cgit v1.2.3

