diff --git a/Components.py b/Components.py index c6f78bf1..1dbc95d6 100644 --- a/Components.py +++ b/Components.py @@ -34,8 +34,6 @@ if builtins.__dict__['GUI_FLAG']: import wx - - _ = wx.GetTranslation if wx.VERSION_STRING < '2.9': from wx.lib.pubsub import Publisher @@ -51,7 +49,7 @@ #from DomainInterface.DomainBehavior import DomainBehavior #from DomainInterface.DomainStructure import DomainStructure from ReloadModule import recompile -from Utilities import GetActiveWindow, path_to_module, install_and_import +from Utilities import GetActiveWindow, path_to_module, install_and_import, printOnStatusBar from NetManager import Net from SimpleFrameEditor import FrameEditor from which import which @@ -62,12 +60,6 @@ ### ########################################################### -def printOnStatusBar(statusbar, data={}): - """ Send data on status bar - """ - for k,v in list(data.items()): - statusbar.SetStatusText(v, k) - def getClassMember(python_file = ''): """ Get class member from python file. """ diff --git a/Container.py b/Container.py index 0b695500..6c3ea8a7 100644 --- a/Container.py +++ b/Container.py @@ -110,7 +110,7 @@ sys.modules['Savable'] = sys.modules['Mixins.Savable'] from Decorators import BuzyCursorNotification, StatusBarNotification, ProgressNotification, Pre_Undo, Post_Undo, cond_decorator -from Utilities import HEXToRGB, RGBToHEX, relpath, GetActiveWindow, playSound, sendEvent, getInstance, FixedList, getObjectFromString, getTopLevelWindow +from Utilities import HEXToRGB, RGBToHEX, relpath, GetActiveWindow, playSound, sendEvent, getInstance, FixedList, getObjectFromString, getTopLevelWindow, printOnStatusBar from Patterns.Observer import Subject, Observer if builtins.__dict__['GUI_FLAG']: @@ -212,12 +212,6 @@ def MsgBoxError(event, parent, msg): else: wx.MessageBox(_("There is errors in python file.\nTrying to translate error informations: %s %s %s")%(typ, val, tb), _("Error"), wx.OK|wx.ICON_ERROR) -def printOnStatusBar(statusbar, data={}): - """ Send data on status bar - """ - for k,v in list(data.items()): - statusbar.SetStatusText(v, k) - def CheckClass(m): """ Check if class is ok and return it. """ @@ -3466,7 +3460,7 @@ def OnExport(self, event): try: ### Block is Savable self.SaveFile(path) - + printOnStatusBar(mainW.statusbar, {0:_('%s Exported')%label, 1:''}) except IOError as error: diff --git a/DiagramNotebook.py b/DiagramNotebook.py index acd972cf..5e97cbf3 100644 --- a/DiagramNotebook.py +++ b/DiagramNotebook.py @@ -37,6 +37,7 @@ from DetachedFrame import DetachedFrame from PrintOut import Printable +from Utilities import printOnStatusBar _ = wx.GetTranslation @@ -194,7 +195,7 @@ def OnPageChanged(self, evt): if hasattr(self.parent, 'statusbar'): diagram = canvas.GetDiagram() txt = _('%s modified')%(self.GetPageText(id)) if diagram.modify else "" - self.parent.statusbar.SetStatusText(txt) + printOnStatusBar(self.parent.statusbar,{0:txt}) ### propagate event also error in OnClosePage because GetSelection is wrong evt.Skip() diff --git a/Editor.py b/Editor.py index c30546c4..51c3cd0b 100644 --- a/Editor.py +++ b/Editor.py @@ -42,7 +42,7 @@ from wx import stc from Decorators import redirectStdout -from Utilities import path_to_module, PrintException +from Utilities import path_to_module, PrintException, printOnStatusBar import ReloadModule import ZipManager @@ -1645,7 +1645,7 @@ def Notification(self, modify, *args): if hasattr(self, 'statusbar'): for i, s in enumerate(args): - self.statusbar.SetStatusText(s, i) + printOnStatusBar(self.statusbar, {i:s}) ### NOTE: Editor :: StatusBar => Create a status bar def GetStatusBar(self): diff --git a/LibPanel.py b/LibPanel.py index 06155cf1..edcc8f65 100644 --- a/LibPanel.py +++ b/LibPanel.py @@ -34,7 +34,7 @@ class SearchLib(wx.SearchCtrl): def __init__(self, *args, **kwargs): """ """ - wx.SearchCtrl.__init__(self, *args, **kwargs) + super(SearchLib, self).__init__(*args, **kwargs) self.treeChildren = [] self.treeCopy = None @@ -63,7 +63,7 @@ class LibPanel(wx.Panel): """ """ def __init__(self, parent, name): - wx.Panel.__init__(self, parent=parent, id=wx.NewIdRef(), name=name) + super(LibPanel, self).__init__(parent, name=name) libSizer = wx.BoxSizer(wx.VERTICAL) @@ -154,6 +154,7 @@ def __set_tips(self): """ self.propToolTip =[_("Select model and instantiate it in the diagram (right part) using a drag-and-drop.")] + ### for Phoenix version () if wx.VERSION_STRING < '4.0': self.SetToolTipString(self.propToolTip[0]) diff --git a/LibraryTree.py b/LibraryTree.py index 7307f176..031ddc81 100644 --- a/LibraryTree.py +++ b/LibraryTree.py @@ -33,7 +33,7 @@ import Container import Menu -from Utilities import replaceAll, getPYFileListFromInit, path_to_module +from Utilities import replaceAll, getPYFileListFromInit, path_to_module, printOnStatusBar, NotificationMessage, install_and_import from Decorators import BuzyCursorNotification from Components import BlockFactory, DEVSComponent, GetClass from ZipManager import Zip, getPythonModelFileName @@ -208,8 +208,7 @@ def OnLeftClick(self, evt): self.UnselectAll() mainW = wx.GetApp().GetTopWindow() - mainW.statusbar.SetStatusText('', 0) - mainW.statusbar.SetStatusText('', 1) + printOnStatusBar(mainW.statusbar, {0:'', 1:''}) #self.SetFocus() evt.Skip() @@ -834,29 +833,39 @@ def CheckItem(self, path): ### Check the class info = Container.CheckClass(file_path) - ### there is error during the chek of class ? + ### there is error during the chek of class? if isinstance(info, tuple): - ### recompile if no error - info = recompile(path_to_module(file_path)) - - ### there is error during recompilation ? - if isinstance(info, (Exception,str)): - ### Until it has parent, we redifine icon to inform user - while(item): - ### change image - self.SetItemImage(item, self.not_importedidx, wx.TreeItemIcon_Normal) - ### next parent item - item = self.GetItemParent(item) + + ### if module are missing, we propose to install him with pip + if ModuleNotFoundError in info: + package = info[1].name + if install_and_import(package): + wx.CallAfter(self.UpdateAll) + + ### else there is an error in the code of the model... else: - ### change image - self.SetItemImage(item, self.pythonfileidx, wx.TreeItemIcon_Normal) - #### Until it has parent, we redifine icon to inform user + ### recompile if no error + info = recompile(path_to_module(file_path)) + + ### there is error during recompilation? + if isinstance(info, (Exception,str)): + ### Until it has parent, we redifine icon to inform user while(item): - #### change image - self.SetItemImage(item, self.fldropenidx if self.IsExpanded(item) else self.fldridx, wx.TreeItemIcon_Normal) - #### next parent item + ### change image + self.SetItemImage(item, self.not_importedidx, wx.TreeItemIcon_Normal) + ### next parent item item = self.GetItemParent(item) + else: + ### change image + self.SetItemImage(item, self.pythonfileidx, wx.TreeItemIcon_Normal) + + #### Until it has parent, we redifine icon to inform user + while(item): + #### change image + self.SetItemImage(item, self.fldropenidx if self.IsExpanded(item) else self.fldridx, wx.TreeItemIcon_Normal) + #### next parent item + item = self.GetItemParent(item) else: sys.stdout.write("File %s is not checked!") @@ -912,6 +921,8 @@ def OnUpdateAll(self, event): """ Update all imported domain """ self.UpdateAll() + + NotificationMessage(_('Information'), _("All librairies have been succeffully updated!"), self, timeout=5) def OnMCCClick(self, event): """ @@ -989,14 +1000,22 @@ def OnItemRefresh(self, evt): """ Refresh action has been invoked. """ - item = self.GetSelection() - path = self.GetItemPyData(item) - ext = os.path.splitext(path)[1] + try: + item = self.GetSelection() + path = self.GetItemPyData(item) + ext = os.path.splitext(path)[1] + + if ext in (".py",".pyc"): + self.CheckItem(os.path.splitext(path)[0]) + else: + self.CheckItem(path) + except: + NotificationMessage(_('Error'), _("Error updating the model %s")%self.GetItemText(item), self, timeout=5) + finally: + if self.GetItemImage(item) != 1: + + NotificationMessage(_('Information'), _("Model %s has been succeffully updated!")%self.GetItemText(item), self, flag=wx.ICON_ERROR, timeout=5) - if ext in (".py",".pyc"): - self.CheckItem(os.path.splitext(path)[0]) - else: - self.CheckItem(path) ### def OnItemEdit(self, evt): """ Edition menu has been invoked. diff --git a/SimulationGUI.py b/SimulationGUI.py index d07f6941..03a9b01c 100644 --- a/SimulationGUI.py +++ b/SimulationGUI.py @@ -48,7 +48,7 @@ 'PyDEVS':os.path.join(os.pardir,'DEVSKernel','PyDEVS'),\ 'PyPDEVS':os.path.join(os.pardir,'DEVSKernel','PyPDEVS')} -from Utilities import IsAllDigits, playSound +from Utilities import IsAllDigits, playSound, printOnStatusBar from pluginmanager import trigger_event, is_enable from Patterns.Strategy import * from Decorators import BuzyCursorNotification, hotshotit @@ -492,9 +492,9 @@ def OnOk(self, event): #self._gauge.SetMax(self.current_master.FINAL_TIME) self.statusbar.SetBackgroundColour('') - self.statusbar.SetStatusText("", 1) + printOnStatusBar(self.statusbar, {1:""}) if self.statusbar.GetFieldsCount() > 2: - self.statusbar.SetStatusText("", 2) + printOnStatusBar(self.statusbar, {2:""}) if (self.thread is None) or (not self.timer.IsRunning()): @@ -573,10 +573,10 @@ def OnStop(self, event): self._gauge.SetValue(0) self.statusbar.SetBackgroundColour('') - self.statusbar.SetStatusText(_('Interrupted'), 0) - self.statusbar.SetStatusText("", 1) + printOnStatusBar(self.statusbar, {0:_('Interrupted')}) + printOnStatusBar(self.statusbar, {1:""}) if self.statusbar.GetFieldsCount() > 2: - self.statusbar.SetStatusText("", 2) + printOnStatusBar(self.statusbar, {2:""}) ### def OnSuspend(self, event): @@ -592,7 +592,7 @@ def OnSuspend(self, event): if self.count == 0 or self.count >= 100 or not self.timer.IsRunning(): return - self.statusbar.SetStatusText(_('Suspended'),0) + printOnStatusBar(self.statusbar, {0:_('Suspended')}) # way to interact with the model #self.parent.Enable(True) @@ -633,13 +633,12 @@ def OnTimer(self, event): ### update the status bar self.statusbar.SetBackgroundColour('') - self.statusbar.SetStatusText(_("Completed!"), 0) - self.statusbar.SetStatusText(self.GetClock(), 1) - + printOnStatusBar(self.statusbar, {0:_("Completed!"), 1:self.GetClock()}) + ### 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) + printOnStatusBar(self.statusbar, {2:str(100)+"%"}) ### stop the timer self.timer.Stop() @@ -649,14 +648,12 @@ def OnTimer(self, event): ### udpate the status bar self.statusbar.SetBackgroundColour('GREY') - self.statusbar.SetStatusText(_("Processing..."), 0) - self.statusbar.SetStatusText(self.GetClock(), 1) - #self.statusbar.SetStatusText("%0.4f s"%(self.thread.cpu_time), 1) + printOnStatusBar(self.statusbar, {0:_("Processing..."), 1:self.GetClock()}) ### 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) + printOnStatusBar(self.statusbar, {2:str(self.count)[:4]+"%"}) #wx.Yield() wx.YieldIfNeeded() @@ -691,8 +688,7 @@ def SetFields(self): if wx.VERSION_STRING < '4.0': self.statusbar.SetFields([""]*self.statusbar.GetFieldsCount()) else: - for i in range(self.statusbar.GetFieldsCount()): - self.statusbar.SetStatusText("",i) + printOnStatusBar(self.statusbar, {i:'' for i in range(self.statusbar.GetFieldsCount())}) def DestroyWin(self): """ To destroy the simulation frame diff --git a/SpreadSheet.py b/SpreadSheet.py index 92ee4d62..11f96a04 100644 --- a/SpreadSheet.py +++ b/SpreadSheet.py @@ -35,6 +35,7 @@ #from Container import * from PlotGUI import * +from Utilities import printOnStatusBar ### class MySheet(sheet.CSheet): @@ -251,7 +252,7 @@ def EnableGraphIcon(self, msg): else: toolbar = self.GetToolBar() toolbar.EnableTool(self.chart.GetId(), msg) - self.statusbar.SetStatusText("", 0) + printOnStatusBar(self.statusbar, {0:""}) ### def OnTab(self, event): @@ -265,7 +266,7 @@ def OnProgress(self, msg): """ Update status bar with loading data progression """ pourcent = 100*float(msg) - self.statusbar.SetStatusText(_("Loading data... (%d %%)")%int(pourcent), 0) + printOnStatusBar(self.statusbar, {0:_("Loading data... (%d %%)")%int(pourcent)}) ### def AddPage(self, data = [[]], label = ""): diff --git a/Utilities.py b/Utilities.py index d5f08f9d..27b8908d 100644 --- a/Utilities.py +++ b/Utilities.py @@ -44,6 +44,9 @@ import fnmatch import urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, http.client +import pip +import importlib + # Used for smooth (spectrum) try: from numpy import * @@ -59,9 +62,6 @@ sys.stdout.write("Unknown operating system.\n") sys.exit() -import pip -import importlib - #------------------------------------------------------------------------------- def PrintException(): exc_type, exc_obj, tb = sys.exc_info() @@ -72,6 +72,31 @@ def PrintException(): line = linecache.getline(filename, lineno, f.f_globals) print('EXCEPTION IN {}\nLINE {}\n"{}": {}'.format(filename, lineno, line.strip(), exc_obj)) +def printOnStatusBar(statusbar, data={}): + """ Send data on status bar + """ + for k,v in list(data.items()): + statusbar.SetStatusText(v, k) + +def NotificationMessage(title,message,parent,flag=wx.ICON_INFORMATION, timeout=False): + notify = wx.adv.NotificationMessage( + title=title, + message=message, + parent=parent, flags=flag) + + # Various options can be set after the message is created if desired. + # notify.SetFlags(# wx.ICON_INFORMATION + # wx.ICON_WARNING + # # wx.ICON_ERROR + # ) + # notify.SetTitle("Wooot") + # notify.SetMessage("It's a message!") + # notify.SetParent(self) + if timeout: + notify.Show(timeout=timeout) # 1 for short timeout, 100 for long timeout + else: + notify.Show() + def now(): """ Returns the current time formatted. """ @@ -131,15 +156,17 @@ def install_and_import(package): importlib.import_module(package) installed = True except: - dial = wx.MessageDialog(None, _('Do you want to install the %s using pip?'%package), _('Install Package'), wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) - - if dial.ShowModal() == wx.ID_YES: - pip.main(['install', package]) - installed = True - dial.Destroy() - else: - installed = False - dial.Destroy() + + if pip.main(['search', package]) != 23: + dial = wx.MessageDialog(None, _('We find that the package %s is missing. \n\n Do you want to install him using pip?'%(package)), _('Install Package'), wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) + + if dial.ShowModal() == wx.ID_YES: + pip.main(['install', package]) + installed = True + dial.Destroy() + else: + installed = False + dial.Destroy() finally: if installed : globals()[package] = importlib.import_module(package) diff --git a/devsimpy.py b/devsimpy.py index 08bc7c03..2f731931 100644 --- a/devsimpy.py +++ b/devsimpy.py @@ -186,7 +186,7 @@ from PreferencesGUI import PreferencesGUI from pluginmanager import load_plugins, enable_plugin from which import which -from Utilities import GetUserConfigDir, install_and_import +from Utilities import GetUserConfigDir, install_and_import, printOnStatusBar, NotificationMessage from Decorators import redirectStdout, BuzyCursorNotification from DetachedFrame import DetachedFrame from LibraryTree import LibraryTree @@ -792,23 +792,8 @@ def OnDeleteRecentFiles(self, event): self.cfg.Write("openFileList", str(eval("self.openFileList"))) self.cfg.Flush() - notify = wx.adv.NotificationMessage( - title="Information", - message="Recent opened files list has been deleted!", - parent=self, flags=wx.ICON_INFORMATION) - - # Various options can be set after the message is created if desired. - # notify.SetFlags(# wx.ICON_INFORMATION - # wx.ICON_WARNING - # # wx.ICON_ERROR - # ) - # notify.SetTitle("Wooot") - # notify.SetMessage("It's a message!") - # notify.SetParent(self) - - notify.Show(timeout=5) # 1 for short timeout, 100 for long timeout - # notify.Close() # Hides the notification. - + NotificationMessage(_("Information"), _("Recent opened files list has been deleted!"), self, timeout=5) + dial.Destroy() def OnCreatePerspective(self, event): @@ -1071,7 +1056,7 @@ def OnZoom(self, event): currentPage.scaley=max(currentPage.scaley+.05,.3) currentPage.Refresh() - self.statusbar.SetStatusText(_('Zoom In')) + printOnStatusBar(self.statusbar,{0:_('Zoom In')}) ### def OnUnZoom(self, event): @@ -1088,7 +1073,7 @@ def OnUnZoom(self, event): currentPage.scaley=currentPage.scaley-.05 currentPage.Refresh() - self.statusbar.SetStatusText(_('Zoom Out')) + printOnStatusBar(self.statusbar,{0:_('Zoom Out')}) ### def AnnuleZoom(self, event): @@ -1105,7 +1090,7 @@ def AnnuleZoom(self, event): currentPage.scaley = 1.0 currentPage.Refresh() - self.statusbar.SetStatusText(_('No Zoom')) + printOnStatusBar(self.statusbar,{0:_('No Zoom')}) ### def OnNew(self, event): @@ -1313,8 +1298,6 @@ def OnSaveFile(self, event): tb = self.GetToolBar() ### enable save button on status bar tb.EnableTool(Menu.ID_SAVE, diagram.modify) - - #self.statusbar.SetStatusText(_('%s saved')%diagram.last_name_saved) else: wx.MessageBox( _('Error saving file.') ,_('Error'), wx.OK | wx.ICON_ERROR) else: @@ -2190,7 +2173,7 @@ def ShowMain(self): self.app.frame = MainApplication(None, wx.NewIdRef(), 'DEVSimPy %s'%__version__) - self.app.frame.statusbar.SetStatusText(_('wxPython %s - python %s'%(wx.version(),platform.python_version())),1) + printOnStatusBar(self.app.frame.statusbar,{1:_('wxPython %s - python %s'%(wx.version(),platform.python_version()))}) # keep in a attribute of stdio which is invisible until now self.app.frame.stdioWin = self.app.stdioWin