[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