[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    trash cleaning - 3rd attempt
From:       Philippe Fremy <pfremy () chez ! com>
Date:       2001-03-07 10:54:30
[Download RAW message or body]

Hi,

Ok, here is my patch again, updated with the previous remarks.

I still find the the configuration dialog quite big, but it is not due to 
folder configuration.

The only thing it is missing right now is a folder icon. I'll try to find one 
later.

	regards,

	Philippe
--
Free the mallocs!
["keep-small-trash-2.diff" (text/x-c)]

Index: configuredialog.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/configuredialog.cpp,v
retrieving revision 1.79
diff -u -3 -p -r1.79 configuredialog.cpp
--- configuredialog.cpp	2001/02/24 15:35:55	1.79
+++ configuredialog.cpp	2001/03/07 10:12:42
@@ -474,6 +474,7 @@ ConfigureDialog::ConfigureDialog( QWidge
   makeComposerPage();
   makeMimePage();
   makeSecurityPage();
+  makeFolderPage();
   makeMiscPage();
 }
 
@@ -1261,42 +1262,98 @@ void ConfigureDialog::makeSecurityPage( 
 #include <kinstance.h>
 #include <kglobal.h>
 
-void ConfigureDialog::makeMiscPage( void )
+void ConfigureDialog::makeFolderPage( void )
 {
   //KIconLoader *loader = instace->iconLoader();
   ///KGlobal::instance()->iconLoader()
 
-  QFrame *page = addPage( i18n("Miscellaneous"), i18n("Various settings"),
-    KGlobal::instance()->iconLoader()->loadIcon( "misc", KIcon::NoGroup,
+  QFrame *page = addPage( i18n("Folder"), i18n("Folder settings"),
+    KGlobal::instance()->iconLoader()->loadIcon( /*XXX*/ "misc", KIcon::NoGroup,
     KIcon::SizeMedium ));
   QVBoxLayout *topLevel = new QVBoxLayout( page, 0, spacingHint() );
-  mMisc.pageIndex = pageIndex(page);
+  mFolder.pageIndex = pageIndex(page);
+
+  //---------- group: trash folder
+  QGroupBox *tgroup = new QGroupBox( i18n("&Trash folder"), page );
+  topLevel->addWidget( tgroup );
+  QVBoxLayout *tvlay = new QVBoxLayout( tgroup, spacingHint() );
+
+  tvlay->addSpacing( fontMetrics().lineSpacing() );
+  mFolder.emptyTrashCheck =
+    new QCheckBox(i18n("Empty trash on exit"), tgroup );
+  connect( mFolder.emptyTrashCheck, SIGNAL(stateChanged(int)), 
+		  this, SLOT(slotEmptyTrashState(int)) );
+  tvlay->addWidget( mFolder.emptyTrashCheck );
+  QHBoxLayout *stlay = new QHBoxLayout( spacingHint() ,"hly1");
+  stlay->setMargin(0);
+  tvlay->addLayout( stlay );
+  mFolder.keepSmallTrashCheck =
+    new QCheckBox(i18n("Keep trash size below "), tgroup );
+  stlay->addWidget( mFolder.keepSmallTrashCheck );
+  mFolder.smallTrashSizeSpin = new KIntNumInput( tgroup );
+  //mFolder.smallTrashSizeSpin->setMinValue(1);
+  stlay->addWidget( mFolder.smallTrashSizeSpin );
+  stlay->addWidget( new QLabel( "MB", tgroup ) );
+  stlay->addStretch( 100 );
+
+  QHBoxLayout *rmvlay = new QHBoxLayout( spacingHint(),"hly2" );
+  rmvlay->setMargin(0);
+  tvlay->addLayout( rmvlay );
+  mFolder.removeOldMailCheck =
+    new QCheckBox(i18n("In trash, on exit, remove messages older than"), tgroup );
+  rmvlay->addWidget( mFolder.removeOldMailCheck );
+  mFolder.oldMailAgeSpin = new KIntNumInput( tgroup );
+  mFolder.oldMailAgeSpin->setValue(1);
+  //mFolder.oldMailAgeSpin->setMinValue(1);
+  rmvlay->addWidget( mFolder.oldMailAgeSpin );
+  mFolder.timeUnitCombo = new QComboBox( tgroup );
+  mFolder.timeUnitCombo->insertItem(i18n("month(s)"));
+  mFolder.timeUnitCombo->insertItem(i18n("week(s)"));
+  mFolder.timeUnitCombo->insertItem(i18n("day(s)"));
+  rmvlay->addWidget( mFolder.timeUnitCombo );
+  rmvlay->addStretch( 100 );
 
+
+
   //---------- group: folders
+
   QGroupBox *group = new QGroupBox( i18n("&Folders"), page );
   topLevel->addWidget( group );
   QVBoxLayout *vlay = new QVBoxLayout( group, spacingHint() );
   vlay->addSpacing( fontMetrics().lineSpacing() );
-  mMisc.emptyTrashCheck =
-    new QCheckBox(i18n("Empty trash on exit"), group );
-  vlay->addWidget( mMisc.emptyTrashCheck );
-  mMisc.sendOutboxCheck =
+  mFolder.sendOutboxCheck =
     new QCheckBox(i18n("Send Mail in outbox Folder on Check"), group );
-  vlay->addWidget( mMisc.sendOutboxCheck );
-  mMisc.sendReceiptCheck = new QCheckBox(
+  vlay->addWidget( mFolder.sendOutboxCheck );
+  mFolder.sendReceiptCheck = new QCheckBox(
     i18n("Automatically send receive- and read confirmations"), group );
-  vlay->addWidget( mMisc.sendReceiptCheck );
-  mMisc.compactOnExitCheck =
+  vlay->addWidget( mFolder.sendReceiptCheck );
+  mFolder.compactOnExitCheck =
     new QCheckBox(i18n("Compact all folders on exit"), group );
-  vlay->addWidget( mMisc.compactOnExitCheck );
-  mMisc.emptyFolderConfirmCheck =
+  vlay->addWidget( mFolder.compactOnExitCheck );
+  mFolder.emptyFolderConfirmCheck =
     new QCheckBox(i18n("Confirm before emptying folders"), group );
-  vlay->addWidget( mMisc.emptyFolderConfirmCheck );
+  vlay->addWidget( mFolder.emptyFolderConfirmCheck );
+
+  topLevel->addStretch( 10 );
+}
+
+  
+  
+void ConfigureDialog::makeMiscPage( void )
+{
+  //KIconLoader *loader = instace->iconLoader();
+  ///KGlobal::instance()->iconLoader()
 
+  QFrame *page = addPage( i18n("Miscellaneous"), i18n("Various settings"),
+    KGlobal::instance()->iconLoader()->loadIcon( "misc", KIcon::NoGroup,
+    KIcon::SizeMedium ));
+  QVBoxLayout *topLevel = new QVBoxLayout( page, 0, spacingHint() );
+  mMisc.pageIndex = pageIndex(page);
+
   //---------- group: External editor
-  group = new QGroupBox( i18n("&External Editor"), page );
+  QGroupBox * group = new QGroupBox( i18n("&External Editor"), page );
   topLevel->addWidget( group );
-  vlay = new QVBoxLayout( group, spacingHint() );
+  QBoxLayout * vlay = new QVBoxLayout( group, spacingHint() );
   vlay->addSpacing( fontMetrics().lineSpacing() );
   mMisc.externalEditorCheck =
     new QCheckBox(i18n("Use external editor instead of composer"), group );
@@ -1365,8 +1422,8 @@ void ConfigureDialog::setup( void )
   setupComposerPage();
   setupMimePage();
   setupSecurityPage();
+  setupFolderPage();
   setupMiscPage();
-
 }
 
 
@@ -1687,22 +1744,39 @@ void ConfigureDialog::setupSecurityPage(
 }
 
 
-void ConfigureDialog::setupMiscPage( void )
+void ConfigureDialog::setupFolderPage( void )
 {
   KConfig &config = *kapp->config();
   config.setGroup("General");
 
-  bool state = config.readBoolEntry("empty-trash-on-exit",true);
-  mMisc.emptyTrashCheck->setChecked( state );
+  bool state = config.readBoolEntry("empty-trash-on-exit",false);
+  mFolder.emptyTrashCheck->setChecked( state );
+  state = config.readBoolEntry("keep-small-trash", true);
+  mFolder.keepSmallTrashCheck->setChecked( state );
+  int num = config.readNumEntry("small-trash-size", 1);
+  mFolder.smallTrashSizeSpin->setValue( num );
+  state = config.readBoolEntry("remove-old-mail-from-trash", true);
+  mFolder.removeOldMailCheck->setChecked( state );
+  num = config.readNumEntry("old-mail-age", 1);
+  mFolder.oldMailAgeSpin->setValue( num );
+  num = config.readNumEntry("old-mail-age-unit", 1);
+  mFolder.timeUnitCombo->setCurrentItem( num );
   state = config.readBoolEntry("sendOnCheck", false);
-  mMisc.sendOutboxCheck->setChecked( state );
+  mFolder.sendOutboxCheck->setChecked( state );
   state = config.readBoolEntry("send-receipts", false );
-  mMisc.sendReceiptCheck->setChecked( state );
+  mFolder.sendReceiptCheck->setChecked( state );
   state = config.readBoolEntry("compact-all-on-exit", true );
-  mMisc.compactOnExitCheck->setChecked( state );
+  mFolder.compactOnExitCheck->setChecked( state );
   state = config.readBoolEntry("confirm-before-empty", true );
-  mMisc.emptyFolderConfirmCheck->setChecked( state );
-  state = config.readBoolEntry( "use-external-editor", false );
+  mFolder.emptyFolderConfirmCheck->setChecked( state );
+}
+
+void ConfigureDialog::setupMiscPage( void )
+{
+  KConfig &config = *kapp->config();
+  config.setGroup("General");
+
+  bool state = config.readBoolEntry( "use-external-editor", false );
   mMisc.externalEditorCheck->setChecked( state );
   mMisc.externalEditorEdit->setText( config.readEntry("external-editor", "") );
   state = config.readBoolEntry("beep-on-mail", false );
@@ -2091,19 +2165,33 @@ void ConfigureDialog::slotDoApply( bool 
   {
     mSecurity.pgpConfig->applySettings();
   }
-  if( activePage == mMisc.pageIndex || everything )
+  if( activePage == mFolder.pageIndex || everything )
   {
     config.setGroup("General");
     config.writeEntry( "empty-trash-on-exit",
-		       mMisc.emptyTrashCheck->isChecked() );
+		       mFolder.emptyTrashCheck->isChecked() );
+    config.writeEntry( "keep-small-trash",
+               mFolder.keepSmallTrashCheck->isChecked() );
+	config.writeEntry( "small-trash-size", 
+               mFolder.smallTrashSizeSpin->value() );
+    config.writeEntry( "remove-old-mail-from-trash",
+               mFolder.removeOldMailCheck->isChecked() );
+	config.writeEntry( "old-mail-age", 
+               mFolder.oldMailAgeSpin->value() );
+	config.writeEntry( "old-mail-age-unit",
+               mFolder.timeUnitCombo->currentItem() );
     config.writeEntry( "sendOnCheck",
-		       mMisc.sendOutboxCheck->isChecked() );
+		       mFolder.sendOutboxCheck->isChecked() );
     config.writeEntry( "send-receipts",
-		       mMisc.sendReceiptCheck->isChecked() );
+		       mFolder.sendReceiptCheck->isChecked() );
     config.writeEntry( "compact-all-on-exit",
-		       mMisc.compactOnExitCheck->isChecked() );
+		       mFolder.compactOnExitCheck->isChecked() );
     config.writeEntry( "confirm-before-empty",
-                       mMisc.emptyFolderConfirmCheck->isChecked() );
+                       mFolder.emptyFolderConfirmCheck->isChecked() );
+  }
+
+  if( activePage == mMisc.pageIndex || everything )
+  {
     config.writeEntry( "use-external-editor",
 		       mMisc.externalEditorCheck->isChecked() );
     config.writeEntry( "external-editor",
@@ -3137,6 +3225,15 @@ void ConfigureDialog::slotMailCommandCho
   }
 }
 
+void ConfigureDialog::slotEmptyTrashState( int state)
+{
+  bool on = ( state == 0 ); // button not checked
+  mFolder.removeOldMailCheck->setEnabled( on );
+  mFolder.oldMailAgeSpin->setEnabled( on );
+  mFolder.timeUnitCombo->setEnabled( on );
+  mFolder.keepSmallTrashCheck->setEnabled( on );
+  mFolder.smallTrashSizeSpin->setEnabled( on );
+}
 
 IdentityEntry::IdentityEntry( void )
 {
Index: configuredialog.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/configuredialog.h,v
retrieving revision 1.31
diff -u -3 -p -r1.31 configuredialog.h
--- configuredialog.h	2001/02/23 15:09:50	1.31
+++ configuredialog.h	2001/03/07 10:12:44
@@ -361,14 +361,23 @@ class ConfigureDialog : public KDialogBa
       int        pageIndex;
       KpgpConfig *pgpConfig;
     };
-    struct MiscWidget
+    struct FolderWidget
     {
       int         pageIndex;
       QCheckBox   *emptyTrashCheck;
+      QCheckBox   *keepSmallTrashCheck;
+      KIntNumInput *smallTrashSizeSpin;
+      QCheckBox   *removeOldMailCheck;
+      KIntNumInput *oldMailAgeSpin;
+      QComboBox   *timeUnitCombo;
       QCheckBox   *sendOutboxCheck;
       QCheckBox   *sendReceiptCheck;
       QCheckBox   *compactOnExitCheck;
       QCheckBox   *emptyFolderConfirmCheck;
+    };
+    struct MiscWidget
+    {
+      int         pageIndex;
       QCheckBox   *externalEditorCheck;
       QLineEdit   *externalEditorEdit;
       QPushButton *externalEditorChooseButton;
@@ -391,6 +400,7 @@ class ConfigureDialog : public KDialogBa
       page_mimeheader,
       page_security,
       page_misc,
+      page_folder,
       page_max
     };
 
@@ -413,6 +423,7 @@ class ConfigureDialog : public KDialogBa
     void makeComposerPage( void );
     void makeMimePage( void );
     void makeSecurityPage( void );
+    void makeFolderPage( void );
     void makeMiscPage( void );
 
     void setupIdentityPage( void );
@@ -421,6 +432,7 @@ class ConfigureDialog : public KDialogBa
     void setupComposerPage( void );
     void setupMimePage( void );
     void setupSecurityPage( void );
+    void setupFolderPage( void );
     void setupMiscPage( void );
     void installProfile( void );
 
@@ -477,6 +489,7 @@ class ConfigureDialog : public KDialogBa
     void slotMailCommandSelectionChanged( void );
     void slotExternalEditorChooser( void );
     void slotMailCommandChooser( void );
+    void slotEmptyTrashState( int );
 
   private:
     IdentityWidget   mIdentity;
@@ -485,6 +498,7 @@ class ConfigureDialog : public KDialogBa
     ComposerWidget   mComposer;
     MimeWidget       mMime;
     SecurityWidget   mSecurity;
+    FolderWidget     mFolder;
     MiscWidget       mMisc;
 
     IdentityList     mIdentityList;
Index: kmfolder.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolder.cpp,v
retrieving revision 1.132
diff -u -3 -p -r1.132 kmfolder.cpp
--- kmfolder.cpp	2001/03/01 20:08:36	1.132
+++ kmfolder.cpp	2001/03/07 10:13:10
@@ -2,6 +2,7 @@
 // Author: Stefan Taferner <taferner@alpin.or.at>
 
 #include <qfileinfo.h>
+#include <qsortedlist.h>
 
 #include "kmglobal.h"
 #include "kmfolder.h"
@@ -839,9 +840,134 @@ void KMFolder::quiet(bool beQuiet)
 
 
 //-----------------------------------------------------------------------------
+
+// Needed to use QSortedList in reduceSize()
+
+/** Compare message's date. This is useful for message sorting */
+int operator<( KMMsgBase & m1, KMMsgBase & m2 )
+{
+  return (m1.date() < m2.date());
+}
+  
+/** Compare message's date. This is useful for message sorting */
+int operator==( KMMsgBase & m1, KMMsgBase & m2 )
+{
+  return (m1.date() == m2.date());
+}
+  
+//-----------------------------------------------------------------------------
+int KMFolder::reduceSize( int aSize )
+{
+  kdDebug() << "Reducing folder to size of " << aSize << " Mo" << endl;
+  QSortedList<KMMsgBase> * slice=0L;
+  QList< QSortedList<KMMsgBase> > sliceArr;
+  KMMsgBase* mb;
+  ulong folderSize, msgSize, sliceSize, firstSliceSize, lastSliceSize, size;
+  int sliceIndex;
+  int delMsg = 0;
+  int i;
+
+  sliceArr.setAutoDelete( true );
+
+  // I put each email in a slice according to its size (slices of 500Ko, 1Mo,
+  // 2Mo, ... 10 Mo). Then I delete the oldest mail until the good size is 
+  // reached. 10 slices of 1Mo each is probably overkill. 500Ko, 1Mo, 5Mo 
+  // and 10Mo could be enough.
+
+
+// Is it 1000 or 1024 ?
+#define KILO 	(1000)
+
+  size = KILO * KILO * aSize; // to have size in Ko;
+  sliceSize = KILO * KILO ; // slice of 1 Mo
+  lastSliceSize = 10 * sliceSize; // last slice is for item > 10 Mo
+  firstSliceSize = sliceSize / 2; // first slice is for < 500 Ko
+  folderSize = 0;
+
+  for(i=0; i<12; i++) {
+    sliceArr.append( new QSortedList<KMMsgBase> );
+    sliceArr.at(i)->setAutoDelete(false);
+  }
+
+  for (i=count()-1; i>=0; i--) {
+    mb = getMsgBase(i);
+    assert(mb);
+    msgSize = mb->msgSize();
+    folderSize += msgSize;
+
+    if (msgSize < firstSliceSize) {
+      sliceIndex = 0;
+    } else if (msgSize >= lastSliceSize) {
+        sliceIndex = 11;
+    } else {
+        sliceIndex = 1 + (int) (msgSize / sliceSize); //  1 <= n < 10
+    }
+
+    sliceArr.at(sliceIndex)->append( mb );
+  }
+
+  //kdDebug() << "Folder size : " << (folderSize/KILO) << " ko" << endl;
+
+  // Ok, now we have our slices
+
+  slice = sliceArr.last();
+  while (folderSize > size) {
+    //kdDebug() << "Treating slice " << sliceArr.at()-1 << " Mo : " << \
slice->count() << endl; +    assert( slice );
+    
+    slice->sort();
+
+    // Empty this slice taking the oldest mails first:
+    while( slice->count() > 0 && folderSize > size ) {
+      mb = slice->take(0);
+      msgSize = mb->msgSize();
+      //kdDebug() << "deleting msg : " << (msgSize / KILO) << " ko - " << \
mb->subject() << " - " << mb->dateStr(); +      assert( folderSize >= msgSize );
+      folderSize -= msgSize;
+      delMsg++;
+      removeMsg(mb);
+    }
+
+    slice = sliceArr.prev();
+
+  }
+
+  return delMsg;
+}
+
+
+
+//-----------------------------------------------------------------------------
+int KMFolder::expungeOldMsg(int days)
+{
+  int i, msgnb=0;
+  time_t msgTime, maxTime;
+  KMMsgBase* mb;
+  QValueList<int> rmvMsgList;
+
+  maxTime = time(0L) - days * 3600 * 24;
+
+  for (i=count()-1; i>=0; i--) {
+    mb = getMsgBase(i);
+    assert(mb);
+	msgTime = mb->date();
+
+	if (msgTime < maxTime) {
+		//kdDebug() << "deleting msg " << i << " : " << mb->subject() << " - " << \
mb->dateStr(); // << endl; +        removeMsg( i );
+		msgnb++;
+	}
+  }
+  return msgnb;
+}
+
+
+//-----------------------------------------------------------------------------
 void KMFolder::removeMsg(KMMsgBasePtr aMsg)
 {
-  removeMsg(find(aMsg));
+  int idx = find(aMsg);
+  assert( idx != -1);
+  removeMsg(idx);
 }
 
 
Index: kmfolder.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolder.h,v
retrieving revision 1.37
diff -u -3 -p -r1.37 kmfolder.h
--- kmfolder.h	2001/02/23 16:11:38	1.37
+++ kmfolder.h	2001/03/07 10:13:13
@@ -116,6 +116,14 @@ public:
   virtual void removeMsg(int i);
   virtual void removeMsg(KMMsgBasePtr msg);
 
+  /** Delete messages in the folder that are older than days. Return the
+   * number of deleted messages. */
+  virtual int expungeOldMsg(int days);
+
+  /** Delete messages until the size of the folder goes below size Mo. 
+   * Returns the number of deleted messages. */
+  virtual int reduceSize( int size );
+
   /** Detaches the given message from it's current folder and
     adds it to this folder. Returns zero on success and an errno error
     code on failure. The index of the new message is stored in index_return
Index: kmkernel.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmkernel.cpp,v
retrieving revision 1.37
diff -u -3 -p -r1.37 kmkernel.cpp
--- kmkernel.cpp	2001/02/09 15:17:34	1.37
+++ kmkernel.cpp	2001/03/07 10:13:16
@@ -504,11 +504,48 @@ void KMKernel::cleanup(void)
   KConfig* config =  kapp->config();
 
   if (the_trashFolder) {
+
     the_trashFolder->close(TRUE);
     config->setGroup("General");
     if (config->readBoolEntry("empty-trash-on-exit", true))
       the_trashFolder->expunge();
+
+	// Phil add on
+    if (config->readBoolEntry("remove-old-mail-from-trash", true) 
+		|| (config->readBoolEntry("keep-small-trash", true)) ) {
+      the_trashFolder->open();
+      the_trashFolder->quiet(true);
+	}
+
+    if (config->readBoolEntry("remove-old-mail-from-trash", true)) {
+      int age;
+      int old_age = config->readNumEntry("old-mail-age", 1);
+      int age_unit = config->readNumEntry("old-mail-age-unit", 1);
+      if (age_unit == 0) { // month
+        age = 31 * old_age;
+      } else if (age_unit == 1) { // week
+        age = 7 * old_age;
+      } else if (age_unit == 2) { // day
+        age = old_age;
+      } else {
+        kdDebug() << "Unknown unit for mail age : " << old_age << endl;
+        age = old_age;
+      }
+      kdDebug() << "Removing mail older than " << age << " days" << endl;
+
+	  the_trashFolder->expungeOldMsg( age );
+    }
+
+    if (config->readBoolEntry("keep-small-trash", true)) {
+      int size = config->readNumEntry("small-trash-size", 10);
+      the_trashFolder->reduceSize( size );
+    }
+
+	the_trashFolder->close();
+    the_trashFolder->compact();
+    kdDebug() << "trash clean-up done.";
   }
+
 
   if (the_folderMgr) {
     if (config->readBoolEntry("compact-all-on-exit", true))


_______________________________________________
Kmail Developers mailing list
Kmail@master.kde.org
http://master.kde.org/mailman/listinfo/kmail


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic