[Spambayes-checkins] spambayes/Outlook2000 addin.py,1.36,1.37
Mark Hammond
mhammond@users.sourceforge.net
Sat Nov 23 10:34:26 2002
Update of /cvsroot/spambayes/spambayes/Outlook2000
In directory sc8-pr-cvs1:/tmp/cvs-serv9397
Modified Files:
addin.py
Log Message:
Ensure our UI is attached to every Outlook window, not just the first one when we start. Involved a fair bit of reorganization!
Index: addin.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/Outlook2000/addin.py,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** addin.py 21 Nov 2002 02:57:05 -0000 1.36
--- addin.py 23 Nov 2002 10:34:24 -0000 1.37
***************
*** 100,104 ****
tlb, index = ti.GetContainingTypeLib()
tla = tlb.GetLibAttr()
! mod = gencache.EnsureModule(tla[0], tla[1], tla[3], tla[4])
disp_class = gencache.GetClassForProgID(str(disp_clsid))
except pythoncom.com_error:
--- 100,104 ----
tlb, index = ti.GetContainingTypeLib()
tla = tlb.GetLibAttr()
! gencache.EnsureModule(tla[0], tla[1], tla[3], tla[4])
disp_class = gencache.GetClassForProgID(str(disp_clsid))
except pythoncom.com_error:
***************
*** 213,222 ****
# Event function fired from the "Show Clues" UI items.
! def ShowClues(mgr, app):
from cgi import escape
! msgstore_message = mgr.addin.GetSelectedMessages(False)
if msgstore_message is None:
return
item = msgstore_message.GetOutlookItem()
score, clues = mgr.score(msgstore_message, evidence=True, scale=False)
--- 213,224 ----
# Event function fired from the "Show Clues" UI items.
! def ShowClues(mgr, explorer):
from cgi import escape
! app = explorer.Application
! msgstore_message = explorer.GetSelectedMessages(False)
if msgstore_message is None:
return
+
item = msgstore_message.GetOutlookItem()
score, clues = mgr.score(msgstore_message, evidence=True, scale=False)
***************
*** 262,328 ****
new_msg.Display()
- # Events from our Explorer instance - currently used to enable/disable
- # controls
- class ExplorerEvent:
- def Init(self, manager, application, but_delete_as, but_recover_as):
- self.manager = manager
- self.application = application
- self.but_delete_as = but_delete_as
- self.but_recover_as = but_recover_as
- def Close(self):
- self.but_delete_as = self.but_recover_as = None
- def OnFolderSwitch(self):
- # Work out what folder we are in.
- explorer = self.application.ActiveExplorer()
- if explorer is None:
- print "** Folder Change, but don't have an explorer"
- return
-
- outlook_folder = explorer.CurrentFolder
- show_delete_as = True
- show_recover_as = False
- try:
- if outlook_folder is not None:
- mapi_folder = self.manager.message_store.GetFolder(outlook_folder)
- look_id = self.manager.config.filter.spam_folder_id
- if look_id:
- look_folder = self.manager.message_store.GetFolder(look_id)
- if mapi_folder == look_folder:
- # This is the Spam folder - only show "recover"
- show_recover_as = True
- show_delete_as = False
- # Check if uncertain
- look_id = self.manager.config.filter.unsure_folder_id
- if look_id:
- look_folder = self.manager.message_store.GetFolder(look_id)
- if mapi_folder == look_folder:
- show_recover_as = True
- show_delete_as = True
- except:
- print "Error finding the MAPI folders for a folder switch event"
- import traceback
- traceback.print_exc()
- self.but_recover_as.Visible = show_recover_as
- self.but_delete_as.Visible = show_delete_as
-
# The "Delete As Spam" and "Recover Spam" button
# The event from Outlook's explorer that our folder has changed.
class ButtonDeleteAsEventBase:
! def Init(self, manager, application):
! # NOTE - keeping a reference to 'explorer' in this event
! # appears to cause an Outlook circular reference, and outlook
! # never terminates (it does close, but the process remains alive)
! # This is why we needed to use WithEvents, so the event class
! # itself doesnt keep such a reference (and we need to keep a ref
! # to the event class so it doesn't auto-disconnect!)
self.manager = manager
! self.application = application
def Close(self):
! self.manager = self.application = None
class ButtonDeleteAsSpamEvent(ButtonDeleteAsEventBase):
! def Init(self, manager, application):
! ButtonDeleteAsEventBase.Init(self, manager, application)
image = "delete_as_spam.bmp"
self.Caption = "Delete As Spam"
--- 264,280 ----
new_msg.Display()
# The "Delete As Spam" and "Recover Spam" button
# The event from Outlook's explorer that our folder has changed.
class ButtonDeleteAsEventBase:
! def Init(self, manager, explorer):
self.manager = manager
! self.explorer = explorer
def Close(self):
! self.manager = self.explorer = None
class ButtonDeleteAsSpamEvent(ButtonDeleteAsEventBase):
! def Init(self, manager, explorer):
! ButtonDeleteAsEventBase.Init(self, manager, explorer)
image = "delete_as_spam.bmp"
self.Caption = "Delete As Spam"
***************
*** 334,338 ****
def OnClick(self, button, cancel):
msgstore = self.manager.message_store
! msgstore_messages = self.manager.addin.GetSelectedMessages(True)
if not msgstore_messages:
return
--- 286,290 ----
def OnClick(self, button, cancel):
msgstore = self.manager.message_store
! msgstore_messages = self.explorer.GetSelectedMessages(True)
if not msgstore_messages:
return
***************
*** 356,361 ****
class ButtonRecoverFromSpamEvent(ButtonDeleteAsEventBase):
! def Init(self, manager, application):
! ButtonDeleteAsEventBase.Init(self, manager, application)
image = "recover_ham.bmp"
self.Caption = "Recover from Spam"
--- 308,313 ----
class ButtonRecoverFromSpamEvent(ButtonDeleteAsEventBase):
! def Init(self, manager, explorer):
! ButtonDeleteAsEventBase.Init(self, manager, explorer)
image = "recover_ham.bmp"
self.Caption = "Recover from Spam"
***************
*** 369,373 ****
def OnClick(self, button, cancel):
msgstore = self.manager.message_store
! msgstore_messages = self.manager.addin.GetSelectedMessages(True)
if not msgstore_messages:
return
--- 321,325 ----
def OnClick(self, button, cancel):
msgstore = self.manager.message_store
! msgstore_messages = self.explorer.GetSelectedMessages(True)
if not msgstore_messages:
return
***************
*** 375,381 ****
# Get the inbox as the default place to restore to
# (incase we dont know (early code) or folder removed etc
inbox_folder = msgstore.GetFolder(
! self.application.Session.GetDefaultFolder(
! constants.olFolderInbox))
import train
for msgstore_message in msgstore_messages:
--- 327,333 ----
# Get the inbox as the default place to restore to
# (incase we dont know (early code) or folder removed etc
+ app = self.explorer.Application
inbox_folder = msgstore.GetFolder(
! app.Session.GetDefaultFolder(constants.olFolderInbox))
import train
for msgstore_message in msgstore_messages:
***************
*** 408,411 ****
--- 360,515 ----
button.PasteFace()
+ # A class that manages an "Outlook Explorer" - that is, a top-level window
+ # All UI elements are managed here, and there is one instance per explorer.
+ class ExplorerWithEvents:
+ def Init(self, manager, explorer_list):
+ self.manager = manager
+ self.have_setup_ui = False
+ self.explorer_list = explorer_list
+
+ def SetupUI(self):
+ application = self.Application
+ manager = self.manager
+ self.buttons = []
+ activeExplorer = self
+ bars = activeExplorer.CommandBars
+ toolbar = bars.Item("Standard")
+ # Add our "Delete as ..." and "Recover as" buttons
+ self.but_delete_as = button = toolbar.Controls.Add(
+ Type=constants.msoControlButton,
+ Temporary=True)
+ # Hook events for the item
+ button.BeginGroup = True
+ button = DispatchWithEvents(button, ButtonDeleteAsSpamEvent)
+ button.Init(self.manager, self)
+ self.buttons.append(button)
+ # And again for "Recover as"
+ self.but_recover_as = button = toolbar.Controls.Add(
+ Type=constants.msoControlButton,
+ Temporary=True)
+ button = DispatchWithEvents(button, ButtonRecoverFromSpamEvent)
+ self.buttons.append(button)
+ # Hook our explorer events, and pass the buttons.
+ button.Init(self.manager, self)
+
+ # And prime our event handler.
+ self.OnFolderSwitch()
+
+ # The main tool-bar dropdown with all our entries.
+ # Add a pop-up menu to the toolbar
+ popup = toolbar.Controls.Add(
+ Type=constants.msoControlPopup,
+ Temporary=True)
+ popup.Caption="Anti-Spam"
+ popup.TooltipText = "Anti-Spam filters and functions"
+ popup.Enabled = True
+ # Convert from "CommandBarItem" to derived
+ # "CommandBarPopup" Not sure if we should be able to work
+ # this out ourselves, but no introspection I tried seemed
+ # to indicate we can. VB does it via strongly-typed
+ # declarations.
+ popup = CastTo(popup, "CommandBarPopup")
+ # And add our children.
+ self._AddPopup(popup, manager.ShowManager, (),
+ Caption="Anti-Spam Manager...",
+ TooltipText = "Show the Anti-Spam manager dialog.",
+ Enabled = True)
+ self._AddPopup(popup, ShowClues, (self.manager, self),
+ Caption="Show spam clues for current message",
+ Enabled=True)
+ self.have_setup_ui = True
+
+ def _AddPopup(self, parent, target, target_args, **item_attrs):
+ item = parent.Controls.Add(Type=constants.msoControlButton, Temporary=True)
+ # Hook events for the item
+ item = DispatchWithEvents(item, ButtonEvent)
+ item.Init(target, target_args)
+ for attr, val in item_attrs.items():
+ setattr(item, attr, val)
+ self.buttons.append(item)
+
+ def GetSelectedMessages(self, allow_multi = True, explorer = None):
+ if explorer is None:
+ explorer = self.Application.ActiveExplorer()
+ sel = explorer.Selection
+ if sel.Count > 1 and not allow_multi:
+ win32ui.MessageBox("Please select a single item", "Large selection")
+ return None
+
+ ret = []
+ for i in range(sel.Count):
+ item = sel.Item(i+1)
+ if item.Class == constants.olMail:
+ msgstore_message = self.manager.message_store.GetMessage(item)
+ ret.append(msgstore_message)
+
+ if len(ret) == 0:
+ win32ui.MessageBox("No mail items are selected", "No selection")
+ return None
+ if allow_multi:
+ return ret
+ return ret[0]
+
+ # The Outlook event handlers
+ def OnActivate(self):
+ if not self.have_setup_ui:
+ self.SetupUI()
+
+ def OnClose(self):
+ self.explorer_list.remove(self)
+ self.explorer_list = None
+ for button in self.buttons:
+ button.Close()
+ self.buttons = []
+ self.close() # disconnect events.
+
+ def OnFolderSwitch(self):
+ # Work out what folder we are in.
+ outlook_folder = self.CurrentFolder
+ show_delete_as = True
+ show_recover_as = False
+ try:
+ if outlook_folder is not None:
+ mapi_folder = self.manager.message_store.GetFolder(outlook_folder)
+ look_id = self.manager.config.filter.spam_folder_id
+ if look_id:
+ look_folder = self.manager.message_store.GetFolder(look_id)
+ if mapi_folder == look_folder:
+ # This is the Spam folder - only show "recover"
+ show_recover_as = True
+ show_delete_as = False
+ # Check if uncertain
+ look_id = self.manager.config.filter.unsure_folder_id
+ if look_id:
+ look_folder = self.manager.message_store.GetFolder(look_id)
+ if mapi_folder == look_folder:
+ show_recover_as = True
+ show_delete_as = True
+ except:
+ print "Error finding the MAPI folders for a folder switch event"
+ import traceback
+ traceback.print_exc()
+ self.but_recover_as.Visible = show_recover_as
+ self.but_delete_as.Visible = show_delete_as
+
+ # Events from our "Explorers" collection (not an Explorer instance)
+ class ExplorersEvent:
+ def Init(self, manager):
+ self.manager = manager
+ self.explorers = []
+
+ def Close(self):
+ self.explorers = None
+
+ def _DoNewExplorer(self, explorer, do_activate):
+ explorer = DispatchWithEvents(explorer, ExplorerWithEvents)
+ explorer.Init(self.manager, self.explorers)
+ if do_activate:
+ explorer.OnActivate()
+ self.explorers.append(explorer)
+
+ def OnNewExplorer(self, explorer):
+ self._DoNewExplorer(explorer, False)
+
# The outlook Plugin COM object itself.
class OutlookAddin:
***************
*** 420,424 ****
self.folder_hooks = {}
self.application = None
- self.buttons = []
def OnConnection(self, application, connectMode, addin, custom):
--- 524,527 ----
***************
*** 431,488 ****
assert self.manager.addin is None, "Should not already have an addin"
self.manager.addin = self
- self.explorer_events = None
-
- # ActiveExplorer may be none when started without a UI (eg, WinCE synchronisation)
- activeExplorer = application.ActiveExplorer()
- if activeExplorer is not None:
- bars = activeExplorer.CommandBars
- toolbar = bars.Item("Standard")
- # Add our "Delete as ..." and "Recover as" buttons
- but_delete_as = button = toolbar.Controls.Add(
- Type=constants.msoControlButton,
- Temporary=True)
- # Hook events for the item
- button.BeginGroup = True
- button = DispatchWithEvents(button, ButtonDeleteAsSpamEvent)
- button.Init(self.manager, application)
- self.buttons.append(button)
- # And again for "Recover as"
- but_recover_as = button = toolbar.Controls.Add(
- Type=constants.msoControlButton,
- Temporary=True)
- button = DispatchWithEvents(button, ButtonRecoverFromSpamEvent)
- self.buttons.append(button)
- # Hook our explorer events, and pass the buttons.
- button.Init(self.manager, application)
! self.explorer_events = WithEvents(activeExplorer,
! ExplorerEvent)
!
! self.explorer_events.Init(self.manager, application, but_delete_as, but_recover_as)
! # And prime the event handler.
! self.explorer_events.OnFolderSwitch()
!
! # The main tool-bar dropdown with all our entries.
! # Add a pop-up menu to the toolbar
! popup = toolbar.Controls.Add(
! Type=constants.msoControlPopup,
! Temporary=True)
! popup.Caption="Anti-Spam"
! popup.TooltipText = "Anti-Spam filters and functions"
! popup.Enabled = True
! # Convert from "CommandBarItem" to derived
! # "CommandBarPopup" Not sure if we should be able to work
! # this out ourselves, but no introspection I tried seemed
! # to indicate we can. VB does it via strongly-typed
! # declarations.
! popup = CastTo(popup, "CommandBarPopup")
! # And add our children.
! self._AddPopup(popup, manager.ShowManager, (self.manager,),
! Caption="Anti-Spam Manager...",
! TooltipText = "Show the Anti-Spam manager dialog.",
! Enabled = True)
! self._AddPopup(popup, ShowClues, (self.manager, application),
! Caption="Show spam clues for current message",
! Enabled=True)
self.FiltersChanged()
--- 534,546 ----
assert self.manager.addin is None, "Should not already have an addin"
self.manager.addin = self
! explorers = application.Explorers
! # and Explorers events so we know when new explorers spring into life.
! self.explorers_events = WithEvents(explorers, ExplorersEvent)
! self.explorers_events.Init(self.manager)
! # And hook our UI elements to all existing explorers
! for i in range(explorers.Count):
! explorer = explorers.Item(i+1)
! self.explorers_events._DoNewExplorer(explorer, True)
self.FiltersChanged()
***************
*** 495,507 ****
traceback.print_exc()
- def _AddPopup(self, parent, target, target_args, **item_attrs):
- item = parent.Controls.Add(Type=constants.msoControlButton, Temporary=True)
- # Hook events for the item
- item = DispatchWithEvents(item, ButtonEvent)
- item.Init(target, target_args)
- for attr, val in item_attrs.items():
- setattr(item, attr, val)
- self.buttons.append(item)
-
def ProcessMissedMessages(self):
# This could possibly spawn threads if it was too slow!
--- 553,556 ----
***************
*** 568,608 ****
return new_hooks
- def GetSelectedMessages(self, allow_multi = True, explorer = None):
- if explorer is None:
- explorer = self.application.ActiveExplorer()
- sel = explorer.Selection
- if sel.Count > 1 and not allow_multi:
- win32ui.MessageBox("Please select a single item", "Large selection")
- return None
-
- ret = []
- for i in range(sel.Count):
- item = sel.Item(i+1)
- if item.Class == constants.olMail:
- msgstore_message = self.manager.message_store.GetMessage(item)
- ret.append(msgstore_message)
-
- if len(ret) == 0:
- win32ui.MessageBox("No mail items are selected", "No selection")
- return None
- if allow_multi:
- return ret
- return ret[0]
-
def OnDisconnection(self, mode, custom):
print "SpamAddin - Disconnecting from Outlook"
self.folder_hooks = None
self.application = None
if self.manager is not None:
self.manager.Save()
self.manager.Close()
self.manager = None
-
- if self.explorer_events is not None:
- self.explorer_events = None
- if self.buttons:
- for button in self.buttons:
- button.Close()
- self.buttons = None
print "Addin terminating: %d COM client and %d COM servers exist." \
--- 617,629 ----
return new_hooks
def OnDisconnection(self, mode, custom):
print "SpamAddin - Disconnecting from Outlook"
self.folder_hooks = None
self.application = None
+ self.explorers_events = None
if self.manager is not None:
self.manager.Save()
self.manager.Close()
self.manager = None
print "Addin terminating: %d COM client and %d COM servers exist." \
More information about the Spambayes-checkins
mailing list