C:/mesDocs/QT_confDbVis_canvas/mainWindow.py

Go to the documentation of this file.
00001 ##
00002 #  cdbVis (Configuration DataBase Visualization Tool).
00003 # 
00004 #     This program is designed to help human users of the LHCb Configuration 
00005 #     Database. It supports them understanding the contents saved in this 
00006 #     database by having a visual view on the components, their connections and 
00007 #     the parameters and information saved with them.
00008 # 
00009 #     This program should give the user a feel of how the system and subsystems of the LHCb
00010 #     system is built up and assembled. The user should be able to do all alterings on the system
00011 #     in this GUI (Graphical User Interface). The GUI should be very intuitive and easy to use
00012 #     for people who are both familiar and unfamiliar with the system.
00013 #     
00014 #     The first version(s) of this program was written by Felix Schmidt-Eisenlohr during summer 2004
00015 #     as work project at the CERN Summer Student Programme 2004. Because the program was far from
00016 #     finished, Technical Student Thomas Johansen continued working on this program from August 2005.
00017 # 
00018 
00019 from GUImainWindow import *
00020 import ConfigParser
00021 from CreateDeviceType import *
00022 from CreateDevice import *
00023 # from CreateLinkType import *
00024 from CreateLink import *
00025 
00026 from sys import *
00027 import csv
00028 
00029 
00030 
00031 
00032 # Global configfile reference
00033 configfile = None
00034 
00035 ##########################################################################
00036 # MainWindow class
00037 ##########################################################################
00038 
00039         
00040 ##
00041 #  This is the Main Window of the CdbVis program. 
00042 #     
00043 class mainWindow(GUImainWindow, dbUpdate):
00044 
00045     ##
00046     #  Initialize main window frame.
00047     #             @parent -- parent window (usually CdbVis)
00048     #         
00049     def __init__(self, app, parent = None,name = None,fl = 0):
00050         # Appel du constructeur du parent
00051         # todo :  Set to fixed size: 800x600 at startup, recommended view is full screen.
00052         GUImainWindow.__init__(self,parent = None,name = None,fl = 0)
00053         self.connect(self.fileExitAction,SIGNAL("activated()"),self.close)
00054         
00055         self.__cfg = None
00056         self.app = app
00057         #status bar
00058         # la creation de la status bar devra se faire dans la classe : GUImainWindow
00059         
00060         # mainPanel : Covers the whole mainWindow except menu bar, tool bar and status bar
00061         
00062         # myLayout = QGridLayout(self.centralWidget(),1,1,5,6," My Layout")
00063         # self.panel = mainPanel(self,self.centralWidget(),"panelFrame")
00064         # myLayout.addWidget(self.panel,0,0)
00065         ##########myLayout.setStretchFactor(self.visWindow,1)
00066         # self.resize(QSize(800,600).expandedTo(self.minimumSizeHint()))
00067         
00068         logfilename = "CdbVis.log"
00069         self.__logsessionfile = os.path.normpath(logfilename)
00070         
00071         try:
00072                 file = open(self.__logsessionfile,"r")
00073                 file = open(self.__logsessionfile,"w")
00074         except IOError,err:
00075                 file = open(self.__logsessionfile,"w") #file does not exist, ignore recover, but create file
00076         
00077         file.write("")
00078         file.close()
00079 
00080         # Should be possible to set by the user whether he/she wants to see error messages in message boxes or in the
00081         # status bar
00082         self.__showmsgbox = False
00083         self.__previouserror = [] # we store the previous error, so that the user can easily access it and view it in a
00084         # message box if he/she clicks on the message icon in the status bar.
00085 
00086     #methode
00087         self.ShowError("Configuration Database Visualizer Version " + VERSION, ERR_INFORMATION,False)
00088         self.pbarvalue = 0
00089         #zoom toolbar
00090         self.zoomvalues = [10,15,20,25,33,50,75,100,150,200,400]
00091         self.__zoomvalue = 100 #default startup value
00092         self.__zoomindex = 0
00093         x = 0
00094         for itm in self.zoomvalues:
00095                 if itm == 100:
00096                         self.__zoomindex = x
00097                 x += 1
00098 
00099         
00100         #DBSystem object; which contains the connect/disconnect confdb methods
00101         self.__cdb = None
00102 
00103         # At the moment, not in use. 
00104         self.__availablesystems = []
00105         self.__availabledevicetypes = []
00106         self.__availabledevices = []
00107         self.__availableports = []
00108         self.__availablelinktypes = []
00109         self.__availablelinks = []
00110 
00111         # mapping between name and ids, not used much
00112         self.__linktypetable = {}
00113         self.__devicetable = {}
00114 
00115         #what systems, devicetypes,devices etc are active; the current one.
00116         # Used a lot.
00117         self.__activesystem = None
00118         self.__activedevicetype = None
00119         self.__activedevice = None
00120         self.__activeport = None
00121         self.__activelinktype = None
00122         self.__activelink = None
00123 
00124         # The name of the only link type that should be shown in visual window, or "" if all should be visible.
00125         self.__restrictedlinktype = ""
00126         self.__restrictedLinks = False
00127         self.__restrictedsparepart = ""
00128         self.__list_sparedevice=[]
00129         self.__devicenrlist = {} #??
00130         self.__lastlinknr = 0 #last temporary link name (id) given to a link, so that the next one will be set to
00131         # self.__lastlinknr + 1
00132 
00133         #other lists
00134         """ The dirty objects list is a list of all kinds of objects that have been created or modified since the last time the user stored anything in the database. Whenever information is going to be read from objects, we have to see in this list if the object is placed here for creation/modification. Then we will get the objectinfo from this list, remove it from the list, and append it again when it is changed (or not if it is deleted) """
00135         self.__dirtyobjects = []
00136         """ Dirty objects, for renaming linktypes, devicetypes or devices. Cannot be a part of dirtyobjects because 
00137         it is not connected to UNDO and REDO functionality.
00138         """
00139         self.__undolist = [] #information needed for undo
00140         self.__redolist = [] #Once you undo, the undo object is appended to the redo list. information needed for redo
00141         self.__redoobjectlist = [] #undone objects, opposite to dirtyobjects list. Can be added back to dirtylist and savelist if REDOed
00142 
00143         self.__visualundolist = [] #On delete, store object here if want to UNDO it later
00144         self.__visualredolist = [] #When UNDOing a create 
00145 
00146         
00147         # Rename lists for renamed objects
00148         self.__renameobjects = [] # Objects of all kinds with the new name and old name set
00149         self.__oldnames = [] # Names of all kinds of objects that has been renamed (the name before renaming)
00150         self.__oldnamesrenamed = {} # Names of all kinds of objects that has been renamed; mapping oldname : newname
00151         self.__newnames = [] # names of all kinds of objects that has been renamed (the name after renaming)
00152         self.__newnamesrenamed = {} # names of all kinds of objects that has been renamed; mapping newname : oldname
00153 
00154         self.__currentview = 0 #keep track on when views are changed, and whether the
00155                                #undone/redone objects should be added in visual window
00156         self.__prevview = ID_SUCCESSORS_MODE #neighbor view
00157 
00158         # other containers etc.
00159         self.__selectcreatedevtype = "" # device type selected in device combo box, the device to be created will get this
00160                                         # deice type
00161 
00162         # set up user mode
00163         self.__userMode = ID_NAVIGATION_MODE #default
00164         self.fileStore_object_in_DBAction.setEnabled(False)
00165         #self.__userMode = ID_CREATION_MODE
00166         self.__viewmode = ID_SUCCESSORS_MODE #ID_PATHS_MODE  #default, neighbor view
00167         '''     self.GetStatusBar().SetStatusText("Navigation Mode", 5)
00168         self.GetStatusBar().SetStatusText("Neighbour View", 6)
00169         '''
00170         self.__processubsystems = True #??
00171 
00172         #device types that does not have a colour set
00173         self.tempdevicetypecolour = {}
00174 
00175         #set up to use tool_SELECT on default
00176         self.__userModeTool = tool_SELECT # normal arrow in the visual window
00177 
00178         #methode
00179         self.systemlevels = {"MUON":4,"VELO":2,"VELO_A":1,"VELO_C":1,"MUON_A":3,"MUON_C":3,"RICH1":2,"TT":2,"OT":3,"IT":2,"RICH2":2,"PSSPD":1,"ECAL":1,"HCAL":1,"TFC":1,"DAQ":1,"L0MUON":1,"L0DU":1,"L0CALO":1,"Spare devices":1,"PUS":1,"ST":2,"OT_A":1,"OT_C":1,"RICH":3,"L0TRIGGER":2,"ECS":1,"PRS":1,"":0,None:0 }
00180 
00181         self.layouttype = INV_PARABOLIC
00182         self.DoNotShow = []  #added by walid : containt the devices to remove
00183 
00184 
00185     #############################################
00186     # Methods                                   #
00187     #############################################
00188     # def DoCloneHelper(self,...):
00189         # self.pamel.visWindow.DoCloneHelper
00190     
00191     
00192     ##
00193     #  Returns the current layout type that is used.
00194     #   !return - Integer constant for the layout type
00195     def GetLayoutType(self):
00196         return self.layouttype
00197     
00198     ##
00199     #  Sets the current layout type that is used for node layout.
00200     #   @layouttype - An integer constant defining the layouttype to be used (0->4)
00201     def SetLayoutType(self,layouttype):
00202         self.layouttype = layouttype
00203 
00204     ##
00205     #  Get a random colour for the given device type, if the device type is not already set. If
00206     #   it is set, then return the temporary device type colour for that device type.
00207     #   @devicetype - the name of the device type
00208     #   !return - temporary colour set for the given device type
00209     #   
00210     def GetTempDeviceTypeColour(self,devicetype):
00211            
00212         if devicetype in self.tempdevicetypecolour.keys():
00213                 return self.tempdevicetypecolour[devicetype]
00214                     
00215         import random
00216         random.seed()
00217         while (True):
00218                 random.random()
00219                 r = random.randint(0,255)
00220                 g = random.randint(0,255)
00221                 b = random.randint(0,255)
00222 
00223                 if (r < 20 and g < 20 and b < 20):
00224                         continue
00225                 else:
00226                         break
00227 
00228         self.tempdevicetypecolour[devicetype] = "( " + str(r) + ", " + str(g) + ", " + str(b) + " )" #QColor(r,g,b)
00229         
00230         return self.tempdevicetypecolour[devicetype]
00231         
00232     ##
00233     #  Enable or disable the 'go down one level' toolbar button. It should only
00234     #   be enabled if it is just above the device level; so that a click on that button
00235     #   should lead you to the device level
00236     #   
00237     def EnableDisableLevelDown(self):
00238         
00239         if self.systemlevels[self.GetActiveSystem()] == self.GetVisWindow().GetLevelZoom(): # Last level?
00240                 self.GetToolBar().EnableTool(LEVEL_DOWN_BTN,True) # If yes: Enable
00241         else:
00242                 self.GetToolBar().EnableTool(LEVEL_DOWN_BTN,False) # If no: Disable
00243 
00244     ##
00245     #  Zoom and scroll should only be enabled when we are in zoom level -1 (device level), otherwise it should
00246     #   be disabled.
00247     #   
00248     def EnableDisableZoomAndScroll(self):
00249         if self.GetVisWindow().GetLevelZoom() == -1: #ok, enable
00250                 self.GetToolBar().EnableTool(ZOOMIN_BUTTON,True)
00251                 self.GetToolBar().EnableTool(ZOOMOUT_BUTTON,True)
00252                 self.GetToolBar().EnableTool(CUSTOMZOOM_BUTTON,True)
00253                 self.GetMenuBar().Enable(ZOOMMENU,True)
00254                 self.GetVisWindow().EnableScrolling(True,True) #doesnt work
00255         else: #not ok, disable
00256                 self.GetToolBar().EnableTool(ZOOMIN_BUTTON,False)
00257                 self.GetToolBar().EnableTool(ZOOMOUT_BUTTON,False)
00258                 self.GetToolBar().EnableTool(CUSTOMZOOM_BUTTON,False)
00259                 self.GetMenuBar().Enable(ZOOMMENU,False)
00260                 if self.GetZoomValue() != 100:
00261                         self.OnZoom(100,False)
00262                 self.SetZoomValue(100)
00263                 self.GetVisWindow().EnableScrolling(False,False) #doesnt work
00264 
00265 
00266     ##
00267     #  When the user clicks on the 'go down one level' button. So far it only works for the
00268     #   Muon subsystem, and should perhaps be limited to this subsystem.
00269     #   !return - False on error
00270     #   
00271     def OnDownOneLevel(self,event):
00272         
00273         if self.systemlevels[self.GetActiveSystem()] == self.GetVisWindow().GetLevelZoom(): # last level?
00274                 if self.GetActiveSystem() == "MUON":
00275                         self.GetVisWindow().SetLevelZoom(-1) # go to device level
00276                         # Get name of the device shown at the last level to show it in device level
00277                         devname = self.GetVisWindow().GetLevelSelection(self.systemlevels[self.GetActiveSystem()])
00278 
00279                         if devname in [False,[],""]: # If not set...fail!
00280                                 self.ShowError("Failed to show a general device view of the given chamber, because of an database error.",ERR_ERROR)
00281                                 return False
00282 
00283                         # Create device
00284                         device = Device(self.GetActiveSystem(),devname,False)
00285                         self.SetActiveDevice(device.GetName())
00286                         self.GetVisWindow().Clear()
00287                         self.GetVisWindow().ResetMacroObjects()
00288                         
00289                         # And show it in the current view
00290                         if self.GetViewMode() == ID_SUCCESSORS_MODE:
00291                                 self.GetVisWindow().OnDeviceSelected(device)
00292                         elif self.GetViewMode() == ID_PATHS_MODE:
00293                                 self.UpdatePath(device)
00294                         elif self.GetViewMode() == ID_DYNAMIC_MODE:
00295                                 self.GetVisWindow().OnDeviceSelected(device,False)
00296                         elif self.GetViewMode() == ID_SUBSYSTEM_MODE:
00297                                 if self.NeedToDrawSubsystem():
00298                                         self.ViewSubSystem(device.GetName())
00299                                 else:
00300                                         self.GetVisWindow().OnDeviceSelected(device,False)
00301                 else:
00302                         self.GetVisWindow().SetLevelZoom(-1) # default for other systems...
00303                         #self.ShowError("Only the Muon subsystem has support for this functionality.",ERR_ERROR)
00304                         #return False
00305 
00306 
00307     ##
00308     #  When the user clicks on the 'go up one level' toolbar button. This is accessible
00309     #   from most levels; except in device level if you have navigated to the device in the treeview.
00310     #   Because then it will not always know (at least in the Muon subsystem) what to show in the
00311     #   levels above.
00312     # 
00313     #   !return - False on error.
00314     #   
00315     def OnUpOneLevel(self,event):
00316         
00317         level = self.GetVisWindow().GetLevelZoom() # Get levelzoom
00318 
00319         # greater than level 0 (lhcb system level)
00320         if level >= 0:
00321                 if level == 0: # if lhcb system level, first clear the window
00322                         self.GetVisWindow().Clear()
00323 
00324                 self.GetVisWindow().ResetMacroObjects()
00325                 self.GetVisWindow().SetLevelZoom(level-1) # f.ex. level 0 (lhcb system) take you to level -1 (device level)
00326         elif level == -1: #default level, device level -> go one up if we have history information for that.
00327                 levelinfo = self.GetVisWindow().GetLevelInfo()
00328                 if levelinfo == False:
00329                         return False
00330                 try:
00331                         if self.GetActiveSystem() == "MUON" and not self.GetVisWindow().IsChamberFoundAtLocation():
00332                                 if len(levelinfo) >= 3:
00333                                         self.GetVisWindow().ResetMacroObjects()
00334                                         self.GetVisWindow().SetLevelZoom(2)
00335                                 else:
00336                                         return False
00337                         else:
00338                                 if len(levelinfo) > self.systemlevels[self.GetActiveSystem()]:
00339                                         self.GetVisWindow().ResetMacroObjects()
00340                                         self.GetVisWindow().SetLevelZoom(self.systemlevels[self.GetActiveSystem()])
00341                                 else:
00342                                         return False
00343                 except KeyError,err:
00344                         self.GetVisWindow().ResetMacroObjects()
00345                         self.GetVisWindow().SetLevelZoom(0)
00346                         
00347         else:
00348                 self.ShowError("Level " + str(level) + " is not a known level.",ERR_ERROR)
00349                 return False
00350 
00351     ##
00352     #  (Obsolete). Was used to generate temporary device names. Now we generate
00353     #   temporary device names (if needed) using the same as for generating temporary
00354     #   link names.
00355     #   @devicetype - name of the device type to create a temporary devicename for
00356     #   
00357     def GetNewDeviceNr(self,devicetype):
00358         
00359         try:
00360                 tmp = self.__devicenrlist[devicetype]   #devicetype is here _the_ string name
00361                 self.__devicenrlist[devicetype] += 1
00362         except KeyError,err:
00363                 #First device of this devicetype, assume we start at 0
00364                 self.__devicenrlist[devicetype] = 0
00365 
00366         return self.__devicenrlist[devicetype]
00367 
00368     ##
00369     #  Creates a new unique session id for a link nr. We start at 0, and increases it by 1
00370     #   every time we create a new temporary link name for the current session. The link names
00371     #   is put together with the prefixed string 'temporary_link_'.
00372     # 
00373     #   !return - returns a new unique link name in this session.
00374     #   
00375     def GetNewLinkNr(self):
00376         
00377         self.__lastlinknr += 1 #inc first,then return new ID
00378         return self.__lastlinknr
00379 
00380     ##
00381     #  In case a link creation is UNDOne, we free up the link names
00382     #   it used as well by decreasing by one for each link UNDOne.
00383     #   
00384     def SetPreviousLinkNr(self):
00385         
00386         self.__lastlinknr -= 1
00387 
00388     ##
00389     #  This method tries to guess the syntax of devices of a given device type
00390     #   available in one or several subsystems, so that new devices that are created with
00391     #   duplicate or clone methods automatically can get the names they should have, or at
00392     #   least with the correct syntax.
00393     # 
00394     #   TODO: This method is quite slow if you run it for each device, and you duplicate/clone
00395     #   maybe 100 devices. Therefore this method should be changed to generate deviceIDs for
00396     #   a number of devices; the number of devices of a given type that will be created. So that
00397     #   this method will only run once for each device type duplication/cloning.
00398     # 
00399     #   For a more close explanation of how the function works, have a look in the user documentation
00400     #   or code documentation for the CreateDevice(...) class.
00401     # 
00402     #   @system - the subsystem(s) the device type is available in
00403     #   @devicetype - the device type of the devices to be duplicated.
00404     # 
00405     #   !return - the guessed deviceID for the next device of the given device type, if found, or
00406     #   a temporary device name such as 'device_%d'. Returns False on error.
00407     #   
00408     def GetNextDeviceID(self,system,devicetype):
00409         
00410         devtype = DeviceType(system,devicetype,False)
00411         devs = devtype.GetDevices() #get all devices of given devtype
00412         if devs == False:
00413                 #an error occured
00414                 return False
00415 
00416         devs.sort()
00417         prefixvalue = devs[0] #lowest id
00418 
00419         syntax = prefixvalue
00420         if syntax == "":
00421                 return False #cannot happen
00422         if devs == []:
00423                 return False #cannot happen
00424                                                                                                                                                                
00425         i = len(syntax)-1
00426         nrofindexint = []
00427         prevwasint = False
00428         while i >= 0:
00429                 try:
00430                         nr = int(syntax[i])
00431                         nrofindexint.insert(0,i)
00432                         prevwasint = True
00433                 except ValueError,err:
00434                         #print str(syntax[i]) + " is not an int"
00435                         if prevwasint: #we found the whole integer string
00436                                 break
00437                 i -= 1
00438                                                                                                                                                                
00439         #Get nr substring
00440         start = nrofindexint[0]
00441         end = nrofindexint[len(nrofindexint)-1]
00442         if start == end:
00443                 substring = syntax[start]
00444         else:
00445                 substring = syntax[start:end+1]
00446                                                                                                                                                                
00447         #Get start and end substring; before and after nr
00448         if nrofindexint[0]-1 >= 0:
00449                 startstr = syntax[0:nrofindexint[0]]
00450         else:
00451                 startstr = ""
00452                                                                                                                                                                
00453         if len(syntax)-1 > nrofindexint[len(nrofindexint)-1]:
00454                 endstr = syntax[nrofindexint[len(nrofindexint)-1]+1:len(syntax)]
00455         else:
00456                 endstr = ""
00457                                                                                                                                                                
00458         #Set prefix
00459         prefix = startstr + "%d" + endstr #we have found the prefix, we want to change %d with the new index
00460         #self.__prefixtxtbox.SetValue(prefix)
00461                                                                                                                                                                
00462         #NB! Test padding
00463         padding = False
00464         paddingnr = 0
00465         if len(str(int(substring))) != len(str(substring)): #we have padding
00466                 nrofdigits = len(str(substring))
00467                 padding = True
00468                 paddingnr = nrofdigits
00469                                                                                                                                                                
00470         nrs = []
00471         #print "Start: " + str(startstr) + " End: " + str(endstr)
00472         for dev in devs:
00473                 if startstr != "":
00474                         dev = dev.replace(startstr,"")
00475                 if endstr != "":
00476                         dev = dev.replace(endstr,"")
00477                                                                                                                                                                
00478                 try:
00479                         nrs.append(int(dev))
00480                 except ValueError,err:
00481                         self.ShowError("No support for several %ds in the same name string yet. You will have to set the other %d yourself!",ERR_ERROR)
00482                         return False
00483                                                                                                                                                                
00484         nrs.sort()
00485         next = nrs[len(nrs)-1]+1
00486 
00487         nrlength = len(str(next)) #length of our number
00488         if nrlength > paddingnr and padding:
00489                 self.ShowError("You have exceeded the maximum number of digits that you set as a maximum for the given device type.",ERR_ERROR)
00490                 return False
00491         elif padding:
00492                 padstr = "".zfill(paddingnr-nrlength)
00493         else:
00494                 padstr = ""
00495                 #print "No padding"
00496 
00497         devname = startstr + str(padstr) + str(next) + endstr
00498         if devname in devs:
00499                 self.ShowError("The device " + str(devname) + " already exists. You have to change the range or delete the device with the same name in order to save a new one with that name.",ERR_ERROR)
00500                 return False
00501 
00502         return devname
00503 
00504     ##
00505     #  Set the device type chosen in the combo box to be the one
00506     #   chosen if user choose to drag and drop a device in the visual window.
00507     #   
00508     def OnDevTypeForCreationSelected(self,event):
00509         
00510         self.__seldevtypeforcreation = event.GetString()
00511         
00512     ##
00513     #  Set the link type chosen in the combo box to be the one
00514     #   chosen if the user clicks on the Connect button to connect two
00515     #   devices together in the visual window.
00516     #   
00517     def OnLinkTypeForCreationSelected(self,event):
00518         
00519         self.__sellinktypeforcreation = event.GetString()
00520 
00521     ##
00522     #  When the user clicks down the left mouse button on the device button on the tool bar
00523     #   the drag and drop has started; and is initialized here. We add data to the drag-and-drop
00524     #   action (device type chosen).
00525     #   
00526     def OnDragInit(self,event):
00527 
00528 
00529         if event.GetId() == DEVTYPE_BUTTON: 
00530                 # string syntax: SUBSYSTEM|DEVICETYPE|Device
00531                 # The device indicates that it is a device drag and drop action that is happening;
00532                 # others can easily be added later.
00533                 my_drag_value = self.GetActiveSystem() + "|" + self.__devtypecombobox.GetValue() + "|Device"
00534                 tdo = wxPyTextDataObject(my_drag_value)
00535                 tds = wxDropSource(self.__devtypebutton)
00536 
00537                 tds.SetData(tdo)
00538                 tds.DoDragDrop(True)
00539 
00540     ##
00541     #  The user clicks on the connect button in the tool bar to connect two devices together.
00542     #   We check that two devices are selected in the visual window, if yes we pop up the Create link
00543     #   window.
00544     # 
00545     #   !return - False on error.
00546     #   
00547     def OnConnectDevices(self,event):
00548         
00549         selected_devs = self.GetVisWindow().GetSelection()
00550         if len(selected_devs) != 2: # two visual objects in selection?
00551                 self.ShowError("You have to choose _two_ devices to connect together.",ERR_ERROR)
00552                 return False
00553 
00554         for dev in selected_devs:
00555                 if dev.GetType() != obj_NODE: # two DEVICES in selection?
00556                         self.ShowError("You have to choose two _devices_ to connect together.",ERR_ERROR)
00557                         return False
00558 
00559         self.SetActiveLinkType(self.__linktypecombobox.GetValue())
00560         # show window with parameters set for devices selected.
00561         self.CreateLinkClick(None,obj1=selected_devs[0].GetObject(),obj2=selected_devs[1].GetObject())
00562         
00563     ##
00564     #  Change the tool used in the visual window. The tool defines whether we are
00565     #   viewing or altering things in the visual window. The cursor is used for navigation mode.
00566     # 
00567     #   @tool - a constant (tool_SELECT or tool_EDIT) defining whether what we will do with the visual objects
00568     #   
00569     def SetCurrentTool(self,tool):
00570         
00571         self.__userModeTool = tool
00572         self.GetVisWindow().SetCurrentTool(tool)
00573 
00574     ##
00575     #  Get currently used tool in the visual window.
00576     # 
00577     #   !return - tool (constant) that is currently used in the visual window.
00578     #   
00579     def GetCurrentTool(self):
00580         
00581         return self.__userModeTool
00582 
00583     ##
00584     #  Menubar check item to turn on and off auto zoom. 
00585     def EnableAutoZoom(self,event=False,enable=False):
00586 
00587         if event == False: #Not caused by event, toggling of check has to be handled manually
00588                 #if self.GetMenuBar().IsChecked(ID_ENABLEAUTOZOOM):
00589                 if enable == False:
00590                         self.GetVisWindow().EnableAutoZoom(False)
00591                         self.GetMenuBar().Check(ID_ENABLEAUTOZOOM,False)
00592                 else:
00593                         self.GetVisWindow().EnableAutoZoom(True)
00594                         self.GetMenuBar().Check(ID_ENABLEAUTOZOOM,True)
00595                         self.GetVisWindow().OnPaintEvent(None)
00596         else: #user clicked on menu item
00597                 if self.GetMenuBar().IsChecked(ID_ENABLEAUTOZOOM):
00598                         self.GetVisWindow().EnableAutoZoom(True)
00599                         self.GetVisWindow().OnPaintEvent(None)
00600                 else:
00601                         self.GetVisWindow().EnableAutoZoom(False)
00602 
00603 
00604     ##
00605     #  Zoom in in the visual window one factor (the factors are set in the 
00606     #   self.zoomvalues list).
00607     #   
00608     def ZoomIn(self,event=None):
00609         self.panel.visWindow.ZoomIn()
00610         
00611         # self.EnableAutoZoom(False,False)
00612         # if self.__zoomindex >= len(self.zoomvalues)-1:
00613                 # wxBell() #cannot zoom in more
00614                 # self.ShowError("To zoom in more than 400%, choose custom zoom.",ERR_INFORMATION,False)
00615                 # self.__zoomindex = len(self.zoomvalues)-1
00616         # else:
00617                 # self.__zoomindex += 1
00618 
00619         # self.OnZoom(self.zoomvalues[self.__zoomindex],True) # Make the zoom happen.
00620         
00621 
00622     ##
00623     #  Zoom out in the visual window one factor (the factors are set in the
00624     #   self.zoomvalues list)
00625     #   
00626     def ZoomOut(self,event=None):
00627         self.panel.visWindow.ZoomOut()
00628 
00629         #self.GetVisWindow().EnableAutoZoom(False)
00630         # self.EnableAutoZoom(False,False)
00631         # if self.__zoomindex <= 0:
00632                 # wxBell() #cannot zoom out more
00633                 # self.ShowError("To zoom out less than 10%, choose custom zoom.",ERR_INFORMATION,False)
00634                 # self.__zoomindex = 0
00635         # else:
00636                 # self.__zoomindex -= 1
00637 
00638         # self.OnZoom(self.zoomvalues[self.__zoomindex],True) # Make the zoom happen
00639         
00640     ##
00641     #  Zoom in or out in the visual window using a custom zoom given as a number in 
00642     #   a input text box.
00643     #   
00644     def ZoomCustom(self,event=None):
00645         
00646         #self.GetVisWindow().EnableAutoZoom(False)
00647         self.EnableAutoZoom(False,False)
00648         nr = wxGetNumberFromUser("Type in a custom zoom value in percent, 100% is original/default size:","Zoom in %:","Custom Zoom",100,1,1000,self)
00649         if nr < 0:
00650                 self.ShowError("You typed an invalid number.",ERR_INFORMATION,False)
00651         elif nr == 0:
00652                 self.ShowError("You cannot zoom to 0%. Then it is not visible!",ERR_INFORMATION,False)
00653         else:
00654                 self.OnZoom(nr,True) # Make the zoom happen
00655         
00656                 self.__zoomindex = -1
00657                 i = 0
00658                 for itm in self.zoomvalues:
00659                         if itm <= nr:
00660                                 self.__zoomindex = i
00661                         else:
00662                                 break
00663                         i += 1
00664 
00665     ##
00666     #  Calls the zoom function in the visual window to change to the zoom given.
00667     # 
00668     #   @zoom - the zoom factor in percent
00669     #   @paintevent - whether a paintevent has to be triggered to redraw the contents of the visual window.
00670     # 
00671     #   !return - True on success, False otherwise.
00672     #   
00673     def OnZoom(self,zoom,paintevent=True):
00674         
00675         #STATUS_CALL self.GetStatusBar().SetStatusText(str(zoom) + "%",4)
00676 
00677         if zoom == self.__zoomvalue:
00678                 self.ShowError("The zoom value you chose is already the current one!",ERR_INFORMATION,False)
00679                 return False
00680         else:
00681                 self.__zoomvalue = zoom
00682                 self.GetVisWindow().Zoom(self.__zoomvalue,paintevent)
00683                 return True
00684 
00685     ##
00686     #  Set the currently zoom value (as it is in the visual window) to the 
00687     #   member variable in this class (visual window instance sets the value once it has
00688     #   successfully changed the zoom of the visual window contents)
00689     # 
00690     #   @value - the zoom factor in percent.
00691     #   
00692     def SetZoomValue(self,value):
00693         
00694         self.__zoomvalue = value
00695         i = 0
00696         for itm in self.zoomvalues:
00697                 if itm == value:
00698                         self.__zoomindex = i
00699                 i += 1
00700 
00701         self.GetStatusBar().SetStatusText(str(self.__zoomvalue) + "%",4) # Show zoom value in the status bar
00702 
00703     def GetZoomValue(self):
00704         return self.__zoomvalue
00705         
00706     ##
00707     #  Get the current view: neighbour view, path view, dynamic link view or subsystem view.
00708     # 
00709     #   !return -  the constant for the current view
00710     #   
00711     def GetViewMode(self):
00712         
00713         return self.__viewmode
00714 
00715     def SetCreationMode(self,event):
00716         if event:
00717                 self.__userMode = ID_CREATION_MODE
00718                 self.myStatusbar.modeIcon.setPixmap(self.myStatusbar.imageCreation)
00719                 self.myStatusbar.mode.setText("Creation Mode")
00720                 self.fileStore_object_in_DBAction.setEnabled(True)
00721         else:
00722                 self.__userMode = ID_NAVIGATION_MODE
00723                 self.myStatusbar.modeIcon.setPixmap(self.myStatusbar.imageNavigation)
00724                 self.myStatusbar.mode.setText("Navigation Mode")
00725                 self.fileStore_object_in_DBAction.setEnabled(False)
00726 
00727     def OnPathView(self,event):
00728         if event:
00729                 self.__viewmode = ID_PATHS_MODE
00730         else:
00731                 self.__viewmode = ID_SUCCESSORS_MODE  # default
00732 
00733     def OnCreateLinkMode(self,event):
00734         if event:
00735                 self.__viewmode = ID_PATHS_MODE
00736         else:
00737                 self.__viewmode = ID_SUCCESSORS_MODE  # default
00738                 
00739     ##
00740     #  If the view was changed by the user from the toolbar; this is called
00741     #   in order to change the check mark in the menu bar for the currently chosen view.
00742     #   
00743     def OnChangeViewT(self,event):
00744 
00745         viewmode = ""
00746 
00747         if self.GetToolBar().GetToolState(NEIGHBOUR_BUTTON):
00748                 self.__viewmode = ID_SUCCESSORS_MODE
00749                 self.GetMenuBar().Check(ID_VIEW_SUCCESSORS,True)
00750                 viewmode = "Neighbour View"
00751         if self.GetToolBar().GetToolState(PATH_BUTTON):
00752                 self.__viewmode = ID_PATHS_MODE
00753                 self.GetMenuBar().Check(ID_VIEW_PATHS,True)
00754                 viewmode = "Path View"
00755         if self.GetToolBar().GetToolState(DYNAMICLINK_BUTTON):
00756                 self.__viewmode = ID_DYNAMIC_MODE
00757                 self.GetMenuBar().Check(ID_VIEW_DYNAMIC,True)
00758                 viewmode = "Dynamic Link View"
00759         if self.GetToolBar().GetToolState(SUBSYSTEM_BUTTON):
00760                 self.__viewmode = ID_SUBSYSTEM_MODE
00761                 self.GetMenuBar().Check(ID_VIEW_SUBSYSTEM,True)
00762                 viewmode = "Subsystem View"
00763                 self.__processubsystems = True
00764         
00765         self.GetStatusBar().SetStatusText(viewmode, 6)
00766 
00767 
00768 
00769     ##
00770     #  If the view was changed by the user from the menu bar; this is called
00771     #   in order to change the depressed button on the tool bar for the currently chosen view.
00772     #   
00773     def OnChangeViewM(self,event):
00774 
00775         viewmode = ""
00776 
00777         if self.GetMenuBar().IsChecked(ID_VIEW_SUCCESSORS):
00778                 self.__viewmode = ID_SUCCESSORS_MODE
00779                 self.GetToolBar().ToggleTool(NEIGHBOUR_BUTTON,True)
00780                 self.GetToolBar().ToggleTool(PATH_BUTTON,False)
00781                 self.GetToolBar().ToggleTool(DYNAMICLINK_BUTTON,False)
00782                 self.GetToolBar().ToggleTool(SUBSYSTEM_BUTTON,False)
00783                 viewmode = "Neighbour View"
00784         elif self.GetMenuBar().IsChecked(ID_VIEW_PATHS):
00785                 self.__viewmode = ID_PATHS_MODE
00786                 self.GetToolBar().ToggleTool(PATH_BUTTON,True)
00787                 self.GetToolBar().ToggleTool(DYNAMICLINK_BUTTON,False)
00788                 self.GetToolBar().ToggleTool(SUBSYSTEM_BUTTON,False)
00789                 self.GetToolBar().ToggleTool(NEIGHBOUR_BUTTON,False)
00790                 viewmode = "Path View"
00791         elif self.GetMenuBar().IsChecked(ID_VIEW_DYNAMIC):
00792                 self.__viewmode = ID_DYNAMIC_MODE
00793                 self.GetToolBar().ToggleTool(DYNAMICLINK_BUTTON,True)
00794                 self.GetToolBar().ToggleTool(SUBSYSTEM_BUTTON,False)
00795                 self.GetToolBar().ToggleTool(PATH_BUTTON,False)
00796                 self.GetToolBar().ToggleTool(NEIGHBOUR_BUTTON,False)
00797                 viewmode = "Dynamic Link View"
00798         elif self.GetMenuBar().IsChecked(ID_VIEW_SUBSYSTEM):
00799                 self.__viewmode = ID_SUBSYSTEM_MODE
00800                 self.GetToolBar().ToggleTool(SUBSYSTEM_BUTTON,True)
00801                 self.GetToolBar().ToggleTool(DYNAMICLINK_BUTTON,False)
00802                 self.GetToolBar().ToggleTool(PATH_BUTTON,False)
00803                 self.GetToolBar().ToggleTool(NEIGHBOUR_BUTTON,False)
00804                 viewmode = "Subsystem View"
00805                 self.__processubsystems = True
00806         
00807         #no other options available
00808 
00809         self.GetStatusBar().SetStatusText(viewmode, 6)
00810 
00811     ##
00812     #  Get the constant for the currently chosen user mode set in the CdbVisCore module.
00813     # 
00814     #   !return - the constant for the currently chosen user mode (ID_NAVIGATION_MODE or ID_CREATION_MODE)
00815     #   
00816     def GetUserMode(self):
00817         
00818         return self.__userMode #ID_NAVIGATION_MODE or ID_CREATION_MODE
00819 
00820     ##
00821     #  Change the user mode; and only make the functionality that is accessible in the new user mode to be
00822     #   accessible, the rest should be disabled and inaccessible.
00823     # 
00824     #   !return - False if unsuccessful; and user mode not changed.
00825     #   
00826     def SetUserMode(self,event):
00827         
00828         if self.GetToolBar().GetToolState(NAVIGATE_TOGGLE_BUTTON):
00829                 if not self.IsSaveListEmpty():
00830                         ans = QMessageBox.question(self,"Save Changes?","You have to save changes before you go back to Navigation Mode. Save Changes?","Yes","No","",0,1)
00831                         #ans = wxMessageBox("You have to save changes before you go back to Navigation Mode. Save Changes?","Save Changes?", wxYES_NO | wxCANCEL | wxICON_QUESTION)
00832                         if ans == 0: # Yes
00833                                 #save changes, if successful; goto navigation mode; if not 
00834                                 res = self.OnSave(None,False)
00835                                 if res == False:
00836                                         self.ShowError("Could not store all changes in confDB. If you still want to change to navigation mode, you will have to change without storing the changes made.",ERR_ERROR)
00837                                         ##self.GetToolBar().ToggleTool(NAVIGATE_TOGGLE_BUTTON, False)
00838                                         ##self.GetToolBar().ToggleTool(CREATE_TOGGLE_BUTTON, True)
00839                                         return False
00840                                 
00841                         elif ans == 1: # No
00842                                 #do not save changes, discard, and continue
00843                                 ##self.ProgressData(len(self.__undolist),False,0)
00844                                 while len(self.__undolist) != 0:
00845                                         self.DoUndo(None,False)
00846                                         ##self.ProgressData(0,False,1)
00847                                 ##self.ProgressData(0,True,0)
00848                         else: # cancel pressed
00849                                 #user changed his mind, do not save and do not change mode...return
00850                                 #or should navigation mode button be disabled until save
00851                                 ##self.GetToolBar().ToggleTool(NAVIGATE_TOGGLE_BUTTON, False)
00852                                 ##self.GetToolBar().ToggleTool(CREATE_TOGGLE_BUTTON, True)
00853                                 return False
00854 
00855                 self.ResetDirtyObjects() #no undo possible
00856 
00857                 # Set the edit menu with undo and redo to be empty
00858                 '''menu = wxMenu()
00859                 menu.Append(ID_UNDO,"&Undo\tCtrl-Z","")
00860                 menu.Append(ID_REDO,"&Redo\tCtrl-R","")
00861                 self.GetMenuBar().Replace(1,menu,"&Edit")
00862 
00863                 self.GetMenuBar().Enable(ID_UNDO,False)
00864                 self.GetMenuBar().Enable(ID_REDO,False)
00865 
00866                 # disable/enable functions etc. for the current user mode
00867                 self.GetMenuBar().Enable(ID_STORE_OBJS,False)
00868                 self.GetMenuBar().Enable(ID_MASSINSERT,False)
00869                 self.GetMenuBar().Enable(ID_GENERATESQL,False)
00870 '''
00871                 self.__userMode = ID_NAVIGATION_MODE
00872                 ##self.GetStatusBar().SetStatusText("Navigation Mode", 5)
00873                 self.SetCurrentTool(tool_SELECT)
00874 
00875                 '''self.GetToolBar().EnableTool(NAVIGATE_TOGGLE_BUTTON,True)
00876                 self.GetToolBar().EnableTool(CREATE_TOGGLE_BUTTON,True)
00877                 self.GetToolBar().EnableTool(COPY_TOGGLE_BUTTON,False)
00878                 self.GetToolBar().EnableTool(PASTE_TOGGLE_BUTTON,False)
00879                 self.GetToolBar().EnableTool(DELETE_TOGGLE_BUTTON,False)
00880                 self.GetToolBar().EnableTool(SAVE_TOGGLE_BUTTON,False) #possible to change between modes and save at any time?
00881 
00882                 self.GetToolBar().EnableTool(LEVEL_DOWN_BTN,True)
00883                 self.GetToolBar().EnableTool(LEVEL_UP_BTN,True)
00884 
00885                 self.GetToolBar().EnableTool(ZOOMIN_BUTTON,True)
00886                 self.GetToolBar().EnableTool(ZOOMOUT_BUTTON,True)
00887                 self.GetToolBar().EnableTool(CUSTOMZOOM_BUTTON,True)
00888                 
00889                 self.__devtypecombobox.Enable(False)
00890                 self.__devtypebutton.Enable(False)
00891 
00892                 self.__linktypecombobox.Enable(False)
00893                 self.__linktypebutton.Enable(False)
00894 
00895                 self.GetMenuBar().EnableTop(3,False) #create
00896                 self.GetMenuBar().EnableTop(4,False) #modify
00897                 self.GetMenuBar().EnableTop(5,False) #delete
00898                 
00899                 # visual menu
00900                 self.GetMenuBar().Enable(ZOOMMENU,True)
00901                 self.GetMenuBar().Enable(SELECTIONMENU,True)
00902                 self.GetMenuBar().Enable(OBJECTMENU,False)
00903                 '''
00904         else: # CREATE_TOGGLE_BUTTON
00905 
00906                 self.__userMode = ID_CREATION_MODE
00907                 ##self.GetStatusBar().SetStatusText("Creation Mode", 5)
00908                 ##self.SetCurrentTool(tool_EDIT)
00909                 
00910                 self.RecoverObjectFromFile() #recover objects, if any
00911 
00912                 # enable/disable functions etc. for the current user mode
00913                 '''self.GetToolBar().EnableTool(NAVIGATE_TOGGLE_BUTTON,True)
00914                 self.GetToolBar().EnableTool(CREATE_TOGGLE_BUTTON,True)
00915                 self.GetToolBar().EnableTool(COPY_TOGGLE_BUTTON,True)
00916                 self.GetToolBar().EnableTool(PASTE_TOGGLE_BUTTON,True)
00917                 self.GetToolBar().EnableTool(DELETE_TOGGLE_BUTTON,True)
00918                 self.GetToolBar().EnableTool(SAVE_TOGGLE_BUTTON,True) #possible to change between modes and save at any time?
00919 
00920                 self.GetToolBar().EnableTool(ZOOMIN_BUTTON,True)
00921                 self.GetToolBar().EnableTool(ZOOMOUT_BUTTON,True)
00922                 self.GetToolBar().EnableTool(CUSTOMZOOM_BUTTON,True)
00923 
00924                 self.GetToolBar().EnableTool(LEVEL_DOWN_BTN,True)
00925                 self.GetToolBar().EnableTool(LEVEL_UP_BTN,True)
00926 
00927                 self.__devtypecombobox.Enable(True)
00928                 self.__devtypebutton.Enable(True)
00929 
00930                 self.__linktypecombobox.Enable(True)
00931                 self.__linktypebutton.Enable(True)
00932 
00933                 self.GetMenuBar().EnableTop(3,True) #create
00934                 self.GetMenuBar().EnableTop(4,True) #modify
00935                 self.GetMenuBar().EnableTop(5,True) #delete
00936                 
00937                 # visual menu
00938                 self.GetMenuBar().Enable(ZOOMMENU,True)
00939                 self.GetMenuBar().Enable(SELECTIONMENU,True)
00940                 self.GetMenuBar().Enable(OBJECTMENU,True)
00941 
00942                 # TODO: Only enable if there is something to store in DB. (Dirty List != [])
00943                 self.GetMenuBar().Enable(ID_STORE_OBJS,True)
00944                 self.GetMenuBar().Enable(ID_MASSINSERT,True)
00945                 self.GetMenuBar().Enable(ID_GENERATESQL,True)
00946                 '''
00947     ##
00948     #  Enables/Disables the export to text option in the File menu
00949     #   This should only be active when we are viewing a sub-system
00950     #   
00951     def EnableDisableExportText(self,enable=False):
00952 
00953         #WALPROB self.GetMenuBar().Enable(ID_EXPORT_TEXT,enable)
00954 
00955 
00956     ##
00957     #  Set the device type to the given device type to be
00958     #   chosen if user choose to drag and drop a device in the visual window.
00959     # 
00960     #   @devtype - the device type name; to be used next time a device is created
00961     #   
00962     def SetCreateDeviceType(self,devtype):
00963 
00964         self.__selectcreatedevtype = devtype
00965         
00966     ##
00967     #  Get the device type a device will be created of. Device type chosen from combo box
00968     #   on tool bar.
00969     # 
00970     #   !return - the name of the device type currently chosen in the combo box in the tool bar.
00971     #   
00972     def GetCreateDeviceType(self):
00973         
00974         return self.__selectcreatedevtype
00975 
00976     ##
00977     #  If the view changes we keep track of this in a variable; cause when a new device is selected to be viewed
00978     #   in the visual window, a undo/redo which causes visual objects to be created should not be added to the visual window,
00979     #   if the view is now of different devices than it was when the undo/redo happened the first time.
00980     #   
00981     def WhenChangeView(self):
00982         
00983         self.__currentview += 1
00984         
00985     ##
00986     #  Get current view; the integer telling whether we have changed the device to view in neighbor or path view.
00987     #   
00988     def GetCurrentView(self):
00989         
00990         return self.__currentview
00991 
00992     ##
00993     #  When the current view changes, the previous view is set here. So that we can compare current and previous view,
00994     #   and thereafter make a decision whether we should add the undone/redone objects to the visual window or not.
00995     #   
00996     def GetPrevView(self):
00997         
00998         return self.__prevview
00999 
01000     ##
01001     #  Set the previous view (the view that was the current view before it changed).
01002     #   
01003     def SetPrevView(self,prev):
01004         
01005         self.__prevview = prev
01006         
01007     ##
01008     #  REDOES the previously UNDONE action. Does not take any in parameters, but looks in different lists for input.
01009     #   
01010     def DoRedo(self,event):
01011 
01012         self.ShowError("Please wait while REDOing " + str(self.__redolist[len(self.__redolist)-1][1]),ERR_INFORMATION,False)
01013 
01014         save_tmp = [] #a list where we save earlier instances of objects in the dirty list if we add a newer one to the dirtylist
01015 
01016         # Get Redo action from redo list
01017         tmp_redo = self.__redolist.pop()
01018 
01019         # And add it to the UNDO list, so that the redone action can be undone later..if wanted
01020         self.__undolist.append([len(self.__dirtyobjects),tmp_redo[1],tmp_redo[2]])
01021 
01022         # Add the objects in the redo object list to the dirty objects list
01023         tmp_listredo = [] # We add all redo object to this list, and iterate it afterwards
01024         i = tmp_redo[0]
01025         while i < len(self.__redoobjectlist):
01026                 tmp_redoobj = self.__redoobjectlist.pop(i)
01027                 fromdirtyobjs = self.FindDirtyObject(tmp_redoobj.GetName(),tmp_redoobj.__class__)
01028                 if fromdirtyobjs:
01029                         save_tmp.append(fromdirtyobjs)
01030                 self.AddToDirtyObjects(tmp_redoobj,fromredoundo=True)
01031                 tmp_listredo.append(tmp_redoobj)
01032 
01033                 self.RecoverObjectToFile(tmp_redoobj,state=REDO) # Save that we REDID an object to the recover file
01034 
01035         self.ProgressData(len(tmp_listredo),False,0)
01036 
01037         for itm in tmp_listredo: # Iterate through REDID objects, make changes happen in visual window if needed (and treeview)
01038                 
01039                 #TreeView Changes
01040                 if itm.__class__ == Device:
01041                         parent = itm.GetType()
01042                         type = TN_DEVICE
01043                 elif itm.__class__ == Link:
01044                         parent = itm.GetType()
01045                         type = TN_LINK
01046                 elif itm.__class__ == DeviceType:
01047                         parent = "Device types"
01048                         type = TN_DEVICETYPE
01049                 elif itm.__class__ == LinkType:
01050                         parent = "Link types"
01051                         type = TN_LINKTYPE
01052                 elif itm.__class__ == Port:
01053                         parent = itm.GetDevice()
01054                         type = TN_PORT
01055                 elif itm.__class__==Spare_Port:
01056                         parent=itm.GetSpareDevice()
01057                         type = TN_PORT
01058                 elif itm.__class__==Spare_Device:
01059                         parent=itm.GetHWType()
01060                         type=TN_DEVICE
01061 
01062                 # Redo delete from treeview -> remove node
01063                 if itm.GetSaveStatus() == DELETE: #Redo delete
01064                         try:
01065                                 my_id = self.GetSelectWindow().GetItemID(itm.GetName())
01066                                 self.GetSelectWindow().RemoveItem(my_id,parent)
01067                                 self.GetSelectWindow().SetItemToDeleted(itm.GetName())
01068                         except KeyError,err:
01069                                 pass
01070                 # Redo create from treeview -> add node
01071                 elif itm.GetSaveStatus() == CREATE: #Redo create
01072                         try:
01073                                 my_id = self.GetSelectWindow().GetItemID(parent)
01074                                 self.GetSelectWindow().AddItem(itm,type)
01075                         except KeyError,err:
01076                                 pass
01077                 else: #Redo modify (its NOT possible to redo rename), so nothing to do
01078                         pass
01079 
01080 
01081                 # Redo create or modify in visual window; add new visual object
01082                 if itm.__class__ in [Device,Link] and itm.GetSaveStatus() != DELETE: #redo create (or modify) node...then links included
01083 
01084                         if itm.GetSaveStatus() == CREATE:
01085                                 tmp_obj = self.GetVisWindow().FindByName(itm.GetName())
01086         
01087                                 if itm.__class__ == Link:
01088                                         if tmp_obj:
01089                                                 self.GetVisWindow().DoDeleteObj(itm.GetName(),False,refresh=False)
01090                                                 self.__visualundolist.append(tmp_obj)
01091                                         else:
01092                                                 found = False
01093                                                 for objitm in save_tmp:
01094                                                         if itm.GetName() == objitm.GetName() and itm.__class__ == objitm.__class__:
01095                                                                 self.__visualundolist.append(objitm)
01096                                                                 found = True
01097                                                                 break
01098                                                 if not found:
01099                                                                 tmp_link = Link(itm.GetSystem(),itm.GetName(),False,False)
01100                                                                 self.__visualundolist.append(tmp_link)
01101                                 else: #Device
01102                                         if tmp_obj:
01103                                                 self.GetVisWindow().Deselect(tmp_obj,refresh=False)
01104                                                 newobj = Device(itm.GetSystem(),itm.GetName(),False)
01105                                                 tmp_obj.SetObjectRef(newobj)
01106                                                 self.GetVisWindow().Select(tmp_obj,refresh=False)
01107                                                 self.__visualundolist.append(tmp_obj) #with wrong reference, but will be fixed
01108                                         else:
01109                                                 tmp_dev = Device(itm.GetSystem(),itm.GetName(),False)
01110                                                 self.__visualundolist.append(tmp_dev)
01111                                                 
01112                                         continue #finished with modified device, next itm in undo
01113 
01114                         else: # redo modify in visual window
01115                                 try:
01116                                         if itm.__class__ == DrawingObject:
01117                                                 type = itm.GetObject().GetType()
01118                                         else:
01119                                                 type = itm.GetType()
01120                                         id = self.GetSelectWindow().GetItemID(type)
01121                                 except KeyError,err:
01122                                         pass
01123 
01124 
01125                         # redo create or modify
01126                         vis_obj = None
01127 
01128                         i = len(self.__visualredolist)-1
01129                         while i >= 0:
01130                                 if self.__visualredolist[i].__class__ == DrawingObject:
01131                                         if self.__visualredolist[i].GetName() == itm.GetName() and self.__visualredolist[i].GetObject().__class__ == itm.__class__:
01132                                                 vis_obj = self.__visualredolist.pop(i)
01133                                                 break
01134                                 elif self.__visualredolist[i].__class__ in [Device,Link]:
01135                                         if self.__visualredolist[i].GetName() == itm.GetName() and self.__visualredolist[i].__class__ == itm.__class__:
01136                                                 vis_obj = self.__visualredolist.pop(i)
01137                                                 break
01138 
01139                                 else:
01140                                         print "Unkown class type"
01141                                 
01142                                 i -= 1
01143 
01144                         if vis_obj and not (itm.__class__ == Device and itm.GetSaveStatus() == CREATE):
01145                                 if vis_obj.__class__ == DrawingObject:
01146                                         if vis_obj.GetObject().__class__ == Device: #found device object, can easily recover
01147                                                 print "Add to contents"
01148                                                 self.GetVisWindow().AddToContents(vis_obj,False)
01149                                         elif vis_obj.GetObject().__class__ == Link: #found link object
01150                                                 vis_link = self.GetVisWindow().CreateConnectedLink(vis_obj.GetObject(),vis_obj.GetPosition(),vis_obj.GetSize())
01151                                 elif vis_obj.__class__ in [Device,Link]:
01152                                         if vis_obj.__class__ == Device: #found device object, can easily recover
01153                                                 print "Create node"
01154                                                 self.GetVisWindow().CreateNode(0,0,vis_obj,False)
01155                                         elif vis_obj.__class__ == Link: #found link object
01156                                                 self.GetVisWindow().CreateConnectedLink(vis_obj)
01157                                                 #print "Added non visual object"
01158                                 else:
01159                                         print "we dont know how to handle this class type"
01160 
01161                         else:
01162                                 print "visual object not found in visual redo list because of some strange reason"
01163                                 
01164                 # redo delete in visual window
01165                 elif itm.__class__ in [Device,Link] and itm.GetSaveStatus() == DELETE: #redo delete of node or link
01166                         tmp_obj = self.GetVisWindow().FindByName(itm.GetName())
01167 
01168                         if tmp_obj:
01169                                 self.GetVisWindow().DeselectAll(refresh=False)
01170                                 self.GetVisWindow().Select(tmp_obj,refresh=False)
01171                                 self.GetVisWindow().DoDelete(None,False,refresh=False)
01172 
01173                                 self.__visualundolist.append(tmp_obj) #For UNDOing delete
01174                         else: #not found in visual contents, create dataobject:
01175                                 found = False
01176                                 for objitm in save_tmp:
01177                                         if itm.GetName() == objitm.GetName() and itm.__class__ == objitm.__class__:
01178                                                 self.__visualundolist.append(objitm)
01179                                                 found = True
01180                                                 break
01181                                 if not found:
01182                                         if itm.__class__ == Device:
01183                                                 tmp_dev = Device(itm.GetSystem(),itm.GetName(),False)
01184                                                 self.__visualundolist.append(tmp_dev)
01185                                         elif itm.__class__ == Link:
01186                                                 tmp_link = Link(itm.GetSystem(),itm.GetName(),False,False)
01187                                                 self.__visualundolist.append(tmp_link)
01188 
01189                 self.ProgressData(0,False,1)
01190 
01191         #Fix Edit menu -> new text for redo and undo
01192         if self.__redolist == []:
01193                 description = ""
01194         else:
01195                 description = self.__redolist[len(self.__redolist)-1][1]
01196 
01197         #REDO descr:
01198         descrundo = self.__undolist[len(self.__undolist)-1][1]
01199 
01200         menu = wxMenu()
01201         menu.Append(ID_UNDO,"&Undo " + str(descrundo) + "\tCtrl-Z","The last action you did will be undone, and added to the Redo list")
01202         menu.Append(ID_REDO,"&Redo " + str(description) + "\tCtrl-R","The last action you UNDOed will be undone")
01203         self.GetMenuBar().Replace(1,menu,"&Edit")
01204 
01205         if self.__redolist == []:
01206                 menu.Enable(ID_REDO,False)
01207 
01208         menu.Enable(ID_UNDO,True)
01209 
01210         self.ProgressData(0,True,0)
01211 
01212         self.GetVisWindow().Refresh()
01213         self.ShowError("The REDO action was successfully finished.",ERR_INFORMATION,False)
01214 
01215         
01216     ##
01217     #  Get the index of the next undo will start from 
01218     #   
01219     def GetFirstNewUndoIndex(self):
01220         
01221         return len(self.__dirtyobjects)
01222 
01223     ##
01224     #  Add a new UNDO action/operation to the UNDO list so that the user can UNDO the operation later.
01225     #   Can be called from any place where an action in the program. Maybe we will have an other list specific 
01226     #   for the visual contents and what is done there to be possibly undone as well, then we will need an extra 
01227     #   parameter constant saying what list. 
01228     #   
01229     #   @fromindex - the index in the dirty objects list where the UNDO operation will remove objects from
01230     #   @description - a string description of the action; so that the user knows what he/she UNDOes.
01231     #   
01232     def AddToUndo(self,fromindex,description):
01233         
01234         my_view = self.__currentview
01235         self.__undolist.append([fromindex,description,my_view]) #fromindex means _FROM_THIS_ONE_IS_INCLUDED_
01236 
01237         '''#Edit menu
01238         menu = wxMenu()
01239         menu.Append(ID_UNDO,"&Undo " + str(description) + "\tCtrl-Z","The last action you did will be undone, and added to the Redo list")
01240         if not self.GetMenuBar().IsEnabled(ID_REDO):
01241                 menu.Append(ID_REDO,"&Redo\tCtrl-R","The last action you UNDOed will be undone")
01242                 menu.Enable(ID_REDO,False)
01243         else:
01244                 tmp_menuitm = self.GetMenuBar().GetMenu(1).FindItemById(ID_REDO)
01245                 tmp_text = tmp_menuitm.GetLabel()
01246                 menu.Append(ID_REDO,"&Redo\tCtrl-R","The last action you UNDOed will be undone")
01247                 menu.Enable(ID_REDO,False)
01248                 self.ResetRedoObjects() # New action added to UNDO; that means that we have to reset the REDO possibility
01249 
01250         self.GetMenuBar().Replace(1,menu,"&Edit")
01251         menu.Enable(ID_UNDO,True)'''
01252 
01253     ##
01254     #  Empties all redo lists for objects that is no longer needed because REDO action is reset.
01255     #           
01256     def ResetRedoObjects(self):
01257             
01258                 self.__redolist = []
01259 
01260                 #delete visual object first because they contain references to data objects
01261                 for visobj in self.__visualredolist: # delete visual redo objects
01262                         del visobj
01263                         visobj = None
01264 
01265                 for obj in self.__redoobjectlist: # delete data redo objects
01266                         del obj
01267                         obj = None
01268 
01269                 
01270                 self.__redoobjectlist = []
01271                 self.__visualredolist = []
01272         
01273 
01274     ##
01275     #  UNDOES the previously done action. Gets information about the undo from the undo lists.
01276     # 
01277     #   @showprogress - whether the progressbar should show the progress of the UNDO or not.
01278     #   
01279     def DoUndo(self,event=None,showprogress=True):
01280         
01281         self.ShowError("Please wait while UNDOing " + str(self.__undolist[len(self.__undolist)-1][1]),ERR_INFORMATION,False)
01282 
01283         # Get undo information and remove objects from dirty objects list for that undo operation.
01284         tmp_undo = self.__undolist.pop()
01285         tmp_removed = self.RemoveDirtyObjects(tmp_undo[0])
01286 
01287         #add action to redo list, and the objects in the redo object list, so that it can later be redone
01288         self.__redolist.append([len(self.__redoobjectlist),tmp_undo[1],tmp_undo[2]])
01289         self.__redoobjectlist.extend(tmp_removed)
01290 
01291         if showprogress:
01292                 self.ProgressData(len(tmp_removed),False,0) # initialize progress bar
01293         
01294         for itm in tmp_removed: # go through each UNDONE item and make necessary action in the tree view and visual window (add or remove objects)
01295                 self.RecoverObjectToFile(itm,state=UNDO) # add undo activity information to recover file
01296 
01297                 #TreeView Changes
01298                 if itm.__class__ == Device:
01299                         parent = itm.GetType()
01300                         type = TN_DEVICE
01301                 elif itm.__class__ == Link:
01302                         parent = itm.GetType()
01303                         type = TN_LINK
01304                 elif itm.__class__ == DeviceType:
01305                         parent = "Device types"
01306                         type = TN_DEVICETYPE
01307                 elif itm.__class__ == LinkType:
01308                         parent = "Link types"
01309                         type = TN_LINKTYPE
01310                 elif itm.__class__ == Port:
01311                         parent = itm.GetDevice()
01312                         type = TN_PORT
01313                 elif itm.__class__ == Spare_Device:
01314                         parent = itm.GetHWType()
01315                         type = TN_DEVICE
01316                 elif itm.__class__ == Spare_Port:
01317                         parent = itm.GetSpareDevice()
01318                         type = TN_PORT
01319                 if itm.GetSaveStatus() == CREATE: #undo create in tree view
01320                         try:
01321                                 my_id = self.GetSelectWindow().GetItemID(itm.GetName())
01322                                 self.GetSelectWindow().RemoveItem(my_id,parent)
01323                                 self.GetSelectWindow().SetItemToDeleted(itm.GetName())
01324                         except KeyError,err:
01325                                 pass
01326                 elif itm.GetSaveStatus() == DELETE: #undo delete in tree view
01327                         try:
01328                                 my_id = self.GetSelectWindow().GetItemID(parent)
01329                                 self.GetSelectWindow().AddItem(itm,type)
01330                         except KeyError,err:
01331                                 pass
01332                 else: #undo modify, we do NOT undo rename, so no action necessary
01333                         pass
01334 
01335                 # undo stuff in visual window
01336                 if itm.__class__ in [Device,Link] and itm.GetSaveStatus() == CREATE: #undo create device and link
01337                         tmp_obj = self.GetVisWindow().FindByName(itm.GetName())
01338 
01339                         if tmp_obj:
01340                                 self.GetVisWindow().DeselectAll(refresh=False)
01341                                 self.GetVisWindow().Select(tmp_obj,False,False,refresh=False)
01342                                 self.GetVisWindow().DoDelete(None,False,refresh=False)
01343 
01344                                 self.__visualredolist.append(tmp_obj) #For REDOing create
01345                         else: #not found in visual contents, create dataobject
01346                                 self.__visualredolist.append(itm)
01347 
01348                 elif itm.__class__ in [Device,Link] and itm.GetSaveStatus() != CREATE: #undo modify or delete
01349 
01350                         if itm.GetSaveStatus() == MODIFY:
01351                                 tmp_obj = self.GetVisWindow().FindByName(itm.GetName())
01352 
01353                                 if itm.__class__ == Link:
01354                         
01355                                         if tmp_obj:
01356                                                 self.GetVisWindow().DoDeleteObj(itm.GetName(),False,refresh=False)
01357                                                 self.__visualredolist.append(tmp_obj)
01358                                         else:
01359                                                 self.__visualredolist.append(itm)
01360                                 else: #Device
01361 
01362                                         if tmp_obj:
01363                                                 self.GetVisWindow().Deselect(tmp_obj,refresh=False)
01364                                                 newobj = Device(itm.GetSystem(),itm.GetName(),False)
01365                                                 tmp_obj.SetObjectRef(newobj)
01366                                                 self.GetVisWindow().Select(tmp_obj,refresh=False)
01367                                                 self.__visualredolist.append(tmp_obj) #with wrong reference, but will be fixed
01368                                         else:
01369                                                 #tmp_dev = Device(itm.GetSystem(),itm.GetName(),False)
01370                                                 self.__visualredolist.append(itm)
01371 
01372                         #for both delete and modify
01373                         vis_obj = None
01374 
01375                         i = len(self.__visualundolist)-1
01376                         while i >= 0:
01377                                 if self.__visualundolist[i].__class__ == DrawingObject:
01378                                         if self.__visualundolist[i].GetName() == itm.GetName() and self.__visualundolist[i].GetObject().__class__ == itm.__class__:
01379                                                 vis_obj = self.__visualundolist.pop(i)
01380                                                 break
01381                                 elif self.__visualundolist[i].__class__ in [Device,Link]:
01382                                         if self.__visualundolist[i].GetName() == itm.GetName() and self.__visualundolist[i].__class__ == itm.__class__:
01383                                                 vis_obj = self.__visualundolist.pop(i)
01384                                                 break
01385                                         
01386                                 i -= 1
01387 
01388                         if vis_obj and not (itm.__class__ == Device and itm.GetSaveStatus() == MODIFY):
01389                                 if vis_obj.__class__ == DrawingObject:
01390                                         #dynamic view, subsystem view or view not changed since UNDO
01391                                         if vis_obj.GetObject().__class__ == Device: #found device object, can easily recover
01392                                                 self.GetVisWindow().AddToContents(vis_obj,False)
01393                                                 self.GetVisWindow().Deselect(vis_obj,refresh=False)
01394                                                 newobj = Device(itm.GetSystem(),itm.GetName(),False)
01395                                                 vis_obj.SetObjectRef(newobj)
01396                                                 self.GetVisWindow().Select(vis_obj,refresh=False)
01397 
01398                                                 #may need to connect to links as well
01399                                         elif vis_obj.GetObject().__class__ == Link: #found link object
01400                                                 #self.GetVisWindow().AddToContents(vis_obj,False) #need to connect to devices as well
01401                                                 vis_link = self.GetVisWindow().CreateConnectedLink(vis_obj.GetObject(),vis_obj.GetPosition(),vis_obj.GetSize())
01402                                 elif vis_obj.__class__ in [Device,Link]:
01403                                         if vis_obj.__class__ == Device:
01404                                                 self.GetVisWindow().CreateNode(0,0,vis_obj,False)
01405                                         elif vis_obj.__class__ == Link:
01406                                                 self.GetVisWindow().CreateConnectedLink(vis_obj)
01407 
01408                                 else: #another unknown classtype
01409                                         print "Found a classtype we do not know how to handle!"
01410 
01411 
01412                 if showprogress:
01413                         self.ProgressData(0,False,1)
01414 
01415         #Edit menu
01416         if self.__undolist == []:
01417                 description = ""
01418         else:
01419                 description = self.__undolist[len(self.__undolist)-1][1]
01420 
01421         #REDO descr:
01422         descrredo = self.__redolist[len(self.__redolist)-1][1]
01423 
01424         menu = wxMenu()
01425         menu.Append(ID_UNDO,"&Undo " + str(description) + "\tCtrl-Z","The last action you did will be undone, and added to the Redo list")
01426         menu.Append(ID_REDO,"&Redo " + str(descrredo) + "\tCtrl-R","The last action you UNDOed will be undone")
01427         self.GetMenuBar().Replace(1,menu,"&Edit")
01428 
01429         if self.__undolist == []:
01430                 menu.Enable(ID_UNDO,False)
01431 
01432         menu.Enable(ID_REDO,True)
01433 
01434         if showprogress:
01435                 self.ProgressData(0,True,0)
01436 
01437         self.GetVisWindow().Refresh()
01438         self.ShowError("The UNDO operation was successfully finished.",ERR_INFORMATION,False)
01439 
01440     ##
01441     #  We check if there is anything to save in the dirty objects list. We actually check
01442     #   that if there are any objects in the dirty objects list that cancel each other 
01443     #   (first create, then delete = no change in ConfDB).
01444     # 
01445     #   !return - True if there is nothing to save, False otherwise.
01446     #   
01447     def IsSaveListEmpty(self):
01448         
01449         return (self.CleanUpDirtyObjects(False) == [])
01450 
01451     ##
01452     #  Get the dirty objects list.
01453     #   
01454     def GetDirtyObjects(self):
01455         return self.__dirtyobjects
01456 
01457     ##
01458     #  Get the rename objects list.
01459     #   
01460     def GetRenamedObjects(self):
01461         return self.__renameobjects
01462 
01463     ##
01464     #  Get the list of names of objects that have been renamed. This returns the names of the 
01465     #   objects before they were renamed.
01466     #   
01467     def GetOldNames(self):
01468         return self.__oldnames
01469 
01470     ##
01471     #  Get the list of names of objects that have been renamed. This returns the names of the
01472     #   objects after they were renamed.
01473     #   
01474     def GetNewNames(self):
01475         return self.__newnames
01476 
01477     ##
01478     #  Get a dictionary of mapping between old and new names of renamed objects:
01479     #   old names : new names
01480     #   
01481     def GetOldNamesOfRenamed(self):
01482         return self.__oldnamesrenamed
01483 
01484     ##
01485     #  Get a dictionary of mappings between new and old names of renamed objects:
01486     #   new names : old names    
01487     #   
01488     def GetNewNamesOfRenamed(self):
01489         return self.__newnamesrenamed
01490 
01491     ##
01492     #  Reset all lists that has something to do with dirty objects: UNDO,REDO,rename etc.
01493     #   and the dirty objects list itself of course. Done on program termination and
01494     #   if the user switches from creation mode to navigation mode f.ex.
01495     # 
01496     #   TODO: should there also be an iteration through the objects and explicitly
01497     #   deleting each one of them, or is this not necessary? Check if the memory usage
01498     #   of the program changes.
01499     #   
01500     def ResetDirtyObjects(self):
01501 
01502         self.__dirtyobjects = []
01503         self.__undolist = [] #information needed for undo
01504         self.__redolist = [] #Once you undo, the undo object is appended to the redo list. information needed for redo
01505         self.__redoobjectlist = [] #undone objects, opposite to dirtyobjects list. Can be added back to dirtylist and savelist if REDOed
01506 
01507         self.__visualundolist = [] #On delete, store object here if want to UNDO it later
01508         self.__visualredolist = [] #When UNDOing a create 
01509         self.__renameobjects = []
01510         self.__oldnamesrenamed = {}
01511         self.__newnamesofrenamed = {}
01512         self.__newnames = []
01513         self.__oldnames = []
01514 
01515     ##
01516     #  Adds a data object to the dirty objects list. This can be done when
01517     #   the user changes something (create,modify,delete) or objects are UNDONE
01518     #   and REDONE.
01519     # 
01520     #   @object - the object that is being added to the dirty objects list (because
01521     #   it will be applied to the ConfDB later
01522     #   @fromredoundo - If the object is added as a result/action of a REDO or UNDO (True),
01523     #   otherwise set to False
01524     # 
01525     #   !return - False on Error, true if success
01526     #   
01527     def AddToDirtyObjects(self,object,fromredoundo=False):
01528         if self.GetUserMode() != ID_CREATION_MODE:
01529                 self.SetCreationMode(True)
01530         
01531         if not fromredoundo:
01532                 self.RecoverObjectToFile(object,state=DESIGN) # Add to recover file as normal if this function is not called from redo or undo
01533 
01534         
01535         i = len(self.__dirtyobjects) - 1
01536         while i >= 0:
01537                 # if we find the "same" object in the dirty list and the save statuses for the objects are inconsistent...return False
01538                 if self.__dirtyobjects[i].GetName() == object.GetName() and self.__dirtyobjects[i].__class__ == object.__class__:
01539                         if (isinstance(self.__dirtyobjects[i],Link) and self.__dirtyobjects[i].GetNodeTo()==object.GetNodeTo() and self.__dirtyobjects[i].GetNodeFrom()== object.GetNodeFrom() and self.__dirtyobjects[i].GetPortTo()== object.GetPortTo() and self.__dirtyobjects[i].GetPortFrom()== object.GetPortFrom()):
01540                                 linkExist = True
01541                         else:
01542                                 linkExist = False
01543                                 
01544                         if isinstance(self.__dirtyobjects[i],Device) or isinstance(self.__dirtyobjects[i],Port) or linkExist:
01545                                 if self.__dirtyobjects[i].GetSaveStatus() == DELETE and object.GetSaveStatus() != CREATE:
01546                                         self.ShowError("You are trying to modify or delete an object that has already been deleted: " + str(object.GetName()),ERR_ERROR)
01547                                         return False #if deleted, we cannot delete again or modify : set error message
01548                                 elif self.__dirtyobjects[i].GetSaveStatus() == CREATE and object.GetSaveStatus() == CREATE:
01549                                         self.ShowError("You are trying to create an object with the same name as an already existing object: " + str(object.GetName()),ERR_ERROR)
01550 
01551                                         return False #we cannot recreate same object : set error message
01552                                 elif self.__dirtyobjects[i].GetSaveStatus() == MODIFY and object.GetSaveStatus() == CREATE:
01553                                         self.ShowError("You are trying to create an object with the same name as an already existing object: " + str(object.GetName()),ERR_ERROR)
01554                                         return False #cannot recreate already created object
01555                         
01556                         break #found a valid object in the list, and the given object for insertion is valid, break while loop and append
01557                 i -= 1
01558 
01559 
01560 
01561         if object.GetSaveStatus() == DELETE: #deleting object, save visual object in a list for later UNDO possibility
01562                 visobj = self.GetVisWindow().FindByName(object.GetName())
01563                 if visobj != None:
01564                         self.__visualundolist.append(visobj)
01565                 else:
01566                         pass
01567 
01568         self.__dirtyobjects.append(object)
01569         return True
01570 
01571     ##
01572     #  Remove the last instance of an object from the dirtylist given the name (ID) of the object 
01573     #   and the objectype, and return it. Return False if not found
01574     #   The objecttype can be of the following types: Device, DeviceType, SubSystem, Link, LinkType, Port.
01575     #           
01576     #   @objectname - name of the object to be removed
01577     #   @objecttype - class type of the object to be removed (Device, DeviceType, etc)
01578     # 
01579     #   !return - the removed object instance if found, False if not found
01580     #   
01581     def RemoveFromDirtyObjects(self,objectname,objecttype):
01582         
01583         i = len(self.__dirtyobjects) - 1
01584         while i >= 0:
01585                 if self.__dirtyobjects[i].GetName() == objectname and self.__dirtyobjects[i].__class__ == objecttype:
01586                         my_item = str(self.__dirtyobjects[i].__class__) + ": " + str(self.__dirtyobjects[i].GetSaveStatus())
01587                         return self.__dirtyobjects.pop(i)
01588                 i -= 1
01589 
01590         return False #not found
01591 
01592     ##
01593     #  Used for UNDOing operations. One operation like duplicate items can include n number of DBcalls, starting from the index given. 
01594     #   
01595     #   @indexfrom - start index to remove objects from the dirty objects list from (all objects from and after this index will be removed)
01596     # 
01597     #   !return - a list of the objects that were removed
01598     #   
01599     def RemoveDirtyObjects(self,indexfrom):
01600 
01601         tmp_removed = []
01602         i = indexfrom #check that indexfrom is not >= len(list)
01603         while i < len(self.__dirtyobjects):
01604                 tmp_removed.append(self.__dirtyobjects.pop(i))
01605 
01606         return tmp_removed
01607 
01608     ##
01609     #  Get an object from the dirty list by name and type. We only look for objects that exist, and are not set for deletion.
01610     #   If object is found, and the last instance is not set for deletion, return the last instance, otherwise False.
01611     #   
01612     #   @objectname - name of the object to remove
01613     #   @objecttype - type of the object to remove (Device,DeviceType etc)
01614     # 
01615     #   !return - The instance of the last object with objectname and objectype given as parameters if it is not set for deletion,
01616     #   otherwise return False
01617     #   
01618     def GetDirtyObject(self,objectname,objecttype):
01619         
01620         i = len(self.__dirtyobjects) - 1
01621         while i >= 0:
01622                 if self.__dirtyobjects[i].GetName() == objectname and self.__dirtyobjects[i].__class__ == objecttype:
01623                         if self.__dirtyobjects[i].GetSaveStatus() == DELETE:
01624                                 return False
01625                         else:
01626                                 return self.__dirtyobjects[i]
01627                 i -= 1
01628 
01629         return False
01630 
01631     ##
01632     #  Get an object from the dirty list...returns the object if found, or False if not found 
01633     # 
01634     #   @objectname - name of the object to find
01635     #   @objecttype - type of the object to find
01636     # 
01637     #   !return - the last instance of the object if found, otherwise False
01638     #   
01639     def FindDirtyObject(self,objectname,objecttype):
01640         
01641         i = len(self.__dirtyobjects) - 1
01642         while i >= 0:
01643                 if self.__dirtyobjects[i].GetName() == objectname and self.__dirtyobjects[i].__class__ == objecttype:
01644                                 return self.__dirtyobjects[i]
01645                 i -= 1
01646 
01647         return False
01648 
01649     ##
01650     #  Recover previously stored objects in the recover file to the dirty objects list; because
01651     #   the objects stored in recover file is stored there because they are not applied to the
01652     #   ConfDB.
01653     #   
01654     #   First we check to see if the file is not empty. If it is not, it is most likely that the application crashed 
01655     #   or the user closed the application before he/she had saved the data, ask therefore to recover non-saved objects 
01656     #   since last time the app was run. Ask first to recover, the if you should reset the file. If user wants to recover,
01657     #   all objects are recovered to dirtylist, of he wants to reset, file is reset. 
01658     #   
01659     #   @filename - name of the recover file where we should look for recovered/not stored objects.
01660     # 
01661     #   !return - True if successful, False otherwise.
01662     #   
01663     def RecoverObjectFromFile(self,filename="recover.dat"):
01664         devicetype_found = False
01665         linktype_found = False
01666         
01667         try:
01668                 try:
01669                         file = open(filename,"r")
01670                 except IOError,err:   
01671                         file = open(filename,"w") #file does not exist, ignore recover, but create file
01672                         file.close()
01673                         self.ShowError("Error opening file recover.dat for reading " + str(err),ERR_ERROR)
01674                         return False    
01675 
01676                 if file.read(1) != "":
01677                         file.close()
01678                         ans = wxMessageBox("It seems that you did not save your changes in the database last time you used the program. The changes you did can be recovered, do you want to recover?","Recover?", wxYES_NO | wxICON_QUESTION)
01679                         if ans == wxNO:
01680                                 ans = wxMessageBox("Ok. Are you sure you want to reset/remove the recovered objects?","Reset recovered objects?", wxYES_NO | wxICON_QUESTION)
01681                                 if ans == wxYES:
01682                                         self.ResetRecoverFile()
01683                                 else: #wxNO
01684                                         self.RecoverObjectFromFile() #restart questioning
01685                         else: #wxYES
01686                                 #recover objects
01687                                 file = open(filename,"r")
01688                                 for line in file:
01689                                         obj_arr = line.split("|")
01690                                         tmp_dict = {}
01691                                         for itm in obj_arr:
01692                                                 tmp_val = itm.split("^")
01693                                                 if tmp_val[1] != "\n":
01694                                                         if tmp_val[2] == "s": #s(tring)
01695                                                                 tmp_dict[tmp_val[0]] = str(tmp_val[1])
01696                                                         elif tmp_val[2] == "i": #i(nteger)
01697                                                                 tmp_dict[tmp_val[0]] = int(tmp_val[1])
01698                                                         elif tmp_val[2] == "w": #wxColour
01699                                                                 cols = tmp_val[1].split("(")
01700                                                                 cols = cols[1].split(")")
01701                                                                 cols = cols[0].split(",")
01702                                                                 tmp_dict[tmp_val[0]] = wxColour(int(cols[0]),int(cols[1]),int(cols[2]))
01703                                                         else:
01704                                                                 print "A value could not be interpreted correctly, and was not extracted: " + str(tmp_val[0])
01705 
01706                                         classtype = tmp_dict["Class"]
01707                                         statetype = tmp_dict["State"]
01708                                         del tmp_dict["State"] #This is only helpers for writing/reading to/from file, not needed any more
01709                                         del tmp_dict["Class"]
01710 
01711                                         if classtype == "objectclasses.Device":
01712                                                 tmp_obj = Device(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_NAME],True)
01713                                         elif classtype == "objectclasses.Link":
01714                                                 tmp_obj = Link(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_LINK],False,True)
01715 
01716                                                 #Update last temporary link nr/ID, so we know where to go from on next
01717                                                 if tmp_dict[DEV_LINK].find("TMP_LINK_",0,len(tmp_dict[DEV_LINK])) != -1:
01718                                                         tmp_string = tmp_dict[DEV_LINK].replace("TMP_LINK_","")
01719                                                         try:
01720                                                                 tmp_string = int(tmp_string)
01721                                                                 if self.__lastlinknr < tmp_string:
01722                                                                         self.__lastlinknr = tmp_string
01723                                                         except ValueError,err:
01724                                                                 pass #an invalid number was given or invalid string for the
01725                                                                 # tmp link name
01726 
01727                                         elif classtype == "objectclasses.DeviceType":
01728                                                 tmp_obj = DeviceType(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_TYPE],True)
01729                                                 devicetype_found = True
01730                                         elif classtype == "objectclasses.Port":
01731                                                 tmp_obj = Port(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_PORTNBR],tmp_dict[DEV_PORTTYPE],tmp_dict[DEV_PORTWAY],tmp_dict[DEV_NAME],True)
01732                                         elif classtype == "objectclasses.LinkType":
01733                                                 tmp_obj = LinkType(tmp_dict[DEV_SYSTEM],tmp_dict[LINK_NAME],True)
01734                                                 linktype_found = True
01735                                         else:
01736                                                 print "Found a class type saved in Recover file that is not supported: " + str(classtype)
01737                                                 continue #next
01738 
01739                                         tmp_obj.SetDict(tmp_dict)
01740 
01741                                         if tmp_obj.GetSaveStatus() == RENAME: #rename object, update prev objects to the current name
01742                                                 self.UpdateRenamedObject(tmp_obj,recovertofile=False) #ignore db errors
01743                                         else:
01744                                                 if statetype == DESIGN:
01745                                                         self.AddToDirtyObjects(tmp_obj,True)
01746                                                 elif statetype == UNDO:
01747                                                         self.RemoveFromDirtyObjects(tmp_obj.GetName(),tmp_obj.__class__)
01748                                                 elif statetype == REDO:
01749                                                         self.AddToDirtyObjects(tmp_obj,True)
01750 
01751                                 file.close()
01752 
01753                                 if devicetype_found or linktype_found:
01754                                         self.RefreshObjectBoxData()
01755                 return True
01756 
01757         except IOError,err:
01758                 self.ShowError("An unexpected IOError occured while reading from recover.dat: " + str(err),ERR_ERROR)
01759                 return False
01760                                 
01761     ##
01762     #  Reset (clear) the recover file.
01763     # 
01764     #   @filename -  the name of the recover file to reset.
01765     #   
01766     #   !return - True if successful, otherwise False
01767     #   
01768     def ResetRecoverFile(self,filename="recover.dat"):
01769         
01770         try:
01771                 file = open(filename,"w")
01772                 file.write("") #reset
01773                 file.close()
01774                 return True
01775                 
01776         except IOError,err:
01777                 self.ShowError("An unexpected IOError occured while trying to reset the file " + str(filename),ERR_ERROR)
01778                 return False
01779 
01780     ##
01781     #  Write a data object to a recover file for later be able to recover it to the
01782     #   dirty objects list if it is not stored in the ConfDB before program termination.
01783     #   
01784     #   When objects are added to the dirty list or UNDOne/REDOne, they will be stored in a data file, with all the info 
01785     #   on the objects. This file will be erased as soon as the user have done a successful save to the database. If
01786     #   unsuccessful it is not cleared, and if the program crashes etc, this file will be automatically loaded on startup
01787     #   if user wants to, then all information will be added to the dirty objects list, and the user can continue where 
01788     #   he/she stopped the time before. When all the data is reloaded on startup, it is not cleared, it is only cleared 
01789     #   when a successful save is done.
01790     # 
01791     #   All kinds of actions are written; what the user do of actions, and also redo and undo actions by the user. This
01792     #   way the recover file looks like a history log of what the user have done of manipulative actions in CdbVis in the
01793     #   current (previous) session, and everything can easily be recovered to the previous state of the program.
01794     # 
01795     #   @object - the data object that should be added to the recover file
01796     #   @state - the type of action done on the object: DESIGN, UNDO or REDO
01797     #   @filename - name of the recover file to save it to
01798     #   @write - w or a, w will start to write to the file at the beginning overwriting the previous contents,
01799     #   a will write to the file at the end; append to the file.
01800     # 
01801     #   !return - True if successful, False otherwise
01802     #   
01803     def RecoverObjectToFile(self,object,state=DESIGN,filename="recover.dat",write="a"):
01804         
01805         try:    
01806                 file = open(filename,write) #open() is an alias to file(), a - append, w - write (overwrite)
01807                 properties = object.GetObjectInfo(True)
01808                 file.write("Class" + "^" + str(object.__class__) + "^s")
01809                 file.write("|" + "State" + "^" + str(state) + "^i|")
01810 
01811                 #AND we must save datatype; i for integers and booleans, s for strings (the rest), w for wxColour obj
01812                 for property in properties:
01813                         if (properties[property]).__class__ == int(3).__class__: #integers and boolean
01814                                 file.write(str(property) + "^" + str(properties[property]) + "^i|")
01815                         elif (properties[property]).__class__ == str("string").__class__: #string or similar
01816                                 file.write(str(property) + "^" + str(properties[property]) + "^s|")
01817                         elif (properties[property]).__class__ == tuple: #Colour
01818                                 file.write(str(property) + "^" + str(properties[property]) + "^w|")
01819                         else:
01820                                 print "Class type not supported: " + str(properties[property].__class__) + " for storing in the recover file"
01821                                 
01822                 file.write("^\n")
01823                 file.close()
01824 
01825                 return True
01826 
01827         except IOError,err:
01828                 self.ShowError("An unexpected error occured while writing to recovery file",ERR_ERROR)
01829                 return False
01830 
01831     ##
01832     #  Remove objects in the dirty objects list that cancel each other out; f.ex. first a create and then a
01833     #           delete on the same object will cancel both of them out, and hence not necessary to write in the ConfDB.
01834     #           May act directly on the dirty objects list before dirty objects are stored in ConfDB, or that the user
01835     #           checks whether there is something to save or not in the dirty objects list.
01836     #       
01837     #           This auxiliary function is deleting create-modify-delete objects from the dirty list, since we do not 
01838     #           want to store those in the database. ie. objects that are both created (and modified) before they are
01839     #           deleted in this session. This may cause some naming problems, but hopefully not, if we can have a list
01840     #           of names on deleted objects, that are free to use for new objects. 
01841     # 
01842     #           We also but several CREATE and MODIFY instances of the same object together to 1 object for storing in
01843     #           ConfDB.
01844     # 
01845     #           Rename objects are not affected at all.
01846     # 
01847     #           @actOnDirtyList - Whether objects that cancel each other out are directly removed from the dirty objects
01848     #           list or only done in a temporary list copy of the dirty objects list.
01849     # 
01850     #           !return - If we act on the real dirty objects list: True if dirty objects list became empty after 
01851     #                   cancelling out objects, False if not.
01852     #                   If we act on a copy of the real dirty objects list: The "repaired" dirty objects list copy where
01853     #                   objects that appeal each other are compressed if the list is not empty, else the empty list is 
01854     #                   returned.
01855     #           
01856     def CleanUpDirtyObjects(self,actOnDirtyList=True):
01857                 
01858                 dict_setformodify = {} #name : index, for objects set for modify
01859                 dict_delobjs = {} #delete objects found, see if we find modify and create of these object, if so, remove them
01860 
01861                 lst_delobjs = []
01862                 if not actOnDirtyList:
01863                         dirtyobjs = self.__dirtyobjects[:]
01864                 else:
01865                         dirtyobjs = self.__dirtyobjects
01866 
01867 
01868                 i = len(dirtyobjs)-1
01869                 while i >= 0:
01870                         if dirtyobjs[i].GetSaveStatus() == DELETE: #id 2
01871                                 dict_delobjs[dirtyobjs[i].GetName()] = dirtyobjs[i]
01872                                 lst_delobjs.append(dirtyobjs[i].GetName())
01873                         elif dirtyobjs[i].GetSaveStatus() == MODIFY and dirtyobjs[i].GetName() in lst_delobjs:
01874                                 if dirtyobjs[i].__class__ != Port:
01875                                         try:
01876                                                 dict_setformodify[dirtyobjs[i].GetName()].append(dirtyobjs[i])
01877                                         except KeyError,err:
01878                                                 dict_setformodify[dirtyobjs[i].GetName()] = []
01879                                                 dict_setformodify[dirtyobjs[i].GetName()].append(dirtyobjs[i])
01880                                 else:
01881                                         try:
01882                                                 dict_setformodify[dirtyobjs[i].GetName()].append(dirtyobjs[i])
01883                                         except KeyError,err:
01884                                                 dict_setformodify[dirtyobjs[i].GetName()] = []
01885                                                 dict_setformodify[dirtyobjs[i].GetName()].append(dirtyobjs[i])
01886                                         
01887                                         
01888                         elif dirtyobjs[i].GetSaveStatus() == CREATE and dirtyobjs[i].GetName() in lst_delobjs:  
01889                                 lst_delobjs.remove(dirtyobjs[i].GetName())
01890                                 dirtyobjs.remove(dict_delobjs[dirtyobjs[i].GetName()])
01891 
01892                                 try:
01893                                         mod_objs = dict_setformodify[dirtyobjs[i].GetName()]
01894                                         for mod_obj in mod_objs:
01895                                                 dirtyobjs.remove(mod_obj)
01896 
01897                                 except KeyError,err:
01898                                         print "Modify object not found for " + str(dirtyobjs[i].GetName()) + ", delete create object instance then."
01899 
01900                                 dirtyobjs.remove(dirtyobjs[i])
01901 
01902                         i -= 1
01903 
01904                 if dirtyobjs == []:
01905                         if not actOnDirtyList: #return the empty list
01906                                 return []
01907                         return True #if savelist was "empty", nothing to do against database.
01908                 else:
01909                         if not actOnDirtyList: #return the copy
01910                                 return dirtyobjs
01911                         return False
01912 
01913     ##
01914     #  Load a file (XML or TEXT) with data to be added to the ConfDB as objects of DeviceType, LinkType, 
01915     #   Device, Link and Port, and add them to the dirty objects list, pending for storing in the ConfDB. The
01916     #   user will him/herself store the objects with the OnSave function, or use the ExportConfDBFunctions function
01917     #   to export the objects to a file.
01918     # 
01919     #   !return - False on Error
01920     #   
01921     def MassInsert(self):
01922         # Constants that can be used in the data file, conversion to integer
01923         conversions = {'NO_STATUS':-1,'CREATE':0,'MODIFY':1,'DELETE':2,'RENAME':3,'False':0,'True':1}
01924         
01925         self.__directoryname = "" # Application (or current) directory
01926         opendlg = QFileDialog.getOpenFileName(self.__directoryname,\
01927                     "Data file (*.dat);;Text files (*.txt);;XML files (*.xml)",\
01928                     self,\
01929                     "Find a data file to load",\
01930                     "Choose a file" );
01931         opendlg = str(opendlg)
01932         if opendlg=='':
01933                 self.ShowError("Mass Insert : No file selected", ERR_ERROR,False)
01934                 return False
01935         print "file selected : "+opendlg
01936         filename =  opendlg[len(opendlg)-opendlg[::-1].index("/"):]
01937         directory = opendlg.strip(filename)
01938         fileext = filename.split(".")[1] # Cannot get error because only files with extensions are filtered to be shown
01939 
01940         filepath = os.path.join(directory,filename) # the filepath and file name        
01941         
01942         if fileext == "xml": #predefined xml format, see user documentation (also for txt and dat)
01943                 from xml.dom import Node
01944                 import xml.dom.minidom # import parse
01945                 try:
01946 
01947                         xmldocument = xml.dom.minidom.parse(filepath)
01948                         # The first child to this document is the root/top node, which covers the whole file
01949                         # This has to be here as defined, and will cause parser error if removed
01950                         root = xmldocument.childNodes[0] #first element; outer element: only 1
01951 
01952                         for node in root.childNodes: # We should have the data types (Device, Link, Port...) as children here
01953                                 # The parameter-value pairs are attributes of the element, or a text element
01954                                 if node.nodeType == Node.ELEMENT_NODE:
01955                                         tmp_dict = {}
01956                                         tmp_dict["Datatype"] = node.nodeName
01957                                         
01958                                         print 'Element name: %s' % node.nodeName
01959                                         for child in node.childNodes: # property nodes
01960                                                 if child.nodeType == Node.ELEMENT_NODE:
01961                                                         print 'Element name: %s' % child.nodeName
01962                                                         attributeName = child.nodeName
01963                                                         for textnode in child.childNodes: # text nodes
01964                                                                 if textnode.nodeType == Node.TEXT_NODE:
01965                                                                         if str(textnode.data).strip() == "":
01966                                                                                 # line break
01967                                                                                 pass
01968                                                                         elif textnode.nodeName == "#text":
01969                                                                                 print '\tTextValue: %s' % (textnode.data)
01970                                                                                 tmp_val = str(textnode.data).split(";")
01971                                                                                 if tmp_val[1] == "s": #s(tring)
01972                                                                                         tmp_dict[attributeName] = str(tmp_val[0])
01973                                                                                 elif tmp_val[1] == "i": #i(nteger)
01974                                                                                         # if we used constant instead of int
01975                                                                                         # find corresponding int in dict.
01976                                                                                         if tmp_val[0] in conversions:
01977                                                                                                 tmp_dict[attributeName] = conversions[tmp_val[0]]
01978                                                                                         else:
01979                                                                                                 tmp_dict[attributeName] = int(tmp_val[0])
01980                                                                                 elif tmp_val[1] == "w": #wxColour
01981                                                                                         cols = tmp_val[0].split("(")
01982                                                                                         cols = cols[1].split(")")
01983                                                                                         cols = cols[0].split(",")
01984                                                                                         tmp_dict[attributeName] = wxColour(int(cols[0]),int(cols[1]),int(cols[2]))
01985                                                                                 else:
01986                                                                                         print "A value could not be interpreted correctly, and was not extracted: " + str(tmp_val[0])
01987 
01988                                         classtype = tmp_dict["Datatype"]
01989                                         del tmp_dict["Datatype"]
01990 
01991                                         if classtype == "Device":
01992                                                 tmp_obj = Device(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_NAME],True)
01993                                         elif classtype == "Link":
01994                                                 tmp_obj = Link(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_LINK],False,True)
01995                                                 tmp_dict[DEV_LINK] = "TMP_LINK_" + str(self.GetNewLinkNr())
01996                                         elif classtype == "Spare_Device":
01997                                                 tmp_obj = Spare_Device(tmp_dict[DEV_HWTYPE],tmp_dict[DEV_SERIAL],tmp_dict[SPARE_DEV_NAME],True)
01998                                         elif classtype == "DeviceType":
01999                                                 tmp_obj = DeviceType(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_TYPE],True)
02000                                         elif classtype == "Port":
02001                                                 tmp_obj = Port(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_PORTNBR],tmp_dict[DEV_PORTTYPE],tmp_dict[DEV_PORTWAY],tmp_dict[DEV_NAME],True)
02002                                         elif classtype == "Spare_Port":
02003                                                 tmp_obj = Spare_Port(tmp_dict[DEV_PORTNBR],tmp_dict[DEV_PORTTYPE],tmp_dict[DEV_PORTWAY],tmp_dict[DEV_SERIAL],True)
02004                                         elif classtype == "LinkType":
02005                                                 tmp_obj = LinkType(tmp_dict[DEV_SYSTEM],tmp_dict[LINK_NAME],True)
02006                                         else:
02007                                                 print "Found a Datatype that is not supported: " + str(classtype)
02008                                                 continue #next
02009 
02010                                         tmp_obj.SetDict(tmp_dict)
02011 
02012                                         if tmp_obj.GetSaveStatus() == RENAME: #rename object, update those in dirty list
02013                                                 self.UpdateRenamedObject(tmp_obj,recovertofile=True)
02014                                         else: # normal add to dirty objects list
02015                                                 self.AddToDirtyObjects(tmp_obj,False)
02016 
02017                 except xml.parsers.expat.ExpatError,err:
02018                         self.ShowError("Error while parsing XML file: " + str(err),ERR_ERROR)
02019                         return False
02020                 except IndexError,err:
02021                         self.ShowError("An unexpected IndexError occured while reading, probably due to a syntax error; remember that every parameter and value must be set like this: <parametername>parametervalue:datatype</parametername>",ERR_ERROR)
02022                         return False
02023                 except ValueError,err:
02024                         self.ShowError("There was a data conversion error while reading from file, probably due to wrong data type given for a value.",ERR_ERROR)
02025                         return False
02026 
02027 
02028         elif fileext in ["txt","dat"]: # the same format, just different file extension. Similar to recovery file format.
02029                 try:
02030                         try:
02031                                 file = open(filepath,"r")
02032                         except IOError,err:
02033                                 self.ShowError("Error opening file " + str(filepath) + " for reading: " + str(err),ERR_ERROR)
02034                                 return False    
02035                         
02036                         if file.read(1) != "":
02037                                 file.seek(0) # go back to start of file
02038                                 for line in file: # one object per line
02039                                         obj_arr = line.split("|") # attributename - value pairs split by |
02040                                         tmp_dict = {}
02041                                         for itm in obj_arr:
02042                                                 if itm != "" and itm[0] not in ["","\r","\n"]: #empty row
02043                                                         tmp_val = itm.split(";")
02044                                                         if tmp_val[1] not in ["\n","\r"]:
02045                                                                 if tmp_val[2] == "s": #s(tring)
02046                                                                         tmp_dict[tmp_val[0]] = str(tmp_val[1])
02047                                                                 elif tmp_val[2] == "i": #i(nteger)
02048                                                                         if tmp_val[1] in conversions:
02049                                                                                 tmp_dict[tmp_val[0]] = conversions[tmp_val[1]]
02050                                                                         else:
02051                                                                                 tmp_dict[tmp_val[0]] = int(tmp_val[1])
02052                                                                 elif tmp_val[2] == "w": #wxColour
02053                                                                         cols = tmp_val[1].split("(")
02054                                                                         cols = cols[1].split(")")
02055                                                                         cols = cols[0].split(",")
02056                                                                         tmp_dict[tmp_val[0]] = (int(cols[0]),int(cols[1]),int(cols[2]))
02057                                                                 else:
02058                                                                         print "A value could not be interpreted correctly, and was not extracted: " + str(tmp_val[0])
02059 
02060                                         classtype = tmp_dict["Datatype"]
02061                                         del tmp_dict["Datatype"]
02062                                         if classtype == "Device":
02063                                                 tmp_obj = Device(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_NAME],True)
02064                                         elif classtype == "Link":
02065                                                 tmp_obj = Link(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_LINK],False,True)
02066                                                 tmp_dict[DEV_LINK] = "TMP_LINK_" + str(self.GetNewLinkNr())
02067                                         elif classtype == "Spare_Device":
02068                                                 tmp_obj = Spare_Device(tmp_dict[DEV_HWTYPE],tmp_dict[DEV_SERIAL],tmp_dict[SPARE_DEV_NAME],True)
02069                                         elif classtype == "DeviceType":
02070                                                 tmp_obj = DeviceType(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_TYPE],True)
02071                                         elif classtype == "Port":
02072                                                 tmp_obj = Port(tmp_dict[DEV_SYSTEM],tmp_dict[DEV_PORTNBR],tmp_dict[DEV_PORTTYPE],tmp_dict[DEV_PORTWAY],tmp_dict[DEV_NAME],True)
02073                                         elif classtype == "Spare_Port":
02074                                                 tmp_obj = Spare_Port(tmp_dict[DEV_PORTNBR],tmp_dict[DEV_PORTTYPE],tmp_dict[DEV_PORTWAY],tmp_dict[DEV_SERIAL],True)
02075                                         elif classtype == "LinkType":
02076                                                 tmp_obj = LinkType(tmp_dict[DEV_SYSTEM],tmp_dict[LINK_NAME],True)
02077                                         else:
02078                                                 print "Found a Datatype that is not supported: " + str(classtype)
02079                                                 continue #next
02080 
02081                                         tmp_obj.SetDict(tmp_dict)
02082 
02083                                         if tmp_obj.GetSaveStatus() == RENAME: #rename object, update those in dirty list
02084                                                 self.UpdateRenamedObject(tmp_obj,recovertofile=True)
02085                                         else: # normal add to dirty objects list
02086                                                 self.AddToDirtyObjects(tmp_obj,False)
02087 
02088                                 file.close()
02089                                 self.ShowError(" Data in "+opendlg+" was successfuly loaded !",ERR_SUCCESS)
02090                 except IOError,err:
02091                         self.ShowError("An unexpected IOError occured while reading from " + str(filepath) + ": " + str(err),ERR_ERROR)
02092                         return False
02093                 except IndexError,err:
02094                         self.ShowError("An unexpected IndexError occured while reading, probably due to a syntax error; remember that every parameter and value must be set like this: |parametername:parametervalue:parametertype|",ERR_ERROR)
02095                         return False
02096                 except ValueError,err:
02097                         self.ShowError("There was a data conversion error while reading from file, probably due to wrong data type given for a value.",ERR_ERROR)
02098                         return False
02099 
02100         else:
02101                 self.ShowError("The file extension of the file you loaded is not supported",ERR_ERROR)
02102                 return False
02103 
02104 
02105     def ImportCSV(self,filename):
02106         def __addTo(elt,object_list):
02107                 if object_list==[] or (object_list and elt.GetName() not in [item.GetName() for item in object_list]):
02108                         object_list.append(elt)
02109                         return elt
02110                 else:
02111                         for item in object_list:
02112                                 if item.GetName() == elt.GetName():
02113                                         return item
02114         
02115         def __CreateLink(FromPort,ToPort):
02116                 if not FromPort or not ToPort:
02117                         pdb.set_trace()
02118                         raise 'No Port Given to the __CreateLink function'
02119                         return False
02120                 tmp_link = Link('')
02121                 tmp_link.SetNodeTo(ToPort.GetDevice())
02122                 tmp_link.SetNodeFrom(FromPort.GetDevice())
02123                 tmp_link.SetPortTo(str(ToPort.GetPortNbr()))
02124                 tmp_link.SetPortFrom(str(FromPort.GetPortNbr()))
02125                 tmp_link.SetType(LINK_TYPE)
02126                 tmp_link.SetName(tmp_link.GetNodeFrom()+":"+str(tmp_link.GetPortFrom())+":"+tmp_link.GetNodeTo()+":"+str(tmp_link.GetPortTo()))
02127                 return tmp_link
02128         def LookIn(list,current,steps):
02129                 length = len(list)
02130                 index = current
02131                 count = 0
02132                 if steps>0:
02133                         while index < length-1 and count < steps:
02134                                 if list[index]!=None:
02135                                         count += 1
02136                                 index += 1
02137                         if list[index] == None:
02138                                 return None
02139                         else:
02140                                 return list[index]
02141                 if steps<0:
02142                         while index >0 and count < abs(steps):
02143                                 if list[index]!=None:
02144                                         count += 1
02145                                 index -= 1
02146                         if list[index] == None:
02147                                 return None
02148                         else:
02149                                 return list[index]
02150                                 
02151                 
02152         filename = "Velo_Connectivity_clean.csv"
02153         reader = csv.reader(open(filename, "rb"))
02154         DEVICE, DEVPORT, PORT, LINK = 0, 1, 2, 3
02155         LINK_TYPE = 'hv'
02156         device_list = []
02157         port_list = []
02158         link_list = []
02159         types = [None, None, None, None, DEVICE, PORT, LINK, DEVPORT, DEVPORT, None, LINK, DEVPORT, DEVPORT, LINK, DEVICE]
02160         lastWay = 2
02161         lastPort = None
02162 
02163         try:
02164             # pdb.set_trace()
02165             for row in reader:
02166                 #print row
02167                 index = 0
02168                 length = len(row)
02169                 while index < length:
02170                         cell = row[index]
02171                         tmp_port = None
02172                         if types[index]==DEVICE:
02173                                 # create device if does not exist and add it the the  object_list
02174                                 tmp_device = __addTo(Device("",cell),device_list)
02175                                 # Create a Link if  next cell is not a Port and previous cell is a LINK or a Port or a DEVPORT. 
02176                                 if index+1==length or (index+1<length and LookIn(types,index,1)!=PORT):  # if there is no port after our device we should create a port (with number = 1 and way= not lastWay) and a link.
02177                                         # creating the port
02178                                         lastWay = 3-lastWay
02179                                         tmp_port = Port('','1','',str(lastWay),cell)  # Port Nr = 1;   port way = Opposite of the last Port Way. (use of the function x -> 3-x) 
02180                                         tmp_port = __addTo(tmp_port, port_list)
02181                                         # ceating the link
02182                                         if index-1>0 and lastPort:
02183                                             if LookIn(types,index,-1) == DEVICE: # if there is a different device before we  create a link
02184                                                 tmp_link = __CreateLink(lastPort,tmp_port)
02185                                                 tmp_link = __addTo(tmp_link,link_list)
02186                                             elif LookIn(types,index,-1)== PORT:
02187                                                 pass # TO DO 
02188                                             elif LookIn(types,index,-1)== DEVPORT:
02189                                                 pass # TO DO    
02190                                 
02191                         elif types[index]==DEVPORT: # DEVPORT =   device_name[in/out][ _ ][integer]
02192                                 # 1 - extract data from the current column
02193                                 portWay = -1
02194                                 try:
02195                                         portNr = int(cell[-1:]) # if the last caractere is a number so we have to continue to find how many caracter is the port number made of.
02196                                         i = 2
02197                                         while(i<len(cell)):
02198                                                 try:
02199                                                         portNr = int(cell[-i:])
02200                                                         i += 1
02201                                                 except:
02202                                                         i -= 1
02203                                                         break;
02204                                 except:
02205                                         portNr = 1  # default : if no port number is indiquited
02206                                         if cell[-2:]=="in":
02207                                                 portWay = 1
02208                                                 cell = cell[:-2]
02209                                         elif cell[-3:] == "out":
02210                                                 portWay = 2
02211                                                 cell = cell[:-3]
02212                                         else:
02213                                                 print "error : this is not a DEVICE PORT"
02214                                                 return
02215                                 
02216                                 if portWay == -1: # in the case have found a valid Port Number
02217                                         cell = cell[:(len(cell)-i)]
02218                                         if cell[-1:] in ['-','_']:
02219                                                 cell = cell[:-1] # we delete the underscore.
02220                                         if cell[-2:]=="in":
02221                                                 portWay = 1
02222                                                 cell = cell[:-2]
02223                                         elif cell[-3:] == "out":
02224                                                 portWay = 2
02225                                                 cell = cell[:-3]
02226                                         else:
02227                                                 print "Warinig: No port Way found for a DEVPORT"
02228                                                 portWay = 3 - lastWay
02229                                 # 2 - Now we have the devicename (cell), the port number (portNr) and the port Way (potWay).
02230                                 lastWay = portWay
02231                                 tmp_device = __addTo(Device('',cell),device_list) # adding the port to the list if not already done
02232                                 # update the ports number for our device
02233                                 if portWay == 1:        tmp_device.SetPortsIn(max(tmp_device.GetPortsIn(),portNr))
02234                                 else:   tmp_device.SetPortsOut(max(tmp_device.GetPortsOut(),portNr))
02235                                 
02236                                 # Create Port
02237                                 tmp_port = __addTo(Port('',portNr,"",portWay,cell), port_list)
02238                                 
02239                                 #Create The link:
02240                                 if index-1 >= 0 and lastPort:
02241                                    if LookIn(types,index,-1)== DEVICE: #types[index-1]==DEVICE:
02242                                         tmp_link = __CreateLink(lastPort,tmp_port)
02243                                         tmp_link = __addTo(tmp_link,link_list)
02244                                    if LookIn(types,index,-1)==DEVPORT: #types[index-1]==DEVPORT:
02245                                         tmp_link = __CreateLink(lastPort,tmp_port)
02246                                         tmp_link = __addTo(tmp_link,link_list)
02247                                    if LookIn(types,index,-1)== PORT:
02248                                         tmp_link = __CreateLink(lastPort,tmp_port)
02249                                         tmp_link = __addTo(tmp_link,link_list)
02250                                    if LookIn(types,index,-1)== LINK:
02251                                         tmp_link = __CreateLink(lastPort,tmp_port)
02252                                         tmp_link.SetLinkInfo(row[index-1])
02253                                         tmp_link = __addTo(tmp_link,link_list)
02254                                 
02255                         elif types[index]==PORT: #here we should create the Port then the Link if possible
02256                                 if LookIn(types,index,-1)!=DEVICE:  #types[index-1]!=DEVICE:
02257                                         print "error: No device correspond to a Port"
02258                                         return
02259                                 lastWay = 3 - lastWay
02260                                 tmp_port = Port('',cell,"",lastWay,row[index-1])
02261                                 tmp_port = __addTo(tmp_port, port_list)
02262                                 
02263                                 # Create the link
02264                                 if index-2>=0 and lastPort:
02265                                         if LookIn(types,index,-2)==LINK:
02266                                                 tmp_link = __CreateLink(lastPort,tmp_port)
02267                                                 tmp_link.SetLinkInfo(row[index-2])
02268                                                 tmp_link = __addTo(tmp_link,link_list)
02269                                         elif LookIn(types,index,-2)!=None:
02270                                                 tmp_link = __CreateLink(lastPort,tmp_port)
02271                                                 tmp_link = __addTo(tmp_link,link_list)                                  
02272                         elif types[index]==LINK:
02273                                 pass
02274 
02275                         if tmp_port:
02276                                 lastPort = tmp_port
02277                         index += 1
02278                 
02279         # except csv.Error, e:
02280             # sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
02281         finally:
02282                 print "DEVICEs successfuly imported : ",len(device_list)
02283                 print "PORT successfuly imported : ",len(port_list)
02284                 print "LINK successfuly imported : ",len(link_list)
02285                 for item in device_list+port_list+link_list:
02286                         item.Create()
02287 
02288                 print "items added to the Dirty List"
02289                 pdb.set_trace()
02290                 
02291                 DirtyItems = QListViewItem(self.GetSelectWindow().treeroot,"Imported Items")
02292                 for device in device_list:
02293                         elt = QListViewItem(DirtyItems,device.GetName(),str(TN_DEVICE) + "|" + "VELO")
02294 
02295     ##
02296     #  Generates a file with the function calls needed to ConfDBLibrary for all the changes made by the user since
02297     #   last commit to  ConfDB. If the user has commited changes to the ConfDB and the user calls this function, nothing
02298     #   will be generated because there are no objects to generate from, therefore: this function will always _have to_ be
02299     #   called _before_ the user store changes in the ConfDB.
02300     # 
02301     #   !return - False if unsuccessful
02302     #   
02303     def GenerateSQL(self,event=None):
02304 
02305         dirtylistcopy = self.CleanUpDirtyObjects(False) # we clean and compress the dirty objects list
02306 
02307         # Initializing progress bar and busy cursor
02308         ##self.ProgressData(len(self.__dirtyobjects),False,0)
02309         self.setCursor(QCursor(Qt.WaitCursor))
02310         self.ShowError("Please wait while preprocessing and validating objects before save.",ERR_WAIT,False)
02311 
02312         dirtylistcopy = self.FixDataObjectOrder(dirtylistcopy)
02313 
02314         ##self.ProgressData(0,True,0)
02315         self.ShowError("Preprocessing and validating finished successfully. Please wait while generating ConfDBLibrary functions file." ,ERR_WAIT, False)
02316 
02317         firstlist = [] #add Device, DeviceType,Link and LinkType *and Port* after first time use, + GetSaveStatus()
02318         backup_objects = []
02319         first = False
02320         many = True
02321         last = False #last item of the given type and function (insert, update, delete)
02322         i = 0
02323         prev_item = -1
02324         somefailed = False
02325         self.ResetRecoverFile(filename="recover_tmp.dat") #reset "backup" file
02326         objects_not_stored = []
02327         
02328         ##self.ProgressData(len(dirtylistcopy),False,0)
02329         self.ShowError("Please wait while generating ConfDBLibrary functions code, progress is shown in the progressbar.",ERR_WAIT,False)
02330 
02331 
02332         for ren in self.__renameobjects:
02333                 dirtylistcopy.insert(0,ren)
02334 
02335         if dirtylistcopy == []: #nothing to store
02336                 self.ShowError("There are no objects to generate ConfDBLibrary functions of.",ERR_ERROR)
02337                 self.setCursor(QCursor(Qt.ArrowCursor))
02338                 return False
02339 
02340         try:
02341                 directory = ""
02342                 while True:
02343                         savedlg = QFileDialog.getSaveFileName(directory,\
02344                         "Python file (*.py)",\
02345                         self,\
02346                         "Save ConfDBLibrary functions file as...",\
02347                         "Save" );
02348                         #savedlg = wxFileDialog(self,"Save ConfDBLibrary functions file as...",directory,"","*.py",wxSAVE)
02349                         savedlg = str(savedlg)
02350                         if savedlg=='':  #clicked cancel
02351                                 self.ShowError("Mass Insert : No file selected", ERR_ERROR,False)
02352                                 self.setCursor(QCursor(Qt.ArrowCursor))
02353                                 return False
02354                         if savedlg[-3::]!='.py':
02355                                 savedlg = savedlg + ".py"
02356                         filename =  savedlg[len(savedlg)-savedlg[::-1].index("/"):]
02357                         directory = savedlg.strip(filename)
02358                         if OS_VERSION == WINDOWS:
02359                                 if directory.split(":")[1] == "": #we have chosen the root of a drive
02360                                         directory += os.sep
02361                         filepath = os.path.join(directory,filename)
02362                         path_already_exists = os.path.exists(filepath)
02363                         if path_already_exists:
02364                                 ans = QMessageBox.question(self,"Overwrite File?","The file already exists, do you want to replace the file?","Yes","No","",0,1)
02365 
02366                                 if ans == 1: # NO : If user changed his/her mind, or didnt intend to replace
02367                                         continue #new while loop
02368                                 else:
02369                                         break #ok, replace file
02370                         break #out of loop, to write to file
02371 
02372                 file = open(filepath,"w")
02373 
02374                 startcode = ""
02375                 startcode +=   "#################################################\n\
02376 #            AUTOGENERATED PYTHON CODE          #\n\
02377 #                   BY CDBVIS                   #\n\
02378 #################################################\n\n"
02379                 startcode += "Edit the following : \ndatabasename=\"Your_DB_Name\"\nusername=\"Username\"\npassword=\"Password\"\n\n"
02380 
02381                 if OS_VERSION == LINUX:
02382                         startcode += "from libconfDBpython import *\n"
02383                 elif OS_VERSION == WINDOWS:
02384                         startcode += "from confDBpython import *\n"
02385                 else:
02386                         startcode += "from libconfDBpython import *\n" #linux distro..or linux "compatible" with *.so's
02387 
02388                 startcode += "import cx_Oracle\n\n"     
02389                 startcode += 'cfDB = CONFDB(databasename,username,password)\n' # here you can optionally set the username, password and database name to the ConfDB, so that the sqlfunctions file is always ready to be commited to the ConfDB.
02390                 startcode += "cfDB.DBConnexion()\n\n"
02391                 startcode += "oracle = cx_Oracle.connect(username+'/'+password+'@'+databasename)\ncfDB2 = oracle.cursor()\n\n"
02392 
02393                 file.write(startcode)
02394         
02395                 old_and_new_linknames = {} # old name : new object; for update of links in visual window
02396                 while i < len(dirtylistcopy):
02397                         item = dirtylistcopy[i] #index 0
02398 
02399                         many = True
02400                         if (item.__class__ in [Port,Device]) and item.GetSaveStatus() == MODIFY:
02401                                 my_item = str(item.__class__) + ":" + str(item.GetSaveStatus()) + ":" + str(item.GetModifyStatus())
02402                         else:
02403                                 my_item = str(item.__class__) + ":" + str(item.GetSaveStatus())
02404 
02405                         #pop it, do not fetch it since we have it in the item variable
02406                         if (i+1) == len(dirtylistcopy): #do not have a next one; this is the last of its type/kind
02407                                 last = True
02408                         else:
02409                                 if (dirtylistcopy[i+1].__class__ in [Port,Device]) and dirtylistcopy[i+1].GetSaveStatus() == MODIFY:
02410                                         next_item = str(dirtylistcopy[i+1].__class__) + ":" + str(dirtylistcopy[i+1].GetSaveStatus()) + ":" + str(dirtylistcopy[i+1].GetModifyStatus())
02411                                         
02412                                 else:
02413                                         next_item = str(dirtylistcopy[i+1].__class__) + ":" + str(dirtylistcopy[i+1].GetSaveStatus())
02414                                 if my_item == next_item:
02415                                         last = False
02416                                 else:
02417                                         last = True
02418 
02419                         # We use cache to temporary store objects of same kind (same save status (and modify status)), and
02420                         # store them in the ConfDB on the last object of its kind. If the next object in the list is another
02421                         # kind, we store them to the ConfDB, and next iteration we will have to initialize a new cache for the
02422                         # next kind.
02423                         if prev_item != my_item:
02424                                 firstlist = []
02425                                 if last: #only one of this kind in this sequence. First and last, use single insert/update/delete.
02426                                         many = False
02427                         
02428                         # first object of its kind?
02429                         if firstlist == []:
02430                                 first = True
02431                         else:
02432                                 first = False
02433                         firstlist.append(item.GetName())
02434 
02435                         # Debug information
02436                         print "Item: " + str(item.GetName()) + " First: " + str(first) + " many: " + str(many) + " last: " + str(last) + " savestatus: " + str(item.GetSaveStatus())
02437                         my_savestatus = item.GetSaveStatus()
02438 
02439                         # Call the save method for the object to be saved/applied to ConfDB
02440                         function_to_file = item.PrintSaveFunction(first,many,last)
02441                         if not last:
02442                                 appendix = "\n" #collection of same type, only 1 line break
02443                         else:
02444                                 appendix = "\n\n" #next type, 2 line breaks
02445 
02446                         #Save to file
02447                         file.write(function_to_file + appendix)
02448 
02449                         prev_item = my_item
02450                         dirtylistcopy.pop(i)
02451                         ##self.ProgressData(0,False,1) # Update progress bar, one step
02452 
02453                 ##self.ProgressData(0,True,0) # Stop progress bar, and reset it.
02454                 file.write("\ncfDB.DBDeconnexion()\noracle.commit()\n")
02455                 file.close()
02456 
02457                 self.ShowError("ConfDBLibrary functions file successfully generated!",ERR_SUCCESS)
02458                 self.setCursor(QCursor(Qt.ArrowCursor))
02459                 return True
02460                 
02461         except IOError,err:
02462                 self.ShowError("An unexpected error occured while writing to " + str(filepath) + ".",ERR_CRITICAL)
02463                 self.setCursor(QCursor(Qt.ArrowCursor))
02464                 return False
02465 
02466     ##
02467     #  This function is a helper function to OnSave(...) and GenerateSQL(...) to sort the data objects in
02468     #   the dirty list (or a copy) after each other in a correct order based on data object type, save status 
02469     #   (and modify status). Returns the new and ordered list.
02470     # 
02471     #   Parameters:
02472     #   @objectlist - if the dirty objects list is not directly used, we use the list that is sent in this parameter. If
02473     #   no list is sent (None object), then we use the dirty objects list.
02474     # 
02475     #   !return - an save-ordered list of all the objects in the dirty objects list.
02476     #   
02477     def FixDataObjectOrder(self,objectlist=None):
02478         
02479         if objectlist == None: # If we do not set another list, use the default dirty objects list (only used in OnSave)
02480                 objectlist = self.__dirtyobjects
02481             
02482         devtypes_sort = {}
02483         linktypes_sort = {}
02484         devs_sort = {}
02485         links_sort = {}
02486         ports_sort = {}
02487         #now we want to go through the dirtylist and set several objects of the same type together, since it is
02488         #chronological we can iterate from the start and add more and more, we create an objectlist of each 
02489         #objecttype, before we finally set them together in the dirtyobjectlist, in the correct order: 
02490         #devicetype, linktype, device, link, port, so that the consistency in the ConfDB is not violated, and
02491         #neither foreign keys and other constraints.
02492         
02493         for item in objectlist: #!
02494                 if item.__class__ == Device:
02495                         if item.GetSaveStatus() == MODIFY:
02496                                 if item.GetName() in devs_sort.keys(): #looking for prev create objects
02497                                         prevstatus = devs_sort[item.GetName()].GetSaveStatus()
02498                                         devs_sort[item.GetName()].SetDict(item.GetObjectInfo(True))
02499                                         devs_sort[item.GetName()].SetSaveStatus(prevstatus)
02500                                 else:
02501                                         newname = "#1:"+str(item.GetModifyStatus())+":"+item.GetName()
02502                                         if newname in devs_sort.keys():
02503                                                 prevstatus = devs_sort[newname].GetSaveStatus()
02504                                                 devs_sort[newname].SetDict(item.GetObjectInfo(True))
02505                                                 devs_sort[newname].SetSaveStatus(prevstatus) #always modify
02506                                         else:
02507                                                 devs_sort[newname] = item
02508                         elif item.GetSaveStatus() == CREATE:
02509                                 devs_sort[item.GetName()] = item
02510                         elif item.GetSaveStatus() == DELETE:
02511                                 devs_sort["#0:"+item.GetName()] = item
02512                 if item.__class__ == Spare_Device:
02513                         if item.GetSaveStatus() == CREATE:
02514                                 devs_sort[item.GetName()] = item
02515                         elif item.GetSaveStatus() == DELETE:
02516                                 devs_sort["#0:"+item.GetName()] = item
02517                 if item.__class__ == Spare_Port:
02518                         if item.GetSaveStatus() == CREATE:
02519                                 devs_sort[item.GetName()] = item
02520                         elif item.GetSaveStatus() == DELETE:
02521                                 devs_sort["#0:"+item.GetName()] = item
02522                 elif item.__class__ == Link:
02523                         if item.GetSaveStatus() == MODIFY:
02524                                 newname = "#1:"+item.GetName()
02525                                 if item.GetName() in links_sort.keys():
02526                                         prevstatus = links_sort[item.GetName()].GetSaveStatus()
02527                                         links_sort[item.GetName()].SetDict(item.GetObjectInfo(True))
02528                                         links_sort[item.GetName()].SetSaveStatus(prevstatus)
02529                                 else:
02530                                         if newname in links_sort.keys():
02531                                                 prevstatus = links_sort[newname].GetSaveStatus()
02532                                                 links_sort[newname].SetDict(item.GetObjectInfo(True))
02533                                                 links_sort[newname].SetSaveStatus(prevstatus)
02534                                         else:
02535                                                 links_sort[newname] = item
02536                         elif item.GetSaveStatus() == CREATE:
02537                                 links_sort[item.GetName()] = item
02538                         elif item.GetSaveStatus() == DELETE:
02539                                 links_sort["#0:"+item.GetName()] = item
02540 
02541                 elif item.__class__ == DeviceType:
02542                         if item.GetSaveStatus() == MODIFY:
02543                                 newname = "#1:"+item.GetName()
02544                                 if item.GetName() in devtypes_sort.keys():
02545                                         prevstatus = devtypes_sort[item.GetName()].GetSaveStatus()
02546                                         devtypes_sort[item.GetName()].SetDict(item.GetObjectInfo(True))
02547                                         devtypes_sort[item.GetName()].SetSaveStatus(prevstatus)
02548                                 else:
02549                                         if newname in devtypes_sort.keys():
02550                                                 prevstatus = devtypes_sort[newname].GetSaveStatus()
02551                                                 devtypes_sort[newname].SetDict(item.GetObjectInfo(True))
02552                                                 devtypes_sort[newname].SetSaveStatus(prevstatus)
02553                                         else:
02554                                                 devtypes_sort[newname] = item
02555                         elif item.GetSaveStatus() == CREATE:
02556                                 devtypes_sort[item.GetName()] = item
02557                         elif item.GetSaveStatus() == DELETE:
02558                                 devtypes_sort["#0:"+item.GetName()] = item
02559                 elif item.__class__ == LinkType:
02560                         if item.GetSaveStatus() == MODIFY:
02561                                 newname = "#1:"+item.GetName()
02562                                 if item.GetName() in linktypes_sort.keys():
02563                                         prevstatus = linktypes_sort[item.GetName()].GetSaveStatus()
02564                                         linktypes_sort[item.GetName()].SetDict(item.GetObjectInfo(True))
02565                                         linktypes_sort[item.GetName()].SetSaveStatus(prevstatus)
02566                                 else:
02567                                         if newname in linktypes_sort.keys():
02568                                                 prevstatus = linktypes_sort[newname].GetSaveStatus()
02569                                                 linktypes_sort[newname].SetDict(item.GetObjectInfo(True))
02570                                                 linktypes_sort[newname].SetSaveStatus(prevstatus)
02571                                         else:
02572                                                 linktypes_sort[newname] = item
02573                         elif item.GetSaveStatus() == CREATE:
02574                                 linktypes_sort[item.GetName()] = item
02575                         elif item.GetSaveStatus() == DELETE:
02576                                 linktypes_sort["#0:"+item.GetName()] = item
02577                 elif item.__class__ == Port:
02578                         if item.GetName() in ports_sort.keys(): #ok, we have a create object from before, can add any modify object here
02579                                 prevstatus = ports_sort[item.GetName()].GetSaveStatus()
02580                                 ports_sort[item.GetName()].SetDict(item.GetObjectInfo(True))
02581                                 ports_sort[item.GetName()].SetSaveStatus(prevstatus)
02582                         else: #ok, no create objects, but perhaps an equal modify object?
02583                                 if item.GetSaveStatus() == MODIFY:
02584                                         newname = "#1:"+str(item.GetModifyStatus())+":"+item.GetName()
02585                                         if newname in ports_sort.keys():
02586                                                 prevstatus = ports_sort[newname].GetSaveStatus()
02587                                                 ports_sort[newname].SetDict(item.GetObjectInfo(True))
02588                                                 ports_sort[newname].SetSaveStatus(prevstatus) #not necessary
02589                                         else:
02590                                                 ports_sort[newname] = item
02591                                 elif item.GetSaveStatus() == CREATE:
02592                                         ports_sort[item.GetName()] = item
02593                                 elif item.GetSaveStatus() == DELETE:
02594                                         ports_sort["#0:"+item.GetName()] = item
02595                 ##self.ProgressData(0,False,1)
02596 
02597 
02598         #Now we sort the data objects by the save status, first delete, then modify and create last.
02599         #For an object there is only 1 action that will be stored in the ConfDB, because we put together
02600         #several create and modify, we cancel out create,modify,delete etc.
02601         mysorteddevtypes = devtypes_sort.keys()
02602         mysorteddevtypes.sort()
02603         mysortedlinktypes = linktypes_sort.keys()
02604         mysortedlinktypes.sort()
02605         mysorteddevs = devs_sort.keys()
02606         mysorteddevs.sort()
02607         mysortedlinks = links_sort.keys()
02608         mysortedlinks.sort()
02609         mysortedports = ports_sort.keys()
02610         mysortedports.sort()
02611 
02612         #self.__dirtyobjects = []
02613         objectlist = []
02614         for itm in mysorteddevtypes:
02615                 objectlist.append(devtypes_sort[itm]) #!
02616         for itm in mysortedlinktypes:
02617                 objectlist.append(linktypes_sort[itm]) #!
02618         for itm in mysorteddevs:
02619                 objectlist.append(devs_sort[itm]) #!
02620         for itm in mysortedlinks:
02621                 objectlist.append(links_sort[itm]) #!
02622         for itm in mysortedports:
02623                 objectlist.append(ports_sort[itm]) #!
02624 
02625         return objectlist
02626 
02627     ##
02628     #  Save/Apply objects in dirty objects list to the ConfDB, remove one and one after successful save.
02629     #   After every object is saved, reset dirtylist, undolist and redolist.
02630     # 
02631     #   More details on each step in this method is explained below in the code.
02632     #   
02633     def OnSave(self,event=None,prompt=True):
02634         
02635         if prompt:
02636                 ans = QMessageBox.question(self,"Commit Changes?","Are you sure that you want to store the changes made in CdbVis to the ConfDB?","Yes","No","",0,1)
02637                 if ans == 1: # NO : If user changed his/her mind, or didnt intend to
02638                         return False
02639 
02640         # Initializing progress bar and busy cursor
02641         ##self.ProgressData(len(self.__dirtyobjects),False,0)
02642         ##wxBeginBusyCursor()
02643         self.ShowError("Please wait while preprocessing and validating objects before save.",ERR_WAIT, False)
02644 
02645         # Check if there is something to save, and to clean up objects cancelling out each other.
02646         self.CleanUpDirtyObjects(True)
02647 
02648         self.__dirtyobjects = self.FixDataObjectOrder() #Fix the order of the data objects
02649         
02650         ##self.ProgressData(0,True,0)
02651         self.ShowError("Preprocessing and validating finished successfully. Please wait while saving objects in the database." ,ERR_SUCCESS, False)
02652         ##wxEndBusyCursor()
02653 
02654         # We will need som info to handle the commit/cache functions. We will need to count nr of inserts, 
02655         #updates and deletes for each objecttype so that we set commit on the last one. If commit fails, 
02656         #none of the objects is saved, therefore they should be put in a backuplist just in case...
02657         firstlist = [] #add Device, DeviceType,Link and LinkType *and Port* after first time use, + GetSaveStatus()
02658         backup_objects = []
02659         first = False
02660         many = True
02661         last = False #last item of the given type and function (insert, update, delete)
02662         i = 0
02663         prev_item = -1
02664         somefailed = False
02665         self.ResetRecoverFile(filename="recover_tmp.dat") #reset "backup" file
02666         objects_not_stored = []
02667         
02668         ##self.ProgressData(len(self.__dirtyobjects)+len(self.__renameobjects),False,0)
02669         ##wxBeginBusyCursor()
02670         self.ShowError("Please wait while saving objects in the database",ERR_WAIT, False)
02671 
02672         for ren in self.__renameobjects:
02673                 self.__dirtyobjects.insert(0,ren)
02674 
02675         old_and_new_linknames = {} # old name : new object; for update of links in visual window
02676         while i < len(self.__dirtyobjects):
02677                 item = self.__dirtyobjects[i] #index 0
02678 
02679                 many = True
02680                 if (item.__class__ in [Port,Device]) and item.GetSaveStatus() == MODIFY:
02681                         my_item = str(item.__class__) + ":" + str(item.GetSaveStatus()) + ":" + str(item.GetModifyStatus())
02682                 else:
02683                         my_item = str(item.__class__) + ":" + str(item.GetSaveStatus())
02684 
02685                 #pop it, do not fetch it since we have it in the item variable
02686                 if (i+1) == len(self.__dirtyobjects): #do not have a next one; this is the last of its type/kind
02687                         last = True
02688                 else:
02689                         if (self.__dirtyobjects[i+1].__class__ in [Port,Device]) and self.__dirtyobjects[i+1].GetSaveStatus() == MODIFY:
02690                                 next_item = str(self.__dirtyobjects[i+1].__class__) + ":" + str(self.__dirtyobjects[i+1].GetSaveStatus()) + ":" + str(self.__dirtyobjects[i+1].GetModifyStatus())
02691                                 
02692                         else:
02693                                 next_item = str(self.__dirtyobjects[i+1].__class__) + ":" + str(self.__dirtyobjects[i+1].GetSaveStatus())
02694                         if my_item == next_item:
02695                                 last = False
02696                         else:
02697                                 last = True
02698 
02699                 # We use cache to temporary store objects of same kind (same save status (and modify status)), and
02700                 # store them in the ConfDB on the last object of its kind. If the next object in the list is another
02701                 # kind, we store them to the ConfDB, and next iteration we will have to initialize a new cache for the
02702                 # next kind.
02703                 if prev_item != my_item:
02704                         firstlist = []
02705                         if last: #only one of this kind in this sequence. First and last, use single insert/update/delete.
02706                                 many = False
02707                 
02708                 # first object of its kind?
02709                 if firstlist == []:
02710                         first = True
02711                 else:
02712                         first = False
02713                 firstlist.append(item.GetName())
02714 
02715                 # Debug information
02716                 print "Item: " + str(item.GetName()) + " First: " + str(first) + " many: " + str(many) + " last: " + str(last) + " savestatus: " + str(item.GetSaveStatus())
02717                 my_savestatus = item.GetSaveStatus()
02718 
02719                 # Call the save method for the object to be saved/applied to ConfDB
02720                 success = item.Save(first,many,last)
02721 
02722                 if success == False: # Save failed
02723                         somefailed = True
02724                         for obj in backup_objects: # Backup all objects of same kind, that was in cache and not commited yet
02725                                 objects_not_stored.append(obj)
02726                                 self.RecoverObjectToFile(obj,DESIGN,filename="recover_tmp.dat",write="a") # temp recover file
02727                                 
02728                         self.RecoverObjectToFile(item,DESIGN,filename="recover_tmp.dat",write="a") # also the failing object
02729                         objects_not_stored.append(item)
02730 
02731                         self.ShowError("An unexpected error occured while trying to save the " + str(item.__class__) + ": " + str(item.GetName()) + ": " + str(item.GetErrorMessage()),ERR_ERROR)
02732                         # We do not return False, we will try to finish.
02733                 elif success == True and last == True: #Success and commited
02734                         backup_objects.append(item) # we also add the current item to the list for update
02735                         if item.__class__ == Link and my_savestatus != DELETE:
02736                                 # Update Linkname to the LinkID from the temporary link name we set on it, of course not when
02737                                 # deleted.
02738                                 for itm in backup_objects:
02739                                         tmp_oldname = itm.GetName()
02740                                         print "Old name: " + str(tmp_oldname)
02741                                         success = itm.UpdateLinkID()
02742                                         print "New name: " + str(itm.GetName())
02743                                         if not success:
02744                                                 self.ShowError("An unexpected error occured while converting temporary link names to linkids in the database: " + str(itm.GetErrorMessage()),ERR_ERROR)
02745                                         else: #if success
02746                                                 old_and_new_linknames[tmp_oldname] = itm
02747 
02748                                 # Update all names in visual window for links; if they are there
02749                                 for old_linkname in old_and_new_linknames:
02750                                                 vis_linkobj = self.GetVisWindow().FindByName(old_linkname)
02751                                                 if vis_linkobj != None:
02752                                                         if old_linkname != old_and_new_linknames[old_linkname].GetName(): # if changed
02753                                                                 vis_linkobj.SetText(old_and_new_linknames[old_linkname].GetName())#new
02754                                                         vis_linkobj.SetObjectRef(old_and_new_linknames[old_linkname])
02755                                                         
02756                                 old_and_new_linknames = {} # old name : new object; for update of links in visual window; RESET.
02757                                                 
02758                         elif item.__class__ != Link and my_savestatus != DELETE: # update with ConfDB info
02759                                 for itm in backup_objects:
02760                                         itm.Update(True) #retrieve data from database.
02761                                         # Not update objects in visual window; should be update already
02762                         backup_objects = [] #reset list
02763 
02764                 elif success == True and last != True: # not commit yet, backup objects temp in a list
02765                         backup_objects.append(item)
02766 
02767                 prev_item = my_item
02768                 self.__dirtyobjects.pop(i)
02769                 ##self.ProgressData(0,False,1) # Update progress bar, one step
02770 
02771         ##self.ProgressData(0,True,0) # Stop progress bar, and reset it.
02772 
02773         #Ok, reset files
02774         self.ResetRecoverFile() #Reset file yes, and make ready to put in those objects that could not be saved.
02775         self.ResetDirtyObjects() #includes undo list and redo list
02776 
02777         if somefailed: #Recovering failed objects.
02778                 self.__dirtyobjects = objects_not_stored
02779                 for obj in self.__dirtyobjects:
02780                         self.RecoverObjectToFile(obj,DESIGN)
02781                 self.ResetRecoverFile(filename="recover_tmp.dat") #reset backup recover file, but this file must also be taken into consideration after if the program fails in the middle of saving, or right before fixing the proper recover.dat...
02782                 
02783                 self.ShowError("Not all objects stored in ConfDB. Double-click on the message icon to see the logged errors.",ERR_ERROR)
02784         else:
02785                 self.ShowError("All objects successfully stored in database!",ERR_SUCCESS,True)
02786                 self.SetCreationMode(False)  # Return to the creation Mode
02787         
02788 
02789     ##
02790     #  Delete one or several objects in the visual window. This method only calls some big
02791     #   methods in the visual window module that actually is responsible for errors etc. that
02792     #   may happen.
02793     #   
02794     def OnDelete(self,event):
02795         self.GetVisWindow().DoDelete(None,True,refresh=False)
02796         self.GetVisWindow().Refresh()
02797 
02798     ##
02799     #  Duplicate one or several objects in the visual window. This method only calls some big
02800     #   methods in the visual window moudle that actually is responsible for errors etc. that may
02801     #   happen.
02802     #   
02803     def OnDuplicate(self,event):
02804         self.GetVisWindow().DoDuplicateHelper(event,True)
02805 
02806     ##
02807     #  Clone one or several objects in the visual window. This method only calls some big
02808     #   methods in the visual window moudle that actually is responsible for errors etc. that may
02809     #   happen.
02810     #   
02811     def OnClone(self,event):
02812         self.GetVisWindow().DoCloneHelper(event,True)
02813 
02814     ##
02815     #  Initialize, Update or Reset the progress bar in the status bar for an action.
02816     # 
02817     #   @range - set when progress bar is initialized, how many steps the progress bar should show
02818     #   @finished - if this is set to True, it is the reset of the progress bar, if False, ignore
02819     #   @step - how big step for the last update; usually 1, like once every iteration.
02820     #   
02821     def ProgressData(self,range=0,finished=False,step=0):
02822         
02823         if range != 0:
02824                 self.progressbar.SetRange(range)
02825                 self.pbarvalue = 0
02826                 wxYield() # Needed to make the CPU give some time to refresh GUI.
02827         elif finished == True:
02828                 self.pbarvalue = 0
02829                 wxYield()
02830         else: #update
02831                 self.pbarvalue += step
02832                 wxYield()
02833 
02834     ##
02835     #  We will trigger a timer event quite frequently so that we can update our 
02836     #   progressbar value and graphics (because wxYield() doesnt give any CPU time
02837     #   in Windows.
02838     #   
02839     def OnTimer(self,event):
02840 
02841         self.progressbar.SetValue(self.pbarvalue)
02842 
02843     ##
02844     #  Called when wxYield() is called, short idle time for the CPU to update the GUI;
02845     #   here we update the progress bar state.
02846     #   
02847     def IdleHandler(self,event):
02848         
02849         self.progressbar.SetValue(self.pbarvalue)
02850 
02851     ##
02852     #  ??? Obsolete ???
02853     #   
02854     def NeedToClearWindow(self):
02855         return self.__clearfordynamic
02856 
02857     ##
02858     #  The new name is ViewNHopsOfDevices. The user clicks on a device node in the tree view in this view mode,
02859     #   a input box will pop up where the user has to type in how many hops out from this device he/she wants to see.
02860     #   Then the private draw function of this function will draw the devices recursively.
02861     # 
02862     #   @refresh - whether we should manually trigger a paint event (if the program does not do it itself)
02863     #   
02864     def ViewSubSystem(self,refresh=True):
02865 
02866         #First we get the currently active device, if any, if none is active, we quite and warns the user
02867         active_device = self.GetActiveDevice()
02868         if active_device in [None,""]:
02869                 self.ShowError("You have not chosen any device to start from. A device has to be selected!", ERR_INFORMATION,False)
02870                 return False
02871 
02872         #Then we ask the user about how many levels/links/hops he/she wants to view
02873         nr_of_hops = wxGetNumberFromUser("How many hops/links do you want to view outside this device?","Nr. of hops","Nr. of hops",1,0,1000,self)
02874         if nr_of_hops == -1:
02875                 self.ShowError("Invalid number of hops.",ERR_ERROR)
02876                 return False
02877         teststr = str(nr_of_hops)
02878         if teststr.find(".",0,len(teststr)) != -1: #float
02879                 self.ShowError("Float number is not supported.",ERR_ERROR)
02880                 return False
02881         
02882         #Inform user that it is processing
02883         # (We cannot indicate this with a progress bar becaus then we would have to know how many devices there are to
02884         # process, we could find out but then it would take much longer time to process...as we had to calculate this
02885         # before we could really start)
02886         wxBeginBusyCursor()
02887         self.ShowError("Please wait while processing content",ERR_INFORMATION, False)
02888 
02889 
02890         # We create the two lists we will need, a list of devices, to be filled up as we iterate
02891         # and a list of links for each device we process, as well as a list of already added devices, so that we dont
02892         # add them again...
02893         list_of_links = []
02894         list_of_added_devices = []
02895 
02896         # And clear the visual window
02897         self.GetVisWindow().DoDeleteAll(refresh=True)
02898 
02899         # internal recursive function for finding all devices within maxlevels for the selected active device
02900         ##
02901         #  This private function finds and draws a device and its neighbors in the visual window recursively
02902         #                   until there are no more links to neighbors or the maximum hop distance given by the user has been
02903         #                   reached.
02904         # 
02905         #                   @list_of_links - a list of link objects from the previous device added, to expand its neighbors
02906         #                   if we have not reached the maximum level
02907         #                   @level - the level or hop distance we are at, we start at hop 2 since the first device and its 
02908         #                   neighbors are added before this function is called
02909         #                   @maxlevel - the maximum level/hop distance given by the user
02910         #                   @inlinks - whether the list_of_links list is of links going in or out of the previous device added
02911         #                   @list_of_added_devices - list of devices that have been drawn and possibly expanded in the visual window
02912         #                   @list_of_expanded_devices - list of devices that have been expanded in the visual window
02913         #                   @maxhop - the highest level so far we have reached in this recursion...to controll progress bar
02914         # 
02915         #                   !return @list_of_added_devices, @list_of_expanded_devices, @maxhop, to get the data for recursive search
02916         #                   on the other branch
02917         # 
02918         #                   TODO: add list_of_links, list_of_added_devices and list_of_expanded_devices to global list for less
02919         #                   memory consumption
02920         #               
02921         def findDevicesRec(list_of_links,level=2,maxlevel=0,inlinks=True,list_of_added_devices=[],list_of_expanded_devices=[],maxhop=1):
02922 
02923                 #break statement 1 -> if we've passed the max level of hops given
02924                 if (level > maxlevel):
02925                         return list_of_added_devices,list_of_expanded_devices,maxhop
02926 
02927                 #break statement 2 -> if there are no links to iterate through
02928                 if (list_of_links == []):
02929                         return list_of_added_devices,list_of_expanded_devices,maxhop
02930                 
02931                 #Just to show the progress to the user, so that he knows that it is processing
02932                 #One step for each new level hop we reach
02933                 if (level > maxhop):
02934                         self.ProgressData(0,False,1) #1 step
02935                         maxhop = level
02936 
02937                 new_links_in = []
02938                 new_links_out = []
02939                 for link in list_of_links:
02940                         if inlinks:
02941                                 tmp_devicename = link.GetNodeFrom()
02942                         else:
02943                                 tmp_devicename = link.GetNodeTo()
02944 
02945                         # if the next level is the last level, we only check if the device has already been added
02946                         # cause it will not have needed to have been expanded, because its to many hops away, at least
02947                         # on the current path
02948                         # If the next level is not the last level, we check whether it has been expanded or not
02949                         if ((level+1 > maxlevel and tmp_devicename not in list_of_added_devices) or \
02950                         (level+1 <= maxlevel and tmp_devicename not in list_of_expanded_devices)):
02951                                 tmp_device = Device(self.GetActiveSystem(),tmp_devicename,False)
02952                                 inL,outL = self.GetVisWindow().OnDeviceSelected(tmp_device,False,True,0,0,False)
02953 
02954                                 # Next level is not the last level, the device will be expanded, so we add links for it
02955                                 if level+1 <= maxlevel:
02956                                         list_of_expanded_devices.append(tmp_devicename)
02957                                         new_links_in.extend(inL)
02958                                         new_links_out.extend(outL)
02959 
02960                                 # always add the device to say that is has been added
02961                                 list_of_added_devices.append(tmp_devicename)
02962 
02963                 # Then we take the left branch (input links) recursively
02964                 list_of_added_devices,list_of_expanded_devices,maxhop = findDevicesRec(new_links_in,level+1,maxlevel,True,list_of_added_devices,list_of_expanded_devices,maxhop)
02965                 # and finally the right branch (output links) recursively
02966                 return findDevicesRec(new_links_out,level+1,maxlevel,False,list_of_added_devices,list_of_expanded_devices,maxhop)
02967         #And now we are ready to start on the real thing, the processing
02968         self.ProgressData(nr_of_hops*2,False,0)
02969         tmp_device = Device(self.GetActiveSystem(),active_device,False)
02970         maxhop = 1
02971         list_of_expanded_devices = []
02972         list_of_added_devices.append(active_device)
02973         list_of_expanded_devices.append(active_device)
02974         if nr_of_hops == 0: #only the device itself is drawn
02975                 self.GetVisWindow().AddNode(tmp_device,0,0) #hop 0
02976         else:
02977                 # add the node selected itself, and if available, its neighbors
02978                 inL,outL = self.GetVisWindow().OnDeviceSelected(tmp_device,False,True,0,0,False) #hop 0 (and 1)
02979                 self.ProgressData(0,False,1) #first step
02980                 # inL and outL now consists of links to and from this device, from and to devices it was connected to
02981                 # so that we can draw them the same way
02982                 if inL != []:
02983                         list_of_added_devices,list_of_expanded_devices,maxhop1 = findDevicesRec(inL,2,nr_of_hops,True,list_of_added_devices,list_of_expanded_devices,maxhop)
02984                 if outL != []:
02985                         list_of_added_devices,list_of_expanded_devices,maxhop = findDevicesRec(outL,2,nr_of_hops,False,list_of_added_devices,list_of_expanded_devices,maxhop)
02986 
02987         self.ProgressData(0,True,0) #finished,step
02988 
02989         self.GetVisWindow().DeselectAll(refresh=False)
02990 
02991         visobj = self.GetVisWindow().FindByName(active_device)
02992         if visobj != None:
02993                 self.GetVisWindow().Select(visobj,refresh=False)
02994                 self.GetVisWindow().CenterToObject(visobj)
02995         else:
02996                 self.GetVisWindow().Center() #so that the user see what that is drawn
02997 
02998         if refresh:
02999                 self.GetVisWindow().Refresh()
03000 
03001         self.ShowError("The chosen selection of devices was successfully created." ,ERR_INFORMATION,False)
03002         wxEndBusyCursor()
03003 
03004     ##
03005     #  Return handle on Configuration Database object; the DBSystem object/class
03006     #             If not connected return None.
03007     # 
03008     #       !return - the reference to the ConfDB object.
03009     #         
03010     def GetCdb(self):
03011         
03012         return self.__cdb
03013 
03014     ##
03015     #  Set the ConfDB object.
03016     # 
03017     #   @cdb - the ConfDB object reference.
03018     #   
03019     def SetCdb(self,cdb):
03020         
03021         self.__cdb = cdb
03022 
03023     ##
03024     #  Reset all active objects of all kinds.
03025     #   
03026     def ResetActiveObjects(self):
03027         
03028         self.__activedevicetype = None
03029         self.__activedevice = None
03030         self.__activeport = None
03031         self.__activelinktype = None
03032         self.__activelink = None
03033 
03034     ##
03035     #  Change or set the active subsystem, so that this will be affected in all windows: tree view and visual window.
03036     # 
03037     #   @system - the new active subsystem
03038     #   @source - in which window we changed the subsystem: "visual" or "select"
03039     #   
03040     def SetActiveSystem(self,system,source):
03041         
03042         if self.__activesystem != system:
03043                 self.__activesystem = system
03044 
03045                 visual = self.panel.GetVisWindow()
03046                 select = self.panel.GetSelectWindow()
03047 
03048                 if source == "visual":
03049                     select.SystemChanged()      
03050                 else: # Called from this window
03051                     # also update visual window somehow
03052                     pass
03053 
03054                 #WALPROB self.GetStatusBar().SetStatusText(str(self.__activesystem),3)
03055                 #WALPROB self.SetCursor(wxStockCursor(wxCURSOR_ARROW))
03056                 
03057     """ Set or Get active objects, or set or get available objects of all kinds defined in objectclasses.py. """
03058     def GetActiveSystem(self):
03059         return self.__activesystem
03060     def SetAvailableSystems(self,systems):
03061         self.__availablesystems = systems
03062     def GetAvailableSystems(self):
03063         return self.__availablesystems
03064     def GetActiveDeviceType(self):
03065         return self.__activedevicetype
03066     def SetActiveDeviceType(self,devtype):
03067         self.__activedevicetype = devtype
03068     def SetAvailableDeviceTypes(self,devtypes):
03069         self.__availabledevicetypes = devtypes
03070     def GetAvailableDeviceTypes(self):
03071         return self.__availabledevicetypes
03072     def AddAvailableDeviceType(self,devtype):
03073         self.__availabledevicetypes.append(devtype)
03074     def RemoveAvailableDeviceType(self,devtype):
03075         self.__availabledevicetypes.remove(devtype)
03076     def GetActiveDevice(self):
03077         return self.__activedevice
03078     def SetActiveDevice(self,device):
03079         self.__activedevice = device
03080     def SetAvailableDevices(self,devices):
03081         self.__availabledevices = devices
03082     def GetAvailableDevices(self):
03083         return self.__availabledevices
03084     def AddAvailableDevice(self,device):
03085         self.__availabledevices.append(device)
03086     def RemoveAvailableDevice(self,device):
03087         self.__availabledevices.remove(device)
03088     def GetActivePort(self):
03089         return self.__activeport
03090     def SetActivePort(self,port):
03091         self.__activeport = port
03092     def SetAvailablePorts(self,ports):
03093         self.__availableports = ports
03094     def GetAvailablePorts(self):
03095         return self.__availableports
03096     def AddAvailablePort(self,port):
03097         self.__availableports.append(port)
03098     def RemoveAvailablePort(self,port):
03099         self.__availableports.remove(port)
03100     def GetActiveLinkType(self):
03101         return self.__activelinktype
03102     def SetActiveLinkType(self,linktype):
03103         self.__activelinktype = linktype
03104     def SetAvailableLinkTypes(self,linktypes):
03105         self.__availablelinktypes = linktypes
03106     def GetAvailableLinkTypes(self):
03107         return self.__availablelinktypes
03108     def AddAvailableLinkType(self,linktype):
03109         self.__availablelinktypes.append(linktype)
03110     def RemoveAvailableLinkType(self,linktype):
03111         self.__availablelinktypes.remove(linktype)
03112 
03113     """ Available link types and devices in current subsystem set and get here. """
03114     def GetLinkTypeTable(self):
03115         return self.__linktypetable
03116     def SetLinkTypeTable(self,table):
03117         self.__linktypetable = table
03118     def SetRestrictedSparePart(self,sparepart):
03119         self.__restrictedsparepart = sparepart
03120         print self.__restrictedsparepart
03121     def GetRestrictedSparePart(self):
03122         return self.__restrictedsparepart
03123   
03124     def GetDeviceTable(self):
03125         return self.__devicetable
03126     def SetDeviceTable(self,table):
03127         self.__devicetable = table
03128 
03129     """ Get info on restricted link type: links of link type that is the only one to be shown. """
03130     ##
03131     #  If this is set to TRUE, only links of the active linktype is shown. Else links of all linktypes is shown.
03132     #   
03133     #   @restrict - Whether only links of the active link type should be shown, or all kinds of links (active link type set
03134     #   to "")
03135     #   
03136     def RestrictLinkType(self,restrict=True):
03137         
03138         self.__restrictedLinks = restrict
03139         
03140     def IsLinkTypeRestricted(self):
03141         return self.__restrictedLinks
03142     def GetRestrictedLinkType(self):
03143         return self.__restrictedlinktype
03144     def SetRestrictedLinkType(self,linktype):
03145         self.__restrictedlinktype = linktype
03146 
03147     def GetActiveLink(self):
03148         return self.__activelink
03149     def SetActiveLink(self,link):
03150         self.__activelink = link
03151     def SetAvailableLinks(self,links):
03152         self.__availablelinks = links
03153     def GetAvailableLinks(self):
03154         return self.__availablelinks
03155     def AddAvailableLink(self,link):
03156         self.__availablelinks.append(link)
03157     def RemoveAvailableLink(self,link):
03158         self.__availablelinks.remove(link)
03159 
03160 
03161     ##
03162     #  React on File/Connect menu action to connect to the ConfDB, set up the
03163     #   
03164     def test(self,event):
03165         if self.GetCdb(): # already connected
03166             return
03167         
03168         wxBeginBusyCursor()
03169         if not self.__cfg:
03170             path = os.path.join(os.getcwd(),"settings.cfg") #default file name
03171 
03172     # Menu-EventHandler
03173     ##
03174     #  React on File/Connect menu action to connect to the ConfDB, set up the
03175     #   configuration file and initialize the program after ConfDB connection.
03176     # 
03177     #   !return - False on error, True on success.
03178     #   
03179     def OnConnect(self):
03180         # 2DO: draw a dialog to select the parameters (username,pwd,db), animation during connect
03181         cfgRootPath = "/db/devdb"
03182         
03183         if self.GetCdb(): # already connected
03184             return
03185         
03186         self.setCursor(QCursor(Qt.WaitCursor))
03187         
03188         if not self.__cfg:
03189                 path = os.path.join(os.getcwd(),"settings.cfg") #default file name
03190                 if os.path.exists(path):
03191                         self.__cfg = ConfigParser.ConfigParser() #if another config file has not been loaded by the user
03192                         self.__cfg.read(path)
03193                 else:
03194                         QMessageBox.warning(self,"Error","No configuration file is specified, \nchoose File > Load settings... to open the config file")
03195                         del self.__cdb
03196                         self.unsetCursor()
03197                         return False
03198 
03199 
03200         #Our new dbsystem object: to handle dbconnection and retrieval of subsystems from settingsfile
03201         self.__cdb = DBSystem(self.__cfg,self)
03202 
03203         if not self.__cdb.Connect(cfgRootPath): # Try to connect to ConfDB
03204                 self.aConnect.setOn(False) # self.GetToolBar().ToggleTool(CONN_TOGGLE_BUTTON,False)
03205                 self.aDisconn.setOn(True) # self.GetToolBar().ToggleTool(DISCONN_TOGGLE_BUTTON,True)
03206                 self.setCursor(QCursor(Qt.ArrowCursor)) # wxEndBusyCursor()
03207                 self.ShowError("Connection error: " + self.__cdb.GetErrorMessage(),ERR_ERROR,True)
03208                 self.__cdb = None
03209                 return False
03210         
03211         # Update tool bar
03212         self.aConnect.setEnabled(False) # self.GetMenuBar().Enable(ID_CONNECT, False)
03213         self.aDisconn.setEnabled(True)  # self.GetMenuBar().Enable(ID_DISCONNECT, True)
03214 
03215         self.aConnect.setOn(True)  # self.GetToolBar().ToggleTool(CONN_TOGGLE_BUTTON,True)
03216         self.aDisconn.setOn(False) # self.GetToolBar().ToggleTool(DISCONN_TOGGLE_BUTTON,False)
03217         self.setCursor(QCursor(Qt.ArrowCursor))
03218         self.ShowError("Connected...",ERR_INFORMATION,False)
03219         
03220         self.DbUpdate(DB_CONNECTED)
03221         ## !!!!!!!!  self.SetUserMode(None)
03222         
03223     ##
03224     #  React on File/Disconnect menu action to disconnect form the ConfDB, and update the program
03225     #   to after ConfDB disconnection.
03226     #         
03227     def OnDisconnect(self):
03228         if not self.GetCdb(): # Not connected
03229                 return
03230         
03231         if self.__cdb.Disconnect() == True: # Try to disconnect
03232             # self.GetMenuBar().Enable(ID_CONNECT, True)
03233             # self.GetMenuBar().Enable(ID_DISCONNECT, False) 
03234             self.ShowError("Disconnected...",ERR_INFORMATION,False)
03235             self.__cdb = None
03236             self.DbUpdate(DB_DISCONNECTED)
03237             # self.GetToolBar().EnableTool(DISCONN_TOGGLE_BUTTON,False)
03238             # self.GetToolBar().EnableTool(CONN_TOGGLE_BUTTON,True)
03239             # self.GetToolBar().ToggleTool(CONN_TOGGLE_BUTTON,False)
03240             # self.GetToolBar().ToggleTool(DISCONN_TOGGLE_BUTTON,True)
03241             self.aDisconn.setEnabled(False)
03242             self.aConnect.setEnabled(True)
03243         else:
03244             self.ShowError("Disconnection error: " + self.__cdb.GetErrorMessage(),ERR_ERROR,True)
03245     
03246     ##
03247     #  Open a configuration file. We use the settings in the config file to:
03248     #       find user,password and database name for connecting to the database
03249     #       and find out what systems that are created
03250     #   
03251     def OnOpen(self,event):
03252         
03253         self.__directoryname = ""
03254         opendlg = wxFileDialog(self,"Choose a Configuration File",self.__directoryname,"","*.cfg",wxOPEN)
03255         
03256         if opendlg.ShowModal() == wxID_OK: #The OK button was clicked when closing the dialog
03257                 filename = opendlg.GetFilename()
03258                 directory = opendlg.GetDirectory()
03259                 self.__cfg = wxConfig("cdbVis","CERN",os.path.join(directory,filename))
03260 
03261         opendlg.Destroy()
03262     
03263         
03264     ##
03265     #  React on File/Exit menu action. Prompt for saving changes, if not everything is applied
03266     #   to the ConfDB, possible to veto the closure.
03267     #         
03268     def closeEvent(self,event):
03269         empty_dirtylist = self.CleanUpDirtyObjects(False) # Check if there is any obj in dirty objects list toapply to ConfDB
03270         if empty_dirtylist != []: #only save if there is something to save
03271                 ans = QMessageBox.question(self,"Save Changes?","You have chosen to close the application, but there are objects you have\ncreated/modified/deleted that are not saved yet. Save Changes?","Yes","No","Cancel",0,1)
03272                 if ans == 0: #Yes
03273                         #do save, close # error may arise
03274                         res = self.OnSave(None,False)
03275                         if res == False:
03276                                 return False # Do not exit because of save error
03277                 elif ans == 2: #Cancel
03278                         #do not close app.
03279                         return
03280                 elif ans == 1: #No
03281                         #do not save, close
03282                         pass
03283 
03284         if self.GetCdb(): # Disconnect gracefully from ConfDB if connected
03285             self.OnDisconnect()
03286             self.__cdb = None
03287         
03288         event.accept() # Close the application
03289 
03290 
03291     ##
03292     #  React on Help/About menu action and show a dialog with Program version,
03293     #   date and other information
03294     #         
03295     def OnAbout(self, event):
03296         
03297         dlg = wxMessageDialog(self, "CdbVis\n"
03298                                     "Configuration Database Visualizer\n"
03299                                     "Version " + VERSION + "\n"
03300                                     "Date " + DATE + "\n"
03301                                     "Felix Schmidt-Eisenlohr, CERN, 2004\nThomas Johansen, CERN, 2005-2006",
03302                                     "About CdbVis", wxOK | wxICON_INFORMATION)
03303         dlg.ShowModal()
03304         dlg.Destroy()
03305 
03306 
03307     ##
03308     #  Show or hide the miniature window. If it is shown, this method will hide it,
03309     #   if it is hidden, this method will show it.
03310     #   
03311     def ViewSystemsClick(self,event):
03312 
03313         if event == False: #Not caused by event, toggling of check has to be handled manually
03314                 if self.GetMenuBar().IsChecked(ID_VIEW_SUBSYSTEMS):
03315                         self.panel.CloseAreaWindow(True)
03316                         self.GetMenuBar().Check(ID_VIEW_SUBSYSTEMS,False)
03317                 else:
03318                         self.panel.CloseAreaWindow(False)
03319                         self.GetMenuBar().Check(ID_VIEW_SUBSYSTEMS,True)
03320         else:
03321                 if self.GetMenuBar().IsChecked(ID_VIEW_SUBSYSTEMS):
03322                         self.panel.CloseAreaWindow(False)
03323                 else:
03324                         self.panel.CloseAreaWindow(True)
03325 
03326 
03327     ##
03328     #  Obsolete, used to have an object box for creating objects (devices etc)
03329     #   
03330     def ViewObjectBox(self,event,show=False):
03331 
03332         if show == True and event==None: #creation mode selected
03333                 self.__objectbox_inst.Show(True)
03334                 self.GetMenuBar().Check(ID_VIEW_OBJECTBOX,True)
03335                 return
03336         elif show == False and event==None:     
03337                 self.__objectbox_inst.Show(False)
03338                 self.GetMenuBar().Check(ID_VIEW_OBJECTBOX,False)
03339                 return
03340         else:
03341 
03342                 if event == False: #triggered bu user or object toolbox window
03343                         if self.GetMenuBar().IsChecked(ID_VIEW_OBJECTBOX): #hide
03344                                 self.__objectbox_inst.Show(False)
03345                                 self.GetMenuBar().Check(ID_VIEW_OBJECTBOX,False)
03346                         else:
03347                                 self.__objectbox_inst.Show(True)
03348                                 self.GetMenuBar().Check(ID_VIEW_OBJECTBOX,True)
03349                 else:
03350                         if self.GetMenuBar().IsChecked(ID_VIEW_OBJECTBOX):
03351                                 self.__objectbox_inst.Show(True)
03352                         else: #hide
03353                                 self.__objectbox_inst.Show(False)
03354 
03355     ##
03356     #  React on the resize of the Main Window: set the error/information message to
03357     #   be shown in the status bar (have to resize the size of the text control)
03358     #   
03359     def OnSize(self,event):
03360         
03361         self.ShowError(self.__previouserror[1],self.__previouserror[0],False,log=False)
03362         event.Skip()
03363 
03364     ##
03365     #  Show the log window where the user can view every error and informative message
03366     #   sent to the user in the current session.
03367     #   
03368     def ShowLog(self,event=None):
03369         
03370         logwindow = LogWindow(self,-1,self.__logsessionfile)
03371         logwindow.ShowModal()
03372 
03373 
03374     ##
03375     #  Show an error or informative message to the user, either in the status bar or in
03376     #   a message box.
03377     #   
03378     #   @descr - the message to the user
03379     #   @errtype - the message type - ERR_INFORMATION, ERR_ERROR or ERR_CRITICAL
03380     #   @forcemsgbox - whether we should force to show a message box with the message to the user or not.
03381     #   @log - whether the message should be logged to the log session file or not.
03382     #   
03383     def ShowError(self,descr,errtype,forcemsgbox=True,log=True):
03384         
03385         if log:
03386                 try:
03387                         file = open(self.__logsessionfile,"r")
03388                         file = open(self.__logsessionfile,"a")
03389                 except IOError,err:
03390                         file = open(self.__logsessionfile,"w") #file does not exist, ignore recover, but create file
03391                         
03392                 file.close()
03393 
03394                 errnames = ["Information","Critical","Error","Busy","SUCCESSFUL"]
03395                 file = open(self.__logsessionfile,"a") #open() is an alias to file(), a - append
03396                 mod_descr = descr[:]
03397                 mod_descr = mod_descr.replace("\n"," ") # We replace line breaks in the original message with spaces
03398                 mod_descr = mod_descr.replace("\r"," ")
03399                 file.write("Error type : " + str(errnames[errtype]) + " | Message : " + str(mod_descr) + "\n")
03400                 file.close()
03401 
03402         ID_INFOTEXT = 987
03403 
03404         # If we show the message in a message box, we have a tiny algorithm to split up the text so that the
03405         # message boxes are not too big
03406         # TODO: make the messages be split where there are spaces in the message, and not in the middle of words.
03407         if (errtype != ERR_INFORMATION and forcemsgbox):
03408                 new_descr = ""
03409                 i = 1
03410                 while True:
03411                         if len(descr) <= (80*i)-1:
03412                                 new_descr += descr[80*(i-1):len(descr)]
03413                                 break
03414                         new_descr += descr[80*(i-1):80*i] + "\n"
03415                         i += 1
03416 
03417                 descr = new_descr
03418 
03419         # Set the text control width of the text control in the status bar: same size as the column
03420         
03421         if errtype == ERR_INFORMATION: # informative message
03422                 self.myStatusbar.info.setText("Information : "+descr) #self.statusBar().message("Information : "+descr)
03423         elif errtype == ERR_CRITICAL: # critical message -> if we can not continue normally.
03424                 self.myStatusbar.icon.setPixmap(self.myStatusbar.imageCross)
03425                 self.myStatusbar.info.setText("Critical : "+descr)
03426                 if forcemsgbox:
03427                         QMessageBox.critical(self,"CDBVis: CRITICAL ERROR",descr,"Ok" )
03428 
03429         elif errtype == ERR_ERROR:
03430                 self.myStatusbar.icon.setPixmap(self.myStatusbar.imageWarning)
03431                 self.myStatusbar.info.setText("Warning : "+descr)
03432                 if forcemsgbox:
03433                         QMessageBox.warning(self,"CDBVis: ERROR",descr,"Ok" )
03434         elif errtype == ERR_WAIT:
03435                 self.myStatusbar.icon.setPixmap(self.myStatusbar.imageClock)
03436                 self.myStatusbar.info.setText("Busy : "+descr)
03437         elif errtype == ERR_SUCCESS:
03438                 self.myStatusbar.icon.setPixmap(self.myStatusbar.imageCheck)
03439                 self.myStatusbar.info.setText(descr)
03440                 if forcemsgbox:
03441                         QMessageBox.information(self,"CDBVis: Success",descr,"Ok" )
03442 
03443 
03444         
03445         '''
03446         if errtype == ERR_INFORMATION: # informative message
03447                 if forcemsgbox:
03448                         ans = QMessageBox.Information(self,"Information!") # wxMessageBox(descr,"Information!", wxOK | wxICON_INFORMATION)
03449                 else:
03450                         ##pic = wxArtProvider_GetBitmap(wxART_INFORMATION,wxART_TOOLBAR,(16,16))
03451                         ##picbmp = wxStaticBitmap(self.GetStatusBar(),-1,pic)
03452                         ##errtext = wxTextCtrl(self.GetStatusBar(),ID_INFOTEXT,descr,size=wxSize(txtctrl_width,20),style=wxTE_READONLY)
03453                         ##errtext.SetCursor(wxStockCursor(wxCURSOR_ARROW))
03454                         ##errtext.SetForegroundColour(wxColour(0,0,255))
03455                         ##errtext.SetBackgroundColour(wxLIGHT_GREY)
03456         elif errtype == ERR_CRITICAL: # critical message -> if we can not continue normally.
03457                 wxBell()
03458                 if self.__showmsgbox or forcemsgbox:
03459                         ans = wxMessageBox(descr,"Critical error!", wxOK | wxICON_EXCLAMATION)
03460                 else:
03461                         pic = wxArtProvider_GetBitmap(wxART_ERROR,wxART_TOOLBAR,(16,16))
03462                         picbmp = wxStaticBitmap(self.GetStatusBar(),-1,pic)
03463                         errtext = wxTextCtrl(self.GetStatusBar(),ID_INFOTEXT,descr,size=wxSize(txtctrl_width,20),style=wxTE_READONLY)
03464                         errtext.SetCursor(wxStockCursor(wxCURSOR_ARROW))
03465                         errtext.SetForegroundColour(wxColour(255,0,0))
03466                         errtext.SetBackgroundColour(wxColour(0,0,0))
03467         elif errtype == ERR_ERROR: # normal error message
03468                 wxBell()
03469                 if self.__showmsgbox or forcemsgbox:
03470                         ans = wxMessageBox(descr,"Error!", wxOK | wxICON_ERROR)
03471                 else:
03472                         pic = wxArtProvider_GetBitmap(wxART_ERROR,wxART_TOOLBAR,(16,16))
03473                         picbmp = wxStaticBitmap(self.GetStatusBar(),-1,pic)
03474                         errtext = wxTextCtrl(self.GetStatusBar(),ID_INFOTEXT,descr,size=wxSize(txtctrl_width,20),style=wxTE_READONLY)
03475                         errtext.SetCursor(wxStockCursor(wxCURSOR_ARROW))
03476                         errtext.SetForegroundColour(wxColour(255,0,0))
03477                         errtext.SetBackgroundColour(wxLIGHT_GREY)
03478         
03479         if (errtype == ERR_INFORMATION or not self.__showmsgbox) and not forcemsgbox: # show message in status bar
03480                 ##self.GetStatusBar().AddWidget(picbmp,pos=0)
03481                 ##self.GetStatusBar().AddWidget(errtext,pos=1,horizontalalignment=ESB_ALIGN_LEFT)
03482         
03483                 self.__previouserror = []
03484                 self.__previouserror.append(errtype)
03485                 self.__previouserror.append(descr)
03486 
03487                 #EVT_LEFT_DCLICK(picbmp,self.ShowLog)
03488                 #EVT_LEFT_DCLICK(errtext,self.ForceMsgBox)
03489         '''
03490                 
03491     ##
03492     #  Show the last shown error message in a message box.
03493     #   
03494     def ForceMsgBox(self,event):
03495         
03496         self.ShowError(self.__previouserror[1],self.__previouserror[0],True)
03497 
03498     ##
03499     #  Refresh combo boxes in the main window with the most recent information (f.ex.
03500     #   if device types or link types have been added or removed, this should be shown immediately).
03501     #   
03502     def RefreshObjectBoxData(self):
03503         my_subsystem = SubSystem(self.GetCfg(),self.GetActiveSystem())
03504         my_devicetypes = my_subsystem.GetDeviceTypes()
03505         self.__devtypecombobox.Clear()
03506         if my_devicetypes == False:
03507                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
03508         elif my_devicetypes == []:
03509                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_INFORMATION,False)
03510         else:
03511                 map(self.__devtypecombobox.Append,my_devicetypes)
03512 
03513         my_linktypes = my_subsystem.GetLinkTypes()
03514         self.__linktypetable = my_subsystem.GetLinkTypeTable()
03515 
03516         self.__linktypecombobox.Clear()
03517         self.GetSelectWindow().linktypeCtrl.Clear()
03518         if my_linktypes == False:
03519                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
03520         elif my_linktypes == []:
03521                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_INFORMATION,False)
03522         else:
03523                 map(self.__linktypecombobox.Append,my_linktypes)
03524                 map(self.GetSelectWindow().linktypeCtrl.Append, my_linktypes)
03525                 self.GetSelectWindow().linktypeCtrl.Enable(True)
03526                 self.GetSelectWindow().linktyperestrictchk.Enable(True)
03527                 self.GetSelectWindow().linktyperestrictchk.SetValue(False)
03528 
03529     ##
03530     #  At the moment obsolete. Maybe we should use this to set subsystem settings that are specific for
03531     #   a subsystem, and store it in the configuration file. F.ex. image map ++.
03532     #   
03533     def CreateSystemClick(self,event):
03534 
03535         systemchoices = allvalidsystems[:] #retrieved from global variable allvalidsystems in cdbVisCore module. Force COPY
03536         systemchoices_tmp = self.GetAvailableSystems() #get already created subsystems
03537         
03538         for obj in systemchoices_tmp:
03539                 if obj.GetName() in systemchoices: #not yet created
03540                         systemchoices.remove(obj.GetName())
03541         
03542         createsystemframe = CreateSystemWindow(self,-1,systemchoices)
03543         
03544         #show create sub system window, and retrieve values
03545         if createsystemframe.ShowModal() == wxID_OK: #retrieve values from the window
03546                 systemname = createsystemframe.GetSystemName().upper()
03547                 selectedcolor = createsystemframe.GetColorSelected()
03548                 if self.__cdb != None:
03549                         newsubsystem = SubSystem(self.__cfg,systemname)
03550                         newsubsystem.SetColour(selectedcolor)
03551                         #here we should throw up a dialog box telling the user to wait while the scehma(s) is being created...
03552                         wxBeginBusyCursor()
03553                         success = newsubsystem.Create()
03554                         wxEndBusyCursor()
03555                         if success == True:
03556                              self.DbUpdate(DB_CONNECTED)
03557                              dlg = wxMessageDialog(self,str(systemname) + " was successfully created.!")
03558                              dlg.ShowModal()
03559                              dlg.Destroy()     
03560                         else:
03561                             dlg = wxMessageDialog(self,newsubsystem.GetErrorMessage(),"Error!",wxOK | wxICON_ERROR)
03562                             dlg.ShowModal()
03563                             dlg.Destroy()
03564                                         
03565                 else:#if not connected to db
03566                         dlg = wxMessageDialog(self,"Lost connection to database, sub system _not_ created!","Error!",wxOK | wxICON_ERROR)
03567                         dlg.ShowModal()
03568                         dlg.Destroy()
03569         else: #cancel clicked
03570                 pass
03571 
03572         createsystemframe.Destroy()
03573 
03574     ##
03575     #  Shows the modify window for systems, and initializes all fields with the already set values
03576     #       Perhaps used later if we need to set system settings (Obsolete)
03577     #   
03578     def ModifySystemClick(self,event):
03579 
03580         activesystem = self.GetActiveSystem()
03581         if activesystem == None or activesystem == "":
03582                 self.ShowError("No subsystem is selected!",ERR_ERROR)
03583                 return False
03584         modsubsystem = SubSystem(self.__cfg,activesystem)
03585         modsubsystem.GetObjectInfo()
03586         modifysystemframe = CreateSystemWindow(self,-1,[activesystem],False,modsubsystem.GetColour()) #initial values on modify
03587 
03588         if modifysystemframe.ShowModal() == wxID_OK:
03589                 #systemname is the same
03590                 if modsubsystem.IsCreated() == False:
03591                         dlg = wxMessageDialog(self,str(activesystem) + " is not yet created.!")
03592                         dlg.ShowModal()
03593                         dlg.Destroy()
03594                 else:
03595                         if self.__cdb != None: #we have a db connection
03596                                 selectedcolor = modifysystemframe.GetColorSelected()
03597 
03598                                 modsubsystem.SetColour(selectedcolor)
03599                                 wxBeginBusyCursor()
03600                                 success = modsubsystem.Modify()
03601                                 wxEndBusyCursor()
03602 
03603                                 if success == True:
03604                                      #self.GetSystemWindow().SystemChanged() #need to change, colour might have been changed
03605                                      dlg = wxMessageDialog(self,str(activesystem) + " was successfully modified.!", "Success!",wxOK | wxICON_INFORMATION)
03606                                      dlg.ShowModal()
03607                                      dlg.Destroy()     
03608                                 else:
03609                                     dlg = wxMessageDialog(self,modsubsystem.GetErrorMessage(),"Error!",wxOK | wxICON_ERROR)
03610                                     dlg.ShowModal()
03611                                     dlg.Destroy()
03612                         else:#if not connected to db
03613                                 dlg = wxMessageDialog(self,"Lost connection to database, sub system _not_ modified!","Error!",wxOK | wxICON_ERROR)
03614                                 dlg.ShowModal()
03615                                 dlg.Destroy()
03616         else: #cancel clicked
03617                 pass
03618                                 
03619                 
03620         modifysystemframe.Destroy()                             
03621         
03622 
03623 
03624     ##
03625     #  Show create device type window, create a new device type, and add it to the dirty objects
03626     #   list.
03627     #   
03628     def CreateDeviceTypeClick(self):
03629 
03630         # We have to have an active subsystem to store the device type in (can be stored in several)
03631         activesystem = self.GetActiveSystem()
03632         if activesystem == None or activesystem == "":
03633                 self.ShowError("No subsystem is selected!",ERR_ERROR)
03634                 return False
03635 
03636         my_subsystem = SubSystem(self.__cfg,activesystem)
03637         my_devicetypes = my_subsystem.GetDeviceTypes() # Get all the device types of that subsystem; so that we do not
03638         
03639         # create device types with the same name that conflict with each other.
03640         # TODO: check device type name against device types in the subsystem the user creates them in when the user
03641         # clicks on OK button in create device type window, because the subsystems may be different from the active
03642         # subsystem
03643         my_createdevicetypeframe = CreateDeviceTypeWindow(self,"",activesystem,True,None,my_devicetypes)
03644         my_createdevicetypeframe.show()
03645         ans =  my_createdevicetypeframe.exec_loop()
03646              
03647         #show create device window, and retrieve values set by the user
03648         if ans == 1: #retrieve values from the window
03649                 my_devicetype = my_createdevicetypeframe.GetDeviceTypeObj() # get the device type object created
03650                 ### self.AddToUndo(self.GetFirstNewUndoIndex(),"create devicetype: " + str(my_devicetype.GetName())) # undo info
03651                 my_devicetype.Create() # add to dirty objects list
03652                 
03653                 try: # add to treeview
03654                         self.GetSelectWindow().AddItem(my_devicetype,TN_DEVICETYPE)
03655                         ##my_id = self.GetSelectWindow().GetItemID("Device types")
03656                         ##self.GetSelectWindow().AddItem(my_id,my_devicetype.GetName(),TN_DEVICETYPE)
03657                 except KeyError,err:
03658                         print "petite exception"
03659                         pass
03660         else: #cancel clicked
03661                 pass
03662 
03663 
03664     ##
03665     #  Update this objects renaming to reflect in all previous objects of this type and all objects with 
03666     #   references to this object in dirty objects list. Also save the renaming update to recover file (easier than
03667     #   iterating through every object in recover file, and restore them with new name/settings if needed).
03668     # 
03669     #   @obj - the object that is renamed and to be added to rename objects
03670     #   @recovertofile - whether it should be stored in recover file or not
03671     #   
03672     def UpdateRenamedObject(self,obj,recovertofile=True):
03673 
03674         # For information about how this renaming works - look in the programmers documentation
03675         i = 0
03676         if obj.__class__ == DeviceType:
03677                 while i < len(self.__dirtyobjects):
03678                         if self.__dirtyobjects[i].__class__ == DeviceType and self.__dirtyobjects[i].GetName() == obj.GetOldName(): #rename
03679                                 self.__dirtyobjects[i].SetName(obj.GetName())
03680                         elif self.__dirtyobjects[i].__class__ == Device and self.__dirtyobjects[i].GetType() == obj.GetOldName():
03681                                 self.__dirtyobjects[i].SetType(obj.GetName(),update=False)
03682                         i += 1
03683                 tmpobj = DeviceType(self.GetActiveSystem(),obj.GetOldName(),True)       
03684                         
03685         elif obj.__class__ == LinkType:
03686                 while i < len(self.__dirtyobjects):
03687                         if self.__dirtyobjects[i].__class__ == LinkType and self.__dirtyobjects[i].GetName() == obj.GetOldName(): #rename
03688                                 self.__dirtyobjects[i].SetName(obj.GetName())
03689                         elif self.__dirtyobjects[i].__class__ == Link and self.__dirtyobjects[i].GetType() == obj.GetOldName():
03690                                 self.__dirtyobjects[i].SetType(obj.GetName())
03691                         i += 1
03692                 tmpobj = LinkType(self.GetActiveSystem(),obj.GetOldName(),True) 
03693         elif obj.__class__ == Device:
03694                 while i < len(self.__dirtyobjects):
03695                         if self.__dirtyobjects[i].__class__ == Device and self.__dirtyobjects[i].GetName() == obj.GetOldName(): #rename
03696                                 self.__dirtyobjects[i].SetName(obj.GetName())
03697                         elif self.__dirtyobjects[i].__class__ == Link:
03698                                 if self.__dirtyobjects[i].GetNodeTo() == obj.GetOldName():
03699                                         self.__dirtyobjects[i].SetNodeTo(obj.GetName())
03700                                 elif self.__dirtyobjects[i].GetNodeFrom() == obj.GetOldName():
03701                                         self.__dirtyobjects[i].SetNodeFrom(obj.GetName())
03702                         elif self.__dirtyobjects[i].__class__ == Port:
03703                                 if self.__dirtyobjects[i].GetDevice() == obj.GetOldName():
03704                                         self.__dirtyobjects[i].SetDevice(obj.GetName())
03705                         i += 1
03706 
03707 
03708         #look for previous rename objects,in case we have renamed the same object earlier, this will be removed
03709         j = 0
03710         found = False
03711         while j < len(self.__renameobjects):
03712                 if self.__renameobjects[j].__class__ == obj.__class__ and self.__renameobjects[j].GetName() == obj.GetOldName():
03713                         if obj.__class__ == Device:
03714                                 tmpobj = Device(self.GetActiveSystem(),obj.GetName(),True)
03715                                 tmpobj.SetType(self.__renameobjects[j].GetType(),False)
03716                         elif obj.__class__ == DeviceType:
03717                                 tmpobj = DeviceType(self.GetActiveSystem(),obj.GetName(),True)
03718                         elif obj.__class__ == LinkType:
03719                                 tmpobj = LinkType(self.GetActiveSystem(),obj.GetName(),True)
03720                         
03721                         found = True
03722                         prev_oldname = self.__renameobjects[j].GetOldName()
03723                         tmpobj.SetID(self.__renameobjects[j].GetID())
03724                         tmpobj.SetOldName(prev_oldname)
03725                         tmpobj.SetSaveStatus(3)
03726 
03727                         #set up a list of oldnames to newnames
03728                         self.__newnamesrenamed[prev_oldname] = obj.GetName() #instance of b found in list were a -> b, now b is changed to c, so a -> c
03729                         self.__newnames.append(obj.GetName()) #c is the new name of a renamed obj
03730                         self.__oldnamesrenamed[obj.GetName()] = prev_oldname #c had the name a before renaming
03731 
03732                         self.__renameobjects.pop(j)
03733                         self.__renameobjects.insert(0,tmpobj)
03734 
03735                         break
03736                 j += 1
03737 
03738         if not found:
03739                 if obj.__class__ == Device:
03740                         tmpobj = Device(self.GetActiveSystem(),obj.GetOldName(),True)
03741                 elif obj.__class__ == DeviceType:
03742                         tmpobj = DeviceType(self.GetActiveSystem(),obj.GetOldName(),True)
03743                 elif obj.__class__ == LinkType:
03744                         tmpobj = LinkType(self.GetActiveSystem(),obj.GetOldName(),True)
03745         
03746                 #check if it is stored in db, if so, insert rename object on first position in the dirty list
03747                 res = tmpobj.Update(True)
03748                 if res == {}: #not in db
03749                         pass
03750                 elif res == False:
03751                         self.ShowError("An error occured when trying to retrieve data from the database: " + str(tmpobj.GetErrorMessage()),ERR_ERROR)
03752                         #cannot return false here, since we cannot undo the prev. renaming..or?
03753                 else: #dictionary, in DB, not renamed before
03754                         self.__renameobjects.insert(0,obj)
03755                         self.__oldnames.insert(0,obj.GetOldName()) #a has been renamed
03756                         self.__newnamesrenamed[obj.GetOldName()] = obj.GetName() #a has been renamed to b
03757                         self.__newnames.append(obj.GetName()) #b is the new name of the renamed
03758                         self.__oldnamesrenamed[obj.GetName()] = obj.GetOldName() #b had the name a before renaming
03759 
03760 
03761         #update objects in visual window, if needed:
03762         if obj.__class__ == DeviceType:
03763                 for visobj in self.GetVisWindow().GetContents():
03764                         if visobj == Device:
03765                                 if visobj.GetObject().GetType() == obj.GetOldName():
03766                                         visobj.GetObject().SetType(obj.GetName(),True)
03767         elif obj.__class__ == LinkType:
03768                 for visobj in self.GetVisWindow().GetContents():
03769                         if visobj == Link:
03770                                 if visobj.GetObject().GetType() == obj.GetOldName():
03771                                         visobj.GetObject().SetType(obj.GetName(),False)
03772         elif obj.__class__ == Device:
03773                 for visobj in self.GetVisWindow().GetContents(): #not update ports cause they are not in visual window
03774                         if visobj == Link:
03775                                 if visobj.GetObject().GetNodeFrom() == obj.GetOldName():
03776                                         visobj.GetObject().SetNodeFrom(obj.GetName())
03777                                 elif visobj.GetObject().GetNodeTo() == obj.GetOldName():
03778                                         visobj.GetObject().SetNodeTo(obj.GetName())
03779                 
03780         if recovertofile:
03781                 res = self.RecoverObjectToFile(obj,state=DESIGN) #save rename object in recovery file
03782                 # TODO: actually check that this happens...and that the rename object is handled properly and right
03783                 # on recover from file
03784                 if not res:
03785                         return False
03786                 
03787         return True
03788         # TODO: update objects in the visual window to be renamed as well.
03789 
03790     ##
03791     #  Open the Modify device type window, let the user do changes to
03792     #   the device type, and store it in the dirty objects list, and rename
03793     #   list if renamed.
03794     #   
03795     def ModifyDeviceTypeClick(self,event):
03796 
03797         # active subsystem
03798         my_activesystem = self.GetActiveSystem()
03799         if my_activesystem == None or my_activesystem == "":
03800                 self.ShowError("No subsystem is selected!",ERR_ERROR)
03801                 return False
03802 
03803         # active device type
03804         my_activedevicetype = self.GetActiveDeviceType()
03805         if my_activedevicetype == None or my_activedevicetype == "":
03806                 self.ShowError("No devicetype is selected.",ERR_ERROR)
03807                 return False
03808 
03809         # TODO: check that the device types that are loaded, are always loaded for the
03810         # subsystem that the device type will be stored in. Same in create device type.
03811         my_subsystem = SubSystem(self.__cfg,my_activesystem)
03812         my_devicetypes = my_subsystem.GetDeviceTypes()
03813 
03814         my_devicetype = DeviceType(my_activesystem,my_activedevicetype,False)
03815 
03816         my_createdevicetypeframe = CreateDeviceTypeWindow(self,"Create Device Type",my_activesystem,False,my_devicetype,my_devicetypes)
03817                                                                                                                                                                        
03818         if my_createdevicetypeframe.ShowModal() == wxID_OK:
03819                 my_devicetype,renameobj = my_createdevicetypeframe.GetDeviceTypeObj()
03820                 res = True
03821                 if renameobj != None:
03822                         res = self.UpdateRenamedObject(renameobj) 
03823                         #if error occured in the middle of the renaming..we will have to continue
03824                         #TODO: If error occurs, we should return.
03825                         if res:
03826                                 try:
03827                                         #remove from tree view, and add to tree view (new name)
03828                                         my_id = self.GetSelectWindow().GetItemID(renameobj.GetOldName())
03829                                         self.GetSelectWindow().RemoveItem(my_id,"Device types") #link and device
03830                                         self.GetSelectWindow().SetItemToDeleted(renameobj.GetOldName())
03831 
03832                                         my_id = self.GetSelectWindow().GetItemID("Device types")
03833                                         self.GetSelectWindow().AddItem(renameobj,TN_DEVICETYPE)
03834 
03835                                         self.SetActiveDeviceType(renameobj.GetName())    
03836                                 except KeyError,err:
03837                                         #print "treeitemid not found"
03838                                         pass
03839                 if res:
03840                         # undo
03841                         self.AddToUndo(self.GetFirstNewUndoIndex(),"modify devicetype: " + str(my_devicetype.GetName()))
03842                         my_devicetype.Modify() # to dirty objects list
03843                         self.GetSelectWindow().UpdateInfo(my_devicetype)
03844         else: #cancel clicked
03845                 pass
03846 
03847         my_createdevicetypeframe.Destroy()
03848 
03849     def DoModify(self):
03850         # define wich componant to Modify :
03851         if self.GetVisWindow().selection and self.GetActiveDevice():
03852                 self.ModifyDeviceClick(None)
03853         
03854         elif self.GetActiveLink():
03855                 toModify = self.GetActiveLink()
03856                 print "modify LINK"
03857         else:
03858                 print "No device selected ?"
03859                 return
03860                 
03861     def DoDelete(self):
03862         # define wich componant to delete :
03863         if self.GetVisWindow().selection:
03864                 toDelete = self.GetVisWindow().selection
03865         elif self.GetActiveLink():
03866                 toDelete = [self.GetActiveLink()]
03867         else:
03868                 return
03869                 
03870         toDeleteNames = []
03871         for item in toDelete:
03872                 toDeleteNames.append(item.GetObject().GetName())
03873 
03874         ans = QMessageBox.question(self,"Delete ?","Are you sur you want to delete: %s"%', '.join(toDeleteNames),"Yes","No","",0,1)
03875         if ans == 1: # No
03876                 return
03877         self.SetCreationMode(True)
03878         for item in toDelete:
03879                 if isinstance(item,Box):
03880                         # check if the device is connected to an other devie
03881                         if item.GetObject().GetLinks(False)!=[] or item.GetObject().GetLinks(True)!=[]:
03882                                 self.ShowError("Cannot Delete : "+item.GetObject().GetName()+" because it is still connected to an other device",ERR_ERROR,True)
03883                                 return
03884                 elif isinstance(item,myLine):
03885                         pass
03886                 else:
03887                         self.ShowError("Cannot Delete : "+item.GetObject().GetName()+" ",ERR_ERROR,True)
03888                         return
03889                         
03890                 item.GetObject().Delete()
03891                 self.DoNotShow.append(item.GetObject().GetName())
03892                 # Delete the item fro the tree:
03893                 ## itm = self.GetSelectWindow().treectrl.findItem(item.GetObject().GetName(),0)
03894                 ## self.GetSelectWindow().treectrl.takeItem(itm)
03895                 self.ShowError("You will have to commit the changes to the Database, other wise you will continue seeing the deleted items",ERR_INFORMATION,True)
03896                 
03897         self.GetVisWindow().canvas.update()
03898         
03899     ##
03900     #  Show the create device window, let the user create a device (and ports), and store
03901     #   the device(s) and port(s) in the dirty objects list.
03902     # 
03903     #   @location - if the location string of the device to be created is already defined, to be set in the location
03904     #   text control in create device window.
03905     #   
03906     def CreateDeviceClick(self,event=None,location=""):
03907 
03908         # active subsystem
03909         my_activesystem = self.GetActiveSystem()
03910         if my_activesystem == None or my_activesystem == "":
03911                 self.ShowError("No subsystem is selected!",ERR_ERROR)
03912                 return False
03913 
03914         my_subsystem = SubSystem(self.__cfg,my_activesystem)
03915         my_devtypes = my_subsystem.GetDeviceTypes()
03916         my_functions= "" ### WALID_RPOB self.__cdb.GetAllDeviceFunctions();
03917         # Get all device types in that subsystem
03918         # TODO: user can change subsystem in createwindow, therefore we should be able to load
03919         # device types of that subsystem as well, or else it is inconsistent.
03920         if my_devtypes == False:
03921                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
03922                 return False
03923 
03924         # set device type to either the active one, or the one selected in the combo box
03925         my_devtype = self.GetActiveDeviceType()
03926         
03927         createdeviceframe = CreateDeviceWindow(self,my_activesystem,True,None,my_devtypes,my_devtype,location,my_functions)
03928         createdeviceframe.show()
03929         ans =  createdeviceframe.exec_loop()
03930         
03931         if ans == 1: #retrieve values from the window
03932                 my_devobjs,my_devports = createdeviceframe.GetDeviceObjs()
03933                 if len(my_devobjs) == 1:
03934                         self.AddToUndo(self.GetFirstNewUndoIndex(),"create device and ports: " + str(my_devobjs[0].GetName()))
03935                 else:
03936                         self.AddToUndo(self.GetFirstNewUndoIndex(),"create " + str(len(my_devobjs)) + " devices with ports")
03937 
03938                 j = 0
03939                 
03940                 for my_devobj in my_devobjs:
03941                         my_devobj.Create() # to dirty objects list.
03942                         # add to tree view
03943                         try:
03944                                 # my_id = self.GetSelectWindow().GetItemID(my_devobj.GetType())
03945                                 self.GetSelectWindow().AddItem(my_devobj,TN_DEVICE)
03946                         except KeyError,err:
03947                                 pass
03948  
03949                         # if event == None:
03950                                 # pass #called from drop visual device
03951                         # else: # where to place the created devices in the visual window (if many)
03952                                 # x_offset,y_offset = self.GetVisWindow().CalcUnscrolledPosition(10,10+j)
03953                                 # self.GetVisWindow().CreateNode(x_offset,y_offset,my_devobj,True)
03954                                 # visobj = self.GetVisWindow().FindByName(my_devobj.GetName())
03955                                 # if visobj:
03956                                         # self.GetVisWindow().Select(visobj,refresh=False)
03957 
03958                         #Create ports for every device
03959                         for port in my_devports:
03960                                 tmp_port = Port(self.GetActiveSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),my_devobj.GetName(),True)
03961                                 tmp_port.SetDict(port.GetObjectInfo(True))
03962                                 tmp_port.SetDevice(my_devobj.GetName())
03963                                 tmp_port.Create() # We are creating new device so we can only create port (no modify or delet possible)
03964                                 self.GetSelectWindow().AddItem(tmp_port,TN_PORT) # add the Port to the tree:
03965 
03966                         j += 5
03967 
03968                 self.SetCreationMode(True)
03969                 self.GetVisWindow().canvas.update()
03970 
03971                 if event == None and location == "":
03972                         return my_devobjs #drop objs
03973 
03974         else: #cancel clicked
03975                 return False
03976 
03977         
03978 
03979     ##
03980     #  Show the modify device window to the user, let the user do changes
03981     #   for the device (and ports), and then add the changes to the dirty objects
03982     #   list.
03983     #   
03984     def ModifyDeviceClick(self,event=None):
03985         my_activesystem = self.GetActiveSystem()
03986         if my_activesystem == None or my_activesystem == "":
03987                 self.ShowError("No subsystem is selected!",ERR_ERROR)
03988                 return False
03989         
03990         my_activedevice = self.GetActiveDevice()
03991 
03992         if my_activedevice == None or my_activedevice == "":
03993                 self.ShowError("No device is selected.",ERR_ERROR)
03994                 return False
03995         
03996         if type(my_activedevice)==type("") :
03997                 devName = my_activedevice
03998         else:
03999                 devName = my_activedevice.GetObject().GetName()
04000         device_tmp = Device(my_activesystem,devName,False)
04001 
04002         my_subsystem = SubSystem(self.__cfg,my_activesystem)
04003         my_devtypes = my_subsystem.GetDeviceTypes()
04004         # TODO: devicetypes to be selected from selected subsystem(s), as in create device
04005 
04006         if my_devtypes == False:
04007                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
04008                 return False
04009 
04010         createdeviceframe = CreateDeviceWindow(self,my_activesystem,False,device_tmp,my_devtypes)
04011         createdeviceframe.show()
04012         ans =  createdeviceframe.exec_loop()                                                                                                                                                
04013         #show modify device window, and retrieve values
04014         if ans == 1: #retrieve values from the window
04015                 self.SetCreationMode(True)
04016                 device_tmp,renameobj,my_devports,deletedports = createdeviceframe.GetDeviceObjs()
04017                 prev_name = device_tmp.GetName()
04018                 if renameobj != None:
04019                         prev_name = renameobj.GetOldName()
04020 
04021                 obj = self.GetVisWindow().FindByName(prev_name)
04022 
04023                 if renameobj != None:
04024                         prev_name = renameobj.GetOldName()
04025                         res = self.UpdateRenamedObject(renameobj) #what if this fails?
04026                         # if it fails, we should just return, and inform the user.
04027                         try:
04028                                 #remove from tree view, and add to tree view (rename)
04029                                 # my_id = self.GetSelectWindow().GetItemID(renameobj.GetOldName())
04030                                 # self.GetSelectWindow().RemoveItem(my_id,renameobj.GetType()) #link and device
04031                                 # self.GetSelectWindow().SetItemToDeleted(renameobj.GetOldName())
04032                                 ## Walid : I replaced the commented line above by :
04033                                 itm = self.GetSelectWindow().treectrl.findItem(renameobj.GetOldName(),0)
04034                                 itm.setText(0,renameobj.GetName())
04035 
04036 
04037                                 # my_id = self.GetSelectWindow().GetItemID(renameobj.GetType())
04038                                 # self.GetSelectWindow().AddItem(renameobj,TN_DEVICE)
04039                                 self.SetActiveDevice(renameobj.GetName())
04040                         except KeyError,err:
04041                                 pass
04042                 undoindex = self.GetFirstNewUndoIndex()
04043                 if device_tmp.IsSystemChanged():        
04044                         newtmpdev = Device(device_tmp.GetSystem(),device_tmp.GetName(),True)
04045                         newtmpdev.SetDict(device_tmp.GetObjectInfo(True))
04046                         newtmpdev.SetModifyStatus(1) #system update
04047                         newtmpdev.Modify()
04048                         
04049                 device_tmp.SetModifyStatus(0) # Default.
04050                 device_tmp.Modify() #added to dirtylist
04051                 self.AddToUndo(undoindex,"modify device (and ports): " + str(device_tmp.GetName()))
04052                 self.GetSelectWindow().UpdateInfo(device_tmp) #Update info
04053                 obj.GetObject().SetDict(device_tmp.GetObjectInfo())
04054                 # If any ports where deleted by the user, we add them to dirty objects list here
04055                 for deleted_port in deletedports: #portnbr,porttype,portway,portid
04056                         tmp_port = Port(self.GetActiveSystem()) #,deleted_port[0],deleted_port[1],int(deleted_port[2]),device_tmp.GetName(),True)
04057                         tmp_port.SetDict(deleted_port.GetObjectInfo(True))
04058                         tmp_port.SetPortID(int(deleted_port.GetPortID())) #deleted_port[3]))
04059                         tmp_port.Delete()                               
04060 
04061                 # add changed ports to dirty objects list
04062                 for port in my_devports:
04063                         tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04064                         tmp_port.SetDict(port.GetObjectInfo(True))
04065                         if port.GetSaveStatus() == CREATE:
04066                                 tmp_port.Create()
04067                         elif port.GetSaveStatus() == MODIFY:
04068                                 tmp_port.Modify()
04069                         '''if port.GetSaveStatus() == 10: #port changed
04070                                 port.SetDevice(device_tmp.GetName())
04071 
04072                                 modifystatus = port.GetModifyStatus()
04073                                 if modifystatus.find("3",0,len(modifystatus)) != -1: #this modify status means that it has been created (modify points to that a device is modifyed, and here we have a port that is being created.
04074                                         tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04075                                         tmp_port.SetDict(port.GetObjectInfo(True))
04076                                         tmp_port.Create()
04077                                 else:
04078 
04079                                         if modifystatus.find("0",0,len(modifystatus)) != -1:
04080                                                 tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04081                                                 tmp_port.SetDict(port.GetObjectInfo(True))
04082                                                 tmp_port.SetModifyStatus(0)
04083                                                 tmp_port.Modify() #Ports cannot be deleted here, must be done manually!!
04084                                         if modifystatus.find("1",0,len(modifystatus)) != -1:
04085                                                 tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04086                                                 tmp_port.SetDict(port.GetObjectInfo(True))
04087                                                 tmp_port.SetModifyStatus(1)
04088                                                 tmp_port.Modify() #Ports cannot be deleted here, must be done manually!!
04089                                         if modifystatus.find("2",0,len(modifystatus)) != -1:
04090                                                 tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04091                                                 tmp_port.SetDict(port.GetObjectInfo(True))
04092                                                 tmp_port.SetModifyStatus(2)
04093                                                 tmp_port.Modify() #Ports cannot be deleted here, must be done manually!!
04094 
04095                         if not obj:
04096                                 obj = Device(device_tmp.GetSystem(),device_tmp.GetName(),False)
04097                         self.__visualundolist.append(obj)
04098 
04099                         if obj.__class__ == DrawingObject:
04100                                 self.GetVisWindow().Deselect(obj,refresh=False)
04101                                 obj.SetObjectRef(device_tmp)
04102                                 self.GetVisWindow().Select(obj,refresh=False)
04103                         '''
04104         else: #cancel clicked
04105                 pass
04106 
04107         self.GetVisWindow().canvas.update()
04108 
04109     ##
04110     #  Show the create link type window, let the user create a simple
04111     #   or composite link type, and add changes to dirty objects list when user is finished.
04112     #   
04113     def CreateLinkTypeClick(self,event):
04114 
04115         activesystem = self.GetActiveSystem()
04116         if activesystem == None or activesystem == "":
04117                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04118                 return False
04119 
04120         my_subsystem = SubSystem(self.__cfg,activesystem)
04121         my_linktypes = my_subsystem.GetLinkTypes()
04122 
04123         createlinktypeframe = CreateLinkTypeWindow(self,-1,activesystem,True,None,my_linktypes)
04124         
04125         #show create linktype window, and retrieve values
04126         if createlinktypeframe.ShowModal() == wxID_OK: #retrieve values from the window
04127                 my_linktypeobj = createlinktypeframe.GetLinkTypeObj()   
04128                 self.AddToUndo(self.GetFirstNewUndoIndex(),"create linktype: " + str(my_linktypeobj.GetName()))
04129                 my_linktypeobj.Create() 
04130                 try:
04131                         my_id = self.GetSelectWindow().GetItemID("Link types")
04132                         self.GetSelectWindow().AddItem(my_linktypeobj,TN_LINKTYPE)
04133                 except KeyError,err:
04134                         #print "treeitemid not found"
04135                         pass
04136  
04137         else: #cancel clicked
04138                 pass
04139 
04140         createlinktypeframe.Destroy()
04141 
04142     ##
04143     #  Show the modify link type window, let the user modify the link type,
04144     #   and add the changes to the dirty objects list if the user pressed the Ok button
04145     #   
04146     def ModifyLinkTypeClick(self,event):
04147 
04148         my_activesystem = self.GetActiveSystem()
04149         if my_activesystem == None or my_activesystem == "":
04150                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04151                 return False
04152         my_activelinktype = self.GetActiveLinkType()
04153 
04154         if my_activelinktype == None:
04155                 self.ShowError("No linktype is selected.",ERR_ERROR)
04156                 return False
04157 
04158         my_subsystem = SubSystem(self.__cfg,my_activesystem)
04159         my_linktypes = my_subsystem.GetLinkTypes()
04160 
04161         for obj in my_linktypes:
04162                 print str(obj)
04163 
04164         my_linktype = LinkType(my_activesystem,my_activelinktype,False)
04165         my_createlinktypeframe = CreateLinkTypeWindow(self,-1,my_activesystem,False,my_linktype,my_linktypes)
04166                                                                                                                                                                        
04167         if my_createlinktypeframe.ShowModal() == wxID_OK: #retrieve values from the window
04168                 my_linktype,renameobj = my_createlinktypeframe.GetLinkTypeObj() 
04169                 res = True
04170                 if renameobj != None:
04171                         res = self.UpdateRenamedObject(renameobj)
04172                         if res: #remove from treelist, and replace
04173                                 try:
04174                                         #remove from treelist
04175                                         my_id = self.GetSelectWindow().GetItemID(renameobj.GetOldName())
04176                                         self.GetSelectWindow().RemoveItem(my_id,"Link types")
04177                                         self.GetSelectWindow().SetItemToDeleted(renameobj.GetOldName())
04178 
04179                                         my_id = self.GetSelectWindow().GetItemID("Link types")
04180                                         self.GetSelectWindow().AddItem(renameobj,TN_LINKTYPE)
04181 
04182                                         self.SetActiveLinkType(renameobj.GetName())      
04183                                 except KeyError,err:
04184                                         pass
04185 
04186                 if res:
04187                         self.AddToUndo(self.GetFirstNewUndoIndex(),"modify linktype: " + str(my_linktype.GetName()))
04188                         my_linktype.Modify()
04189                         self.GetSelectWindow().UpdateInfo(my_linktype)
04190         else: #cancel clicked
04191                 pass
04192 
04193         my_createlinktypeframe.Destroy()
04194     def CreateLinkClick(self,device1,device2):
04195         self.SetCreationMode(True)
04196         my_createlinkframe = CreateLinkWindow(self,self,device1,device2)
04197         my_createlinkframe.show()
04198         ans =  my_createlinkframe.exec_loop()
04199         
04200         
04201         '''# Creating / deleting the ports modified
04202         deletedports, createdports =  my_createlinkframe.GetPorts()
04203         pdb.set_trace()
04204         # If any ports where deleted by the user, we add them to dirty objects list here
04205         for deleted_port in deletedports: #portnbr,porttype,portway,portid
04206                 tmp_port = Port(self.GetActiveSystem()) #,deleted_port[0],deleted_port[1],int(deleted_port[2]),device_tmp.GetName(),True)
04207                 tmp_port.SetDict(deleted_port.GetObjectInfo(True))
04208                 tmp_port.SetPortID(int(deleted_port.GetPortID())) #deleted_port[3]))
04209                 tmp_port.Delete()                               
04210 
04211         # add changed ports to dirty objects list
04212         for port in createdports:
04213                 tmp_port = Port(port.GetSystem(),port.GetPortNbr(),port.GetPortType(),port.GetPortWay(),port.GetDevice(),True)
04214                 tmp_port.SetDict(port.GetObjectInfo(True))
04215                 if port.GetSaveStatus() == CREATE:
04216                         tmp_port.Create()'''
04217         
04218     ##
04219     #  Show the create link/connection window, let the user set link properties,
04220     #   and connection properties (between which to devices, and ports), and if the user
04221     #   pressed the Ok button, add the changes to the dirty objects list.
04222     # 
04223     #   @obj1 - if set, the device object for the FROM/START end of the link
04224     #   @obj2 - if set, the device object for the TO/END end of the link
04225     #   
04226     def CreateLinkClick_OLD(self,event=None,obj1=None,obj2=None):
04227         
04228         my_activesystem = self.GetActiveSystem()
04229         if my_activesystem == None or my_activesystem == "":
04230                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04231                 return False
04232 
04233         my_subsystem = SubSystem(self.__cfg,my_activesystem)
04234         my_linktypes = my_subsystem.GetLinkTypes()
04235         my_devtypes = my_subsystem.GetDeviceTypes()
04236 
04237         if my_linktypes == False or my_devtypes == False:
04238                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
04239                 return False
04240 
04241         createlinkframe = CreateLinkWindow(self,-1,my_activesystem,True,None,my_linktypes,my_devtypes,True,obj1,obj2)
04242                                                                                                                                                                        
04243         #show create device windiw, and retrieve values
04244         if createlinkframe.ShowModal() == wxID_OK: #retrieve values from the window
04245                 linkobj = createlinkframe.GetLinkObj()
04246                 self.GetVisWindow().CreateConnectedLink(linkobj,wxPoint(0,0),wxSize(0,0),True)
04247                 self.AddToUndo(self.GetFirstNewUndoIndex(),"create link: " + str(linkobj.GetName()))    
04248                 linkobj.Create() #added to dirtylist
04249                 try:
04250                         my_id = self.GetSelectWindow().GetItemID(linkobj.GetType())
04251                         self.GetSelectWindow().AddItem(linkobj,TN_LINK)
04252                 except KeyError,err:
04253                         pass
04254  
04255         else: #cancel clicked
04256                 self.SetPreviousLinkNr() #we didnt use the given linknr, set to previous so that we can reuse this number
04257                 pass
04258 
04259         createlinkframe.Destroy()
04260 
04261     ##
04262     #  Open the modify link/connection window, let the user change properties
04263     #   for the link and connection, and add changes to dirty objects list if the
04264     #   user presses the Ok button.
04265     # 
04266     #   @obj - the object to modify (link), if not set, the active link is chosen
04267     #   @setfromnode - whether the node that is at the start of the link is given in @newnode, or the node at the end
04268     #   @newnode - either the device at the start of the link (@setfromnode=True), 
04269     #   or at the end of the link (@setfromnode=False)
04270     #   
04271     def ModifyLinkClick(self,event=None,obj=None,setfromnode=True,newnode=None):
04272 
04273         my_activesystem = self.GetActiveSystem()
04274         if my_activesystem == None or my_activesystem == "":
04275                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04276                 return False
04277 
04278         if event != None:
04279                 my_activelink = self.GetActiveLink()
04280                 if my_activelink == None or my_activelink == "":
04281                         self.ShowError("No link selected!",ERR_ERROR)
04282                         return False
04283 
04284                 link_tmp = Link(my_activesystem,my_activelink,False,False)
04285         else:
04286                 link_tmp = obj
04287 
04288         my_subsystem = SubSystem(self.__cfg,my_activesystem)
04289         my_linktypes = my_subsystem.GetLinkTypes()
04290         my_devtypes = my_subsystem.GetDeviceTypes()
04291 
04292         if my_linktypes == False or my_devtypes == False:
04293                 self.ShowError(my_subsystem.GetErrorMessage(),ERR_ERROR)
04294                 return False
04295 
04296         if obj:
04297                 if setfromnode:
04298                         if obj.GetNodeTo()  == newnode.GetName():
04299                                 self.ShowError("You cannot connect a device to itself!",ERR_ERROR)
04300                                 return False
04301                 else:
04302                         if obj.GetNodeFrom() == newnode.GetName():
04303                                 self.ShowError("You cannot connect a device to itself!",ERR_ERROR)
04304                                 return False
04305 
04306         createlinkframe = CreateLinkWindow(self,-1,my_activesystem,False,link_tmp,my_linktypes,my_devtypes,setfromnode,newnode)
04307                                                                                                                                                                        
04308         #show modify link window, and retrieve values
04309         if createlinkframe.ShowModal() == wxID_OK: #retrieve values from the window
04310                 # It is not possible to modify a link in the ConfDB, therefore we do a
04311                 # delete and then a create instead.
04312                 link_tmp = createlinkframe.GetLinkObj()
04313 
04314                 create_link = Link(link_tmp.GetSystem(),link_tmp.GetName(),False,True)
04315                 create_link.SetDict(link_tmp.GetObjectInfo(True))
04316 
04317                 obj = self.GetVisWindow().FindByName(create_link.GetName())
04318                 if obj:
04319                         self.GetVisWindow().DoDeleteObj(create_link.GetName(),False,refresh=False)
04320                 else:
04321                         obj = Link(create_link.GetSystem(),create_link.GetName(),False,True)
04322                         obj.SetDict(create_link.GetObjectInfo(True))
04323 
04324                 self.__visualundolist.append(obj)
04325 
04326                 self.GetVisWindow().CreateConnectedLink(create_link)
04327                 self.GetVisWindow().Refresh()
04328 
04329                 undoindex = self.GetFirstNewUndoIndex()
04330                 link_tmp.Delete() #added to dirtylist
04331                 create_link.Create()
04332                 # As you see, we never modify links, we always delete them and recreate them, do not think they will
04333                 # be modified that often, so no performance loss
04334                 self.AddToUndo(undoindex,"modify link: " + str(create_link.GetName()))
04335         else: #cancel clicked
04336                 pass
04337 
04338         createlinkframe.Destroy()
04339 
04340     ##
04341     #  A window pops up where the user can choose to delete a device
04342     #   type in the currently active subsystem. It is only device types that are not yet stored in the ConfDB
04343     #   that is shown, because it is not possible to delete device types stored in ConfDB.
04344     #   
04345     def DeleteDeviceTypeClick(self,event):
04346         
04347         my_activesystem = self.GetActiveSystem()
04348         if my_activesystem == None or my_activesystem == "":
04349                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04350                 return False
04351 
04352         tmp_system = SubSystem(self.__cfg,my_activesystem)
04353         my_devtypes = tmp_system.GetDeviceTypes(onlyfromdl=True)
04354 
04355         if my_devtypes == []: #no devtypes found
04356                 self.ShowError("No devicetypes found in: " + str(my_activesystem),ERR_ERROR)
04357                 return False
04358         elif my_devtypes == False:
04359                 self.ShowError("Could not find any devicetypes because an error occured: " + tmp_system.GetErrorMessage(),ERR_ERROR)
04360                 return False
04361 
04362         res = wxGetSingleChoice("Select a devicetype to delete from the single-selection listbox.","Delete Devicetype",my_devtypes,self)
04363         if res != "": #Not cancel
04364                 deltype = DeviceType(my_activesystem,res,False)
04365                 devs = deltype.GetDevices()
04366                 if devs == []: #no devices found, ok
04367                         undoindex = self.GetFirstNewUndoIndex()
04368                         deltype.Delete() #added to dirtylist
04369                         self.AddToUndo(undoindex,"delete devicetype: " + str(res))
04370                         try:
04371                                 #remove from treelist
04372                                 my_id = self.GetSelectWindow().GetItemID(res)
04373                                 self.GetSelectWindow().RemoveItem(my_id,"Device types") #link and device
04374                                 self.GetSelectWindow().SetItemToDeleted(deltype.GetName())
04375                         except KeyError,err:
04376                                 #print "treeitemid not found"
04377                                 pass
04378 
04379                         self.SetActiveDeviceType(None)
04380 
04381                 elif devs == False:
04382                         self.ShowError("Could not delete devicetype because an error occured: " + deltype.GetErrorMessage(),ERR_ERROR)
04383                 else: #found devices
04384                         self.ShowError("Could not delete devicetype because there are still devices in the database of the given devicetype.",ERR_ERROR)
04385 
04386     ##
04387     #  Calls the delete method in the visual window, that can delete visual objects. Links can
04388     #   be deleted at any time, but devices can only be deleted if they are not stored in ConfDB yet.
04389     #   TODO: check that the delete method in the visual window is working properly.
04390     #   
04391     def DeleteDeviceLinkClick(self,event):
04392         
04393         my_activesystem = self.GetActiveSystem()
04394         if my_activesystem == None or my_activesystem == "":
04395                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04396                 return False
04397 
04398         self.GetVisWindow().DoDelete(None,True,refresh=False) #both device and link
04399         self.GetVisWindow().Refresh()
04400 
04401     ##
04402     #  A window pops up where the user can choose to delete a link
04403     #   type in the currently active subsystem. It is only link types that are not yet stored in the ConfDB
04404     #   that is shown, because it is not possible to delete link types stored in ConfDB.
04405     #   
04406     def DeleteLinkTypeClick(self,event):
04407 
04408         my_activesystem = self.GetActiveSystem()
04409         if my_activesystem == None or my_activesystem == "":
04410                 self.ShowError("No subsystem is selected!",ERR_ERROR)
04411                 return False
04412 
04413         tmp_system = SubSystem(self.__cfg,my_activesystem)
04414         my_linktypes = tmp_system.GetLinkTypes(onlyfromdl=True)
04415         if my_linktypes == []: #no linktypes found
04416                 self.ShowError("No linktypes found in: " + str(my_activesystem),ERR_ERROR)
04417                 return False
04418         elif my_linktypes == False:
04419                 self.ShowError("Could not find any linktypes because an error occured: " + tmp_system.GetErrorMessage(),ERR_ERROR)
04420                 return False
04421 
04422         res = wxGetSingleChoice("Select a linktype to delete from the single-selection listbox.","Delete Linktype",my_linktypes,self)
04423         if res != "": #Not cancel
04424                 linktype = LinkType(my_activesystem,res,False)
04425                 #devs = deltype.GetLinks()
04426                 links = True #temp cause we don\t have the abovegiven function yet..ask Lana
04427 
04428                 if links == []: #no devices found, ok
04429                         undoindex = self.GetFirstNewUndoIndex()
04430                         linktype.Delete() #added to dirtylist
04431                         self.AddToUndo(undoindex,"delete linktype: " + str(res))        
04432                         try:
04433                                 #remove from treelist
04434                                 my_id = self.GetSelectWindow().GetItemID(res)
04435                                 self.GetSelectWindow().RemoveItem(my_id,"Link types") #link and device
04436                                 self.GetSelectWindow().SetItemToDeleted(linktype.GetName())
04437                         except KeyError,err:
04438                                 #print "treeitemid not found"
04439                                 pass
04440 
04441                         self.SetActiveLinkType(None)
04442 
04443                 elif links == False:
04444                         self.ShowError("Could not delete linktype because an error occured: " + linktype.GetErrorMessage(),ERR_ERROR)
04445                 else: #found devices
04446                         self.ShowError("Could not delete linktype because there are still links in the database of the given linktype.",ERR_ERROR)
04447 
04448     ##
04449     #  Readct on Test/Test menu action
04450     #             Call a function to test their functionality.
04451     #       Just for debugging.
04452     #         
04453     def OnTest(self, event):
04454         print "Dirty list: " + str(self.__dirtyobjects)
04455         #print "Is there anything to store?: " + str(self.IsSaveListEmpty()) + " 0: Yes, 1: No"
04456 
04457         print "UNDO list: " + str(self.__undolist)
04458         print "Visual UNDO Objects: " + str(self.__visualundolist)
04459 
04460         print "REDO objects: " + str(self.__redoobjectlist)
04461         print "REDO list: " + str(self.__redolist)
04462         print "Visual REDO Objects: " + str(self.__visualredolist)
04463         #print "Renamed objs, old db names: " + str(self.__oldnamesrenamed)
04464 
04465         for itm in self.__dirtyobjects:
04466                 print "Status: " + str(itm.GetObjectInfo(True))
04467 
04468         #print "Visual Contents: " + str(self.GetVisWindow().GetContents())
04469         #print "Selected Contents: " + str(self.GetVisWindow().GetSelection())
04470 
04471 
04472     ##
04473     #  Return reference (handle) to the wxConfig file object.
04474     # 
04475     #   !return - reference to the wxConfig file object.        
04476     #         
04477     def GetCfg(self):
04478         return self.__cfg
04479 
04480     ##
04481     #  Get the handle/reference to the miniature window
04482     # 
04483     #   !return - the reference to the miniature window
04484     #   
04485     def GetAreaWindow(self):
04486         return self.panel.GetAreaWindow()
04487     
04488     ##
04489     #  Return handle/reference to the visuali window
04490     #   
04491     #   !return - the reference to the visual window
04492     #         
04493     def GetVisWindow(self):
04494         
04495         return self.panel.GetVisWindow()
04496     
04497     ##
04498     #  Return handle/reference to the selection window
04499     # 
04500     #   !return - the reference to the selection window
04501     #         
04502     def GetSelectWindow(self):
04503         
04504         return self.panel.GetSelectWindow()
04505 
04506     ##
04507     # Inform other windows that the state of the database changed
04508     #         Inherited from dbUpdate interface class
04509     # 
04510     #   @evtReason - constant telling the current state of the ConfDB (DB_CONNECTED,DB_DISCONNECTED)
04511     #         
04512     def DbUpdate(self, evtReason):
04513         
04514         self.OnDbUpdate(evtReason, self.GetCdb())
04515         #walprob : j'ai pas encore defini tous les bouttons pour les disabler
04516         self.panel.OnDbUpdate(evtReason, self.GetCdb())
04517 
04518     ##
04519     #  React on database state change event
04520     #         Inherited from dbUpdate interface class
04521     # 
04522     #   @evtReason - constant telling the current state of the ConfDB (DB_CONNECTED or DB_DISCONNECTED)
04523     #   @cdb - the ConfDB instance
04524     #         
04525     def OnDbUpdate(self, evtReason, cdb):
04526         
04527         if evtReason == DB_DISCONNECTED:
04528                 #CREATE
04529                 pass
04530                 '''self.GetMenuBar().Enable(ID_CREATE_DEVICETYPE,False)
04531                 self.GetMenuBar().Enable(ID_CREATE_DEVICE,False)
04532                 self.GetMenuBar().Enable(ID_CREATE_LINKTYPE,False)
04533                 self.GetMenuBar().Enable(ID_CREATE_LINK,False)
04534                 #MODIFY
04535                 self.GetMenuBar().Enable(ID_MODIFY_DEVICETYPE,False)
04536                 self.GetMenuBar().Enable(ID_MODIFY_DEVICE,False)
04537                 self.GetMenuBar().Enable(ID_MODIFY_LINKTYPE,False)
04538                 self.GetMenuBar().Enable(ID_MODIFY_LINK,False)
04539 
04540                 #DELETE
04541                 self.GetMenuBar().Enable(ID_DELETE_DEVICETYPE,False)
04542                 self.GetMenuBar().Enable(ID_DELETE_DEVICE,False)
04543                 self.GetMenuBar().Enable(ID_DELETE_LINKTYPE,False)
04544 
04545                 #TOOLBAR
04546                 self.GetToolBar().EnableTool(NAVIGATE_TOGGLE_BUTTON,False)
04547                 self.GetToolBar().EnableTool(CREATE_TOGGLE_BUTTON,False)
04548                 self.GetToolBar().EnableTool(COPY_TOGGLE_BUTTON,False)
04549                 self.GetToolBar().EnableTool(PASTE_TOGGLE_BUTTON,False)
04550                 self.GetToolBar().EnableTool(DELETE_TOGGLE_BUTTON,False)
04551                 self.GetToolBar().EnableTool(SAVE_TOGGLE_BUTTON,False)
04552 
04553                 self.GetToolBar().EnableTool(ZOOMIN_BUTTON,False)
04554                 self.GetToolBar().EnableTool(ZOOMOUT_BUTTON,False)
04555                 self.GetToolBar().EnableTool(CUSTOMZOOM_BUTTON,False)
04556 
04557                 self.GetToolBar().FindControl(DEVTYPE_COMBOBOX).Enable(False)
04558                 self.GetToolBar().FindControl(LINKTYPE_COMBOBOX).Enable(False)
04559                 self.GetToolBar().FindControl(DEVTYPE_BUTTON).Enable(False)
04560                 self.GetToolBar().FindControl(LINKTYPE_BUTTON).Enable(False)
04561 
04562                 self.GetToolBar().EnableTool(NEIGHBOUR_BUTTON,False)
04563                 self.GetToolBar().EnableTool(PATH_BUTTON,False)
04564                 self.GetToolBar().EnableTool(DYNAMICLINK_BUTTON,False)
04565                 self.GetToolBar().EnableTool(SUBSYSTEM_BUTTON,False)
04566 
04567                 self.GetToolBar().EnableTool(LEVEL_DOWN_BTN,False)
04568                 self.GetToolBar().EnableTool(LEVEL_UP_BTN,False)
04569                 
04570                 self.GetMenuBar().EnableTop(1,False) #edit
04571                 self.GetMenuBar().EnableTop(2,False) #view
04572                 self.GetMenuBar().EnableTop(6,False) #visual
04573                 self.GetMenuBar().EnableTop(7,False) #test'''
04574                 
04575         else: # Connected
04576                 #CREATE
04577                 '''self.GetMenuBar().Enable(ID_CREATE_DEVICETYPE,True)
04578                 self.GetMenuBar().Enable(ID_CREATE_DEVICE,True)
04579                 self.GetMenuBar().Enable(ID_CREATE_LINKTYPE,True)
04580                 self.GetMenuBar().Enable(ID_CREATE_LINK,True)
04581                 #MODIFY
04582                 self.GetMenuBar().Enable(ID_MODIFY_DEVICETYPE,True)
04583                 self.GetMenuBar().Enable(ID_MODIFY_DEVICE,True)
04584                 self.GetMenuBar().Enable(ID_MODIFY_LINKTYPE,True)
04585                 self.GetMenuBar().Enable(ID_MODIFY_LINK,True)
04586                 #DELETE
04587                 self.GetMenuBar().Enable(ID_DELETE_DEVICETYPE,True)
04588                 self.GetMenuBar().Enable(ID_DELETE_DEVICE,True)
04589                 self.GetMenuBar().Enable(ID_DELETE_LINKTYPE,True)
04590                 
04591                 self.GetToolBar().EnableTool(NEIGHBOUR_BUTTON,True)
04592                 self.GetToolBar().EnableTool(PATH_BUTTON,True)
04593                 self.GetToolBar().EnableTool(DYNAMICLINK_BUTTON,True)
04594                 self.GetToolBar().EnableTool(SUBSYSTEM_BUTTON,True)
04595                 
04596                 self.GetMenuBar().EnableTop(2,True) #Test
04597                 self.GetMenuBar().EnableTop(6,True) #visual
04598                 self.GetMenuBar().EnableTop(7,True) #Test
04599                 '''
04600 
04601 
04602 
04603 

Generated on Fri Aug 31 11:11:15 2007 for CDBVis by  doxygen 1.5.3