def sendMail(to, subject, body, cc=None, openURL=openfile.openFile): def unicode_quote(s): # This is like urllib.quote but leaves out Unicode characters, # which urllib.quote does not support. chars = [c if ord(c) >= 128 else urllib.quote(c) for c in s] return ''.join(chars) cc = cc or [] if isinstance(to, (str, unicode)): to = [to] # FIXME: Very strange things happen on MacOS X. If there is one # non-ASCII character in the body, it works. If there is more than # one, it fails. Maybe we should use Mail.app directly ? What if # the user uses something else ? if not operating_system.isMac(): body = unicode_quote(body) # Otherwise newlines disappear cc = map(unicode_quote, cc) to = map(unicode_quote, to) components = ['subject=%s' % subject, 'body=%s' % body] if cc: components.append('cc=%s' % ','.join(cc)) openURL(u'mailto:%s?%s' % (','.join(to), '&'.join(components)))
def getSimple(klass): """ Returns a notifier suitable for simple notifications. This defaults to Growl/Snarl/libnotify depending on their availability. """ if klass._enabled: if operating_system.isMac(): return klass.get("Growl") or klass.get("Task Coach") elif operating_system.isWindows(): return klass.get("Snarl") or klass.get("Task Coach") else: return klass.get("libnotify") or klass.get("Task Coach") else: class DummyNotifier(AbstractNotifier): def getName(self): return u"Dummy" def isAvailable(self): return True def notify(self, title, summary, bitmap, **kwargs): pass return DummyNotifier()
def __init__(self, *args, **kwargs): super(TaskReminderPage, self).__init__(columns=3, growableColumn=-1, *args, **kwargs) names = [] # There's at least one, the universal one for name in notify.AbstractNotifier.names(): names.append((name, name)) self.addChoiceSetting('feature', 'notifier', _('Notification system to use for reminders'), '', names, flags=(None, wx.ALL | wx.ALIGN_LEFT)) if operating_system.isMac() or operating_system.isGTK(): self.addBooleanSetting('feature', 'sayreminder', _('Let the computer say the reminder'), _('(Needs espeak)') if operating_system.isGTK() else '', flags=(None, wx.ALL | wx.ALIGN_LEFT, wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)) snoozeChoices = [(str(choice[0]), choice[1]) for choice in date.snoozeChoices] self.addChoiceSetting('view', 'defaultsnoozetime', _('Default snooze time to use after reminder'), '', snoozeChoices, flags=(None, wx.ALL | wx.ALIGN_LEFT)) self.addMultipleChoiceSettings('view', 'snoozetimes', _('Snooze times to offer in task reminder dialog'), date.snoozeChoices[1:], flags=(wx.ALIGN_TOP | wx.ALL, None)) # Don't offer "Don't snooze" as a choice self.fit()
def _createSpinCtrl(self, percentage): entry = widgets.SpinCtrl( self, value=percentage, min=0, max=100, size=(60 if operating_system.isMac() else 50, -1) ) for eventType in wx.EVT_SPINCTRL, wx.EVT_KILL_FOCUS: entry.Bind(eventType, self.onSpin) return entry
def getSimple(klass): """ Returns a notifier suitable for simple notifications. This defaults to Growl/Snarl/libnotify depending on their availability. """ if klass._enabled: if operating_system.isMac(): return klass.get('Growl') or klass.get('Task Coach') elif operating_system.isWindows(): return klass.get('Snarl') or klass.get('Task Coach') else: return klass.get('libnotify') or klass.get('Task Coach') else: class DummyNotifier(AbstractNotifier): def getName(self): return u'Dummy' def isAvailable(self): return True def notify(self, title, summary, bitmap, **kwargs): pass return DummyNotifier()
def __init__(self): if operating_system.isMac(): self.__binary = 'say' elif operating_system.isGTK(): self.__binary = 'espeak' self.__texts_to_say = [] self.__current_speech_process = None
def test_initial_size(self): # See MainWindowTest... width, height = self.frame.GetSizeTuple() if operating_system.isMac(): # pragma: no cover width, height = self.frame.GetClientSize() height -= 18 self.assertEqual((width, height), self.settings.getvalue(self.section, "size"))
def __init__(self, iocontroller=None, *args, **kwargs): self.iocontroller = iocontroller super(SyncMLPreferences, self).__init__(bitmap='wrench_icon', *args, **kwargs) self.SetSize((700, -1)) if operating_system.isMac(): self.CentreOnParent()
def test_change_size(self): self.frame.Maximize(False) if operating_system.isMac(): self.frame.SetClientSize((123, 200)) else: self.frame.ProcessEvent(wx.SizeEvent((123, 200))) self.assertEqual((123, 200), self.settings.getvalue(self.section, "size"))
def __init__(self, settings=None, *args, **kwargs): self.settings = settings super(Preferences, self).__init__(bitmap='wrench_icon', *args, **kwargs) if operating_system.isMac(): self.CentreOnParent()
class TaskList(TaskListQueryMixin, categorizable.CategorizableContainer): # FIXME: TaskList should be called TaskCollection or TaskSet newItemMenuText = _('&New task...') + ( '\tINSERT' if not operating_system.isMac() else '\tCtrl+N') newItemHelpText = help.taskNew def nrBeingTracked(self): return len(self.tasksBeingTracked()) def tasksBeingTracked(self): return [eachTask for eachTask in self if eachTask.isBeingTracked()] def efforts(self): result = [] for task in self: # pylint: disable=W0621 result.extend(task.efforts()) return result def originalLength(self): ''' Provide a way for bypassing the __len__ method of decorators. ''' return len([t for t in self if not t.isDeleted()]) def minPriority(self): return min(self.__allPriorities()) def maxPriority(self): return max(self.__allPriorities()) def __allPriorities(self): return [task.priority() for task in self if not task.isDeleted()] or (0, ) # pylint: disable=W0621
def pathToDocumentsDir(): if operating_system.isWindows(): from win32com.shell import shell, shellcon try: return shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_PERSONAL) except: # Yes, one of the documented ways to get this sometimes fail with "Unspecified error". Not sure # this will work either. # Update: There are cases when it doesn't work either; see support request #410... try: return shell.SHGetFolderPath(None, shellcon.CSIDL_PERSONAL, None, 0) # SHGFP_TYPE_CURRENT not in shellcon except: return os.getcwd() # F**k this elif operating_system.isMac(): import Carbon.Folder, Carbon.Folders, Carbon.File pathRef = Carbon.Folder.FSFindFolder(Carbon.Folders.kUserDomain, Carbon.Folders.kDocumentsFolderType, True) return Carbon.File.pathname(pathRef) elif operating_system.isGTK(): try: from PyKDE4.kdeui import KGlobalSettings except ImportError: pass else: return unicode(KGlobalSettings.documentPath()) # Assuming Unix-like return os.path.expanduser('~')
def __init__(self, window, settings): super(WindowDimensionsTracker, self).__init__(window, settings, 'window') self.__settings = settings if self.__start_iconized(): if operating_system.isMac() or operating_system.isGTK(): # Need to show the window on Mac OS X first, otherwise it # won't be properly minimized. On wxGTK we need to show the # window first, otherwise clicking the task bar icon won't # show it. self._window.Show() self._window.Iconize(True) if not operating_system.isMac() and \ self.get_setting('hidewheniconized'): # Seems like hiding the window after it's been # iconized actually closes it on Mac OS... wx.CallAfter(self._window.Hide)
def __init__(self): self.__iconCache = dict() if operating_system.isMac(): self.__iconSizeOnCurrentPlatform = 128 elif operating_system.isGTK(): self.__iconSizeOnCurrentPlatform = 48 else: self.__iconSizeOnCurrentPlatform = 16
def test_initial_size(self): # See MainWindowTest... width, height = self.frame.GetSizeTuple() if operating_system.isMac(): # pragma: no cover width, height = self.frame.GetClientSize() height -= 18 self.assertEqual((width, height), self.settings.getvalue(self.section, 'size'))
def onTaskbarClick(self, event): if self.__window.IsIconized() or not self.__window.IsShown(): self.__window.restore(event) else: if operating_system.isMac(): self.__window.Raise() else: self.__window.Iconize()
def test_change_size(self): self.frame.Maximize(False) if operating_system.isMac(): self.frame.SetClientSize((123, 200)) else: self.frame.ProcessEvent(wx.SizeEvent((123, 200))) self.assertEqual((123, 200), self.settings.getvalue(self.section, 'size'))
def __get_agw_style(): agw_style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_MULTIPLE \ | wx.TR_EDIT_LABELS | wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT \ | customtree.TR_HAS_VARIABLE_ROW_HEIGHT if operating_system.isMac(): agw_style |= wx.TR_NO_LINES agw_style &= ~hypertreelist.TR_NO_HEADER return agw_style
def __should_create_page(self, page_name): if page_name == 'iphone': return self.settings.getboolean('feature', 'iphone') elif page_name == 'os_darwin': return operating_system.isMac() elif page_name == 'os_linux': return operating_system.isGTK() else: return True
def __init__(self, parent, *args, **kwargs): super(BaseTextCtrl, self).__init__(parent, -1, *args, **kwargs) self.__data = None if operating_system.isGTK() or operating_system.isMac(): if operating_system.isGTK(): self.Bind(wx.EVT_KEY_DOWN, self.__on_key_down) self.Bind(wx.EVT_KILL_FOCUS, self.__on_kill_focus) self.__initial_value = self.GetValue() self.__undone_value = None
def testClearEmitsNoEventOnMacOSX(self): self.clearTextCausesEvent = False # pylint: disable=W0201 textCtrl = wx.TextCtrl(self.frame) textCtrl.Bind(wx.EVT_TEXT, self.onTextChanged) textCtrl.Clear() if operating_system.isMac(): # pragma: no cover self.failIf(self.clearTextCausesEvent) else: # pragma: no cover self.failUnless(self.clearTextCausesEvent)
def tearDown(self): if operating_system.isMac(): self.mainwindow.OnQuit() # Stop power monitoring thread # Also stop idle time thread self.mainwindow._idleController.stop() del self.mainwindow super(MainWindowTestCase, self).tearDown() self.taskFile.close() self.taskFile.stop()
def OnInit(self): if operating_system.isWindows(): self.Bind(wx.EVT_QUERY_END_SESSION, self.onQueryEndSession) if (operating_system.isMac() and hasattr(sys, 'frozen')) or \ (operating_system.isGTK() and not sys.stdout.isatty()): sys.stdout = sys.stderr = RedirectedOutput() return True
def __init__(self, *args, **kwargs): super(EditorPage, self).__init__(columns=2, *args, **kwargs) if operating_system.isMac() and \ not operating_system.isMacOsXMountainLion_OrNewer(): self.addBooleanSetting('editor', 'maccheckspelling', _('Check spelling in editors')) self.addFontSetting('editor', 'descriptionfont', _('Font to use in the description field of edit dialogs')) self.fit()
def __init__(self, *args, **kwargs): super(EditorPage, self).__init__(columns=2, *args, **kwargs) if operating_system.isMac() and \ not operating_system.isMacOsXMountainLion_OrNewer(): self.addBooleanSetting('editor', 'maccheckspelling', _('Check spelling in editors')) self.addFontSetting( 'editor', 'descriptionfont', _('Font to use in the description field of edit dialogs')) self.fit()
def _createSpinCtrl(self, percentage): entry = widgets.SpinCtrl(self, value=percentage, min=0, max=100, size=(60 if operating_system.isMac() else 50, -1)) for eventType in wx.EVT_SPINCTRL, wx.EVT_KILL_FOCUS: entry.Bind(eventType, self.onSpin) return entry
def __init__(self, window, settings, size=(32, 32)): self.__window = window self.__settings = settings self.__visibleUICommands = list() self.__cache = None super(ToolBar, self).__init__(window, style=wx.TB_FLAT|wx.TB_NODIVIDER) self.SetToolBitmapSize(size) if operating_system.isMac(): # Extra margin needed because the search control is too high self.SetMargins(0, 7) self.loadPerspective(window.getToolBarPerspective())
def open(self, filename=None, showerror=wx.MessageBox, fileExists=os.path.exists, breakLock=False, lock=True): if self.__taskFile.needSave(): if not self.__saveUnsavedChanges(): return if not filename: filename = self.__askUserForFile(_('Open'), self.__tskFileOpenDialogOpts) if not filename: return self.__updateDefaultPath(filename) if fileExists(filename): self.__closeUnconditionally() self.__addRecentFile(filename) try: try: self.__taskFile.load(filename, lock=lock, breakLock=breakLock) except: # Need to destroy splash screen first because it may # interfere with dialogs we show later on Mac OS X if self.__splash: self.__splash.Destroy() raise except lockfile.LockTimeout: if breakLock: if self.__askOpenUnlocked(filename): self.open(filename, showerror, lock=False) elif self.__askBreakLock(filename): self.open(filename, showerror, breakLock=True) else: return except lockfile.LockFailed: if self.__askOpenUnlocked(filename): self.open(filename, showerror, lock=False) else: return except persistence.xml.reader.XMLReaderTooNewException: self.__showTooNewErrorMessage(filename, showerror) return except Exception: self.__showGenericErrorMessage(filename, showerror, showBackups=True) return self.__messageCallback(_('Loaded %(nrtasks)d tasks from ' '%(filename)s') % dict(nrtasks=len(self.__taskFile.tasks()), filename=self.__taskFile.filename())) else: errorMessage = _("Cannot open %s because it doesn't exist") % filename # Use CallAfter on Mac OS X because otherwise the app will hang: if operating_system.isMac(): wx.CallAfter(showerror, errorMessage, **self.__errorMessageOptions) else: showerror(errorMessage, **self.__errorMessageOptions) self.__removeRecentFile(filename)
def __set_dimensions(self): ''' Set the window position and size based on the settings. ''' x, y = self.get_setting('position') # pylint: disable=C0103 width, height = self.get_setting('size') if operating_system.isMac(): # Under MacOS 10.5 and 10.4, when setting the size, the actual # window height is increased by 40 pixels. Dunno why, but it's # highly annoying. This doesn't hold for dialogs though. Sigh. if not isinstance(self._window, wx.Dialog): height += 18 self._window.SetDimensions(x, y, width, height) if operating_system.isMac(): self._window.SetClientSize((width, height)) if self.get_setting('maximized'): self._window.Maximize() # Check that the window is on a valid display and move if necessary: if wx.Display.GetFromWindow(self._window) == wx.NOT_FOUND: self._window.SetDimensions(0, 0, width, height) if operating_system.isMac(): self._window.SetClientSize((width, height))
def __init__(self, window, settings, size=(32, 32)): self.__window = window self.__settings = settings self.__visibleUICommands = list() self.__cache = None super(ToolBar, self).__init__(window, style=wx.TB_FLAT | wx.TB_NODIVIDER) self.SetToolBitmapSize(size) if operating_system.isMac(): # Extra margin needed because the search control is too high self.SetMargins(0, 7) self.loadPerspective(window.getToolBarPerspective())
def __set_dimensions(self): ''' Set the window position and size based on the settings. ''' x, y = self.get_setting('position') # pylint: disable=C0103 width, height = self.get_setting('size') if operating_system.isMac(): # Under MacOS 10.5 and 10.4, when setting the size, the actual # window height is increased by 40 pixels. Dunno why, but it's # highly annoying. This doesn't hold for dialogs though. Sigh. if not isinstance(self._window, wx.Dialog): height += 18 self._window.SetDimensions(x, y, width, height) if operating_system.isMac(): self._window.SetClientSize((width, height)) if self.get_setting('maximized'): self._window.Maximize() # Check that the window is on a valid display and move if necessary: if wx.Display.GetFromWindow(self._window) == wx.NOT_FOUND: # Not (0, 0) because on OSX this hides the window bar... self._window.SetDimensions(50, 50, width, height) if operating_system.isMac(): self._window.SetClientSize((width, height))
def getSimple(klass): """ Returns a notifier suitable for simple notifications. This defaults to Growl/Snarl/libnotify depending on their availability. """ if operating_system.isMac(): return klass.get('Growl') or klass.get('Task Coach') elif operating_system.isWindows(): return klass.get('Snarl') or klass.get('Task Coach') else: return klass.get('libnotify') or klass.get('Task Coach')
def accelerators(self): # The ENTER and NUMPAD_ENTER keys are treated differently between platforms... if '\t' in self.menuText and ('ENTER' in self.menuText or 'RETURN' in self.menuText): flags = wx.ACCEL_NORMAL for key in self.menuText.split('\t')[1].split('+'): if key == 'Ctrl': flags |= wx.ACCEL_CMD if operating_system.isMac() else wx.ACCEL_CTRL elif key in ['Shift', 'Alt']: flags |= dict(Shift=wx.ACCEL_SHIFT, Alt=wx.ACCEL_ALT)[key] else: assert key in ['ENTER', 'RETURN'], key return [(flags, wx.WXK_NUMPAD_ENTER, self.id)] return []
def on_change_size(self, event): ''' Handle a size event by saving the new size of the window in the settings. ''' # Ignore the EVT_SIZE when the window is maximized or iconized. # Note how this depends on the EVT_MAXIMIZE being sent before the # EVT_SIZE. maximized = self._window.IsMaximized() if not maximized and not self._window.IsIconized(): self.set_setting('size', self._window.GetClientSize() \ if operating_system.isMac() else event.GetSize()) # Jerome, 2008/07/12: On my system (KDE 3.5.7), EVT_MAXIMIZE # is not triggered, so set 'maximized' to True here as well as in # onMaximize: self.set_setting('maximized', maximized) event.Skip()
def onItemActivated(self, event): ''' Override default behavior to attach the column clicked on to the event so we can use it elsewhere. ''' window = self.GetMainWindow() if operating_system.isMac(): window = window.GetChildren()[0] mouse_position = window.ScreenToClient(wx.GetMousePosition()) index, dummy_flags, column = self.HitTest(mouse_position) if index >= 0: # Only get the column name if the hittest returned an item, # otherwise the item was activated from the menu or by double # clicking on a portion of the tree view not containing an item. column = max(0, column) # FIXME: Why can the column be -1? event.columnName = self._getColumn(column).name() # pylint: disable=E1101 self.editCommand(event)
def accelerators(self): # The ENTER and NUMPAD_ENTER keys are treated differently between platforms... if '\t' in self.menuText and ('ENTER' in self.menuText or 'RETURN' in self.menuText): flags = wx.ACCEL_NORMAL for key in self.menuText.split('\t')[1].split('+'): if key == 'Ctrl': flags |= wx.ACCEL_CMD if operating_system.isMac( ) else wx.ACCEL_CTRL elif key in ['Shift', 'Alt']: flags |= dict(Shift=wx.ACCEL_SHIFT, Alt=wx.ACCEL_ALT)[key] else: assert key in ['ENTER', 'RETURN'], key return [(flags, wx.WXK_NUMPAD_ENTER, self.id)] return []
def sendMail(to, subject, body, openURL=desktop.open): def unicode_quote(s): # This is like urllib.quote but leaves out Unicode characters, # which urllib.quote does not support. chars = [c if ord(c) >= 128 else urllib.quote(c) for c in s] return ''.join(chars) # FIXME: Very strange things happen on MacOS X. If there is one # non-ASCII character in the body, it works. If there is more than # one, it fails. Maybe we should use Mail.app directly ? What if # the user uses something else ? if not operating_system.isMac(): body = unicode_quote(body) # Otherwise newlines disappear openURL(u'mailto:%s?subject=%s&body=%s' % (to, subject, body))
def Style(self): """Return the frame's style""" style = wx.FRAME_NO_TASKBAR | wx.TAB_TRAVERSAL if operating_system.isMac(): # style |= wx.NO_BORDER|wx.POPUP_WINDOW # XXXFIXME: without the POPUP_WINDOW style, the frame # steals the focus. But with it, when the frame is created # while the user is on another Space that the main # window's, it cannot receive user events any more, so # cannot be dismissed... style |= wx.NO_BORDER return style
def Style(self): """Return the frame's style""" style = wx.FRAME_NO_TASKBAR|wx.TAB_TRAVERSAL if operating_system.isMac(): # style |= wx.NO_BORDER|wx.POPUP_WINDOW # XXXFIXME: without the POPUP_WINDOW style, the frame # steals the focus. But with it, when the frame is created # while the user is on another Space that the main # window's, it cannot receive user events any more, so # cannot be dismissed... style |= wx.NO_BORDER return style
def createTemplateList(self, pane): panel = sized_controls.SizedPanel(pane) panel.SetSizerType('horizontal') panel.SetSizerProps(expand=True, proportion=1) self._templateList = wx.TreeCtrl(panel, style=wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE) self._templateList.SetMinSize((300, 200)) self._templateList.SetSizerProps(expand=True, proportion=1) self._templateList.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged) self._templates = persistence.TemplateList(self.settings.pathToTemplatesDir()) self._root = self._templateList.AddRoot('Root') for task in self._templates.tasks(): item = self.appendTemplate(self._root, task) if operating_system.isMac(): # See http://trac.wxwidgets.org/ticket/10085 self._templateList.SetItemText(item, task.subject()) self.createTemplateListButtons(panel) panel.Fit()
def pathToConfigDir(self, environ): try: if operating_system.isGTK(): from taskcoachlib.thirdparty.xdg import BaseDirectory path = BaseDirectory.save_config_path(meta.name) elif operating_system.isMac(): import Carbon.Folder, Carbon.Folders, Carbon.File pathRef = Carbon.Folder.FSFindFolder(Carbon.Folders.kUserDomain, Carbon.Folders.kPreferencesFolderType, True) path = Carbon.File.pathname(pathRef) # XXXFIXME: should we release pathRef ? Doesn't seem so since I get a SIGSEGV if I try. elif operating_system.isWindows(): from win32com.shell import shell, shellcon path = os.path.join(shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_APPDATA, True), meta.name) else: path = self.pathToConfigDir_deprecated(environ=environ) except: # Fallback to old dir path = self.pathToConfigDir_deprecated(environ=environ) return path
def loadPerspective(self, perspective, customizable=True, cache=True): self.Clear() commands = self._filterCommands(perspective, cache=cache) self.__visibleUICommands = commands[:] if customizable: if 1 not in commands: commands.append(1) from taskcoachlib.gui.dialog.toolbar import ToolBarEditor uiCommand = uicommand.EditToolBarPerspective( self, ToolBarEditor, settings=self.__settings) commands.append(uiCommand) self.__customizeId = uiCommand.id if operating_system.isMac(): commands.append(None) # Errr... self.appendUICommands(*commands) self.Realize()
def _pathToDataDir(self, *args, **kwargs): forceGlobal = kwargs.pop('forceGlobal', False) if operating_system.isGTK(): from taskcoachlib.thirdparty.xdg import BaseDirectory path = BaseDirectory.save_data_path(meta.name) elif operating_system.isMac(): import Carbon.Folder, Carbon.Folders, Carbon.File pathRef = Carbon.Folder.FSFindFolder( Carbon.Folders.kUserDomain, Carbon.Folders.kApplicationSupportFolderType, True) path = Carbon.File.pathname(pathRef) # XXXFIXME: should we release pathRef ? Doesn't seem so since I get a SIGSEGV if I try. path = os.path.join(path, meta.name) elif operating_system.isWindows(): if self.__iniFileSpecifiedOnCommandLine and not forceGlobal: path = self.pathToIniFileSpecifiedOnCommandLine() else: from win32com.shell import shell, shellcon path = os.path.join( shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_APPDATA, True), meta.name) else: # Errr... path = self.path() if operating_system.isWindows(): # Follow shortcuts. from win32com.client import Dispatch shell = Dispatch('WScript.Shell') for component in args: path = os.path.join(path, component) if os.path.exists(path + '.lnk'): shortcut = shell.CreateShortcut(path + '.lnk') path = shortcut.TargetPath else: path = os.path.join(path, *args) exists = os.path.exists(path) if not exists: os.makedirs(path) return path, exists
def createTemplateList(self, pane): panel = sized_controls.SizedPanel(pane) panel.SetSizerType('horizontal') panel.SetSizerProps(expand=True, proportion=1) self._templateList = wx.TreeCtrl(panel, style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_SINGLE) self._templateList.SetMinSize((300, 200)) self._templateList.SetSizerProps(expand=True, proportion=1) self._templateList.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged) self._templates = persistence.TemplateList( self.settings.pathToTemplatesDir()) self._root = self._templateList.AddRoot('Root') for task in self._templates.tasks(): item = self.appendTemplate(self._root, task) if operating_system.isMac(): # See http://trac.wxwidgets.org/ticket/10085 self._templateList.SetItemText(item, task.subject()) self.createTemplateListButtons(panel) panel.Fit()