#!/usr/bin/python3
import os,sys,time,re,traceback,platform
from utilities.Qt import QtGui, QtCore, QtWidgets
from utilities.templates import ui_layout as layout
from utilities import dio,REGISTERS,uploader
import constants,inspect
from functools import partial
from collections import OrderedDict
_translate = QtCore.QCoreApplication.translate
class myTimer():
def __init__(self,interval):
self.interval = interval
self.reset()
def reset(self):
self.timeout = time.time()+self.interval
def ready(self):
T = time.time()
dt = T - self.timeout
if dt>0: #timeout is ahead of current time
#if self.interval>5:print('reset',self.timeout,dt)
self.timeout = T - dt%self.interval + self.interval
#if self.interval>5:print(self.timeout)
return True
return False
def progress(self):
return 100*(self.interval - self.timeout + time.time())/(self.interval)
class AppWindow(QtWidgets.QMainWindow, layout.Ui_MainWindow):
p=None
ports = ['A','B','C','D']
logThis = QtCore.pyqtSignal(str)
logThisPlain = QtCore.pyqtSignal(bytes)
serialGaugeSignal = QtCore.pyqtSignal(int)
def __init__(self, parent=None, **kwargs):
super(AppWindow, self).__init__(parent)
self.setupUi(self)
self.VERSION = REGISTERS.VERSION_ATMEGA32 #This needs to be dynamically changed when hardware is connected
self.SPECIALS = REGISTERS.VERSIONS[self.VERSION]['SPECIALS']
self.REGISTERS = REGISTERS.VERSIONS[self.VERSION]['REGISTERS']
self.EXAMPLES_DIR = REGISTERS.VERSIONS[self.VERSION]['examples directory']
self.docks = [self.padock,self.pbdock,self.pcdock,self.pddock]
self.sensorList = []
self.monitoring = True
self.logRegisters = True
self.userHexRunning = False
self.uploadingHex = False
self.autoUpdateUserRegisters = False
self.CFile = None #'~/kuttyPy.c'
self.setTheme("material")
examples = [a for a in os.listdir(os.path.join(path["examples"],self.EXAMPLES_DIR)) if ('.py' in a) and a != 'kuttyPy.py'] #.py files except the library
self.exampleList.addItems(examples)
blinkindex = self.exampleList.findText('blink.py')
if blinkindex!=-1: #default example. blink.py present in examples directory
self.exampleList.setCurrentIndex(blinkindex)
######## PYTHON CODE
self.codeThread = QtCore.QThread()
self.codeEval = self.codeObject(self.REGISTERS)
self.codeEval.moveToThread(self.codeThread)
self.codeEval.finished.connect(self.codeThread.quit)
self.codeEval.logThis.connect(self.appendLog) #Connect to the log window
self.logThis.connect(self.appendLog) #Connect to the log window
self.logThisPlain.connect(self.appendLogPlain) #Connect to the log window
self.serialGaugeSignal.connect(self.setSerialgauge)
self.codeThread.started.connect(self.codeEval.execute)
self.codeThread.finished.connect(self.codeFinished)
######### C CODE UPLOADER
self.uploadThread = QtCore.QThread()
self.UploadObject = self.uploadObject()
self.UploadObject.moveToThread(self.uploadThread)
self.UploadObject.finished.connect(self.uploadThread.quit)
self.UploadObject.logThis.connect(self.appendLog) #Connect to the log window
self.UploadObject.logThisPlain.connect(self.appendLogPlain) #Connect to the log window. add plain text
self.logThis.connect(self.appendLog) #Connect to the log window
self.uploadThread.started.connect(self.UploadObject.execute)
self.uploadThread.finished.connect(self.codeFinished)
self.commandQ = []
self.btns={}
self.registers = []
self.addPins()
self.statusBar = self.statusBar()
self.makeBottomMenu()
global app
self.initializeCommunications()
self.updatedRegs=OrderedDict()
self.currentRegister = 0
self.getRegs=[
('PINA',self.updateInputs),
('PINB',self.updateInputs),
('PINC',self.updateInputs),
('PIND',self.updateInputs),
]
self.pending = {
'status':myTimer(constants.STATUS_UPDATE_INTERVAL),
'update':myTimer(constants.AUTOUPDATE_INTERVAL),
}
serialgaugeoptions = {'name':'Serial Monitor', 'init':print, 'read':None,
'fields':['Value'],
'min':[0],
'max':[255]}
self.serialGauge = dio.DIOSENSOR(self,serialgaugeoptions)
self.startTime = time.time()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updateEverything)
self.timer.start(20)
#Auto-Detector
self.shortlist=KuttyPyLib.getFreePorts()
def newRegister(self):
reg = dio.REGEDIT(self.commandQ)
#self.registerLayout.addWidget(reg)
#self.registers.append(reg)
#TODO: Convert layout to listwidget to enable re-ordering
regItem = QtWidgets.QListWidgetItem()
regItem.setSizeHint(QtCore.QSize(200,40))
self.registerList.addItem(regItem)
self.registerList.setItemWidget(regItem,reg)
self.registers.append(regItem)
def addPins(self):
for port,dock in zip(self.ports,[self.palayout,self.pblayout,self.pclayout,self.pdlayout]):
checkbox = dio.REGVALS(port)
dock.addWidget(checkbox)
self.btns[port] = checkbox
seq = range(7,-1,-1)
if port == 'C':seq = reversed(seq) #PORTC pins are ordered top to bottom
for a in seq:
name = 'P'+port+str(a)
checkbox = dio.widget(name,self.commandQ,extra = self.SPECIALS.get(name,''))
dock.addWidget(checkbox)
self.btns[name] = checkbox
def tabChanged(self,index):
if index != 0 : #examples/editor tab. disable monitoring
self.monitoring = False
for a in self.docks:
a.hide()
else: #Playground . enable monitoring and control.
self.monitoring = True
self.autoRefreshUserRegisters.setChecked(False)
self.userRegistersAutoRefresh(False)
for a in self.docks:
a.show()
################USER CODE SECTION####################
class codeObject(QtCore.QObject):
finished = QtCore.pyqtSignal()
logThis = QtCore.pyqtSignal(str)
code = ''
def __init__(self,REGISTERS):
super(AppWindow.codeObject, self).__init__()
self.PORTMAP = {v: k for k, v in REGISTERS.items()} #Lookup port name based on number
self.compiled = ''
self.SR = None
self.GR = None
self.evalGlobals = {}
self.evalGlobals['getReg'] = self.getReg
self.evalGlobals['setReg'] = self.setReg
self.evalGlobals['print'] = self.printer
def setCode(self,code,**kwargs):
try:
self.compiled = compile(code.encode(), '<string>', mode='exec')
except SyntaxError as err:
error_class = err.__class__.__name__
detail = err.args[0]
line_number = err.lineno
return _translate("AppWindow", '''<span style="color:red;">{err} at line {num} : {detail}</span>''').format(err = error_class, num = line_number, detaim = detail)
except Exception as err:
error_class = err.__class__.__name__
detail = err.args[0]
cl, exc, tb = sys.exc_info()
line_number = traceback.extract_tb(tb)[-1][1]
return _translate("AppWindow", '''<span style="color:red;">{err} at line {num} : {detail}</span>''').format(err = error_class, num = line_number, detaim = detail)
self.SR = kwargs.get('setReg')
self.GR = kwargs.get('getReg')
self.evalGlobals = kwargs
self.evalGlobals['getReg'] = self.getReg #Overwrite these three. They will be wrapped.
self.evalGlobals['setReg'] = self.setReg
self.evalGlobals['print'] = self.printer
return ''
def printer(self,*args):
self.logThis.emit('''<span style="color:cyan;">%s</span>'''%(' '.join([str(a) for a in args])))
def setReg(self,reg,value):
html=u'''<pre><span>W\u2193</span>{0:s}\t{1:d}\t0x{1:02x} / 0b{1:08b}</pre>'''.format(self.PORTMAP.get(reg,''),value)
self.logThis.emit(html)
self.SR(reg,value)
def getReg(self,reg):
value = self.GR(reg)
html=u'''<pre><span>R\u2191</span>{0:s}\t{1:d}\t0x{1:02x} / 0b{1:08b}</pre>'''.format(self.PORTMAP.get(reg,''),value)
self.logThis.emit(html)
return value
def execute(self):
#old = sys.stdout
#olde = sys.stderr
#sys.stdout = self.toLog(self.logThis)
#sys.stderr = self.toLog(self.logThis)
try:
exec(self.compiled,{},self.evalGlobals)
except SyntaxError as err:
error_class = err.__class__.__name__
detail = err.args[0]
line_number = err.lineno
self.logThis.emit(_translate("AppWindow", '''<span style="color:red;">{err} at line {num} : {detail}</span>''').format(err = error_class, num = line_number, detail = detail))
except Exception as err:
error_class = err.__class__.__name__
detail = err.args[0]
cl, exc, tb = sys.exc_info()
line_number = traceback.extract_tb(tb)[-1][1]
self.logThis.emit(_translate("AppWindow", '''<span style="color:red;">{err} at line {num} : {detail}</span>''').format(err = error_class, num = line_number, detail = detail))
#sys.stdout = old
#sys.stderr = olde
self.logThis.emit(_translate("AppWindow", "Finished executing user code"))
self.finished.emit()
def runCode(self):
#if self.p:
# try:
# self.p.fd.read() #Clear junk
# self.p.fd.close()
# except:pass
if self.codeThread.isRunning():
print('one code is already running')
return
self.log.clear() #clear the log window
self.log.setText(_translate("AppWindow", '''<span style="color:green;">----------User Code Started-----------</span>'''))
kwargs = {}
for a in dir(self.p):
attr = getattr(self.p, a)
if inspect.ismethod(attr) and a[:2]!='__':
kwargs[a] = attr
compilemsg = self.codeEval.setCode('{0:s}'.format(self.userCode.text()),**kwargs)
if len(compilemsg):
self.log.append(compilemsg)
return
self.codeThread.start()
self.userCode.setStyleSheet("border: 3px dashed #53ffff;")
self.tabs.setTabEnabled(0,False)
def codeFinished(self):
print('finished')
self.tabs.setTabEnabled(0,True)
self.userCode.setStyleSheet("")
self.uploadingHex = False
def abort(self):
if self.codeThread.isRunning():
self.log.append(_translate("AppWindow", '''<span style="color:red;">----------Kill Signal(Doesn't work yet. Restart the application)-----------</span>'''))
self.codeThread.quit()
self.codeThread.terminate()
def getReg(self,reg,record = True):
val = self.p.getReg(reg)
if record:
self.updatedRegs[reg] = [0,val]
return val
def setReg(self,reg,val,record = True):
self.p.setReg(reg,val)
if record:
self.updatedRegs[reg] = [1,val]
return val
def appendLog(self,txt):
self.log.append(txt)
def appendLogPlain(self,txt):
self.log.moveCursor(QtGui.QTextCursor.End)
self.log.insertPlainText(txt.decode('ascii'))
def setSerialgauge(self,val):
self.serialGauge.setValue([val])
def genLog(self):
html='''<table border="1" align="center" cellpadding="1" cellspacing="0" style="font-family:arial,helvetica,sans-serif;font-size:9pt;">
<tbody><tr><td colspan="4">%s</td></tr>'''%(time.ctime())
#html+='''<tr><td style="background-color:#77cfbb;">R/W</td><td style="background-color:#77cfbb;">REGISTER</td>
#<td style="background-color:#77cfbb;">Value</td><td style="background-color:#77cfbb;">Hex/Binary</td></tr>'''
for a in self.updatedRegs:
row = self.updatedRegs[a]
html+=u'''
<tr>
<td>{0:s}</td>
<td>{1:s}</td>
<td>{2:d}</td>
<td>0b{2:08b} | 0x{2:02x}</td>
</tr>
'''.format(u'W \u2193' if row[0] else u'R \u2191',a,row[1])
html+="</tbody></table>"
self.log.setHtml(html)
def userRegistersAutoRefresh(self,state):
self.autoUpdateUserRegisters = state
def updateEverything(self):
self.locateDevices()
if not self.checkConnectionStatus():return
#KuttyPy monitor has handed over control to native code. act as serial monitor/ debug window
if self.uploadingHex:
return
if self.userHexRunning:
t = self.p.fd.read(self.p.fd.in_waiting)
if len(t):
self.serialGaugeSignal.emit(t[0])
self.logThisPlain.emit(t)
return
#self.setTheme('material')
if self.codeThread.isRunning():
return
if self.autoUpdateUserRegisters:
for a in range(self.registerList.count()):
self.registerList.itemWidget(self.registerList.item(a)).execute()
while len(self.commandQ):
if not self.centralWidget().isEnabled():
return
a = self.commandQ.pop(0)
if a[0] == 'DSTATE': #Digital Out ['DSTATE','Pxx',state]
pname = 'PORT'+a[1][1].upper()
bit = int(a[1][2])
reg = self.getReg(pname)
reg &=~ (1<<bit)
if(a[2]):reg |= (1<<bit)
self.setReg(pname,reg);
elif a[0] == 'DTYPE': #Digital pin I/O ['DTYPE','Pxx',state]
pname = 'DDR'+a[1][1].upper()
bit = int(a[1][2])
reg = self.getReg(pname)
reg &=~ (1<<bit)
if(a[2]):reg |= (1<<bit)
self.setReg(pname,reg);
elif a[0] == 'WRITE': #['WRITE','REGNAME',val]
self.setReg(a[1],a[2]);
elif a[0] == 'READ': #['READ','REGNAME',function]
val = self.getReg(a[1])
a[2](val)
elif a[0] == 'CNTR1': #['CNTR1',output with setValue function]
cl = self.getReg('TCNT1L',False)
ch = self.getReg('TCNT1H',False)
a[1].setValue(cl|(ch<<8))
elif a[0] == 'ADC': #['ADC',ADMUX,output with setValue function, to log, or not to log]
self.setReg('ADMUX',a[1],a[3])
self.setReg('ADCSRA',196|1,a[3])
adcl = self.getReg('ADCL',a[3])
adch = self.getReg('ADCH',a[3])
a[2].setValue(adcl|(adch<<8))
for a in self.sensorList:
if a[0].isVisible():
a[0].setValue(a[0].read())
if self.enableLog.isChecked():
if self.clearLog.isChecked() and len(self.updatedRegs):
self.log.clear()
if len(self.updatedRegs):
self.genLog()
self.updatedRegs = OrderedDict()
if self.pending['status'].ready() and self.monitoring:
val = self.p.getReg(self.getRegs[self.currentRegister][0])
self.getRegs[self.currentRegister][1](self.getRegs[self.currentRegister][0],val)
self.currentRegister +=1
if self.currentRegister==len(self.getRegs):
self.currentRegister = 0
for a in self.ports:
self.btns[a].setRegs(self.p.REGSTATES)
if self.pending['update'].ready():
pass
#print('update')
def updateInputs(self,port,value):
portchar = port[3]
for a in range(8):
btn = self.btns['P'+portchar+str(a)]
btn.nameIn.setChecked((value>>a)&1)
if portchar == 'A': #ADC
if btn.currentPage == 2: #ADC Page displayed
self.commandQ.append(['ADC',btn.ADMUX,btn,btn.logstate])
elif type(btn)==dio.DIOCNTR and btn.currentPage==2: # CNTR
self.commandQ.append(['CNTR1',btn.slider])
############ I2C SENSORS #################
def I2CScan(self):
if self.p.connected:
x = self.p.I2CScan()
print('Responses from: ',x)
for a in self.sensorList:
a[0].setParent(None)
a[1].setParent(None)
self.sensorList = []
for a in x:
s = self.p.sensors.get(a,None)
if s is not None:
btn = QtWidgets.QPushButton(s['name']+':'+hex(a))
dialog = dio.DIOSENSOR(self,s)
btn.clicked.connect(dialog.launch)
self.sensorLayout.addWidget(btn)
self.sensorList.append([dialog,btn])
continue
s = self.p.controllers.get(a,None)
if s is not None:
btn = QtWidgets.QPushButton(s['name']+':'+hex(a))
dialog = dio.DIOCONTROL(self,s)
btn.clicked.connect(dialog.launch)
self.sensorLayout.addWidget(btn)
#self.sensorList.append([dialog,btn])
continue
s = self.p.special.get(a,None)
if s is not None:
btn = QtWidgets.QPushButton(s['name']+':'+hex(a))
dialog = dio.DIOROBOT(self,s)
btn.clicked.connect(dialog.launch)
self.sensorLayout.addWidget(btn)
#self.sensorList.append([dialog,btn])
continue
def loadExample(self,filename):
self.userCode.setText(open(os.path.join(path["examples"],self.EXAMPLES_DIR,filename), "r").read())
########################### UPLOAD HEX FILE #######################
class uploadObject(QtCore.QObject):
finished = QtCore.pyqtSignal()
logThis = QtCore.pyqtSignal(str)
logThisPlain = QtCore.pyqtSignal(bytes)
fname = ''
p = None
def __init__(self):
super(AppWindow.uploadObject, self).__init__()
def config(self,mode,p,fname):
self.p = p
self.fname = fname
self.mode = mode
def execute(self):
if self.mode == 'compileupload':
try:
import subprocess
fname = self.fname.split(".")[0]
cmd = 'avr-gcc -Wall -O2 -mmcu=%s -o %s %s' %('atmega32',fname,self.fname)
res = subprocess.getstatusoutput(cmd)
if res[0] != 0:
self.logThis.emit(_translate("AppWindow", '''<span style="color:red;">Compile Error: {res}</span>''').format(res = res[1]))
self.finished.emit()
return
else:
self.logThis.emit('''<span style="color:white;">%s</span><br>'''%res[1])
cmd = 'avr-objcopy -j .text -j .data -O ihex %s %s.hex' %(fname,fname)
res = subprocess.getstatusoutput(cmd)
self.logThis.emit('''<span style="color:white;">%s</span><br>'''%res[1])
cmd = 'avr-objdump -S %s > %s.lst'%(fname,fname)
res = subprocess.getstatusoutput(cmd)
self.logThis.emit('''<span style="color:white;">%s</span><br>'''%res[1])
if self.fname[-2:] in ['.c','.C']:
self.fname = self.fname[:-2]+'.hex' #Replace .c with .hex
self.mode = 'upload'
self.logThis.emit(_translate("AppWindow", '''<span style="color:green;">Generated Hex File</span>'''))
self.logThis.emit(_translate("AppWindow", '''<span style="color:green;">Finished Compiling: Generated Hex File</span>'''))
except Exception as err:
self.logThis.emit(_translate("AppWindow", '''<span style="color:red;">Failed to Compile: {err}</span>''').format(str(err)))
if self.p.connected:
if self.mode == 'upload':
try:
self.p.fd.setRTS(0);time.sleep(0.01);self.p.fd.setRTS(1);time.sleep(0.4)
dude = uploader.Uploader(self.p.fd, hexfile=self.fname,logger = self.logThis)
dude.program()
dude.verify()
self.p.fd.setRTS(0);time.sleep(0.01);self.p.fd.setRTS(1);time.sleep(0.2)
self.p.get_version()
self.logThis.emit(_translate("AppWindow", '''<span style="color:green;">Finished upload</span>'''))
except Exception as err:
self.logThis.emit(_translate("AppWindow", '''<span style="color:red;">Failed to upload</span>'''))
self.finished.emit()
def uploadHex(self):
filename = QtWidgets.QFileDialog.getOpenFileName(self,_translate("AppWindow", "Open a hex file to upload to your KuttyPy"), "", _translate("AppWindow", "Hex Files (*.hex)"))
if len(filename[0]):
#self.userCode.setStyleSheet("border: 3px dashed #53ffff;")
#self.tabs.setTabEnabled(0,False)
self.uploadingHex = True
self.log.clear()
self.log.setText(_translate("AppWindow", '''<span style="color:cyan;">-- Uploading Code --</span><br>'''))
self.UploadObject.config('upload',self.p,filename[0])
self.uploadThread.start()
def openFile(self):
filename = QtWidgets.QFileDialog.getOpenFileName(self,_translate("AppWindow", "Open a C file to edit"), path["examples"], _translate("AppWindow", "C Files (*.c *.C)"))
if len(filename[0]):
self.filenameLabel.setText(filename[0])
self.CFile = filename[0]
self.log.clear()
self.log.setText(_translate("AppWindow", '''<span style="color:cyan;">-- Opened File: {f} --</span><br>''').format(f = filename[0]))
if 'inux' in platform.system(): #Linux based system
os.system('%s %s' % ('xdg-open', filename[0]))
else:
os.system('%s %s' % ('open', filename[0]))
def compileAndUpload(self):
if self.CFile:
self.uploadingHex = True
self.log.clear()
self.log.setText(_translate("AppWindow", '''<span style="color:cyan;">-- Compiling and Uploading Code --</span><br>'''))
self.UploadObject.config('compileupload',self.p,self.CFile)
self.uploadThread.start()
##############################
def setTheme(self,theme):
self.setStyleSheet("")
self.setStyleSheet(open(os.path.join(path["themes"],theme+".qss"), "r").read())
def initializeCommunications(self,port=False):
if self.p:
try:self.p.fd.close()
except:pass
if port:
self.p = KuttyPyLib.connect(port = port)
else:
self.p = KuttyPyLib.connect(autoscan=True)
if self.p.connected:
self.userApplication.setChecked(False)
self.setWindowTitle(_translate("AppWindow", 'KuttyPy Interactive Console [{0:s}]').format(self.p.portname))
else:
self.setWindowTitle(_translate("AppWindow", 'KuttyPy Interactive Console [ Hardware not detected ]'))
def jumpToApplication(self,state):
if self.p:
if state:
self.userHexRunning=True
self.p.fd.write(b'j') #Skip to application (Bootloader resets)
for a in self.docks:
a.setEnabled(False)
self.tabs.setEnabled(False)
self.log.clear()
self.log.setText(_translate("AppWindow", '''<span style="color:cyan;">-- Serial Port Monitor --</span><br>'''))
self.serialGauge.show()
else:
self.p.fd.setRTS(0) #Trigger a reset
time.sleep(0.01)
self.p.fd.setRTS(1)
time.sleep(0.1)
while self.p.fd.in_waiting:
self.p.fd.read()
self.p.get_version()
for a in self.docks:
a.setEnabled(True)
self.userHexRunning=False
self.tabs.setEnabled(True)
self.serialGauge.hide()
else:
if self.isChecked():
self.setChecked(False)
def makeBottomMenu(self):
try:self.pushbutton.setParent(None)
except:pass
self.pushbutton = QtWidgets.QPushButton(_translate("AppWindow", 'Menu'))
self.pushbutton.setStyleSheet("height: 13px;padding:3px;color: #FFFFFF;")
menu = QtWidgets.QMenu()
menu.addAction(_translate("AppWindow", 'Save Window as Svg'), self.exportSvg)
#Theme
self.themeAction = QtWidgets.QWidgetAction(menu)
themes = [a.split('.qss')[0] for a in os.listdir(path["themes"]) if '.qss' in a]
self.themeBox = QtWidgets.QComboBox(); self.themeBox.addItems(themes)
self.themeBox.currentIndexChanged['QString'].connect(self.setTheme)
self.themeAction.setDefaultWidget(self.themeBox)
menu.addAction(self.themeAction)
self.pushbutton.setMenu(menu)
self.userApplication = QtWidgets.QCheckBox(_translate("AppWindow", "User App"));
self.userApplication.toggled['bool'].connect(self.jumpToApplication)
self.statusBar.addPermanentWidget(self.userApplication)
self.hexUploadButton = QtWidgets.QPushButton(_translate("AppWindow", "Upload Hex"));
self.hexUploadButton.clicked.connect(self.uploadHex)
self.statusBar.addPermanentWidget(self.hexUploadButton)
self.speedbutton = QtWidgets.QComboBox(); self.speedbutton.addItems([_translate("AppWindow", 'Slow'), _translate("AppWindow", 'Fast') ,_translate("AppWindow", 'Ultra')]);
self.speedbutton.setCurrentIndex(1);
self.speedbutton.currentIndexChanged['int'].connect(self.setSpeed)
self.statusBar.addPermanentWidget(self.speedbutton)
self.statusBar.addPermanentWidget(self.pushbutton)
def setSpeed(self,index):
self.timer.setInterval([100,20,5][index])
def locateDevices(self):
try:L = KuttyPyLib.getFreePorts(self.p.portname)
except Exception as e:print(e)
total = len(L)
menuChanged = False
if L != self.shortlist:
menuChanged = True
if self.p.connected:
if self.p.portname not in L:
self.setWindowTitle(_translate("AppWindow", 'Error : Device Disconnected'))
QtWidgets.QMessageBox.warning(self, 'Connection Error', 'Device Disconnected. Please check the connections')
try:
self.p.fd.close()
self.p.portname = None
except:pass
self.p.connected = False
self.setWindowTitle(_translate("AppWindow", 'KuttyPy Interactive Console [ Hardware not detected ]'))
elif True in L.values():
reply = QtWidgets.QMessageBox.question(self, 'Connection', 'Device Available. Connect?', QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
self.initializeCommunications()
#update the shortlist
self.shortlist=L
def checkConnectionStatus(self,dialog=False):
if self.p.connected:return True
else:
if dialog: QtWidgets.QMessageBox.warning(self, 'Connection Error', 'Device not connected. Please connect a KuttyPy to the USB port')
return False
def updateStatus(self):
if not self.checkConnectionStatus():
self.countLabel.setText('Not Connected')
return
try:
state,cnt = self.p.getStatus()
self.currentState = state
self.countLabel.setText('%s: %d'%(_translate("AppWindow", "Running") if state else _translate("AppWindow", "Paused"),cnt))
except:
self.countLabel.setText('Disconnect!')
self.p.fd.close()
######## WINDOW EXPORT SVG
def exportSvg(self):
from utilities.Qt import QtSvg
path, _filter = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File', '~/')
if path:
generator = QtSvg.QSvgGenerator()
generator.setFileName(path)
target_rect = QtCore.QRectF(0, 0, 800, 600)
generator.setSize(target_rect.size().toSize())#self.size())
generator.setViewBox(self.rect())
generator.setTitle(_translate("AppWindow", "Your title"))
generator.setDescription(_translate("AppWindow", "some description"))
p = QtGui.QPainter()
p.begin(generator)
self.render(p)
p.end()
def translators(langDir, lang=None):
"""
create a list of translators
@param langDir a path containing .qm translation
@param lang the preferred locale, like en_IN.UTF-8, fr_FR.UTF-8, etc.
@result a list of QtCore.QTranslator instances
"""
if lang==None:
lang=QtCore.QLocale.system().name()
result=[]
qtTranslator=QtCore.QTranslator()
qtTranslator.load("qt_" + lang,
QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath))
result.append(qtTranslator)
# path to the translation files (.qm files)
sparkTranslator=QtCore.QTranslator()
sparkTranslator.load(lang[:2]+".qm", langDir)
result.append(sparkTranslator)
return result
def firstExistingPath(l):
"""
Returns the first existing path taken from a list of
possible paths.
@param l a list of paths
@return the first path which exists in the filesystem, or None
"""
for p in l:
if os.path.exists(p):
return p
return None
def common_paths():
"""
Finds common paths
@result a dictionary of common paths
"""
path={}
curPath = os.path.dirname(os.path.realpath(__file__))
path["current"] = curPath
sharedPath = "/usr/share/kuttypy"
path["translation"] = firstExistingPath(
[os.path.join(p, "lang") for p in
(curPath, sharedPath,)])
path["utilities"] = firstExistingPath(
[os.path.join(p,'utilities') for p in
(curPath, sharedPath,)])
path["templates"] = firstExistingPath(
[os.path.join(p,'utilities','templates') for p in
(curPath, sharedPath,)])
path["themes"] = firstExistingPath(
[os.path.join(p,'utilities','themes') for p in
(curPath, sharedPath,)])
path["examples"] = firstExistingPath(
[os.path.join(p,'examples') for p in
(curPath, sharedPath,)])
path["editor"] = firstExistingPath(
[os.path.join(p,'editor') for p in
(curPath, sharedPath,)])
lang=str(QtCore.QLocale.system().name())
shortLang=lang[:2]
return path
if __name__ == "__main__":
path = common_paths()
the_translators = translators(path['translation'])
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
app = QtWidgets.QApplication(sys.argv)
for t in the_translators:
app.installTranslator(t)
import KuttyPyLib
myapp = AppWindow(app=app, path=path)
myapp.show()
r = app.exec_()
'''
if myapp.p.connected:
myapp.p.fd.write(b'j')
#myapp.p.fd.setRTS(0)
#time.sleep(0.01)
#myapp.p.fd.setRTS(1)
'''
app.deleteLater()
sys.exit(r)