From 8d0663a2f8cf71382d6110d32bafc6fd6a34edac Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 16:06:16 +0000 Subject: [PATCH 01/10] Improve layout a bit svn path=/branches/kdepim/enterprise/kdepim/; revision=1048019 --- archivefolderdialog.cpp | 6 ++++-- importarchivedialog.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/archivefolderdialog.cpp b/archivefolderdialog.cpp index 24407bb4d..d0a3bc89f 100644 --- a/archivefolderdialog.cpp +++ b/archivefolderdialog.cpp @@ -57,8 +57,6 @@ ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent ) // TODO: Explaination label // TODO: Use QFormLayout in KDE4 - // TODO: sensible stretch factors - // TODO: sensible minimum horizontal size QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget ); mainLayout->addWidget( folderLabel, row, 0 ); @@ -97,7 +95,11 @@ ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent ) // TODO: Warn that user should do mail check for online IMAP and possibly cached IMAP as well + mainLayout->setColStretch( 1, 1 ); mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 ); + + // Make it a bit bigger, else the folder requester cuts off the text too early + resize( 500, minimumSize().height() ); } void ArchiveFolderDialog::setFolder( KMFolder *defaultFolder ) diff --git a/importarchivedialog.cpp b/importarchivedialog.cpp index e051dc859..b5aed7cc9 100644 --- a/importarchivedialog.cpp +++ b/importarchivedialog.cpp @@ -48,8 +48,6 @@ ImportArchiveDialog::ImportArchiveDialog( QWidget *parent ) // TODO: Explaination label // TODO: Use QFormLayout in KDE4 - // TODO: sensible stretch factors - // TODO: sensible minimum horizontal size QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget ); mainLayout->addWidget( folderLabel, row, 0 ); @@ -67,7 +65,11 @@ ImportArchiveDialog::ImportArchiveDialog( QWidget *parent ) // TODO: what's this, tooltips + mainLayout->setColStretch( 1, 1 ); mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 ); + + // Make it a bit bigger, else the folder requester cuts off the text too early + resize( 500, minimumSize().height() ); } void ImportArchiveDialog::setFolder( KMFolder *defaultFolder ) From 0da87307089a77157b43a5aa8b1982ef8cda56ef Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 16:11:42 +0000 Subject: [PATCH 02/10] Don't crash when there is no folder selected. svn path=/branches/kdepim/enterprise/kdepim/; revision=1048021 --- archivefolderdialog.cpp | 6 ++++++ importarchivedialog.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/archivefolderdialog.cpp b/archivefolderdialog.cpp index d0a3bc89f..d4652e504 100644 --- a/archivefolderdialog.cpp +++ b/archivefolderdialog.cpp @@ -119,6 +119,12 @@ void ArchiveFolderDialog::slotOk() } } + if ( !mFolderRequester->folder() ) { + KMessageBox::information( this, i18n( "Please select the folder that should be archived." ), + i18n( "No folder selected" ) ); + return; + } + // TODO: check if url is empty. or better yet, disable ok button until file is chosen KMail::BackupJob *backupJob = new KMail::BackupJob( mParentWidget ); backupJob->setRootFolder( mFolderRequester->folder() ); diff --git a/importarchivedialog.cpp b/importarchivedialog.cpp index b5aed7cc9..fc8745f45 100644 --- a/importarchivedialog.cpp +++ b/importarchivedialog.cpp @@ -85,6 +85,12 @@ void ImportArchiveDialog::slotOk() return; } + if ( !mFolderRequester->folder() ) { + KMessageBox::information( this, i18n( "Please select the folder where the archive should be imported to." ), + i18n( "No target folder selected" ) ); + return; + } + // TODO: check if url is empty. or better yet, disable ok button until file is chosen ImportJob *importJob = new KMail::ImportJob( mParentWidget ); From affdec3ec3536abe7dda5f1ffec00ea6a74b1bac Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 20:45:18 +0000 Subject: [PATCH 03/10] Connect the backupjob to the progress manager svn path=/branches/kdepim/enterprise/kdepim/; revision=1048166 --- archivefolderdialog.cpp | 2 ++ backupjob.cpp | 35 +++++++++++++++++++++++++++++++++++ backupjob.h | 7 +++++++ 3 files changed, 44 insertions(+) diff --git a/archivefolderdialog.cpp b/archivefolderdialog.cpp index d4652e504..86cc09141 100644 --- a/archivefolderdialog.cpp +++ b/archivefolderdialog.cpp @@ -117,6 +117,8 @@ void ArchiveFolderDialog::slotOk() KGuiItem( i18n( "Cancel" ) ) ) != KMessageBox::Yes ) { return; } + + // TODO: Check if overwriting actually works! } if ( !mFolderRequester->folder() ) { diff --git a/backupjob.cpp b/backupjob.cpp index b4741b98a..3d0689e33 100644 --- a/backupjob.cpp +++ b/backupjob.cpp @@ -23,6 +23,8 @@ #include "kmfoldercachedimap.h" #include "kmfolderdir.h" +#include "progressmanager.h" + #include "kzip.h" #include "ktar.h" #include "kmessagebox.h" @@ -42,6 +44,8 @@ BackupJob::BackupJob( QWidget *parent ) mCurrentFolderOpen( false ), mArchivedMessages( 0 ), mArchivedSize( 0 ), + mProgressItem( 0 ), + mAborted( false ), mCurrentFolder( 0 ), mCurrentMessage( 0 ), mCurrentJob( 0 ) @@ -107,9 +111,19 @@ bool BackupJob::hasChildren( KMFolder *folder ) const return false; } +void BackupJob::cancelJob() +{ + abort( i18n( "The operation was cancelled by the user." ) ); +} void BackupJob::abort( const QString &errorMessage ) { + // We could be called this twice, since killing the current job below will cause the job to fail, + // and that will call abort() + if ( mAborted ) + return; + + mAborted = true; if ( mCurrentFolderOpen && mCurrentFolder ) { mCurrentFolder->close( "BackupJob" ); mCurrentFolder = 0; @@ -121,6 +135,11 @@ void BackupJob::abort( const QString &errorMessage ) mCurrentJob->kill(); mCurrentJob = 0; } + if ( mProgressItem ) { + mProgressItem->setComplete(); + mProgressItem = 0; + // The progressmanager will delete it + } QString text = i18n( "Failed to archive the folder '%1'." ).arg( mRootFolder->name() ); text += "\n" + errorMessage; @@ -139,6 +158,10 @@ void BackupJob::finish() } } + mProgressItem->setStatus( i18n( "Archiving finished" ) ); + mProgressItem->setComplete(); + mProgressItem = 0; + QFileInfo archiveFileInfo( mMailArchivePath.path() ); QString text = i18n( "Archiving folder '%1' successfully completed. " "The archive was written to the file '%2'." ) @@ -206,6 +229,8 @@ void BackupJob::archiveNextMessage() abort( i18n( "Internal error while trying to retrieve a message from folder '%1'." ) .arg( mCurrentFolder->name() ) ); } + + mProgressItem->setProgress( ( mProgressItem->progress() + 5 ) ); } static int fileInfoToUnixPermissions( const QFileInfo &fileInfo ) @@ -327,6 +352,7 @@ void BackupJob::archiveNextFolder() mCurrentFolder = mPendingFolders.take( 0 ); kdDebug(5006) << "===> Archiving next folder: " << mCurrentFolder->name() << endl; + mProgressItem->setStatus( i18n( "Archiving folder %1" ).arg( mCurrentFolder->name() ) ); if ( mCurrentFolder->open( "BackupJob" ) != 0 ) { abort( i18n( "Unable to open folder '%1'.").arg( mCurrentFolder->name() ) ); return; @@ -418,6 +444,15 @@ void BackupJob::start() return; } + mProgressItem = KPIM::ProgressManager::createProgressItem( + "BackupJob", + i18n( "Archiving" ), + QString(), + true ); + mProgressItem->setUsesBusyIndicator( true ); + connect( mProgressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)), + this, SLOT(cancelJob()) ); + archiveNextFolder(); } diff --git a/backupjob.h b/backupjob.h index 82b255244..2b9215281 100644 --- a/backupjob.h +++ b/backupjob.h @@ -30,6 +30,10 @@ class KArchive; class KProcess; class QWidget; +namespace KPIM { + class ProgressItem; +} + namespace KMail { class FolderJob; @@ -62,6 +66,7 @@ class BackupJob : public QObject void messageRetrieved( KMMessage *message ); void folderJobFinished( KMail::FolderJob *job ); void processCurrentMessage(); + void cancelJob(); private: @@ -82,6 +87,8 @@ class BackupJob : public QObject bool mCurrentFolderOpen; int mArchivedMessages; uint mArchivedSize; + KPIM::ProgressItem *mProgressItem; + bool mAborted; QPtrList mPendingFolders; KMFolder *mCurrentFolder; From f9b1a77d18b1115766845c9646cfe1fdaa66bb17 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 21:02:02 +0000 Subject: [PATCH 04/10] Hook up the importjob into the progessmanager as well. Add some saftey checks to the backup job to prevent crashes when the job was aborted. svn path=/branches/kdepim/enterprise/kdepim/; revision=1048176 --- backupjob.cpp | 12 ++++++++++++ importjob.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- importjob.h | 9 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/backupjob.cpp b/backupjob.cpp index 3d0689e33..9a997f067 100644 --- a/backupjob.cpp +++ b/backupjob.cpp @@ -176,6 +176,9 @@ void BackupJob::finish() void BackupJob::archiveNextMessage() { + if ( mAborted ) + return; + mCurrentMessage = 0; if ( mPendingMessages.isEmpty() ) { kdDebug(5006) << "===> All messages done in folder " << mCurrentFolder->name() << endl; @@ -250,6 +253,9 @@ static int fileInfoToUnixPermissions( const QFileInfo &fileInfo ) void BackupJob::processCurrentMessage() { + if ( mAborted ) + return; + if ( mCurrentMessage ) { kdDebug(5006) << "Processing message with subject " << mCurrentMessage->subject() << endl; const DwString &messageDWString = mCurrentMessage->asDwString(); @@ -316,6 +322,9 @@ void BackupJob::messageRetrieved( KMMessage *message ) void BackupJob::folderJobFinished( KMail::FolderJob *job ) { + if ( mAborted ) + return; + // The job might finish after it has emitted messageRetrieved(), in which case we have already // started a new job. Don't set the current job to 0 in that case. if ( job == mCurrentJob ) { @@ -345,6 +354,9 @@ bool BackupJob::writeDirHelper( const QString &directoryPath, const QString &per void BackupJob::archiveNextFolder() { + if ( mAborted ) + return; + if ( mPendingFolders.isEmpty() ) { finish(); return; diff --git a/importjob.cpp b/importjob.cpp index d4b6a759c..49b22e3b9 100644 --- a/importjob.cpp +++ b/importjob.cpp @@ -21,6 +21,8 @@ #include "kmfolder.h" #include "folderutil.h" +#include "progressmanager.h" + #include #include #include @@ -40,7 +42,9 @@ ImportJob::ImportJob( QWidget *parentWidget ) mRootFolder( 0 ), mParentWidget( parentWidget ), mNumberOfImportedMessages( 0 ), - mCurrentFolder( 0 ) + mCurrentFolder( 0 ), + mProgressItem( 0 ), + mAborted( false ) { } @@ -66,6 +70,8 @@ void ImportJob::setRootFolder( KMFolder *rootFolder ) void ImportJob::finish() { kdDebug(5006) << "Finished import job." << endl; + mProgressItem->setComplete(); + mProgressItem = 0; QString text = i18n( "Importing the archive file '%1' into the folder '%2' succeeded." ) .arg( mArchiveFile.path() ).arg( mRootFolder->name() ); text += "\n" + i18n( "%1 messages were imported." ).arg( mNumberOfImportedMessages ); @@ -73,10 +79,24 @@ void ImportJob::finish() deleteLater(); } +void ImportJob::cancelJob() +{ + abort( i18n( "The operation was cancelled by the user." ) ); +} + void ImportJob::abort( const QString &errorMessage ) { + if ( mAborted ) + return; + + mAborted = true; QString text = i18n( "Failed to import the archive into folder '%1'." ).arg( mRootFolder->name() ); text += "\n" + errorMessage; + if ( mProgressItem ) { + mProgressItem->setComplete(); + mProgressItem = 0; + // The progressmanager will delete it + } KMessageBox::sorry( mParentWidget, text, i18n( "Importing archive failed." ) ); deleteLater(); } @@ -134,6 +154,9 @@ void ImportJob::enqueueMessages( const KArchiveDirectory *dir, KMFolder *folder void ImportJob::importNextMessage() { + if ( mAborted ) + return; + if ( mQueuedMessages.isEmpty() ) { kdDebug(5006) << "importNextMessage(): Processed all messages in the queue." << endl; if ( mCurrentFolder ) { @@ -163,7 +186,11 @@ void ImportJob::importNextMessage() return; } kdDebug(5006) << "importNextMessage(): Current folder of queue is now: " << mCurrentFolder->name() << endl; + mProgressItem->setStatus( i18n( "Importing folder %1" ).arg( mCurrentFolder->name() ) ); } + + mProgressItem->setProgress( ( mProgressItem->progress() + 5 ) ); + const KArchiveFile *file = messages.files.first(); Q_ASSERT( file ); messages.files.removeFirst(); @@ -201,6 +228,9 @@ void ImportJob::importNextMessage() void ImportJob::importNextDirectory() { + if ( mAborted ) + return; + if ( mQueuedDirectories.isEmpty() ) { finish(); return; @@ -269,6 +299,15 @@ void ImportJob::start() return; } + mProgressItem = KPIM::ProgressManager::createProgressItem( + "ImportJob", + i18n( "Importing Archive" ), + QString(), + true ); + mProgressItem->setUsesBusyIndicator( true ); + connect( mProgressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem*)), + this, SLOT(cancelJob()) ); + Folder nextFolder; nextFolder.archiveDir = mArchive->directory(); nextFolder.parent = mRootFolder; diff --git a/importjob.h b/importjob.h index 8e24fb3c2..345a3c80e 100644 --- a/importjob.h +++ b/importjob.h @@ -33,6 +33,11 @@ class KArchiveDirectory; class KArchiveFile; class KMFolder; +namespace KPIM +{ + class ProgressItem; +} + namespace KMail { @@ -57,6 +62,7 @@ class ImportJob : public QObject private slots: void importNextMessage(); + void cancelJob(); private: @@ -98,6 +104,9 @@ class ImportJob : public QObject // The folder to which we are currently importing messages KMFolder *mCurrentFolder; + + KPIM::ProgressItem *mProgressItem; + bool mAborted; }; } From f5d7204c1c257fa5bb4124d33ce189c44eb6cfab Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 21:02:50 +0000 Subject: [PATCH 05/10] Fix copy and paste typo svn path=/branches/kdepim/enterprise/kdepim/; revision=1048177 --- importarchivedialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/importarchivedialog.cpp b/importarchivedialog.cpp index fc8745f45..efcdad73e 100644 --- a/importarchivedialog.cpp +++ b/importarchivedialog.cpp @@ -33,7 +33,7 @@ using namespace KMail; ImportArchiveDialog::ImportArchiveDialog( QWidget *parent ) - : KDialogBase( parent, "archive_folder_dialog", false, i18n( "Archive Folder" ), + : KDialogBase( parent, "import_archive_dialog", false, i18n( "Import Archive" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true ), mParentWidget( parent ) From b0c4245747ca91d8b2608b9b8b5af99e074c7977 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 21:36:38 +0000 Subject: [PATCH 06/10] Correctly import archives which have empty folders with subfolders. svn path=/branches/kdepim/enterprise/kdepim/; revision=1048190 --- importjob.cpp | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/importjob.cpp b/importjob.cpp index 49b22e3b9..f3e0f11b3 100644 --- a/importjob.cpp +++ b/importjob.cpp @@ -20,6 +20,7 @@ #include "kmfolder.h" #include "folderutil.h" +#include "kmfolderdir.h" #include "progressmanager.h" @@ -226,6 +227,21 @@ void ImportJob::importNextMessage() QTimer::singleShot( 0, this, SLOT( importNextMessage() ) ); } +// Input: .inbox.directory +// Output: inbox +// Can also return an empty string if this is no valid dir name +static QString folderNameForDirectoryName( const QString &dirName ) +{ + Q_ASSERT( dirName.startsWith( "." ) ); + const QString end = ".directory"; + const int expectedIndex = dirName.length() - end.length(); + if ( dirName.lower().find( end ) != expectedIndex ) + return QString(); + QString returnName = dirName.left( dirName.length() - end.length() ); + returnName = returnName.right( returnName.length() - 1 ); + return returnName; +} + void ImportJob::importNextDirectory() { if ( mAborted ) @@ -256,18 +272,33 @@ void ImportJob::importNextDirectory() return; enqueueMessages( dir, subFolder ); + } + + // Entry starts with a dot, so we assume it is a subdirectory + else { - const QString dirName = "." + entries[i] + ".directory"; - QStringList::iterator it = entries.find( dirName ); - if ( it != entries.end() ) { - Q_ASSERT( folder.archiveDir->entry( *it )->isDirectory() ); - Q_ASSERT( folder.archiveDir->entry( *it )->name() == dirName ); - Folder newFolder; - newFolder.archiveDir = static_cast( folder.archiveDir->entry( *it ) ); - newFolder.parent = subFolder; - kdDebug(5006) << "Enqueueing directory " << newFolder.archiveDir->name() << endl; - mQueuedDirectories.push_back( newFolder ); + // Check if the subfolder already exists or create it + KMFolder *subFolder = 0; + const QString folderName = folderNameForDirectoryName( entry->name() ); + if ( folderName.isEmpty() ) { + abort( i18n( "Unexpected subdirectory named '%1'." ).arg( entry->name() ) ); + return; + } + if ( currentFolder->child() ) { + subFolder = dynamic_cast( currentFolder->child()->hasNamedFolder( folderName ) ); } + if ( !subFolder ) { + kdDebug(5006) << "Creating subfolder for directory " << entry->name() << endl; + subFolder = createSubFolder( currentFolder, folderName, entry->permissions() ); + if ( !subFolder ) + return; + } + + Folder newFolder; + newFolder.archiveDir = dir; + newFolder.parent = subFolder; + kdDebug(5006) << "Enqueueing directory " << entry->name() << endl; + mQueuedDirectories.push_back( newFolder ); } } } From 79648c50677bd04f15b505287bb4960e4da949ab Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 21:49:05 +0000 Subject: [PATCH 07/10] Factor out folder deletion into its own function svn path=/branches/kdepim/enterprise/kdepim/; revision=1048194 --- archivefolderdialog.cpp | 1 + folderutil.cpp | 34 +++++++++++++++++++++++++++++++++- folderutil.h | 11 +++++++++++ importarchivedialog.cpp | 1 + kmmainwidget.cpp | 28 ++-------------------------- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/archivefolderdialog.cpp b/archivefolderdialog.cpp index 86cc09141..3136c5268 100644 --- a/archivefolderdialog.cpp +++ b/archivefolderdialog.cpp @@ -55,6 +55,7 @@ ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent ) int row = 0; + // TODO: better label for "Ok" button // TODO: Explaination label // TODO: Use QFormLayout in KDE4 diff --git a/folderutil.cpp b/folderutil.cpp index 31e0662d3..2dbac6fba 100644 --- a/folderutil.cpp +++ b/folderutil.cpp @@ -23,6 +23,8 @@ #include "kmfoldercachedimap.h" #include "kmfoldermgr.h" +#include + using namespace KMail; using namespace FolderUtil; @@ -78,4 +80,34 @@ KMFolder *KMail::FolderUtil::createSubFolder( KMFolder *parentFolder, KMFolderDi } return newFolder; -} \ No newline at end of file +} + +void KMail::FolderUtil::deleteFolder( KMFolder *folderToDelete, QWidget *parent ) +{ + if ( folderToDelete->hasAccounts() ) { + // this folder has an account, so we need to change that to the inbox + for ( AccountList::Iterator it (folderToDelete->acctList()->begin() ), + end( folderToDelete->acctList()->end() ); it != end; ++it ) { + (*it)->setFolder( kmkernel->inboxFolder() ); + KMessageBox::information(parent, + i18n("The folder you deleted was associated with the account " + "%1 which delivered mail into it. The folder the account " + "delivers new mail into was reset to the main Inbox folder.").arg( (*it)->name())); + } + } + if (folderToDelete->folderType() == KMFolderTypeImap) + kmkernel->imapFolderMgr()->remove(folderToDelete); + else if (folderToDelete->folderType() == KMFolderTypeCachedImap) { + // Deleted by user -> tell the account (see KMFolderCachedImap::listDirectory2) + KMFolderCachedImap* storage = static_cast( folderToDelete->storage() ); + KMAcctCachedImap* acct = storage->account(); + if ( acct ) + acct->addDeletedFolder( folderToDelete ); + + kmkernel->dimapFolderMgr()->remove(folderToDelete); + } + else if (folderToDelete->folderType() == KMFolderTypeSearch) + kmkernel->searchFolderMgr()->remove(folderToDelete); + else + kmkernel->folderMgr()->remove(folderToDelete); +} diff --git a/folderutil.h b/folderutil.h index 82aa3afd2..88a9c51c5 100644 --- a/folderutil.h +++ b/folderutil.h @@ -24,6 +24,7 @@ class KMFolder; class KMFolderDir; class QString; +class QWidget; namespace KMail { @@ -47,6 +48,16 @@ KMFolder *createSubFolder( KMFolder *parentFolder, KMFolderDir *parentDir, const QString &folderName, const QString &namespaceName, KMFolderType localFolderType ); +/** + * Deletes a folder and all its subfolders. + * Handles all types of folders correctly, as well as folders with accounts + * + * @param folderToDelete the folder which is going to be deleted + * @param parent the parent widget, which is used when displaying a messagebox, + * which happens when removing a folder with an associated account + */ +void deleteFolder( KMFolder *folderToDelete, QWidget *parent ); + } } diff --git a/importarchivedialog.cpp b/importarchivedialog.cpp index efcdad73e..be1c92858 100644 --- a/importarchivedialog.cpp +++ b/importarchivedialog.cpp @@ -48,6 +48,7 @@ ImportArchiveDialog::ImportArchiveDialog( QWidget *parent ) // TODO: Explaination label // TODO: Use QFormLayout in KDE4 + // TODO: better label for "Ok" button QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget ); mainLayout->addWidget( folderLabel, row, 0 ); diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index adba5ddfd..026778142 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -101,6 +101,7 @@ using KMail::HeaderListQuickSearch; #include "templateparser.h" #include "archivefolderdialog.h" #include "importarchivedialog.h" +#include "folderutil.h" #if !defined(NDEBUG) #include "sievedebugdialog.h" @@ -1249,32 +1250,7 @@ void KMMainWidget::slotRemoveFolder() KGuiItem( i18n("&Delete"), "editdelete")) == KMessageBox::Continue) { - if ( mFolder->hasAccounts() ) { - // this folder has an account, so we need to change that to the inbox - for ( AccountList::Iterator it (mFolder->acctList()->begin() ), - end( mFolder->acctList()->end() ); it != end; ++it ) { - (*it)->setFolder( kmkernel->inboxFolder() ); - KMessageBox::information(this, - i18n("The folder you deleted was associated with the account " - "%1 which delivered mail into it. The folder the account " - "delivers new mail into was reset to the main Inbox folder.").arg( (*it)->name())); - } - } - if (mFolder->folderType() == KMFolderTypeImap) - kmkernel->imapFolderMgr()->remove(mFolder); - else if (mFolder->folderType() == KMFolderTypeCachedImap) { - // Deleted by user -> tell the account (see KMFolderCachedImap::listDirectory2) - KMFolderCachedImap* storage = static_cast( mFolder->storage() ); - KMAcctCachedImap* acct = storage->account(); - if ( acct ) - acct->addDeletedFolder( mFolder ); - - kmkernel->dimapFolderMgr()->remove(mFolder); - } - else if (mFolder->folderType() == KMFolderTypeSearch) - kmkernel->searchFolderMgr()->remove(mFolder); - else - kmkernel->folderMgr()->remove(mFolder); + KMail::FolderUtil::deleteFolder( mFolder, this ); } } From 6aa03c6306a9b597738f627e25ee066e66dc7ec4 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 22:07:18 +0000 Subject: [PATCH 08/10] Add the ability to delete the folders that were archived. Use with care! svn path=/branches/kdepim/enterprise/kdepim/; revision=1048205 --- archivefolderdialog.cpp | 7 ++++++- archivefolderdialog.h | 2 ++ backupjob.cpp | 16 ++++++++++++++++ backupjob.h | 2 ++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/archivefolderdialog.cpp b/archivefolderdialog.cpp index 3136c5268..671fe746b 100644 --- a/archivefolderdialog.cpp +++ b/archivefolderdialog.cpp @@ -30,6 +30,7 @@ #include #include +#include #include using namespace KMail; @@ -90,7 +91,10 @@ ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent ) mainLayout->addWidget( mUrlRequester, row, 1 ); row++; - // TODO: checkbox "delete after success" + // TODO: Make this appear more dangerous! + mDeleteCheckBox = new QCheckBox( i18n( "Delete folders after completion" ), mainWidget ); + mainLayout->addMultiCellWidget( mDeleteCheckBox, row, row, 0, 1, Qt::AlignLeft ); + row++; // TODO: what's this, tooltips @@ -133,6 +137,7 @@ void ArchiveFolderDialog::slotOk() backupJob->setRootFolder( mFolderRequester->folder() ); backupJob->setSaveLocation( mUrlRequester->url() ); backupJob->setArchiveType( static_cast( mFormatComboBox->currentItem() ) ); + backupJob->setDeleteFoldersAfterCompletion( mDeleteCheckBox->isChecked() ); backupJob->start(); accept(); } diff --git a/archivefolderdialog.h b/archivefolderdialog.h index 6701d9906..70a6cd624 100644 --- a/archivefolderdialog.h +++ b/archivefolderdialog.h @@ -21,6 +21,7 @@ #include +class QCheckBox; class KURLRequester; class KComboBox; class KMFolder; @@ -48,6 +49,7 @@ class ArchiveFolderDialog : public KDialogBase private: QWidget *mParentWidget; + QCheckBox *mDeleteCheckBox; FolderRequester *mFolderRequester; KComboBox *mFormatComboBox; KURLRequester *mUrlRequester; diff --git a/backupjob.cpp b/backupjob.cpp index 9a997f067..e6dc02821 100644 --- a/backupjob.cpp +++ b/backupjob.cpp @@ -22,6 +22,7 @@ #include "kmfolder.h" #include "kmfoldercachedimap.h" #include "kmfolderdir.h" +#include "folderutil.h" #include "progressmanager.h" @@ -46,6 +47,7 @@ BackupJob::BackupJob( QWidget *parent ) mArchivedSize( 0 ), mProgressItem( 0 ), mAborted( false ), + mDeleteFoldersAfterCompletion( false ), mCurrentFolder( 0 ), mCurrentMessage( 0 ), mCurrentJob( 0 ) @@ -76,6 +78,11 @@ void BackupJob::setArchiveType( ArchiveType type ) mArchiveType = type; } +void BackupJob::setDeleteFoldersAfterCompletion( bool deleteThem ) +{ + mDeleteFoldersAfterCompletion = deleteThem; +} + QString BackupJob::stripRootPath( const QString &path ) const { QString ret = path; @@ -171,6 +178,15 @@ void BackupJob::finish() text += "\n" + i18n( "The archive file has a size of %1." ) .arg( KIO::convertSize( archiveFileInfo.size() ) ); KMessageBox::information( mParentWidget, text, i18n( "Archiving finished." ) ); + + if ( mDeleteFoldersAfterCompletion ) { + // Some saftey checks first... + if ( archiveFileInfo.size() > 0 && mArchivedMessages > 0 && mArchivedSize > 0 ) { + // Sorry for any data loss! + FolderUtil::deleteFolder( mRootFolder, mParentWidget ); + } + } + deleteLater(); } diff --git a/backupjob.h b/backupjob.h index 2b9215281..cd5341fc9 100644 --- a/backupjob.h +++ b/backupjob.h @@ -59,6 +59,7 @@ class BackupJob : public QObject void setRootFolder( KMFolder *rootFolder ); void setSaveLocation( const KURL &savePath ); void setArchiveType( ArchiveType type ); + void setDeleteFoldersAfterCompletion( bool deleteThem ); void start(); private slots: @@ -89,6 +90,7 @@ class BackupJob : public QObject uint mArchivedSize; KPIM::ProgressItem *mProgressItem; bool mAborted; + bool mDeleteFoldersAfterCompletion; QPtrList mPendingFolders; KMFolder *mCurrentFolder; From 282ca92991531e811b8bc971c7b6f84e106c6fa4 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 22:18:23 +0000 Subject: [PATCH 09/10] Fix bug that importing created a folder twice in some circumstances. svn path=/branches/kdepim/enterprise/kdepim/; revision=1048210 --- importjob.cpp | 38 +++++++++++++++++++++----------------- importjob.h | 2 ++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/importjob.cpp b/importjob.cpp index f3e0f11b3..20bbf1cf1 100644 --- a/importjob.cpp +++ b/importjob.cpp @@ -104,11 +104,6 @@ void ImportJob::abort( const QString &errorMessage ) KMFolder * ImportJob::createSubFolder( KMFolder *parent, const QString &folderName, mode_t permissions ) { - if ( !parent->createChildFolder() ) { - abort( i18n( "Unable to create subfolder for folder '%1'." ).arg( parent->name() ) ); - return 0; - } - KMFolder *newFolder = FolderUtil::createSubFolder( parent, parent->child(), folderName, QString(), KMFolderTypeMaildir ); if ( !newFolder ) { @@ -242,6 +237,23 @@ static QString folderNameForDirectoryName( const QString &dirName ) return returnName; } +KMFolder* ImportJob::getOrCreateSubFolder( KMFolder *parentFolder, const QString &subFolderName, + mode_t subFolderPermissions ) +{ + if ( !parentFolder->createChildFolder() ) { + abort( i18n( "Unable to create subfolder for folder '%1'." ).arg( parentFolder->name() ) ); + return 0; + } + + KMFolder *subFolder = 0; + subFolder = dynamic_cast( parentFolder->child()->hasNamedFolder( subFolderName ) ); + + if ( !subFolder ) { + subFolder = createSubFolder( parentFolder, subFolderName, subFolderPermissions ); + } + return subFolder; +} + void ImportJob::importNextDirectory() { if ( mAborted ) @@ -267,7 +279,7 @@ void ImportJob::importNextDirectory() if ( !dir->name().startsWith( "." ) ) { kdDebug(5006) << "Queueing messages in folder " << entry->name() << endl; - KMFolder *subFolder = createSubFolder( currentFolder, entry->name(), entry->permissions() ); + KMFolder *subFolder = getOrCreateSubFolder( currentFolder, entry->name(), entry->permissions() ); if ( !subFolder ) return; @@ -277,22 +289,14 @@ void ImportJob::importNextDirectory() // Entry starts with a dot, so we assume it is a subdirectory else { - // Check if the subfolder already exists or create it - KMFolder *subFolder = 0; const QString folderName = folderNameForDirectoryName( entry->name() ); if ( folderName.isEmpty() ) { abort( i18n( "Unexpected subdirectory named '%1'." ).arg( entry->name() ) ); return; } - if ( currentFolder->child() ) { - subFolder = dynamic_cast( currentFolder->child()->hasNamedFolder( folderName ) ); - } - if ( !subFolder ) { - kdDebug(5006) << "Creating subfolder for directory " << entry->name() << endl; - subFolder = createSubFolder( currentFolder, folderName, entry->permissions() ); - if ( !subFolder ) - return; - } + KMFolder *subFolder = getOrCreateSubFolder( currentFolder, folderName, entry->permissions() ); + if ( !subFolder ) + return; Folder newFolder; newFolder.archiveDir = dir; diff --git a/importjob.h b/importjob.h index 345a3c80e..57e0a8fd4 100644 --- a/importjob.h +++ b/importjob.h @@ -83,6 +83,8 @@ class ImportJob : public QObject void queueFolders(); void importNextDirectory(); KMFolder* createSubFolder( KMFolder *parent, const QString &folderName, mode_t permissions ); + KMFolder* getOrCreateSubFolder( KMFolder *parentFolder, const QString &subFolderName, + mode_t subFolderPermissions ); void enqueueMessages( const KArchiveDirectory *dir, KMFolder *folder ); KArchive *mArchive; From 483b173841a1239eb591e6146490a45855d06980 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Thu, 12 Nov 2009 23:53:54 +0000 Subject: [PATCH 10/10] Remove the import archive action from the main menu, let KMailCVT do that instead, by calling a DCOP method. svn path=/branches/kdepim/enterprise/kdepim/; revision=1048250 --- importarchivedialog.cpp | 3 ++- importarchivedialog.h | 2 +- kmailIface.h | 1 + kmail_part.rc | 1 - kmkernel.cpp | 9 +++++++++ kmkernel.h | 1 + kmmainwidget.cpp | 14 -------------- kmmainwidget.h | 3 +-- kmmainwin.rc | 1 - 9 files changed, 15 insertions(+), 20 deletions(-) diff --git a/importarchivedialog.cpp b/importarchivedialog.cpp index be1c92858..a1e1302c4 100644 --- a/importarchivedialog.cpp +++ b/importarchivedialog.cpp @@ -32,12 +32,13 @@ using namespace KMail; -ImportArchiveDialog::ImportArchiveDialog( QWidget *parent ) +ImportArchiveDialog::ImportArchiveDialog( QWidget *parent, Qt::WidgetFlags flags ) : KDialogBase( parent, "import_archive_dialog", false, i18n( "Import Archive" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true ), mParentWidget( parent ) { + setWFlags( flags ); QWidget *mainWidget = new QWidget( this ); QGridLayout *mainLayout = new QGridLayout( mainWidget ); mainLayout->setSpacing( KDialog::spacingHint() ); diff --git a/importarchivedialog.h b/importarchivedialog.h index 7d707d7b9..86f79e402 100644 --- a/importarchivedialog.h +++ b/importarchivedialog.h @@ -35,7 +35,7 @@ class ImportArchiveDialog : public KDialogBase public: - ImportArchiveDialog( QWidget *parent = 0 ); + ImportArchiveDialog( QWidget *parent, Qt::WidgetFlags flags ); void setFolder( KMFolder *defaultFolder ); protected slots: diff --git a/kmailIface.h b/kmailIface.h index fd76d1af2..01cf8bdb5 100644 --- a/kmailIface.h +++ b/kmailIface.h @@ -115,6 +115,7 @@ k_dcop: virtual int dcopAddMessage(const QString & foldername, const KURL & messagefile, const QString & MsgStatusFlags = QString()) = 0; + virtual void showImportArchiveDialog() = 0; virtual QStringList folderList() const =0; virtual DCOPRef getFolder( const QString& vpath ) =0; diff --git a/kmail_part.rc b/kmail_part.rc index aeefb2629..fb4794dfd 100644 --- a/kmail_part.rc +++ b/kmail_part.rc @@ -19,7 +19,6 @@ - diff --git a/kmkernel.cpp b/kmkernel.cpp index 0540294bb..8704c5b4a 100644 --- a/kmkernel.cpp +++ b/kmkernel.cpp @@ -44,6 +44,7 @@ using KRecentAddress::RecentAddresses; #include "kmcommands.h" #include "kmsystemtray.h" #include "transportmanager.h" +#include "importarchivedialog.h" #include #include "kmailicalifaceimpl.h" @@ -1085,6 +1086,14 @@ int KMKernel::dcopAddMessage_fastImport( const QString & foldername, return retval; } +void KMKernel::showImportArchiveDialog() +{ + KMMainWidget *mainWidget = getKMMainWidget(); + KMail::ImportArchiveDialog *importDialog = new KMail::ImportArchiveDialog( mainWidget, WDestructiveClose ); + importDialog->setFolder( mainWidget->folderTree()->currentFolder() ); + importDialog->show(); +} + QStringList KMKernel::folderList() const { QStringList folders; diff --git a/kmkernel.h b/kmkernel.h index 08b6ea160..7fc2aeee8 100644 --- a/kmkernel.h +++ b/kmkernel.h @@ -196,6 +196,7 @@ public: const QString & MsgStatusFlags = QString()); int dcopAddMessage_fastImport(const QString & foldername, const KURL & messagefile, const QString & MsgStatusFlags = QString()); + void showImportArchiveDialog(); QStringList folderList() const; DCOPRef getFolder( const QString& vpath ); diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index 026778142..b9c896a8f 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -100,7 +100,6 @@ using KMail::HeaderListQuickSearch; #include "mailinglistpropertiesdialog.h" #include "templateparser.h" #include "archivefolderdialog.h" -#include "importarchivedialog.h" #include "folderutil.h" #if !defined(NDEBUG) @@ -146,7 +145,6 @@ KMMainWidget::KMMainWidget(QWidget *parent, const char *name, mFolderViewSplitter( 0 ), mQuickSearchLine( 0 ), mArchiveFolderAction( 0 ), - mImportArchiveAction( 0 ), mShowBusySplashTimer( 0 ), mShowingOfflineScreen( false ), mMsgActions( 0 ), @@ -1180,14 +1178,6 @@ void KMMainWidget::slotEmptyFolder() mEmptyFolderAction->setEnabled( false ); } -//----------------------------------------------------------------------------- -void KMMainWidget::slotImportArchive() -{ - KMail::ImportArchiveDialog importDialog; - importDialog.setFolder( mFolder ); - importDialog.exec(); -} - //----------------------------------------------------------------------------- void KMMainWidget::slotArchiveFolder() { @@ -2798,10 +2788,6 @@ void KMMainWidget::setupActions() SLOT( slotArchiveFolder() ), actionCollection(), "archive_folder" ); - mImportArchiveAction = new KAction( i18n( "Import Archive..." ), "fileload", 0, this, - SLOT( slotImportArchive() ), actionCollection(), - "import_archive" ); - mPreferHtmlAction = new KToggleAction( i18n("Prefer &HTML to Plain Text"), 0, this, SLOT(slotOverrideHtml()), actionCollection(), "prefer_html" ); diff --git a/kmmainwidget.h b/kmmainwidget.h index a92f53b91..911446b94 100644 --- a/kmmainwidget.h +++ b/kmmainwidget.h @@ -284,7 +284,6 @@ protected slots: void slotInvalidateIMAPFolders(); void slotMarkAllAsRead(); void slotArchiveFolder(); - void slotImportArchive(); void slotRemoveFolder(); void slotEmptyFolder(); void slotCompactFolder(); @@ -534,7 +533,7 @@ private: *mCompactFolderAction, *mRefreshFolderAction, *mEmptyFolderAction, *mMarkAllAsReadAction, *mFolderMailingListPropertiesAction, *mFolderShortCutCommandAction, *mTroubleshootFolderAction, - *mRemoveDuplicatesAction, *mArchiveFolderAction, *mImportArchiveAction; + *mRemoveDuplicatesAction, *mArchiveFolderAction; KToggleAction *mPreferHtmlAction, *mPreferHtmlLoadExtAction, *mThreadMessagesAction; KToggleAction *mThreadBySubjectAction; KToggleAction *mFolderAction, *mHeaderAction, *mMimeAction; diff --git a/kmmainwin.rc b/kmmainwin.rc index 32e1961b5..955dabad2 100644 --- a/kmmainwin.rc +++ b/kmmainwin.rc @@ -22,7 +22,6 @@ -