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

Reply via email to