--Boundary-00=_Oyy/+hc1+5BWvBw Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-Description: clearsigned data Content-Disposition: inline =2D----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi there! I recently started using KMail, but I miss one feature available in other m= ail readers: Leave mail on server for N days. This wish is registered as bug #38177. I have now implemented this feature in KMail. This is actually my first contribution to the KDE project, but hopefully not my last! Some comments about my implementation: I have studied the source for KMail = for some time, and I see that the mail UIDs are stored simply as a list of strings. To implement this feature the time the mail was first seen is also needed; the simplest way to add this is to store it in a new list of ints (seconds since epoch). To improve the UI (IMHO of course) I have changed th= e=20 "Delete mail from server" option to "Leave message on server"; the change i= s=20 only in the UI (it already is mLeaveOnServer in kmacctexppop.cpp) so no mai= l=20 should be deleted accidentally from this. Now, when both the "leave message= =20 on server" and "delete from sever after N days" options are enabled KMail=20 will check the age of each message on the server, and delete those which ar= e=20 too old. Does this seem like an acceptable approach? If it is I hope my code can be added to KMail. Unfortunately I only have very limited bandwidth to the Internet at the moment, so haven't been able to check out the latest CVS version of KDE; the patch is against KMail 1.5. I hope the patch can still = be applied without too many changes. One more thing: I haven't been able to test this code extensively, so I wou= ld appreciate anyone willing to test it and give me feedback. =2D -- Kristian =2D----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (GNU/Linux) iD8DBQE+/yyRRBuET7ul/ccRAhAkAJ0fRq0PyYzJrD38NJAbd6gb0LBu6ACdFOo6 o3grM4WVV7awrf1XSE7pV/0=3D =3DljKA =2D----END PGP SIGNATURE----- --Boundary-00=_Oyy/+hc1+5BWvBw Content-Type: text/x-diff; charset="us-ascii"; name="delete-after-days.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="delete-after-days.patch" diff -u ../../kdenetwork-3.1-orig/kmail/accountdialog.cpp ./accountdialog.cpp --- ../../kdenetwork-3.1-orig/kmail/accountdialog.cpp 2002-12-05 21:49:11.000000000 +0100 +++ ./accountdialog.cpp 2003-06-29 20:05:56.000000000 +0200 @@ -518,13 +518,34 @@ new QCheckBox( i18n("Sto&re POP password in configuration file"), page1 ); grid->addMultiCellWidget( mPop.storePasswordCheck, 6, 6, 0, 1 ); - mPop.deleteMailCheck = - new QCheckBox( i18n("&Delete message from server after fetching"), page1 ); - grid->addMultiCellWidget( mPop.deleteMailCheck, 7, 7, 0, 1 ); + mPop.leaveMailCheck = + new QCheckBox( i18n("&Leave messages on server after fetching"), page1 ); + grid->addMultiCellWidget( mPop.leaveMailCheck, 7, 7, 0, 1 ); + + QHBox * hboxDelete = new QHBox( page1 ); + hboxDelete->setSpacing( KDialog::spacingHint() ); + mPop.deleteAfterDaysCheck = + new QCheckBox( i18n("&Delete from server after"), hboxDelete ); + mPop.deleteAfterDaysCheck->setEnabled( false ); + connect( mPop.leaveMailCheck, SIGNAL(toggled(bool)), + mPop.deleteAfterDaysCheck, SLOT(setEnabled(bool)) ); + mPop.deleteAfterDaysSpin = new KIntNumInput ( hboxDelete ); + mPop.deleteAfterDaysSpin->setEnabled( false ); + hboxDelete->setStretchFactor( mPop.deleteAfterDaysSpin, 1 ); + mPop.deleteAfterDaysSpin->setRange( 1, 10000, 1, FALSE ); + mPop.deleteAfterDaysSpin->setValue( 7 ); + mPop.deleteAfterDaysSpin->setSuffix( i18n(" days") ); + grid->addMultiCellWidget( hboxDelete, 8, 8, 0, 1 ); + connect( mPop.deleteAfterDaysCheck, SIGNAL(toggled(bool)), + mPop.deleteAfterDaysSpin, SLOT(setEnabled(bool)) ); + QString msgDelete = i18n("If you select this option, messages on the server " + "will be automatically delete after this many days."); + QWhatsThis::add( mPop.deleteAfterDaysCheck, msgDelete ); + QWhatsThis::add( mPop.deleteAfterDaysSpin, msgDelete ); mPop.excludeCheck = new QCheckBox( i18n("E&xclude from \"Check Mail\""), page1 ); - grid->addMultiCellWidget( mPop.excludeCheck, 8, 8, 0, 1 ); + grid->addMultiCellWidget( mPop.excludeCheck, 9, 9, 0, 1 ); QHBox * hbox = new QHBox( page1 ); hbox->setSpacing( KDialog::spacingHint() ); @@ -536,40 +557,40 @@ mPop.filterOnServerSizeSpin->setRange( 1, 10000000, 100, FALSE ); mPop.filterOnServerSizeSpin->setValue( 50000 ); mPop.filterOnServerSizeSpin->setSuffix( i18n(" byte") ); - grid->addMultiCellWidget( hbox, 9, 9, 0, 1 ); + grid->addMultiCellWidget( hbox, 10, 10, 0, 1 ); connect( mPop.filterOnServerCheck, SIGNAL(toggled(bool)), - mPop.filterOnServerSizeSpin, SLOT(setEnabled(bool)) ); + mPop.filterOnServerSizeSpin, SLOT(setEnabled(bool)) ); QString msg = i18n("If you select this option, POP Filters will be used to " - "decide what to do with messages. You can then select " - "to download, delete or keep them on the server." ); + "decide what to do with messages. You can then select " + "to download, delete or keep them on the server." ); QWhatsThis::add( mPop.filterOnServerCheck, msg ); QWhatsThis::add( mPop.filterOnServerSizeSpin, msg ); mPop.intervalCheck = new QCheckBox( i18n("Enable &interval mail checking"), page1 ); - grid->addMultiCellWidget( mPop.intervalCheck, 10, 10, 0, 1 ); + grid->addMultiCellWidget( mPop.intervalCheck, 11, 11, 0, 1 ); connect( mPop.intervalCheck, SIGNAL(toggled(bool)), - this, SLOT(slotEnablePopInterval(bool)) ); + this, SLOT(slotEnablePopInterval(bool)) ); mPop.intervalLabel = new QLabel( i18n("Check inter&val:"), page1 ); - grid->addWidget( mPop.intervalLabel, 11, 0 ); + grid->addWidget( mPop.intervalLabel, 12, 0 ); mPop.intervalSpin = new KIntNumInput( page1 ); mPop.intervalSpin->setRange( 1, 10000, 1, FALSE ); mPop.intervalSpin->setSuffix( i18n(" min") ); mPop.intervalSpin->setValue( 1 ); mPop.intervalLabel->setBuddy( mPop.intervalSpin ); - grid->addWidget( mPop.intervalSpin, 11, 1 ); + grid->addWidget( mPop.intervalSpin, 12, 1 ); label = new QLabel( i18n("Des&tination folder:"), page1 ); grid->addWidget( label, 12, 0 ); mPop.folderCombo = new QComboBox( false, page1 ); label->setBuddy( mPop.folderCombo ); - grid->addWidget( mPop.folderCombo, 12, 1 ); + grid->addWidget( mPop.folderCombo, 13, 1 ); label = new QLabel( i18n("Precom&mand:"), page1 ); grid->addWidget( label, 13, 0 ); mPop.precommand = new QLineEdit( page1 ); label->setBuddy(mPop.precommand); - grid->addWidget( mPop.precommand, 13, 1 ); + grid->addWidget( mPop.precommand, 14, 1 ); QWidget *page2 = new QWidget( tabWidget ); tabWidget->addTab( page2, i18n("&Extras") ); @@ -819,7 +840,9 @@ mPop.portEdit->setText( QString("%1").arg( ap.port() ) ); mPop.usePipeliningCheck->setChecked( ap.usePipelining() ); mPop.storePasswordCheck->setChecked( ap.storePasswd() ); - mPop.deleteMailCheck->setChecked( !ap.leaveOnServer() ); + mPop.leaveMailCheck->setChecked( ap.leaveOnServer() ); + mPop.deleteAfterDaysCheck->setChecked( ap.deleteAfterDays() >= 0 ); + if (ap.deleteAfterDays() >= 0) mPop.deleteAfterDaysSpin->setValue( ap.deleteAfterDays() ); mPop.filterOnServerCheck->setChecked( ap.filterOnServer() ); mPop.filterOnServerSizeSpin->setValue( ap.filterOnServerCheckSize() ); mPop.intervalCheck->setChecked( interval >= 1 ); @@ -1115,7 +1138,8 @@ epa.setUsePipelining( mPop.usePipeliningCheck->isChecked() ); epa.setStorePasswd( mPop.storePasswordCheck->isChecked() ); epa.setPasswd( mPop.passwordEdit->text(), epa.storePasswd() ); - epa.setLeaveOnServer( !mPop.deleteMailCheck->isChecked() ); + epa.setLeaveOnServer( mPop.leaveMailCheck->isChecked() ); + if (mPop.deleteAfterDaysCheck->isChecked()) epa.setDeleteAfterDays( mPop.deleteAfterDaysSpin->value() ); epa.setFilterOnServer( mPop.filterOnServerCheck->isChecked() ); epa.setFilterOnServerCheckSize (mPop.filterOnServerSizeSpin->value() ); epa.setPrecommand( mPop.precommand->text() ); diff -u ../../kdenetwork-3.1-orig/kmail/accountdialog.h ./accountdialog.h --- ../../kdenetwork-3.1-orig/kmail/accountdialog.h 2002-12-05 21:49:11.000000000 +0100 +++ ./accountdialog.h 2003-06-29 20:00:48.000000000 +0200 @@ -101,7 +101,9 @@ QPushButton *checkCapabilities; QCheckBox *usePipeliningCheck; QCheckBox *storePasswordCheck; - QCheckBox *deleteMailCheck; + QCheckBox *leaveMailCheck; + QCheckBox *deleteAfterDaysCheck; + KIntNumInput *deleteAfterDaysSpin; QCheckBox *retriveAllCheck; QCheckBox *excludeCheck; QCheckBox *intervalCheck; diff -u ../../kdenetwork-3.1-orig/kmail/kmacctexppop.cpp ./kmacctexppop.cpp --- ../../kdenetwork-3.1-orig/kmail/kmacctexppop.cpp 2002-12-05 21:49:12.000000000 +0100 +++ ./kmacctexppop.cpp 2003-06-29 20:03:58.000000000 +0200 @@ -83,6 +83,7 @@ mStorePasswd = FALSE; mAskAgain = FALSE; mLeaveOnServer = FALSE; + mDeleteAfterDays = -1; mFilterOnServer = FALSE; //tz todo mFilterOnServerCheckSize = 50000; @@ -123,6 +124,7 @@ setStorePasswd(acct->storePasswd()); setPasswd(acct->passwd(), acct->storePasswd()); setLeaveOnServer(acct->leaveOnServer()); + setDeleteAfterDays(acct->deleteAfterDays()); setFilterOnServer(acct->filterOnServer()); setFilterOnServerCheckSize(acct->filterOnServerCheckSize()); setPrecommand(acct->precommand()); @@ -151,11 +153,13 @@ } QString seenUidList = locateLocal( "appdata", mLogin + ":" + "@" + mHost + - ":" + QString("%1").arg(mPort) ); + ":" + QString("%1").arg(mPort) ); KConfig config( seenUidList ); uidsOfSeenMsgs = config.readListEntry( "seenUidList" ); + timeOfSeenMsgs = config.readIntListEntry( "seenUidTimeList" ); headerLaterUids = config.readListEntry( "downloadLater" ); uidsOfNextSeenMsgs.clear(); + timeOfNextSeenMsgs.clear(); interactive = _interactive; mUidlFinished = FALSE; @@ -195,6 +199,7 @@ mPort = config.readNumEntry("port"); mProtocol = config.readNumEntry("protocol"); mLeaveOnServer = config.readNumEntry("leave-on-server", FALSE); + mDeleteAfterDays = config.readNumEntry("delete-after-days", -1); mFilterOnServer = config.readNumEntry("filter-on-server", FALSE); mFilterOnServerCheckSize = config.readUnsignedNumEntry("filter-os-check-size", 50000); } @@ -218,6 +223,7 @@ config.writeEntry("port", static_cast(mPort)); config.writeEntry("protocol", mProtocol); config.writeEntry("leave-on-server", mLeaveOnServer); + config.writeEntry("delete-after-days", mDeleteAfterDays); config.writeEntry("filter-on-server", mFilterOnServer); config.writeEntry("filter-os-check-size", mFilterOnServerCheckSize); } @@ -263,6 +269,13 @@ } +//----------------------------------------------------------------------------- +void KMAcctExpPop::setDeleteAfterDays(int n) +{ + mDeleteAfterDays = n; +} + + //--------------------------------------------------------------------------- void KMAcctExpPop::setFilterOnServer(bool b) { @@ -383,6 +396,7 @@ else { idsOfMsgsToDelete.append( *curId ); uidsOfNextSeenMsgs.append( *curUid ); + timeOfNextSeenMsgs.append( QDateTime::currentDateTime().toTime_t() ); } ++cur; ++curId; @@ -668,6 +682,7 @@ if (headersOnServer.current()->action() == Delete) { headerDeleteUids.append(headersOnServer.current()->uid()); uidsOfNextSeenMsgs.append(headersOnServer.current()->uid()); + timeOfNextSeenMsgs.append( QDateTime::currentDateTime().toTime_t() ); idsOfMsgsToDelete.append(headersOnServer.current()->id()); } else { @@ -704,7 +719,25 @@ kernel->folderMgr()->syncAllFolders(); KURL url = getUrl(); - if (mLeaveOnServer || idsOfMsgsToDelete.isEmpty()) { + if (mLeaveOnServer && mDeleteAfterDays >= 0 && !idsOfMsgsToDelete.isEmpty()) { + // Remove from idsOfMsgsToDelete entries which are newer than the limit + QDateTime timeLimit = QDateTime::currentDateTime(); + timeLimit.addDays( -mDeleteAfterDays ); + QStringList::Iterator cur = idsOfMsgsToDelete.begin(); + while (cur != idsOfMsgsToDelete.end()) { + QDateTime msgTime; + msgTime.setTime_t( timeOfNextSeenMsgs[uidsOfNextSeenMsgs.findIndex(*cur)] ); + + if (msgTime >= timeLimit) { + cur = idsOfMsgsToDelete.remove( cur ); + } + else { + ++cur; + } + } + } + + if ((mLeaveOnServer && mDeleteAfterDays < 0) || idsOfMsgsToDelete.isEmpty()) { url.setPath(QString("/commit")); job = KIO::get(url, false, false ); } @@ -774,9 +807,10 @@ // a new list from the server if (!mUidlFinished) return; QString seenUidList = locateLocal( "appdata", mLogin + ":" + "@" + mHost + - ":" + QString("%1").arg(mPort) ); + ":" + QString("%1").arg(mPort) ); KConfig config( seenUidList ); config.writeEntry( "seenUidList", uidsOfNextSeenMsgs ); + config.writeEntry( "seenUidTimeList", timeOfNextSeenMsgs ); config.writeEntry( "downloadLater", headerLaterUids ); config.sync(); } @@ -891,9 +925,10 @@ } else kdDebug(5006) << "KMAcctExpPop::slotData synchronization failure." << endl; - if (uidsOfSeenMsgs.contains( uid )) - idsOfMsgsToDelete.append( id ); + + idsOfMsgsToDelete.append( id ); uidsOfNextSeenMsgs.append( uid ); + timeOfNextSeenMsgs.append( timeOfSeenMsgs[uidsOfSeenMsgs.findIndex(uid)] ); } } } diff -u ../../kdenetwork-3.1-orig/kmail/kmacctexppop.h ./kmacctexppop.h --- ../../kdenetwork-3.1-orig/kmail/kmacctexppop.h 2002-12-05 21:49:12.000000000 +0100 +++ ./kmacctexppop.h 2003-06-29 13:32:43.000000000 +0200 @@ -110,6 +110,12 @@ virtual void setLeaveOnServer(bool); /** + * If value is positive, delete mail from server after that many days. + */ + int deleteAfterDays(void) const { return mDeleteAfterDays; } + virtual void setDeleteAfterDays(int); + + /** * Shall messages be filter on the server (TRUE) * or not (FALSE). */ @@ -170,6 +176,7 @@ bool mStorePasswd; bool mAskAgain; bool mLeaveOnServer; + int mDeleteAfterDays; bool gotMsgs; bool mFilterOnServer; unsigned int mFilterOnServerCheckSize; @@ -192,7 +199,9 @@ QValueList lensOfMsgs; QStringList uidsOfMsgs; QStringList uidsOfSeenMsgs; //UIDS of seen messages, saved in config + QValueList timeOfSeenMsgs; //UIDS of seen messages, saved in config QStringList uidsOfNextSeenMsgs; //UIDS of new seen messages, for writing in the config file + QValueList timeOfNextSeenMsgs; //UIDS of new seen messages, for writing in the config file QStringList idsOfMsgsToDelete; int indexOfCurrentMsg; --Boundary-00=_Oyy/+hc1+5BWvBw Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kde-pim mailing list kde-pim@mail.kde.org http://mail.kde.org/mailman/listinfo/kde-pim kde-pim home page at http://pim.kde.org/ --Boundary-00=_Oyy/+hc1+5BWvBw--