class PreviewFileDialog(QFileDialog): def __init__(self, caption, directory, filter): QFileDialog.__init__(self, None, caption, directory, filter) self.setObjectName('PreviewFileDialog') box = QVBoxLayout() self.preview = QLabel("Preview", self) self.preview.setAlignment(Qt.AlignCenter) self.preview.setObjectName("labelPreview") box.addWidget(self.preview) # inject into own layout layout = self.layout() layout.addLayout(box, 1, 3, 3, 1) self.preview.setFixedWidth(400) self.currentChanged.connect(self.onCurrentChanged) def onCurrentChanged(self, path): print("current changed") pixmap = QPixmap(path) if not pixmap: self.preview.setText("Not an image") else: self.preview.setPixmap(pixmap.scaled(self.preview.width(), self.preview.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
class MActionBar(MFrame): def __init__(self, parent=None): super(MActionBar, self).__init__(parent) self.__pic_bg = QPixmap(':resource') self.__dict_widget = dict() self.__setup_ui() def __setup_ui(self): self.__btn_music_previous = MButton(self, MButton.Type.Previous) self.__btn_music_previous.setToolTip('上一首') self.__dict_widget['BTN_PREVIOUS'] = self.__btn_music_previous self.__btn_music_next = MButton(self, MButton.Type.Next) self.__btn_music_next.setToolTip('下一首') self.__dict_widget['BTN_NEXT'] = self.__btn_music_next self.__btn_music_play_pause = MButton(self, MButton.Type.Play) self.__btn_music_play_pause.setToolTip('播放') self.__dict_widget['BTN_PLAY_PAUSE'] = self.__btn_music_play_pause self.__btn_music_stop = MButton(self, MButton.Type.Stop) self.__btn_music_stop.setToolTip('停止') self.__btn_music_stop.setEnabled(False) self.__dict_widget['BTN_STOP'] = self.__btn_music_stop self.__indicator = MIndicator(self) self.__indicator.setText(u'无音乐') self.__indicator.setRollingSpeed(300) self.__dict_widget['INDICT_INFO'] = self.__indicator self.__volume_slider = MVolumeSlider(self) self.__dict_widget['SLD_VOL'] = self.__volume_slider self.__seek_slider = MSeekSlider(self) self.__dict_widget['SLD_SEEK'] = self.__seek_slider self.__label_time_remain = QLabel(self) self.__label_time_remain.setAlignment(Qt.AlignLeft | Qt.AlignTop) MStyleSetter.setStyle(self.__label_time_remain, ':qss_lbl_time_remain') self.__label_time_remain.setText('00:00') self.__dict_widget['LBL_TIME_REMAIN'] = self.__label_time_remain self.__label_time_total = QLabel(self) self.__label_time_total.setAlignment(Qt.AlignRight | Qt.AlignTop) MStyleSetter.setStyle(self.__label_time_total, ':qss_lbl_time_remain') self.__label_time_total.setText('00:00') self.__dict_widget['LBL_TIME_TOTAL'] = self.__label_time_total self.__btn_lyric = MButton(self, MButton.Type.Hide_Lyric) self.__btn_lyric.setToolTip('歌词') self.__dict_widget['BTN_LYRIC'] = self.__btn_lyric self.__btn_add_music = MButton(self, MButton.Type.Add_Music) self.__btn_add_music.setToolTip('添加音乐') self.__dict_widget['BTN_ADD_MUSIC'] = self.__btn_add_music def get_widget(self, key): return self.__dict_widget[key] def paintEvent(self, event): painter = QPainter(self) painter.drawPixmap(0, 0, self.width(), self.height() - 8, self.__pic_bg, 12, 28, 1, 54) painter.drawPixmap(0, self.height() - 8, self.width(), 8, self.__pic_bg, 12, 82, 1, 8) def resizeEvent(self, event): self.__indicator.setGeometry(16, 16, self.width() - 32, 23) self.__seek_slider.setGeometry(self.__indicator.x() - 20, self.__indicator.y() + 38, self.width() + 6, 3) self.__label_time_remain.setGeometry(self.__seek_slider.x() + 12, self.__seek_slider.y() + 4, 65, 15) self.__label_time_total.setGeometry( self.__label_time_remain.x() + self.__seek_slider.width() - 88, self.__label_time_remain.y(), self.__label_time_remain.width(), self.__label_time_remain.height()) self.__btn_music_previous.setGeometry(self.width() / 2 - 54, self.__indicator.y() + 65, 28, 29) self.__btn_music_next.setGeometry(self.__btn_music_previous.x() + 56, self.__btn_music_previous.y(), self.__btn_music_previous.width(), self.__btn_music_previous.height()) self.__btn_music_play_pause.setGeometry( self.__btn_music_previous.x() + 25, self.__btn_music_previous.y() - 3, 34, 35) self.__btn_music_stop.setGeometry(self.__btn_music_previous.x() + 81, self.__btn_music_previous.y(), self.__btn_music_previous.width(), self.__btn_music_previous.height()) self.__volume_slider.setGeometry(self.__btn_music_previous.x() + 120, self.__btn_music_previous.y() + 5, 100, 18) self.__btn_add_music.setGeometry(self.__seek_slider.x() + 40, self.__btn_music_previous.y() + 4, 28, 23) self.__btn_lyric.setGeometry(self.__btn_add_music.x() + 25, self.__btn_music_previous.y() + 4, 28, 23)
class EditPhotoDialog(QDialog): def __init__(self, parent, path, comment, keywords): super(EditPhotoDialog, self).__init__(parent) controlframe = QFrame() self.image = None self.imgLabel = QLabel() #75 is a magic hack number for my netbook to get the buttons showing on the dlg box as well! self.imgLabel.setPixmap(loadQPixMap(self.image, path, self.imgLabel.width()-75, self.imgLabel.height()-75)) self.imgLabel.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) #self.imgLabel.setScaledContents = True self.imgLabel.setAlignment(Qt.AlignCenter) commentLabel = QLabel("Comment") self.commentEdit = QLineEdit(comment) keywordLabel = QLabel("Keyword") self.keywordEdit = QLineEdit(keywords) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.connect(buttonBox, SIGNAL("accepted()"), self, SLOT("accept()")) self.connect(buttonBox, SIGNAL("rejected()"), self, SLOT("reject()")) self.setWindowTitle("Edit Photo") grid = QGridLayout() grid.addWidget(commentLabel, 0, 0) grid.addWidget(self.commentEdit, 0, 1) grid.addWidget(keywordLabel, 1, 0) grid.addWidget(self.keywordEdit, 1, 1) grid.addWidget(buttonBox, 2, 0, 1, 2) controlframe.setLayout(grid) box = QVBoxLayout() box.addWidget(self.imgLabel) box.addWidget(controlframe) self.setLayout(box)
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 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 XSplitterHandle(QSplitterHandle): CollapseDirection = enum('After', 'Before') def __init__( self, orientation, parent ): super(XSplitterHandle, self).__init__( orientation, parent ) # create a layout for the different buttons self._collapsed = False self._storedSizes = None self._collapseBefore = QToolButton(self) self._resizeGrip = QLabel(self) self._collapseAfter = QToolButton(self) self._collapseBefore.setAutoRaise(True) self._collapseAfter.setAutoRaise(True) self._collapseBefore.setCursor(Qt.ArrowCursor) self._collapseAfter.setCursor(Qt.ArrowCursor) # define the layout layout = QBoxLayout(QBoxLayout.LeftToRight, self) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch(1) layout.addWidget(self._collapseBefore) layout.addWidget(self._resizeGrip) layout.addWidget(self._collapseAfter) layout.addStretch(1) self.setLayout(layout) # set the orientation to start with self.setOrientation(orientation) # create connections self._collapseAfter.clicked.connect( self.toggleCollapseAfter ) self._collapseBefore.clicked.connect( self.toggleCollapseBefore ) def collapse( self, direction ): """ Collapses this splitter handle before or after other widgets based on \ the inputed CollapseDirection. :param direction | <XSplitterHandle.CollapseDirection> :return <bool> | success """ if ( self.isCollapsed() ): return False splitter = self.parent() if ( not splitter ): return False sizes = splitter.sizes() handles = [splitter.handle(i) for i in range(len(sizes))] index = handles.index(self) self.markCollapsed(direction, sizes) # determine the sizes to use based on the direction if ( direction == XSplitterHandle.CollapseDirection.Before ): sizes = [0 for i in range(i)] + sizes[i+1:] else: sizes = sizes[:i] + [0 for i in range(i, len(sizes))] splitter.setSizes(sizes) return True def collapseAfter( self, handle ): """ Collapses the splitter after the inputed handle. :param handle | <XSplitterHandle> """ self.setUpdatesEnabled(False) # collapse all items after the current handle if ( handle.isCollapsed() ): self.setSizes(handle.restoreSizes()) found = False sizes = self.sizes() handle.storeSizes(sizes) for c in range(self.count()): if ( self.handle(c) == handle ): found = True if ( found ): sizes[c] = 0 self.setSizes(sizes) self.update() self.setUpdatesEnabled(True) def collapseBefore( self, handle ): """ Collapses the splitter before the inputed handle. :param handle | <XSplitterHandle> """ self.setUpdatesEnabled(False) # collapse all items after the current handle if ( handle.isCollapsed() ): self.setSizes(handle.restoreSizes()) # collapse all items before the current handle found = False sizes = self.sizes() handle.storeSizes(sizes) for c in range(self.count()): if ( self.handle(c) == handle ): break sizes[c] = 0 self.setSizes(sizes) self.setUpdatesEnabled(True) def isCollapsed( self ): """ Returns whether or not this widget is collapsed. :return <bool> """ return self._collapsed def markCollapsed( self, direction, sizes ): """ Updates the interface to reflect that the splitter is collapsed. :param direction | <XSplitterHandle.CollapseDirection> sizes | [<int>, ..] """ self._collapsed = True self._storedSizes = sizes[:] if ( direction == XSplitterHandle.CollapseDirection.Before ): if ( self.orientation() == Qt.Horizontal ): self._collapseAfter.setArrowType( Qt.RightArrow ) self._collapseBefore.setArrowType( Qt.RightArrow ) else: self._collapseAfter.setArrowType( Qt.DownArrow ) self._collapseBefore.setArrowType( Qt.DownArrow ) else: if ( self.orientation() == Qt.Horizontal ): self._collapseAfter.setArrowType( Qt.LeftArrow ) self._collapseBefore.setArrowType( Qt.LeftArrow ) else: self._collapseAfter.setArrowType( Qt.UpArrow ) self._collapseAfter.setArrowType( Qt.UpArrow ) def paintEvent( self, event ): """ Overloads the paint event to handle drawing the splitter lines. :param event | <QPaintEvent> """ lines = [] count = 20 # calculate the lines if ( self.orientation() == Qt.Vertical ): x = self._resizeGrip.pos().x() h = self.height() spacing = int(float(self._resizeGrip.width()) / count) for i in range(count): lines.append(QLine(x, 0, x, h)) x += spacing else: y = self._resizeGrip.pos().y() w = self.width() spacing = int(float(self._resizeGrip.height()) / count) for i in range(count): lines.append(QLine(0, y, w, y)) y += spacing # draw the lines painter = QPainter() painter.begin(self) pal = self.palette() painter.setPen(pal.color(pal.Window).darker(120)) painter.drawLines(lines) painter.end() def setOrientation( self, orientation ): """ Sets the orientation for this handle and updates the widgets linked \ with it. :param orientation | <Qt.Orientation> """ super(XSplitterHandle, self).setOrientation(orientation) if ( orientation == Qt.Vertical ): self.layout().setDirection( QBoxLayout.LeftToRight ) # update the widgets self._collapseBefore.setFixedSize(30, 10) self._collapseAfter.setFixedSize(30, 10) self._resizeGrip.setFixedSize(60, 10) self._collapseBefore.setArrowType(Qt.UpArrow) self._collapseAfter.setArrowType(Qt.DownArrow) elif ( orientation == Qt.Horizontal ): self.layout().setDirection( QBoxLayout.TopToBottom ) # update the widgets self._collapseBefore.setFixedSize(10, 30) self._collapseAfter.setFixedSize(10, 30) self._resizeGrip.setFixedSize(10, 60) self._collapseBefore.setArrowType(Qt.LeftArrow) self._collapseAfter.setArrowType(Qt.RightArrow) def uncollapse( self ): """ Uncollapses the splitter this handle is associated with by restoring \ its sizes from before the collapse occurred. :return <bool> | changed """ if ( not self.isCollapsed() ): return False self.parent().setSizes(self._storedSizes) self.unmarkCollapsed() return True def unmarkCollapsed( self ): """ Unmarks this splitter as being in a collapsed state, clearing any \ collapsed information. """ if ( not self.isCollapsed() ): return self._collapsed = False self._storedSizes = None if ( self.orientation() == Qt.Vertical ): self._collapseBefore.setArrowType( Qt.UpArrow ) self._collapseAfter.setArrowType( Qt.DownArrow ) else: self._collapseBefore.setArrowType( Qt.LeftArrow ) self._collapseAfter.setArrowType( Qt.RightArrow ) def toggleCollapseAfter( self ): """ Collapses the splitter after this handle. """ if ( self.isCollapsed() ): self.uncollapse() else: self.collapse( XSplitterHandle.CollapseDirection.After ) def toggleCollapseBefore( self ): """ Collapses the splitter before this handle. """ if ( self.isCollapsed() ): self.uncollapse() else: self.collapse( XSplitterHandle.CollapseDirection.Before )
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 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()
def __init__(self, parent=None): QWidget.__init__(self, parent) #self.setupUi(self) self.setWindowTitle(u'大图检测') #self.setFixedSize(1280,720) screen = QDesktopWidget().screenGeometry() #self.resize(screen.width(), screen.height()) self.setFixedSize(screen.width() - 100, screen.height() - 100) self.center() ##########################背景层,使用绝对坐标######################## palette = QPalette() self.setBackgroundandSize(self, './background.png', self.backgroundRole(), screen.height(), screen.width()) ##########################标题部分,用的一张图片###################### title = QLabel() self.setBackgroundandSize(title, './titlebg.png', QPalette.Window, 100, 706) hboxTilte = QHBoxLayout() hboxTilte.addWidget(title) ##############################下方左侧############################# #########并列部分 btnSelFile = QPushButton(u"选择文件") self.setBackgroundandSize(btnSelFile, './yellowbar.png', QPalette.Button, 23, 76) btnSelFile.setFlat(True) #边缘消失 editSelFile = QLineEdit(u"file:///") self.setBackgroundandSize(editSelFile, './greybar.png', QPalette.Base, 23, 115) hboxSelFile = QHBoxLayout() hboxSelFile.addWidget(btnSelFile) hboxSelFile.addWidget(editSelFile) self.connect( btnSelFile, SIGNAL("clicked()"), lambda: self.button_openfile_click( Application.btncontrol, editSelFile, previewImg)) hboxPicSize = QHBoxLayout() self.addRow(hboxPicSize, u"大图尺寸", u"宽:xxx 高:xxx", Application.leftSide) hboxOnlineNodes = QHBoxLayout() self.addRow(hboxOnlineNodes, u"联机集群节点数", u"xxx", Application.leftSide, smaller=True) hboxUsedNodes = QHBoxLayout() self.addRow(hboxUsedNodes, u"使用集群节点数", u"xxx", Application.leftSide, smaller=True) ########原图预览 previewTxt = QLabel(u"原图预览") previewTxt.setFixedHeight(25) previewTxt.setFont(QFont("Times New Roman", 12)) palette.setColor(QPalette.WindowText, Qt.yellow) previewTxt.setPalette(palette) previewTxt.setAlignment(Qt.AlignCenter) previewImg = QLabel() previewImg.setFixedHeight(0.3 * screen.height()) previewImg.setFixedWidth(0.2 * screen.width()) previewImg.setAutoFillBackground(True) previewImg.setAlignment(Qt.AlignCenter) image = QPixmap("./rawpic.png").scaled(previewImg.width(), previewImg.height()) previewImg.setPixmap(image) #self.setBackgroundandSize(previewImg,'./rawpic.png',QPalette.Window,128,196) ########终端显示 statusTxt = QLabel(u"集群终端状态") statusTxt.setFixedHeight(25) statusTxt.setFont(QFont("Times New Roman", 12)) palette.setColor(QPalette.WindowText, Qt.yellow) statusTxt.setPalette(palette) statusTxt.setAlignment(Qt.AlignCenter) #statusImg = QLabel() #statusImg.setFixedHeight(0.3 * screen.height()) #statusImg.setFixedWidth(0.2 * screen.width()) #statusImg.setAutoFillBackground(True) #statusImg.setAlignment(Qt.AlignCenter) #palette.setColor(statusImg.backgroundRole(), Qt.black) #statusImg.setPalette(palette) #statusImg.setText("hello!") self.statusEdit = QTextEdit("python gui.py") statusEdit = self.statusEdit statusEdit.setFixedHeight(0.3 * screen.height()) statusEdit.setFixedWidth(0.2 * screen.width()) statusEdit.setAutoFillBackground(True) statusEdit.setAlignment(Qt.AlignLeft) palette.setColor(QPalette.Base, Qt.black) palette.setColor(QPalette.Text, Qt.yellow) statusEdit.setPalette(palette) #self.setBackgroundandSize(statusImg, './rawpic.png', QPalette.Window, 128, 196) ########以垂直的结构显示 vboxleft = QVBoxLayout() vboxleft.addLayout(hboxSelFile) vboxleft.addLayout(hboxPicSize) vboxleft.addLayout(hboxOnlineNodes) vboxleft.addLayout(hboxUsedNodes) vboxleft.addWidget(previewTxt) vboxleft.addWidget(previewImg) vboxleft.addWidget(statusTxt) #vboxleft.addWidget(statusImg) vboxleft.addWidget(statusEdit) ###########################下方中间部分########################## ########控制按钮 Application.btncontrol = QPushButton(u"将大图发送至集群") Application.btncontrol.setFont(QFont("Times New Roman", 12)) Application.btncontrol.setEnabled(False) Application.btncontrol.setFixedHeight(25) Application.btncontrol.setFixedWidth(200) self.connect(Application.btncontrol, SIGNAL("clicked()"), self.button_control_click) ########显示处理后的图片 mid = QLabel() mid.setFixedHeight(440) mid.setFixedWidth(550) # palette.setColor(QPalette.Window, Qt.red) # mid.setAutoFillBackground(True) # mid.setPalette(palette) ########中间部分垂直布局 vboxmid = QVBoxLayout() vboxmid.addWidget(Application.btncontrol) vboxmid.addWidget(mid) ##########################下方右侧部分############################ ########三个返回值 hboxTime = QHBoxLayout() self.addRow(hboxTime, u"运行时间", u"xxx", Application.rightSide) hboxPlanes = QHBoxLayout() self.addRow(hboxPlanes, u"飞机目标数", u"xxx", Application.rightSide) hboxShips = QHBoxLayout() self.addRow(hboxShips, u"舰船目标数", u"xxx", Application.rightSide) btnCoordFile = QPushButton(u"展示结果图") #self.setBackgroundandSize(btnCoordFile, './yellowbar2.png', QPalette.Button, 23, 115) btnCoordFile.setFlat(True) # 边缘消失 self.connect(btnCoordFile, SIGNAL("clicked()"), self.button_show_click) ###飞机船照片路径 ########显示处理后的图片 #coordFilePath = QLabel(u"file:///") #self.setBackgroundandSize(coordFilePath, './greybar.png', QPalette.Window, 23, 115) hboxCoordFile = QHBoxLayout() #hboxCoordFile.addWidget(coordFilePath) hboxCoordFile.addWidget(btnCoordFile) ########飞机 self.planeImg = QLabel() planeImg = self.planeImg #planeImg.setAlignment(Qt.AlignCenter) #self.setBackgroundandSize(planeImg,'./rawpic2a.png',QPalette.Window,128,196) planeImg.setFixedHeight(0.3 * screen.height()) planeImg.setFixedWidth(0.2 * screen.width()) planeImg.setAutoFillBackground(True) planeImg.setAlignment(Qt.AlignCenter) planeimage = QPixmap("./rawpic2a.png").scaled(planeImg.width(), planeImg.height()) planeImg.setPixmap(planeimage) ########船 self.shipImg = QLabel() shipImg = self.shipImg #shipImg.setAlignment(Qt.AlignCenter) #self.setBackgroundandSize(shipImg, './rawpic2b.png', QPalette.Window, 128, 196) shipImg.setFixedHeight(0.3 * screen.height()) shipImg.setFixedWidth(0.2 * screen.width()) shipImg.setAutoFillBackground(True) shipImg.setAlignment(Qt.AlignCenter) self.shipimage = QPixmap("./rawpic2b.png").scaled( shipImg.width(), shipImg.height()) shipImg.setPixmap(self.shipimage) ########下方右侧布局 vboxright = QVBoxLayout() vboxright.addLayout(hboxTime) vboxright.addLayout(hboxPlanes) vboxright.addLayout(hboxShips) vboxright.addLayout(hboxCoordFile) vboxright.addWidget(planeImg) vboxright.addWidget(shipImg) ##########################整体布局############################ ########下方左中右 hboxbody = QHBoxLayout() hboxbody.addLayout(vboxleft) hboxbody.addStretch(1) hboxbody.addLayout(vboxmid) hboxbody.addStretch(1) hboxbody.addLayout(vboxright) ########上下两部分 vbox = QVBoxLayout() vbox.addLayout(hboxTilte) vbox.addStretch(0) vbox.addLayout(hboxbody) vbox.addStretch(1) self.setLayout(vbox)
class Application(QWidget): leftSide = 1 rightSide = 0 btncontrol = None def __init__(self, parent=None): QWidget.__init__(self, parent) #self.setupUi(self) self.setWindowTitle(u'大图检测') #self.setFixedSize(1280,720) screen = QDesktopWidget().screenGeometry() #self.resize(screen.width(), screen.height()) self.setFixedSize(screen.width() - 100, screen.height() - 100) self.center() ##########################背景层,使用绝对坐标######################## palette = QPalette() self.setBackgroundandSize(self, './background.png', self.backgroundRole(), screen.height(), screen.width()) ##########################标题部分,用的一张图片###################### title = QLabel() self.setBackgroundandSize(title, './titlebg.png', QPalette.Window, 100, 706) hboxTilte = QHBoxLayout() hboxTilte.addWidget(title) ##############################下方左侧############################# #########并列部分 btnSelFile = QPushButton(u"选择文件") self.setBackgroundandSize(btnSelFile, './yellowbar.png', QPalette.Button, 23, 76) btnSelFile.setFlat(True) #边缘消失 editSelFile = QLineEdit(u"file:///") self.setBackgroundandSize(editSelFile, './greybar.png', QPalette.Base, 23, 115) hboxSelFile = QHBoxLayout() hboxSelFile.addWidget(btnSelFile) hboxSelFile.addWidget(editSelFile) self.connect( btnSelFile, SIGNAL("clicked()"), lambda: self.button_openfile_click( Application.btncontrol, editSelFile, previewImg)) hboxPicSize = QHBoxLayout() self.addRow(hboxPicSize, u"大图尺寸", u"宽:xxx 高:xxx", Application.leftSide) hboxOnlineNodes = QHBoxLayout() self.addRow(hboxOnlineNodes, u"联机集群节点数", u"xxx", Application.leftSide, smaller=True) hboxUsedNodes = QHBoxLayout() self.addRow(hboxUsedNodes, u"使用集群节点数", u"xxx", Application.leftSide, smaller=True) ########原图预览 previewTxt = QLabel(u"原图预览") previewTxt.setFixedHeight(25) previewTxt.setFont(QFont("Times New Roman", 12)) palette.setColor(QPalette.WindowText, Qt.yellow) previewTxt.setPalette(palette) previewTxt.setAlignment(Qt.AlignCenter) previewImg = QLabel() previewImg.setFixedHeight(0.3 * screen.height()) previewImg.setFixedWidth(0.2 * screen.width()) previewImg.setAutoFillBackground(True) previewImg.setAlignment(Qt.AlignCenter) image = QPixmap("./rawpic.png").scaled(previewImg.width(), previewImg.height()) previewImg.setPixmap(image) #self.setBackgroundandSize(previewImg,'./rawpic.png',QPalette.Window,128,196) ########终端显示 statusTxt = QLabel(u"集群终端状态") statusTxt.setFixedHeight(25) statusTxt.setFont(QFont("Times New Roman", 12)) palette.setColor(QPalette.WindowText, Qt.yellow) statusTxt.setPalette(palette) statusTxt.setAlignment(Qt.AlignCenter) #statusImg = QLabel() #statusImg.setFixedHeight(0.3 * screen.height()) #statusImg.setFixedWidth(0.2 * screen.width()) #statusImg.setAutoFillBackground(True) #statusImg.setAlignment(Qt.AlignCenter) #palette.setColor(statusImg.backgroundRole(), Qt.black) #statusImg.setPalette(palette) #statusImg.setText("hello!") self.statusEdit = QTextEdit("python gui.py") statusEdit = self.statusEdit statusEdit.setFixedHeight(0.3 * screen.height()) statusEdit.setFixedWidth(0.2 * screen.width()) statusEdit.setAutoFillBackground(True) statusEdit.setAlignment(Qt.AlignLeft) palette.setColor(QPalette.Base, Qt.black) palette.setColor(QPalette.Text, Qt.yellow) statusEdit.setPalette(palette) #self.setBackgroundandSize(statusImg, './rawpic.png', QPalette.Window, 128, 196) ########以垂直的结构显示 vboxleft = QVBoxLayout() vboxleft.addLayout(hboxSelFile) vboxleft.addLayout(hboxPicSize) vboxleft.addLayout(hboxOnlineNodes) vboxleft.addLayout(hboxUsedNodes) vboxleft.addWidget(previewTxt) vboxleft.addWidget(previewImg) vboxleft.addWidget(statusTxt) #vboxleft.addWidget(statusImg) vboxleft.addWidget(statusEdit) ###########################下方中间部分########################## ########控制按钮 Application.btncontrol = QPushButton(u"将大图发送至集群") Application.btncontrol.setFont(QFont("Times New Roman", 12)) Application.btncontrol.setEnabled(False) Application.btncontrol.setFixedHeight(25) Application.btncontrol.setFixedWidth(200) self.connect(Application.btncontrol, SIGNAL("clicked()"), self.button_control_click) ########显示处理后的图片 mid = QLabel() mid.setFixedHeight(440) mid.setFixedWidth(550) # palette.setColor(QPalette.Window, Qt.red) # mid.setAutoFillBackground(True) # mid.setPalette(palette) ########中间部分垂直布局 vboxmid = QVBoxLayout() vboxmid.addWidget(Application.btncontrol) vboxmid.addWidget(mid) ##########################下方右侧部分############################ ########三个返回值 hboxTime = QHBoxLayout() self.addRow(hboxTime, u"运行时间", u"xxx", Application.rightSide) hboxPlanes = QHBoxLayout() self.addRow(hboxPlanes, u"飞机目标数", u"xxx", Application.rightSide) hboxShips = QHBoxLayout() self.addRow(hboxShips, u"舰船目标数", u"xxx", Application.rightSide) btnCoordFile = QPushButton(u"展示结果图") #self.setBackgroundandSize(btnCoordFile, './yellowbar2.png', QPalette.Button, 23, 115) btnCoordFile.setFlat(True) # 边缘消失 self.connect(btnCoordFile, SIGNAL("clicked()"), self.button_show_click) ###飞机船照片路径 ########显示处理后的图片 #coordFilePath = QLabel(u"file:///") #self.setBackgroundandSize(coordFilePath, './greybar.png', QPalette.Window, 23, 115) hboxCoordFile = QHBoxLayout() #hboxCoordFile.addWidget(coordFilePath) hboxCoordFile.addWidget(btnCoordFile) ########飞机 self.planeImg = QLabel() planeImg = self.planeImg #planeImg.setAlignment(Qt.AlignCenter) #self.setBackgroundandSize(planeImg,'./rawpic2a.png',QPalette.Window,128,196) planeImg.setFixedHeight(0.3 * screen.height()) planeImg.setFixedWidth(0.2 * screen.width()) planeImg.setAutoFillBackground(True) planeImg.setAlignment(Qt.AlignCenter) planeimage = QPixmap("./rawpic2a.png").scaled(planeImg.width(), planeImg.height()) planeImg.setPixmap(planeimage) ########船 self.shipImg = QLabel() shipImg = self.shipImg #shipImg.setAlignment(Qt.AlignCenter) #self.setBackgroundandSize(shipImg, './rawpic2b.png', QPalette.Window, 128, 196) shipImg.setFixedHeight(0.3 * screen.height()) shipImg.setFixedWidth(0.2 * screen.width()) shipImg.setAutoFillBackground(True) shipImg.setAlignment(Qt.AlignCenter) self.shipimage = QPixmap("./rawpic2b.png").scaled( shipImg.width(), shipImg.height()) shipImg.setPixmap(self.shipimage) ########下方右侧布局 vboxright = QVBoxLayout() vboxright.addLayout(hboxTime) vboxright.addLayout(hboxPlanes) vboxright.addLayout(hboxShips) vboxright.addLayout(hboxCoordFile) vboxright.addWidget(planeImg) vboxright.addWidget(shipImg) ##########################整体布局############################ ########下方左中右 hboxbody = QHBoxLayout() hboxbody.addLayout(vboxleft) hboxbody.addStretch(1) hboxbody.addLayout(vboxmid) hboxbody.addStretch(1) hboxbody.addLayout(vboxright) ########上下两部分 vbox = QVBoxLayout() vbox.addLayout(hboxTilte) vbox.addStretch(0) vbox.addLayout(hboxbody) vbox.addStretch(1) self.setLayout(vbox) def center(self): screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def setBackgroundandSize(self, qwidget, imgpath, role, fixedHeight=None, fixedWidth=None): if isinstance(qwidget, QWidget) and isinstance(imgpath, str): palette = QPalette() palette.setBrush(role, QBrush(QPixmap(imgpath))) qwidget.setAutoFillBackground(True) qwidget.setPalette(palette) if fixedHeight is not None and fixedWidth is not None: qwidget.setFixedHeight(fixedHeight) qwidget.setFixedWidth(fixedWidth) def addRow(self, box, text, text_, pos, smaller=False): # 用smaller的原因是有时候文本过长,所以缩小字号 lab = QLabel(text) if smaller: lab.setFont(QFont("Times New Roman", 8)) lab.setAlignment(Qt.AlignCenter) if pos: self.setBackgroundandSize(lab, './yellowbar.png', QPalette.Window, 23, 76) else: self.setBackgroundandSize(lab, './yellowbar2.png', QPalette.Window, 23, 76) lab_ = QLabel(text_) lab_.setAlignment(Qt.AlignCenter) self.setBackgroundandSize(lab_, './greybar.png', QPalette.Window, 23, 115) if pos: #pos==1表示左侧那四行,pos==0表示右侧那四行 box.addWidget(lab) box.addWidget(lab_) else: box.addWidget(lab_) box.addWidget(lab) #self.labels.append(lab) #self.labels.append(lab_) def button_openfile_click(self, btncontrol, editSelFile, previewImg): absulute_path = QFileDialog.getOpenFileName(self, 'Open File', '.', 'png files(*.png)') if absulute_path: cur_path = QDir('.') relative_path = cur_path.relativeFilePath(absulute_path) editSelFile.setText(relative_path) image = QPixmap(relative_path).scaled(previewImg.width(), previewImg.height()) previewImg.setPixmap(image) os.system("python aaa.py") self.statusEdit.append("python aaa.py") #self.hboxPicSize.setText(u"???") #self.hboxOnlineNodes.setText(u"???") #self.hboxUsedNodes.setText(u"???") btncontrol.setEnabled(True) def button_control_click(self): #点几次?? Application.btncontrol.setEnabled(False) self.statusEdit.append("./???.sh") self.controlThread = Runthread(True) self.controlThread.finishSignal_sh.connect(self.terminal) self.controlThread.start() def terminal(self, str): self.statusEdit.append(str) #进程窗口展示进度条??? if str == "end": Application.btncontrol.setEnabled(True) def button_show_click(self): self.planeThread = Runthread(False, "plane") self.planeThread.finishSignal_sh.connect(self.showplanepicture) self.planeThread.start() self.shipThread = Runthread(False, "ship") self.shipThread.finishSignal_sh.connect(self.showshippicture) self.shipThread.start() #def button_show_click(self): # kinds =["plane","ship"] # for kind in kinds: # self.kindThread = Runthread(False,kind) # if kind =="plane": # self.kindThread.finishSignal_show.connect(self.showplanepicture) # else: # self.kindThread.finishSignal_show.connect(self.showshippicture) # self.kindThread.start() def showshippicture(self, str): print str if "png" in str: print "right" shipimage = QPixmap("./ship/" + str).scaled( self.shipImg.width(), self.shipImg.height()) self.shipImg.setPixmap(shipimage) else: self.statusEdit.append(str) # 进程窗口展示进度条??? def showplanepicture(self, str): print str if "png" in str: print "right" planeimage = QPixmap("./plane/" + str).scaled( self.planeImg.width(), self.planeImg.height()) self.planeImg.setPixmap(planeimage) else: self.statusEdit.append(str) # 进程窗口展示进度条???