Sorry for all the email

I have created a patch (attached).  As far as I can tell, it works in 
windows.  I can't add all the columns to the task tree view, but it 
works well enough on windows.

Your new changes have effected the code, but it isn't tramatic.  See the 
comments in the code for potential issues.
I also am using eclipse tasks (FIXME: cz are mine).

I am going on vacation soon and I don't want to have to come back to it.

The feature seems to work well, but it could be tuned a little.  It 
definitely reduces the number of mouse clicks that I need.


Carl

Carl Zmola wrote:
> Frank,
>
> I just realized that the TaskEditorPage was removed.
> I think the subject page should be an editor page, but I have added the 
> needed fields and methods to it temporarily.
>
> I can't proceed testing right now until the windows column header issue 
> is fixed. 
> If you have a workaround, let me know and I will continue testing.  I 
> want to get this fix into the tree quickly before too much else changes.
>
> Carl
>
> Carl Zmola wrote:
>   
>> Frank,
>>
>> The editor;py changes have thrown me for a loop.
>> Before all task editor pages were of type: TaskEditorPage
>> Now the subject page isn't even an EditorPage.
>> Is this a mistake?
>>
>> I have some code and date that go into the EditorPage.
>>
>> An editor page knows what fields are contained in it, so it has a 
>> _fieldMap
>> In addition, they all have a setFocusForField and containsField method.
>> I can add these to Subject page manually, but it seems like the subject
>> page should be an editor page.
>>
>> Is TaskEditorPage going to go away entirely?
>>
>>  
>>     
>
>   

Index: taskcoachlib/gui/dialog/editor.py
===================================================================
--- taskcoachlib/gui/dialog/editor.py   (revision 1174)
+++ taskcoachlib/gui/dialog/editor.py   (working copy)
@@ -143,6 +143,8 @@
 class EditorPage(widgets.PanelWithBoxSizer):
     def __init__(self, parent, item, *args, **kwargs):
         super(EditorPage, self).__init__(parent, *args, **kwargs)
+        self._defaultControl=None
+        self._fieldMap={}   
         self._item = item
 
     def addHeaders(self, box):
@@ -154,6 +156,19 @@
         for header in headers:
             box.add(header)
 
+    def containsField(self,fieldname):
+        return fieldname in self._fieldMap.keys()
+
+    def setFocusForField(self, fieldname):        
+        ''' if a field has an associated control, set focus on that control.
+            if not, set focus to the default control.
+        '''
+        if self.containsField(fieldname):
+            self._fieldMap[fieldname].SetFocus()
+        else:
+            self._defaultControl.SetFocus()
+
+
     def ok(self):
         pass
 
@@ -177,7 +192,29 @@
         self.addPriorityEntry()
         self.addColorEntry()
         self.fit()
+        self._defaultControl=self._subjectEntry
+        self._fieldMap={}   #FIXME: cz: remove when subject page is an editor 
page
+        self._fieldMap['subject']    = self._subjectEntry
+        self._fieldMap['description']= self._descriptionEntry
+        self._fieldMap['priority']   = self._prioritySpinner
 
+    def containsField(self,fieldname):
+        #FIXME: cz: remove when subject page is an editor page
+        # print fieldname , "  ",fieldname in self._fieldMap.keys(),' ',self
+        return fieldname in self._fieldMap.keys()
+            
+    def setFocusForField(self, fieldname):        
+        #FIXME: cz: remove when subject page is an editor page
+        ''' if a field has an associated control, set focus on that control.
+            if not, set focus to the default control.
+        '''
+        if self.containsField(fieldname):
+            self._fieldMap[fieldname].SetFocus()
+        else:
+            self._defaultControl.SetFocus()
+
+
+
     def addSubjectEntry(self):
         self._subjectEntry = widgets.SingleLineTextCtrl(self, 
             self._item.subject())
@@ -223,6 +260,7 @@
             entry = DateEntry(datesBox, taskMethod(),
                               callback=self.onDateChanged)
             setattr(self, '_%sEntry'%taskMethodName, entry)
+            self._fieldMap[taskMethodName]= entry
             datesBox.add(entry)
             if task.children():
                 recursiveEntry = DateEntry(datesBox,
@@ -236,7 +274,8 @@
         reminderBox.add(_('Reminder'))
         self._reminderDateTimeEntry = widgets.DateTimeCtrl(reminderBox,
             task.reminder())
-        # If the users has not set a reminder, make sure that the default
+        self._fieldMap['reminder']= self._reminderDateTimeEntry
+        # If the users has not set a reminder, make sure that the default 
         # date time in the reminder entry is a reasonable suggestion:
         if self._reminderDateTimeEntry.GetValue() == date.DateTime.max:
             self.suggestReminder()
@@ -249,6 +288,7 @@
         panelSizer = wx.BoxSizer(wx.HORIZONTAL)
         self._recurrenceEntry = wx.Choice(panel,
             choices=[_('None'), _('Daily'), _('Weekly'), _('Monthly'), 
_('Yearly')])
+        self._fieldMap['recurrence']= self._recurrenceEntry        
         self._recurrenceEntry.Bind(wx.EVT_CHOICE, self.onRecurrenceChanged)
         panelSizer.Add(self._recurrenceEntry, flag=wx.ALIGN_CENTER_VERTICAL)
         panelSizer.Add((3,-1))
@@ -296,7 +336,8 @@
             box.fit()
             self.add(box, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
         self.fit()
-
+        self._defaultControl=self._reminderDateTimeEntry  #  need to confirm 
this is the right box
+        
     def onRecurrenceChanged(self, event):
         event.Skip()
         recurrenceOn = event.String != _('None')
@@ -419,6 +460,21 @@
             box.fit()
             self.add(box, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
         self.fit()
+        self._fieldMap['budget']=self._budgetEntry
+        #FIXME: cz: ?  The calculated fields now actually set focus on budget 
entry
+        # behavior can be chaned by adding a separate map, that can be checked 
in containsField
+        # or changing the setFocusForField method to recognize NONE for field
+        # this behavior will be OK for now.         
+        self._fieldMap['timeSpent']=self._budgetEntry
+        self._fieldMap['totalTimeSpent']=self._budgetEntry
+        self._fieldMap['totalBudget']=self._budgetEntry
+        self._fieldMap['timeLeft']=self._budgetEntry
+        self._fieldMap['budgetLeft']=self._budgetEntry
+        self._fieldMap['totalTimeLeft']=self._budgetEntry
+        self._fieldMap['hourlyFee']=self._hourlyFeeEntry
+        self._fieldMap['revenue']=self._hourlyFeeEntry
+        self._fieldMap['totalRevenue']=self._hourlyFeeEntry
+        self._defaultControl = self._budgetEntry
 
     def ok(self):
         self._item.setBudget(self._budgetEntry.get())
@@ -466,6 +522,8 @@
         categoriesBox.fit()
         self.add(categoriesBox)
         self.fit()
+        self._fieldMap['categories']=self._treeCtrl
+        self._fieldMap['totalCategories']=self._treeCtrl # readOnlyFiled maps 
to base 
 
     def getCategoryWithIndex(self, index):
         children = self.__categories.rootItems()
@@ -520,6 +578,8 @@
         self.add(notesBox, proportion=1, flag=wx.EXPAND|wx.ALL,
                  border=5)
         self.TopLevelParent.Bind(wx.EVT_CLOSE, self.onClose)
+        self._fieldMap['note']=self.noteViewer # not sure of the fieldname
+        self._defaultControl=self.noteViewer # not sure of the fieldname
         self.fit()
         
     def onClose(self, event):
@@ -542,6 +602,7 @@
         self._listCtrl.SetColumnWidth(0, 500)
         attachmentBox.add(self._listCtrl, flag=wx.EXPAND|wx.ALL, proportion=1)
         self._listData = {}
+        self._fieldMap['attachments']=self._listCtrl
 
         boxSizer = wx.BoxSizer(wx.HORIZONTAL)
         self._buttonBox = widgets.ButtonBox(attachmentBox,
@@ -695,6 +756,8 @@
         behaviorBox.fit()
         self.add(behaviorBox, border=5)
         self.fit()
+        self._defaultControl=choice
+        self._fieldMap['behavior']=choice
 
     def ok(self):
         self._item.shouldMarkCompletedWhenAllChildrenCompleted = \
@@ -926,7 +989,8 @@
     def __init__(self, parent, command, uiCommands, *args, **kwargs):
         self._uiCommands = uiCommands
         self._command = command
-        super(EditorWithCommand, self).__init__(parent, command.name(), *args, 
**kwargs)
+        bitmap=kwargs.pop('bitmap','edit') # hack due to bitmap being a 
positional arg now
+        super(EditorWithCommand, self).__init__(parent, command.name(), 
bitmap, *args, **kwargs)
         self.setFocusOnFirstEntry()
         
     def setFocusOnFirstEntry(self):
@@ -950,7 +1014,51 @@
         self._taskList = taskList
         self._categories = categories
         super(TaskEditor, self).__init__(parent, command, uiCommands, bitmap, 
*args, **kwargs)
+        self[0][0]._subjectEntry.SetSelection(-1, -1)
+        # This works on Linux Ubuntu 5.10, but fails silently on Windows XP:
+        self.setFocus(*args,**kwargs) 
+        # This works on Windows XP, but fails silently on Linux Ubuntu 5.10:
+        wx.CallAfter(self.setFocus,*args,**kwargs) 
+        # So we did just do it twice, guess it doesn't hurt
 
+    def setFocus(self, *args, **kwargs):
+        ''' select the correct page and correct control on a page
+            kwargs include:
+            Page --  index of page to select
+            Task --  index of task (in tabbed notebook)
+            Field -- field to highlight (overrides page)
+            '''
+        tsk=0
+        page=0
+        fieldname=''
+        #print args
+        #print kwargs
+        if kwargs.has_key('Task'):
+            tsk=kwargs['Task']
+            self.ChangeSelection(kwargs['Task'])    # always go to the first 
tab
+        if kwargs.has_key('Page'):
+            page=kwargs['Page']
+            selectCtrl= self[tsk][page]._defaultControl
+        if kwargs.has_key('Field'):
+            # lookup the what page the field is edite on.
+            fieldname=kwargs['Field']    
+            page=self.getFieldPage(fieldname)
+            self[tsk].ChangeSelection(page) # go to the second tab,  try by 
name.
+        self[tsk].ChangeSelection(page) # go to the second tab,  try by name.
+        self[tsk][page].setFocusForField(fieldname)
+
+    def getFieldPage(self,fieldname,task=0):
+        ''' return the page on which the field should be edited'''
+        page=0 #hard code the second page for sample
+        for  p in range((self[task]).GetPageCount()):
+            if self[task][p].containsField(fieldname):
+                return p
+        return page
+        
+    def addPages(self):
+        for task in self._command.items:
+            self.addPage(task)
+
     def addPage(self, task):
         page = TaskEditBook(self._interior, task, self._taskList,
             self._uiCommands, self._settings, self._categories)
Index: taskcoachlib/gui/mainwindow.py
===================================================================
--- taskcoachlib/gui/mainwindow.py      (revision 1174)
+++ taskcoachlib/gui/mainwindow.py      (working copy)
@@ -20,8 +20,7 @@
 from taskcoachlib import meta, patterns, widgets, command, help
 from taskcoachlib.i18n import _
 from taskcoachlib.domain import task, effort
-import viewer, viewercontainer, viewerfactory, toolbar, uicommand,\
-    remindercontroller
+import viewer, viewercontainer, viewerfactory, toolbar, 
uicommand,remindercontroller
 
 
 
Index: taskcoachlib/gui/uicommand.py
===================================================================
--- taskcoachlib/gui/uicommand.py       (revision 1174)
+++ taskcoachlib/gui/uicommand.py       (working copy)
@@ -1142,8 +1142,49 @@
             menuText=taskList.editItemMenuText, 
             helpText=taskList.editItemHelpText, *args, **kwargs)
 
-    def doCommand(self, event, show=True):
-        editor = self.viewer.editTaskDialog(bitmap=self.bitmap)
+    def onCommandActivate(self, event, field=''):
+        ''' 
+        this is a menu command, so we need to check for enabled, but we also 
want to 
+        pass in an optional field.
+        '''
+        #FIXME: cz: I put this in early in the development cycle when adding 
the 'field' parameter
+        # I am not sure if it is necessary
+        if self.enabled(event):
+            self.doCommand(event, True, field)
+
+
+
+    def doCommand(self, event, show=True, field=''):
+        ''' 
+        open the task editor
+
+        If the mouse has been clicked, check to see what column it is in.
+        open the appropriate page on the edit task dialog.
+        '''
+        #
+        columnName='subject'
+        
+        if 'columnName' in dir(event):
+            columnName=event.columnName
+        #FIXME: cz: remove event.columnHeader everywhere, not used
+        try: #FIXME: cz: remove debug code
+            print 'doTaskEdit', columnName
+        except e: # AttributeError: # this is debug code.  column name and 
column header might not exist.
+            pass  #just ignore exceptions for now.
+        #   The following code will need to get executed someplace (for 
treecontroller, but 
+        #   The event should carry the field to edit if appropriate
+        #        pos = event.GetPosition()
+        #        item, flags, col = self.tree.HitTest(pos)
+        #        if item:
+        #
+        #    Page should be the page that the column that is clicked on can be 
+        #    found on.  This parameter should change to "FieldToEdit and the 
editor should
+        #    know where the field resides.
+        #    can we pass the information in the event?
+        editor = self.viewer.editTaskDialog(bitmap=self.bitmap, 
+                                            Field=columnName,
+                                            Task=0,  # This is always 
appropriate.
+                                            Page=1)  
         editor.Show(show)
 
 
Index: taskcoachlib/gui/viewer.py
===================================================================
--- taskcoachlib/gui/viewer.py  (revision 1174)
+++ taskcoachlib/gui/viewer.py  (working copy)
@@ -1064,7 +1064,7 @@
         return dialog.editor.TaskEditor(wx.GetTopLevelParent(self),
             command.EditTaskCommand(self.list, self.curselection()),
             self.list, self.uiCommands, self.settings, self.categories,
-            bitmap=kwargs['bitmap'])
+            *args,**kwargs)
     
     editTaskDialog = editItemDialog
     
Index: taskcoachlib/widgets/dialog.py
===================================================================
--- taskcoachlib/widgets/dialog.py      (revision 1174)
+++ taskcoachlib/widgets/dialog.py      (working copy)
@@ -94,7 +94,25 @@
     def addPages(self):
         raise NotImplementedError 
               
-        
+    def SetSelection(self,tag_index):
+        ''' set the book's item by index.  Note that index can be numeric or 
name
+        This is the same signature that exists in the Notebook or Listbook 
allowing polymorphism
+
+        SetSelection has been Deprecated in wxWidgets.  Use Change Selection 
instead
+        '''
+        #FIXME: cz: did I add these?  I think my docstring and implementation 
don't agree
+        self._interior.SetSelection(index)
+
+    def ChangeSelection(self,index):
+        ''' set the book's item by index.  Note that index can be numeric or 
name
+        This is the same signature that exists in the Notebook or Listbook 
allowing polymorphism
+
+        SetSelection has been Deprecated in wxWidgets.  Use Change Selection 
instead
+        '''
+        #FIXME: cz: did I add these?  I think my docstring and implementation 
don't agree
+        self._interior.SetSelection(index)
+
+
 class NotebookDialog(BookDialog):
     def createInterior(self):
         return notebook.Notebook(self._panel)
Index: taskcoachlib/widgets/treectrl.py
===================================================================
--- taskcoachlib/widgets/treectrl.py    (revision 1174)
+++ taskcoachlib/widgets/treectrl.py    (working copy)
@@ -387,3 +387,23 @@
             item = self.GetNextVisible(item)
         return count
 
+    def onItemActivated(self, event):
+        ''' override TreeMixin default behavior
+            we know that there is a column, so use it.
+        '''    
+        
+        pos=self.ScreenToClient(wx.GetMousePosition())
+        item, flags, col = self.HitTest(pos)
+        if item:
+            # only get the column name if the hittest returned an item
+            # otherwise the item was activated from the menu or by 
doubleclicking
+            # on a portion of the treeview not containing a record.
+            #FIXME: cz Remove debug prints
+            print ('ItemActivated: column name %s, %s' % 
(self._getColumn(col).name(),self._getColumn(col).header() ))
+            print ('Flags: %s, Col:%s, Text: %s' % (flags, col, 
self.GetItemText(item, col)))
+            event.hitTestFlags=flags
+            #            event.column=col
+            event.columnName=self._getColumn(col).name()
+        self.editCommand(event)
+        event.Skip(False)
+

Reply via email to