Check ProjectPath write permission
authorgreg
Fri, 23 Oct 2009 15:41:48 +0200
changeset 427 7ac746c07ff2
parent 426 3f285782ac9b
child 428 ea09f33ce717
Check ProjectPath write permission
Manage buildpath
Beremiz.py
plugger.py
plugins/c_ext/CFileEditor.py
plugins/c_ext/c_ext.py
plugins/canfestival/canfestival.py
plugins/python/PythonEditor.py
plugins/python/modules/svgui/svgui.py
plugins/python/modules/wxglade_hmi/wxglade_hmi.py
plugins/python/python.py
targets/toolchain_gcc.py
--- a/Beremiz.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/Beremiz.py	Fri Oct 23 15:41:48 2009 +0200
@@ -293,6 +293,8 @@
               kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O'))
         AppendMenu(parent, help='', id=wx.ID_SAVE,
               kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S'))
+        AppendMenu(parent, help='', id=wx.ID_SAVEAS,
+              kind=wx.ITEM_NORMAL, text=_(u'Save as\tCTRL+S'))
         AppendMenu(parent, help='', id=wx.ID_CLOSE,
               kind=wx.ITEM_NORMAL, text=_(u'Close Tab\tCTRL+W'))
         AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL,
@@ -314,6 +316,7 @@
         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
         self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE)
+        self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS)
         self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE)
         self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL)
         self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
@@ -543,6 +546,7 @@
                 self.FileMenu.Enable(wx.ID_PRINT, False)
             self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
             self.FileMenu.Enable(wx.ID_SAVE, True)
+            self.FileMenu.Enable(wx.ID_SAVEAS, True)
             self.FileMenu.Enable(wx.ID_PROPERTIES, True)
             self.FileMenu.Enable(wx.ID_CLOSE_ALL, True)
         else:
@@ -551,6 +555,7 @@
             self.FileMenu.Enable(wx.ID_PREVIEW, False)
             self.FileMenu.Enable(wx.ID_PRINT, False)
             self.FileMenu.Enable(wx.ID_SAVE, False)
+            self.FileMenu.Enable(wx.ID_SAVEAS, False)
             self.FileMenu.Enable(wx.ID_PROPERTIES, False)
             self.FileMenu.Enable(wx.ID_CLOSE_ALL, False)
         
@@ -1370,6 +1375,13 @@
             self.RefreshAll()
             self.RefreshTitle()
     
+    def OnSaveProjectAsMenu(self, event):
+        if self.PluginRoot is not None:
+            self.PluginRoot.SaveProjectAs()
+            self.RefreshAll()
+            self.RefreshTitle()
+        event.Skip()
+    
     def OnPropertiesMenu(self, event):
         self.ShowProperties()
     
@@ -1402,24 +1414,26 @@
         return DeleteButtonFunction
     
     def AddPlugin(self, PluginType, plugin):
-        dialog = wx.TextEntryDialog(self, _("Please enter a name for plugin:"), _("Add Plugin"), "", wx.OK|wx.CANCEL)
-        if dialog.ShowModal() == wx.ID_OK:
-            PluginName = dialog.GetValue()
-            plugin.PlugAddChild(PluginName, PluginType)
-            self.RefreshPluginTree()
-            self.PluginRoot.RefreshPluginsBlockLists()
-        dialog.Destroy()
+        if self.PluginRoot.CheckProjectPathPerm():
+            dialog = wx.TextEntryDialog(self, _("Please enter a name for plugin:"), _("Add Plugin"), "", wx.OK|wx.CANCEL)
+            if dialog.ShowModal() == wx.ID_OK:
+                PluginName = dialog.GetValue()
+                plugin.PlugAddChild(PluginName, PluginType)
+                self.RefreshPluginTree()
+                self.PluginRoot.RefreshPluginsBlockLists()
+            dialog.Destroy()
     
     def DeletePlugin(self, plugin):
-        dialog = wx.MessageDialog(self, _("Really delete plugin ?"), _("Remove plugin"), wx.YES_NO|wx.NO_DEFAULT)
-        if dialog.ShowModal() == wx.ID_YES:
-            self.PluginInfos.pop(plugin)
-            plugin.PlugRemove()
-            del plugin
-            self.PluginRoot.RefreshPluginsBlockLists()
-            self.RefreshPluginTree()
-        dialog.Destroy()
-
+        if self.PluginRoot.CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self, _("Really delete plugin ?"), _("Remove plugin"), wx.YES_NO|wx.NO_DEFAULT)
+            if dialog.ShowModal() == wx.ID_YES:
+                self.PluginInfos.pop(plugin)
+                plugin.PlugRemove()
+                del plugin
+                self.PluginRoot.RefreshPluginsBlockLists()
+                self.RefreshPluginTree()
+            dialog.Destroy()
+    
 #-------------------------------------------------------------------------------
 #                               Exception Handler
 #-------------------------------------------------------------------------------
--- a/plugger.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugger.py	Fri Oct 23 15:41:48 2009 +0200
@@ -74,7 +74,17 @@
 # helper func to get path to images
 def opjimg(imgname):
     return os.path.join("images",imgname)
-
+    
+# helper func to check path write permission
+def CheckPathPerm(path):
+    if path is None or not os.path.isdir(path):
+        return False
+    for root, dirs, files in os.walk(path):
+         for name in files:
+             if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
+                 return False
+    return True
+    
 class PlugTemplate:
     """
     This class is the one that define plugins.
@@ -181,38 +191,39 @@
         os.mkdir(self.PlugPath())
 
     def PlugRequestSave(self):
-        # If plugin do not have corresponding directory
-        plugpath = self.PlugPath()
-        if not os.path.isdir(plugpath):
-            # Create it
-            os.mkdir(plugpath)
-
-        # generate XML for base XML parameters controller of the plugin
-        if self.MandatoryParams:
-            BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
-            BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-            BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
-            BaseXMLFile.close()
-        
-        # generate XML for XML parameters controller of the plugin
-        if self.PlugParams:
-            XMLFile = open(self.PluginXmlFilePath(),'w')
-            XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-            XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
-            XMLFile.close()
-        
-        # Call the plugin specific OnPlugSave method
-        result = self.OnPlugSave()
-        if not result:
-            return _("Error while saving \"%s\"\n")%self.PlugPath()
-
-        # mark plugin as saved
-        self.ChangesToSave = False        
-        # go through all childs and do the same
-        for PlugChild in self.IterChilds():
-            result = PlugChild.PlugRequestSave()
-            if result:
-                return result
+        if self.GetPlugRoot().CheckProjectPathPerm(False):
+            # If plugin do not have corresponding directory
+            plugpath = self.PlugPath()
+            if not os.path.isdir(plugpath):
+                # Create it
+                os.mkdir(plugpath)
+    
+            # generate XML for base XML parameters controller of the plugin
+            if self.MandatoryParams:
+                BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
+                BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+                BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
+                BaseXMLFile.close()
+            
+            # generate XML for XML parameters controller of the plugin
+            if self.PlugParams:
+                XMLFile = open(self.PluginXmlFilePath(),'w')
+                XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+                XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
+                XMLFile.close()
+            
+            # Call the plugin specific OnPlugSave method
+            result = self.OnPlugSave()
+            if not result:
+                return _("Error while saving \"%s\"\n")%self.PlugPath()
+    
+            # mark plugin as saved
+            self.ChangesToSave = False
+            # go through all childs and do the same
+            for PlugChild in self.IterChilds():
+                result = PlugChild.PlugRequestSave()
+                if result:
+                    return result
         return None
     
     def PlugImport(self, src_PlugPath):
@@ -690,7 +701,7 @@
                    "LREAL" :      8,
                   } 
 
-import re
+import re, tempfile
 import targets
 import connectors
 from discovery import DiscoveryDialog
@@ -764,7 +775,7 @@
         self.PlugType = "Beremiz"
         # After __init__ root plugin is not valid
         self.ProjectPath = None
-        self.BuildPath = None
+        self._setBuildPath(None)
         self.DebugThread = None
         self.debug_break = False
         self.previous_plcstate = None
@@ -852,6 +863,23 @@
         if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
             self.BeremizRoot.setTargetType(self.GetDefaultTarget())
         return PlugTemplate.SetParamsAttribute(self, path, value)
+        
+    # helper func to check project path write permission
+    def CheckProjectPathPerm(self, dosave=True):
+        if CheckPathPerm(self.ProjectPath):
+            return True
+        dialog = wx.MessageDialog(self.AppFrame, 
+                    _('You must have write permission to work on the project\nWork on a project copy ?'),
+                    _('Error'), 
+                    wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+        answer = dialog.ShowModal()
+        dialog.Destroy()
+        if answer == wx.ID_YES:
+            if self.SaveProjectAs():
+                self.AppFrame.RefreshAll()
+                self.AppFrame.RefreshTitle()
+                return True
+        return False
     
     def NewProject(self, ProjectPath, BuildPath=None):
         """
@@ -879,7 +907,7 @@
         self.PluggedChilds = {}
         # Keep track of the root plugin (i.e. project path)
         self.ProjectPath = ProjectPath
-        self.BuildPath = BuildPath
+        self._setBuildPath(BuildPath)
         # get plugins bloclist (is that usefull at project creation?)
         self.RefreshPluginsBlockLists()
         # this will create files base XML files
@@ -906,7 +934,7 @@
         self.PluggedChilds = {}
         # Keep track of the root plugin (i.e. project path)
         self.ProjectPath = ProjectPath
-        self.BuildPath = BuildPath
+        self._setBuildPath(BuildPath)
         # If dir have already be made, and file exist
         if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
             #Load the plugin.xml file into parameters members
@@ -930,11 +958,26 @@
         self.ResetAppFrame(None)
         
     def SaveProject(self):
-        if not self.SaveXMLFile():
+        if self.CheckProjectPathPerm(False):
             self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
-        result = self.PlugRequestSave()
-        if result:
-            self.logger.write_error(result)
+            result = self.PlugRequestSave()
+            if result:
+                self.logger.write_error(result)
+    
+    def SaveProjectAs(self, dosave=True):
+        # Ask user to choose a path with write permissions
+        dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), os.getenv("HOME"), wx.DD_NEW_DIR_BUTTON)
+        answer = dirdialog.ShowModal()
+        dirdialog.Destroy()
+        if answer == wx.ID_OK:
+            newprojectpath = dirdialog.GetPath()
+            if os.path.isdir(newprojectpath):
+                self.ProjectPath = newprojectpath
+                if dosave:
+                    self.SaveProject()
+                self._setBuildPath(self.BuildPath)
+                return True
+        return False
     
     # Update PLCOpenEditor Plugin Block types from loaded plugins
     def RefreshPluginsBlockLists(self):
@@ -971,10 +1014,33 @@
     def ParentsBlockTypesFactory(self):
         return self.BlockTypesFactory()
 
+    def _setBuildPath(self, buildpath):
+        if CheckPathPerm(buildpath):
+            self.BuildPath = buildpath
+        else:
+            self.BuildPath = None
+        self.BuildPath = buildpath
+        self.DefaultBuildPath = None
+        if self._builder is not None:
+            self._builder.SetBuildPath(self._getBuildPath())
+
     def _getBuildPath(self):
-        if self.BuildPath is None:
-            return os.path.join(self.ProjectPath, "build")
-        return self.BuildPath
+        # BuildPath is defined by user
+        if self.BuildPath is not None:
+            return self.BuildPath
+        # BuildPath isn't defined by user but already created by default
+        if self.DefaultBuildPath is not None:
+            return self.DefaultBuildPath
+        # Create a build path in project folder if user has permissions
+        if CheckPathPerm(self.ProjectPath):
+            self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
+        # Create a build path in temp folder
+        else:
+            self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
+            
+        if not os.path.exists(self.DefaultBuildPath):
+            os.makedirs(self.DefaultBuildPath)
+        return self.DefaultBuildPath
     
     def _getExtraFilesPath(self):
         return os.path.join(self._getBuildPath(), "extra_files")
--- a/plugins/c_ext/CFileEditor.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/c_ext/CFileEditor.py	Fri Oct 23 15:41:48 2009 +0200
@@ -908,14 +908,12 @@
         selected = self.PartsOpened.GetSelection()
         if selected >= 0:
             self.PartsOpened.DeletePage(selected)
-        event.Skip()
 
     def OnSaveMenu(self, event):
         if getattr(self, "_onsave", None) != None:
             self._onsave()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
 
 #-------------------------------------------------------------------------------
 #                            Notebook Unified Functions
@@ -957,7 +955,6 @@
         if selected != -1:
             window = self.PartsOpened.GetPage(selected)
             window.RefreshView()
-        event.Skip()
 
     def OnUndoMenu(self, event):
         self.Controler.LoadPrevious()
@@ -967,7 +964,6 @@
             window.RefreshView()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
     
     def OnRedoMenu(self, event):
         self.Controler.LoadNext()
@@ -977,7 +973,6 @@
             window.RefreshView()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
         
 #-------------------------------------------------------------------------------
 #                      CFile Editor Panels Management Functions
--- a/plugins/c_ext/c_ext.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/c_ext/c_ext.py	Fri Oct 23 15:41:48 2009 +0200
@@ -222,14 +222,28 @@
     _View = None
     def _OpenView(self):
         if not self._View:
-            def _onclose():
-                self._View = None
-            def _onsave():
-                self.GetPlugRoot().SaveProject()
-            self._View = CFileEditor(self.GetPlugRoot().AppFrame, self)
-            self._View._onclose = _onclose
-            self._View._onsave = _onsave
-            self._View.Show()
+            open_cfileeditor = True
+            has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+            if not has_permissions:
+                dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                          _("You don't have write permissions.\nOpen CFileEditor anyway ?"),
+                                          _("Open CFileEditor"),
+                                          wx.YES_NO|wx.ICON_QUESTION)
+                open_cfileeditor = dialog.ShowModal() == wx.ID_YES
+                dialog.Destroy()
+            if open_cfileeditor:
+                def _onclose():
+                    self._View = None
+                if has_permissions:
+                    def _onsave():
+                        self.GetPlugRoot().SaveProject()
+                else:
+                    def _onsave():
+                        pass
+                self._View = CFileEditor(self.GetPlugRoot().AppFrame, self)
+                self._View._onclose = _onclose
+                self._View._onsave = _onsave
+                self._View.Show()
 
     PluginMethods = [
         {"bitmap" : os.path.join("images", "EditCfile"),
--- a/plugins/canfestival/canfestival.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/canfestival/canfestival.py	Fri Oct 23 15:41:48 2009 +0200
@@ -100,16 +100,31 @@
     _View = None
     def _OpenView(self):
         if not self._View:
-            def _onclose():
-                self._View = None
-            def _onsave():
-                self.GetPlugRoot().SaveProject()
-            self._View = objdictedit(self.GetPlugRoot().AppFrame, self)
-            # TODO redefine BusId when IEC channel change
-            self._View.SetBusId(self.GetCurrentLocation())
-            self._View._onclose = _onclose
-            self._View._onsave = _onsave
-            self._View.Show()
+            open_objdictedit = True
+            has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+            if not has_permissions:
+                dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                          _("You don't have write permissions.\nOpen ObjDictEdit anyway ?"),
+                                          _("Open ObjDictEdit"),
+                                          wx.YES_NO|wx.ICON_QUESTION)
+                open_objdictedit = dialog.ShowModal() == wx.ID_YES
+                dialog.Destroy()
+            if open_objdictedit:
+                def _onclose():
+                    self._View = None
+                if has_permissions:
+                    def _onsave():
+                        self.GetPlugRoot().SaveProject()
+                else:
+                    def _onsave():
+                        pass
+            
+                self._View = objdictedit(self.GetPlugRoot().AppFrame, self)
+                # TODO redefine BusId when IEC channel change
+                self._View.SetBusId(self.GetCurrentLocation())
+                self._View._onclose = _onclose
+                self._View._onsave = _onsave
+                self._View.Show()
 
     PluginMethods = [
         {"bitmap" : os.path.join("images", "NetworkEdit"),
@@ -185,16 +200,30 @@
     _View = None
     def _OpenView(self):
         if not self._View:
-            def _onclose():
-                self._View = None
-            def _onsave():
-                self.GetPlugRoot().SaveProject()
-            self._View = networkedit(self.GetPlugRoot().AppFrame, self)
-            # TODO redefine BusId when IEC channel change
-            self._View.SetBusId(self.GetCurrentLocation())
-            self._View._onclose = _onclose
-            self._View._onsave = _onsave
-            self._View.Show()
+            open_networkedit = True
+            has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+            if not has_permissions:
+                dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                          _("You don't have write permissions.\nOpen NetworkEdit anyway ?"),
+                                          _("Open NetworkEdit"),
+                                          wx.YES_NO|wx.ICON_QUESTION)
+                open_networkedit = dialog.ShowModal() == wx.ID_YES
+                dialog.Destroy()
+            if open_networkedit:
+                def _onclose():
+                    self._View = None
+                if has_permissions:
+                    def _onsave():
+                        self.GetPlugRoot().SaveProject()
+                else:
+                    def _onsave():
+                        pass
+                self._View = networkedit(self.GetPlugRoot().AppFrame, self)
+                # TODO redefine BusId when IEC channel change
+                self._View.SetBusId(self.GetCurrentLocation())
+                self._View._onclose = _onclose
+                self._View._onsave = _onsave
+                self._View.Show()
 
     def _ShowMasterGenerated(self):
         buildpath = self._getBuildPath()
--- a/plugins/python/PythonEditor.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/python/PythonEditor.py	Fri Oct 23 15:41:48 2009 +0200
@@ -560,7 +560,6 @@
             self._onsave()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
 
     def RefreshTitle(self):
         title = _("PythonEditor")
@@ -577,19 +576,17 @@
 
     def OnRefreshMenu(self, event):
         self.PythonEdited.RefreshView()
-        event.Skip()
 
     def OnUndoMenu(self, event):
         self.Controler.LoadPrevious()
         self.PythonEdited.RefreshView()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
     
     def OnRedoMenu(self, event):
         self.Controler.LoadNext()
         self.PythonEdited.RefreshView()
         self.RefreshTitle()
         self.RefreshEditMenu()
-        event.Skip()
-
+        
+
--- a/plugins/python/modules/svgui/svgui.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/python/modules/svgui/svgui.py	Fri Oct 23 15:41:48 2009 +0200
@@ -98,6 +98,15 @@
 
     def _StartInkscape(self):
         svgfile = self._getSVGpath()
-        if not os.path.isfile(svgfile):
-            svgfile = None
-        open_svg(svgfile)
+        open_inkscape = True
+        if not self.GetPlugRoot().CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                      _("You don't have write permissions.\nOpen Inkscape anyway ?"),
+                                      _("Open Inkscape"),
+                                      wx.YES_NO|wx.ICON_QUESTION)
+            open_inkscape = dialog.ShowModal() == wx.ID_YES
+            dialog.Destroy()
+        if open_inkscape:
+            if not os.path.isfile(svgfile):
+                svgfile = None
+            open_svg(svgfile)
--- a/plugins/python/modules/wxglade_hmi/wxglade_hmi.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/python/modules/wxglade_hmi/wxglade_hmi.py	Fri Oct 23 15:41:48 2009 +0200
@@ -100,16 +100,25 @@
 
     def _editWXGLADE(self):
         wxg_filename = self._getWXGLADEpath()
-        if not os.path.exists(wxg_filename):
-            hmi_name = self.BaseParams.getName()
-            open(wxg_filename,"w").write("""<?xml version="1.0"?>
-<application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
-    <object class="%(class)s" name="%(name)s" base="EditFrame">
-        <style>wxDEFAULT_FRAME_STYLE</style>
-        <title>frame_1</title>
-    </object>
-</application>
-""" % {"name": hmi_name, "class": "Class_%s" % hmi_name})
-        if wx.Platform == '__WXMSW__':
-            wxg_filename = "\"%s\""%wxg_filename
-        self.launch_wxglade([wxg_filename])
+        open_wxglade = True
+        if not self.GetPlugRoot().CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                      _("You don't have write permissions.\nOpen wxGlade anyway ?"),
+                                      _("Open wxGlade"),
+                                      wx.YES_NO|wx.ICON_QUESTION)
+            open_wxglade = dialog.ShowModal() == wx.ID_YES
+            dialog.Destroy()
+        if open_wxglade:
+            if not os.path.exists(wxg_filename):
+                hmi_name = self.BaseParams.getName()
+                open(wxg_filename,"w").write("""<?xml version="1.0"?>
+    <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
+        <object class="%(class)s" name="%(name)s" base="EditFrame">
+            <style>wxDEFAULT_FRAME_STYLE</style>
+            <title>frame_1</title>
+        </object>
+    </application>
+    """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
+            if wx.Platform == '__WXMSW__':
+                wxg_filename = "\"%s\""%wxg_filename
+            self.launch_wxglade([wxg_filename])
--- a/plugins/python/python.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/plugins/python/python.py	Fri Oct 23 15:41:48 2009 +0200
@@ -141,14 +141,28 @@
     _View = None
     def _OpenView(self):
         if not self._View:
-            def _onclose():
-                self._View = None
-            def _onsave():
-                self.GetPlugRoot().SaveProject()
-            self._View = PythonEditorFrame(self.GetPlugRoot().AppFrame, self)
-            self._View._onclose = _onclose
-            self._View._onsave = _onsave
-            self._View.Show()
+            open_pyeditor = True
+            has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+            if not has_permissions:
+                dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                          _("You don't have write permissions.\nOpen PythonEditor anyway ?"),
+                                          _("Open PythonEditor"),
+                                          wx.YES_NO|wx.ICON_QUESTION)
+                open_pyeditor = dialog.ShowModal() == wx.ID_YES
+                dialog.Destroy()
+            if open_pyeditor:
+                def _onclose():
+                    self._View = None
+                if has_permissions:
+                    def _onsave():
+                        self.GetPlugRoot().SaveProject()
+                else:
+                    def _onsave():
+                        pass
+                self._View = PythonEditorFrame(self.GetPlugRoot().AppFrame, self)
+                self._View._onclose = _onclose
+                self._View._onsave = _onsave
+                self._View.Show()
     
     def OnPlugSave(self):
         filepath = self.PythonFileName()
--- a/targets/toolchain_gcc.py	Thu Oct 22 17:20:24 2009 +0200
+++ b/targets/toolchain_gcc.py	Fri Oct 23 15:41:48 2009 +0200
@@ -12,11 +12,8 @@
     """
     def __init__(self, PluginsRootInstance):
         self.PluginsRootInstance = PluginsRootInstance
-        self.exe = PluginsRootInstance.GetProjectName() + self.extension
-        self.buildpath = PluginsRootInstance._getBuildPath()
-        self.exe_path = os.path.join(self.buildpath, self.exe)
-        self.md5key = None
-        self.srcmd5 = {}
+        self.buildpath = None
+        self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
 
     def getTarget(self):
         target = self.PluginsRootInstance.BeremizRoot.getTargetType()
@@ -54,7 +51,15 @@
                 return open(self._GetMD5FileName(), "r").read()
             except Exception, e:
                 return None
-
+    
+    def SetBuildPath(self, buildpath):
+        if self.buildpath != buildpath:
+            self.buildpath = buildpath
+            self.exe = self.PluginsRootInstance.GetProjectName() + self.extension
+            self.exe_path = os.path.join(self.buildpath, self.exe)
+            self.md5key = None
+            self.srcmd5 = {}
+    
     def check_and_update_hash_and_deps(self, bn):
         # Get latest computed hash and deps
         oldhash, deps = self.srcmd5.get(bn,(None,[]))