Created
December 27, 2012 11:33
-
-
Save SpaceManiac/4387574 to your computer and use it in GitHub Desktop.
Utils.py from Profile Master for use in formats
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# utils.py | |
# common utilities for profile master format files | |
from construct import * | |
from PyQt4 import QtCore, QtGui | |
import functools | |
# qt utilities | |
class Dialog(QtGui.QDialog): | |
def __init__(self, ui): | |
QtGui.QDialog.__init__(self) | |
self.ui = ui() | |
self.ui.setupUi(self) | |
self.show() | |
qconnect = QtGui.QWidget.connect | |
qsignal = QtCore.SIGNAL | |
# constructs | |
class MysteryCounter(): | |
def __init__(self): | |
self.num = 0 | |
def __call__(self, len): | |
self.num += 1 | |
return Field("mystery_%d" % self.num, len) | |
def Finish(self): | |
self.num += 1 | |
return FinishAdapter(OptionalGreedyRepeater(Field("mystery_%d" % self.num, 1))) | |
class FinishAdapter(Adapter): | |
def _decode(self, obj, ctx): | |
return ''.join(obj) | |
def _encode(self, obj, ctx): | |
return list(obj) | |
class WithContext(Construct): | |
def __init__(self, func): | |
Construct.__init__(self, "_WithContext") | |
self.func = func | |
def _parse(self, stream, context): | |
self.func(context) | |
class NullTerminateAdapter(Adapter): | |
def _encode(self, obj, ctx): | |
return obj | |
def _decode(self, obj, ctx): | |
idx = obj.find('\x00') | |
if idx >= 0: | |
return obj[:obj.find('\x00')] | |
else: | |
return obj | |
def echo(x): print x | |
def PrintContext(): | |
return WithContext(echo) | |
def PrintContextItem(field): | |
return WithContext(lambda ctx: echo(ctx[field])) | |
def PackedString(name, len=32): | |
return NullTerminateAdapter(String(name, len, padchar="\x00")) | |
# editables | |
class Editable(object): | |
text = "" | |
children = None | |
notes = "" | |
def edit(self, callback): | |
return | |
def construct(self, ctx): | |
return None | |
class EditableAdapter(Adapter): | |
def __init__(self, type, sub): | |
Adapter.__init__(self, sub) | |
self.type = type | |
def _decode(self, obj, ctx): | |
return self.type(obj, ctx) | |
def _encode(self, obj, ctx): | |
return obj.construct(ctx) | |
class NonEditable(Editable): | |
def __init__(self, val): | |
self.val = val | |
self.text = str(val) | |
self.notes = "Cannot edit values of type: %s" % type(val).__name__ | |
def edit(self, callback): | |
return | |
# base should be some variety of editable, func takes value & ctx, ctx may be None | |
def NoteWrapper(base, func): | |
class result(base): | |
def __init__(self, obj, ctx): | |
self.dict = {'value': obj} | |
base.__init__(self, self.dict, 'value') | |
self.notes = func(obj, ctx) | |
def edit(self, callback): | |
self.w_callback_ = callback | |
base.edit(self, self.w_callback) | |
def w_callback(self): | |
self.notes = func(self.dict['value'], None) | |
self.w_callback_() | |
def construct(self, ctx): | |
return self.dict['value'] | |
return result | |
# enumerations | |
#class EditEnum(Editable): | |
# def __init__(self, obj, ctx): | |
#def EnumWrapper( | |
# default editables | |
class DefaultEditable(Editable): | |
def __init__(self, cont, key): | |
self.cont = cont | |
self.key = key | |
@property | |
def text(self): | |
return self.cont[self.key] | |
class EditBoolean(DefaultEditable): | |
def edit(self, callback): | |
self.cont[self.key] = not self.cont[self.key] | |
callback() | |
class EditNumber(DefaultEditable): | |
def edit(self, callback): | |
from ui.editnumber import Ui_EditNumber | |
self.type = type(self.cont[self.key]) | |
self.callback = callback | |
self.dialog = Dialog(Ui_EditNumber) | |
self.dialog.ui.varLabel.setText(str(self.key)) | |
self.dialog.ui.lineEdit.setText(str(self.cont[self.key])) | |
self.dialog.ui.errorLabel.setText("") | |
qconnect(self.dialog.ui.buttonBox, qsignal("accepted()"), self.accept) | |
def accept(self): | |
value = str(self.dialog.ui.lineEdit.text()) | |
try: | |
if self.type == float: | |
result = self.type(value) | |
else: # int or long | |
base = 10 | |
if value.startswith("0x"): | |
base = 16 | |
value = value[2:] | |
result = int(value, base) | |
self.cont[self.key] = result | |
self.dialog.accept() | |
self.callback() | |
except ValueError: | |
self.dialog.ui.errorLabel.setText("Invalid value") | |
from texteditor import EditText | |
defaultEditors = { | |
bool: EditBoolean, | |
int: EditNumber, | |
float: EditNumber, | |
long: EditNumber, | |
str: EditText | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment