Exemple #1
0
    def ErrorManager(self, msg):
        """ An error is occurred.
		"""

        ### try to find the file which have the error from traceback
        devs_error = False
        try:
            typ, val, tb = msg.date if wx.VERSION_STRING < '2.9' else msg
            trace = traceback.format_exception(typ, val, tb)

            mainW = wx.GetApp().GetTopWindow()
            ### paths in traceback
            paths = [
                a for a in trace if a.split(',')[0].strip().startswith('File')
            ]

            ### find if DOMAIN_PATH is in the first file path of the trace
            path = paths[-1]
            devs_error = DOMAIN_PATH in path or HOME_PATH not in path

        except Exception as info:
            sys.stdout.write(_("Error in ErrorManager: %s" % info))

        ### if error come from devs python file
        if devs_error:

            try:
                ### simulate event button for the code editor
                event = wx.PyCommandEvent(wx.EVT_BUTTON.typeId,
                                          self._btn1.GetId())
            except:
                pass
            else:
                ### Error dialog
                if not Container.MsgBoxError(
                        event, self.parent,
                        msg.date if wx.VERSION_STRING < '2.9' else msg):
                    ### if user dont want correct the error, we destroy the simulation windows
                    self.PrepareDestroyWin()
                    self.Destroy()
                else:
                    ### if user want to correct error through an editor, we stop simulation process for trying again after the error is corrected.
                    self.OnStop(event)
        else:
            print(msg)
            raise MyBad(msg)
Exemple #2
0
class SimulationDialog(wx.Frame, wx.Panel):
    """ SimulationDialog(parent, id, title, master)

		Frame or Panel with progress bar
	"""
    def __init__(self, parent, id, title, master):
        """ Constructor
		"""

        if isinstance(parent, wx.Panel):
            wx.Panel.__init__(self, parent, id)
            self.SetBackgroundColour(wx.NullColour)
            self.panel = self

            ### panel inherit of the left splitter size
            self.panel.SetSize(parent.GetParent().GetSize())

            # status bar of main application
            self.statusbar = parent.GetTopLevelParent().statusbar
        else:
            wx.Frame.__init__(self,
                              parent,
                              id,
                              title,
                              style=wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP)

            ### adapt size of frame depending on the plate-form
            if '__WXMSW__' in wx.PlatformInfo:
                self.SetSize((320, 280))
            else:
                self.SetSize((280, 160))

            # disable the roll out of the frame
            self.SetMinSize(self.GetSize())

            self.panel = wx.Panel(self, -1)

            wx.CallAfter(self.CreateBar)

            self.__set_properties()

        # local copy
        self.parent = parent
        self.master = master
        self.title = title

        ### current master for multi-simulation without simulationDialog reloading (show OnOk)
        self.current_master = None

        # simulator strategy
        self.selected_strategy = DEFAULT_SIM_STRATEGY

        ### profiling simulation with hotshot
        self.prof = False

        ### No time limit simulation (defined in the builtin dictionary from .devsimpy file)
        self.ntl = __builtin__.__dict__['NTL']

        self.verbose = False

        # definition of the thread, the timer and the counter for the simulation progress
        self.thread = None
        self.timer = wx.Timer(self, wx.NewId())
        self.count = 10.0
        self.stdioWin = None

        self.__widgets()
        self.__do_layout()
        self.__set_events()

        ### create a pubsub receiver (simple way to communicate with thread)
        Publisher.subscribe(self.ErrorManager, "error")

    def CreateBar(self):
        self.statusbar = self.CreateStatusBar(2)

    def __set_properties(self):
        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(
            wx.Bitmap(os.path.join(ICON_PATH_16_16, "simulation.png"),
                      wx.BITMAP_TYPE_ANY))
        self.SetIcon(icon)

        self.Center()

    def __widgets(self):

        self._text1 = wx.StaticText(self.panel, wx.ID_ANY, _('Final time:'))
        self._value = wx.TextCtrl(self.panel,
                                  wx.ID_ANY,
                                  str(float(self.master.FINAL_TIME)),
                                  validator=TextObjectValidator())
        self._btn1 = wx.Button(self.panel, wx.NewId(), _('Run'))
        self._btn2 = wx.Button(self.panel, wx.NewId(), _('Stop'))
        self._btn3 = wx.Button(self.panel, wx.NewId(), _('Suspend'))
        self._btn4 = wx.Button(self.panel, wx.NewId(), _('Log'))
        self._gauge = wx.Gauge(self.panel,
                               wx.ID_ANY,
                               100,
                               size=(-1, 25),
                               style=wx.GA_HORIZONTAL | wx.GA_SMOOTH)
        self._cp = CollapsiblePanel(self.panel, self)

        self._text1.Enable(not self.ntl)
        self._value.Enable(not self.ntl)

        self._btn1.SetToolTipString(_("Begin simulation process."))
        self._btn2.SetToolTipString(_("Stop the simulation process."))
        self._btn3.SetToolTipString(_("Suspend the simulation process."))
        self._btn4.SetToolTipString(
            _("Launch the log window (often depends on some plug-ins (verbose, activity, ...))."
              ))

    def __do_layout(self):

        #vbox_top = wx.BoxSizer(wx.VERTICAL)
        vbox_body = wx.BoxSizer(wx.VERTICAL)

        #panel 1
        grid1 = wx.GridSizer(1, 2)
        grid1.Add(self._text1, 0,
                  wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
        grid1.Add(self._value, 1, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL)

        # panel2
        grid2 = wx.GridSizer(3, 2, 2, 2)
        grid2.Add(
            self._btn1, 0,
            wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
        grid2.Add(
            self._btn3, 0,
            wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
        grid2.Add(
            self._btn2, 0,
            wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
        grid2.Add(
            self._btn4, 0,
            wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)

        # panel4
        #hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        #hbox1.Add(self._gauge, 1, wx.EXPAND, 9)

        ## panel5
        #hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        #hbox2.Add(self._cp, 1, wx.EXPAND, 9)

        vbox_body.Add(grid1, 0, wx.EXPAND, 9)
        vbox_body.Add(grid2, 0, wx.EXPAND, 9)
        vbox_body.Add(self._gauge, 0, wx.EXPAND, 9)
        vbox_body.Add(self._cp, 0, wx.EXPAND, 9)

        # fin panel
        #vbox_top.Add(vbox_body, 0, wx.EXPAND|wx.ALL, 9)
        self.panel.SetSizer(vbox_body)

        #		vbox_body.Fit(self)

        self._text1.SetFocus()
        self._btn1.SetDefault()
        self._btn2.Disable()
        self._btn3.Disable()

    ###
    def __set_events(self):

        ### binding event
        self.Bind(wx.EVT_BUTTON, self.OnOk, self._btn1)
        self.Bind(wx.EVT_BUTTON, self.OnStop, self._btn2)
        self.Bind(wx.EVT_BUTTON, self.OnSuspend, self._btn3)
        self.Bind(wx.EVT_BUTTON, self.OnViewLog, self._btn4)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.Bind(wx.EVT_TEXT, self.OnText, self._value)
        self.Bind(wx.EVT_CLOSE, self.OnQuit)

    ###
    def ChangeButtonLabel(self, btn, new_label):
        """ Change the label of the Log button depending on the active plug-in
		"""

        ### if activity plug-in is enabled
        if is_enable('start_activity_tracking'):
            self._btn4.SetLabel("Activity")

    ###
    def OnText(self, event):
        self._gauge.SetValue(0)

    ###
    @BuzyCursorNotification
    def OnViewLog(self, event):
        """	When View button is clicked
		"""
        # The simulation verbose event occurs
        trigger_event("START_SIM_VERBOSE", parent=self)

        # The simulation verbose event occurs
        trigger_event("VIEW_ACTIVITY_REPORT",
                      parent=self,
                      master=self.current_master)

    ###
    def OnOk(self, event):
        """ When Run button is clicked
		"""

        assert (self.master is not None)

        if self._value.GetValidator().Validate(self._value) or self.ntl:

            ### pour prendre en compte les simulations multiples sans relancer un SimulationDialog
            ### si le thread n'est pas lancé (pas pendant un suspend)
            if self.thread is not None and not self.thread.thread_suspend:
                diagram = self.master.getBlockModel()
                diagram.Clean()
                self.current_master = Container.Diagram.makeDEVSInstance(
                    diagram)
            else:
                self.current_master = self.master

            if isinstance(self.parent, wx.Panel):
                # redirection du stdout ici dans le cas du Panel (sinon dans OnSimulation)
                mainW = self.parent.GetTopLevelParent()
                sys.stdout = mainW.stdioWin

            ### test si le modele et bien charge
            if (self.current_master
                    == None) or (self.current_master.componentSet == []):
                return self.MsgBoxEmptyModel()

            ### dont erase the gauge if ntl
            if not self.ntl:
                # stockage du temps de simulation dans le master
                self.current_master.FINAL_TIME = float(self._value.GetValue())
                self._gauge.SetValue(0)
                ### if _gauge is wx.Slider
                #self._gauge.SetMax(self.current_master.FINAL_TIME)

            self.statusbar.SetBackgroundColour('')
            self.statusbar.SetStatusText("", 1)
            if self.statusbar.GetFieldsCount() > 2:
                self.statusbar.SetStatusText("", 2)

            if (self.thread is None) or (not self.timer.IsRunning()):

                trigger_event("START_BLINK",
                              parent=self,
                              master=self.current_master)
                trigger_event("START_TEST",
                              parent=self,
                              master=self.current_master)

                ### The START_ACTIVITY_TRACKING event occurs
                trigger_event("START_ACTIVITY_TRACKING",
                              parent=self,
                              master=self.current_master)

                ### The START_ACTIVITY_TRACKING event occurs
                trigger_event("START_STATE_TRAJECTORY",
                              parent=self,
                              master=self.current_master)

                ### The START_CONCURRENT_SIMULATION event occurs
                trigger_event("START_CONCURRENT_SIMULATION",
                              parent=self,
                              master=self.current_master)

                ### future call is required because the simulator is flattened during the execution of the strategy 3
                wx.FutureCall(1,
                              trigger_event,
                              'START_DIAGRAM',
                              parent=self,
                              master=self.current_master)

                ### clear all log file
                for fn in filter(lambda f: f.endswith('.devsimpy.log'),
                                 os.listdir(gettempdir())):
                    os.remove(os.path.join(gettempdir(), fn))

                self.thread = simulator_factory(self.current_master,
                                                self.selected_strategy,
                                                self.prof, self.ntl,
                                                self.verbose)
                self.thread.setName(self.title)

                ### si le modele n'a pas de couplage, ou si pas de generateur: alors pas besoin de simuler
                if self.thread.end_flag:
                    self.OnTimer(event)
                else:
                    self.timer.Start(100)

            else:
                #print self.thread.getAlgorithm().trace
                ### for back simulation
                #self.thread.s = shelve.open(self.thread.f.name+'.db',flag='r')
                #self.thread.model = self.thread.s['s'][str(float(self._gauge.GetValue()))]

                ### restart the hiding gauge
                if self.ntl:
                    self._gauge.Show()

                ### restart thread
                self.thread.resume_thread()

            self.Interact(False)

            if self.count >= 100:
                return

            # aucune possibilité d'interagir avec le modele
            #self.parent.Enable(False)

    def Interact(self, access=True):
        """ Enabling and disabling options (buttons, checkbox, ...)
		"""

        self._btn1.Enable(access)
        self._btn2.Enable(not access)
        self._btn3.Enable(not access)
        self._value.Enable(not self.ntl)
        self._cp.Enable(access)

    ###
    def OnStop(self, event):
        """ When Stop button is clicked
		"""

        self.Interact()
        self.thread.terminate()
        self.timer.Stop()
        wx.Bell()

        self._gauge.SetValue(0)
        self.statusbar.SetBackgroundColour('')
        self.statusbar.SetStatusText(_('Interrupted'), 0)
        self.statusbar.SetStatusText("", 1)
        if self.statusbar.GetFieldsCount() > 2:
            self.statusbar.SetStatusText("", 2)

    ###
    def OnSuspend(self, event):
        """ When Stop button is clicked
		"""

        self.Interact()
        self.thread.suspend()

        if self.ntl:
            self._gauge.Hide()

        if self.count == 0 or self.count >= 100 or not self.timer.IsRunning():
            return

        self.statusbar.SetStatusText(_('Suspended'), 0)

        # way to interact with the model
        #self.parent.Enable(True)
        wx.Bell()

    ###
    def OnTimer(self, event):
        """ Give the pourcentage of simulation progress
		"""

        ### if no time limit, gauge pulse
        if self.ntl:
            self._gauge.Pulse()
        else:
            if not isinstance(self.thread.model.timeLast, tuple):
                timeLast = self.thread.model.timeLast
            else:
                timeLast = self.thread.model.timeLast[0]

            self.count = (timeLast / self.thread.model.FINAL_TIME) * 100

            self._gauge.SetValue(self.count)

        ### if simulation is over
        if self.thread.end_flag:

            ### update the status of buttons
            self._btn1.Enable(True)
            self._btn2.Disable()
            self._btn3.Disable()
            self._value.Enable(not self.ntl)
            self._cp.Enable()

            ### check if gauge is full (can appear if timer is too slow)
            if self.count != 100:
                self.count = 100
                self._gauge.SetValue(self.count)

            ### update the status bar
            self.statusbar.SetBackgroundColour('')
            self.statusbar.SetStatusText(_("Completed!"), 0)
            self.statusbar.SetStatusText("%0.4f s" % (self.thread.cpu_time), 1)

            ### is no time limit add some informations in status bar
            if not self.ntl:
                if self.statusbar.GetFieldsCount() > 2:
                    self.statusbar.SetStatusText(str(100) + "%", 2)

            ### stop the timer
            self.timer.Stop()

        ### if the simulation is suspended
        elif not self.thread.thread_suspend:
            ### udpate the status bar
            self.statusbar.SetBackgroundColour('GREY')
            self.statusbar.SetStatusText(_("Processing..."), 0)
            self.statusbar.SetStatusText("%0.4f s" % (self.thread.cpu_time), 1)

            ### is no time limit, add some information in status bar
            if not self.ntl:
                if self.statusbar.GetFieldsCount() > 2:
                    self.statusbar.SetStatusText(str(self.count)[:4] + "%", 2)

            #wx.Yield()
            wx.YieldIfNeeded()

    ###
    def MsgBoxEmptyModel(self):
        """ Pop-up alert for empty model
		"""
        dial = wx.MessageDialog(
            self, _('You want to simulate an empty master model!'),
            _('Simulation Manager'), wx.OK | wx.ICON_EXCLAMATION)

        if (dial.ShowModal() == wx.ID_OK) and (isinstance(
                self.parent, wx.Frame)):
            self.DestroyWin()
        else:
            return

    def DestroyWin(self):
        """ To destroy the simulation frame
		"""

        ### clean status bar
        self.statusbar.SetBackgroundColour('')
        self.statusbar.SetFields([""] * self.statusbar.GetFieldsCount())

        ### try to hidden stdioWin
        try:
            self.parent.stdioWin.frame.Show(False)
        except:
            pass

        try:
            ## left panel enabled
            nb1 = self.parent.mainW.GetControlNotebook()
            nb1.Enable()

            ## menu enabled
            self.parent.tb.Enable()
            for i in xrange(self.parent.menuBar.GetMenuCount()):
                self.parent.menuBar.EnableTop(i, True)

            ### other tab diagram enabled
            nb2 = self.parent.GetDiagramNotebook()
            for p in xrange(nb2.GetPageCount()):
                ## pour tout les tab non selectionner
                if p != nb2.GetSelection():
                    nb2.GetPage(p).Enable()

        except Exception:
            #sys.stdout.write(_("Empty mode over\n"))
            pass

        ### destroy the frame
        self.Destroy()

    def OnQuit(self, event):
        """ When the simulation are stopping
		"""

        # if the simulation is running
        if self.timer.IsRunning():
            dial = wx.MessageDialog(
                self, _('Are you sure to stop simulation?'),
                _('Simulation Manager'),
                wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
            self.thread.suspend()

            ### if user wants to stop simulation process
            if dial.ShowModal() == wx.ID_YES:
                self.DestroyWin()
                self.thread.terminate()
            else:
                self.thread.resume_thread()

        else:
            self.DestroyWin()

    def ErrorManager(self, msg):
        """ An error is occurred.
		"""

        ### try to find the file which have the error from traceback
        devs_error = False
        try:
            typ, val, tb = msg.data
            trace = traceback.format_exception(typ, val, tb)

            mainW = wx.GetApp().GetTopWindow()
            ### paths in traceback
            paths = filter(
                lambda a: a.split(',')[0].strip().startswith('File'), trace)
            ### find if DOMAIN_PATH is in paths list (inversed because traceback begin by the end)
            for path in paths[::-1]:
                ### find if one path in trace comes from Domain or exported path list
                for d in [DOMAIN_PATH] + mainW.GetExportPathsList():

                    if d in path:
                        devs_error = True
                        break

        except Exception, info:
            print _("Error in ErrorManager: %s" % info)

        ### if error come from devs python file
        if devs_error:

            ### simulate event button for the code editor
            event = wx.PyCommandEvent(wx.EVT_BUTTON.typeId, self._btn1.GetId())

            ### Error dialog
            if not Container.MsgBoxError(event, self.parent, msg.data):
                ### if user dont want correct the error, we destroy the simulation windows
                self.DestroyWin()
            else:
                ### if user want to correct error through an editor, we stop simulation process for trying again after the error is corrected.
                self.OnStop(event)
        else:

            raise msg
    def SelectProp(self, evt):
        """
		"""

        row, col = evt.GetRow(), evt.GetCol()

        table = self.GetTable()

        typ = table.dataTypes[row][1]
        prop = self.GetCellValue(row, 0)

        if prop == 'fill' or re.findall(
                "[.]*color[.]*", prop, flags=re.IGNORECASE):
            val = self.GetCellValue(row, 1)
            dlg = wx.ColourDialog(self.parent)
            dlg.GetColourData().SetChooseFull(True)
            if dlg.ShowModal() == wx.ID_OK:
                data = dlg.GetColourData()
                val = str([RGBToHEX(data.GetColour().Get())])
                self.SetCellValue(row, 1, val)
            else:
                dlg.Destroy()
                return False

            dlg.Destroy()

            self.AcceptProp(row, col)

        elif prop == 'font':
            val = eval(self.GetCellValue(row, 1))
            default_font = wx.Font(val[0], val[1], val[2], val[3], False,
                                   val[4])
            data = wx.FontData()
            if sys.platform == 'win32':
                data.EnableEffects(True)
            data.SetAllowSymbols(False)
            data.SetInitialFont(default_font)
            data.SetRange(10, 30)
            dlg = wx.FontDialog(self.parent, data)
            if dlg.ShowModal() == wx.ID_OK:
                data = dlg.GetFontData()
                font = data.GetChosenFont()
                color = data.GetColour()
                val = [
                    font.GetPointSize(),
                    font.GetFamily(),
                    font.GetStyle(),
                    font.GetWeight(),
                    font.GetFaceName()
                ]
                self.SetCellValue(row, 1, str(val))
            else:
                dlg.Destroy()
                return False

            dlg.Destroy()

            self.AcceptProp(row, col)

        elif prop == 'label':

            d = LabelGUI.LabelDialog(self.parent, self.parent.model)
            d.ShowModal()

            self.SetCellValue(row, 1, str(self.parent.model.label))
            self.AcceptProp(row, col)

        elif prop == 'image_path':

            dlg = ib.ImageDialog(self, os.path.join(HOME_PATH))
            dlg.Centre()

            if dlg.ShowModal() == wx.ID_OK:
                val = os.path.normpath(dlg.GetFile())
                if val != self.GetCellValue(row, 1):
                    self.SetCellValue(row, 1, val)
                    self.canvas.UpdateShapes([self.parent.model])
            else:
                dlg.Destroy()
                return False

            dlg.Destroy()

            self.AcceptProp(row, col)

        elif 'filename' in str(prop).lower():
            wcd = _('Data files All files (*)|*')
            val = self.GetCellValue(row, 1)
            default_dir = os.path.dirname(val) if os.path.exists(
                os.path.dirname(val)) else HOME_PATH
            dlg = wx.FileDialog(self,
                                message=_("Select file ..."),
                                defaultDir=default_dir,
                                defaultFile="",
                                wildcard=wcd,
                                style=wx.OPEN | wx.CHANGE_DIR)
            if dlg.ShowModal() == wx.ID_OK:
                val = os.path.normpath(dlg.GetPath())
                if val != self.GetCellValue(row, 1):
                    self.SetCellValue(row, 1, val)
                    self.canvas.UpdateShapes([self.parent.model])
            else:
                dlg.Destroy()
                return False

            dlg.Destroy()

            self.AcceptProp(row, col)

        elif prop == 'python_path':

            model = self.parent.model

            ### for .amd or .cmd
            if model.model_path != '':
                wcd = _(
                    'Atomic DEVSimPy model (*.amd)|*.amd|Coupled DEVSimPy model (*.cmd)|*.cmd|All files (*)|*'
                )
            else:
                wcd = _('Python files (*.py)|*.py|All files (*)|*')

            default_dir = os.path.dirname(model.python_path) if os.path.exists(
                os.path.dirname(model.python_path)) else DOMAIN_PATH
            dlg = wx.FileDialog(self,
                                message=_("Select file ..."),
                                defaultDir=default_dir,
                                defaultFile="",
                                wildcard=wcd,
                                style=wx.OPEN | wx.CHANGE_DIR)
            if dlg.ShowModal() == wx.ID_OK:
                new_python_path = os.path.normpath(dlg.GetPath())

                ### if the user would like to load a compressed python file, he just give the name of compressed file that contain the python file
                if zipfile.is_zipfile(new_python_path):
                    zf = zipfile.ZipFile(new_python_path, 'r')
                    new_python_path = os.path.join(
                        new_python_path,
                        filter(
                            lambda f: f.endswith('.py') and f != 'plugins.py',
                            zf.namelist())[0])
                    ### update model path
                    model.model_path = os.path.dirname(new_python_path)

                self.SetCellValue(row, 1, new_python_path)

                # behavioral args update (because depends of the new class coming from new python file)
                new_cls = Components.GetClass(new_python_path)

                if inspect.isclass(new_cls):

                    ### update attributes (behavioral ang graphic)
                    model.args = Components.GetArgs(new_cls)
                    model.SetAttributes(Attributable.GRAPHICAL_ATTR)

                    ### TODO: when ScopeGUI and DiskGUI will be amd models, delete this line)
                    ### delete xlabel and ylabel attributes if exist
                    model.RemoveAttribute('xlabel')
                    model.RemoveAttribute('ylabel')
                    ### Update of DEVSimPy model from new python behavioral file (ContainerBlock is not considered because he did not behavioral)
                    if new_cls.__name__ in ('To_Disk', 'MessagesCollector'):
                        model.__class__ = Container.DiskGUI
                    elif new_cls.__name__ == 'QuickScope':
                        model.__class__ = Container.ScopeGUI
                        model.AddAttribute("xlabel")
                        model.AddAttribute("ylabel")
                    elif True in map(lambda a: 'DomainStructure' in str(a),
                                     new_cls.__bases__):
                        model.__class__ = Container.ContainerBlock
                    else:
                        model.__class__ = Container.CodeBlock

                    ### if we change the python file from zipfile we compresse the new python file and we update the python_path value
                    if zipfile.is_zipfile(model.model_path):
                        zf = ZipManager.Zip(model.model_path)
                        zf.Update([new_python_path])
                        #model.model_path =

                    ### update flag and color if bad filename
                    if model.bad_filename_path_flag:
                        model.bad_filename_path_flag = False
                else:
                    Container.MsgBoxError(evt, self, new_cls)
                    dlg.Destroy()
                    return False
            else:
                dlg.Destroy()
                return False

            dlg.Destroy()

            self.AcceptProp(row, col)

        elif typ == "list":
            frame = ListEditor(self,
                               wx.ID_ANY,
                               _('List editor'),
                               values=self.GetCellValue(row, 1))
            if frame.ShowModal() == wx.ID_CANCEL:
                self.SetCellValue(row, 1, frame.GetValueAsString())
            else:
                frame.Destroy()

            self.AcceptProp(row, col)

        elif typ == 'dict':
            frame = DictionaryEditor(self,
                                     wx.ID_ANY,
                                     _('List editor'),
                                     values=self.GetCellValue(row, 1))
            if frame.ShowModal() == wx.ID_CANCEL:
                self.SetCellValue(row, 1, frame.GetValueAsString())
            else:
                frame.Destroy()

            self.AcceptProp(row, col)
        elif 'choice' in typ:
            self.AcceptProp(row, col)
        else:
            pass

        ### all properties grid update (because the python classe has been changed)
        ### here, because OnAcceptProp should be executed before
        if prop == 'python_path':

            ### Update table from new model
            table.UpdateRowBehavioralData(model)
            self.SetTable(table, False)
            self.ForceRefresh()
            self.AutoSizeColumns()

            # code updating
            if isinstance(model, Achievable):
                new_code = CodeCB(self.parent, wx.ID_ANY, model)
                #self.parent.boxH.Remove(0)
                if hasattr(self.parent, '_boxH'):
                    # DeleteWindows work better in vista
                    if wx.VERSION_STRING < '4.0':
                        self.parent._boxH.DeleteWindows()
                        self.parent._boxH.AddWindow(new_code,
                                                    1,
                                                    wx.EXPAND,
                                                    userData='code')
                    else:
                        self.parent._boxH.Clear()
                        self.parent._boxH.Add(new_code,
                                              1,
                                              wx.EXPAND,
                                              userData='code')

                    self.parent._boxH.Layout()
                else:
                    sys.stdout.write("_boxH is unknown!")