added the ini editor

doublebuf
Ondřej Hruška 6 years ago
parent 76ade9f5cd
commit 7069a3ff81
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 5
      gex/Client.py
  2. 1
      gex/transport.py
  3. 119
      gexync.py
  4. 81
      ini_syntax.py
  5. 4
      main.py

@ -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()

@ -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 """

@ -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_())

@ -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)

@ -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')

Loading…
Cancel
Save