diff options
Diffstat (limited to 'src/frontEnd')
-rw-r--r-- | src/frontEnd/Application.py | 579 | ||||
-rw-r--r-- | src/frontEnd/DockArea.py | 63 | ||||
-rw-r--r-- | src/frontEnd/ProjectExplorer.py | 128 | ||||
-rw-r--r-- | src/frontEnd/Workspace.py | 74 | ||||
-rw-r--r-- | src/frontEnd/pathmagic.py | 1 |
5 files changed, 573 insertions, 272 deletions
diff --git a/src/frontEnd/Application.py b/src/frontEnd/Application.py index 4f77a321..92013409 100644 --- a/src/frontEnd/Application.py +++ b/src/frontEnd/Application.py @@ -1,5 +1,4 @@ # ========================================================================= -# # FILE: Application.py # # USAGE: --- @@ -11,11 +10,13 @@ # BUGS: --- # NOTES: --- # AUTHOR: Fahim Khan, fahim.elex@gmail.com +# MODIFIED: Rahul Paknikar, rahulp@iitb.ac.in # ORGANIZATION: eSim team at FOSSEE, IIT Bombay. -# CREATED: Wednesday 21 January 2015 -# REVISION: --- +# CREATED: Tuesday 24 February 2015 +# REVISION: Friday 14 February 2020 # ========================================================================= -import pathmagic # noqa + +from frontEnd import pathmagic # noqa from PyQt4 import QtGui, QtCore from configuration.Appconfig import Appconfig from projManagement.openProject import OpenProjectInfo @@ -30,11 +31,12 @@ import time from PyQt4.Qt import QSize import sys import os +import shutil # Its our main window of application. class Application(QtGui.QMainWindow): - """This class initializes all objects used in this file(Application.py).""" + """This class initializes all objects used in this file.""" global project_name def __init__(self, *args): @@ -43,6 +45,9 @@ class Application(QtGui.QMainWindow): # Calling __init__ of super class QtGui.QMainWindow.__init__(self, *args) + # Flag for mode of operation. Default is set to offline mode. + self.online_flag = False + # Creating require Object self.obj_workspace = Workspace.Workspace() self.obj_Mainview = MainView() @@ -59,58 +64,86 @@ class Application(QtGui.QMainWindow): self.obj_appconfig._app_heigth) self.setWindowTitle(self.obj_appconfig._APPLICATION) self.showMaximized() - self.setWindowIcon(QtGui.QIcon('../../images/logo.png')) - # self.show() + self.setWindowIcon(QtGui.QIcon('images/logo.png')) + self.systemTrayIcon = QtGui.QSystemTrayIcon(self) - self.systemTrayIcon.setIcon(QtGui.QIcon('../../images/logo.png')) + self.systemTrayIcon.setIcon(QtGui.QIcon('images/logo.png')) self.systemTrayIcon.setVisible(True) - # This function initializes Tool Bars def initToolBar(self): """ - In this function we are setting icons, short-cuts,and - defining functonality for: - - - Top-tool-bar (New project, Open project, Close project,\ - Help option ) - - Left-tool-bar (Open Schematic, Convert KiCad to NgSpice,\ - Simuation, Model Editor, Subcircuit, NGHDL, Modelica\ - Converter, OM Optimisation ) + This function initializes Tool Bars. + It setups the icons, short-cuts and defining functonality for: + + - Top-tool-bar (New project, Open project, Close project, \ + Mode switch, Help option) + - Left-tool-bar (Open Schematic, Convert KiCad to NgSpice, \ + Simuation, Model Editor, Subcircuit, NGHDL, Modelica \ + Converter, OM Optimisation) """ # Top Tool bar self.newproj = QtGui.QAction( - QtGui.QIcon('../../images/newProject.png'), - '<b>New Project</b>', - self) + QtGui.QIcon('images/newProject.png'), + '<b>New Project</b>', self + ) self.newproj.setShortcut('Ctrl+N') self.newproj.triggered.connect(self.new_project) - # self.newproj.connect(self.newproj, QtCore.SIGNAL('triggered()'), - # self, QtCore.SLOT(self.new_project())) self.openproj = QtGui.QAction( - QtGui.QIcon('../../images/openProject.png'), - '<b>Open Project</b>', - self) + QtGui.QIcon('images/openProject.png'), + '<b>Open Project</b>', self + ) self.openproj.setShortcut('Ctrl+O') self.openproj.triggered.connect(self.open_project) self.closeproj = QtGui.QAction( - QtGui.QIcon('../../images/closeProject.png'), - '<b>Close Project</b>', - self) + QtGui.QIcon('images/closeProject.png'), + '<b>Close Project</b>', self + ) self.closeproj.setShortcut('Ctrl+X') self.closeproj.triggered.connect(self.close_project) + self.wrkspce = QtGui.QAction( + QtGui.QIcon('images/workspace.ico'), + '<b>Change Workspace</b>', self + ) + self.wrkspce.setShortcut('Ctrl+W') + self.wrkspce.triggered.connect(self.change_workspace) + + self.switchmode = None + self.validate_mode() + if self.online_flag is True: + self.switchmode = QtGui.QAction(QtGui.QIcon( + 'images/online.png'), + '<b>Go Offline</b>', self + ) + elif self.online_flag is False: + self.switchmode = QtGui.QAction(QtGui.QIcon( + 'images/offline.png'), + '<b>Go Online</b>', self + ) + elif self.online_flag is None: + self.switchmode = QtGui.QAction(QtGui.QIcon( + 'images/disable.png'), + '<b>Mode switching has been disabled. ' + + 'Default mode set to offline</b>', self + ) + self.switchmode.setEnabled(False) + self.switchmode.setShortcut('Ctrl+G') + self.switchmode.triggered.connect(self.change_mode) + self.helpfile = QtGui.QAction( - QtGui.QIcon('../../images/helpProject.png'), '<b>Help</b>', self) + QtGui.QIcon('images/helpProject.png'), '<b>Help</b>', self + ) self.helpfile.setShortcut('Ctrl+H') self.helpfile.triggered.connect(self.help_project) self.topToolbar = self.addToolBar('Top Tool Bar') self.topToolbar.addAction(self.newproj) self.topToolbar.addAction(self.openproj) - self.topToolbar.addAction(self.closeproj) + self.topToolbar.addAction(self.wrkspce) + self.topToolbar.addAction(self.switchmode) self.topToolbar.addAction(self.helpfile) # This part is setting fossee logo to the right @@ -123,9 +156,8 @@ class Application(QtGui.QMainWindow): self.logo = QtGui.QLabel() self.logopic = QtGui.QPixmap( os.path.join( - os.path.abspath('../..'), - 'images', - 'fosseeLogo.png')) + os.path.abspath(''), 'images', 'fosseeLogo.png' + )) self.logopic = self.logopic.scaled( QSize(150, 150), QtCore.Qt.KeepAspectRatio) self.logo.setPixmap(self.logopic) @@ -134,51 +166,46 @@ class Application(QtGui.QMainWindow): # Left Tool bar Action Widget self.kicad = QtGui.QAction( - QtGui.QIcon('../../images/kicad.png'), - '<b>Open Schematic</b>', - self) + QtGui.QIcon('images/kicad.png'), + '<b>Open Schematic</b>', self + ) self.kicad.triggered.connect(self.obj_kicad.openSchematic) self.conversion = QtGui.QAction( - QtGui.QIcon('../../images/ki-ng.png'), - '<b>Convert Kicad to Ngspice</b>', - self) + QtGui.QIcon('images/ki-ng.png'), + '<b>Convert Kicad to Ngspice</b>', self + ) self.conversion.triggered.connect(self.obj_kicad.openKicadToNgspice) self.ngspice = QtGui.QAction( - QtGui.QIcon('../../images/ngspice.png'), - '<b>Simulation</b>', - self) + QtGui.QIcon('images/ngspice.png'), '<b>Simulation</b>', self + ) self.ngspice.triggered.connect(self.open_ngspice) self.model = QtGui.QAction( - QtGui.QIcon('../../images/model.png'), - '<b>Model Editor</b>', - self) + QtGui.QIcon('images/model.png'), '<b>Model Editor</b>', self + ) self.model.triggered.connect(self.open_modelEditor) self.subcircuit = QtGui.QAction( - QtGui.QIcon('../../images/subckt.png'), - '<b>Subcircuit</b>', - self) + QtGui.QIcon('images/subckt.png'), '<b>Subcircuit</b>', self + ) self.subcircuit.triggered.connect(self.open_subcircuit) self.nghdl = QtGui.QAction( - QtGui.QIcon('../../images/nghdl.png'), - '<b>Nghdl</b>', - self) + QtGui.QIcon('images/nghdl.png'), '<b>Nghdl</b>', self + ) self.nghdl.triggered.connect(self.open_nghdl) self.omedit = QtGui.QAction( - QtGui.QIcon('../../images/omedit.png'), - '<b>Modelica Converter</b>', - self) + QtGui.QIcon('images/omedit.png'), + '<b>Modelica Converter</b>', self + ) self.omedit.triggered.connect(self.open_OMedit) self.omoptim = QtGui.QAction( - QtGui.QIcon('../../images/omoptim.png'), - '<b>OM Optimisation</b>', - self) + QtGui.QIcon('images/omoptim.png'), '<b>OM Optimisation</b>', self + ) self.omoptim.triggered.connect(self.open_OMoptim) # Adding Action Widget to tool bar @@ -195,30 +222,30 @@ class Application(QtGui.QMainWindow): self.lefttoolbar.setOrientation(QtCore.Qt.Vertical) self.lefttoolbar.setIconSize(QSize(40, 40)) - # This function closes the ongoing program(process). def closeEvent(self, event): ''' - When exit button is pressed a Message box pops out with + This function closes the ongoing program (process). + When exit button is pressed a Message box pops out with \ exit message and buttons 'Yes', 'No'. 1. If 'Yes' is pressed: - - it checks that program(process) in procThread_list\ - (list made in Appconfig.py): + - check that program (process) in procThread_list \ + (a list made in Appconfig.py): - - if available it terminates that program - - if the program(process) is not available,\ - it checks for it - in process_obj (list made in Appconfig.py) if found it - closes the program. + - if available it terminates that program. + - if the program (process) is not available, \ + then check it in process_obj (a list made in \ + Appconfig.py) and if found, it closes the program. 2. If 'No' is pressed: - the program just continues as it was doing earlier. ''' - exit_msg = "Are you sure you want to exit the program?" \ - " All unsaved data will be lost." + exit_msg = "Are you sure you want to exit the program?" + exit_msg += " All unsaved data will be lost." reply = QtGui.QMessageBox.question( self, 'Message', exit_msg, QtGui.QMessageBox.Yes, - QtGui.QMessageBox.No) + QtGui.QMessageBox.No + ) if reply == QtGui.QMessageBox.Yes: for proc in self.obj_appconfig.procThread_list: @@ -234,8 +261,9 @@ class Application(QtGui.QMainWindow): pass except BaseException: pass - # Just checking if open project and New project window is open. If - # yes just close it when application is closed + + # Check if "Open project" and "New project" window is open. + # If yes, just close it when application is closed. try: self.project.close() except BaseException: @@ -246,15 +274,48 @@ class Application(QtGui.QMainWindow): elif reply == QtGui.QMessageBox.No: event.ignore() - # This function closes the saved project. + def new_project(self): + """This function call New Project Info class.""" + text, ok = QtGui.QInputDialog.getText( + self, 'New Project Info', 'Enter Project Name:' + ) + if ok: + self.projname = (str(text)) + self.project = NewProjectInfo() + directory, filelist = self.project.createProject(self.projname) + self.obj_Mainview.obj_projectExplorer.addTreeNode( + directory, filelist) + else: + print("No new project created") + self.obj_appconfig.print_info('No new project created') + try: + self.obj_appconfig.print_info( + 'Current project is : ' + + self.obj_appconfig.current_project["ProjectName"] + ) + except BaseException: + pass + + def open_project(self): + """This project call Open Project Info class.""" + print("Function : Open Project") + self.project = OpenProjectInfo() + try: + directory, filelist = self.project.body() + self.obj_Mainview.obj_projectExplorer.addTreeNode( + directory, filelist) + except BaseException: + pass + def close_project(self): """ - This function first checks whether project(file) is present in list. + This function closes the saved project. + It first checks whether project (file) is present in list. - If present: - it first kills that process-id. - closes that file. - - Shows message "Current project <path of file> is closed" + - Shows message "Current project <path_to_file> is closed" - If not present: pass """ @@ -272,60 +333,173 @@ class Application(QtGui.QMainWindow): self.obj_Mainview.obj_dockarea.closeDock() self.obj_appconfig.current_project['ProjectName'] = None self.systemTrayIcon.showMessage( - 'Close', - 'Current project ' + - os.path.basename(current_project) + - ' is Closed.') + 'Close', 'Current project ' + + os.path.basename(current_project) + ' is Closed.' + ) - # This function call New Project Info class. - def new_project(self): - text, ok = QtGui.QInputDialog.getText( - self, 'New Project Info', 'Enter Project Name:') - if ok: - self.projname = (str(text)) - self.project = NewProjectInfo() - directory, filelist = self.project.createProject(self.projname) + def change_workspace(self): + """ + This function call changes Workspace + """ + print("Function : Change Workspace") + self.obj_workspace.returnWhetherClickedOrNot(self) + self.hide() + self.obj_workspace.show() - self.obj_Mainview.obj_projectExplorer.addTreeNode( - directory, filelist) + def validate_mode(self): + """ + This functions checks whether proper fp-lib-table* files are \ + available or not. If not, then move appropriate files from \ + library/supportFiles folder and set `self.online_flag` accordingly. + @params + + @return + None + """ + remove = False + + if self.obj_appconfig.kicad_path is not None: + + if not os.path.exists( + self.obj_appconfig.kicad_path + "/fp-lib-table" + ): + remove = True + elif os.path.exists(self.obj_appconfig.kicad_path + + "/fp-lib-table-offline"): + if os.path.exists(self.obj_appconfig.kicad_path + + "/fp-lib-table-online"): + remove = True + os.remove(self.obj_appconfig.kicad_path + + "/fp-lib-table") + else: + self.online_flag = True + else: + if not os.path.exists(self.obj_appconfig.kicad_path + + "/fp-lib-table-online"): + remove = True + os.remove(self.obj_appconfig.kicad_path + + "/fp-lib-table") + else: + self.online_flag = False + + if remove: + # Remove invalid files + if os.path.exists( + self.obj_appconfig.kicad_path + "/fp-lib-table-offline" + ): + os.remove(self.obj_appconfig.kicad_path + + "/fp-lib-table-offline") + + if os.path.exists( + self.obj_appconfig.kicad_path + "/fp-lib-table-online" + ): + os.remove(self.obj_appconfig.kicad_path + + "/fp-lib-table-online") + + # Restore original files + shutil.copy('library/supportFiles/fp-lib-table-online', + self.obj_appconfig.kicad_path + "/") + shutil.copy('library/supportFiles/fp-lib-table', + self.obj_appconfig.kicad_path + "/") + + self.online_flag = False else: - print("No new project created") - self.obj_appconfig.print_info('No new project created') - try: - self.obj_appconfig.print_info( - 'Current project is : ' + - self.obj_appconfig.current_project["ProjectName"]) - except BaseException: - pass + self.online_flag = None - # This project call Open Project Info class - def open_project(self): - print("Function : Open Project") - self.project = OpenProjectInfo() + def change_mode(self): + """ + - This function is used for changing mode of operation for KiCad. \ + - There are three modes of operation : + - online + - offline + - disable + + - If none of the KiCad tools (associated with eSim) are \ + open, then validate this mode by calling the function \ + `validate_mode` and depending on online_flag, swap \ + appropriate fp-lib-table files. + - If any of the KiCad tools (associated with eSim) is open, \ + then ask user to close all these tools. + - If `online_flag` is `None`, then disable this feature. + + @params + + @return + None + """ + if not self.obj_kicad.check_open_schematic(): + self.validate_mode() + if self.online_flag is True: + os.rename( + self.obj_appconfig.kicad_path + "/fp-lib-table", + self.obj_appconfig.kicad_path + + "/fp-lib-table-online" + ) + os.rename( + self.obj_appconfig.kicad_path + + "/fp-lib-table-offline", + self.obj_appconfig.kicad_path + "/fp-lib-table" + ) + self.switchmode.setIcon( + QtGui.QIcon('images/offline.png') + ) + self.switchmode.setText('<b>Go Online</b>') + self.switchmode.setEnabled(True) + self.online_flag = False + + elif self.online_flag is False: + os.rename( + self.obj_appconfig.kicad_path + "/fp-lib-table", + self.obj_appconfig.kicad_path + + "/fp-lib-table-offline" + ) + os.rename( + self.obj_appconfig.kicad_path + + "/fp-lib-table-online", + self.obj_appconfig.kicad_path + "/fp-lib-table" + ) + self.switchmode.setIcon( + QtGui.QIcon('images/online.png') + ) + self.switchmode.setText('<b>Go Offline</b>') + self.switchmode.setEnabled(True) + self.online_flag = True - try: - directory, filelist = self.project.body() - self.obj_Mainview.obj_projectExplorer.addTreeNode( - directory, filelist) - except BaseException: - pass + elif self.online_flag is None: + self.switchmode.setIcon( + QtGui.QIcon('images/disable.png') + ) + self.switchmode.setText( + '<b>Mode switching has been ' + + 'disabled. Default mode set to offline</b>.' + ) + self.switchmode.setEnabled(False) + else: + self.msg = QtGui.QErrorMessage() + self.msg.setWindowTitle("Error Message") + self.msg.setModal(True) + self.msg.showMessage( + 'Please save and close all the Kicad ' + + 'windows first, then change the mode' + ) + self.msg.exec_() - # This page opens usermanual in dockarea. def help_project(self): """ - - It prints the message ""Function : Help"" - - Uses print_info() method of class Appconfig - from Configuration/Appconfig.py file. - - Call method usermanual() from ./DockArea.py. + This function opens usermanual in dockarea. + - It prints the message ""Function : Help"" + - Uses print_info() method of class Appconfig + from Configuration/Appconfig.py file. + - Call method usermanual() from ./DockArea.py. """ print("Function : Help") self.obj_appconfig.print_info('Help is called') print("Current Project is : ", self.obj_appconfig.current_project) self.obj_Mainview.obj_dockarea.usermanual() - # This Function execute ngspice on current project. def open_ngspice(self): + """This Function execute ngspice on current project.""" self.projDir = self.obj_appconfig.current_project["ProjectName"] if self.projDir is not None: @@ -340,37 +514,44 @@ class Application(QtGui.QMainWindow): break except Exception: pass - time.sleep(0.2) + time.sleep(0.5) # Fail Safe ===> count += 1 - if count >= 100: + if count >= 10: raise Exception( - "ngspice taking too long, check netlist file") + "Ngspice taking too long for simulation. " + "Check netlist file to change simulation parameters." + ) # Calling Python Plotting - try: self.obj_Mainview.obj_dockarea.plottingEditor() except Exception as e: - self.msg = QtGui.QErrorMessage(None) + self.msg = QtGui.QErrorMessage() + self.msg.setModal(True) + self.msg.setWindowTitle("Error Message") self.msg.showMessage( 'Error while opening python plotting Editor.' - ' Please look at console for more details') + ' Please look at console for more details.' + ) + self.msg.exec_() print("Exception Message:", str(e)) self.obj_appconfig.print_error('Exception Message : ' + str(e)) - self.msg.setWindowTitle("Error Message") else: self.msg = QtGui.QErrorMessage() + self.msg.setModal(True) + self.msg.setWindowTitle("Error Message") self.msg.showMessage( 'Please select the project first.' - ' You can either create new project or open existing project') - self.msg.setWindowTitle("Error Message") + ' You can either create new project or open existing project' + ) + self.msg.exec_() - # This function opens 'subcircuit' option in left-tool-bar. def open_subcircuit(self): """ + This function opens 'subcircuit' option in left-tool-bar. When 'subcircuit' icon is clicked wich is present in left-tool-bar of main page: @@ -382,36 +563,36 @@ class Application(QtGui.QMainWindow): self.obj_appconfig.print_info('Subcircuit editor is called') self.obj_Mainview.obj_dockarea.subcircuiteditor() - # This function calls NGHDl option in left-tool-bar. def open_nghdl(self): """ - This function uses validateTool() method from - Validation.py: + This function calls NGHDL option in left-tool-bar. + It uses validateTool() method from Validation.py: - If 'nghdl' is present in executables list then - it adds passes command 'nghdl -e' to WorkerThread class of + it passes command 'nghdl -e' to WorkerThread class of Worker.py. - - If 'nghdl' not present then it shows error message. + - If 'nghdl' is not present, then it shows error message. """ - print("Function : Nghdl") - self.obj_appconfig.print_info('Nghdl is called') + print("Function : NGHDL") + self.obj_appconfig.print_info('NGHDL is called') if self.obj_validation.validateTool('nghdl'): self.cmd = 'nghdl -e' self.obj_workThread = Worker.WorkerThread(self.cmd) self.obj_workThread.start() - else: - self.msg = QtGui.QErrorMessage(None) - self.msg.showMessage('Error while opening nghdl.\ - Please make sure nghdl is installed') - self.obj_appconfig.print_error('Error while opening nghdl.\ - Please make sure nghdl is installed') - self.msg.setWindowTitle('nghdl Error Message') - - # This function opens model editor option in left-tool-bar. + self.msg = QtGui.QErrorMessage() + self.msg.setModal(True) + self.msg.setWindowTitle('NGHDL Error') + self.msg.showMessage('Error while opening NGHDL. ' + + 'Please make sure it is installed') + self.obj_appconfig.print_error('Error while opening NGHDL. ' + + 'Please make sure it is installed') + self.msg.exec_() + def open_modelEditor(self): """ + This function opens model editor option in left-tool-bar. When model editor icon is clicked which is present in left-tool-bar of main page: @@ -423,50 +604,100 @@ class Application(QtGui.QMainWindow): self.obj_appconfig.print_info('Model editor is called') self.obj_Mainview.obj_dockarea.modelEditor() - # This function call ngspice to OM edit converter - # and then launch OM edit. def open_OMedit(self): - self.obj_appconfig.print_info('OM edit is called') + """ + This function calls ngspice to OMEdit converter and then launch OMEdit. + """ + self.obj_appconfig.print_info('OMEdit is called') self.projDir = self.obj_appconfig.current_project["ProjectName"] if self.projDir is not None: if self.obj_validation.validateCirOut(self.projDir): self.projName = os.path.basename(self.projDir) self.ngspiceNetlist = os.path.join( - self.projDir, self.projName + ".cir.out") + self.projDir, self.projName + ".cir.out" + ) self.modelicaNetlist = os.path.join( - self.projDir, self.projName + ".mo") + self.projDir, self.projName + ".mo" + ) + + """ + try: + # Creating a command for Ngspice to Modelica converter + self.cmd1 = " + python3 ../ngspicetoModelica/NgspicetoModelica.py "\ + +self.ngspiceNetlist + self.obj_workThread1 = Worker.WorkerThread(self.cmd1) + self.obj_workThread1.start() + if self.obj_validation.validateTool("OMEdit"): + # Creating command to run OMEdit + self.cmd2 = "OMEdit "+self.modelicaNetlist + self.obj_workThread2 = Worker.WorkerThread(self.cmd2) + self.obj_workThread2.start() + else: + self.msg = QtGui.QMessageBox() + self.msgContent = "There was an error while + opening OMEdit.<br/>\ + Please make sure OpenModelica is installed in your\ + system. <br/>\ + To install it on Linux : Go to\ + <a href=https://www.openmodelica.org/download/\ + download-linux>OpenModelica Linux</a> and \ + install nigthly build release.<br/>\ + To install it on Windows : Go to\ + <a href=https://www.openmodelica.org/download/\ + download-windows>OpenModelica Windows</a>\ + and install latest version.<br/>" + self.msg.setTextFormat(QtCore.Qt.RichText) + self.msg.setText(self.msgContent) + self.msg.setWindowTitle("Missing OpenModelica") + self.obj_appconfig.print_info(self.msgContent) + self.msg.exec_() + + except Exception as e: + self.msg = QtGui.QErrorMessage() + self.msg.setModal(True) + self.msg.setWindowTitle( + "Ngspice to Modelica conversion error") + self.msg.showMessage( + 'Unable to convert NgSpice netlist to\ + Modelica netlist :'+str(e)) + self.msg.exec_() + self.obj_appconfig.print_error(str(e)) + """ self.obj_Mainview.obj_dockarea.modelicaEditor(self.projDir) else: self.msg = QtGui.QErrorMessage() - self.msg.showMessage( - 'Current project does not contain any ngspice file.\ - Please create ngspice file with extension .cir.out') + self.msg.setModal(True) self.msg.setWindowTitle("Missing Ngspice netlist") + self.msg.showMessage( + 'Current project does not contain any Ngspice file. ' + + 'Please create Ngspice file with extension .cir.out' + ) + self.msg.exec_() else: self.msg = QtGui.QErrorMessage() - self.msg.showMessage( - 'Please select the project first.\ - You can either create new project\ - or open existing project') + self.msg.setModal(True) self.msg.setWindowTitle("Error Message") + self.msg.showMessage( + 'Please select the project first. ' + + 'You can either create a new project or open existing project' + ) + self.exec_() - # sdf def open_OMoptim(self): """ - This function uses validateTool() method from - Validation.py: + This function uses validateTool() method from Validation.py: - If 'OMOptim' is present in executables list then - it adds passes command 'OMOptim' to WorkerThread class of - Worker.py. - - If 'OMOptim' not present then it shows error message with + it passes command 'OMOptim' to WorkerThread class of Worker.py + - If 'OMOptim' is not present, then it shows error message with link to download it on Linux and Windows. """ - print("Function : OM Optim") - self.obj_appconfig.print_info('OM Optim is called') + print("Function : OMOptim") + self.obj_appconfig.print_info('OMOptim is called') # Check if OMOptim is installed if self.obj_validation.validateTool("OMOptim"): # Creating a command to run @@ -486,7 +717,7 @@ class Application(QtGui.QMainWindow): "To install it on Windows : Go to <a href=" "https://www.openmodelica.org/download/download-windows" ">OpenModelica Windows</a> and install latest version.<br/>" - ) + ) self.msg.setTextFormat(QtCore.Qt.RichText) self.msg.setText(self.msgContent) self.msg.setWindowTitle("Error Message") @@ -500,14 +731,11 @@ class MainView(QtGui.QWidget): This class defines whole view and style of main page: - Position of tool bars: - - - Top tool bar. - - Left tool bar. - + - Top tool bar. + - Left tool bar. - Project explorer Area. - Dock area. - Console area. - """ def __init__(self, *args): @@ -561,7 +789,7 @@ class MainView(QtGui.QWidget): self.setLayout(self.mainLayout) -# It is main function of the module.It starts the application +# It is main function of the module and starts the application def main(args): """ The splash screen opened at the starting of screen is performed @@ -570,21 +798,32 @@ def main(args): print("Starting eSim......") app = QtGui.QApplication(args) - splash_pix = QtGui.QPixmap('../../images/splash_screen_esim.png') + splash_pix = QtGui.QPixmap('images/splash_screen_esim.png') splash = QtGui.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) splash.setMask(splash_pix.mask()) splash.show() appView = Application() appView.splash = splash appView.obj_workspace.returnWhetherClickedOrNot(appView) - appView.hide() - appView.obj_workspace.show() - sys.exit(app.exec_()) + try: + file = open(os.path.join( + os.path.expanduser("~"), ".esim/workspace.txt"), 'r' + ) + work = int(file.read(1)) + file.close() + except IOError: + work = 0 + if work != 0: + appView.obj_workspace.defaultWorkspace() + else: + appView.hide() + appView.obj_workspace.show() -# Call main function + sys.exit(app.exec_()) +# Call main function if __name__ == '__main__': # Create and display the splash screen main(sys.argv) diff --git a/src/frontEnd/DockArea.py b/src/frontEnd/DockArea.py index 0aa8ff17..b8ebfac4 100644 --- a/src/frontEnd/DockArea.py +++ b/src/frontEnd/DockArea.py @@ -15,7 +15,6 @@ count = 1 dock = {} -# class DockArea(QtGui.QMainWindow): """ This class contains function for designing UI of all the editors @@ -24,8 +23,8 @@ class DockArea(QtGui.QMainWindow): - Test Editor. - Model Editor. - Python Plotting. - - NgSpice Editor. - - Kicad to NgSpice Editor. + - Ngspice Editor. + - Kicad to Ngspice Editor. - Subcircuit Editor. - Modelica editor. """ @@ -55,8 +54,9 @@ class DockArea(QtGui.QMainWindow): self.show() def createTestEditor(self): - """This function create widget for Library Editor.""" + """This function create widget for Library Editor""" global count + self.testWidget = QtGui.QWidget() self.testArea = QtGui.QTextEdit() self.testLayout = QtGui.QVBoxLayout() @@ -77,15 +77,17 @@ class DockArea(QtGui.QMainWindow): dock['Tips-' + str(count)].raise_() temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['Tips-' + str(count)]) + if temp: + self.obj_appconfig.dock_dict[temp].append( + dock['Tips-' + str(count)] + ) count = count + 1 def plottingEditor(self): - """This function create widget for interactive PythonPlotting""" + """This function create widget for interactive PythonPlotting.""" self.projDir = self.obj_appconfig.current_project["ProjectName"] self.projName = os.path.basename(self.projDir) - # self.project = os.path.join(self.projDir,self.projName) + # self.project = os.path.join(self.projDir, self.projName) global count self.plottingWidget = QtGui.QWidget() @@ -107,12 +109,14 @@ class DockArea(QtGui.QMainWindow): dock['Plotting-' + str(count)].raise_() temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['Plotting-' + str(count)]) + if temp: + self.obj_appconfig.dock_dict[temp].append( + dock['Plotting-' + str(count)] + ) count = count + 1 def ngspiceEditor(self, projDir): - """Sdf.""" + """ This function creates widget for Ngspice window.""" self.projDir = projDir self.projName = os.path.basename(self.projDir) self.ngspiceNetlist = os.path.join( @@ -123,9 +127,8 @@ class DockArea(QtGui.QMainWindow): self.ngspiceLayout = QtGui.QVBoxLayout() self.ngspiceLayout.addWidget( - NgspiceWidget( - self.ngspiceNetlist, - self.projDir)) + NgspiceWidget(self.ngspiceNetlist, self.projDir) + ) # Adding to main Layout self.ngspiceWidget.setLayout(self.ngspiceLayout) @@ -145,9 +148,12 @@ class DockArea(QtGui.QMainWindow): dock['NgSpice-' + str(count)].setVisible(True) dock['NgSpice-' + str(count)].setFocus() dock['NgSpice-' + str(count)].raise_() + temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['NgSpice-' + str(count)]) + if temp: + self.obj_appconfig.dock_dict[temp].append( + dock['NgSpice-' + str(count)] + ) count = count + 1 def modelEditor(self): @@ -180,15 +186,11 @@ class DockArea(QtGui.QMainWindow): dock['Model Editor-' + str(count)].setFocus() dock['Model Editor-' + str(count)].raise_() - temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['Model Editor-' + str(count)]) count = count + 1 def kicadToNgspiceEditor(self, clarg1, clarg2=None): """ - This function is creating Editor UI for- - Kicad to Ngspice conversion. + This function is creating Editor UI for Kicad to Ngspice conversion. """ global count self.kicadToNgspiceWidget = QtGui.QWidget() @@ -214,10 +216,13 @@ class DockArea(QtGui.QMainWindow): dock['kicadToNgspice-' + str(count)].setVisible(True) dock['kicadToNgspice-' + str(count)].setFocus() dock['kicadToNgspice-' + str(count)].raise_() + dock['kicadToNgspice-' + str(count)].activateWindow() temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['kicadToNgspice-' + str(count)]) + if temp: + self.obj_appconfig.dock_dict[temp].append( + dock['kicadToNgspice-' + str(count)] + ) count = count + 1 def subcircuiteditor(self): @@ -246,12 +251,10 @@ class DockArea(QtGui.QMainWindow): dock['Subcircuit-' + str(count)].setFocus() dock['Subcircuit-' + str(count)].raise_() - temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['Subcircuit-' + str(count)]) count = count + 1 def usermanual(self): + """This function creates a widget for user manual.""" global count self.usermanualWidget = QtGui.QWidget() self.usermanualLayout = QtGui.QVBoxLayout() @@ -279,7 +282,7 @@ class DockArea(QtGui.QMainWindow): count = count + 1 def modelicaEditor(self, projDir): - """Dfg.""" + """This function sets up the UI for ngspice to modelica conversion.""" global count self.modelicaWidget = QtGui.QWidget() self.modelicaLayout = QtGui.QVBoxLayout() @@ -303,8 +306,10 @@ class DockArea(QtGui.QMainWindow): padding: 5px; width: 200px; height: 150px; } \ ") temp = self.obj_appconfig.current_project['ProjectName'] - self.obj_appconfig.dock_dict[temp].append( - dock['Modelica-' + str(count)]) + if temp: + self.obj_appconfig.dock_dict[temp].append( + dock['Modelica-' + str(count)] + ) count = count + 1 diff --git a/src/frontEnd/ProjectExplorer.py b/src/frontEnd/ProjectExplorer.py index 4627d294..c733c9b1 100644 --- a/src/frontEnd/ProjectExplorer.py +++ b/src/frontEnd/ProjectExplorer.py @@ -35,20 +35,22 @@ class ProjectExplorer(QtGui.QWidget): # CSS self.treewidget.setStyleSheet(" \ + QTreeView { border-radius: 15px; border: 1px \ + solid gray; padding: 5px; width: 200px; height: 150px; }\ QTreeView::branch:has-siblings:!adjoins-item { \ - border-image: url(../../images/vline.png) 0;} \ + border-image: url(images/vline.png) 0;} \ QTreeView::branch:has-siblings:adjoins-item { \ - border-image: url(../../images/branch-more.png) 0; } \ + border-image: url(images/branch-more.png) 0; } \ QTreeView::branch:!has-children:!has-siblings:adjoins-item { \ - border-image: url(../../images/branch-end.png) 0; } \ + border-image: url(images/branch-end.png) 0; } \ QTreeView::branch:has-children:!has-siblings:closed, \ QTreeView::branch:closed:has-children:has-siblings { \ border-image: none; \ - image: url(../../images/branch-closed.png); } \ + image: url(images/branch-closed.png); } \ QTreeView::branch:open:has-children:!has-siblings, \ QTreeView::branch:open:has-children:has-siblings { \ border-image: none; \ - image: url(../../images/branch-open.png); } \ + image: url(images/branch-open.png); } \ ") for parents, children in list( @@ -61,7 +63,8 @@ class ProjectExplorer(QtGui.QWidget): ) for files in children: QtGui.QTreeWidgetItem( - parentnode, [files, os.path.join(parents, files)]) + parentnode, [files, os.path.join(parents, files)] + ) self.window.addWidget(self.treewidget) self.treewidget.doubleClicked.connect(self.openProject) @@ -74,7 +77,8 @@ class ProjectExplorer(QtGui.QWidget): os.path.join(parents) pathlist = parents.split(os.sep) parentnode = QtGui.QTreeWidgetItem( - self.treewidget, [pathlist[-1], parents]) + self.treewidget, [pathlist[-1], parents] + ) for files in children: QtGui.QTreeWidgetItem( parentnode, [files, os.path.join(parents, files)] @@ -90,7 +94,6 @@ class ProjectExplorer(QtGui.QWidget): ) = [] def openMenu(self, position): - indexes = self.treewidget.selectedIndexes() if len(indexes) > 0: level = 0 @@ -101,6 +104,8 @@ class ProjectExplorer(QtGui.QWidget): menu = QtGui.QMenu() if level == 0: + renameProject = menu.addAction(self.tr("Rename Project")) + renameProject.triggered.connect(self.renameProject) deleteproject = menu.addAction(self.tr("Remove Project")) deleteproject.triggered.connect(self.removeProject) refreshproject = menu.addAction(self.tr("Refresh")) @@ -115,9 +120,8 @@ class ProjectExplorer(QtGui.QWidget): self.indexItem = self.treewidget.currentIndex() filename = str(self.indexItem.data()) self.filePath = str( - self.indexItem.sibling( - self.indexItem.row(), - 1).data()) + self.indexItem.sibling(self.indexItem.row(), 1).data() + ) self.obj_appconfig.print_info( 'The current project is ' + self.filePath) @@ -130,16 +134,15 @@ class ProjectExplorer(QtGui.QWidget): self.save = QtGui.QPushButton('Save and Exit') self.save.setDisabled(True) self.windowgrid = QtGui.QGridLayout() - # if (os.path.isfile(str(self.filePath))) == True: + if (os.path.isfile(str(self.filePath))): self.fopen = open(str(self.filePath), 'r') lines = self.fopen.read() self.text.setText(lines) QtCore.QObject.connect( - self.text, - QtCore.SIGNAL("textChanged()"), - self.enable_save) + self.text, QtCore.SIGNAL("textChanged()"), self.enable_save + ) vbox_main = QtGui.QVBoxLayout(self.textwindow) vbox_main.addWidget(self.text) @@ -165,29 +168,30 @@ class ProjectExplorer(QtGui.QWidget): self.obj_appconfig.current_project['ProjectName']] ) = [] - # This function is enabling save button option. def enable_save(self): + """This function enables save button option.""" self.save.setEnabled(True) - # This function is saving data before it closes the given file. def save_data(self): """ - This function first opens file in write-mode, when write - operation is performed it closes that file and then it closes window. + This function saves data before it closes the given file. + It first opens file in write-mode, write operation is performed, \ + closes that file and then it closes window. """ self.fopen = open(self.filePath, 'w') self.fopen.write(self.text.toPlainText()) self.fopen.close() self.textwindow.close() - # This function removes the project in explorer area by right - # clicking on project and selecting remove option. def removeProject(self): + """ + This function removes the project in explorer area by right \ + clicking on project and selecting remove option. + """ self.indexItem = self.treewidget.currentIndex() self.filePath = str( - self.indexItem.sibling( - self.indexItem.row(), - 1).data()) + self.indexItem.sibling(self.indexItem.row(), 1).data() + ) self.int = self.indexItem.row() self.treewidget.takeTopLevelItem(self.int) @@ -196,16 +200,17 @@ class ProjectExplorer(QtGui.QWidget): del self.obj_appconfig.project_explorer[str(self.filePath)] json.dump(self.obj_appconfig.project_explorer, - open(self.obj_appconfig.dictPath, 'w')) + open(self.obj_appconfig.dictPath["path"], 'w')) - # This function refresh the project in explorer area by right - # clicking on project and selecting refresh option. def refreshProject(self): + """ + This function refresh the project in explorer area by right \ + clicking on project and selecting refresh option. + """ self.indexItem = self.treewidget.currentIndex() self.filePath = str( - self.indexItem.sibling( - self.indexItem.row(), - 1).data()) + self.indexItem.sibling(self.indexItem.row(), 1).data() + ) filelistnew = os.listdir(os.path.join(self.filePath)) parentnode = self.treewidget.currentItem() count = parentnode.childCount() @@ -214,33 +219,31 @@ class ProjectExplorer(QtGui.QWidget): items.removeChild(items.child(0)) for files in filelistnew: QtGui.QTreeWidgetItem( - parentnode, [ - files, os.path.join( - self.filePath, files)]) + parentnode, [files, os.path.join(self.filePath, files)] + ) self.obj_appconfig.project_explorer[self.filePath] = filelistnew json.dump(self.obj_appconfig.project_explorer, - open(self.obj_appconfig.dictPath, 'w')) + open(self.obj_appconfig.dictPath["path"], 'w')) def renameProject(self): """ - This function renames the project present in project explorer area - it validates first: + This function renames the project present in project explorer area. + It validates first: - If project names is not empty. - Project name does not contain spaces between them. - Project name is different between what it was earlier. - Project name should not exist. - And after project name is changed it recreates - the project explorer tree. + After project name is changed, it recreates the project explorer tree. """ self.indexItem = self.treewidget.currentIndex() self.baseFileName = str(self.indexItem.data()) newBaseFileName, ok = QtGui.QInputDialog.getText( - self, 'Rename Project', 'Project Name:', QtGui.QLineEdit.Normal, - self.baseFileName - ) + self, 'Rename Project', 'Project Name:', + QtGui.QLineEdit.Normal, self.baseFileName + ) if ok and newBaseFileName: print(newBaseFileName) print("=================") @@ -261,19 +264,23 @@ class ProjectExplorer(QtGui.QWidget): newBaseFileName = str(newBaseFileName).rstrip().lstrip() projDir = os.path.join(self.workspace, str(newBaseFileName)) - if newBaseFileName == "": - print("Project name can not be empty") + if not newBaseFileName.strip(): + print("Project name cannot be empty") print("==================") msg = QtGui.QErrorMessage(self) - msg.showMessage('The project name cannot be empty') + msg.setModal(True) msg.setWindowTitle("Error Message") + msg.showMessage('The project name cannot be empty') + msg.exec_() elif self.baseFileName == newBaseFileName: print("Project name has to be different") print("==================") msg = QtGui.QErrorMessage(self) - msg.showMessage('The project name has to be different') + msg.setModal(True) msg.setWindowTitle("Error Message") + msg.showMessage('The project name has to be different') + msg.exec_() else: reply = self.obj_validation.validateNewproj(str(projDir)) @@ -282,8 +289,8 @@ class ProjectExplorer(QtGui.QWidget): # rename project folder updatedProjectPath = newBaseFileName.join( projectPath.rsplit(self.baseFileName, 1)) - print("Renaming " + projectPath + " to " - + updatedProjectPath) + print("Renaming " + projectPath + " to " + + updatedProjectPath) os.rename(projectPath, updatedProjectPath) # rename files matching project name @@ -295,8 +302,8 @@ class ProjectExplorer(QtGui.QWidget): self.baseFileName, newBaseFileName, 1) newFilePath = os.path.join( updatedProjectPath, projectFile) - print("Renaming " + oldFilePath + " to" - + newFilePath) + print("Renaming " + oldFilePath + " to" + + newFilePath) os.rename(oldFilePath, newFilePath) updatedProjectFiles.append(projectFile) @@ -307,7 +314,7 @@ class ProjectExplorer(QtGui.QWidget): # save project_explorer dictionary on disk json.dump(self.obj_appconfig.project_explorer, open( - self.obj_appconfig.dictPath, 'w')) + self.obj_appconfig.dictPath["path"], 'w')) # recreate project explorer tree self.treewidget.clear() @@ -320,18 +327,23 @@ class ProjectExplorer(QtGui.QWidget): print("Project name already exists.") print("==========================") msg = QtGui.QErrorMessage(self) - msg.showMessage( - 'The project "' - + newBaseFileName - + '" already exist.Please select the different name or' - + ' delete existing project') + msg.setModal(True) msg.setWindowTitle("Error Message") + msg.showMessage( + 'The project "' + newBaseFileName + + '" already exist. Please select a different name or' + + ' delete existing project' + ) + msg.exec_() elif reply == "CHECKNAME": print("Name can not contain space between them") print("===========================") msg = QtGui.QErrorMessage(self) - msg.showMessage( - 'The project name should not' - + 'contain space between them') + msg.setModal(True) msg.setWindowTitle("Error Message") + msg.showMessage( + 'The project name should not ' + + 'contain space between them' + ) + msg.exec_() diff --git a/src/frontEnd/Workspace.py b/src/frontEnd/Workspace.py index 55a8c95e..6940da59 100644 --- a/src/frontEnd/Workspace.py +++ b/src/frontEnd/Workspace.py @@ -1,5 +1,4 @@ # ========================================================================= -# # FILE: Workspace.py # # USAGE: --- @@ -11,27 +10,27 @@ # BUGS: --- # NOTES: --- # AUTHOR: Fahim Khan, fahim.elex@gmail.com +# MODIFIED: Rahul Paknikar, rahulp@iitb.ac.in # ORGANIZATION: eSim team at FOSSEE, IIT Bombay. # CREATED: Wednesday 05 February 2015 -# REVISION: --- +# REVISION: Friday 14 February 2020 # ========================================================================= + from PyQt4 import QtCore, QtGui from configuration.Appconfig import Appconfig import time import os +import json -# This class creates Workspace GUI. class Workspace(QtGui.QWidget): """ This class creates UI for WorkSpace selection window. - This window contains text area to select location of your choice - or browse location for workspace area. - - By default workspace is set in ~/eSim-Workspace. - - This workspace area contains all the projects made by user. + - This window contains text area to select location of your choice \ + or browse location for workspace area. + - By default workspace is set in ~/eSim-Workspace. + - This workspace area contains all the projects made by user. """ @@ -43,7 +42,6 @@ class Workspace(QtGui.QWidget): self.initWorkspace() def initWorkspace(self): - # print "Calling workspace" self.mainwindow = QtGui.QVBoxLayout() self.split = QtGui.QSplitter() @@ -65,22 +63,27 @@ class Workspace(QtGui.QWidget): self.okbtn.clicked.connect(self.createWorkspace) self.cancelbtn = QtGui.QPushButton('Cancel') self.cancelbtn.clicked.connect(self.defaultWorkspace) + + # Checkbox + self.chkbox = QtGui.QCheckBox('Set Default', self) + self.chkbox.setCheckState(int(self.obj_appconfig.workspace_check)) + # Layout self.grid.addWidget(self.note, 0, 0, 1, 15) self.grid.addWidget(self.workspace_label, 2, 1) self.grid.addWidget(self.workspace_loc, 2, 2, 2, 12) self.grid.addWidget(self.browsebtn, 2, 14) - self.grid.addWidget(self.okbtn, 4, 13) - self.grid.addWidget(self.cancelbtn, 4, 14) + self.grid.addWidget(self.chkbox, 4, 2) + self.grid.addWidget(self.okbtn, 5, 13) + self.grid.addWidget(self.cancelbtn, 5, 14) self.setGeometry(QtCore.QRect(500, 250, 400, 400)) self.setMaximumSize(4000, 200) self.setWindowTitle("eSim") self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.note.setReadOnly(True) - self.setWindowIcon(QtGui.QIcon('../../images/logo.png')) + self.setWindowIcon(QtGui.QIcon('images/logo.png')) self.setLayout(self.grid) - self.show() def defaultWorkspace(self): print("Default workspace selected : " + @@ -90,6 +93,13 @@ class Workspace(QtGui.QWidget): 'Default workspace selected : ' + self.obj_appconfig.default_workspace["workspace"]) self.close() + + var_appView.obj_Mainview.obj_projectExplorer.treewidget.clear() + for parent, children in self.obj_appconfig.project_explorer.items(): + var_appView.obj_Mainview.obj_projectExplorer.addTreeNode( + parent, children + ) + var_appView.show() time.sleep(1) var_appView.splash.close() @@ -105,6 +115,18 @@ class Workspace(QtGui.QWidget): def createWorkspace(self): print("Function : Create workspace") + + self.obj_appconfig.workspace_check = self.chkbox.checkState() + print(self.workspace_loc.text()) + file = open(os.path.join( + os.path.expanduser("~"), ".esim/workspace.txt"), 'w' + ) + file.writelines( + str(self.obj_appconfig.workspace_check) + + " " + self.workspace_loc.text() + ) + file.close() + self.create_workspace = str(self.workspace_loc.text()) self.obj_appconfig.print_info('Workspace : ' + self.create_workspace) # Checking if Workspace already exist or not @@ -117,6 +139,27 @@ class Workspace(QtGui.QWidget): = self.create_workspace self.imp_var = 1 self.close() + + self.obj_appconfig.dictPath["path"] = os.path.join( + self.obj_appconfig.default_workspace["workspace"], + ".projectExplorer.txt" + ) + + try: + self.obj_appconfig.project_explorer = json.load( + open(self.obj_appconfig.dictPath["path"]) + ) + except BaseException: + self.obj_appconfig.project_explorer = {} + + Appconfig.project_explorer = self.obj_appconfig.project_explorer + + var_appView.obj_Mainview.obj_projectExplorer.treewidget.clear() + for parent, children in self.obj_appconfig.project_explorer.items(): + var_appView.obj_Mainview.obj_projectExplorer.addTreeNode( + parent, children + ) + var_appView.show() time.sleep(1) var_appView.splash.close() @@ -124,5 +167,6 @@ class Workspace(QtGui.QWidget): def browseLocation(self): print("Function : Browse Location") self.workspace_directory = QtGui.QFileDialog.getExistingDirectory( - self, "Browse Location", os.path.expanduser("~")) + self, "Browse Location", os.path.expanduser("~") + ) self.workspace_loc.setText(self.workspace_directory) diff --git a/src/frontEnd/pathmagic.py b/src/frontEnd/pathmagic.py index 49c4932d..5f0d712c 100644 --- a/src/frontEnd/pathmagic.py +++ b/src/frontEnd/pathmagic.py @@ -1,5 +1,6 @@ import os import sys + # Setting PYTHONPATH cwd = os.getcwd() (setPath, fronEnd) = os.path.split(cwd) |