parent
							
								
									76ade9f5cd
								
							
						
					
					
						commit
						7069a3ff81
					
				| @ -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) | ||||
					Loading…
					
					
				
		Reference in new issue