Exemplo n.º 1
0
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))
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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()
Exemplo n.º 6
0
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 )
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
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()
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
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)  # 进程窗口展示进度条???