class DiffGUI(object): ' diff gui class ' def __init__(self): ' make a diff method with GUI ' self.dialog = QDialog() self.diff_path = None # directory auto completer self.completer = QCompleter(self.dialog) self.dirs = QDirModel(self.dialog) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) #self.completer.setCompletionMode(QCompleter.InlineCompletion) self.group1 = QGroupBox() self.group1.setTitle('Diff') self.frmt = QComboBox(self.group1) self.frmt.addItems(['Unified', 'Normal', 'Context']) self.file1 = QLineEdit() self.file1.setPlaceholderText('/full/path/to/one_file.py') self.file1.setCompleter(self.completer) self.file2 = QLineEdit() self.file2.setPlaceholderText('/full/path/to/another_file.py') self.file2.setCompleter(self.completer) self.fout = QLineEdit() self.fout.setText(''.join((path.join(gettempdir(), datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff'))))) self.fout.setPlaceholderText('/full/path/to/output_file.diff') self.fout.setCompleter(self.completer) self.regex = QLineEdit() self.regex.setPlaceholderText('DONT use unless you know what are doing') self.regex.setToolTip('Do NOT use unless you know what you are doing !') self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.borig.clicked.connect(lambda: self.file1.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bmodi.clicked.connect(lambda: self.file2.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bout.clicked.connect(lambda: self.fout.setText(str( QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file', path.expanduser("~"), ';;(*.diff)')))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('Original file full path'), self.file1, self.borig, QLabel('Modified file full path'), self.file2, self.bmodi, QLabel('Output file full Path'), self.fout, self.bout, QLabel('Diff Output Format'), self.frmt, QLabel('Diff REGEX to Ignore (ADVANCED)'), self.regex): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle('Options') self.nwfl = QCheckBox('Treat new files as Empty') self.smll = QCheckBox('Look for smaller changes') self.lrgf = QCheckBox('Optimize for large files') self.case = QCheckBox('Ignore case changes on content') self.cnvt = QCheckBox('Convert Tabs to Spaces') self.blnk = QCheckBox('Ignore added or removed Blank lines') self.spac = QCheckBox('Ignore changes in amount of Spaces') self.whit = QCheckBox('Ignore ALL white Spaces') self.tabz = QCheckBox('Ignore changes by Tab expansions') self.sprs = QCheckBox('Remove Space or Tab before empty lines') self.filn = QCheckBox('Ignore case when comparing file names') self.tbs = QComboBox(self.group2) self.tbs.addItems(['4', '6', '8', '10', '2']) self.nice = QComboBox(self.group2) self.nice.addItems(['20', '15', '10', '5', '0']) vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, QLabel('Diff Tabs-to-Spaces Size'), self.tbs, QLabel('Diff Backend CPU Priority'), self.nice): vboxg2.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) group3 = QGroupBox() group3.setTitle('Even More Options') self.plai = QCheckBox('Force treat all files as plain text') self.nocr = QCheckBox('Force strip trailing carriage return') self.ridt = QCheckBox('Report when two files are identical') self.nocm = QCheckBox('Do not output common lines') self.rdif = QCheckBox('Report only when files differ') self.clip = QCheckBox('Copy Diff to Clipboard when done') self.noti = QCheckBox('Use system Notification when done') self.pret = QCheckBox('Align all Tabs by prepending a Tab') self.lolz = QCheckBox('Output Diff in two equal columns') self.odif = QCheckBox('Open Diff with Ninja-IDE when done') self.plac = QCheckBox('Make an Awesome Diff view when done') self.wdth = QComboBox(group3) self.wdth.addItems(['80', '100', '120', '130', '250', '500', '999999']) self.bcknd = QComboBox(group3) self.bcknd.addItems(['diff', 'diff.py']) self.bcknd.setDisabled(True) #TODO this feature needs work vboxg3 = QVBoxLayout(group3) for each_widget in (self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, QLabel('Diff Maximum Total Width'), self.wdth, QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd): vboxg3.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti): widget_should_be_checked.setChecked(True) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) buttons = QDialogButtonBox() buttons.resize(self.dialog.size().width(), buttons.size().height() * 2) buttons.setOrientation(Qt.Horizontal) buttons.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Close | QDialogButtonBox.Help) buttons.setCenterButtons(False) buttons.helpRequested.connect(lambda: QMessageBox.about( self.dialog, __doc__, ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep, 'version ', __version__, ', (', __license__, '), by ', linesep, __author__, ', ( ', __email__, ' ).', linesep)))) buttons.rejected.connect(self.dialog.close) buttons.accepted.connect(self.make_diff) info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>', getoutput('diff --version').split(linesep)[0]))) vbox = QVBoxLayout(self.dialog) for each_widget in ( QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'), container, info, buttons): vbox.addWidget(each_widget) self.dialog.resize(1024, self.dialog.size().height()) self.dialog.exec_() def make_diff(self): ' make the diff ' diff_command = ''.join(( 'nice --adjustment=', str(self.nice.currentText()).strip(), ' ', str(self.bcknd.currentText()).strip(), ' --', str(self.frmt.currentText()).strip().lower(), ' --new-file ' if self.nwfl.isChecked() is True else '', ' --minimal ' if self.smll.isChecked() is True else '', ' --speed-large-files ' if self.lrgf.isChecked() is True else '', ' --ignore-self.case ' if self.case.isChecked() is True else '', ' --expand-tabs ' if self.cnvt.isChecked() is True else '', ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '', ' --ignore-space-change ' if self.spac.isChecked() is True else '', ' --ignore-all-space ' if self.whit.isChecked() is True else '', ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '', ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '', ' --ignore-file-name-case ' if self.filn.isChecked() is True else '', ' --text ' if self.plai.isChecked() is True else '', ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '', ' --suppress-common-lines ' if self.nocm.isChecked() is True else '', ' --initial-tab ' if self.pret.isChecked() is True else '', ' --side-by-side ' if self.lolz.isChecked() is True else '', ' --tabsize=', str(self.tbs.currentText()).strip(), ' --width=', str(self.wdth.currentText()).strip(), str(' --ignore-matching-lines=' + str(self.regex.text()).strip()) if str(self.regex.text()).strip() is not '' else '', ' ', path.abspath(str(self.file1.text())) if str(self.file1.text()).strip() is not '' else __file__, ' ', path.abspath(str(self.file2.text())) if str(self.file2.text()).strip() is not '' else __file__ )) print(diff_command) diff_output = getoutput(diff_command) try: print(' INFO: OK, Saving new Diff to disk...') output_file = file(path.abspath(str(self.fout.text())), 'w') output_file.write(diff_output) output_file.close() except: print(' ERROR: FAIL, Can not save Diff to disk!') if self.clip.isChecked() is True: print(' INFO: OK, Diff Copied to Clipboard...') QApplication.clipboard().setText(diff_output) if self.noti.isChecked() is True: call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True) if self.odif.isChecked() is True: print(' INFO: OK, Opening Diff with Ninja-IDE') call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True) self.diff_path = path.abspath(str(self.fout.text())) return self.diff_path
class GearEntriesFrame(QFrame): read_block = pyqtSignal(int, int) # start_addr, num_bytes poke_block = pyqtSignal(int, QByteArray, bool) # start_addr, raw_bytes, is_ascii log = pyqtSignal(str, str) # msg, color MISSING_SKILL_NAME = '[NOT IN DB]' def __init__(self, addr_start, addr_end, class_label, skill2id, id2skill, parent=None): super(GearEntriesFrame, self).__init__(parent) self.addr_start = addr_start self.addr_end = addr_end self.max_num_slots = (addr_end - addr_start) / 6 / 4 + 1 self.class_label = class_label self.skill2id = skill2id self.id2skill = id2skill self.skill_names = self.skill2id.keys() self.skill_names.sort() self.slots_cache = [] # list of raw 6*4 bytes self.slots_txt = None self.cur_slot_idx = -1 self.cur_slot_bytes = None self.lbl_label = QLabel(self.class_label, self) self.btn_read_slots = QPushButton(' Cache Slots', self) self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png')) self.btn_read_slots.setStyleSheet('background-color: white') self.btn_read_slots.clicked.connect(self.onReadSlots) self.cmb_slots = QComboBox(self) self.cmb_slots.setToolTip('') self.cmb_slots.setStyleSheet('background-color: white') self.cmb_slots.currentIndexChanged[str].connect(self.onChangeSlot) self.cmb_slots.setDisabled(True) self.btn_read = QPushButton(self) self.btn_read.setIcon(QIcon('img/flaticon/open135.png')) self.btn_read.setToolTip('Read item slot value from memory') self.btn_read.setStyleSheet('background-color: white') self.btn_read.clicked.connect(self.onReadSlot) self.txt_raw = QLineEdit(self) self.txt_raw.setPlaceholderText('Raw hex data') self.txt_raw.setMaxLength(8 * 6 + 5) self.txt_raw.editingFinished.connect(self.onChangeRaw) self.btn_poke = QPushButton(self) self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png')) self.btn_poke.setToolTip('Poke new value for item slot') self.btn_poke.setStyleSheet('background-color: white') self.btn_poke.clicked.connect(self.onPokeSlot) self.cmb_skills_a = QComboBox(self) self.cmb_skills_a.setEditable(True) self.cmb_skills_a.addItems(self.skill_names) self.cmb_skills_a.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA) self.cmb_skills_b = QComboBox(self) self.cmb_skills_b.setEditable(True) self.cmb_skills_b.addItems(self.skill_names) self.cmb_skills_b.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB) self.cmb_skills_c = QComboBox(self) self.cmb_skills_c.setEditable(True) self.cmb_skills_c.addItems(self.skill_names) self.cmb_skills_c.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC) incr_labels = [] for incr in xrange(16): incr_labels.append('+%d' % incr) self.cmb_incr_a = QComboBox(self) self.cmb_incr_a.addItems(incr_labels) self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA) self.cmb_incr_b = QComboBox(self) self.cmb_incr_b.addItems(incr_labels) self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB) self.cmb_incr_c = QComboBox(self) self.cmb_incr_c.addItems(incr_labels) self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC) slot_labels = [] for incr in xrange(4): slot_labels.append('%d Augment Slots' % incr) self.cmb_augments = QComboBox(self) self.cmb_augments.addItems(slot_labels) self.cmb_augments.currentIndexChanged[int].connect(self.onChangeAugments) self.layout = QGridLayout(self) self.layout.addWidget(self.lbl_label, 0, 0) self.layout.addWidget(self.btn_read_slots, 0, 1) self.layout.addWidget(self.cmb_slots, 0, 2) self.layout.addWidget(self.btn_read, 0, 3) self.layout.addWidget(self.txt_raw, 1, 0, 1, 3) self.layout.addWidget(self.btn_poke, 1, 3) self.layout.addWidget(self.cmb_skills_a, 2, 0) self.layout.addWidget(self.cmb_incr_a, 2, 1) self.layout.addWidget(self.cmb_skills_b, 3, 0) self.layout.addWidget(self.cmb_incr_b, 3, 1) self.layout.addWidget(self.cmb_skills_c, 4, 0) self.layout.addWidget(self.cmb_incr_c, 4, 1) self.layout.addWidget(self.cmb_augments, 2, 2) self.layout.setColumnStretch(0, 7) self.layout.setColumnStretch(1, 3) self.layout.setColumnStretch(2, 3) self.layout.setColumnStretch(3, 1) self.layout.setContentsMargins(0, 2, 0, 2) icon_height = self.lbl_label.height() * 8 / 15 icon_size = QSize(icon_height, icon_height) self.btn_read_slots.setIconSize(icon_size) self.btn_read.setIconSize(icon_size) self.btn_poke.setIconSize(icon_size) btn_size = QSize(icon_height * 1.5, icon_height * 1.5) self.btn_read.setFixedSize(btn_size) self.btn_poke.setFixedSize(btn_size) self.updateUI() def updateUI(self): # Disable editing if cache missing if not (0 <= self.cur_slot_idx < len(self.slots_cache)) or self.cur_slot_bytes is None: self.cur_slot_idx = -1 self.cur_slot_bytes = None self.cmb_slots.setDisabled(True) self.cmb_skills_a.setDisabled(True) self.cmb_skills_b.setDisabled(True) self.cmb_skills_c.setDisabled(True) self.cmb_incr_a.setDisabled(True) self.cmb_incr_b.setDisabled(True) self.cmb_incr_c.setDisabled(True) self.cmb_augments.setDisabled(True) self.txt_raw.setDisabled(True) return else: self.cmb_slots.setDisabled(False) self.cmb_skills_a.setDisabled(False) self.cmb_skills_b.setDisabled(False) self.cmb_skills_c.setDisabled(False) self.cmb_incr_a.setDisabled(False) self.cmb_incr_b.setDisabled(False) self.cmb_incr_c.setDisabled(False) self.cmb_augments.setDisabled(False) self.txt_raw.setDisabled(False) # Validate current slot's raw bytes try: (gear_id_bytes, index, post_index, skill_a_id, skill_a_incr, skill_b_id, skill_b_incr, skill_c_id, skill_c_incr, augment_a_id, augment_b_id, augment_c_id) = parse_gear_bytes(self.cur_slot_bytes) cur_slot_words = struct.unpack('>IIIIII', self.cur_slot_bytes) num_augments = (augment_a_id != 0xFFFF) + (augment_b_id != 0xFFFF) + (augment_c_id != 0xFFFF) except ValueError, e: self.log.emit('Gear parsing failed: %s' % e.what(), 'red') return # Update UI self.txt_raw.setDisabled(False) self.txt_raw.editingFinished.disconnect() self.txt_raw.setText('%08X %08X %08X %08X %08X %08X' % cur_slot_words) self.txt_raw.editingFinished.connect(self.onChangeRaw) self.cmb_skills_a.setDisabled(False) self.cmb_skills_a.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_a_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_a.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_a.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA) self.cmb_skills_b.setDisabled(False) self.cmb_skills_b.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_b_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_b.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_b.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB) self.cmb_skills_c.setDisabled(False) self.cmb_skills_c.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_c_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_c.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_c.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC) self.cmb_incr_a.setDisabled(False) self.cmb_incr_a.currentIndexChanged[int].disconnect() self.cmb_incr_a.setCurrentIndex(skill_a_incr) self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA) self.cmb_incr_b.setDisabled(False) self.cmb_incr_b.currentIndexChanged[int].disconnect() self.cmb_incr_b.setCurrentIndex(skill_b_incr) self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB) self.cmb_incr_c.setDisabled(False) self.cmb_incr_c.currentIndexChanged[int].disconnect() self.cmb_incr_c.setCurrentIndex(skill_c_incr) self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC) self.cmb_augments.setDisabled(False) self.cmb_augments.currentIndexChanged[int].disconnect() self.cmb_augments.setCurrentIndex(num_augments) self.cmb_augments.currentIndexChanged[int].connect(self.onChangeAugments)
class DiffGUI(object): ' diff gui class ' def __init__(self): ' make a diff method with GUI ' self.dialog = QDialog() self.diff_path = None # directory auto completer self.completer = QCompleter(self.dialog) self.dirs = QDirModel(self.dialog) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.group1 = QGroupBox() self.group1.setTitle('Diff') self.frmt = QComboBox(self.group1) self.frmt.addItems(['Unified', 'Normal', 'Context']) self.file1 = QLineEdit() self.file1.setPlaceholderText('/full/path/to/one_file.py') self.file1.setCompleter(self.completer) self.file2 = QLineEdit() self.file2.setPlaceholderText('/full/path/to/another_file.py') self.file2.setCompleter(self.completer) self.fout = QLineEdit() self.fout.setText(''.join((path.join(gettempdir(), datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff'))))) self.fout.setPlaceholderText('/full/path/to/output_file.diff') self.fout.setCompleter(self.completer) self.regex = QLineEdit() self.regex.setPlaceholderText('DONT use unless you know what are doing') self.regex.setToolTip('Do NOT use unless you know what you are doing !') self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.borig.clicked.connect(lambda: self.file1.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bmodi.clicked.connect(lambda: self.file2.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bout.clicked.connect(lambda: self.fout.setText(str( QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file', path.expanduser("~"), ';;(*.diff)')))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('Original file full path'), self.file1, self.borig, QLabel('Modified file full path'), self.file2, self.bmodi, QLabel('Output file full Path'), self.fout, self.bout, QLabel('Diff Output Format'), self.frmt, QLabel('Diff REGEX to Ignore (ADVANCED)'), self.regex): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle('Options') self.nwfl = QCheckBox('Treat new files as Empty') self.smll = QCheckBox('Look for smaller changes') self.lrgf = QCheckBox('Optimize for large files') self.case = QCheckBox('Ignore case changes on content') self.cnvt = QCheckBox('Convert Tabs to Spaces') self.blnk = QCheckBox('Ignore added or removed Blank lines') self.spac = QCheckBox('Ignore changes in amount of Spaces') self.whit = QCheckBox('Ignore ALL white Spaces') self.tabz = QCheckBox('Ignore changes by Tab expansions') self.sprs = QCheckBox('Remove Space or Tab before empty lines') self.filn = QCheckBox('Ignore case when comparing file names') self.tbs = QComboBox(self.group2) self.tbs.addItems(['4', '6', '8', '10', '2']) self.nice = QComboBox(self.group2) self.nice.addItems(['20', '15', '10', '5', '0']) vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, QLabel('Diff Tabs-to-Spaces Size'), self.tbs, QLabel('Diff Backend CPU Priority'), self.nice): vboxg2.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) group3 = QGroupBox() group3.setTitle('Even More Options') self.plai = QCheckBox('Force treat all files as plain text') self.nocr = QCheckBox('Force strip trailing carriage return') self.ridt = QCheckBox('Report when two files are identical') self.nocm = QCheckBox('Do not output common lines') self.rdif = QCheckBox('Report only when files differ') self.clip = QCheckBox('Copy Diff to Clipboard when done') self.noti = QCheckBox('Use system Notification when done') self.pret = QCheckBox('Align all Tabs by prepending a Tab') self.lolz = QCheckBox('Output Diff in two equal columns') self.odif = QCheckBox('Open Diff with Ninja-IDE when done') self.plac = QCheckBox('Make an Awesome Diff view when done') self.wdth = QComboBox(group3) self.wdth.addItems(['80', '100', '120', '130', '250', '500', '9999999']) self.bcknd = QComboBox(group3) self.bcknd.addItems(['diff', 'diff.py']) self.bcknd.setDisabled(True) # TODO this feature needs work vboxg3 = QVBoxLayout(group3) for each_widget in (self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, QLabel('Diff Maximum Total Width'), self.wdth, QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd): vboxg3.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti): widget_should_be_checked.setChecked(True) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) buttons = QDialogButtonBox() buttons.resize(self.dialog.size().width(), buttons.size().height() * 2) buttons.setOrientation(Qt.Horizontal) buttons.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Close | QDialogButtonBox.Help) buttons.setCenterButtons(False) buttons.helpRequested.connect(lambda: QMessageBox.about( self.dialog, __doc__, ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep, 'version ', __version__, ', (', __license__, '), by ', linesep, __author__, ', ( ', __email__, ' ).', linesep)))) buttons.rejected.connect(self.dialog.close) buttons.accepted.connect(self.make_diff) info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>', getoutput('diff --version').split(linesep)[0]))) vbox = QVBoxLayout(self.dialog) for each_widget in ( QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'), container, info, buttons): vbox.addWidget(each_widget) self.dialog.resize(1024, self.dialog.size().height()) self.dialog.exec_() def make_diff(self): ' make the diff ' diff_command = ''.join(( 'nice --adjustment=', str(self.nice.currentText()).strip(), ' ', str(self.bcknd.currentText()).strip(), ' --', str(self.frmt.currentText()).strip().lower(), ' --new-file ' if self.nwfl.isChecked() is True else '', ' --minimal ' if self.smll.isChecked() is True else '', ' --speed-large-files ' if self.lrgf.isChecked() is True else '', ' --ignore-self.case ' if self.case.isChecked() is True else '', ' --expand-tabs ' if self.cnvt.isChecked() is True else '', ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '', ' --ignore-space-change ' if self.spac.isChecked() is True else '', ' --ignore-all-space ' if self.whit.isChecked() is True else '', ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '', ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '', ' --ignore-file-name-case ' if self.filn.isChecked() is True else '', ' --text ' if self.plai.isChecked() is True else '', ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '', ' --suppress-common-lines ' if self.nocm.isChecked() is True else '', ' --initial-tab ' if self.pret.isChecked() is True else '', ' --side-by-side ' if self.lolz.isChecked() is True else '', ' --tabsize=', str(self.tbs.currentText()).strip(), ' --width=', str(self.wdth.currentText()).strip(), str(' --ignore-matching-lines=' + str(self.regex.text()).strip()) if str(self.regex.text()).strip() is not '' else '', ' ', path.abspath(str(self.file1.text())) if str(self.file1.text()).strip() is not '' else __file__, ' ', path.abspath(str(self.file2.text())) if str(self.file2.text()).strip() is not '' else __file__ )) print(diff_command) diff_output = getoutput(diff_command) try: print(' INFO: OK, Saving new Diff to disk...') output_file = file(path.abspath(str(self.fout.text())), 'w') output_file.write(diff_output) output_file.close() except: print(' ERROR: FAIL, Can not save Diff to disk!') if self.clip.isChecked() is True: print(' INFO: OK, Diff Copied to Clipboard...') QApplication.clipboard().setText(diff_output) if self.noti.isChecked() is True: call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True) if self.odif.isChecked() is True: print(' INFO: OK, Opening Diff with Ninja-IDE') call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True) self.diff_path = path.abspath(str(self.fout.text())) return self.diff_path
class Sidebar(QWidget): """ +----------------------+ | Results | +======================+ | | | Name = Main | | | | +----------------+ | | | ResultsWindow | | | +----------------+ | | | | | | | +----------+ | | | | | - a | | | | | | - b1 | | | | | | - b2 | | | | | | - b3 | | | | | +----------+ | | | | | | | +----------------+ | | | | | | Apply | +----------------------+ For Nastran: - a: Subcase 1 - b1. Displacement - b2. Stress - b3. Strain For Cart3d: - a1. Geometry - b1. ElementID - b2. Region - a2. Results Case 1 - b1. U - b2. V - b3. W +--------------+ | Sub-Result | (pulldown) +==============+ | - a1 | | - a2 | | - a3 | | - a4 | +--------------+ For Nastran: - a1: Displacement X - a2. Displacement Y - a3. Displacmenet Z - a4. Displacmenet Mag For Cart3d: - NA (Greyed Out) +----------------+ | Plot | (pulldown) +================+ | - Fringe | | - Marker | | - Displacement | +----------------+ - Cart3d -> Fringe (disabled) +---------------+ | Scale Display | (text box) +===============+ | 0 < x < 1000 | (not for fringe) +---------------+ +--------------+ | Location | (pulldown) +==============+ | - nodal | | - centroidal | +--------------+ (disabled) +------------------+ | Complex Method | (pulldown) +==================+ | - real | (usually set to real and disabled) | - imag | | - mag | | - phase | | - max over phase | +------------------+ +--------------+ | Derive | (pulldown; only for nodal results) +==============+ | - derive/avg | (default?) | - avg/derive | +--------------+ """ def __init__(self, parent, debug=False): """creates the buttons in the Sidebar, not the actual layout""" QWidget.__init__(self) self.parent = parent self.debug = debug name = 'main' data = [] data = [ ("Alice", None, [ ("Keys", 1, []), ("Purse", 2, [ ("Cellphone", 3, []) ]) ]), ("Bob", None, [ ("Wallet", None, [ ("Credit card", 4, []), ("Money", 5, []) ]) ]), ] choices = ['keys2', 'purse2', 'cellphone2', 'credit_card2', 'money2'] self.result_case_window = ResultsWindow('Case/Results', data, choices) data = [ ('A', 1, []), #('B', 2, []), #('C', 3, []), ] self.result_data_window = ResultsWindow('Method', data, choices) self.result_data_window.setVisible(False) self.show_pulldown = False if self.show_pulldown: combo_options = ['a1', 'a2', 'a3'] self.pulldown = QComboBox() self.pulldown.addItems(choices) self.pulldown.activated[str].connect(self.on_pulldown) self.apply_button = QPushButton('Apply', self) self.apply_button.clicked.connect(self.on_apply) self.name = str(name) self.names = [name] self.name_label = QLabel("Name:") self.name_pulldown = QComboBox() self.name_pulldown.addItem(name) self.name_pulldown.setDisabled(True) self.name_pulldown.currentIndexChanged.connect(self.on_update_name) self.setup_layout() def setup_layout(self): """creates the sidebar visual layout""" vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.name_label) hbox.addWidget(self.name_pulldown) vbox.addLayout(hbox) vbox.addWidget(self.result_case_window) vbox.addWidget(self.result_data_window) if self.show_pulldown: vbox.addWidget(self.pulldown) vbox.addWidget(self.apply_button) self.setLayout(vbox) self.clear_data() def update_method(self, method): if isinstance(method, string_types): datai = self.result_data_window.data[0] self.result_data_window.data[0] = (method, datai[1], datai[2]) print('method=%s datai=%s' % (method, datai)) self.result_data_window.update_data(self.result_data_window.data) else: return # pragma: no cover datai = self.result_data_window.data[0] def get_form(self): return self.result_case_window.data def update_results(self, data, name): """ Updates the sidebar Parameters ---------- data : List[tuple] the form data name : str the name that goes at the side """ name = str(name) if name in self.names: i = self.names.index(name) self.name_pulldown.setCurrentIndex(i) else: self.name_pulldown.addItem(name) self.names.append(name) if len(self.names) >= 2: self.name_pulldown.setEnabled(True) self.name = name self.result_case_window.update_data(data) self.apply_button.setEnabled(True) def update_methods(self, data): """the methods is a hidden box""" self.result_data_window.update_data(data) self.apply_button.setEnabled(True) def clear_data(self): self.result_case_window.clear_data() self.result_data_window.clear_data() self.apply_button.setEnabled(False) def on_pulldown(self, event): print('pulldown...') def on_update_name(self, event): """user clicked the pulldown""" name = str(self.name_pulldown.currentText()) data = self.parent._get_sidebar_data(name) #self.result_case_window.update_data(data) def on_apply(self, event): data = self.result_case_window.data valid_a, keys_a = self.result_case_window.treeView.get_row() data = self.result_data_window.data valid_b, keys_b = self.result_data_window.treeView.get_row() if valid_a and valid_b: if self.debug: # pragma: no cover print(' rows1 = %s' % self.result_case_window.treeView.old_rows) print(' = %s' % str(keys_a)) print(' rows2 = %s' % self.result_data_window.treeView.old_rows) print(' = %s' % str(keys_b)) else: self.update_vtk_window(keys_a, keys_b) def update_vtk_window(self, keys_a, keys_b): if 0: # pragma: no cover print('keys_a = %s' % str(keys_a)) for i, key in enumerate(self.parent.case_keys): if key[1] == keys_a[0]: break print('*i=%s key=%s' % (i, str(key))) #self.parent.update_vtk_window_by_key(i) result_name = key[1] #self.parent.cycle_results_explicit(result_name=result_name, explicit=True) #j = self.parent._get_icase(result_name) #j = i i = keys_a result_name = None self.parent._set_case(result_name, i, explicit=True)
class ItemEntriesFrame(QFrame): read_block = pyqtSignal(int, int) # start_addr, num_bytes poke_block = pyqtSignal(int, QByteArray, bool) # start_addr, raw_bytes, is_ascii log = pyqtSignal(str, str) # msg, color MISSING_ITEM_NAME = '[NOT IN DB]' def __init__(self, type_val, addr_start, addr_end, label, id2name, idx2id, names, parent=None): super(ItemEntriesFrame, self).__init__(parent) self.type_val = type_val self.code_offset = 0 self.addr_start = addr_start self.addr_end = addr_end self.max_num_slots = (addr_end - addr_start) / 3 / 4 + 1 self.label = label self.id2name = id2name self.idx2id = idx2id self.names = names self.slots_cache = [ ] # tuple: (addr_hex, addr_val, slot_number, cur_val) self.cur_slot_idx = -1 self.lbl_label = QLabel(self.label, self) self.btn_read_slots = QPushButton(' Cache Slots', self) self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png')) self.btn_read_slots.setStyleSheet('background-color: white') self.btn_read_slots.clicked.connect(self.onReadSlots) self.btn_search_cache = QPushButton(' Search ID', self) self.btn_search_cache.setIcon(QIcon('img/flaticon/magnifier13.png')) self.btn_search_cache.setToolTip( 'Find slot in cache with specified item ID') self.btn_search_cache.setStyleSheet('background-color: white') self.btn_search_cache.clicked.connect(self.onSearchCacheForID) self.btn_read = QPushButton(self) self.btn_read.setIcon(QIcon('img/flaticon/open135.png')) self.btn_read.setToolTip('Read item slot value from memory') self.btn_read.setStyleSheet('background-color: white') self.btn_read.clicked.connect(self.onReadSlot) self.cmb_slots = QComboBox(self) self.cmb_slots.setStyleSheet('background-color: white') self.cmb_slots.currentIndexChanged[int].connect(self.onChangeSlot) self.cmb_slots.setDisabled(True) self.cmb_names = QComboBox(self) self.cmb_names.setEditable(True) self.cmb_names.addItems(self.names) self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.currentIndexChanged[int].connect(self.fetchID) self.txt_id = QLineEdit(self) self.txt_id.setPlaceholderText('ID (hex)') self.txt_id.setMaxLength(3) self.txt_id.textChanged.connect(self.fetchName) self.btn_rename = QPushButton(' Fix Name', self) self.btn_rename.setIcon(QIcon('img/flaticon/cloud-storage3.png')) self.btn_rename.setToolTip( 'Add/Correct Item Name for %s (type: %02X)' % (self.label, type_val)) self.btn_rename.setStyleSheet('background-color: white') self.btn_rename.clicked.connect(self.onRename) self.txt_amount = QLineEdit(self) self.txt_amount.setPlaceholderText('Amount') self.txt_amount.setMaxLength(3) self.btn_poke = QPushButton(self) self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png')) self.btn_poke.setToolTip('Poke new value for item slot') self.btn_poke.setStyleSheet('background-color: white') self.btn_poke.clicked.connect(self.onPokeSlot) self.layout = QGridLayout(self) self.layout.addWidget(self.lbl_label, 0, 0) self.layout.addWidget(self.btn_read_slots, 0, 1) self.layout.addWidget(self.btn_search_cache, 0, 2) self.layout.addWidget(self.cmb_slots, 0, 3) self.layout.addWidget(self.btn_read, 0, 4) self.layout.addWidget(self.cmb_names, 1, 0) self.layout.addWidget(self.txt_id, 1, 1) self.layout.addWidget(self.btn_rename, 1, 2) self.layout.addWidget(self.txt_amount, 1, 3) self.layout.addWidget(self.btn_poke, 1, 4) self.layout.setColumnStretch(0, 7) self.layout.setColumnStretch(1, 3) self.layout.setColumnStretch(2, 3) self.layout.setColumnStretch(3, 3) self.layout.setColumnStretch(4, 1) self.layout.setContentsMargins(0, 2, 0, 2) icon_height = self.lbl_label.height() * 8 / 15 icon_size = QSize(icon_height, icon_height) self.btn_read_slots.setIconSize(icon_size) self.btn_search_cache.setIconSize(icon_size) self.btn_rename.setIconSize(icon_size) self.btn_read.setIconSize(icon_size) self.btn_poke.setIconSize(icon_size) btn_size = QSize(icon_height * 1.5, icon_height * 1.5) self.btn_read.setFixedSize(btn_size) self.btn_poke.setFixedSize(btn_size) self.updateUI() def updateUI(self): # Disable editing if cache missing if not (0 <= self.cur_slot_idx < len(self.slots_cache)): self.cmb_names.lineEdit().setText( ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.setDisabled(True) self.txt_id.setText('') self.txt_id.setDisabled(True) return # Validate current value cur_val = self.slots_cache[self.cur_slot_idx][3] (type_val, id_val, amount) = parse_item_word(cur_val) if type_val != self.type_val and type_val != 0: cur_addr = self.slots_cache[ self.cur_slot_idx][1] + self.code_offset self.log.emit( 'Cache error: val(0x%08X)=%08X, type (%02X) != expected (%02X)' % (cur_addr, cur_val, type_val, self.type_val), 'red') return # Update UI self.txt_id.setDisabled(False) self.txt_id.setText('%03X' % id_val) self.cmb_names.setDisabled(False) self.fetchName() self.txt_amount.setText(str(amount)) def setAlternateBGColor(self): self.setStyleSheet( 'ItemEntriesFrame { background-color:rgb(248,248,248) }') @pyqtSlot(int) def onSetCodeOffset(self, signed_offset): self.code_offset = signed_offset @pyqtSlot() def onRename(self): id_txt = str(self.txt_id.text()) if len(id_txt) != 3: return dialog = FixItemNameDialog('%02X' % self.type_val, id_txt, self) dialog.log.connect(self.log) dialog.exec_() @pyqtSlot() def onReadSlots(self): self.read_block.emit(self.addr_start + self.code_offset, self.max_num_slots * 4 * 3) @pyqtSlot(int, int, QByteArray) def onBlockRead(self, addr_start_w_code_offset, num_bytes, raw_bytes): # Determine whether block has cache or single slot if (addr_start_w_code_offset == (self.addr_start + self.code_offset) ) and (num_bytes == self.max_num_slots * 4 * 3): self.onCacheRead(addr_start_w_code_offset, raw_bytes) elif num_bytes == 4: # Assume read slot # Ignore if no cache if not (0 <= self.cur_slot_idx < len(self.slots_cache)): return self.onSlotRead(addr_start_w_code_offset, raw_bytes) def onCacheRead(self, addr_start_w_code_offset, raw_bytes): slot_bytes = str(raw_bytes) self.slots_cache = [] slots_txt = [] for slot_i in xrange(self.max_num_slots): byte_offset = slot_i * 3 * 4 cur_slot_bytes = slot_bytes[byte_offset:(byte_offset + 4)] if len(cur_slot_bytes) != 4: continue cur_slot_val = struct.unpack('>I', cur_slot_bytes)[0] (type_val, id_val, amount) = parse_item_word(cur_slot_val) if type_val == 0 or amount == 0: continue elif type_val != self.type_val: self.log.emit( 'val(%08X)=%08X, type_val(%02X) unexpected(%02X)' % (addr_start_w_code_offset + byte_offset, cur_slot_val, type_val, self.type_val), 'red') continue else: addr_val = addr_start_w_code_offset + byte_offset - self.code_offset # remove code_offset since it may change later addr_hex = '%08X' % addr_val slot_number = slot_i + 1 self.slots_cache.append( (addr_hex, addr_val, slot_number, cur_slot_val)) slots_txt.append('Slot %03d' % slot_number) # Update UI self.log.emit( 'Found %d %s slots in memory' % (len(self.slots_cache), self.label), 'black') self.cmb_slots.clear() if len(self.slots_cache) <= 0: self.cmb_slots.setDisabled(True) self.cur_slot_idx = -1 else: self.cmb_slots.setDisabled(False) self.cmb_slots.addItems(slots_txt) self.cur_slot_idx = 0 self.updateUI() def onSlotRead(self, addr_word_w_code_offset, raw_bytes): addr_cur_slot = self.slots_cache[ self.cur_slot_idx][1] + self.code_offset if addr_word_w_code_offset == addr_cur_slot: cur_cache = self.slots_cache[self.cur_slot_idx] new_val = struct.unpack('>I', str(raw_bytes))[0] new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val) self.slots_cache[self.cur_slot_idx] = new_cache self.updateUI() else: # Update cached value of other slots addr_first_slot = self.slots_cache[0][1] + self.code_offset addr_last_slot = self.slots_cache[-1][1] + self.code_offset if (addr_first_slot <= addr_word_w_code_offset <= addr_last_slot) and \ ((addr_word_w_code_offset - addr_first_slot) % 12 == 0): for slot_i in xrange(len(self.slots_cache)): addr_cur_slot = self.slots_cache[slot_i][ 1] + self.code_offset if addr_word_w_code_offset == addr_cur_slot: cur_cache = self.slots_cache[slot_i] new_val = struct.unpack('>I', str(raw_bytes))[0] new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val) self.slots_cache[slot_i] = new_cache return @pyqtSlot() def onSearchCacheForID(self): # Stop if no cache if not (0 <= self.cur_slot_idx < len(self.slots_cache)): self.log.emit('Must cache slots before searching', 'red') return # Fetch and validate target ID try: target_id_val = int(str(self.txt_id.text()), 16) if target_id_val < 0 or target_id_val > Item.MAX_ID_VAL: self.log.emit('Item ID out of [0, 0x%03X] range' % Item.MAX_ID_VAL) return except ValueError: self.log.emit('Failed to parse item ID, expecting XXX', 'red') return # Search ID in cache for cand_slot_idx in xrange(len(self.slots_cache)): (type_val, id_val, amount) = parse_item_word(self.slots_cache[cand_slot_idx][3]) if id_val == target_id_val and type_val == self.type_val: self.cur_slot_idx = cand_slot_idx self.cmb_slots.setCurrentIndex(self.cur_slot_idx) self.updateUI() return self.log.emit( 'Did not find ID=%03X in %d cached %s slots' % (target_id_val, len(self.slots_cache), self.label), 'red') @pyqtSlot(int) def onChangeSlot(self, new_slot_idx): # Validate new_slot_idx if not (0 <= new_slot_idx < len(self.slots_cache)): return # Update slot idx and read value from memory self.cur_slot_idx = new_slot_idx self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.setDisabled(True) self.txt_id.setText('') self.txt_id.setDisabled(True) self.onReadSlot() @pyqtSlot() def fetchName(self): try: id_val = int(str(self.txt_id.text()), 16) except ValueError: return name = self.MISSING_ITEM_NAME if id_val in self.id2name: name = self.id2name[id_val] self.cmb_names.lineEdit().setText(name) @pyqtSlot(int) def fetchID(self, cmb_idx): if cmb_idx < 0 or cmb_idx >= len(self.idx2id): self.txt_id.setText('') else: self.txt_id.setText(self.idx2id[cmb_idx]) @pyqtSlot() def onReadSlot(self): try: if not (0 <= self.cur_slot_idx < len(self.slots_cache)): raise ValueError('must cache slots before reading') addr_cur_slot = self.slots_cache[ self.cur_slot_idx][1] + self.code_offset self.read_block.emit(addr_cur_slot, 4) except ValueError, e: cur_slot_num = self.slots_cache[self.cur_slot_idx][2] self.log.emit( 'READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red') except BaseException, e: cur_slot_num = self.slots_cache[self.cur_slot_idx][2] self.log.emit( 'READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red') traceback.print_exc()
class reglageExpert(QWidget) : """Class pour créer les widgets spécifiques pour les réglages plus fin sur la qualité d'encodage, sur le débit binaire des fichiers, ... """ def __init__(self, listeFormat, comboFormat, parent=None) : super(reglageExpert, self).__init__(parent) self.listeFormat = listeFormat self.comboFormat = comboFormat self.format = self.comboFormat.currentIndex() self.parent = parent layout = QHBoxLayout(self) self.textLabel = QLabel(self) self.textLabel.hide() self.expert = QCheckBox(_(u"Réglage expert : "), self) self.qualite = QComboBox(self) layout.addWidget(self.expert) layout.addWidget(self.textLabel) layout.addWidget(self.qualite) layout.addStretch() i=1 while i<9 : self.qualite.addItem(str(i)) i += 1 self.qualite.hide() self.changeFormat(self.comboFormat.currentIndex()) self.connect(self.expert, SIGNAL("stateChanged(int)"), self.setExpert) self.connect(self.comboFormat, SIGNAL("currentIndexChanged(int)"), self.changeFormat) self.connect(self.qualite, SIGNAL("currentIndexChanged(int)"), self.changeQualite) def setExpert(self, state) : if state : self.qualite.show() self.textLabel.show() else : self.qualite.hide() self.textLabel.hide() def changeQualite(self,qualite) : self.changeFormat(self.comboFormat.currentIndex()) def changeFormat(self, format) : if len(self.listeFormat) == 0 : return else : if self.listeFormat[format] == "mp3" or self.listeFormat[format] == "mp2" or self.listeFormat[format] == "ogg" : self.textLabel.setText(_(u"Qualité d'encodage")) self.qualite.setEnabled(True) self.C = u" -C %f " % (10.0*float(self.qualite.currentIndex()+1)/8.0) elif self.listeFormat[format] == "flac" : self.textLabel.setText(_(u"Taux de compression")) self.qualite.setEnabled(True) self.C = u" -C %d " % (self.qualite.currentIndex()+1) else : self.textLabel.setText(_(u"Non applicable, format non compressé")) self.qualite.setDisabled(True) self.C = u"" def getExpertState(self) : return self.expert.isChecked() def getC(self) : return self.C def saveConfig(self, idsection="") : if idsection == "" : return EkdConfig.set(idsection, u'format', unicode(self.comboFormat.currentIndex())) EkdConfig.set(idsection, u'expert', unicode(int(self.getExpertState()))) EkdConfig.set(idsection, u'qualite', unicode(self.qualite.currentIndex())) def loadConfig(self, idsection="") : if idsection == "" : return self.comboFormat.setCurrentIndex(int(EkdConfig.get(idsection, 'format'))) self.expert.setChecked(int(EkdConfig.get(idsection, 'expert'))) self.qualite.setCurrentIndex(int(EkdConfig.get(idsection, 'qualite')))
class GearEntriesFrame(QFrame): read_block = pyqtSignal(int, int) # start_addr, num_bytes poke_block = pyqtSignal(int, QByteArray, bool) # start_addr, raw_bytes, is_ascii log = pyqtSignal(str, str) # msg, color MISSING_SKILL_NAME = '[NOT IN DB]' def __init__(self, addr_start, addr_end, class_label, skill2id, id2skill, parent=None): super(GearEntriesFrame, self).__init__(parent) self.code_offset = 0 self.addr_start = addr_start self.addr_end = addr_end self.max_num_slots = (addr_end - addr_start) / 6 / 4 + 1 self.class_label = class_label self.skill2id = skill2id self.id2skill = id2skill self.skill_names = self.skill2id.keys() self.skill_names.sort() self.slots_cache = [] # list of raw 6*4 bytes self.slots_txt = None self.cur_slot_idx = -1 self.cur_slot_bytes = None self.lbl_label = QLabel(self.class_label, self) self.btn_read_slots = QPushButton(' Cache Slots', self) self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png')) self.btn_read_slots.setStyleSheet('background-color: white') self.btn_read_slots.clicked.connect(self.onReadSlots) self.cmb_slots = QComboBox(self) self.cmb_slots.setStyleSheet('background-color: white') self.cmb_slots.currentIndexChanged[str].connect(self.onChangeSlot) self.cmb_slots.setDisabled(True) self.btn_read = QPushButton(self) self.btn_read.setIcon(QIcon('img/flaticon/open135.png')) self.btn_read.setToolTip('Read item slot value from memory') self.btn_read.setStyleSheet('background-color: white') self.btn_read.clicked.connect(self.onReadSlot) self.txt_raw = QLineEdit(self) self.txt_raw.setPlaceholderText('Raw hex data') self.txt_raw.setMaxLength(8 * 6 + 5) self.txt_raw.editingFinished.connect(self.onChangeRaw) self.btn_poke = QPushButton(self) self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png')) self.btn_poke.setToolTip('Poke new value for item slot') self.btn_poke.setStyleSheet('background-color: white') self.btn_poke.clicked.connect(self.onPokeSlot) self.cmb_skills_a = QComboBox(self) self.cmb_skills_a.setEditable(True) self.cmb_skills_a.addItems(self.skill_names) self.cmb_skills_a.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA) self.cmb_skills_b = QComboBox(self) self.cmb_skills_b.setEditable(True) self.cmb_skills_b.addItems(self.skill_names) self.cmb_skills_b.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB) self.cmb_skills_c = QComboBox(self) self.cmb_skills_c.setEditable(True) self.cmb_skills_c.addItems(self.skill_names) self.cmb_skills_c.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC) incr_labels = [] for incr in xrange(16): incr_labels.append('+%d' % incr) self.cmb_incr_a = QComboBox(self) self.cmb_incr_a.addItems(incr_labels) self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA) self.cmb_incr_b = QComboBox(self) self.cmb_incr_b.addItems(incr_labels) self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB) self.cmb_incr_c = QComboBox(self) self.cmb_incr_c.addItems(incr_labels) self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC) slot_labels = [] for incr in xrange(4): slot_labels.append('%d Augment Slots' % incr) self.cmb_augments = QComboBox(self) self.cmb_augments.addItems(slot_labels) self.cmb_augments.currentIndexChanged[int].connect( self.onChangeAugments) self.layout = QGridLayout(self) self.layout.addWidget(self.lbl_label, 0, 0) self.layout.addWidget(self.btn_read_slots, 0, 1) self.layout.addWidget(self.cmb_slots, 0, 2) self.layout.addWidget(self.btn_read, 0, 3) self.layout.addWidget(self.txt_raw, 1, 0, 1, 3) self.layout.addWidget(self.btn_poke, 1, 3) self.layout.addWidget(self.cmb_skills_a, 2, 0) self.layout.addWidget(self.cmb_incr_a, 2, 1) self.layout.addWidget(self.cmb_skills_b, 3, 0) self.layout.addWidget(self.cmb_incr_b, 3, 1) self.layout.addWidget(self.cmb_skills_c, 4, 0) self.layout.addWidget(self.cmb_incr_c, 4, 1) self.layout.addWidget(self.cmb_augments, 2, 2) self.layout.setColumnStretch(0, 7) self.layout.setColumnStretch(1, 3) self.layout.setColumnStretch(2, 3) self.layout.setColumnStretch(3, 1) self.layout.setContentsMargins(0, 2, 0, 2) icon_height = self.lbl_label.height() * 8 / 15 icon_size = QSize(icon_height, icon_height) self.btn_read_slots.setIconSize(icon_size) self.btn_read.setIconSize(icon_size) self.btn_poke.setIconSize(icon_size) btn_size = QSize(icon_height * 1.5, icon_height * 1.5) self.btn_read.setFixedSize(btn_size) self.btn_poke.setFixedSize(btn_size) self.updateUI() def updateUI(self): # Disable editing if cache missing if not (0 <= self.cur_slot_idx < len( self.slots_cache)) or self.cur_slot_bytes is None: self.cur_slot_idx = -1 self.cur_slot_bytes = None self.cmb_slots.setDisabled(True) self.cmb_skills_a.setDisabled(True) self.cmb_skills_b.setDisabled(True) self.cmb_skills_c.setDisabled(True) self.cmb_incr_a.setDisabled(True) self.cmb_incr_b.setDisabled(True) self.cmb_incr_c.setDisabled(True) self.cmb_augments.setDisabled(True) self.txt_raw.setDisabled(True) return else: self.cmb_slots.setDisabled(False) self.cmb_skills_a.setDisabled(False) self.cmb_skills_b.setDisabled(False) self.cmb_skills_c.setDisabled(False) self.cmb_incr_a.setDisabled(False) self.cmb_incr_b.setDisabled(False) self.cmb_incr_c.setDisabled(False) self.cmb_augments.setDisabled(False) self.txt_raw.setDisabled(False) # Validate current slot's raw bytes try: (gear_id_bytes, index, post_index, skill_a_id, skill_a_incr, skill_b_id, skill_b_incr, skill_c_id, skill_c_incr, augment_a_id, augment_b_id, augment_c_id) = parse_gear_bytes(self.cur_slot_bytes) cur_slot_words = struct.unpack('>IIIIII', self.cur_slot_bytes) num_augments = (augment_a_id != 0xFFFF) + ( augment_b_id != 0xFFFF) + (augment_c_id != 0xFFFF) except ValueError, e: self.log.emit('Gear parsing failed: %s' % e.what(), 'red') return # Update UI self.txt_raw.setDisabled(False) self.txt_raw.editingFinished.disconnect() self.txt_raw.setText('%08X %08X %08X %08X %08X %08X' % cur_slot_words) self.txt_raw.editingFinished.connect(self.onChangeRaw) self.cmb_skills_a.setDisabled(False) self.cmb_skills_a.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_a_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_a.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_a.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA) self.cmb_skills_b.setDisabled(False) self.cmb_skills_b.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_b_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_b.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_b.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB) self.cmb_skills_c.setDisabled(False) self.cmb_skills_c.currentIndexChanged[str].disconnect() try: skill_name = self.id2skill[skill_c_id] skill_idx = self.skill_names.index(skill_name) self.cmb_skills_c.setCurrentIndex(skill_idx) except (KeyError, ValueError): self.cmb_skills_c.lineEdit().setText( GearEntriesFrame.MISSING_SKILL_NAME) self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC) self.cmb_incr_a.setDisabled(False) self.cmb_incr_a.currentIndexChanged[int].disconnect() self.cmb_incr_a.setCurrentIndex(skill_a_incr) self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA) self.cmb_incr_b.setDisabled(False) self.cmb_incr_b.currentIndexChanged[int].disconnect() self.cmb_incr_b.setCurrentIndex(skill_b_incr) self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB) self.cmb_incr_c.setDisabled(False) self.cmb_incr_c.currentIndexChanged[int].disconnect() self.cmb_incr_c.setCurrentIndex(skill_c_incr) self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC) self.cmb_augments.setDisabled(False) self.cmb_augments.currentIndexChanged[int].disconnect() self.cmb_augments.setCurrentIndex(num_augments) self.cmb_augments.currentIndexChanged[int].connect( self.onChangeAugments)
class NetWidget(QWidget): def __init__(self,parent = None): super(NetWidget,self).__init__(parent) self.setStyleSheet("font-size : 16px")#设置整体的字体大小 self.auto = False self.pro = QProcess(self) # self.tipDlg = TipDialog() # self.tipDlg.setModal(True)#引入tipdlg,并且将这个窗口设置为最前端窗口,且后面窗口无法操作 #初始化comBox控件,并且为其添加选项 self.comBox = QComboBox() self.comBox.setFixedWidth(120) self.comBox.insertItem(0, self.tr("ping")) self.comBox.insertItem(1, self.tr("ifconfig")) self.comBox.insertItem(2, self.tr("display")) #self.comBox.insertItem(3, self.tr("traceroute")) self.comBox.insertItem(4, self.tr("top")) self.connect(self.comBox, SIGNAL('activated(QString)'),self.onActivated)#设置combBox为活动的,与函数关联 """ #初始话控件设置 #lineEdit,固定长度 #runButton,显示字符串,信号量 #pingLabel,当前显示字符 #textBrower """ self.lineEdit = QLineEdit() self.lineEdit.setContextMenuPolicy(Qt.NoContextMenu) self.lineEdit.setFixedWidth(250) self.runButton = QPushButton(self.tr("Run")) self.runButton.setStyleSheet("background: rgb(7,87,198); color: white; width: 70px; height: 20px;font-size : 16px;") self.connect(self.runButton, SIGNAL("clicked()"),self.runButton_clicked) self.pingLabel = QLabel()#初始话,之后在函数操作中会改变 self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button")) self.textBrowser = QTextBrowser() """ #布局一上,横向布局 #将comBox,lineEdit,runButton添加到布局中 #设置前面空为20和后面空为280 """ hLayout1 = QHBoxLayout() hLayout1.addSpacing(20) hLayout1.addWidget(self.comBox) hLayout1.addWidget(self.lineEdit) hLayout1.addWidget(self.runButton) #hLayout1.addStretch() hLayout1.addSpacing(280) #布局二中,横向布局 #将pingLabel添加到布局中,并且诶设置前面的空白为20 hLayout2 = QHBoxLayout() hLayout2.addSpacing(20) hLayout2.addWidget(self.pingLabel) #布局三下 #将textBrower添加爱到布局中,并且设置前面空白为20,后面空白为60,控件的大小自适应 hLayout3 = QHBoxLayout() hLayout3.addSpacing(20) hLayout3.addWidget(self.textBrowser) hLayout3.addSpacing(60) #主题布局总,纵向布局 #将之上的三个布局添加到总布局中,并且设置布局间空间为20,最下面的空白为40 mainLayout = QVBoxLayout() mainLayout.addSpacing(20) mainLayout.addLayout(hLayout1) mainLayout.addSpacing(20) mainLayout.addLayout(hLayout2) mainLayout.addSpacing(20) mainLayout.addLayout(hLayout3) mainLayout.addSpacing(40) self.setLayout(mainLayout) self.thread = MyThread() self.connect(self.thread,SIGNAL("getoutput"),self.append) def append(self,actionType): self.textBrowser.clear() self.textBrowser.append(actionType) #cursor = QTextCursor() #self.runButton.setText(self.tr("Stop")) cursor = self.textBrowser.textCursor() cursor.movePosition(QTextCursor.Start) self.textBrowser.setTextCursor(cursor) #changeLabel = QLabel() def onActivated(self): language = StoreInfoParser.instance().getLanguage() m_pTranslator = QTranslator() exePath = "./" if language == "chinese": QmName = "zh_CN.qm" else: QmName = "en_US.qm" if(m_pTranslator.load(QmName, exePath)): QCoreApplication.instance().installTranslator(m_pTranslator) """#comBox的相应函数,随着comBox中字符串的改变,分别控制pingLabel的显示,以及lineEdit和textBrower的显示清除和可用状态 #如果comBox当前的字符串文字为ping #pingLabel的文字设置为"提示:请在文本框中输入要ping的目标地址,然后点击执行获取结果",保持当前大小 #lineEdit中内容清除,设置为不可用 #textBrower清空""" if(self.comBox.currentText() == "Ping" or self.comBox.currentText() == "ping"): self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button")) self.pingLabel.adjustSize() self.lineEdit.clear() self.lineEdit.setDisabled(False) self.textBrowser.clear() #如果comBox当前的字符串文字为ifconfig #类上所说 elif(self.comBox.currentText() == "ifconfig"): self.pingLabel.setText(self.tr("Tip:get the net information")) self.pingLabel.adjustSize() self.lineEdit.clear() self.lineEdit.setEnabled(False) self.textBrowser.clear() #如果comBox当前的字符串文字为display elif(self.comBox.currentText() == "display"): self.pingLabel.setText(self.tr("Tip:get the resolution information")) self.pingLabel.adjustSize() self.lineEdit.clear() self.lineEdit.setEnabled(False) self.textBrowser.clear() elif(self.comBox.currentText() == "top"): self.pingLabel.setText(self.tr("Tip:run tom command")) self.pingLabel.adjustSize() self.lineEdit.setEnabled(False) self.lineEdit.clear() self.textBrowser.clear() #按钮的响应函数 def runButton_clicked(self): language = StoreInfoParser.instance().getLanguage() m_pTranslator = QTranslator() exePath = "./" if language == "chinese": QmName = "zh_CN.qm" else: QmName = "en_US.qm" if(m_pTranslator.load(QmName, exePath)): QCoreApplication.instance().installTranslator(m_pTranslator) #self.pro = QProcess(self)#外部程序使用声明 desktop = QApplication.desktop()#获得桌面 self.textBrowser.clear()#清除 cmdstr = QString() center = QString() goal = QString() #comBox当前text为ping if (self.comBox.currentText() == "Ping" or self.comBox.currentText() == "ping"): if (self.runButton.text() == self.tr("Run")) : center = self.lineEdit.text().trimmed() if not center: InfoHintDialog(self.tr("please input the IP address")).exec_() # self.tipDlg.setTip(self.tr("请输入ping地址!!!")) # self.tipDlg.show() # self.tipDlg.move((desktop.width()-self.tipDlg.width())/2,(desktop.height()-self.tipDlg.height())/2) self.runButton.setText(self.tr("Run")) else: self.comBox.setDisabled(True) self.pro = QProcess(self) self.runButton.setText(self.tr("stop ping")) cmdstr = "ping " +center self.textBrowser.clear() self.textBrowser.append(self.tr(" ping ")+center+self.tr(" result:")) else: self.comBox.setDisabled(False) self.runButton.setText(self.tr("Run")) self.pro.close() elif(self.comBox.currentText() == "ifconfig"): self.pro = QProcess(self) self.lineEdit.clear() self.lineEdit.setEnabled(False) self.textBrowser.clear() cmdstr = "ifconfig" # #如果comBox当前为traceroute # elif(self.comBox.currentText() == "traceroute"): # goal = self.lineEdit.text() # if (self.runButton.text() == u"执行"): # if( goal.isEmpty() or goal.isNull() ): # InfoHintDialog(u'请输入tracer地址:').exec_() # # self.tipDlg.setTip(self.tr("请输入tracer地址:")) # # self.tipDlg.show() # # self.tipDlg.move((desktop.width()-self.tipDlg.width())/2,(desktop.height()-self.tipDlg.height())/2) # # # #QMessageBox.information(self,self.tr("错误"),self.tr("请输入traceroute的目标地址")) # #return # else: # self.proc = QProcess(self) # #self.textBrowser.clear() # cmdstrc = "traceroute -n "+ goal # self.proc.start(cmdstrc) # self.connect(self.proc, SIGNAL("readyReadStandardOutput()"),self.readR) # self.connect(self.proc, SIGNAL("readyReadStandardError()"),self.readErrorR) # if self.proc.waitForStarted(10) == True: # self.comBox.setDisabled(True) # self.runButton.setText(self.tr("停止执行")) # else: # self.runButton.setText(self.tr("执行")) # self.comBox.setDisabled(False) # self.proc.close() # #如果comBox当前为display elif (self.comBox.currentText() == "display"): self.pro = QProcess(self) cmdstr = "../lib/ccr_jytcapi display" self.textBrowser.clear() #如果当前命令cmdstr不为空,则 elif (self.comBox.currentText() == "top"): if self.runButton.text() == self.tr("Run") : self.thread.start() self.comBox.setDisabled(True) self.runButton.setText(self.tr("stop top")) else: self.textBrowser.clear() self.thread.auto = False #self.thread.destroyed() self.comBox.setDisabled(False) self.runButton.setText(self.tr("Run")) if (cmdstr != ""): self.pro.start(cmdstr)#开启执行命令 self.connect(self.pro, SIGNAL("readyReadStandardOutput()"),self.read)#读取执行正常输出槽函数 self.connect(self.pro, SIGNAL("readyReadStandardError()"),self.readError)#执行异常槽函数 #读取控制台输出 def read(self): res = QString.fromLocal8Bit(self.pro.readAllStandardOutput()) self.textBrowser.append(res)#添加到text框 #读取错误 def readError(self): res = QString.fromLocal8Bit(self.pro.readAllStandardError()) self.textBrowser.append(res) def readR(self): res = QString.fromLocal8Bit(self.proc.readAllStandardOutput()) #self.textBrowser.clear() self.textBrowser.append(res) def readErrorR(self): res = QString.fromLocal8Bit(self.proc.readAllStandardError()) self.textBrowser.append(res) def updateWindow(self): if self.pro.isOpen(): self.pro.close() self.thread.auto = False self.comBox.setDisabled(False) self.comBox.setCurrentIndex(0) self.runButton.setText((self.tr("Run"))) self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button")) self.textBrowser.clear()
class ItemEntriesFrame(QFrame): read_block = pyqtSignal(int, int) # start_addr, num_bytes poke_block = pyqtSignal(int, QByteArray, bool) # start_addr, raw_bytes, is_ascii log = pyqtSignal(str, str) # msg, color MISSING_ITEM_NAME = '[NOT IN DB]' def __init__(self, type_val, addr_start, addr_end, label, id2name, idx2id, names, parent=None): super(ItemEntriesFrame, self).__init__(parent) self.type_val = type_val self.addr_start = addr_start self.addr_end = addr_end self.max_num_slots = (addr_end - addr_start)/3/4 + 1 self.label = label self.id2name = id2name self.idx2id = idx2id self.names = names self.slots_cache = [] # tuple: (addr_hex, addr_val, slot_number, cur_val) self.cur_slot_idx = -1 self.lbl_label = QLabel(self.label, self) self.btn_read_slots = QPushButton(' Cache Slots', self) self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png')) self.btn_read_slots.setStyleSheet('background-color: white') self.btn_read_slots.clicked.connect(self.onReadSlots) self.btn_search_cache = QPushButton(' Search ID', self) self.btn_search_cache.setIcon(QIcon('img/flaticon/magnifier13.png')) self.btn_search_cache.setToolTip('Find slot in cache with specified item ID') self.btn_search_cache.setStyleSheet('background-color: white') self.btn_search_cache.clicked.connect(self.onSearchCacheForID) self.btn_read = QPushButton(self) self.btn_read.setIcon(QIcon('img/flaticon/open135.png')) self.btn_read.setToolTip('Read item slot value from memory') self.btn_read.setStyleSheet('background-color: white') self.btn_read.clicked.connect(self.onReadSlot) self.cmb_slots = QComboBox(self) self.cmb_slots.setToolTip('') self.cmb_slots.setStyleSheet('background-color: white') self.cmb_slots.currentIndexChanged[int].connect(self.onChangeSlot) self.cmb_slots.setDisabled(True) self.cmb_names = QComboBox(self) self.cmb_names.setEditable(True) self.cmb_names.addItems(self.names) self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.currentIndexChanged[int].connect(self.fetchID) self.txt_id = QLineEdit(self) self.txt_id.setPlaceholderText('ID (hex)') self.txt_id.setMaxLength(3) self.txt_id.textChanged.connect(self.fetchName) self.btn_rename = QPushButton(' Fix Name', self) self.btn_rename.setIcon(QIcon('img/flaticon/cloud-storage3.png')) self.btn_rename.setToolTip('Add/Correct Item Name for %s (type: %02X)' % (self.label, type_val)) self.btn_rename.setStyleSheet('background-color: white') self.btn_rename.clicked.connect(self.onRename) self.txt_amount = QLineEdit(self) self.txt_amount.setPlaceholderText('Amount') self.txt_amount.setMaxLength(3) self.btn_poke = QPushButton(self) self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png')) self.btn_poke.setToolTip('Poke new value for item slot') self.btn_poke.setStyleSheet('background-color: white') self.btn_poke.clicked.connect(self.onPokeSlot) self.layout = QGridLayout(self) self.layout.addWidget(self.lbl_label, 0, 0) self.layout.addWidget(self.btn_read_slots, 0, 1) self.layout.addWidget(self.btn_search_cache, 0, 2) self.layout.addWidget(self.cmb_slots, 0, 3) self.layout.addWidget(self.btn_read, 0, 4) self.layout.addWidget(self.cmb_names, 1, 0) self.layout.addWidget(self.txt_id, 1, 1) self.layout.addWidget(self.btn_rename, 1, 2) self.layout.addWidget(self.txt_amount, 1, 3) self.layout.addWidget(self.btn_poke, 1, 4) self.layout.setColumnStretch(0, 7) self.layout.setColumnStretch(1, 3) self.layout.setColumnStretch(2, 3) self.layout.setColumnStretch(3, 3) self.layout.setColumnStretch(4, 1) self.layout.setContentsMargins(0, 2, 0, 2) icon_height = self.lbl_label.height()*8/15 icon_size = QSize(icon_height, icon_height) self.btn_read_slots.setIconSize(icon_size) self.btn_search_cache.setIconSize(icon_size) self.btn_rename.setIconSize(icon_size) self.btn_read.setIconSize(icon_size) self.btn_poke.setIconSize(icon_size) btn_size = QSize(icon_height*1.5, icon_height*1.5) self.btn_read.setFixedSize(btn_size) self.btn_poke.setFixedSize(btn_size) self.updateUI() def updateUI(self): # Disable editing if cache missing if not (0 <= self.cur_slot_idx < len(self.slots_cache)): self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.setDisabled(True) self.txt_id.setText('') self.txt_id.setDisabled(True) return # Validate current value cur_val = self.slots_cache[self.cur_slot_idx][3] (type_val, id_val, amount) = parse_item_word(cur_val) if type_val != self.type_val and type_val != 0: self.log.emit('Coding error: val(%s)=%08X, type (%02X) != expected (%02X)' % (self.cur_addr_str, cur_val, type_val, self.type_val), 'red') return # Update UI self.txt_id.setDisabled(False) self.txt_id.setText('%03X' % id_val) self.cmb_names.setDisabled(False) self.fetchName() self.txt_amount.setText(str(amount)) def setAlternateBGColor(self): self.setStyleSheet('ItemEntriesFrame { background-color:rgb(248,248,248) }') @pyqtSlot() def onRename(self): id_txt = str(self.txt_id.text()) if len(id_txt) != 3: return dialog = FixItemNameDialog('%02X' % self.type_val, id_txt, self) dialog.log.connect(self.log) dialog.exec_() @pyqtSlot() def onReadSlots(self): self.read_block.emit(self.addr_start, self.max_num_slots*4*3) @pyqtSlot(int, int, QByteArray) def onBlockRead(self, addr_start, num_bytes, raw_bytes): # Determine whether block has cache or single slot if addr_start == self.addr_start and num_bytes == self.max_num_slots*4*3: self.onCacheRead(addr_start, raw_bytes) elif num_bytes == 4: # Assume read slot # Ignore if no cache if not (0 <= self.cur_slot_idx < len(self.slots_cache)): return self.onSlotRead(addr_start, raw_bytes) def onCacheRead(self, addr_start, raw_bytes): slot_bytes = str(raw_bytes) self.slots_cache = [] slots_txt = [] for slot_i in xrange(self.max_num_slots): byte_offset = slot_i*3*4 cur_slot_bytes = slot_bytes[byte_offset:(byte_offset+4)] if len(cur_slot_bytes) != 4: continue cur_slot_val = struct.unpack('>I', cur_slot_bytes)[0] (type_val, id_val, amount) = parse_item_word(cur_slot_val) if type_val == 0 or amount == 0: continue elif type_val != self.type_val: self.log.emit('val(%08X)=%08X, type_val(%02X) unexpected(%02X)' % (addr_start+byte_offset, cur_slot_val, type_val, self.type_val), 'red') continue else: addr_val = addr_start + byte_offset addr_hex = '%08X' % addr_val slot_number = slot_i+1 self.slots_cache.append((addr_hex, addr_val, slot_number, cur_slot_val)) slots_txt.append('Slot %03d' % slot_number) # Update UI self.log.emit('Found %d %s slots in memory' % (len(self.slots_cache), self.label), 'black') self.cmb_slots.clear() if len(self.slots_cache) <= 0: self.cmb_slots.setDisabled(True) self.cur_slot_idx = -1 else: self.cmb_slots.setDisabled(False) self.cmb_slots.addItems(slots_txt) self.cur_slot_idx = 0 self.updateUI() def onSlotRead(self, addr_word, raw_bytes): addr_cur_slot = self.slots_cache[self.cur_slot_idx][1] if addr_word == addr_cur_slot: cur_cache = self.slots_cache[self.cur_slot_idx] new_val = struct.unpack('>I', str(raw_bytes))[0] new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val) self.slots_cache[self.cur_slot_idx] = new_cache self.updateUI() else: # Update cached value of other slots addr_first_slot = self.slots_cache[0][1] addr_last_slot = self.slots_cache[-1][1] if (addr_first_slot <= addr_word <= addr_last_slot) and \ ((addr_word - addr_first_slot) % 12 == 0): for slot_i in xrange(len(self.slots_cache)): addr_cur_slot = self.slots_cache[slot_i][1] if addr_word == addr_cur_slot: cur_cache = self.slots_cache[slot_i] new_val = struct.unpack('>I', str(raw_bytes))[0] new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val) self.slots_cache[slot_i] = new_cache return @pyqtSlot() def onSearchCacheForID(self): # Stop if no cache if not (0 <= self.cur_slot_idx < len(self.slots_cache)): self.log.emit('Must cache slots before searching', 'red') return # Fetch and validate target ID try: target_id_val = int(str(self.txt_id.text()), 16) if target_id_val < 0 or target_id_val > Item.MAX_ID_VAL: self.log.emit('Item ID out of [0, 0x%03X] range' % Item.MAX_ID_VAL) return except ValueError: self.log.emit('Failed to parse item ID, expecting XXX', 'red') return # Search ID in cache for cand_slot_idx in xrange(len(self.slots_cache)): (type_val, id_val, amount) = parse_item_word(self.slots_cache[cand_slot_idx][3]) if id_val == target_id_val and type_val == self.type_val: self.cur_slot_idx = cand_slot_idx self.cmb_slots.setCurrentIndex(self.cur_slot_idx) self.updateUI() return self.log.emit('Did not find ID=%03X in %d cached %s slots' % (target_id_val, len(self.slots_cache), self.label), 'red') @pyqtSlot(int) def onChangeSlot(self, new_slot_idx): # Validate new_slot_idx if not (0 <= new_slot_idx < len(self.slots_cache)): return # Update slot idx and read value from memory self.cur_slot_idx = new_slot_idx cur_addr_hex = self.slots_cache[self.cur_slot_idx][0] self.cmb_slots.setToolTip(cur_addr_hex) self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME) self.cmb_names.setDisabled(True) self.txt_id.setText('') self.txt_id.setDisabled(True) self.onReadSlot() @pyqtSlot() def fetchName(self): try: id_val = int(str(self.txt_id.text()), 16) except ValueError: return name = self.MISSING_ITEM_NAME if id_val in self.id2name: name = self.id2name[id_val] self.cmb_names.lineEdit().setText(name) @pyqtSlot(int) def fetchID(self, cmb_idx): if cmb_idx < 0 or cmb_idx >= len(self.idx2id): self.txt_id.setText('') else: self.txt_id.setText(self.idx2id[cmb_idx]) @pyqtSlot() def onReadSlot(self): try: if not (0 <= self.cur_slot_idx < len(self.slots_cache)): raise ValueError('must cache slots before reading') addr_cur_slot = self.slots_cache[self.cur_slot_idx][1] self.read_block.emit(addr_cur_slot, 4) except ValueError, e: cur_slot_num = self.slots_cache[self.cur_slot_idx][2] self.log.emit('READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red') except BaseException, e: cur_slot_num = self.slots_cache[self.cur_slot_idx][2] self.log.emit('READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red') traceback.print_exc()
class PlotExportSettingsWidget(QWidget): def __init__(self, parent, slice_view_widget, context): super(PlotExportSettingsWidget, self).__init__(parent) self._slice_view_widget = slice_view_widget self._context = context self._dpi_units = ["in", "cm", "px"] if parent is None: w, h, dpi = 11.7, 8.3, 100 else: fig = self._slice_view_widget.layout_figure() w, h = fig.get_size_inches() dpi = fig.dpi self._label = QLabel() self._label.setDisabled(True) self._set_label_txt(w, h, self._dpi_units[0]) self._fix_size = QCheckBox() self._fix_width = QDoubleSpinBox() self._fix_width.setDisabled(True) self._fix_height = QDoubleSpinBox() self._fix_height.setDisabled(True) self._fix_dpi_units = QComboBox() self._fix_dpi_units.setDisabled(True) self._fix_width.setMinimum(1) self._fix_width.setMaximum(32000) self._fix_width.setValue(w) self._fix_height.setMinimum(1) self._fix_height.setMaximum(32000) self._fix_height.setValue(h) self._fix_width.valueChanged.connect(self._fixed_image) self._fix_height.valueChanged.connect(self._fixed_image) self._fix_dpi_units.addItems(self._dpi_units) self._fix_dpi_units.activated.connect(self._fixed_image) self._fix_size.toggled.connect(self._fixed_image) self._label_widget = self._label self._enable_widget = self._fix_size self._dpi_widget = self._fix_dpi_units self._height_widget = self._fix_height self._width_widget = self._fix_width @property def label(self): return self._label_widget @property def checkbox(self): return self._enable_widget @property def width_spinbox(self): return self._width_widget @property def height_spinbox(self): return self._height_widget @property def units_combobox(self): return self._dpi_widget @staticmethod def to_inches(width, height, dpi, scale): if scale == "in": return (width, height, dpi) elif scale == "cm": return (width / 2.54, height / 2.54, dpi) elif scale == "px": return (width / dpi, height / dpi, dpi) else: raise NotImplementedError def _set_label_txt(self, w, h, scale): self._label.setText("{0} x {1} {2}".format(w, h, scale)) def _fixed_image(self): ctx = self._context # toggle disabled self._fix_height.setDisabled(not self._fix_size.isChecked()) self._fix_width.setDisabled(not self._fix_size.isChecked()) self._fix_dpi_units.setDisabled(not self._fix_size.isChecked()) self._label.setDisabled(not self._fix_size.isChecked()) if not self._fix_size.isChecked(): ctx.set_image_size(None) return w = self._fix_width.value() h = self._fix_height.value() dpi = 100 scale = self._fix_dpi_units.currentText() self._set_label_txt(w, h, scale) ctx.set_image_size(*self.to_inches(w, h, dpi, scale))