Update of /cvsroot/mahogany/M/src/modules
In directory usw-pr-cvs1:/tmp/cvs-serv19001/src/modules
Modified Files:
Migrate.cpp
Log Message:
migration to local files seems to work
Index: Migrate.cpp
===================================================================
RCS file: /cvsroot/mahogany/M/src/modules/Migrate.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -b -u -2 -r1.6 -r1.7
--- Migrate.cpp 13 Oct 2002 22:36:49 -0000 1.6
+++ Migrate.cpp 14 Oct 2002 21:52:36 -0000 1.7
@@ -103,4 +103,10 @@
// the format of the folders to create
FileMailboxFormat format;
+
+ MigrateLocal()
+ {
+ // use MBOX by default
+ format = FileMbox_MBOX;
+ }
};
@@ -117,4 +123,7 @@
bool toIMAP;
+ // the delimiter of the folder names (NUL initially meaning "unknown")
+ char delimiterDst;
+
// the destination server
MigrateImapServer dstIMAP;
@@ -136,6 +145,32 @@
toIMAP = true;
+ delimiterDst = '\0';
+
countFolders = -1;
}
+
+ // add a new folder to folderNames/folderFlags arrays
+ void AddFolder(const String& path, char delim, long flags)
+ {
+ source.delimiter = delim;
+
+ // check if this folder is a child of the last one and remember it
+ if ( countFolders )
+ {
+ String last = folderNames.Last();
+ if ( last.empty() || path.StartsWith(last + delim) )
+ {
+ folderFlags.Last() &= ~ASMailFolder::ATT_NOINFERIORS;
+ }
+ }
+
+ // we abuse ATT_NOINFERIORS flag here to mean not only that the folder
+ // doesn't have children but also to imply that a folder without this
+ // flag does have children (which is not true for IMAP) -- initially it's
+ // set as we don't have any children yet
+ folderNames.Add(path);
+ folderFlags.Add(flags | ASMailFolder::ATT_NOINFERIORS);
+ countFolders++;
+ }
};
@@ -408,6 +443,6 @@
"the IMAP server %s!\n"
"\n"
- "You may want to change its parameters\n"
- "by return to the previous pages."),
+ "You may want to return to the previous page\n"
+ "and change the server parameters there."),
parent->Data().source.server.c_str()
)
@@ -474,6 +509,4 @@
MigrateWizardProgressPage(MigrateWizard *parent);
- virtual bool TransferDataToWindow();
-
protected:
// enable/disable all wizard buttons
@@ -483,13 +516,46 @@
void OnButtonCancel(wxCommandEvent& event);
+ // we don't have an "Ok" button but we generate a pseudo event from it to
+ // start working immediately after being shown
+ void OnButtonOk(wxCommandEvent& event);
+
+ // this is where we post the "Ok" button event from
+ void OnShow(wxShowEvent& event);
+
private:
// update the messages progress meter
- void UpdateMessageProgress();
+ bool UpdateMessageProgress();
// update the folder progress meter (also updates the messages one)
- void UpdateFolderProgress();
+ bool UpdateFolderProgress();
// update the status shown in m_labelStatus
- void UpdateStatus(const String& msg);
+ bool UpdateStatus(const String& msg);
+
+
+ // returns the folder to copy from
+ MailFolder *OpenSource(const MigrateImapServer& imapData,
+ const String& name);
+
+ // return the MFolder to copy to
+ MFolder *GetDstFolder(const String& name, int flags);
+
+ // return the type of the folders we're creating
+ MFolderType GetDstType() const;
+
+ // get the dst folder name corresponding to the given source folder
+ String GetDstNameForSource(const String& name);
+
+ // do copy all messages
+ bool CopyMessages(MailFolder *mfSrc, MFolder *folderDst);
+
+ // process the source folder with this name
+ bool ProcessOneFolder(const String& name, int flags);
+
+ // create the target folder corresponding to the non-selectable source one
+ bool CreateDstDirectory(const String& name);
+
+ // process all folders
+ void DoMigration();
@@ -499,4 +565,8 @@
m_countMessages; // total number of messages or -1
+ size_t m_nErrors; // number of folders we couldn't copy
+
+ bool m_continue; // set to false if we're cancelled
+
// the GUI controls
wxStaticText *m_labelFolder, // folder progress label
@@ -806,5 +876,5 @@
#ifdef USE_SSL
- m_chkSSL->SetValue(m_folder->GetFlags() & MF_FLAGS_SSLAUTH);
+ m_chkSSL->SetValue((m_folder->GetFlags() & MF_FLAGS_SSLAUTH) != 0);
#endif // USE_SSL
}
@@ -876,5 +946,14 @@
{
m_localData->root = m_textDir->GetValue();
- m_localData->format = (FileMailboxFormat)m_choiceFormat->GetSelection();
+
+ int sel = m_choiceFormat->GetSelection();
+ if ( sel == -1 )
+ {
+ wxLogError(_("Please select the local mailbox format."));
+
+ return false;
+ }
+
+ m_localData->format = (FileMailboxFormat)sel;
return true;
@@ -976,5 +1055,7 @@
);
- m_radioIMAP = new wxRadioButton(this, -1, _("to another &IMAP server:"));
+ m_radioIMAP = new wxRadioButton(this, -1, _("to another &IMAP server:"),
+ wxDefaultPosition, wxDefaultSize,
+ wxRB_SINGLE);
sizer->Add(m_radioIMAP, 0, wxALL, LAYOUT_X_MARGIN);
@@ -982,5 +1063,7 @@
sizer->Add(m_panelIMAP, 1, wxALL | wxEXPAND, LAYOUT_X_MARGIN);
- m_radioLocal = new wxRadioButton(this, -1, _("or to a &local file:"));
+ m_radioLocal = new wxRadioButton(this, -1, _("or to a local &file:"),
+ wxDefaultPosition, wxDefaultSize,
+ wxRB_SINGLE);
sizer->Add(m_radioLocal);
@@ -1008,4 +1091,6 @@
if ( useIMAP )
{
+ m_radioLocal->SetValue(false);
+
// button should be disabled if the server is not entered
m_panelIMAP->UpdateForwardBtnUI();
@@ -1013,4 +1098,6 @@
else // local dst
{
+ m_radioIMAP->SetValue(false);
+
// button is always enabled
EnableButtons(MigrateWizard::Btn_Next, true);
@@ -1026,9 +1113,13 @@
EnablePanelToBeUsed();
- return GetPanelToUse()->TransferDataToWindow();
+ // call TransferDataToWindow() for both panels even if only one is used at
+ // any given moment
+ return m_panelIMAP->TransferDataToWindow() &&
+ m_panelLocal->TransferDataToWindow();
}
bool MigrateWizardDstPage::TransferDataFromWindow()
{
+ // but only call TransferDataFromWindow() for the one the user selected
return GetPanelToUse()->TransferDataFromWindow();
}
@@ -1102,4 +1193,7 @@
BEGIN_EVENT_TABLE(MigrateWizardProgressPage, MigrateWizardPage)
+ EVT_SHOW(MigrateWizardProgressPage::OnShow)
+
+ EVT_BUTTON(wxID_OK, MigrateWizardProgressPage::OnButtonOk)
EVT_BUTTON(wxID_CANCEL, MigrateWizardProgressPage::OnButtonCancel)
END_EVENT_TABLE()
@@ -1112,4 +1206,6 @@
)
{
+ m_continue = true;
+
// create the GUI controls
wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
@@ -1134,5 +1230,7 @@
sizer->Add(m_labelFolder, 0, wxALL | wxEXPAND, LAYOUT_X_MARGIN);
- m_gaugeFolder = new wxGauge(this, -1, Data().countFolders);
+ m_gaugeFolder = new wxGauge(this, -1, Data().countFolders,
+ wxDefaultPosition, wxDefaultSize,
+ wxGA_HORIZONTAL | wxGA_SMOOTH);
sizer->Add(m_gaugeFolder, 0, wxALL | wxEXPAND, LAYOUT_X_MARGIN);
@@ -1140,5 +1238,7 @@
sizer->Add(m_labelMsg, 0, wxALL | wxEXPAND, LAYOUT_X_MARGIN);
- m_gaugeMsg = new wxGauge(this, -1, 0); // range will be set later
+ m_gaugeMsg = new wxGauge(this, -1, 0, // range will be set later
+ wxDefaultPosition, wxDefaultSize,
+ wxGA_HORIZONTAL | wxGA_SMOOTH);
sizer->Add(m_gaugeMsg, 0, wxALL | wxEXPAND, LAYOUT_X_MARGIN);
@@ -1157,9 +1257,7 @@
SetSizer(sizer);
-
- EnableWizardButtons(false);
}
-void MigrateWizardProgressPage::UpdateMessageProgress()
+bool MigrateWizardProgressPage::UpdateMessageProgress()
{
m_labelMsg->SetLabel
@@ -1174,8 +1272,20 @@
m_gaugeMsg->SetValue(m_nMessage);
+
+ wxYield();
+
+ return m_continue;
}
-void MigrateWizardProgressPage::UpdateFolderProgress()
+bool MigrateWizardProgressPage::UpdateFolderProgress()
{
+ String fullname = Data().source.root,
+ name = Data().folderNames[m_nFolder];
+
+ if ( !fullname.empty() && !name.empty() )
+ fullname += Data().source.delimiter;
+
+ fullname += name;
+
m_labelFolder->SetLabel
(
@@ -1185,5 +1295,5 @@
m_nFolder + 1,
Data().countFolders,
- Data().folderNames[m_nFolder].c_str()
+ fullname.c_str()
)
);
@@ -1192,7 +1302,9 @@
wxYield();
+
+ return m_continue;
}
-void MigrateWizardProgressPage::UpdateStatus(const String& msg)
+bool MigrateWizardProgressPage::UpdateStatus(const String& msg)
{
// we need to relayout because the size of the control changed and it must
@@ -1203,38 +1315,32 @@
wxYield();
+
+ return m_continue;
}
void MigrateWizardProgressPage::EnableWizardButtons(bool enable)
{
- EnableButtons(MigrateWizard::Btn_All, enable);
+ // when we (re)enable the buttons, only "Finish" still makes sense, but when
+ // we disable them, we want to disable all of them
+ EnableButtons(enable ? MigrateWizard::Btn_Next
+ : MigrateWizard::Btn_All, enable);
}
-bool MigrateWizardProgressPage::TransferDataToWindow()
+MailFolder *
+MigrateWizardProgressPage::OpenSource(const MigrateImapServer& imapData,
+ const String& name)
{
- const char delimiterSrc = Data().source.delimiter;
-
- for ( m_nFolder = 0; m_nFolder < Data().countFolders; m_nFolder++ )
- {
- UpdateFolderProgress();
-
- // is this a "file" or a "directory"?
- if ( Data().folderFlags[m_nFolder] & ASMailFolder::ATT_NOSELECT )
- {
- }
- else // a "file"-like folder, copy the messages from it
- {
- // open the source folder
MFolder_obj folderSrc(MFolder::CreateTemp(_T(""), MF_IMAP));
+ CHECK( folderSrc, NULL, _T("MFolder::CreateTemp() failed?") );
- const MigrateImapServer& imapData = Data().source;
folderSrc->SetServer(imapData.server);
- String path = imapData.root,
- name = Data().folderNames[m_nFolder];
+ String path = imapData.root;
if ( !name.empty() )
{
- path << delimiterSrc << name;
+ path << Data().source.delimiter << name;
}
folderSrc->SetPath(path);
+
folderSrc->SetAuthInfo(imapData.username, imapData.password);
@@ -1246,12 +1352,10 @@
#endif // USE_SSL
- MailFolder_obj mf = MailFolder::OpenFolder
- (
- folderSrc,
- MailFolder::ReadOnly
- );
- if ( mf )
- {
- // create the folder to save the messages to
+ return MailFolder::OpenFolder(folderSrc, MailFolder::ReadOnly);
+}
+
+MFolderType
+MigrateWizardProgressPage::GetDstType() const
+{
MFolderType folderType;
if ( Data().toIMAP )
@@ -1261,55 +1365,93 @@
else // file, but which?
{
- folderType = Data().dstLocal.format == FileMbox_Max
- ? MF_MH
- : MF_FILE;
+ folderType = Data().dstLocal.format == FileMbox_Max ? MF_MH : MF_FILE;
}
- MFolder_obj folderDst(MFolder::CreateTemp(_T(""), folderType));
- if ( !folderDst )
- {
- FAIL_MSG( _T("MFolder::CreateTemp() failed?") );
+ return folderType;
+}
- continue;
- }
+String
+MigrateWizardProgressPage::GetDstNameForSource(const String& name)
+{
+ // when we start from source folder foo we want the target folder for foo to
+ // be named foo (and not have empty name) so always append source.root to
+ // the path
+ String path = Data().dstLocal.root,
+ rootSrc = Data().source.root;
- if ( folderType == MF_FILE )
+ const char delimiterSrc = Data().source.delimiter;
+
+ if ( !rootSrc.empty() )
{
- folderDst->SetFileMboxFormat(Data().dstLocal.format);
+ if ( !path.empty() )
+ path += delimiterSrc;
+
+ path += rootSrc;
}
- String path = Data().dstLocal.root;
if ( !name.empty() )
{
- path << delimiterSrc << name;
+ if ( !path.empty() )
+ path += delimiterSrc;
+
+ path += name;
}
- // make it into the dst path
- char delimiterDst = '\0';
+ // make it into the dst path: it can have different delimiter
for ( size_t n = 0; n < path.length(); n++ )
{
if ( path[n] == delimiterSrc )
{
- if ( !delimiterDst )
+ if ( !Data().delimiterDst )
{
- // we need to determine it as it can be mostly anything
- // for IMAP
- MailFolder_obj mfTmp = MailFolder::OpenFolder
- (
- folderDst,
- MailFolder::HalfOpen
- );
- if ( !mfTmp )
+ MFolder_obj folderDst = MFolder::CreateTemp(_T(""), GetDstType());
+ Data().delimiterDst = MailFolder::GetFolderDelimiter(folderDst);
+
+ if ( Data().delimiterDst == delimiterSrc )
{
- wxLogError(_("Failed to retrieve the target "
- "folder hierarchy delimiter."));
+ // nothing to do, finally!
+ break;
+ }
+ }
- return true;
+ path[n] = Data().delimiterDst;
+ }
}
- delimiterDst = mfTmp->GetFolderDelimiter();
+ return path;
+}
+
+MFolder *
+MigrateWizardProgressPage::GetDstFolder(const String& name, int flags)
+{
+ // which kind of folder are we going to create?
+ MFolderType folderType = GetDstType();
+ MFolder *folderDst = MFolder::CreateTemp(_T(""), folderType);
+ CHECK( folderDst, NULL, _T("MFolder::CreateTemp() failed?") );
+
+ if ( folderType == MF_FILE )
+ {
+ folderDst->SetFileMboxFormat(Data().dstLocal.format);
}
- path[n] = delimiterDst;
+ String path = GetDstNameForSource(name);
+
+ // there is a complication here: although IMAP folders may (depending on
+ // server) contain both messages and subfolders, this is impossible with
+ // MBOX and MBX folders (although ok with MH) and the way we deal with this
+ // is to put the messages in a file named "folder.messages"
+ if ( folderType == MF_FILE )
+ {
+ if ( !(flags & ASMailFolder::ATT_NOINFERIORS) )
+ {
+ // create a subdirectory for the subfolders
+ if ( !wxMkdir(path) )
+ {
+ wxLogWarning(_("Failed to create directory \"%s\" for folder \"%s\""),
+ path.c_str(), name.c_str());
+ }
+
+ // and modify the name for the file itself
+ path += _T(".messages");
}
}
@@ -1317,22 +1459,25 @@
folderDst->SetPath(path);
- MailFolder_obj mfDst = MailFolder::OpenFolder(folderDst);
- if ( !mfDst )
- {
- wxLogError(_("Failed to create the targer folder \"%s\""),
- path.c_str());
- continue;
- }
+ return folderDst;
+}
- // now copy all the messages from src to dst
+bool
+MigrateWizardProgressPage::CopyMessages(MailFolder *mfSrc, MFolder *folderDst)
+{
UIdArray uids;
uids.Add(UID_ILLEGAL);
- HeaderInfoList_obj headers = mf->GetHeaders();
+ HeaderInfoList_obj headers = mfSrc->GetHeaders();
m_countMessages = headers->Count();
+ m_gaugeMsg->SetRange(m_countMessages);
+
for ( m_nMessage = 0; m_nMessage < m_countMessages; m_nMessage++ )
{
- UpdateMessageProgress();
+ if ( !UpdateMessageProgress() )
+ {
+ // cancelled
+ return true;
+ }
HeaderInfo *hi = headers->GetItemByIndex(m_nMessage);
@@ -1345,16 +1490,142 @@
uids[0] = hi->GetUId();
- if ( !mf->SaveMessages(&uids, folderDst) )
+ if ( !mfSrc->SaveMessages(&uids, folderDst) )
{
- wxLogError(_("Failed to copy the message %d from folder %s"),
+ wxLogError(_("Failed to copy the message %d from folder \"%s\""),
m_nMessage,
Data().folderNames[m_nFolder].c_str());
+
+ return false;
+ }
}
+
+ return true;
+}
+
+bool MigrateWizardProgressPage::CreateDstDirectory(const String& name)
+{
+ if ( Data().toIMAP )
+ {
+ // TODO: do we need to do anything here or will it be created
+ // automatically for us?
+ return true;
}
+ else // local file destination
+ {
+ // create a directory
+ return wxMkdir(GetDstNameForSource(name));
}
+}
+
+bool MigrateWizardProgressPage::ProcessOneFolder(const String& name, int flags)
+{
+ // open the source folder
+ MailFolder_obj mf(OpenSource(Data().source, name));
+ if ( !mf )
+ {
+ wxLogError(_("Failed to open source folder \"%s\""), name.c_str());
+
+ return false;
}
+
+ // create the folder to save the messages to
+ MFolder_obj folderDst = GetDstFolder(name, flags);
+ MailFolder_obj mfDst = MailFolder::OpenFolder(folderDst);
+ if ( !mfDst )
+ {
+ wxLogError(_("Failed to create the targer folder \"%s\""), name.c_str());
+
+ return false;
}
- return true;
+ // now copy all the messages from src to dst
+ return CopyMessages(mf, folderDst);
+}
+
+void MigrateWizardProgressPage::DoMigration()
+{
+ EnableWizardButtons(false);
+
+ for ( m_nFolder = 0, m_nErrors = 0;
+ m_nFolder < Data().countFolders;
+ m_nFolder++ )
+ {
+ if ( !UpdateFolderProgress() )
+ {
+ // cancelled
+ break;
+ }
+;
+ const String& name = Data().folderNames[m_nFolder];
+
+ // is this a "file" or a "directory"?
+ if ( Data().folderFlags[m_nFolder] & ASMailFolder::ATT_NOSELECT )
+ {
+ // just create the corresponding directory or folder
+ if ( !CreateDstDirectory(name) )
+ {
+ // it's not a fatal error (no messages lost...) but still worth
+ // noting
+ wxLogWarning(_("Failed to copy the folder \"%s\""), name.c_str());
+ }
+ }
+ else // a "file"-like folder, copy the messages from it
+ {
+ if ( !ProcessOneFolder(name, Data().folderFlags[m_nFolder]) )
+ {
+ wxLogError(_("Failed to copy messages from folder \"%s\""),
+ name.c_str());
+
+ m_nErrors++;
+ }
+ }
+ }
+
+ // update the UI to show that we're done now
+ if ( m_continue )
+ {
+ m_btnAbort->Disable();
+
+ m_gaugeMsg->SetValue(m_countMessages);
+ m_gaugeFolder->SetValue(Data().countFolders);
+
+ String msg;
+ if ( m_nErrors )
+ {
+ wxLogError(_("There were errors during the migration."));
+
+ msg.Printf(_("Done with %u error(s)"), m_nErrors);
+ }
+ else
+ {
+ msg = _("Completed successfully.");
+ }
+
+ UpdateStatus(msg);
+
+ EnableWizardButtons(true);
+ }
+ //else: cancelled
+
+ wxWindow *btnFinish = GetParent()->FindWindow(wxID_FORWARD);
+ CHECK_RET( btnFinish, _T("no \"Finish\" button?") );
+
+ btnFinish->SetFocus();
+}
+
+void MigrateWizardProgressPage::OnShow(wxShowEvent& event)
+{
+ if ( event.GetShow() )
+ {
+ wxCommandEvent eventOk(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
+ wxPostEvent(this, eventOk);
+ }
+
+ event.Skip();
+}
+
+void MigrateWizardProgressPage::OnButtonOk(wxCommandEvent& /* event */)
+{
+ DoMigration();
}
@@ -1367,4 +1638,6 @@
wxYES_NO | wxICON_QUESTION | wxNO_DEFAULT) == wxYES )
{
+ m_continue = false;
+
m_btnAbort->Disable();
m_labelFolder->Disable();
@@ -1467,5 +1740,5 @@
/* Page_Source */ Page_Max, // not used!
/* Page_CantAccessSource */ Page_Max,
- /* Page_WarnEmptySource */ Page_Dst,
+ /* Page_WarnEmptySource */ Page_Max,
/* Page_Dst */ Page_Confirm,
/* Page_Confirm */ Page_Progress,
@@ -1511,10 +1784,5 @@
m_doneWithList = false;
- // the cast below is needed as ListEventReceiver compares the user
- // data in the results it gets with "this" and its this pointer is
- // different from our "this" as we use multiple inheritance
- Ticket t = asmf->ListFolders(_T(""), false, _T(""),
- (ListEventReceiver *)this);
- if ( t != ILLEGAL_TICKET )
+ if ( ListAll(asmf) )
{
// process the events from ListFolders
@@ -1573,5 +1841,4 @@
{
case Page_Source:
- case Page_WarnEmptySource:
case Page_Dst:
case Page_Confirm:
@@ -1581,4 +1848,5 @@
FAIL_MSG( _T("unknown page in MigrateWizard") );
+ case Page_WarnEmptySource:
case Page_CantAccessSource:
case Page_Progress:
@@ -1596,9 +1864,5 @@
MigrateWizard::OnListFolder(const String& path, char delim, long flags)
{
- Data().source.delimiter = delim;
-
- Data().folderNames.Add(path);
- Data().folderFlags.Add(flags);
- Data().countFolders++;
+ Data().AddFolder(path, delim, flags);
}
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Mahogany-cvsupdates mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates