diff --git a/nghdl/src/createKicadLibrary.py b/nghdl/src/createKicadLibrary.py
index 9eb5ab239..73f6d9b46 100644
--- a/nghdl/src/createKicadLibrary.py
+++ b/nghdl/src/createKicadLibrary.py
@@ -2,7 +2,7 @@
import re
import os
import xml.etree.cElementTree as ET
-from PyQt5 import QtWidgets
+from PyQt6 import QtWidgets
class AutoSchematic(QtWidgets.QWidget):
@@ -20,7 +20,7 @@ def __init__(self, parent, modelname):
inst_dir + '/KiCad/share/kicad/symbols/eSim_Nghdl.kicad_sym'
else:
self.kicad_nghdl_sym = \
- '/Users/thethtarshwesin/Documents/KiCad/6.0/symbols/eSim_Nghdl.kicad_sym'
+ '/usr/share/kicad/symbols/eSim_Nghdl.kicad_sym'
self.parser = Appconfig.parser_nghdl
def createKicadSymbol(self):
@@ -40,9 +40,9 @@ def createKicadSymbol(self):
''' already exist. Do you want to overwrite it?
If yes press ok, else cancel it and ''' +
'''change the name of your vhdl file.''',
- QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Cancel
+ QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel
)
- if ret == QtWidgets.QMessageBox.Ok:
+ if ret == QtWidgets.QMessageBox.StandardButton.Ok:
print("Overwriting existing libraries")
self.getPortInformation()
self.createXML()
@@ -57,7 +57,7 @@ def createKicadSymbol(self):
self.parent, "Error", '''A standard library already ''' +
'''exists with this name.
Please change the ''' +
'''name of your vhdl file and upload it again.''',
- QtWidgets.QMessageBox.Ok
+ QtWidgets.QMessageBox.StandardButton.Ok
)
# quit()
@@ -433,7 +433,7 @@ def createSym(self):
"Symbol details for this model were added to "
"eSim_Nghdl.kicad_sym successfully."
),
- QtWidgets.QMessageBox.Ok
+ QtWidgets.QMessageBox.StandardButton.Ok
)
diff --git a/nghdl/src/model_generation.py b/nghdl/src/model_generation.py
index 58f1aac9d..fb180ff95 100644
--- a/nghdl/src/model_generation.py
+++ b/nghdl/src/model_generation.py
@@ -15,8 +15,7 @@ def __init__(self, file):
if os.name == 'nt':
self.home = os.path.join('library', 'config')
else:
- # self.home = os.expanduser('~')
- self.home = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) # direcotory: Resources/
+ self.home = os.path.expanduser('~')
self.parser = ConfigParser()
self.parser.read(os.path.join(
diff --git a/nghdl/src/ngspice_ghdl.py b/nghdl/src/ngspice_ghdl.py
old mode 100755
new mode 100644
index 1f7975f4e..15aa42376
--- a/nghdl/src/ngspice_ghdl.py
+++ b/nghdl/src/ngspice_ghdl.py
@@ -1,4 +1,4 @@
-#! /Users/thethtarshwesin/Desktop/eSim-2.5/esim-venv/bin/python3
+#!/usr/bin/env python3
# This file create the GUI to install code model in the Ngspice.
@@ -6,7 +6,7 @@
import sys
import shutil
import subprocess
-from PyQt5 import QtGui, QtCore, QtWidgets
+from PyQt6 import QtGui, QtCore, QtWidgets
from configparser import ConfigParser
from Appconfig import Appconfig
from createKicadLibrary import AutoSchematic
@@ -39,6 +39,7 @@ def __init__(self):
print(fileopen.read())
fileopen.close()
self.file_list = [] # to keep the supporting files
+ self.filename = ''
self.errorFlag = False # to keep the check of "make install" errors
self.initUI()
@@ -60,7 +61,7 @@ def initUI(self):
self.termedit.setReadOnly(1)
pal = QtGui.QPalette()
bgc = QtGui.QColor(0, 0, 0)
- pal.setColor(QtGui.QPalette.Base, bgc)
+ pal.setColor(QtGui.QPalette.ColorRole.Base, bgc)
self.termedit.setPalette(pal)
self.termedit.setStyleSheet("QTextEdit {color:white}")
@@ -139,9 +140,9 @@ def createModelDirectory(self):
"This model already exist. Do you want to " +
"overwrite it?
If yes press ok, else cancel it and " +
"change the name of your vhdl file.",
- QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Cancel
+ QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel
)
- if ret == QtWidgets.QMessageBox.Ok:
+ if ret == QtWidgets.QMessageBox.StandardButton.Ok:
print("Overwriting existing model " + self.modelname)
if os.name == 'nt':
cmd = "rmdir " + self.modelname + "/s /q"
@@ -234,7 +235,7 @@ def createModelFiles(self):
self.msys_home = self.parser.get('COMPILER', 'MSYS_HOME')
subprocess.call(self.msys_home + "/usr/bin/bash.exe " +
path + "/DUTghdl/compile.sh", shell=True)
- subprocess.call(self.msys_hoscme + "/usr/bin/bash.exe -c " +
+ subprocess.call(self.msys_home + "/usr/bin/bash.exe -c " +
"'chmod a+x start_server.sh'", shell=True)
subprocess.call(self.msys_home + "/usr/bin/bash.exe -c " +
"'chmod a+x sock_pkg_create.sh'", shell=True)
@@ -249,11 +250,14 @@ def createModelFiles(self):
# Slot to redirect stdout and stderr to window console
@QtCore.pyqtSlot()
def readAllStandard(self):
+ proc = self.sender()
+ if not isinstance(proc, QtCore.QProcess):
+ return
self.termedit.append(
- str(self.process.readAllStandardOutput().data(), encoding='utf-8')
+ str(proc.readAllStandardOutput().data(), encoding='utf-8')
)
- stderror = self.process.readAllStandardError()
- if stderror.toUpper().contains(b"ERROR"):
+ stderror = proc.readAllStandardError()
+ if stderror.toUpper().contains(QtCore.QByteArray(b"ERROR")):
self.errorFlag = True
self.termedit.append(str(stderror.data(), encoding='utf-8'))
@@ -265,22 +269,21 @@ def runMake(self):
try:
if os.name == 'nt':
- # path to msys bin directory where make is located
self.msys_home = self.parser.get('COMPILER', 'MSYS_HOME')
cmd = self.msys_home + "/mingw64/bin/mingw32-make.exe"
else:
- cmd = " make"
+ cmd = "make"
print("Running Make command in " + path_icm)
- path = os.getcwd() # noqa
self.process = QtCore.QProcess(self)
- self.process.start(cmd)
- print("make command process pid ---------- >", self.process.pid())
-
+ self.process.readyReadStandardOutput.connect(self.readAllStandard)
+ self.process.readyReadStandardError.connect(self.readAllStandard)
if os.name == "nt":
self.process.finished.connect(self.createSchematicLib)
- self.process \
- .readyReadStandardOutput.connect(self.readAllStandard)
+ else:
+ self.process.finished.connect(self.runMakeInstall)
+ self.process.start(cmd)
+ print("make command process pid ---------- >", self.process.processId())
except BaseException:
print("There is error in 'make' ")
@@ -291,20 +294,18 @@ def runMakeInstall(self):
try:
if os.name == 'nt':
self.msys_home = self.parser.get('COMPILER', 'MSYS_HOME')
- cmd = self.msys_home + "/mingw64/bin/mingw32-make.exe install"
+ prog = self.msys_home + "/mingw64/bin/mingw32-make.exe"
+ args = ["install"]
else:
- cmd = " make install"
+ prog = "make"
+ args = ["install"]
print("Running Make Install")
- path = os.getcwd() # noqa
- try:
- self.process.close()
- except BaseException:
- pass
self.process = QtCore.QProcess(self)
- self.process.start(cmd)
- self.process.finished.connect(self.createSchematicLib)
self.process.readyReadStandardOutput.connect(self.readAllStandard)
+ self.process.readyReadStandardError.connect(self.readAllStandard)
+ self.process.finished.connect(self.createSchematicLib)
+ self.process.start(prog, args)
os.chdir(self.cur_dir)
except BaseException:
@@ -312,6 +313,19 @@ def runMakeInstall(self):
sys.exit()
def createSchematicLib(self):
+ try:
+ self._createSchematicLib()
+ except Exception as e:
+ print("createSchematicLib exception:", e)
+ import traceback
+ traceback.print_exc()
+ QtWidgets.QMessageBox.critical(
+ self, 'Error', 'Library creation failed: ' + str(e)
+ )
+ self.uploadbtn.setEnabled(True)
+ self.exitbtn.setEnabled(True)
+
+ def _createSchematicLib(self):
if os.name == "nt":
shutil.copy("ghdl/ghdl.cm", "../../../../lib/ngspice/")
@@ -333,6 +347,8 @@ def createSchematicLib(self):
'''To create Schematic Library of your model, ''' +
'''use NGHDL through eSim '''
)
+ self.uploadbtn.setEnabled(True)
+ self.exitbtn.setEnabled(True)
def uploadModel(self):
print("Upload button clicked")
@@ -340,6 +356,10 @@ def uploadModel(self):
self.process.close()
except BaseException:
pass
+ if not self.filename:
+ QtWidgets.QMessageBox.warning(
+ self, 'No File', 'Use Browse to select a .vhdl file first.')
+ return
try:
self.file_extension = os.path.splitext(str(self.filename))[1]
print("Uploaded File extension :" + self.file_extension)
@@ -348,12 +368,13 @@ def uploadModel(self):
self.checkSupportFiles()
if self.file_extension == ".vhdl":
self.errorFlag = False
+ self.uploadbtn.setEnabled(False)
+ self.exitbtn.setEnabled(False)
+ self.termedit.append('Processing... do not close until Symbol Added dialog appears.')
self.createModelDirectory()
self.addingModelInModpath()
self.createModelFiles()
self.runMake()
- if os.name != 'nt':
- self.runMakeInstall()
else:
QtWidgets.QMessageBox.information(
self, 'Message', '''Important Message.
''' +
@@ -439,7 +460,7 @@ def main():
# Mainwindow() object must be assigned to a variable.
# Otherwise, it is destroyed as soon as it gets created.
w = Mainwindow() # noqa
- sys.exit(app.exec_())
+ sys.exit(app.exec())
if __name__ == '__main__':
diff --git a/src/configuration/Appconfig.py b/src/configuration/Appconfig.py
index 3a4ffb4ad..31920a53f 100644
--- a/src/configuration/Appconfig.py
+++ b/src/configuration/Appconfig.py
@@ -46,7 +46,11 @@ class Appconfig(QtWidgets.QWidget):
)
workspace_check, home = file.readline().split(' ', 1)
file.close()
- except IOError:
+ except (IOError, ValueError):
+ # ValueError: workspace.txt was truncated/empty (e.g. an interrupted
+ # write left it blank), so " ".split(' ', 1) cannot unpack
+ # into two names. Fall back to the default workspace instead of letting
+ # the exception escape the class body and abort startup.
home = os.path.join(os.path.expanduser("~"), "eSim-Workspace")
workspace_check = 0
diff --git a/src/converter/browseSchematic.py b/src/converter/browseSchematic.py
index 436c11c6a..f5e9abdc4 100644
--- a/src/converter/browseSchematic.py
+++ b/src/converter/browseSchematic.py
@@ -2,7 +2,7 @@
def browse_path(self, text_box):
file_dialog = QFileDialog() # a dialog that allows the user to select files or directories
- file_dialog.setFileMode(QFileDialog.AnyFile)
+ file_dialog.setFileMode(QFileDialog.FileMode.AnyFile)
file_dialog.setNameFilter("Supported Files (*.sch *.asc *.slb *.asy);;ASY Files (*.asy)") # Include all supported extensions
file_dialog.exec() # Execute the dialog
diff --git a/src/frontEnd/Application.py b/src/frontEnd/Application.py
index 953b8806b..7f8418731 100644
--- a/src/frontEnd/Application.py
+++ b/src/frontEnd/Application.py
@@ -447,7 +447,7 @@ def dev_docs(self):
webbrowser.open("https://esim.readthedocs.io/en/latest/index.html")
@QtCore.pyqtSlot(QtCore.QProcess.ExitStatus, int)
- def plotSimulationData(self, exitCode, exitStatus):
+ def plotSimulationData(self, exitStatus, exitCode):
"""Enables interaction for new simulation and
displays the plotter dock where graphs can be plotted.
"""
diff --git a/src/frontEnd/ProjectExplorer.py b/src/frontEnd/ProjectExplorer.py
old mode 100755
new mode 100644
index ededeb8aa..75f7e0a71
--- a/src/frontEnd/ProjectExplorer.py
+++ b/src/frontEnd/ProjectExplorer.py
@@ -118,12 +118,14 @@ def addTreeNode(self, parents, children):
def openMenu(self, position):
indexes = self.treewidget.selectedIndexes()
- if len(indexes) > 0:
- level = 0
- index = indexes[0]
- while index.parent().isValid():
- index = index.parent()
- level += 1
+ if not indexes:
+ return
+
+ level = 0
+ index = indexes[0]
+ while index.parent().isValid():
+ index = index.parent()
+ level += 1
menu = QtWidgets.QMenu()
if level == 0:
@@ -139,7 +141,7 @@ def openMenu(self, position):
snapshot = menu.addAction(self.tr("Snapshot"))
snapshot.triggered.connect(self.takeSnapshot)
- menu.exec_(self.treewidget.viewport().mapToGlobal(position))
+ menu.exec(self.treewidget.viewport().mapToGlobal(position))
def openProject(self):
self.indexItem = self.treewidget.currentIndex()
@@ -292,7 +294,7 @@ def renameProject(self):
newBaseFileName, ok = QtWidgets.QInputDialog.getText(
self, 'Rename Project', 'Project Name:',
- QtWidgets.QLineEdit.Normal, self.baseFileName
+ QtWidgets.QLineEdit.EchoMode.Normal, self.baseFileName
)
if ok and newBaseFileName:
@@ -474,4 +476,3 @@ def takeSnapshot(self):
self.time_explorer.add_snapshot(file_name, formatted_time)
else:
print(f"Snapshot taken: {snapshot_path}")
- msg.exec()
diff --git a/src/frontEnd/TerminalUi.py b/src/frontEnd/TerminalUi.py
index 2384991e3..20861d9c0 100644
--- a/src/frontEnd/TerminalUi.py
+++ b/src/frontEnd/TerminalUi.py
@@ -24,7 +24,7 @@ def __init__(self, qProcess, args):
self.iconDir = "../../images"
# Load the ui file
- uic.loadUi("TerminalUi.ui", self)
+ uic.loadUi(os.path.join(os.path.dirname(__file__), "TerminalUi.ui"), self)
# Define Our Widgets
self.progressBar = self.findChild(
@@ -94,7 +94,7 @@ def cancelSimulation(self):
def redoSimulation(self):
"""This function reruns the ngspice simulation
"""
- self.Flag = "Flase"
+ self.Flag = False
self.cancelSimulationButton.setEnabled(True)
self.redoSimulationButton.setEnabled(False)
diff --git a/src/frontEnd/TimeExplorer.py b/src/frontEnd/TimeExplorer.py
index 1c38d8023..b028c9740 100644
--- a/src/frontEnd/TimeExplorer.py
+++ b/src/frontEnd/TimeExplorer.py
@@ -2,7 +2,7 @@
import re
import shutil
import json
-from PyQt5 import QtWidgets
+from PyQt6 import QtWidgets
class TimeExplorer(QtWidgets.QWidget):
@@ -81,6 +81,8 @@ def load_last_snapshots(self):
def clear_snapshots(self):
selected = self.treewidget.selectedItems()
project_name = self.current_project["ProjectName"]
+ if not project_name:
+ return
snapshot_dir = os.path.join(self.user_home, ".esim", "history", project_name)
if selected:
@@ -125,6 +127,8 @@ def restore_snapshots(self):
selected_items = self.treewidget.selectedItems()
project_name = self.current_project["ProjectName"]
+ if not project_name:
+ return
snapshot_dir = os.path.join(self.user_home, ".esim", "history", project_name)
if not os.path.exists(snapshot_dir):
diff --git a/src/kicadtoNgspice/Analysis.py b/src/kicadtoNgspice/Analysis.py
index 0b169efd9..c474228e0 100644
--- a/src/kicadtoNgspice/Analysis.py
+++ b/src/kicadtoNgspice/Analysis.py
@@ -282,7 +282,7 @@ def createACgroup(self):
self.ac_parameter[self.parameter_cnt] = "Hz"
# Event listener for combo action
- self.start_fre_combo.activated[str].connect(self.start_combovalue)
+ self.start_fre_combo.currentTextChanged.connect(self.start_combovalue)
self.parameter_cnt = self.parameter_cnt + 1
self.stop_fre_combo = QtWidgets.QComboBox()
@@ -300,7 +300,7 @@ def createACgroup(self):
except BaseException:
self.ac_parameter[self.parameter_cnt] = "Hz"
- self.stop_fre_combo.activated[str].connect(self.stop_combovalue)
+ self.stop_fre_combo.currentTextChanged.connect(self.stop_combovalue)
self.track_obj.AC_entry_var["ITEMS"] = self.ac_entry_var
self.track_obj.AC_Parameter["ITEMS"] = self.ac_parameter
@@ -327,13 +327,15 @@ def createACgroup(self):
self.Dec.setChecked(False)
self.Oct.setChecked(True)
- self.ac_entry_var[0].setText(root[0][3].text)
- self.ac_entry_var[1].setText(root[0][4].text)
- self.ac_entry_var[2].setText(root[0][5].text)
- index = self.start_fre_combo.findText(root[0][6].text)
- self.start_fre_combo.setCurrentIndex(index)
- index = self.stop_fre_combo.findText(root[0][7].text)
- self.stop_fre_combo.setCurrentIndex(index)
+ self.ac_entry_var[0].setText(root[0][3].text or "")
+ self.ac_entry_var[1].setText(root[0][4].text or "")
+ self.ac_entry_var[2].setText(root[0][5].text or "")
+ index = self.start_fre_combo.findText(root[0][6].text or "")
+ if index >= 0:
+ self.start_fre_combo.setCurrentIndex(index)
+ index = self.stop_fre_combo.findText(root[0][7].text or "")
+ if index >= 0:
+ self.stop_fre_combo.setCurrentIndex(index)
except BaseException:
print("AC Analysis XML Parse Error")
@@ -498,7 +500,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.start_combo.activated[str].connect(self.start_changecombo)
+ self.start_combo.currentTextChanged.connect(self.start_changecombo)
self.parameter_cnt += 1
self.increment_combo = QtWidgets.QComboBox(self)
@@ -515,7 +517,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.increment_combo.activated[str].connect(self.increment_changecombo)
+ self.increment_combo.currentTextChanged.connect(self.increment_changecombo)
self.parameter_cnt += 1
self.stop_combo = QtWidgets.QComboBox(self)
@@ -532,7 +534,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.stop_combo.activated[str].connect(self.stop_changecombo)
+ self.stop_combo.currentTextChanged.connect(self.stop_changecombo)
self.parameter_cnt += 1
self.start_combo2 = QtWidgets.QComboBox(self)
@@ -549,7 +551,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.start_combo2.activated[str].connect(self.start_changecombo2)
+ self.start_combo2.currentTextChanged.connect(self.start_changecombo2)
self.parameter_cnt += 1
self.increment_combo2 = QtWidgets.QComboBox(self)
@@ -566,7 +568,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.increment_combo2.activated[str].connect(
+ self.increment_combo2.currentTextChanged.connect(
self.increment_changecombo2)
self.parameter_cnt += 1
@@ -584,7 +586,7 @@ def createDCgroup(self):
except BaseException:
self.dc_parameter[self.parameter_cnt] = "Volts or Amperes"
- self.stop_combo2.activated[str].connect(self.stop_changecombo2)
+ self.stop_combo2.currentTextChanged.connect(self.stop_changecombo2)
self.parameter_cnt += 1
self.check = QtWidgets.QCheckBox('Operating Point Analysis', self)
@@ -609,26 +611,32 @@ def createDCgroup(self):
")
if check:
try:
- self.dc_entry_var[0].setText(root[1][0].text)
- self.dc_entry_var[1].setText(root[1][1].text)
- self.dc_entry_var[2].setText(root[1][2].text)
- self.dc_entry_var[3].setText(root[1][3].text)
- index = self.start_combo.findText(root[1][5].text)
- self.start_combo.setCurrentIndex(index)
- index = self.increment_combo.findText(root[1][6].text)
- self.increment_combo.setCurrentIndex(index)
- index = self.stop_combo.findText(root[1][7].text)
- self.stop_combo.setCurrentIndex(index)
- self.dc_entry_var[4].setText(root[1][8].text)
- self.dc_entry_var[5].setText(root[1][9].text)
- self.dc_entry_var[6].setText(root[1][10].text)
- self.dc_entry_var[7].setText(root[1][11].text)
- index = self.start_combo2.findText(root[1][12].text)
- self.start_combo2.setCurrentIndex(index)
- index = self.increment_combo2.findText(root[1][13].text)
- self.increment_combo2.setCurrentIndex(index)
- index = self.stop_combo2.findText(root[1][14].text)
- self.stop_combo2.setCurrentIndex(index)
+ self.dc_entry_var[0].setText(root[1][0].text or "")
+ self.dc_entry_var[1].setText(root[1][1].text or "")
+ self.dc_entry_var[2].setText(root[1][2].text or "")
+ self.dc_entry_var[3].setText(root[1][3].text or "")
+ index = self.start_combo.findText(root[1][5].text or "")
+ if index >= 0:
+ self.start_combo.setCurrentIndex(index)
+ index = self.increment_combo.findText(root[1][6].text or "")
+ if index >= 0:
+ self.increment_combo.setCurrentIndex(index)
+ index = self.stop_combo.findText(root[1][7].text or "")
+ if index >= 0:
+ self.stop_combo.setCurrentIndex(index)
+ self.dc_entry_var[4].setText(root[1][8].text or "")
+ self.dc_entry_var[5].setText(root[1][9].text or "")
+ self.dc_entry_var[6].setText(root[1][10].text or "")
+ self.dc_entry_var[7].setText(root[1][11].text or "")
+ index = self.start_combo2.findText(root[1][12].text or "")
+ if index >= 0:
+ self.start_combo2.setCurrentIndex(index)
+ index = self.increment_combo2.findText(root[1][13].text or "")
+ if index >= 0:
+ self.increment_combo2.setCurrentIndex(index)
+ index = self.stop_combo2.findText(root[1][14].text or "")
+ if index >= 0:
+ self.stop_combo2.setCurrentIndex(index)
if root[1][4].text == 1:
self.check.setChecked(True)
@@ -746,7 +754,7 @@ def createTRANgroup(self):
except BaseException:
self.tran_parameter[self.parameter_cnt] = "sec"
- self.start_combobox.activated[str].connect(self.start_combo_change)
+ self.start_combobox.currentTextChanged.connect(self.start_combo_change)
self.parameter_cnt += 1
self.step_combobox = QtWidgets.QComboBox()
@@ -761,7 +769,7 @@ def createTRANgroup(self):
except BaseException:
self.tran_parameter[self.parameter_cnt] = "sec"
- self.step_combobox.activated[str].connect(self.step_combo_change)
+ self.step_combobox.currentTextChanged.connect(self.step_combo_change)
self.parameter_cnt += 1
self.stop_combobox = QtWidgets.QComboBox()
@@ -776,7 +784,7 @@ def createTRANgroup(self):
except BaseException:
self.tran_parameter[self.parameter_cnt] = "sec"
- self.stop_combobox.activated[str].connect(self.stop_combo_change)
+ self.stop_combobox.currentTextChanged.connect(self.stop_combo_change)
self.parameter_cnt += 1
self.track_obj.TRAN_entry_var["ITEMS"] = self.tran_entry_var
@@ -791,15 +799,18 @@ def createTRANgroup(self):
")
if check:
try:
- self.tran_entry_var[0].setText(root[2][0].text)
- self.tran_entry_var[1].setText(root[2][1].text)
- self.tran_entry_var[2].setText(root[2][2].text)
- index = self.start_combobox.findText(root[2][3].text)
- self.start_combobox.setCurrentIndex(index)
- index = self.step_combobox.findText(root[2][4].text)
- self.step_combobox.setCurrentIndex(index)
- index = self.stop_combobox.findText(root[2][5].text)
- self.stop_combobox.setCurrentIndex(index)
+ self.tran_entry_var[0].setText(root[2][0].text or "")
+ self.tran_entry_var[1].setText(root[2][1].text or "")
+ self.tran_entry_var[2].setText(root[2][2].text or "")
+ index = self.start_combobox.findText(root[2][3].text or "")
+ if index >= 0:
+ self.start_combobox.setCurrentIndex(index)
+ index = self.step_combobox.findText(root[2][4].text or "")
+ if index >= 0:
+ self.step_combobox.setCurrentIndex(index)
+ index = self.stop_combobox.findText(root[2][5].text or "")
+ if index >= 0:
+ self.stop_combobox.setCurrentIndex(index)
except BaseException:
print("Transient Analysis XML Parse Error")
diff --git a/src/kicadtoNgspice/Convert.py b/src/kicadtoNgspice/Convert.py
old mode 100755
new mode 100644
index 665a30130..4e5fcf227
--- a/src/kicadtoNgspice/Convert.py
+++ b/src/kicadtoNgspice/Convert.py
@@ -331,6 +331,8 @@ def converttosciform(self, string_obj):
This function is used for scientific conversion.
"""
self.string_obj = string_obj
+ if not self.string_obj:
+ return "e-00"
if self.string_obj[0] == 'm':
return "e-03"
elif self.string_obj[0] == 'u':
diff --git a/src/kicadtoNgspice/DeviceModel.py b/src/kicadtoNgspice/DeviceModel.py
index 2088894d0..ead12b3ca 100755
--- a/src/kicadtoNgspice/DeviceModel.py
+++ b/src/kicadtoNgspice/DeviceModel.py
@@ -572,7 +572,7 @@ def eSim_general_libs(self, schematicInfo):
print("=========================================")
print(eachline)
words = eachline.split()
- if eachline[0] == 'q':
+ if eachline[0] == 'q' and len(words) > 4:
# print("Device Model Transistor: ", words[0])
self.devicemodel_dict_beg[words[0]] = self.count
transbox = QtWidgets.QGroupBox()
@@ -637,7 +637,7 @@ def eSim_general_libs(self, schematicInfo):
self.devicemodel_dict_end[words[0]] = self.count
self.count = self.count + 1
- elif eachline[0] == 'd':
+ elif eachline[0] == 'd' and len(words) > 3:
# print("Device Model Diode:", words[0])
self.devicemodel_dict_beg[words[0]] = self.count
diodebox = QtWidgets.QGroupBox()
@@ -701,7 +701,7 @@ def eSim_general_libs(self, schematicInfo):
self.devicemodel_dict_end[words[0]] = self.count
self.count = self.count + 1
- elif eachline[0] == 'j':
+ elif eachline[0] == 'j' and len(words) > 4:
# print("Device Model JFET:", words[0])
self.devicemodel_dict_beg[words[0]] = self.count
jfetbox = QtWidgets.QGroupBox()
@@ -764,7 +764,7 @@ def eSim_general_libs(self, schematicInfo):
self.devicemodel_dict_end[words[0]] = self.count
self.count = self.count + 1
- elif eachline[0] == 's':
+ elif eachline[0] == 's' and len(words) > 5:
# print("Device Model Switch:", words[0])
self.devicemodel_dict_beg[words[0]] = self.count
switchbox = QtWidgets.QGroupBox()
@@ -890,7 +890,7 @@ def eSim_general_libs(self, schematicInfo):
self.devicemodel_dict_end[words[0]] = self.count
self.count = self.count + 1
- elif eachline[0] == 'm':
+ elif eachline[0] == 'm' and len(words) > 4:
self.devicemodel_dict_beg[words[0]] = self.count
mosfetbox = QtWidgets.QGroupBox()
diff --git a/src/kicadtoNgspice/KicadtoNgspice.py b/src/kicadtoNgspice/KicadtoNgspice.py
index 50131609a..1a4f00a12 100644
--- a/src/kicadtoNgspice/KicadtoNgspice.py
+++ b/src/kicadtoNgspice/KicadtoNgspice.py
@@ -59,13 +59,8 @@ def __init__(self, clarg1, clarg2=None):
# Track the dynamically created widget of KicadtoNgspice Window
self.obj_track = TrackWidget.TrackWidget()
- # Clear Dictionary/List item of sub circuit and Ngspice model
- # Dictionary
- self.obj_track.subcircuitList.clear()
- self.obj_track.subcircuitTrack.clear()
- self.obj_track.model_entry_var.clear()
- # List
- self.obj_track.modelTrack[:] = []
+ # Reset all shared class-level state for this conversion run
+ TrackWidget.TrackWidget.reset()
# Object of Processing
obj_proc = PrcocessNetlist()
diff --git a/src/kicadtoNgspice/Processing.py b/src/kicadtoNgspice/Processing.py
index 94de9440c..dbc8f4625 100644
--- a/src/kicadtoNgspice/Processing.py
+++ b/src/kicadtoNgspice/Processing.py
@@ -142,6 +142,8 @@ def insertSpecialSourceParam(self, schematicInfo, sourcelist):
if (compName[0] == 'v' or compName[0] == 'i') and not compName.startswith('ihp'):
# Find the index component from circuit
index = schematicInfo.index(compline)
+ if len(words) <= 3:
+ continue
if words[3] == "pulse":
Title = "Add parameters for pulse source " + compName
v1 = ' Enter initial value (Volts/Amps): '
diff --git a/src/kicadtoNgspice/TrackWidget.py b/src/kicadtoNgspice/TrackWidget.py
index 9f1d07c2d..2aafc2251 100644
--- a/src/kicadtoNgspice/TrackWidget.py
+++ b/src/kicadtoNgspice/TrackWidget.py
@@ -7,6 +7,9 @@ class TrackWidget:
- References
- Model Details
- ... etc
+ - All attributes are class-level (shared across instances by design).
+ - Call TrackWidget.reset() at the start of each conversion to clear
+ accumulated state from previous runs.
"""
# Track widget list for Source details
sourcelisttrack = {"ITEMS": "None"}
@@ -35,3 +38,25 @@ class TrackWidget:
subcircuitTrack = {}
# Track subcircuits which are specified in .cir file
subcircuitList = {}
+
+ @classmethod
+ def reset(cls):
+ """Reset all shared class-level state for a fresh conversion run."""
+ cls.sourcelisttrack = {"ITEMS": "None"}
+ cls.source_entry_var = {"ITEMS": "None"}
+ cls.AC_entry_var = {"ITEMS": "None"}
+ cls.AC_Parameter = {"ITEMS": "None"}
+ cls.DC_entry_var = {"ITEMS": "None"}
+ cls.DC_Parameter = {"ITEMS": "None"}
+ cls.TRAN_entry_var = {"ITEMS": "None"}
+ cls.TRAN_Parameter = {"ITEMS": "None"}
+ cls.set_CheckBox = {"ITEMS": "None"}
+ cls.AC_type = {"ITEMS": "None"}
+ cls.op_check = []
+ cls.modelTrack = []
+ cls.microcontrollerTrack = []
+ cls.model_entry_var = {}
+ cls.microcontroller_var = {}
+ cls.deviceModelTrack = {}
+ cls.subcircuitTrack = {}
+ cls.subcircuitList = {}
diff --git a/src/maker/Maker.py b/src/maker/Maker.py
old mode 100755
new mode 100644
index 9c8727e56..21bdc4bb0
--- a/src/maker/Maker.py
+++ b/src/maker/Maker.py
@@ -29,7 +29,7 @@
# importing the files and libraries
import hdlparse.verilog_parser as vlog
from PyQt6 import QtCore, QtWidgets
-from PyQt6.QtCore import QThread
+from PyQt6.QtCore import QThread, pyqtSignal
from configuration.Appconfig import Appconfig
import os
import watchdog.events
@@ -95,6 +95,23 @@ def createMakerWidget(self):
# self.grid.addWidget(self.creategroup(), 1, 0, 5, 0)
self.show()
+ def _stop_current_toggle(self):
+ global toggle_flag
+ if self.refreshoption in toggle_flag:
+ toggle_flag.remove(self.refreshoption)
+ if hasattr(self, 'event_handler') and self.event_handler.toggle.isRunning():
+ self.event_handler.toggle.requestInterruption()
+ self.event_handler.toggle.wait(2000)
+
+ def closeEvent(self, event):
+ self._stop_current_toggle()
+ if hasattr(self, '_rc_toggle') and self._rc_toggle.isRunning():
+ self._rc_toggle.requestInterruption()
+ self._rc_toggle.wait(2000)
+ if hasattr(self, 'observer') and self.observer.is_alive():
+ self.observer.stop()
+ super().closeEvent(event)
+
# This function is to Add new verilog file
def addverilog(self):
@@ -136,8 +153,7 @@ def addverilog(self):
global verilogFile
verilogFile[self.filecount] = self.verilogfile
- if self.refreshoption in toggle_flag:
- toggle_flag.remove(self.refreshoption)
+ self._stop_current_toggle()
self.observer = watchdog.observers.Observer()
self.event_handler = Handler(
@@ -159,8 +175,10 @@ def addverilog(self):
# (as the original one gets destroyed)
def refresh_change(self):
if self.refreshoption in toggle_flag:
- self.toggle = toggle(self.refreshoption)
- self.toggle.start()
+ if hasattr(self, '_rc_toggle') and self._rc_toggle.isRunning():
+ return
+ self._rc_toggle = toggle(self.refreshoption)
+ self._rc_toggle.start()
# It is used to refresh the file in eSim if its edited anywhere else
def refresh(self):
@@ -171,6 +189,7 @@ def refresh(self):
print("NgVeri File: " + self.verilogfile + " Refreshed")
self.obj_Appconfig.print_info(
"NgVeri File: " + self.verilogfile + " Refreshed")
+ self._stop_current_toggle()
self.observer = watchdog.observers.Observer()
self.event_handler = Handler(
self.verilogfile,
@@ -182,10 +201,6 @@ def refresh(self):
path=self.verilogfile,
recursive=True)
self.observer.start()
- # self.notify.start()
- global toggle_flag
- if self.refreshoption in toggle_flag:
- toggle_flag.remove(self.refreshoption)
# This function is used to save the edited file in eSim
def save(self):
@@ -321,7 +336,7 @@ def runmakerchip(self):
self.process.start(cmd)
print(
"Makerchip IDE command process pid ---------->",
- self.process.pid())
+ self.process.processId())
except BaseException as e:
print(e)
self.msg = QtWidgets.QErrorMessage(self)
@@ -444,6 +459,11 @@ def creategroup(self):
return self.trbox
+class _FileModifiedNotifier(QtCore.QObject):
+ """Bridges watchdog background thread to main thread for GUI notifications."""
+ modified = pyqtSignal(str)
+
+
# The Handler class is used to create a watch on the files using WatchDog
class Handler(watchdog.events.PatternMatchingEventHandler):
# this function initialisses the variable and the objects of watchdog
@@ -456,27 +476,28 @@ def __init__(self, verilogfile, refreshoption, observer):
self.obj_Appconfig = Appconfig()
self.observer = observer
self.toggle = toggle(self.refreshoption)
+ self._notifier = _FileModifiedNotifier()
+ self._notifier.modified.connect(self._show_modified_dialog)
- # if a file is modified, toggle starts to toggle the refresh button
- def on_modified(self, event):
- print("Watchdog received modified event - % s." % event.src_path)
+ def _show_modified_dialog(self, verilogfile):
msg = QtWidgets.QErrorMessage()
msg.setWindowTitle("eSim Message")
msg.showMessage(
- "NgVeri File: " +
- self.verilogfile +
- " modified. Please click on Refresh")
+ "NgVeri File: " + verilogfile + " modified. Please click on Refresh")
msg.exec()
+
+ # if a file is modified, toggle starts to toggle the refresh button
+ def on_modified(self, event):
+ print("Watchdog received modified event - % s." % event.src_path)
print("NgVeri File: " + self.verilogfile +
" modified. Please click on Refresh")
- # self.obj_Appconfig.print_info("NgVeri File:\
- # "+self.verilogfile+" modified. Please click on Refresh")
global toggle_flag
if self.refreshoption not in toggle_flag:
toggle_flag.append(self.refreshoption)
- # i.rm_watch()
self.observer.stop()
- self.toggle.start()
+ if not self.toggle.isRunning():
+ self.toggle.start()
+ self._notifier.modified.emit(self.verilogfile)
# class notify(QThread):
@@ -522,24 +543,23 @@ def on_modified(self, event):
# This class is used to toggle a button(change colour by toggling)
class toggle(QThread):
+ changeStyle = pyqtSignal(str)
+
# initialising the threads
def __init__(self, option):
QThread.__init__(self)
self.option = option
-
- def __del__(self):
- self.wait()
+ self.changeStyle.connect(option.setStyleSheet)
# running the thread to toggle
def run(self):
-
- while True:
- self.option.setStyleSheet("background-color: red")
- self.sleep(1)
- self.option.setStyleSheet("background-color: none")
- self.sleep(1)
- print(toggle_flag)
- if not self.option.isVisible():
+ while not self.isInterruptionRequested():
+ self.changeStyle.emit("background-color: red")
+ self.msleep(1000)
+ if self.isInterruptionRequested():
break
+ self.changeStyle.emit("background-color: none")
+ self.msleep(1000)
if self.option not in toggle_flag:
break
+ self.changeStyle.emit("")
diff --git a/src/maker/ModelGeneration.py b/src/maker/ModelGeneration.py
old mode 100755
new mode 100644
index a58d4a432..3950eb20f
--- a/src/maker/ModelGeneration.py
+++ b/src/maker/ModelGeneration.py
@@ -1000,7 +1000,7 @@ def runMake(self):
print("Running Make command in " + path_icm)
self.process = QtCore.QProcess(self)
self.process.start('sh', ['-c', self.cmd])
- print("make command process pid ---------- >", self.process.pid())
+ print("make command process pid ---------- >", self.process.processId())
self.termtitle("MAKE COMMAND")
self.termtext("Current Directory: " + path_icm)
diff --git a/src/maker/NgVeri.py b/src/maker/NgVeri.py
old mode 100755
new mode 100644
index 3b0f4c2da..3f4efc7ed
--- a/src/maker/NgVeri.py
+++ b/src/maker/NgVeri.py
@@ -402,7 +402,7 @@ def creategroup(self):
for item in self.data:
if item != "\n":
self.entry_var[self.count].addItem(item.strip())
- self.entry_var[self.count].activated[str].connect(self.edit_modlst)
+ self.entry_var[self.count].currentTextChanged.connect(self.edit_modlst)
self.trgrid.addWidget(self.entry_var[self.count], 1, 4, 1, 2)
self.count += 1
self.entry_var[self.count] = QtWidgets.QComboBox()
@@ -418,7 +418,7 @@ def creategroup(self):
for item in self.data:
if item != "\n":
self.entry_var[self.count].addItem(item.strip())
- self.entry_var[self.count].activated[str].connect(self.lint_off_edit)
+ self.entry_var[self.count].currentTextChanged.connect(self.lint_off_edit)
self.trgrid.addWidget(self.entry_var[self.count], 2, 4, 1, 2)
self.count += 1
self.entry_var[self.count] = QtWidgets.QLineEdit(self)
diff --git a/src/modelEditor/ModelEditor.py b/src/modelEditor/ModelEditor.py
index 51136ead2..c069e4b57 100644
--- a/src/modelEditor/ModelEditor.py
+++ b/src/modelEditor/ModelEditor.py
@@ -185,7 +185,7 @@ def bjt_click(self):
filetype = str(self.types.currentText())
self.openfiletype(filetype)
# When element selected from combo box, call setfiletype
- self.types.activated[str].connect(self.setfiletype)
+ self.types.currentTextChanged.connect(self.setfiletype)
def mos_click(self):
'''
@@ -207,7 +207,7 @@ def mos_click(self):
self.types.addItem('PMOS(Level-8 180um)')
filetype = str(self.types.currentText())
self.openfiletype(filetype)
- self.types.activated[str].connect(self.setfiletype)
+ self.types.currentTextChanged.connect(self.setfiletype)
def jfet_click(self):
'''
@@ -224,7 +224,7 @@ def jfet_click(self):
self.types.addItem('P-JFET')
filetype = str(self.types.currentText())
self.openfiletype(filetype)
- self.types.activated[str].connect(self.setfiletype)
+ self.types.currentTextChanged.connect(self.setfiletype)
def igbt_click(self):
'''
@@ -241,7 +241,7 @@ def igbt_click(self):
self.types.addItem('P-IGBT')
filetype = str(self.types.currentText())
self.openfiletype(filetype)
- self.types.activated[str].connect(self.setfiletype)
+ self.types.currentTextChanged.connect(self.setfiletype)
def magnetic_click(self):
'''
diff --git a/src/projManagement/newProject.py b/src/projManagement/newProject.py
index 18ef1b4ce..9163e7715 100644
--- a/src/projManagement/newProject.py
+++ b/src/projManagement/newProject.py
@@ -95,6 +95,7 @@ def createProject(self, projName):
'write permission on ' + self.workspace
)
self.msg.exec()
+ return None, None
# New KiCad v6 file extension
f.write("schematicFile " + self.projName + ".kicad_sch\n")