added the ini editor

This commit is contained in:
2018-02-16 20:34:52 +01:00
parent 76ade9f5cd
commit 7069a3ff81
5 changed files with 205 additions and 5 deletions
+3 -2
View File
@@ -14,7 +14,7 @@ class EventReport:
class Client:
""" GEX client """
def __init__(self, transport):
def __init__(self, transport, load_units=True):
"""
Set up the client, looking up the GEX USB device using the S/N.
You may need to configure the udev rule to have direct access.
@@ -55,7 +55,8 @@ class Client:
self.unit_lu = {}
self.report_handlers = {}
self.load_units()
if load_units:
self.load_units()
def close(self):
self.transport.close()
+1
View File
@@ -184,6 +184,7 @@ class TrxRawUSB (BaseGexTransport):
# Tell the thread to shut down
self._ending = True
self._thread.join()
usb.util.dispose_resources(self._dev)
def write(self, buffer):
""" Send a buffer of bytes """
+119
View File
@@ -0,0 +1,119 @@
#!/bin/env python3
import gex
import sys
from PyQt4 import QtGui, QtCore
import ini_syntax
class GexIniEditor(QtGui.QMainWindow):
"""
Gexync is a GEX ini file editor.
The editor loads the INI file through the communication interface
without having to mount the virtual filesystem, which is unreliable
on some systems.
This utility allows live editing of the UNITS.INI file.
On save, a new version is loaded with formatting and error messages
generated by GEX, as if the virtual config filesystem was re-mounted.
The editor does not keep GEX claimed, instead does so only when needed.
This allows testing of the current configuration without having to close
and reopen the editor.
"""
def __init__(self):
super().__init__()
self.initUI()
# TODO let user pick GEX device if multiple
def initToolbar(self):
icon = self.style().standardIcon(QtGui.QStyle.SP_BrowserReload)
loadAction = QtGui.QAction(icon, 'Reload', self)
loadAction.setShortcut('Ctrl+O')
loadAction.triggered.connect(self.gexLoad)
icon = self.style().standardIcon(QtGui.QStyle.SP_DialogSaveButton)
syncAction = QtGui.QAction(icon, 'Write Changes', self)
syncAction.setShortcut('Ctrl+S')
syncAction.triggered.connect(self.gexSync)
icon = self.style().standardIcon(QtGui.QStyle.SP_DialogOkButton)
persAction = QtGui.QAction(icon, 'Persist, Close', self)
persAction.setShortcut('Ctrl+P')
persAction.triggered.connect(self.gexPersist)
self.toolbar = self.addToolBar('Toolbar')
self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.toolbar.addAction(loadAction)
self.toolbar.addAction(syncAction)
self.toolbar.addSeparator()
self.toolbar.addAction(persAction)
def initEditor(self):
self.editor = QtGui.QPlainTextEdit()
# Editor background and text color
pal = QtGui.QPalette()
bgc = QtGui.QColor(0xFFFFF6)
pal.setColor(QtGui.QPalette.Base, bgc)
textc = QtGui.QColor(0x000000)
pal.setColor(QtGui.QPalette.Text, textc)
self.editor.setPalette(pal)
# Font
font = QtGui.QFont('Liberation Mono', 12)
font.setStyleHint(QtGui.QFont.TypeWriter)
self.editor.setFont(font)
# Initial size
self.highlight = ini_syntax.IniHighlighter(self.editor.document())
def initUI(self):
self.setWindowTitle('GEX config file editor')
self.initToolbar()
self.initEditor()
self.setCentralWidget(self.editor)
self.show()
self.gexLoad()
def gexLoad(self):
self.editor.setPlainText("")
self.editor.repaint()
client = gex.Client(gex.TrxRawUSB(), load_units=False)
read_ini = client.ini_read()
client.close()
self.editor.setPlainText(read_ini)
self.highlight.rehighlight()
def gexSync(self):
new_txt = self.editor.toPlainText()
self.editor.setPlainText("")
self.editor.repaint()
client = gex.Client(gex.TrxRawUSB(), load_units=False)
client.ini_write(new_txt)
read_ini = client.ini_read()
client.close()
self.editor.setPlainText(read_ini)
self.highlight.rehighlight()
def gexPersist(self):
client = gex.Client(gex.TrxRawUSB(), load_units=False)
client.ini_persist()
client.close()
self.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
editor = GexIniEditor()
# centered resize
w = 800
h = 900
ss = app.desktop().availableGeometry().size()
editor.setGeometry(int(ss.width() / 2 - w / 2), int(ss.height() / 2 - h / 2), w, h)
sys.exit(app.exec_())
+81
View File
@@ -0,0 +1,81 @@
# syntax.py
# This is a companion file to gexync.py
# based on https://wiki.python.org/moin/PyQt/Python%20syntax%20highlighting
from PyQt4.QtCore import QRegExp
from PyQt4.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter
def format(color, style=''):
"""Return a QTextCharFormat with the given attributes.
"""
_color = QColor()
_color.setNamedColor(color)
_format = QTextCharFormat()
_format.setForeground(_color)
if 'bold' in style:
_format.setFontWeight(QFont.Bold)
if 'italic' in style:
_format.setFontItalic(True)
return _format
# Syntax styles that can be shared by all languages
STYLES = {
'operator': format('red'),
'string': format('magenta'),
'comment': format('#6C8A70', 'italic'),
'key': format('#008AFF'),
'numbers': format('brown'),
'section': format('black', 'bold'),
}
class IniHighlighter (QSyntaxHighlighter):
# Python braces
def __init__(self, document):
QSyntaxHighlighter.__init__(self, document)
rules = [
(r'=', 0, STYLES['operator']),
(r'\b[YN]\b', 0, STYLES['numbers']),
# Double-quoted string, possibly containing escape sequences
(r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
# Single-quoted string, possibly containing escape sequences
(r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES['string']),
# Numeric literals
(r'\b[+-]?[0-9]+\b', 0, STYLES['numbers']),
(r'\b[+-]?0[xX][0-9A-Fa-f]+\b', 0, STYLES['numbers']),
(r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, STYLES['numbers']),
# From '#' until a newline
(r'#[^\n]*', 0, STYLES['comment']),
(r'^\[.+\]', 0, STYLES['section']),
(r'^[a-zA-Z0-9_-]+\s?=', 0, STYLES['key']),
]
# Build a QRegExp for each pattern
self.rules = [(QRegExp(pat), index, fmt)
for (pat, index, fmt) in rules]
def highlightBlock(self, text):
"""Apply syntax highlighting to the given block of text.
"""
# Do other syntax formatting
for expression, nth, format in self.rules:
index = expression.indexIn(text, 0)
while index >= 0:
# We actually want the index of the nth match
index = expression.pos(nth)
length = len(expression.cap(nth))
self.setFormat(index, length, format)
index = expression.indexIn(text, index + length)
self.setCurrentBlockState(0)
+1 -3
View File
@@ -18,9 +18,7 @@ with gex.Client(transport) as client:
if True:
sipo = gex.SIPO(client, 'sipo')
while True:
sipo.load([[0xFF], [0xAA], [0x11], [0x00]])
time.sleep(0.2)
sipo.load([[0xA5], [0xFF]])
if False:
adc = gex.ADC(client, 'adc')