[Commits] (donn) Better Detail View for Collections

commits at osafoundation.org commits at osafoundation.org
Fri Sep 3 15:54:10 PDT 2004


Commit by: donn
Modified files:
chandler/parcels/osaf/contentmodel/ContentModel.py 1.29 1.30
chandler/parcels/osaf/contentmodel/ItemCollection.py 1.9 1.10
chandler/parcels/osaf/contentmodel/parcel.xml 1.59 1.60
chandler/parcels/osaf/contentmodel/mail/Mail.py 1.22 1.23
chandler/parcels/osaf/contentmodel/mail/parcel.xml 1.57 1.58
chandler/parcels/osaf/contentmodel/tests/TestStamping.py 1.2 1.3
chandler/parcels/osaf/framework/blocks/detail/Detail.py 1.24 1.25
chandler/parcels/osaf/framework/blocks/detail/parcel.xml 1.20 1.21
chandler/parcels/osaf/framework/blocks/Events/parcel.xml 1.49 1.50
chandler/parcels/osaf/views/main/Main.py 1.47 1.48

Log message:
Better Detail View for Collections
* Now supporting Sharing
* Consolidated the Send and Share buttons in DV
* Added progress messages in the Status Bar
* Added MessageMainView() method to call a method in Main
* Replaced usage of x.itsKind.isKindOf() with x.isItemOf()
* Added redirectTo attributes to ItemCollection for easy DV display
* Fixed a problem with ItemCollection
	- had ContentItem as a SuperKind but not a SuperClass
* Removed events from the contentmodel/mail/parcel.xml schema
* Cleaned up the ContentModel to send events instead of doing any UI

ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/ContentModel.py.diff?r1=text&tr1=1.29&r2=text&tr2=1.30
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/ItemCollection.py.diff?r1=text&tr1=1.9&r2=text&tr2=1.10
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/parcel.xml.diff?r1=text&tr1=1.59&r2=text&tr2=1.60
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/mail/Mail.py.diff?r1=text&tr1=1.22&r2=text&tr2=1.23
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/mail/parcel.xml.diff?r1=text&tr1=1.57&r2=text&tr2=1.58
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/contentmodel/tests/TestStamping.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/detail/Detail.py.diff?r1=text&tr1=1.24&r2=text&tr2=1.25
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/detail/parcel.xml.diff?r1=text&tr1=1.20&r2=text&tr2=1.21
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/Events/parcel.xml.diff?r1=text&tr1=1.49&r2=text&tr2=1.50
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/views/main/Main.py.diff?r1=text&tr1=1.47&r2=text&tr2=1.48

Index: chandler/parcels/osaf/contentmodel/tests/TestStamping.py
diff -u chandler/parcels/osaf/contentmodel/tests/TestStamping.py:1.2 chandler/parcels/osaf/contentmodel/tests/TestStamping.py:1.3
--- chandler/parcels/osaf/contentmodel/tests/TestStamping.py:1.2	Sun Aug  8 19:13:24 2004
+++ chandler/parcels/osaf/contentmodel/tests/TestStamping.py	Fri Sep  3 15:54:06 2004
@@ -2,8 +2,8 @@
 Unit tests for notes parcel
 """
 
-__revision__  = "$Revision: 1.2 $"
-__date__      = "$Date: 2004/08/09 02:13:24 $"
+__revision__  = "$Revision: 1.3 $"
+__date__      = "$Date: 2004/09/03 22:54:06 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -71,7 +71,7 @@
     def assertKinds(self, item, kindsList):
         self.assertAttributes(item)
         for kind in kindsList:
-            self.assert_(item.itsKind.isKindOf(kind))
+            self.assert_(item.isItemOf(kind))
 
     def traverseStampSquence(self, item, sequence):
         for operation, stampKind in sequence:
@@ -85,7 +85,7 @@
             item.StampKind(operation, stampKind)
             self.assertAttributes(item)
             if operation == 'add':
-                self.assert_(item.itsKind.isKindOf(stampKind))
+                self.assert_(item.isItemOf(stampKind))
 
     def testStamping(self):
         # Make sure the contentModel is loaded.
@@ -166,7 +166,7 @@
                                           (remove, eventMixin),
                                           (add, taskMixin),
                                           (remove, mailMixin)))
-        self.assert_(aTask.itsKind.isKindOf(taskKind))
+        self.assert_(aTask.isItemOf(taskKind))
 
         # check stamping on an Event
         anEvent = Calendar.CalendarEvent("anEvent")
@@ -179,7 +179,7 @@
                                             (remove, mailMixin),
                                             (add, eventMixin),
                                             (remove, taskMixin)))
-        self.assert_(anEvent.itsKind.isKindOf(eventKind))
+        self.assert_(anEvent.isItemOf(eventKind))
 
         # check stamping on a Mail Message
         aMessage = Mail.MailMessage("aMessage")
@@ -188,7 +188,7 @@
                                              (add, taskMixin),
                                              (remove, eventMixin),
                                              (remove, taskMixin)))
-        self.assert_(aMessage.itsKind.isKindOf(mailKind))
+        self.assert_(aMessage.isItemOf(mailKind))
 
         # now mixin some arbitrary Kind
         anotherKind = self.rep.findPath('//parcels/osaf/framework/blocks/Block')
@@ -221,7 +221,7 @@
         if testFailureCases:
             anotherEvent = Calendar.CalendarEvent("anotherEvent")
             self.setAttributes(anotherEvent)
-            self.assert_(anotherEvent.itsKind.isKindOf(eventKind))
+            self.assert_(anotherEvent.isItemOf(eventKind))
             try:
                 # double stamping
                 self.traverseStampSquence(anotherEvent, ((add, mailMixin),

Index: chandler/parcels/osaf/contentmodel/ItemCollection.py
diff -u chandler/parcels/osaf/contentmodel/ItemCollection.py:1.9 chandler/parcels/osaf/contentmodel/ItemCollection.py:1.10
--- chandler/parcels/osaf/contentmodel/ItemCollection.py:1.9	Tue Aug 24 10:48:11 2004
+++ chandler/parcels/osaf/contentmodel/ItemCollection.py	Fri Sep  3 15:54:05 2004
@@ -1,11 +1,10 @@
-__revision__  = "$Revision: 1.9 $"
-__date__      = "$Date: 2004/08/24 17:48:11 $"
+__revision__  = "$Revision: 1.10 $"
+__date__      = "$Date: 2004/09/03 22:54:05 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
-import repository.item.Item as Item
+import osaf.contentmodel.ContentModel as ContentModel
 import application.Globals as Globals
-
 """
  * Need to dirty the collection when the rule attribute is changed
  * think about implementing the full Set API
@@ -15,7 +14,7 @@
 log = logging.getLogger("ItemCollection")
 log.setLevel(logging.INFO)
 
-class ItemCollection(Item.Item):
+class ItemCollection(ContentModel.ContentItem):
     def __init__(self, name=None, parent=None, kind=None):
         if not parent:
             parent = Globals.repository.findPath('//userdata/contentitems')
@@ -159,7 +158,8 @@
         # post collection_changed notification
         self.getRepositoryView().findPath('//parcels/osaf/contentmodel/collection_changed').Post( {'collection' : self.itsUUID} )
 
-
+    def shareSend (self):
+        self.messageMainView ('ShareCollection', self) # ==> MainView.ShareCollection (self)
 
 class NamedCollection(ItemCollection):
     def __init__(self, name=None, parent=None, kind=None):

Index: chandler/parcels/osaf/framework/blocks/detail/Detail.py
diff -u chandler/parcels/osaf/framework/blocks/detail/Detail.py:1.24 chandler/parcels/osaf/framework/blocks/detail/Detail.py:1.25
--- chandler/parcels/osaf/framework/blocks/detail/Detail.py:1.24	Sun Aug 29 02:08:43 2004
+++ chandler/parcels/osaf/framework/blocks/detail/Detail.py	Fri Sep  3 15:54:07 2004
@@ -1,5 +1,5 @@
-__version__ = "$Revision: 1.24 $"
-__date__ = "$Date: 2004/08/29 09:08:43 $"
+__version__ = "$Revision: 1.25 $"
+__date__ = "$Date: 2004/09/03 22:54:07 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -8,8 +8,10 @@
 import osaf.framework.blocks.Block as Block
 import osaf.framework.blocks.DynamicContainerBlocks as DynamicContainerBlocks
 import osaf.framework.blocks.ControlBlocks as ControlBlocks
+import osaf.framework.sharing.Sharing as Sharing
 import osaf.contentmodel.mail.Mail as Mail
 import osaf.contentmodel.ContentModel as ContentModel
+import osaf.contentmodel.ItemCollection as ItemCollection
 import osaf.contentmodel.tasks.Task as Task
 import osaf.contentmodel.calendar.Calendar as Calendar
 import repository.item.Query as Query
@@ -93,7 +95,7 @@
         super(DetailRoot, self).onDestroyWidget ()
         showReentrant (self)
 
-    def onSendMailMessageEvent (self, notification):
+    def onSendShareItemEvent (self, notification):
         item = self.selectedItem()
         item.shareSend() # tell the ContentItem to share/send itself.
 
@@ -133,9 +135,12 @@
 
     def synchronizeItemDetail (self, item):
         # if there is an item, we should show ourself, else hide
-        shouldShow = item is not None
+        shouldShow = self.shouldShow (item)
         return self.show(shouldShow)
-        
+    
+    def shouldShow (self, item):
+        return item is not None
+
     def show (self, shouldShow):
         # if the show status has changed, tell our widget, and return True
         try:
@@ -203,7 +208,8 @@
       Static Text that displays the name of the selected item's Attribute
     """
     def staticTextLabelValue (self, item):
-        redirectAttr = item.getAttributeAspect(self.whichAttribute(), 'redirectTo')
+        redirectName = self.whichAttribute ()
+        redirectAttr = item.getAttributeAspect(redirectName, 'redirectTo')
         if redirectAttr is None:
             redirectAttr = '  '
         else:
@@ -213,25 +219,12 @@
 class LabeledTextAttributeBlock (ControlBlocks.ContentItemDetail):
     def synchronizeItemDetail(self, item):
         whichAttr = self.selectedItemsAttribute
-        try:
-            attr = item.getAttributeValue(whichAttr)
-            self.isShown = attr is not None
-        except AttributeError:
-            self.isShown = item.hasAttributeAspect(whichAttr, 'redirectTo')
+        if item is None:
+            self.isShown = False
+        else:
+            self.isShown = item.itsKind.hasAttribute(whichAttr)
         self.synchronizeWidget()
 
-class MailMessageBlock (DetailSynchronizer, ControlBlocks.ContentItemDetail):
-    """
-    A block whose contents are shown only when the item is a Mail Message.
-    """
-    def synchronizeItemDetail(self, item):
-        mailKind = Mail.MailParcel.getMailMessageKind ()
-        try:
-            shouldShow = item.itsKind.isKindOf (mailKind)
-        except AttributeError:
-            shouldShow = False
-        return self.show(shouldShow)
-
 class MarkupBar (DetailSynchronizer, DynamicContainerBlocks.Toolbar):
     """   
       Markup Toolbar, for quick control over Items.
@@ -246,7 +239,7 @@
         # Rekind the item by adding or removing the associated Mixin Kind
         tool = notification.data['sender']
         item = self.selectedItem()
-        isANoteKind = item.itsKind.isKindOf(ContentModel.ContentModel.getNoteKind())
+        isANoteKind = item.isItemOf(ContentModel.ContentModel.getNoteKind())
         if not isANoteKind:
             return
         if item is not None:
@@ -265,7 +258,7 @@
     def onButtonPressedUpdateUI (self, notification):
         item = self.selectedItem()
         if item is not None:
-            enable = item.itsKind.isKindOf(ContentModel.ContentModel.getNoteKind())
+            enable = item.isItemOf(ContentModel.ContentModel.getNoteKind())
         else:
             enable = False
         notification.data ['Enable'] = enable
@@ -285,7 +278,7 @@
     def synchronizeItemDetail (self, item):
         # toggle this button to reflect the kind of the selected item
         shouldToggleBasedOnClass = isinstance(item, self.stampMixinClass())
-        shouldToggleBasedOnKind = item.itsKind.isKindOf(self.stampMixinKind())
+        shouldToggleBasedOnKind = item.isItemOf(self.stampMixinKind())
         assert shouldToggleBasedOnClass == shouldToggleBasedOnKind, \
                "Class/Kind mismatch for class %s, kind %s" % (item.__class__, item.itsKind)
         self.dynamicParent.widget.ToggleTool(self.toolID, shouldToggleBasedOnKind)
@@ -375,6 +368,14 @@
     """
     Body attribute of a ContentItem, e.g. a Note
     """
+    def shouldShow (self, item):
+        if item is None:
+            return False
+        # need to show even if there is no value, so we test
+        # the kind to see if it knows about the attribute.
+        knowsBody = item.itsKind.hasAttribute("body")
+        return knowsBody
+
     def saveAttributeFromWidget (self, item, widget):  
         textType = item.getAttributeAspect('body', 'type')
         widgetText = widget.GetValue()
@@ -423,7 +424,10 @@
         widget.SetValue (', '.join (processedAddresses))
 
     def loadAttributeIntoWidget (self, item, widget):
-        whoString = item.ItemWhoString ()
+        try:
+            whoString = item.ItemWhoString ()
+        except AttributeError:
+            whoString = ""
         widget.SetValue (whoString)
 
 class FromEditField (EditTextAttribute):
@@ -431,7 +435,10 @@
     def saveAttributeFromWidget(self, item, widget):  
         pass       
     def loadAttributeIntoWidget(self, item, widget):
-        whoString = item.ItemWhoFromString ()
+        try:
+            whoString = item.ItemWhoFromString ()
+        except AttributeError:
+            whoString = ''
         widget.SetValue (whoString)
 
 class EditRedirectAttribute (EditTextAttribute):
@@ -449,4 +456,44 @@
             value = ''
         widget.SetValue(value)
 
+class SendShareButton (DetailSynchronizer, ControlBlocks.Button):
+    def shouldShow (self, item):
+        if item is None:
+            return False
+        # if the item is a MailMessageMixin, we should show ourself
+        shouldShow = item.isItemOf(Mail.MailParcel.getMailMessageMixinKind())
+        # if the item is a collection, we should show ourself
+        shouldShow = shouldShow or isinstance (item, ItemCollection.ItemCollection)
+        return shouldShow
+
+    def synchronizeItemDetail (self, item):
+        # if the button should be visible, enable/disable
+        if self.shouldShow (item):
+            if isinstance (item, ItemCollection.ItemCollection):
+                # collection: label should read "share"
+                label = "Share"
+                # disable this button if the collection is already shared
+                try:
+                    shouldEnable = not Sharing.isShared (item)
+                except AttributeError:
+                    shouldEnable = True
+                else:
+                    if not shouldEnable:
+                        label = "Shared"
+            else:
+                # not a collection, so it's probably Mail
+                label = "Send"
+                shouldEnable = True
+                try:
+                    dateSent = item.dateSent
+                except AttributeError:
+                    dateSent = None
+                if dateSent is not None:
+                    label = "Sent"
+                    shouldEnable = False
+            self.widget.Enable (shouldEnable)
+            self.widget.SetLabel (label)
+        return super (SendShareButton, self).synchronizeItemDetail (item)
+
+
 

Index: chandler/parcels/osaf/contentmodel/parcel.xml
diff -u chandler/parcels/osaf/contentmodel/parcel.xml:1.59 chandler/parcels/osaf/contentmodel/parcel.xml:1.60
--- chandler/parcels/osaf/contentmodel/parcel.xml:1.59	Fri Aug 27 09:52:51 2004
+++ chandler/parcels/osaf/contentmodel/parcel.xml	Fri Sep  3 15:54:05 2004
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 
 <!-- Parcel manifest for Pim Schema -->
-<!-- $Revision: 1.59 $ -->
-<!-- $Date: 2004/08/27 16:52:51 $ -->
+<!-- $Revision: 1.60 $ -->
+<!-- $Date: 2004/09/03 22:54:05 $ -->
 <!-- Copyright (c) 2003-2004 Open Source Applications Foundation -->
 <!-- License: http://osafoundation.org/Chandler_0.1_license_terms.htm -->
 
@@ -440,6 +440,14 @@
     <core:displayName>Item Collection</core:displayName>
     <core:attributes itemref="collectionOwner"/>
 
+    <core:Attribute itsName="who">
+      <redirectTo>sharees</redirectTo>
+    </core:Attribute>
+
+    <core:Attribute itsName="about">
+      <redirectTo>displayName</redirectTo>
+    </core:Attribute>
+
     <core:Cloud itsName="DefaultCloud">
         <core:Endpoint itsName="collectionOwner">
             <attribute value="collectionOwner"/>

Index: chandler/parcels/osaf/contentmodel/ContentModel.py
diff -u chandler/parcels/osaf/contentmodel/ContentModel.py:1.29 chandler/parcels/osaf/contentmodel/ContentModel.py:1.30
--- chandler/parcels/osaf/contentmodel/ContentModel.py:1.29	Wed Sep  1 12:25:43 2004
+++ chandler/parcels/osaf/contentmodel/ContentModel.py	Fri Sep  3 15:54:05 2004
@@ -1,8 +1,8 @@
 """ Classes used for contentmodel parcel and kinds.
 """
 
-__revision__  = "$Revision: 1.29 $"
-__date__      = "$Date: 2004/09/01 19:25:43 $"
+__revision__  = "$Revision: 1.30 $"
+__date__      = "$Date: 2004/09/03 22:54:05 $"
 __copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -531,6 +531,20 @@
         import mail.Mail as Mail
         return Mail.EmailAddress.getCurrentMeEmailAddress ()
 
+    def messageMainView (cls, methodName, *args, **keywords):
+        messageMainViewEvent = Globals.repository.findPath \
+                             ('//parcels/osaf/framework/blocks/Events/MessageMainView')
+        data = {}
+        data['__methodName'] = methodName
+        data['__args'] = args
+        data['__keys'] = keywords
+        Globals.mainView.Post (messageMainViewEvent, data)
+    messageMainView = classmethod (messageMainView)
+
+    def setStatusText (cls, message):
+        cls.messageMainView ('setStatusText', message)
+    setStatusText = classmethod (setStatusText)
+
 class Project(Item.Item):
     def __init__(self, name=None, parent=None, kind=None):
         if not parent:

Index: chandler/parcels/osaf/framework/blocks/Events/parcel.xml
diff -u chandler/parcels/osaf/framework/blocks/Events/parcel.xml:1.49 chandler/parcels/osaf/framework/blocks/Events/parcel.xml:1.50
--- chandler/parcels/osaf/framework/blocks/Events/parcel.xml:1.49	Wed Sep  1 12:25:44 2004
+++ chandler/parcels/osaf/framework/blocks/Events/parcel.xml	Fri Sep  3 15:54:08 2004
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 
-<!-- $Revision: 1.49 $ -->
-<!-- $Date: 2004/09/01 19:25:44 $ -->
+<!-- $Revision: 1.50 $ -->
+<!-- $Date: 2004/09/03 22:54:08 $ -->
 <!-- Copyright (c) 2003 Open Source Applications Foundation -->
 <!-- License: http://osafoundation.org/Chandler_0.1_license_terms.htm -->
 
@@ -47,6 +47,7 @@
     <subscribeAlwaysEvents itemref="events:CommitRepository"/>
     <subscribeAlwaysEvents itemref="events:AboutChandler"/>    
     <subscribeAlwaysEvents itemref="events:SelectedDateChanged"/>
+    <subscribeAlwaysEvents itemref="events:MessageMainView"/>
   </EventList>
 
   <BlockEvent itsName="NULL">
@@ -174,4 +175,10 @@
     <dispatchEnum>ActiveViewBubbleUp</dispatchEnum>
   </BlockEvent>
 
+  <BlockEvent itsName="MessageMainView">
+    <description>A general event to call a method in the Main View. </description>
+    <dispatchEnum>SendToBlock</dispatchEnum>
+    <dispatchToBlock itemref="doc:MainView"/>
+  </BlockEvent>
+
 </core:Parcel>

Index: chandler/parcels/osaf/contentmodel/mail/parcel.xml
diff -u chandler/parcels/osaf/contentmodel/mail/parcel.xml:1.57 chandler/parcels/osaf/contentmodel/mail/parcel.xml:1.58
--- chandler/parcels/osaf/contentmodel/mail/parcel.xml:1.57	Sun Aug 29 02:08:41 2004
+++ chandler/parcels/osaf/contentmodel/mail/parcel.xml	Fri Sep  3 15:54:06 2004
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 
-<!-- $Revision: 1.57 $ -->
-<!-- $Date: 2004/08/29 09:08:41 $ -->
+<!-- $Revision: 1.58 $ -->
+<!-- $Date: 2004/09/03 22:54:06 $ -->
 <!-- Copyright (c) 2003-2004 Open Source Applications Foundation -->
 <!-- License: http://osafoundation.org/Chandler_0.1_license_terms.htm -->
 
@@ -792,14 +792,4 @@
 
     </Kind>
 
-    <notif:Event itsName="smtpSendErrorEvent">
-        <displayName value="SMTP Send Error Event" />
-        <description value="This event is posted from the mail system when an SMTP Send error happens." />
-    </notif:Event>
-
-    <notif:Event itsName="smtpSendSuccessEvent">
-        <displayName value="SMTP Send Success Event" />
-        <description value="This event is posted from the mail system when an SMTP Send succeeds." />
-    </notif:Event>
-
 </Parcel>

Index: chandler/parcels/osaf/views/main/Main.py
diff -u chandler/parcels/osaf/views/main/Main.py:1.47 chandler/parcels/osaf/views/main/Main.py:1.48
--- chandler/parcels/osaf/views/main/Main.py:1.47	Wed Sep  1 12:25:45 2004
+++ chandler/parcels/osaf/views/main/Main.py	Fri Sep  3 15:54:08 2004
@@ -1,5 +1,5 @@
-__version__ = "$Revision: 1.47 $"
-__date__ = "$Date: 2004/09/01 19:25:45 $"
+__version__ = "$Revision: 1.48 $"
+__date__ = "$Date: 2004/09/03 22:54:08 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -18,9 +18,10 @@
 import osaf.contentmodel.tests.GenerateItems as GenerateItems
 from repository.persistence.RepositoryError import VersionConflictError
 import repository.util.UUID as UUID
-import osaf.framework.sharing.Sharing
+import osaf.framework.sharing.Sharing as Sharing
 import repository.query.Query as Query
-
+import osaf.mail.sharing as MailSharing
+import osaf.framework.webdav.Dav as Dav
 
 
 class MainView(View):
@@ -59,7 +60,7 @@
 
     def onSharingSubscribeToCollectionEvent(self, notification):
         # Triggered from "Tests | Subscribe to collection..."
-        osaf.framework.sharing.Sharing.manualSubscribeToCollection()
+        Sharing.manualSubscribeToCollection()
 
     def onEditAccountPreferencesEvent (self, notification):
         # Triggered from "File | Prefs | Accounts..."
@@ -222,14 +223,14 @@
         # Triggered from "Test | Share collection..."
         collection = self.getSidebarSelectedCollection ()
         if collection is not None:
-            osaf.framework.sharing.Sharing.manualPublishCollection(collection)
+            Sharing.manualPublishCollection(collection)
 
     def onShareCollectionEventUpdateUI (self, notification):
         """
         Update the menu to reflect the selected collection name
         """
         # Only enable it user has set their webdav account up
-        if osaf.framework.sharing.Sharing.getWebDavPath() == None:
+        if Sharing.getWebDavPath() == None:
             notification.data ['Enable'] = False
             return
 
@@ -246,7 +247,7 @@
         # Triggered from "Test | Sync collection..."
         collection = self.getSidebarSelectedCollection ()
         if collection is not None:
-            osaf.framework.sharing.Sharing.syncCollection(collection)
+            Sharing.syncCollection(collection)
 
     def onSyncCollectionEventUpdateUI (self, notification):
         """
@@ -255,7 +256,7 @@
         collection = self.getSidebarSelectedCollection ()
         if collection is not None:
             menuTitle = 'Sync collection "%s"' % collection.displayName
-            if osaf.framework.sharing.Sharing.isShared(collection):
+            if Sharing.isShared(collection):
                 notification.data['Enable'] = True
             else:
                 notification.data['Enable'] = False
@@ -275,7 +276,7 @@
         collQuery.recursive = False
         for collection in collQuery:
             self.setStatusText ("synchronizing %s" % collection)
-            osaf.framework.sharing.Sharing.syncCollection(collection)
+            Sharing.syncCollection(collection)
 
         # synch mail
         self.setStatusText ("Getting new Mail")
@@ -309,7 +310,7 @@
         collection = self.getSidebarSelectedCollection ()
         if collection is not None:
             notification.data['Enable'] = True
-            if osaf.framework.sharing.Sharing.isShared(collection):
+            if Sharing.isShared (collection):
                 menuTitle = 'Manage collection "%s"' % collection.displayName
             else:
                 menuTitle = 'Share collection "%s"' % collection.displayName
@@ -320,3 +321,108 @@
 
     def setStatusText (self, statusMessage):
         Globals.wxApplication.mainFrame.SetStatusText (statusMessage)
+
+    def onMessageMainViewEvent (self, notification):
+        """
+          Handler for general message to call one of my methods.
+        Used by ContentModel when it wants to call a method here,
+        e.g. setStatusText.
+        """
+        # unpack the arguments
+        data = notification.data
+        args = data['__args']
+        keys = data['__keys']
+        methodName = data['__methodName']
+        # look up the method by name
+        try:
+            member = getattr (type(self), methodName)
+        except AttributeError:
+            return
+        # call the method with params
+        member (self, *args, **keys)
+
+    def ShareCollection (self, itemCollection):
+        # put a "committing" message into the status bar
+        self.setStatusText ('Committing changes...')
+
+        # commit changes, since we'll be switching to Twisted thread
+        Globals.repository.commit()
+    
+        # API to tell the collection to share itself.
+        self.setStatusText ("Sharing collection %s" % itemCollection.displayName)
+        try:
+            invitees = itemCollection.sharees
+        except AttributeError:
+            invitees = []
+        if len (invitees) == 0:
+            self.setStatusText ("No sharees!")
+            return
+
+        #account = Sharing.getWebDavAccount ()
+        if Sharing.isShared (itemCollection):
+            url = str (itemCollection.sharedURL)
+            self.setStatusText ("Collection %s is already shared - resharing" % itemCollection.displayName)
+        else:
+            path = Sharing.getWebDavPath()
+            if path:
+                url = "%s/%s" % (path, itemCollection.itsUUID)
+            else:
+                self.setStatusText ("You need to set up the server and path in the account dialog!")
+                return
+            url = url.encode ('utf-8')
+
+        # change the name to include "Shared"
+        if not "Shared" in itemCollection.displayName:
+            itemCollection.displayName = "%s (Shared)" % itemCollection.displayName
+
+        # Sync the collection with WebDAV
+        self.setStatusText ("accessing WebDAV server")
+        Dav.DAV(url).put(itemCollection)
+
+        # Send out sharing invites
+        inviteeStringsList = []
+        for entity in invitees:
+            inviteeStringsList.append (entity.emailAddress)
+        self.setStatusText ("inviting %s" % inviteeStringsList)
+        MailSharing.sendInvitation(url, itemCollection.displayName, inviteeStringsList)
+
+        # Done
+        self.setStatusText ("Sharing initiated.")
+
+    def displaySMTPSendSuccess (self, mailMessageUUID):
+        """
+          Called when the SMTP Send was successful.
+        """
+        mailMessageKind = Mail.MailParcel.getMailMessageKind ()
+        mailMessage = mailMessageKind.findUUID(mailMessageUUID)
+    
+        if mailMessage is not None and mailMessage.isOutbound:
+            self.setStatusText ('mailMessage "%s" sent.' % mailMessage.about)
+
+    def displaySMTPSendError (self, mailMessageUUID):
+        """
+          Called when the SMTP Send generated an error.
+        """
+        # Lookup the message
+        mailMessageKind = Mail.MailParcel.getMailMessageKind ()
+        mailMessage = mailMessageKind.findUUID(mailMessageUUID)
+    
+        if mailMessage is not None and mailMessage.isOutbound:
+            """DLDTBD - Select the message in CPIA"""
+    
+            errorStrings = []
+    
+            for error in mailMessage.deliveryExtension.deliveryErrors:
+                 errorStrings.append(error.errorString)
+   
+            str = "error"
+   
+            if len(errorStrings) > 1:
+                str = "errors"
+   
+            errorMessage = "The following %s occurred. %s" % (str, ', '.join(errorStrings))
+            errorMessage = errorMessage.encode ('utf-8')
+            self.setStatusText (errorMessage)
+            application.dialogs.Util.showAlert(Globals.wxApplication.mainFrame, errorMessage)
+            self.setStatusText ('')
+        
\ No newline at end of file

Index: chandler/parcels/osaf/contentmodel/mail/Mail.py
diff -u chandler/parcels/osaf/contentmodel/mail/Mail.py:1.22 chandler/parcels/osaf/contentmodel/mail/Mail.py:1.23
--- chandler/parcels/osaf/contentmodel/mail/Mail.py:1.22	Sun Aug 29 02:08:41 2004
+++ chandler/parcels/osaf/contentmodel/mail/Mail.py	Fri Sep  3 15:54:06 2004
@@ -1,8 +1,8 @@
 """ Classes used for Mail parcel kinds
 """
 
-__revision__  = "$Revision: 1.22 $"
-__date__      = "$Date: 2004/08/29 09:08:41 $"
+__revision__  = "$Revision: 1.23 $"
+__date__      = "$Date: 2004/09/03 22:54:06 $"
 __copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -39,8 +39,6 @@
                         makeContainer)
             
         self._setUUIDs()
-
-        SMTPDelivery.startup ()
         
     def getMailItemParent(cls, inbound=False):
 
@@ -285,19 +283,6 @@
         self.deliveryType = "SMTP"
         self.state = "DRAFT"
 
-    MAILPARCEL = "//parcels/osaf/contentmodel/mail/"
-
-    def startup (cls):
-        # subscribe to the error and success events, and specify class
-        # methods to be called.
-        event = Globals.repository.findPath(cls.MAILPARCEL + 'smtpSendErrorEvent')
-        Globals.notificationManager.Subscribe([event], UUID.UUID(),
-                                              cls._smtpSendErrorCallback)
-        event = Globals.repository.findPath(cls.MAILPARCEL + 'smtpSendSuccessEvent')
-        Globals.notificationManager.Subscribe([event], UUID.UUID(),
-                                              cls._smtpSendSuccessCallback)
-    startup = classmethod (startup)
-
     #XXX: Will want to expand state to an object with error or sucess code 
     #     desc string, and date
     def sendFailed(self):
@@ -323,50 +308,6 @@
         # announce to the UI thread that an error occurred
         self.announceSMTPSendSuccess (self.mailMessage.itsUUID)
 
-    def _smtpSendErrorCallback (notification):
-        """
-          Called from the UI thread when we receive this event, 
-        to display the error
-        """
-        mailMessageUUID = notification.data['messageUUID']
-
-        # Lookup the message
-        mailMessageKind = MailParcel.getMailMessageKind ()
-        mailMessage = mailMessageKind.findUUID(mailMessageUUID)
-    
-        if mailMessage is not None and mailMessage.isOutbound:
-            """DLDTBD - Switch the CPIA view to show the message"""
-    
-            errorStrings = []
-    
-            for error in mailMessage.deliveryExtension.deliveryErrors:
-                 errorStrings.append(error.errorString)
-   
-            str = "error"
-   
-            if len(errorStrings) > 1:
-                str = "errors"
-   
-            errorMessage = "The following %s occurred: %s" % (str, ', '.join(errorStrings))
-            application.dialogs.Util.showAlert(Globals.wxApplication.mainFrame, errorMessage)
-    _smtpSendErrorCallback = staticmethod (_smtpSendErrorCallback)
-
-    def _smtpSendSuccessCallback (notification):
-        """
-          Called from the UI Thread when send was a success, 
-        to give the user feedback.
-        """
-        mailMessageUUID = notification.data['messageUUID']
-
-        # Lookup the message
-        mailMessageKind = MailParcel.getMailMessageKind ()
-        mailMessage = mailMessageKind.findUUID(mailMessageUUID)
-    
-        if mailMessage is not None and mailMessage.isOutbound:
-            # DLDTBD - do something instead of printing when mail sent.
-            print 'mailMessage "%s" sent!' % mailMessage.about
-    _smtpSendSuccessCallback = staticmethod (_smtpSendSuccessCallback)
-
     def announceSMTPSendError (cls, uuid):
         """ 
           Call this method to announce that an SMTP sending error has
@@ -375,9 +316,8 @@
         """
     
         def _announceSMTPSendError (uuid):
-            # find and post a Chandler event to get back to the UI Thread
-            event = Globals.repository.findPath(cls.MAILPARCEL + 'smtpSendErrorEvent')
-            event.Post( { 'messageUUID' : uuid } )
+            # post a Chandler event to get back to the UI Thread
+            ContentModel.ContentItem.messageMainView ('displaySMTPSendError', uuid)
     
         # post an application event to call above
         Globals.wxApplication.PostAsyncEvent(_announceSMTPSendError, uuid)
@@ -388,8 +328,8 @@
             a success. This method is non-blocking. """
     
         def _announceSMTPSendSuccess (uuid):
-            event = Globals.repository.findPath(cls.MAILPARCEL + 'smtpSendSuccessEvent')
-            event.Post( { 'messageUUID' : uuid } )
+            # post a Chandler event to get back to the UI Thread
+            ContentModel.ContentItem.messageMainView ('displaySMTPSendSuccess', uuid)
     
         Globals.wxApplication.PostAsyncEvent(_announceSMTPSendSuccess, uuid)
     announceSMTPSendSuccess = classmethod (announceSMTPSendSuccess)
@@ -504,13 +444,20 @@
         """
           Share this item, or Send if it's an Email
         We assume we want to send this MailMessage here.
+        DLDTBD - move to MailMessageMixin
         """
+        # put a "committing" message into the status bar
+        self.setStatusText ('Committing changes...')
+
         # commit changes, since we'll be switching to Twisted thread
         Globals.repository.commit()
     
         # get default SMTP account
         account = self.defaultSMTPAccount ()
 
+        # put a sending message into the status bar
+        self.setStatusText ('Sending mail...')
+
         # Now send the mail
         import osaf.mail.smtp as smtp
         smtp.SMTPSender(account, self).sendMail()
@@ -621,20 +568,17 @@
         isValidAddress = message.isValidEmailAddress (address)
 
         # DLDTBD - switch on the better queries
+        # Need to override compare operators to use emailAddressesAreEqual, etc
         useBetterQuery = False
         if useBetterQuery:
 
             # get all addresses whose emailAddress or fullName match the param
             queryString = u'for i in "//parcels/osaf/contentmodel/mail/EmailAddress" \
-                          where contains(i.emailAddress,$0) or contains(i.fullName, $0)'
+                          where i.emailAddress =="$0" or i.fullName =="$0"'
             addrQuery = Query.Query (Globals.repository, queryString)
             addrQuery.args = [ address ]
-            addresses = addrQuery.execute ()
-            
-            try:
-                n = len (addresses)
-            except TypeError:
-                addresses = []
+            addresses = addrQuery
+
         else:
             # old slow query method
             emailAddressKind = MailParcel.getEmailAddressKind ()
@@ -722,14 +666,14 @@
         assert len (imapAccounts) == 1, "The EmailAddress %s is not being used in %d accounts!" \
                   %  (len (imapAccounts), meEmailAddress.emailAddress)
         account = imapAccounts.first()
-
-        # Create a fresh unused EmailAddress for editing
-        newMe = EmailAddress(clone=meEmailAddress) # a fresh unused EmailAddress
-
-        # Put the new EmailAddress into the account that owns "me",
-        account.replyToAddress = newMe
-        assert cls._capturedAccount is None, "capturedAccount error"
-        cls._capturedAccount = account
+        if account:
+            # Create a fresh unused EmailAddress for editing
+            newMe = EmailAddress(clone=meEmailAddress) # a fresh unused EmailAddress
+    
+            # Put the new EmailAddress into the account that owns "me",
+            account.replyToAddress = newMe
+            assert cls._capturedAccount is None, "capturedAccount error"
+            cls._capturedAccount = account
     captureCurrentMeEmailAddress = classmethod (captureCurrentMeEmailAddress)
 
     # the captured IMAP account is save here during capture/release
@@ -741,23 +685,23 @@
         If unchanged, we revert back to the old one.
         """
         # get the new user-edited "me" address out of the account
-        assert cls._capturedAccount is not None, "capuredAccount error"
-        account = cls._capturedAccount
-        cls._capturedAccount = None
-        newMeCandidate = account.replyToAddress
-
-        """
-          We'll want to use whatever existing address matches the user's edit.
-        Could be the new fresh one, could be an existing reuse, 
-        and could be the old one if no edit was made. 
-        If we're not using the new fresh copy, then we delete it.
-        """
-        theNewMe = cls.getEmailAddress (newMeCandidate.emailAddress)
-        account.replyToAddress = theNewMe
-        if theNewMe is not newMeCandidate:
-            newMeCandidate.delete ()
-
-        # Invalidate the "me" emailAddress string cache in case there was an edit.
-        cls._theMeAddress = None
+        if cls._capturedAccount is not None:
+            account = cls._capturedAccount
+            cls._capturedAccount = None
+            newMeCandidate = account.replyToAddress
+    
+            """
+              We'll want to use whatever existing address matches the user's edit.
+            Could be the new fresh one, could be an existing reuse, 
+            and could be the old one if no edit was made. 
+            If we're not using the new fresh copy, then we delete it.
+            """
+            theNewMe = cls.getEmailAddress (newMeCandidate.emailAddress)
+            account.replyToAddress = theNewMe
+            if theNewMe is not newMeCandidate:
+                newMeCandidate.delete ()
+    
+            # Invalidate the "me" emailAddress string cache in case there was an edit.
+            cls._theMeAddress = None
     releaseCurrentMeEmailAddress = classmethod (releaseCurrentMeEmailAddress)
 

Index: chandler/parcels/osaf/framework/blocks/detail/parcel.xml
diff -u chandler/parcels/osaf/framework/blocks/detail/parcel.xml:1.20 chandler/parcels/osaf/framework/blocks/detail/parcel.xml:1.21
--- chandler/parcels/osaf/framework/blocks/detail/parcel.xml:1.20	Thu Aug 19 12:43:54 2004
+++ chandler/parcels/osaf/framework/blocks/detail/parcel.xml	Fri Sep  3 15:54:07 2004
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 
-<!-- $Revision: 1.20 $ -->
-<!-- $Date: 2004/08/19 19:43:54 $ -->
+<!-- $Revision: 1.21 $ -->
+<!-- $Date: 2004/09/03 22:54:07 $ -->
 <!-- Copyright (c) 2003-2004 Open Source Applications Foundation -->
 <!-- License: http://osafoundation.org/Chandler_0.1_license_terms.htm -->
 
@@ -66,9 +66,9 @@
     <dispatchToBlock itemref="doc:MarkupBar"/>
   </BlockEvent>
 
-  <BlockEvent itemName="SendMailMessage">
+  <BlockEvent itemName="SendShareItem">
     <dispatchEnum>SendToBlock</dispatchEnum>
-    <methodName>onSendMailMessageEvent</methodName>
+    <methodName>onSendShareItemEvent</methodName>
     <dispatchToBlock itemref="doc:DetailRootTemplate"/>
   </BlockEvent>
 
@@ -80,7 +80,7 @@
   <SelectionContainer itemName="DetailRootTemplate"
                      itemClass="osaf.framework.blocks.detail.Detail.DetailRoot">
     <childrenBlocks itemref="doc:DetailTrunk"/>
-    <subscribeWhenVisibleEvents itemref="doc:SendMailMessage"/>
+    <subscribeWhenVisibleEvents itemref="doc:SendShareItem"/>
     <subscribeWhenVisibleEvents itemref="doc:NULL"/>
   </SelectionContainer>
 
@@ -90,7 +90,7 @@
     <childrenBlocks itemref="doc:FromAndToArea"/>
     <childrenBlocks itemref="doc:CoreIndent"/>
     <childrenBlocks itemref="doc:NotesArea"/>
-    <childrenBlocks itemref="doc:SendBar"/>
+    <childrenBlocks itemref="doc:SendShareButton"/>
     <!-- Attributes -->
     <orientationEnum>Vertical</orientationEnum>
     <size>80,20</size>
@@ -434,32 +434,10 @@
     <minimumSize>380, 120</minimumSize>
   </EditText>
 
-  <!-- Send Bar -->
-  <ContentItemDetail itsName="SendBar"
-                     itemClass="osaf.framework.blocks.detail.Detail.MailMessageBlock">
-    <childrenBlocks itemref="doc:NotifyRadioBox"/>
-    <childrenBlocks itemref="doc:SendButton"/>
-    <!-- Attributes -->
-    <minimumSize>300,40</minimumSize>
-    <stretchFactor>1</stretchFactor>
-    <orientationEnum>Horizontal</orientationEnum>
-  </ContentItemDetail>
- 
-  <RadioBox itsName="NotifyRadioBox">
-    <!-- Attributes -->
-    <title>Notify</title>
-    <choices>All</choices>
-    <choices>New</choices>
-    <radioAlignEnum>Across</radioAlignEnum>
-    <itemsPerLine>2</itemsPerLine>
+  <!-- Send button -->
+  <Button itsName="SendShareButton"
+          itemClass="osaf.framework.blocks.detail.Detail.SendShareButton">
 
-    <size>200,24</size>
-    <minimumSize>200,30</minimumSize>
-    <border>2.0, 2.0, 2.0, 2.0</border>
-    <stretchFactor>0.0</stretchFactor>
-  </RadioBox>
-  
-  <Button itsName="SendButton">
     <!-- Attributes -->
     <title>Send</title>
     <buttonKind>Text</buttonKind>
@@ -467,7 +445,7 @@
     <size>60,30</size>
     <minimumSize>60,30</minimumSize>
     <border>2.0, 2.0, 2.0, 2.0</border>
-    <event itemref="doc:SendMailMessage"/>
+    <event itemref="doc:SendShareItem"/>
     <alignmentEnum>alignCenter</alignmentEnum>
     <stretchFactor>0.0</stretchFactor>
   </Button>



More information about the Commits mailing list