[Spambayes-checkins] spambayes/Outlook2000/dialogs FilterDialog.py,1.12,1.13 FolderSelector.py,1.10,1.11 TrainingDialog.py,1.8,1.9

Mark Hammond mhammond at users.sourceforge.net
Thu Jan 23 04:17:37 EST 2003


Update of /cvsroot/spambayes/spambayes/Outlook2000/dialogs
In directory sc8-pr-cvs1:/tmp/cvs-serv32672/dialogs

Modified Files:
	FilterDialog.py FolderSelector.py TrainingDialog.py 
Log Message:
A number of changes related to the folder selector dialog - code generally 
inspired by a couple of nice patches by Tony Meyer.  Should be no visible
changes, but under the covers:

* worked out we were using short-term EIDs for folders, causing the
exchange server to fail.  So we are back to a faster MAPI version.
Deleted the other variants - as I said in the comments, CVS is your
friend <wink>.  I was kind enough leave an indication of the last CVS 
revision with the old code though!

* Only build the folder structure as the folder is expanded.  Thus, the 
entire folder hierarchy is no longer walked when displaying the dialog.
This speeds up the code considerable for exchange server users, where the
public folder hierarchy is both huge, and never needed by SpamBayes.

* We generally use the msgstore, rather than hitting MAPI directly, 
abstracting away some ugly code.  Thus we are tied tighter to the 
spambayes manager object.

* Drop all concepts of "default store" - all folder/message IDs are 
expected to be a tuple of (store_id, item_id).  (This code was just
a hangover to prevent CVS users of spambayes from needing to redefine
all their folders when we first moved to the (store_id, item_id) scheme.



Index: FilterDialog.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/Outlook2000/dialogs/FilterDialog.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** FilterDialog.py	23 Nov 2002 21:35:23 -0000	1.12
--- FilterDialog.py	23 Jan 2003 12:17:35 -0000	1.13
***************
*** 201,206 ****
                  ids = [ids]
              single_select = not ids_are_list
! #            d = FolderSelector.FolderSelector(self.mgr.message_store.session, ids, checkbox_state=None, single_select=single_select)
!             d = FolderSelector.FolderSelector(self.mgr.outlook.Session, ids, checkbox_state=None, single_select=single_select)
              if d.DoModal()==win32con.IDOK:
                  new_ids, include_sub = d.GetSelectedIDs()
--- 201,205 ----
                  ids = [ids]
              single_select = not ids_are_list
!             d = FolderSelector.FolderSelector(self.mgr, ids, checkbox_state=None, single_select=single_select)
              if d.DoModal()==win32con.IDOK:
                  new_ids, include_sub = d.GetSelectedIDs()
***************
*** 342,347 ****
              import FolderSelector
              filter = self.mgr.config.filter_now
!             # d = FolderSelector.FolderSelector(self.mgr.message_store.session, filter.folder_ids,checkbox_state=filter.include_sub)
!             d = FolderSelector.FolderSelector(self.mgr.outlook.Session,
                                                filter.folder_ids,
                                                checkbox_state=filter.include_sub)
--- 341,345 ----
              import FolderSelector
              filter = self.mgr.config.filter_now
!             d = FolderSelector.FolderSelector(self.mgr,
                                                filter.folder_ids,
                                                checkbox_state=filter.include_sub)

Index: FolderSelector.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/Outlook2000/dialogs/FolderSelector.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** FolderSelector.py	15 Jan 2003 03:52:09 -0000	1.10
--- FolderSelector.py	23 Jan 2003 12:17:35 -0000	1.11
***************
*** 39,66 ****
  # rat's arse <wink>).
  # So finally we have an Outlook object model version!
! #########################################################################
! ## CDO version of a folder walker.
! #########################################################################
! def _BuildFoldersCDO(folders):
!     children = []
!     folder = folders.GetFirst()
!     while folder:
!         spec = FolderSpec(folder.ID, folder.Name.encode("mbcs", "replace"))
!         spec.children = _BuildFoldersCDO(folder.Folders)
!         children.append(spec)
!         folder = folders.GetNext()
!     return children
  
! def BuildFolderTreeCDO(session):
!     infostores = session.InfoStores
!     root = FolderSpec(None, "root")
!     for i in range(infostores.Count):
!         infostore = infostores[i+1]
!         rootFolder = infostore.RootFolder
!         folders = rootFolder.Folders
!         spec = FolderSpec(rootFolder.ID, infostore.Name.encode("mbcs", "replace"))
!         spec.children = _BuildFoldersCDO(folders)
!         root.children.append(spec)
!     return root
  
  #########################################################################
--- 39,48 ----
  # rat's arse <wink>).
  # So finally we have an Outlook object model version!
! # But then Tony Meyer came to the rescue - he noticed that we were
! # simply using short-term EID values for Exchange Folders - so now that
! # is solved, we are back to the Extended MAPI version.
  
! # These variants were deleted by MarkH - cvs is your friend :)
! # Last appeared in Rev 1.10
  
  #########################################################################
***************
*** 69,76 ****
  from win32com.mapi import mapi
  from win32com.mapi.mapitags import *
  
! default_store_id = None
! 
! def _BuildFoldersMAPI(msgstore, folder):
      # Get the hierarchy table for it.
      table = folder.GetHierarchyTable(0)
--- 51,58 ----
  from win32com.mapi import mapi
  from win32com.mapi.mapitags import *
+ import pythoncom
  
! def _BuildFoldersMAPI(manager, folder_id):
!     folder = manager.message_store.GetFolder(folder_id).OpenEntry()
      # Get the hierarchy table for it.
      table = folder.GetHierarchyTable(0)
***************
*** 80,102 ****
                                         PR_DISPLAY_NAME_A), None, None, 0)
      for (eid_tag, eid),(storeeid_tag, store_eid), (name_tag, name) in rows:
!         folder_id = mapi.HexFromBin(store_eid), mapi.HexFromBin(eid)
!         spec = FolderSpec(folder_id, name)
!         child_folder = msgstore.OpenEntry(eid, None, mapi.MAPI_DEFERRED_ERRORS)
!         spec.children = _BuildFoldersMAPI(msgstore, child_folder)
!         children.append(spec)
      return children
  
  def BuildFolderTreeMAPI(session):
-     global default_store_id
      root = FolderSpec(None, "root")
      tab = session.GetMsgStoresTable(0)
!     prop_tags = PR_ENTRYID, PR_DEFAULT_STORE, PR_DISPLAY_NAME_A
      rows = mapi.HrQueryAllRows(tab, prop_tags, None, None, 0)
      for row in rows:
!         (eid_tag, eid), (is_def_tag, is_def), (name_tag, name) = row
          hex_eid = mapi.HexFromBin(eid)
-         if is_def:
-             default_store_id = hex_eid
- 
          msgstore = session.OpenMsgStore(0, eid, None, mapi.MDB_NO_MAIL |
                                                        mapi.MAPI_DEFERRED_ERRORS)
--- 62,94 ----
                                         PR_DISPLAY_NAME_A), None, None, 0)
      for (eid_tag, eid),(storeeid_tag, store_eid), (name_tag, name) in rows:
!         # Note the eid we get here is short-term - hence we must
!         # re-fetch from the object itself (which is what our manager does,
!         # so no need to do it explicitly - just believe folder.id over eid)
!         temp_id = mapi.HexFromBin(store_eid), mapi.HexFromBin(eid)
!         try:
!             child_folder = manager.message_store.GetFolder(temp_id)
!         except pythoncom.com_error:
!             # Bad folder for some reason - ignore it.
!             child_folder = None
!         if child_folder is not None:
!             spec = FolderSpec(child_folder.GetID(), name)
!             # If we have no children at all, indicate
!             # the item is not expandable.
!             table = child_folder.OpenEntry().GetHierarchyTable(0)
!             if table.GetRowCount(0) == 0:
!                 spec.children = []
!             else:
!                 spec.children = None # Flag as "not yet built"
!             children.append(spec)
      return children
  
  def BuildFolderTreeMAPI(session):
      root = FolderSpec(None, "root")
      tab = session.GetMsgStoresTable(0)
!     prop_tags = PR_ENTRYID, PR_DISPLAY_NAME_A
      rows = mapi.HrQueryAllRows(tab, prop_tags, None, None, 0)
      for row in rows:
!         (eid_tag, eid), (name_tag, name) = row
          hex_eid = mapi.HexFromBin(eid)
          msgstore = session.OpenMsgStore(0, eid, None, mapi.MDB_NO_MAIL |
                                                        mapi.MAPI_DEFERRED_ERRORS)
***************
*** 106,136 ****
          folder_id = hex_eid, mapi.HexFromBin(subtree_eid)
          spec = FolderSpec(folder_id, name)
!         spec.children = _BuildFoldersMAPI(msgstore, folder)
          root.children.append(spec)
      return root
  
- ## <sob> - An Outlook object model version
- import pythoncom
- def _BuildFolderTreeOutlook(session, parent):
-     children = []
-     for i in range(parent.Folders.Count):
-         folder = parent.Folders[i+1]
-         try:
-             spec = FolderSpec((folder.StoreID, folder.EntryID),
-                               folder.Name.encode("mbcs", "replace"))
-         except pythoncom.error:
-             # Something strange with this folder - just ignore it
-             spec = None
-         if spec is not None:
-             if folder.Folders:
-                 spec.children = _BuildFolderTreeOutlook(session, folder)
-             children.append(spec)
-     return children
- 
- def BuildFolderTreeOutlook(session):
-     root = FolderSpec(None, "root")
-     root.children = _BuildFolderTreeOutlook(session, session)
-     return root
- 
  #########################################################################
  ## The dialog itself
--- 98,105 ----
          folder_id = hex_eid, mapi.HexFromBin(subtree_eid)
          spec = FolderSpec(folder_id, name)
!         spec.children = None
          root.children.append(spec)
      return root
  
  #########################################################################
  ## The dialog itself
***************
*** 174,178 ****
      ]
  
!     def __init__ (self, mapi, selected_ids=None,
                                single_select=False,
                                checkbox_state=False,
--- 143,147 ----
      ]
  
!     def __init__ (self, manager, selected_ids=None,
                                single_select=False,
                                checkbox_state=False,
***************
*** 189,204 ****
          self.select_desc_noun_suffix = desc_noun_suffix
          self.selected_ids = selected_ids
!         self.mapi = mapi
          self.checkbox_state = checkbox_state
          self.checkbox_text = checkbox_text or "Include &subfolders"
  
      def CompareIDs(self, id1, id2):
!         if type(id1) != type(()):
!             id1 = default_store_id, id1
!         if type(id2) != type(()):
!             id2 = default_store_id, id2
!         return id1 == id2
! #        return self.mapi.CompareEntryIDs(mapi.BinFromHex(id1[0]), mapi.BinFromHex(id2[0])) and \
! #               self.mapi.CompareEntryIDs(mapi.BinFromHex(id1[1]), mapi.BinFromHex(id2[1]))
  
      def InIDs(self, id, ids):
--- 158,170 ----
          self.select_desc_noun_suffix = desc_noun_suffix
          self.selected_ids = selected_ids
!         self.manager = manager
          self.checkbox_state = checkbox_state
          self.checkbox_text = checkbox_text or "Include &subfolders"
  
      def CompareIDs(self, id1, id2):
!         # Compare the eid of the stores, then the objects
!         CompareEntryIDs = self.manager.message_store.session.CompareEntryIDs
!         return CompareEntryIDs(mapi.BinFromHex(id1[0]), mapi.BinFromHex(id2[0])) and \
!                CompareEntryIDs(mapi.BinFromHex(id1[1]), mapi.BinFromHex(id2[1]))
  
      def InIDs(self, id, ids):
***************
*** 215,222 ****
  
      def _InsertSubFolders(self, hParent, folderSpec):
-         num_children_selected = 0
          for child in folderSpec.children:
              text = child.name
!             cItems = len(child.children)
              if cItems==0:
                  bitmapCol = bitmapSel = 5 # blank doc
--- 181,190 ----
  
      def _InsertSubFolders(self, hParent, folderSpec):
          for child in folderSpec.children:
              text = child.name
!             if child.children is None: # Need to build them!
!                 cItems = 1 # Anything > 0 will do
!             else:
!                 cItems = len(child.children)
              if cItems==0:
                  bitmapCol = bitmapSel = 5 # blank doc
***************
*** 229,233 ****
                          self.InIDs(child.folder_id, self.selected_ids)):
                      state = INDEXTOSTATEIMAGEMASK(IIL_CHECKED)
-                     num_children_selected += 1
                  else:
                      state = INDEXTOSTATEIMAGEMASK(IIL_UNCHECKED)
--- 197,200 ----
***************
*** 243,246 ****
--- 210,219 ----
                                            cItems,
                                            item_id))
+             # If this folder is in the list of ones we need to expand
+             # to show pre-selected items, then force expand now.
+             if self.InIDs(child.folder_id, self.expand_ids):
+                 self.list.Expand(hitem, commctrl.TVE_EXPAND)
+             # If single-select, and this is ours, select it
+             # (multi-select uses check-boxes, not selection)
              if (self.single_select and
                      self.selected_ids and
***************
*** 248,255 ****
                  self.list.SelectItem(hitem)
  
!             num_children_selected += self._InsertSubFolders(hitem, child)
!         if num_children_selected and hParent:
!             self.list.Expand(hParent, commctrl.TVE_EXPAND)
!         return num_children_selected
  
      def _YieldChildren(self, h):
--- 221,235 ----
                  self.list.SelectItem(hitem)
  
!     def _DetermineFoldersToExpand(self):
!         folders_to_expand = []
!         for folder_id in self.selected_ids:
!             folder = self.manager.message_store.GetFolder(folder_id)
!             while folder is not None:
!                 parent = folder.GetParent()
!                 if parent is not None and \
!                    not self.InIDs(parent.GetID(), folders_to_expand):
!                     folders_to_expand.append(parent.GetID())
!                 folder = parent
!         return folders_to_expand
  
      def _YieldChildren(self, h):
***************
*** 324,336 ****
              self.GetDlgItem(IDC_BUTTON_CLEARALL).ShowWindow(win32con.SW_HIDE)
  
!         tree = BuildFolderTreeOutlook(self.mapi)
! #        if hasattr(self.mapi, "_oleobj_"): # Dispatch COM object
! #            # CDO
! #            tree = BuildFolderTreeCDO(self.mapi)
! #        else:
! #            # Extended MAPI.
! #            tree = BuildFolderTreeMAPI(self.mapi)
          self._InsertSubFolders(0, tree)
!         self.selected_ids = [] # wipe this out while we are alive.
          self._UpdateStatus()
  
--- 304,315 ----
              self.GetDlgItem(IDC_BUTTON_CLEARALL).ShowWindow(win32con.SW_HIDE)
  
!         # Extended MAPI version of the tree.
!         # Build list of all ids to expand - ie, list includes all
!         # selected folders, and all parents.
!         self.expand_ids = self._DetermineFoldersToExpand()
!         tree = BuildFolderTreeMAPI(self.manager.message_store.session)
          self._InsertSubFolders(0, tree)
!         self.selected_ids = [] # Only use this while creating dialog.
!         self.expand_ids = [] # Only use this while creating dialog.
          self._UpdateStatus()
  
***************
*** 393,396 ****
--- 372,383 ----
          if idFrom != IDC_LIST_FOLDERS: return None
          action, itemOld, itemNew, pt = extra
+         if action == 1: return 0 # contracting, not expanding
+ 
+         itemHandle = itemNew[0]
+         info = self.list.GetItem(itemHandle)
+         folderSpec = self.item_map[info[7]]
+         if folderSpec.children is None:
+             folderSpec.children = _BuildFoldersMAPI(self.manager, folderSpec.folder_id)
+             self._InsertSubFolders(itemHandle, folderSpec)
          return 0
  
***************
*** 411,440 ****
          return ret, self.GetDlgItem(IDC_BUTTON_SEARCHSUB).GetCheck() != 0
  
! def TestWithCDO():
!     from win32com.client import Dispatch
!     mapi = Dispatch("MAPI.Session")
!     mapi.Logon("", "", False, False)
!     ids = [u'0000000071C4408983B0B24F8863EE66A8F79AFF82800000']
!     d=FolderSelector(mapi, ids, single_select = False)
!     d.DoModal()
!     print d.GetSelectedIDs()
! 
! def TestWithMAPI():
!     mapi.MAPIInitialize(None)
!     logonFlags = mapi.MAPI_NO_MAIL | mapi.MAPI_EXTENDED | mapi.MAPI_USE_DEFAULT
!     session = mapi.MAPILogonEx(0, None, None, logonFlags)
!     ids = [u'0000000071C4408983B0B24F8863EE66A8F79AFF82800000']
!     d=FolderSelector(session, ids, single_select = False)
      d.DoModal()
!     print d.GetSelectedIDs()
! 
! def TestWithOutlook():
!     from win32com.client import Dispatch
!     outlook = Dispatch("Outlook.Application")
!     d=FolderSelector(outlook.Session, None, single_select = False)
      d.DoModal()
-     print d.GetSelectedIDs()
- 
  
  if __name__=='__main__':
!     TestWithOutlook()
--- 398,412 ----
          return ret, self.GetDlgItem(IDC_BUTTON_SEARCHSUB).GetCheck() != 0
  
! def Test():
!     import sys, os
!     sys.path.append(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")))
!     import manager
!     ids = []
!     d=FolderSelector(manager.GetManager(), ids, single_select = False)
      d.DoModal()
!     ids, include_sub = d.GetSelectedIDs()
!     d=FolderSelector(manager.GetManager(), ids, single_select = False)
      d.DoModal()
  
  if __name__=='__main__':
!     Test()

Index: TrainingDialog.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/Outlook2000/dialogs/TrainingDialog.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** TrainingDialog.py	2 Nov 2002 12:28:38 -0000	1.8
--- TrainingDialog.py	23 Jan 2003 12:17:35 -0000	1.9
***************
*** 105,110 ****
                  sub_attr = "ham_include_sub"
              include_sub = getattr(self.config, sub_attr)
! #            d = FolderSelector.FolderSelector(self.mgr.message_store.session, l, checkbox_state=include_sub)
!             d = FolderSelector.FolderSelector(self.mgr.outlook.Session, l, checkbox_state=include_sub)
              if d.DoModal()==win32con.IDOK:
                  l[:], include_sub = d.GetSelectedIDs()[:]
--- 105,109 ----
                  sub_attr = "ham_include_sub"
              include_sub = getattr(self.config, sub_attr)
!             d = FolderSelector.FolderSelector(self.mgr, l, checkbox_state=include_sub)
              if d.DoModal()==win32con.IDOK:
                  l[:], include_sub = d.GetSelectedIDs()[:]





More information about the Spambayes-checkins mailing list