[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