class DiffGUI(object):
    ' diff gui class '
    def __init__(self):
        ' make a diff method with GUI '
        self.dialog = QDialog()
        self.diff_path = None

        # directory auto completer
        self.completer = QCompleter(self.dialog)
        self.dirs = QDirModel(self.dialog)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        #self.completer.setCompletionMode(QCompleter.InlineCompletion)

        self.group1 = QGroupBox()
        self.group1.setTitle('Diff')
        self.frmt = QComboBox(self.group1)
        self.frmt.addItems(['Unified', 'Normal', 'Context'])
        self.file1 = QLineEdit()
        self.file1.setPlaceholderText('/full/path/to/one_file.py')
        self.file1.setCompleter(self.completer)
        self.file2 = QLineEdit()
        self.file2.setPlaceholderText('/full/path/to/another_file.py')
        self.file2.setCompleter(self.completer)
        self.fout = QLineEdit()
        self.fout.setText(''.join((path.join(gettempdir(),
                     datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff')))))
        self.fout.setPlaceholderText('/full/path/to/output_file.diff')
        self.fout.setCompleter(self.completer)
        self.regex = QLineEdit()
        self.regex.setPlaceholderText('DONT use unless you know what are doing')
        self.regex.setToolTip('Do NOT use unless you know what you are doing !')
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.borig.clicked.connect(lambda: self.file1.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))

        self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bmodi.clicked.connect(lambda: self.file2.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))
        self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bout.clicked.connect(lambda: self.fout.setText(str(
            QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file',
                                        path.expanduser("~"), ';;(*.diff)'))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('Original file full path'),
                            self.file1, self.borig,
                            QLabel('Modified file full path'),
                            self.file2, self.bmodi,
                            QLabel('Output file full Path'),
                            self.fout, self.bout,
                            QLabel('Diff Output Format'), self.frmt,
                            QLabel('Diff REGEX to Ignore (ADVANCED)'),
                            self.regex):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle('Options')
        self.nwfl = QCheckBox('Treat new files as Empty')
        self.smll = QCheckBox('Look for smaller changes')
        self.lrgf = QCheckBox('Optimize for large files')
        self.case = QCheckBox('Ignore case changes on content')
        self.cnvt = QCheckBox('Convert Tabs to Spaces')
        self.blnk = QCheckBox('Ignore added or removed Blank lines')
        self.spac = QCheckBox('Ignore changes in amount of Spaces')
        self.whit = QCheckBox('Ignore ALL white Spaces')
        self.tabz = QCheckBox('Ignore changes by Tab expansions')
        self.sprs = QCheckBox('Remove Space or Tab before empty lines')
        self.filn = QCheckBox('Ignore case when comparing file names')
        self.tbs = QComboBox(self.group2)
        self.tbs.addItems(['4', '6', '8', '10', '2'])
        self.nice = QComboBox(self.group2)
        self.nice.addItems(['20', '15', '10', '5', '0'])
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.nwfl, self.smll, self.lrgf, self.case,
                            self.cnvt, self.blnk, self.spac, self.whit,
                            self.tabz, self.sprs, self.filn,
                            QLabel('Diff Tabs-to-Spaces Size'), self.tbs,
                            QLabel('Diff Backend CPU Priority'), self.nice):
            vboxg2.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        group3 = QGroupBox()
        group3.setTitle('Even More Options')
        self.plai = QCheckBox('Force treat all files as plain text')
        self.nocr = QCheckBox('Force strip trailing carriage return')
        self.ridt = QCheckBox('Report when two files are identical')
        self.nocm = QCheckBox('Do not output common lines')
        self.rdif = QCheckBox('Report only when files differ')
        self.clip = QCheckBox('Copy Diff to Clipboard when done')
        self.noti = QCheckBox('Use system Notification when done')
        self.pret = QCheckBox('Align all Tabs by prepending a Tab')
        self.lolz = QCheckBox('Output Diff in two equal columns')
        self.odif = QCheckBox('Open Diff with Ninja-IDE when done')
        self.plac = QCheckBox('Make an Awesome Diff view when done')
        self.wdth = QComboBox(group3)
        self.wdth.addItems(['80', '100', '120', '130', '250', '500', '999999'])
        self.bcknd = QComboBox(group3)
        self.bcknd.addItems(['diff', 'diff.py'])
        self.bcknd.setDisabled(True)  #TODO this feature needs work
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (self.plai, self.nocr, self.ridt, self.nocm,
                            self.rdif, self.pret, self.clip, self.noti,
                            self.lolz, self.odif, self.plac,
                            QLabel('Diff Maximum Total Width'), self.wdth,
                            QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd):
            vboxg3.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf,
                                   self.clip, self.cnvt, self.plai, self.noti):
            widget_should_be_checked.setChecked(True)

        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)

        buttons = QDialogButtonBox()
        buttons.resize(self.dialog.size().width(), buttons.size().height() * 2)
        buttons.setOrientation(Qt.Horizontal)
        buttons.setStandardButtons(
            QDialogButtonBox.Ok |
            QDialogButtonBox.Cancel |
            QDialogButtonBox.Close |
            QDialogButtonBox.Help)
        buttons.setCenterButtons(False)
        buttons.helpRequested.connect(lambda: QMessageBox.about(
            self.dialog, __doc__,
            ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep,
            'version ', __version__, ', (', __license__, '), by ', linesep,
            __author__, ', ( ', __email__, ' ).', linesep))))
        buttons.rejected.connect(self.dialog.close)
        buttons.accepted.connect(self.make_diff)

        info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>',
                      getoutput('diff --version').split(linesep)[0])))

        vbox = QVBoxLayout(self.dialog)
        for each_widget in (
                QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'),
                container, info, buttons):
            vbox.addWidget(each_widget)

        self.dialog.resize(1024, self.dialog.size().height())
        self.dialog.exec_()

    def make_diff(self):
        ' make the diff '
        diff_command = ''.join((
        'nice --adjustment=', str(self.nice.currentText()).strip(), ' ',
        str(self.bcknd.currentText()).strip(), ' --',
        str(self.frmt.currentText()).strip().lower(),

        ' --new-file ' if self.nwfl.isChecked() is True else '',
        ' --minimal ' if self.smll.isChecked() is True else '',
        ' --speed-large-files ' if self.lrgf.isChecked() is True else '',
        ' --ignore-self.case ' if self.case.isChecked() is True else '',
        ' --expand-tabs ' if self.cnvt.isChecked() is True else '',
        ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '',
        ' --ignore-space-change ' if self.spac.isChecked() is True else '',
        ' --ignore-all-space ' if self.whit.isChecked() is True else '',
        ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '',
        ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '',
        ' --ignore-file-name-case ' if self.filn.isChecked() is True else '',
        ' --text ' if self.plai.isChecked() is True else '',
        ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '',
        ' --suppress-common-lines ' if self.nocm.isChecked() is True else '',
        ' --initial-tab ' if self.pret.isChecked() is True else '',
        ' --side-by-side ' if self.lolz.isChecked() is True else '',

        ' --tabsize=', str(self.tbs.currentText()).strip(),
        ' --width=', str(self.wdth.currentText()).strip(),

        str(' --ignore-matching-lines=' + str(self.regex.text()).strip())
                           if str(self.regex.text()).strip() is not '' else '',
        ' ',
        path.abspath(str(self.file1.text()))
                    if str(self.file1.text()).strip() is not '' else __file__,
        ' ',
        path.abspath(str(self.file2.text()))
                    if str(self.file2.text()).strip() is not '' else __file__
        ))

        print(diff_command)
        diff_output = getoutput(diff_command)
        try:
            print(' INFO: OK, Saving new Diff to disk...')
            output_file = file(path.abspath(str(self.fout.text())), 'w')
            output_file.write(diff_output)
            output_file.close()
        except:
            print(' ERROR: FAIL, Can not save Diff to disk!')
        if self.clip.isChecked() is True:
            print(' INFO: OK, Diff Copied to Clipboard...')
            QApplication.clipboard().setText(diff_output)
        if self.noti.isChecked() is True:
            call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True)
        if self.odif.isChecked() is True:
            print(' INFO: OK, Opening Diff with Ninja-IDE')
            call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True)

        self.diff_path = path.abspath(str(self.fout.text()))
        return self.diff_path
class GearEntriesFrame(QFrame):
  read_block = pyqtSignal(int, int)  # start_addr, num_bytes
  poke_block = pyqtSignal(int, QByteArray, bool)  # start_addr, raw_bytes, is_ascii
  log = pyqtSignal(str, str)  # msg, color

  MISSING_SKILL_NAME = '[NOT IN DB]'

  def __init__(self, addr_start, addr_end, class_label, skill2id, id2skill, parent=None):
    super(GearEntriesFrame, self).__init__(parent)
    self.addr_start = addr_start
    self.addr_end = addr_end
    self.max_num_slots = (addr_end - addr_start) / 6 / 4 + 1
    self.class_label = class_label
    self.skill2id = skill2id
    self.id2skill = id2skill

    self.skill_names = self.skill2id.keys()
    self.skill_names.sort()

    self.slots_cache = []  # list of raw 6*4 bytes
    self.slots_txt = None
    self.cur_slot_idx = -1
    self.cur_slot_bytes = None

    self.lbl_label = QLabel(self.class_label, self)

    self.btn_read_slots = QPushButton(' Cache Slots', self)
    self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png'))
    self.btn_read_slots.setStyleSheet('background-color: white')
    self.btn_read_slots.clicked.connect(self.onReadSlots)

    self.cmb_slots = QComboBox(self)
    self.cmb_slots.setToolTip('')
    self.cmb_slots.setStyleSheet('background-color: white')
    self.cmb_slots.currentIndexChanged[str].connect(self.onChangeSlot)
    self.cmb_slots.setDisabled(True)

    self.btn_read = QPushButton(self)
    self.btn_read.setIcon(QIcon('img/flaticon/open135.png'))
    self.btn_read.setToolTip('Read item slot value from memory')
    self.btn_read.setStyleSheet('background-color: white')
    self.btn_read.clicked.connect(self.onReadSlot)

    self.txt_raw = QLineEdit(self)
    self.txt_raw.setPlaceholderText('Raw hex data')
    self.txt_raw.setMaxLength(8 * 6 + 5)
    self.txt_raw.editingFinished.connect(self.onChangeRaw)

    self.btn_poke = QPushButton(self)
    self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png'))
    self.btn_poke.setToolTip('Poke new value for item slot')
    self.btn_poke.setStyleSheet('background-color: white')
    self.btn_poke.clicked.connect(self.onPokeSlot)

    self.cmb_skills_a = QComboBox(self)
    self.cmb_skills_a.setEditable(True)
    self.cmb_skills_a.addItems(self.skill_names)
    self.cmb_skills_a.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA)

    self.cmb_skills_b = QComboBox(self)
    self.cmb_skills_b.setEditable(True)
    self.cmb_skills_b.addItems(self.skill_names)
    self.cmb_skills_b.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB)

    self.cmb_skills_c = QComboBox(self)
    self.cmb_skills_c.setEditable(True)
    self.cmb_skills_c.addItems(self.skill_names)
    self.cmb_skills_c.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC)

    incr_labels = []
    for incr in xrange(16):
      incr_labels.append('+%d' % incr)

    self.cmb_incr_a = QComboBox(self)
    self.cmb_incr_a.addItems(incr_labels)
    self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA)

    self.cmb_incr_b = QComboBox(self)
    self.cmb_incr_b.addItems(incr_labels)
    self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB)

    self.cmb_incr_c = QComboBox(self)
    self.cmb_incr_c.addItems(incr_labels)
    self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC)

    slot_labels = []
    for incr in xrange(4):
      slot_labels.append('%d Augment Slots' % incr)

    self.cmb_augments = QComboBox(self)
    self.cmb_augments.addItems(slot_labels)
    self.cmb_augments.currentIndexChanged[int].connect(self.onChangeAugments)

    self.layout = QGridLayout(self)
    self.layout.addWidget(self.lbl_label, 0, 0)
    self.layout.addWidget(self.btn_read_slots, 0, 1)
    self.layout.addWidget(self.cmb_slots, 0, 2)
    self.layout.addWidget(self.btn_read, 0, 3)
    self.layout.addWidget(self.txt_raw, 1, 0, 1, 3)
    self.layout.addWidget(self.btn_poke, 1, 3)
    self.layout.addWidget(self.cmb_skills_a, 2, 0)
    self.layout.addWidget(self.cmb_incr_a, 2, 1)
    self.layout.addWidget(self.cmb_skills_b, 3, 0)
    self.layout.addWidget(self.cmb_incr_b, 3, 1)
    self.layout.addWidget(self.cmb_skills_c, 4, 0)
    self.layout.addWidget(self.cmb_incr_c, 4, 1)
    self.layout.addWidget(self.cmb_augments, 2, 2)

    self.layout.setColumnStretch(0, 7)
    self.layout.setColumnStretch(1, 3)
    self.layout.setColumnStretch(2, 3)
    self.layout.setColumnStretch(3, 1)
    self.layout.setContentsMargins(0, 2, 0, 2)

    icon_height = self.lbl_label.height() * 8 / 15
    icon_size = QSize(icon_height, icon_height)
    self.btn_read_slots.setIconSize(icon_size)
    self.btn_read.setIconSize(icon_size)
    self.btn_poke.setIconSize(icon_size)
    btn_size = QSize(icon_height * 1.5, icon_height * 1.5)
    self.btn_read.setFixedSize(btn_size)
    self.btn_poke.setFixedSize(btn_size)

    self.updateUI()

  def updateUI(self):
    # Disable editing if cache missing
    if not (0 <= self.cur_slot_idx < len(self.slots_cache)) or self.cur_slot_bytes is None:
      self.cur_slot_idx = -1
      self.cur_slot_bytes = None
      self.cmb_slots.setDisabled(True)
      self.cmb_skills_a.setDisabled(True)
      self.cmb_skills_b.setDisabled(True)
      self.cmb_skills_c.setDisabled(True)
      self.cmb_incr_a.setDisabled(True)
      self.cmb_incr_b.setDisabled(True)
      self.cmb_incr_c.setDisabled(True)
      self.cmb_augments.setDisabled(True)
      self.txt_raw.setDisabled(True)
      return
    else:
      self.cmb_slots.setDisabled(False)
      self.cmb_skills_a.setDisabled(False)
      self.cmb_skills_b.setDisabled(False)
      self.cmb_skills_c.setDisabled(False)
      self.cmb_incr_a.setDisabled(False)
      self.cmb_incr_b.setDisabled(False)
      self.cmb_incr_c.setDisabled(False)
      self.cmb_augments.setDisabled(False)
      self.txt_raw.setDisabled(False)

    # Validate current slot's raw bytes
    try:
      (gear_id_bytes, index, post_index, skill_a_id, skill_a_incr, skill_b_id, skill_b_incr,
       skill_c_id, skill_c_incr, augment_a_id, augment_b_id, augment_c_id) = parse_gear_bytes(self.cur_slot_bytes)
      cur_slot_words = struct.unpack('>IIIIII', self.cur_slot_bytes)
      num_augments = (augment_a_id != 0xFFFF) + (augment_b_id != 0xFFFF) + (augment_c_id != 0xFFFF)
    except ValueError, e:
      self.log.emit('Gear parsing failed: %s' % e.what(), 'red')
      return

    # Update UI
    self.txt_raw.setDisabled(False)
    self.txt_raw.editingFinished.disconnect()
    self.txt_raw.setText('%08X %08X %08X %08X %08X %08X' % cur_slot_words)
    self.txt_raw.editingFinished.connect(self.onChangeRaw)

    self.cmb_skills_a.setDisabled(False)
    self.cmb_skills_a.currentIndexChanged[str].disconnect()
    try:
      skill_name = self.id2skill[skill_a_id]
      skill_idx = self.skill_names.index(skill_name)
      self.cmb_skills_a.setCurrentIndex(skill_idx)
    except (KeyError, ValueError):
      self.cmb_skills_a.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA)

    self.cmb_skills_b.setDisabled(False)
    self.cmb_skills_b.currentIndexChanged[str].disconnect()
    try:
      skill_name = self.id2skill[skill_b_id]
      skill_idx = self.skill_names.index(skill_name)
      self.cmb_skills_b.setCurrentIndex(skill_idx)
    except (KeyError, ValueError):
      self.cmb_skills_b.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB)

    self.cmb_skills_c.setDisabled(False)
    self.cmb_skills_c.currentIndexChanged[str].disconnect()
    try:
      skill_name = self.id2skill[skill_c_id]
      skill_idx = self.skill_names.index(skill_name)
      self.cmb_skills_c.setCurrentIndex(skill_idx)
    except (KeyError, ValueError):
      self.cmb_skills_c.lineEdit().setText(GearEntriesFrame.MISSING_SKILL_NAME)
    self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC)

    self.cmb_incr_a.setDisabled(False)
    self.cmb_incr_a.currentIndexChanged[int].disconnect()
    self.cmb_incr_a.setCurrentIndex(skill_a_incr)
    self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA)

    self.cmb_incr_b.setDisabled(False)
    self.cmb_incr_b.currentIndexChanged[int].disconnect()
    self.cmb_incr_b.setCurrentIndex(skill_b_incr)
    self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB)

    self.cmb_incr_c.setDisabled(False)
    self.cmb_incr_c.currentIndexChanged[int].disconnect()
    self.cmb_incr_c.setCurrentIndex(skill_c_incr)
    self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC)

    self.cmb_augments.setDisabled(False)
    self.cmb_augments.currentIndexChanged[int].disconnect()
    self.cmb_augments.setCurrentIndex(num_augments)
    self.cmb_augments.currentIndexChanged[int].connect(self.onChangeAugments)
Exemple #3
0
class DiffGUI(object):
    ' diff gui class '
    def __init__(self):
        ' make a diff method with GUI '
        self.dialog = QDialog()
        self.diff_path = None

        # directory auto completer
        self.completer = QCompleter(self.dialog)
        self.dirs = QDirModel(self.dialog)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group1 = QGroupBox()
        self.group1.setTitle('Diff')
        self.frmt = QComboBox(self.group1)
        self.frmt.addItems(['Unified', 'Normal', 'Context'])
        self.file1 = QLineEdit()
        self.file1.setPlaceholderText('/full/path/to/one_file.py')
        self.file1.setCompleter(self.completer)
        self.file2 = QLineEdit()
        self.file2.setPlaceholderText('/full/path/to/another_file.py')
        self.file2.setCompleter(self.completer)
        self.fout = QLineEdit()
        self.fout.setText(''.join((path.join(gettempdir(),
                     datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff')))))
        self.fout.setPlaceholderText('/full/path/to/output_file.diff')
        self.fout.setCompleter(self.completer)
        self.regex = QLineEdit()
        self.regex.setPlaceholderText('DONT use unless you know what are doing')
        self.regex.setToolTip('Do NOT use unless you know what you are doing !')
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.borig.clicked.connect(lambda: self.file1.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))

        self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bmodi.clicked.connect(lambda: self.file2.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))
        self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bout.clicked.connect(lambda: self.fout.setText(str(
            QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file',
                                        path.expanduser("~"), ';;(*.diff)'))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('Original file full path'),
                            self.file1, self.borig,
                            QLabel('Modified file full path'),
                            self.file2, self.bmodi,
                            QLabel('Output file full Path'),
                            self.fout, self.bout,
                            QLabel('Diff Output Format'), self.frmt,
                            QLabel('Diff REGEX to Ignore (ADVANCED)'),
                            self.regex):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle('Options')
        self.nwfl = QCheckBox('Treat new files as Empty')
        self.smll = QCheckBox('Look for smaller changes')
        self.lrgf = QCheckBox('Optimize for large files')
        self.case = QCheckBox('Ignore case changes on content')
        self.cnvt = QCheckBox('Convert Tabs to Spaces')
        self.blnk = QCheckBox('Ignore added or removed Blank lines')
        self.spac = QCheckBox('Ignore changes in amount of Spaces')
        self.whit = QCheckBox('Ignore ALL white Spaces')
        self.tabz = QCheckBox('Ignore changes by Tab expansions')
        self.sprs = QCheckBox('Remove Space or Tab before empty lines')
        self.filn = QCheckBox('Ignore case when comparing file names')
        self.tbs = QComboBox(self.group2)
        self.tbs.addItems(['4', '6', '8', '10', '2'])
        self.nice = QComboBox(self.group2)
        self.nice.addItems(['20', '15', '10', '5', '0'])
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.nwfl, self.smll, self.lrgf, self.case,
                            self.cnvt, self.blnk, self.spac, self.whit,
                            self.tabz, self.sprs, self.filn,
                            QLabel('Diff Tabs-to-Spaces Size'), self.tbs,
                            QLabel('Diff Backend CPU Priority'), self.nice):
            vboxg2.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        group3 = QGroupBox()
        group3.setTitle('Even More Options')
        self.plai = QCheckBox('Force treat all files as plain text')
        self.nocr = QCheckBox('Force strip trailing carriage return')
        self.ridt = QCheckBox('Report when two files are identical')
        self.nocm = QCheckBox('Do not output common lines')
        self.rdif = QCheckBox('Report only when files differ')
        self.clip = QCheckBox('Copy Diff to Clipboard when done')
        self.noti = QCheckBox('Use system Notification when done')
        self.pret = QCheckBox('Align all Tabs by prepending a Tab')
        self.lolz = QCheckBox('Output Diff in two equal columns')
        self.odif = QCheckBox('Open Diff with Ninja-IDE when done')
        self.plac = QCheckBox('Make an Awesome Diff view when done')
        self.wdth = QComboBox(group3)
        self.wdth.addItems(['80', '100', '120', '130', '250', '500', '9999999'])
        self.bcknd = QComboBox(group3)
        self.bcknd.addItems(['diff', 'diff.py'])
        self.bcknd.setDisabled(True)  # TODO this feature needs work
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (self.plai, self.nocr, self.ridt, self.nocm,
                            self.rdif, self.pret, self.clip, self.noti,
                            self.lolz, self.odif, self.plac,
                            QLabel('Diff Maximum Total Width'), self.wdth,
                            QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd):
            vboxg3.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf,
                                   self.clip, self.cnvt, self.plai, self.noti):
            widget_should_be_checked.setChecked(True)

        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)

        buttons = QDialogButtonBox()
        buttons.resize(self.dialog.size().width(), buttons.size().height() * 2)
        buttons.setOrientation(Qt.Horizontal)
        buttons.setStandardButtons(
            QDialogButtonBox.Ok |
            QDialogButtonBox.Cancel |
            QDialogButtonBox.Close |
            QDialogButtonBox.Help)
        buttons.setCenterButtons(False)
        buttons.helpRequested.connect(lambda: QMessageBox.about(
            self.dialog, __doc__,
            ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep,
            'version ', __version__, ', (', __license__, '), by ', linesep,
            __author__, ', ( ', __email__, ' ).', linesep))))
        buttons.rejected.connect(self.dialog.close)
        buttons.accepted.connect(self.make_diff)

        info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>',
                      getoutput('diff --version').split(linesep)[0])))

        vbox = QVBoxLayout(self.dialog)
        for each_widget in (
                QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'),
                container, info, buttons):
            vbox.addWidget(each_widget)

        self.dialog.resize(1024, self.dialog.size().height())
        self.dialog.exec_()

    def make_diff(self):
        ' make the diff '
        diff_command = ''.join((
        'nice --adjustment=', str(self.nice.currentText()).strip(), ' ',
        str(self.bcknd.currentText()).strip(), ' --',
        str(self.frmt.currentText()).strip().lower(),

        ' --new-file ' if self.nwfl.isChecked() is True else '',
        ' --minimal ' if self.smll.isChecked() is True else '',
        ' --speed-large-files ' if self.lrgf.isChecked() is True else '',
        ' --ignore-self.case ' if self.case.isChecked() is True else '',
        ' --expand-tabs ' if self.cnvt.isChecked() is True else '',
        ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '',
        ' --ignore-space-change ' if self.spac.isChecked() is True else '',
        ' --ignore-all-space ' if self.whit.isChecked() is True else '',
        ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '',
        ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '',
        ' --ignore-file-name-case ' if self.filn.isChecked() is True else '',
        ' --text ' if self.plai.isChecked() is True else '',
        ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '',
        ' --suppress-common-lines ' if self.nocm.isChecked() is True else '',
        ' --initial-tab ' if self.pret.isChecked() is True else '',
        ' --side-by-side ' if self.lolz.isChecked() is True else '',

        ' --tabsize=', str(self.tbs.currentText()).strip(),
        ' --width=', str(self.wdth.currentText()).strip(),

        str(' --ignore-matching-lines=' + str(self.regex.text()).strip())
                           if str(self.regex.text()).strip() is not '' else '',
        ' ',
        path.abspath(str(self.file1.text()))
                    if str(self.file1.text()).strip() is not '' else __file__,
        ' ',
        path.abspath(str(self.file2.text()))
                    if str(self.file2.text()).strip() is not '' else __file__
        ))

        print(diff_command)
        diff_output = getoutput(diff_command)
        try:
            print(' INFO: OK, Saving new Diff to disk...')
            output_file = file(path.abspath(str(self.fout.text())), 'w')
            output_file.write(diff_output)
            output_file.close()
        except:
            print(' ERROR: FAIL, Can not save Diff to disk!')
        if self.clip.isChecked() is True:
            print(' INFO: OK, Diff Copied to Clipboard...')
            QApplication.clipboard().setText(diff_output)
        if self.noti.isChecked() is True:
            call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True)
        if self.odif.isChecked() is True:
            print(' INFO: OK, Opening Diff with Ninja-IDE')
            call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True)

        self.diff_path = path.abspath(str(self.fout.text()))
        return self.diff_path
class Sidebar(QWidget):
    """
    +----------------------+
    |        Results       |
    +======================+
    |                      |
    |  Name = Main         |
    |                      |
    |  +----------------+  |
    |  | ResultsWindow  |  |
    |  +----------------+  |
    |  |                |  |
    |  |  +----------+  |  |
    |  |  | - a      |  |  |
    |  |  |  - b1    |  |  |
    |  |  |  - b2    |  |  |
    |  |  |  - b3    |  |  |
    |  |  +----------+  |  |
    |  |                |  |
    |  +----------------+  |
    |                      |
    |                      |
    |         Apply        |
    +----------------------+

    For Nastran:
      - a: Subcase 1
       - b1. Displacement
       - b2. Stress
       - b3. Strain

    For Cart3d:
      - a1. Geometry
       - b1. ElementID
       - b2. Region
      - a2. Results Case 1
       - b1. U
       - b2. V
       - b3. W

    +--------------+
    |  Sub-Result  | (pulldown)
    +==============+
    | - a1         |
    | - a2         |
    | - a3         |
    | - a4         |
    +--------------+

    For Nastran:
      - a1: Displacement X
      - a2. Displacement Y
      - a3. Displacmenet Z
      - a4. Displacmenet Mag

    For Cart3d:
      - NA (Greyed Out)

    +----------------+
    |     Plot       | (pulldown)
    +================+
    | - Fringe       |
    | - Marker       |
    | - Displacement |
    +----------------+
    - Cart3d -> Fringe (disabled)


    +---------------+
    | Scale Display | (text box)
    +===============+
    | 0 < x < 1000  | (not for fringe)
    +---------------+

    +--------------+
    |   Location   | (pulldown)
    +==============+
    | - nodal      |
    | - centroidal |
    +--------------+
    (disabled)

    +------------------+
    |  Complex Method  | (pulldown)
    +==================+
    | - real           | (usually set to real and disabled)
    | - imag           |
    | - mag            |
    | - phase          |
    | - max over phase |
    +------------------+

    +--------------+
    |    Derive    | (pulldown; only for nodal results)
    +==============+
    | - derive/avg |  (default?)
    | - avg/derive |
    +--------------+
    """
    def __init__(self, parent, debug=False):
        """creates the buttons in the Sidebar, not the actual layout"""
        QWidget.__init__(self)
        self.parent = parent
        self.debug = debug

        name = 'main'
        data = []
        data = [
            ("Alice", None, [
                ("Keys", 1, []),
                ("Purse", 2, [
                    ("Cellphone", 3, [])
                    ])
                ]),
            ("Bob", None, [
                ("Wallet", None, [
                    ("Credit card", 4, []),
                    ("Money", 5, [])
                    ])
                ]),
            ]

        choices = ['keys2', 'purse2', 'cellphone2', 'credit_card2', 'money2']
        self.result_case_window = ResultsWindow('Case/Results', data, choices)

        data = [
            ('A', 1, []),
            #('B', 2, []),
            #('C', 3, []),
        ]
        self.result_data_window = ResultsWindow('Method', data, choices)
        self.result_data_window.setVisible(False)

        self.show_pulldown = False
        if self.show_pulldown:
            combo_options = ['a1', 'a2', 'a3']
            self.pulldown = QComboBox()
            self.pulldown.addItems(choices)
            self.pulldown.activated[str].connect(self.on_pulldown)

        self.apply_button = QPushButton('Apply', self)
        self.apply_button.clicked.connect(self.on_apply)

        self.name = str(name)
        self.names = [name]
        self.name_label = QLabel("Name:")
        self.name_pulldown = QComboBox()
        self.name_pulldown.addItem(name)
        self.name_pulldown.setDisabled(True)
        self.name_pulldown.currentIndexChanged.connect(self.on_update_name)

        self.setup_layout()

    def setup_layout(self):
        """creates the sidebar visual layout"""
        vbox = QVBoxLayout()
        hbox = QHBoxLayout()

        hbox.addWidget(self.name_label)
        hbox.addWidget(self.name_pulldown)
        vbox.addLayout(hbox)
        vbox.addWidget(self.result_case_window)
        vbox.addWidget(self.result_data_window)
        if self.show_pulldown:
            vbox.addWidget(self.pulldown)
        vbox.addWidget(self.apply_button)
        self.setLayout(vbox)

        self.clear_data()

    def update_method(self, method):
        if isinstance(method, string_types):
            datai = self.result_data_window.data[0]
            self.result_data_window.data[0] = (method, datai[1], datai[2])
            print('method=%s datai=%s' % (method, datai))
            self.result_data_window.update_data(self.result_data_window.data)
        else:
            return
             # pragma: no cover
            datai = self.result_data_window.data[0]

    def get_form(self):
        return self.result_case_window.data

    def update_results(self, data, name):
        """
        Updates the sidebar

        Parameters
        ----------
        data : List[tuple]
            the form data
        name : str
            the name that goes at the side
        """
        name = str(name)
        if name in self.names:
            i = self.names.index(name)
            self.name_pulldown.setCurrentIndex(i)
        else:
            self.name_pulldown.addItem(name)
            self.names.append(name)
        if len(self.names) >= 2:
            self.name_pulldown.setEnabled(True)
        self.name = name

        self.result_case_window.update_data(data)
        self.apply_button.setEnabled(True)

    def update_methods(self, data):
        """the methods is a hidden box"""
        self.result_data_window.update_data(data)
        self.apply_button.setEnabled(True)

    def clear_data(self):
        self.result_case_window.clear_data()
        self.result_data_window.clear_data()
        self.apply_button.setEnabled(False)

    def on_pulldown(self, event):
        print('pulldown...')

    def on_update_name(self, event):
        """user clicked the pulldown"""
        name = str(self.name_pulldown.currentText())
        data = self.parent._get_sidebar_data(name)
        #self.result_case_window.update_data(data)

    def on_apply(self, event):
        data = self.result_case_window.data
        valid_a, keys_a = self.result_case_window.treeView.get_row()

        data = self.result_data_window.data
        valid_b, keys_b = self.result_data_window.treeView.get_row()
        if valid_a and valid_b:
            if self.debug:  # pragma: no cover
                print('  rows1 = %s' % self.result_case_window.treeView.old_rows)
                print('        = %s' % str(keys_a))
                print('  rows2 = %s' % self.result_data_window.treeView.old_rows)
                print('        = %s' % str(keys_b))
            else:
                self.update_vtk_window(keys_a, keys_b)

    def update_vtk_window(self, keys_a, keys_b):
        if 0:  # pragma: no cover
            print('keys_a = %s' % str(keys_a))
            for i, key in enumerate(self.parent.case_keys):
                if key[1] == keys_a[0]:
                    break
            print('*i=%s key=%s' % (i, str(key)))
            #self.parent.update_vtk_window_by_key(i)
            result_name = key[1]
            #self.parent.cycle_results_explicit(result_name=result_name, explicit=True)
            #j = self.parent._get_icase(result_name)
            #j = i
        i = keys_a
        result_name = None
        self.parent._set_case(result_name, i, explicit=True)
Exemple #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()
Exemple #6
0
class reglageExpert(QWidget) :
	"""Class pour créer les widgets spécifiques pour les réglages plus fin sur la qualité d'encodage, sur le débit binaire des fichiers, ... """
	def __init__(self, listeFormat, comboFormat, parent=None) :
		super(reglageExpert, self).__init__(parent)
		self.listeFormat = listeFormat
		self.comboFormat = comboFormat
		self.format = self.comboFormat.currentIndex()
		self.parent = parent
		layout = QHBoxLayout(self)
		self.textLabel = QLabel(self)
		self.textLabel.hide()
		self.expert = QCheckBox(_(u"Réglage expert : "), self)
		self.qualite = QComboBox(self)
		layout.addWidget(self.expert)
		layout.addWidget(self.textLabel)
		layout.addWidget(self.qualite)
		layout.addStretch()
		i=1
		while i<9 :
			self.qualite.addItem(str(i))
			i	+=	1
		self.qualite.hide()
		self.changeFormat(self.comboFormat.currentIndex())
		self.connect(self.expert, SIGNAL("stateChanged(int)"), self.setExpert)
		self.connect(self.comboFormat, SIGNAL("currentIndexChanged(int)"), self.changeFormat)
		self.connect(self.qualite, SIGNAL("currentIndexChanged(int)"), self.changeQualite)

	def setExpert(self, state) :
		if state :
			self.qualite.show()
			self.textLabel.show()
		else :
			self.qualite.hide()
			self.textLabel.hide()

	def changeQualite(self,qualite) :
		self.changeFormat(self.comboFormat.currentIndex())

	def changeFormat(self, format) :
		if len(self.listeFormat) == 0 :
			return
		else :
			if self.listeFormat[format] == "mp3" or self.listeFormat[format] == "mp2" or self.listeFormat[format] == "ogg" :
				self.textLabel.setText(_(u"Qualité d'encodage"))
				self.qualite.setEnabled(True)
				self.C = u" -C %f " % (10.0*float(self.qualite.currentIndex()+1)/8.0)
			elif self.listeFormat[format] == "flac" :
				self.textLabel.setText(_(u"Taux de compression"))
				self.qualite.setEnabled(True)
				self.C = u" -C %d " % (self.qualite.currentIndex()+1)
			else :
				self.textLabel.setText(_(u"Non applicable, format non compressé"))
				self.qualite.setDisabled(True)
				self.C = u""

	def getExpertState(self) :
		return self.expert.isChecked()

	def getC(self) :
		return self.C

	def saveConfig(self, idsection="") :
		if idsection == "" :
			return 
		EkdConfig.set(idsection, u'format', unicode(self.comboFormat.currentIndex()))
		EkdConfig.set(idsection, u'expert', unicode(int(self.getExpertState())))
		EkdConfig.set(idsection, u'qualite', unicode(self.qualite.currentIndex()))


	def loadConfig(self, idsection="") :
		if idsection == "" :
			return 
		self.comboFormat.setCurrentIndex(int(EkdConfig.get(idsection, 'format')))
		self.expert.setChecked(int(EkdConfig.get(idsection, 'expert')))
		self.qualite.setCurrentIndex(int(EkdConfig.get(idsection, 'qualite')))
class GearEntriesFrame(QFrame):
    read_block = pyqtSignal(int, int)  # start_addr, num_bytes
    poke_block = pyqtSignal(int, QByteArray,
                            bool)  # start_addr, raw_bytes, is_ascii
    log = pyqtSignal(str, str)  # msg, color

    MISSING_SKILL_NAME = '[NOT IN DB]'

    def __init__(self,
                 addr_start,
                 addr_end,
                 class_label,
                 skill2id,
                 id2skill,
                 parent=None):
        super(GearEntriesFrame, self).__init__(parent)
        self.code_offset = 0
        self.addr_start = addr_start
        self.addr_end = addr_end
        self.max_num_slots = (addr_end - addr_start) / 6 / 4 + 1
        self.class_label = class_label
        self.skill2id = skill2id
        self.id2skill = id2skill

        self.skill_names = self.skill2id.keys()
        self.skill_names.sort()

        self.slots_cache = []  # list of raw 6*4 bytes
        self.slots_txt = None
        self.cur_slot_idx = -1
        self.cur_slot_bytes = None

        self.lbl_label = QLabel(self.class_label, self)

        self.btn_read_slots = QPushButton(' Cache Slots', self)
        self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png'))
        self.btn_read_slots.setStyleSheet('background-color: white')
        self.btn_read_slots.clicked.connect(self.onReadSlots)

        self.cmb_slots = QComboBox(self)
        self.cmb_slots.setStyleSheet('background-color: white')
        self.cmb_slots.currentIndexChanged[str].connect(self.onChangeSlot)
        self.cmb_slots.setDisabled(True)

        self.btn_read = QPushButton(self)
        self.btn_read.setIcon(QIcon('img/flaticon/open135.png'))
        self.btn_read.setToolTip('Read item slot value from memory')
        self.btn_read.setStyleSheet('background-color: white')
        self.btn_read.clicked.connect(self.onReadSlot)

        self.txt_raw = QLineEdit(self)
        self.txt_raw.setPlaceholderText('Raw hex data')
        self.txt_raw.setMaxLength(8 * 6 + 5)
        self.txt_raw.editingFinished.connect(self.onChangeRaw)

        self.btn_poke = QPushButton(self)
        self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png'))
        self.btn_poke.setToolTip('Poke new value for item slot')
        self.btn_poke.setStyleSheet('background-color: white')
        self.btn_poke.clicked.connect(self.onPokeSlot)

        self.cmb_skills_a = QComboBox(self)
        self.cmb_skills_a.setEditable(True)
        self.cmb_skills_a.addItems(self.skill_names)
        self.cmb_skills_a.lineEdit().setText(
            GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA)

        self.cmb_skills_b = QComboBox(self)
        self.cmb_skills_b.setEditable(True)
        self.cmb_skills_b.addItems(self.skill_names)
        self.cmb_skills_b.lineEdit().setText(
            GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB)

        self.cmb_skills_c = QComboBox(self)
        self.cmb_skills_c.setEditable(True)
        self.cmb_skills_c.addItems(self.skill_names)
        self.cmb_skills_c.lineEdit().setText(
            GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC)

        incr_labels = []
        for incr in xrange(16):
            incr_labels.append('+%d' % incr)

        self.cmb_incr_a = QComboBox(self)
        self.cmb_incr_a.addItems(incr_labels)
        self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA)

        self.cmb_incr_b = QComboBox(self)
        self.cmb_incr_b.addItems(incr_labels)
        self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB)

        self.cmb_incr_c = QComboBox(self)
        self.cmb_incr_c.addItems(incr_labels)
        self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC)

        slot_labels = []
        for incr in xrange(4):
            slot_labels.append('%d Augment Slots' % incr)

        self.cmb_augments = QComboBox(self)
        self.cmb_augments.addItems(slot_labels)
        self.cmb_augments.currentIndexChanged[int].connect(
            self.onChangeAugments)

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.lbl_label, 0, 0)
        self.layout.addWidget(self.btn_read_slots, 0, 1)
        self.layout.addWidget(self.cmb_slots, 0, 2)
        self.layout.addWidget(self.btn_read, 0, 3)
        self.layout.addWidget(self.txt_raw, 1, 0, 1, 3)
        self.layout.addWidget(self.btn_poke, 1, 3)
        self.layout.addWidget(self.cmb_skills_a, 2, 0)
        self.layout.addWidget(self.cmb_incr_a, 2, 1)
        self.layout.addWidget(self.cmb_skills_b, 3, 0)
        self.layout.addWidget(self.cmb_incr_b, 3, 1)
        self.layout.addWidget(self.cmb_skills_c, 4, 0)
        self.layout.addWidget(self.cmb_incr_c, 4, 1)
        self.layout.addWidget(self.cmb_augments, 2, 2)

        self.layout.setColumnStretch(0, 7)
        self.layout.setColumnStretch(1, 3)
        self.layout.setColumnStretch(2, 3)
        self.layout.setColumnStretch(3, 1)
        self.layout.setContentsMargins(0, 2, 0, 2)

        icon_height = self.lbl_label.height() * 8 / 15
        icon_size = QSize(icon_height, icon_height)
        self.btn_read_slots.setIconSize(icon_size)
        self.btn_read.setIconSize(icon_size)
        self.btn_poke.setIconSize(icon_size)
        btn_size = QSize(icon_height * 1.5, icon_height * 1.5)
        self.btn_read.setFixedSize(btn_size)
        self.btn_poke.setFixedSize(btn_size)

        self.updateUI()

    def updateUI(self):
        # Disable editing if cache missing
        if not (0 <= self.cur_slot_idx < len(
                self.slots_cache)) or self.cur_slot_bytes is None:
            self.cur_slot_idx = -1
            self.cur_slot_bytes = None
            self.cmb_slots.setDisabled(True)
            self.cmb_skills_a.setDisabled(True)
            self.cmb_skills_b.setDisabled(True)
            self.cmb_skills_c.setDisabled(True)
            self.cmb_incr_a.setDisabled(True)
            self.cmb_incr_b.setDisabled(True)
            self.cmb_incr_c.setDisabled(True)
            self.cmb_augments.setDisabled(True)
            self.txt_raw.setDisabled(True)
            return
        else:
            self.cmb_slots.setDisabled(False)
            self.cmb_skills_a.setDisabled(False)
            self.cmb_skills_b.setDisabled(False)
            self.cmb_skills_c.setDisabled(False)
            self.cmb_incr_a.setDisabled(False)
            self.cmb_incr_b.setDisabled(False)
            self.cmb_incr_c.setDisabled(False)
            self.cmb_augments.setDisabled(False)
            self.txt_raw.setDisabled(False)

        # Validate current slot's raw bytes
        try:
            (gear_id_bytes, index, post_index, skill_a_id, skill_a_incr,
             skill_b_id, skill_b_incr, skill_c_id, skill_c_incr, augment_a_id,
             augment_b_id,
             augment_c_id) = parse_gear_bytes(self.cur_slot_bytes)
            cur_slot_words = struct.unpack('>IIIIII', self.cur_slot_bytes)
            num_augments = (augment_a_id != 0xFFFF) + (
                augment_b_id != 0xFFFF) + (augment_c_id != 0xFFFF)
        except ValueError, e:
            self.log.emit('Gear parsing failed: %s' % e.what(), 'red')
            return

        # Update UI
        self.txt_raw.setDisabled(False)
        self.txt_raw.editingFinished.disconnect()
        self.txt_raw.setText('%08X %08X %08X %08X %08X %08X' % cur_slot_words)
        self.txt_raw.editingFinished.connect(self.onChangeRaw)

        self.cmb_skills_a.setDisabled(False)
        self.cmb_skills_a.currentIndexChanged[str].disconnect()
        try:
            skill_name = self.id2skill[skill_a_id]
            skill_idx = self.skill_names.index(skill_name)
            self.cmb_skills_a.setCurrentIndex(skill_idx)
        except (KeyError, ValueError):
            self.cmb_skills_a.lineEdit().setText(
                GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_a.currentIndexChanged[str].connect(self.onChangeSkillA)

        self.cmb_skills_b.setDisabled(False)
        self.cmb_skills_b.currentIndexChanged[str].disconnect()
        try:
            skill_name = self.id2skill[skill_b_id]
            skill_idx = self.skill_names.index(skill_name)
            self.cmb_skills_b.setCurrentIndex(skill_idx)
        except (KeyError, ValueError):
            self.cmb_skills_b.lineEdit().setText(
                GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_b.currentIndexChanged[str].connect(self.onChangeSkillB)

        self.cmb_skills_c.setDisabled(False)
        self.cmb_skills_c.currentIndexChanged[str].disconnect()
        try:
            skill_name = self.id2skill[skill_c_id]
            skill_idx = self.skill_names.index(skill_name)
            self.cmb_skills_c.setCurrentIndex(skill_idx)
        except (KeyError, ValueError):
            self.cmb_skills_c.lineEdit().setText(
                GearEntriesFrame.MISSING_SKILL_NAME)
        self.cmb_skills_c.currentIndexChanged[str].connect(self.onChangeSkillC)

        self.cmb_incr_a.setDisabled(False)
        self.cmb_incr_a.currentIndexChanged[int].disconnect()
        self.cmb_incr_a.setCurrentIndex(skill_a_incr)
        self.cmb_incr_a.currentIndexChanged[int].connect(self.onChangeIncrA)

        self.cmb_incr_b.setDisabled(False)
        self.cmb_incr_b.currentIndexChanged[int].disconnect()
        self.cmb_incr_b.setCurrentIndex(skill_b_incr)
        self.cmb_incr_b.currentIndexChanged[int].connect(self.onChangeIncrB)

        self.cmb_incr_c.setDisabled(False)
        self.cmb_incr_c.currentIndexChanged[int].disconnect()
        self.cmb_incr_c.setCurrentIndex(skill_c_incr)
        self.cmb_incr_c.currentIndexChanged[int].connect(self.onChangeIncrC)

        self.cmb_augments.setDisabled(False)
        self.cmb_augments.currentIndexChanged[int].disconnect()
        self.cmb_augments.setCurrentIndex(num_augments)
        self.cmb_augments.currentIndexChanged[int].connect(
            self.onChangeAugments)
class NetWidget(QWidget):
       
    def __init__(self,parent = None):
        super(NetWidget,self).__init__(parent)
        self.setStyleSheet("font-size : 16px")#设置整体的字体大小
        
        
        self.auto = False
        self.pro = QProcess(self)
#         self.tipDlg = TipDialog()
#         self.tipDlg.setModal(True)#引入tipdlg,并且将这个窗口设置为最前端窗口,且后面窗口无法操作
        
            #初始化comBox控件,并且为其添加选项
        self.comBox = QComboBox()
        self.comBox.setFixedWidth(120)
        self.comBox.insertItem(0, self.tr("ping"))
        self.comBox.insertItem(1, self.tr("ifconfig"))
        self.comBox.insertItem(2, self.tr("display"))
        #self.comBox.insertItem(3, self.tr("traceroute"))
        self.comBox.insertItem(4, self.tr("top"))
        self.connect(self.comBox, SIGNAL('activated(QString)'),self.onActivated)#设置combBox为活动的,与函数关联
        """
        #初始话控件设置
        #lineEdit,固定长度
        #runButton,显示字符串,信号量
        #pingLabel,当前显示字符
        #textBrower
          """ 
        self.lineEdit = QLineEdit()
        self.lineEdit.setContextMenuPolicy(Qt.NoContextMenu)
        self.lineEdit.setFixedWidth(250)
        self.runButton = QPushButton(self.tr("Run"))
        self.runButton.setStyleSheet("background: rgb(7,87,198); color: white; width: 70px; height: 20px;font-size : 16px;")
        self.connect(self.runButton, SIGNAL("clicked()"),self.runButton_clicked)
        self.pingLabel = QLabel()#初始话,之后在函数操作中会改变
        self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button"))
        self.textBrowser = QTextBrowser()
        """
            #布局一上,横向布局
            #将comBox,lineEdit,runButton添加到布局中
            #设置前面空为20和后面空为280
            """
        hLayout1 = QHBoxLayout()
        hLayout1.addSpacing(20)
        hLayout1.addWidget(self.comBox)
        hLayout1.addWidget(self.lineEdit)
        hLayout1.addWidget(self.runButton)
        #hLayout1.addStretch()
        hLayout1.addSpacing(280)
        
            #布局二中,横向布局
            #将pingLabel添加到布局中,并且诶设置前面的空白为20
        hLayout2 = QHBoxLayout()
        hLayout2.addSpacing(20)
        hLayout2.addWidget(self.pingLabel)
        
            #布局三下
            #将textBrower添加爱到布局中,并且设置前面空白为20,后面空白为60,控件的大小自适应
        hLayout3 = QHBoxLayout()
        hLayout3.addSpacing(20)
        hLayout3.addWidget(self.textBrowser)
        hLayout3.addSpacing(60)
        
            #主题布局总,纵向布局
            #将之上的三个布局添加到总布局中,并且设置布局间空间为20,最下面的空白为40
        mainLayout = QVBoxLayout()
        mainLayout.addSpacing(20)
        mainLayout.addLayout(hLayout1)
        mainLayout.addSpacing(20)
        mainLayout.addLayout(hLayout2)
        mainLayout.addSpacing(20)
        mainLayout.addLayout(hLayout3)
        mainLayout.addSpacing(40)
        self.setLayout(mainLayout)
        
        
        self.thread = MyThread()
        self.connect(self.thread,SIGNAL("getoutput"),self.append)
        
        
    def append(self,actionType):
        self.textBrowser.clear()
        self.textBrowser.append(actionType)
        #cursor = QTextCursor()
        #self.runButton.setText(self.tr("Stop"))
        
        cursor = self.textBrowser.textCursor()
        cursor.movePosition(QTextCursor.Start)
        self.textBrowser.setTextCursor(cursor)
        #changeLabel = QLabel()
    
    def onActivated(self):
        language = StoreInfoParser.instance().getLanguage()
        m_pTranslator = QTranslator()
        exePath = "./"
        if language == "chinese":
            QmName = "zh_CN.qm"
        else:
            QmName = "en_US.qm"
        if(m_pTranslator.load(QmName, exePath)):
            QCoreApplication.instance().installTranslator(m_pTranslator)
            
        """#comBox的相应函数,随着comBox中字符串的改变,分别控制pingLabel的显示,以及lineEdit和textBrower的显示清除和可用状态
            #如果comBox当前的字符串文字为ping
            #pingLabel的文字设置为"提示:请在文本框中输入要ping的目标地址,然后点击执行获取结果",保持当前大小
            #lineEdit中内容清除,设置为不可用
            #textBrower清空"""
        if(self.comBox.currentText() == "Ping" or self.comBox.currentText() == "ping"):
            self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button"))
            self.pingLabel.adjustSize()
            self.lineEdit.clear()
            self.lineEdit.setDisabled(False)
            self.textBrowser.clear()
            #如果comBox当前的字符串文字为ifconfig
            #类上所说
        elif(self.comBox.currentText() == "ifconfig"):
            self.pingLabel.setText(self.tr("Tip:get the net information"))
            self.pingLabel.adjustSize()
            self.lineEdit.clear()
            self.lineEdit.setEnabled(False)
            self.textBrowser.clear()
            #如果comBox当前的字符串文字为display
        elif(self.comBox.currentText() == "display"):
            self.pingLabel.setText(self.tr("Tip:get the resolution information"))
            self.pingLabel.adjustSize()
            self.lineEdit.clear()
            self.lineEdit.setEnabled(False)
            self.textBrowser.clear()
        
        elif(self.comBox.currentText() == "top"):
    
            self.pingLabel.setText(self.tr("Tip:run tom command"))
            self.pingLabel.adjustSize()
            self.lineEdit.setEnabled(False)
            self.lineEdit.clear()
            self.textBrowser.clear()
            #按钮的响应函数
    def runButton_clicked(self):
        language = StoreInfoParser.instance().getLanguage()
        m_pTranslator = QTranslator()
        exePath = "./"
        if language == "chinese":
            QmName = "zh_CN.qm"
        else:
            QmName = "en_US.qm"
        if(m_pTranslator.load(QmName, exePath)):
            QCoreApplication.instance().installTranslator(m_pTranslator)
            
        #self.pro = QProcess(self)#外部程序使用声明
        desktop = QApplication.desktop()#获得桌面
        self.textBrowser.clear()#清除
        cmdstr = QString()
        center = QString()
        goal = QString()
        #comBox当前text为ping
        if (self.comBox.currentText() == "Ping" or self.comBox.currentText() == "ping"):
            if (self.runButton.text() == self.tr("Run")) :
                center = self.lineEdit.text().trimmed()
                if not center:
                    InfoHintDialog(self.tr("please input the IP address")).exec_()
#                     self.tipDlg.setTip(self.tr("请输入ping地址!!!"))
#                     self.tipDlg.show()
#                     self.tipDlg.move((desktop.width()-self.tipDlg.width())/2,(desktop.height()-self.tipDlg.height())/2)
                    self.runButton.setText(self.tr("Run"))
                else:
                    self.comBox.setDisabled(True)
                    self.pro = QProcess(self)
                    self.runButton.setText(self.tr("stop ping"))
                    cmdstr = "ping " +center
                    self.textBrowser.clear()
                    self.textBrowser.append(self.tr(" ping ")+center+self.tr(" result:"))
            else:
                self.comBox.setDisabled(False)
                self.runButton.setText(self.tr("Run"))
                self.pro.close()
        elif(self.comBox.currentText() == "ifconfig"):
            self.pro = QProcess(self)
            self.lineEdit.clear()
            self.lineEdit.setEnabled(False)
            self.textBrowser.clear()
            cmdstr = "ifconfig"
#             #如果comBox当前为traceroute
#         elif(self.comBox.currentText() == "traceroute"):
#                 goal = self.lineEdit.text()
#                 if (self.runButton.text() == u"执行"):
#                     if( goal.isEmpty() or goal.isNull() ):
#                         InfoHintDialog(u'请输入tracer地址:').exec_()
# #                         self.tipDlg.setTip(self.tr("请输入tracer地址:"))
# #                         self.tipDlg.show()
# #                         self.tipDlg.move((desktop.width()-self.tipDlg.width())/2,(desktop.height()-self.tipDlg.height())/2)
# #                         
#                         #QMessageBox.information(self,self.tr("错误"),self.tr("请输入traceroute的目标地址"))
#                         #return
#                     else:
#                         self.proc = QProcess(self)
#                         #self.textBrowser.clear()
#                         cmdstrc = "traceroute -n "+ goal
#                         self.proc.start(cmdstrc)
#                         self.connect(self.proc, SIGNAL("readyReadStandardOutput()"),self.readR)
#                         self.connect(self.proc, SIGNAL("readyReadStandardError()"),self.readErrorR)
#                         if self.proc.waitForStarted(10) == True:
#                             self.comBox.setDisabled(True)
#                             self.runButton.setText(self.tr("停止执行"))
#                 else:
#                     self.runButton.setText(self.tr("执行"))
#                     self.comBox.setDisabled(False)
#                     self.proc.close()
#             #如果comBox当前为display
        elif (self.comBox.currentText() == "display"):
            self.pro = QProcess(self)
            cmdstr = "../lib/ccr_jytcapi display"
            self.textBrowser.clear()
            #如果当前命令cmdstr不为空,则
        elif (self.comBox.currentText() == "top"):
            if self.runButton.text() == self.tr("Run") :
                self.thread.start()
                self.comBox.setDisabled(True)
                self.runButton.setText(self.tr("stop top"))
            else:
                self.textBrowser.clear()
                self.thread.auto = False
                #self.thread.destroyed()
                self.comBox.setDisabled(False)
                self.runButton.setText(self.tr("Run"))
        if (cmdstr != ""):
                self.pro.start(cmdstr)#开启执行命令
                self.connect(self.pro, SIGNAL("readyReadStandardOutput()"),self.read)#读取执行正常输出槽函数
                self.connect(self.pro, SIGNAL("readyReadStandardError()"),self.readError)#执行异常槽函数
            
            #读取控制台输出
    def read(self):
        res = QString.fromLocal8Bit(self.pro.readAllStandardOutput())
        self.textBrowser.append(res)#添加到text框
        #读取错误
    def readError(self):
        res = QString.fromLocal8Bit(self.pro.readAllStandardError())
        self.textBrowser.append(res)
    def readR(self):
        
        res = QString.fromLocal8Bit(self.proc.readAllStandardOutput())
        #self.textBrowser.clear()
        self.textBrowser.append(res)
        


    def readErrorR(self):

        res = QString.fromLocal8Bit(self.proc.readAllStandardError())
        self.textBrowser.append(res)
        
    def updateWindow(self):
        if self.pro.isOpen():
            self.pro.close()
            
        self.thread.auto = False
        self.comBox.setDisabled(False)
        self.comBox.setCurrentIndex(0)
        self.runButton.setText((self.tr("Run")))
        self.pingLabel.setText(self.tr("Tip:please input the IP address of pinging,then get the result with clicking the button"))
        self.textBrowser.clear()
class ItemEntriesFrame(QFrame):
  read_block = pyqtSignal(int, int) # start_addr, num_bytes
  poke_block = pyqtSignal(int, QByteArray, bool) # start_addr, raw_bytes, is_ascii
  log = pyqtSignal(str, str) # msg, color

  MISSING_ITEM_NAME = '[NOT IN DB]'

  def __init__(self, type_val, addr_start, addr_end, label, id2name, idx2id, names, parent=None):
    super(ItemEntriesFrame, self).__init__(parent)
    self.type_val = type_val
    self.addr_start = addr_start
    self.addr_end = addr_end
    self.max_num_slots = (addr_end - addr_start)/3/4 + 1
    self.label = label
    self.id2name = id2name
    self.idx2id = idx2id
    self.names = names

    self.slots_cache = [] # tuple: (addr_hex, addr_val, slot_number, cur_val)
    self.cur_slot_idx = -1

    self.lbl_label = QLabel(self.label, self)

    self.btn_read_slots = QPushButton(' Cache Slots', self)
    self.btn_read_slots.setIcon(QIcon('img/flaticon/data110.png'))
    self.btn_read_slots.setStyleSheet('background-color: white')
    self.btn_read_slots.clicked.connect(self.onReadSlots)

    self.btn_search_cache = QPushButton(' Search ID', self)
    self.btn_search_cache.setIcon(QIcon('img/flaticon/magnifier13.png'))
    self.btn_search_cache.setToolTip('Find slot in cache with specified item ID')
    self.btn_search_cache.setStyleSheet('background-color: white')
    self.btn_search_cache.clicked.connect(self.onSearchCacheForID)

    self.btn_read = QPushButton(self)
    self.btn_read.setIcon(QIcon('img/flaticon/open135.png'))
    self.btn_read.setToolTip('Read item slot value from memory')
    self.btn_read.setStyleSheet('background-color: white')
    self.btn_read.clicked.connect(self.onReadSlot)

    self.cmb_slots = QComboBox(self)
    self.cmb_slots.setToolTip('')
    self.cmb_slots.setStyleSheet('background-color: white')
    self.cmb_slots.currentIndexChanged[int].connect(self.onChangeSlot)
    self.cmb_slots.setDisabled(True)

    self.cmb_names = QComboBox(self)
    self.cmb_names.setEditable(True)
    self.cmb_names.addItems(self.names)
    self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME)
    self.cmb_names.currentIndexChanged[int].connect(self.fetchID)

    self.txt_id = QLineEdit(self)
    self.txt_id.setPlaceholderText('ID (hex)')
    self.txt_id.setMaxLength(3)
    self.txt_id.textChanged.connect(self.fetchName)

    self.btn_rename = QPushButton(' Fix Name', self)
    self.btn_rename.setIcon(QIcon('img/flaticon/cloud-storage3.png'))
    self.btn_rename.setToolTip('Add/Correct Item Name for %s (type: %02X)' % (self.label, type_val))
    self.btn_rename.setStyleSheet('background-color: white')
    self.btn_rename.clicked.connect(self.onRename)

    self.txt_amount = QLineEdit(self)
    self.txt_amount.setPlaceholderText('Amount')
    self.txt_amount.setMaxLength(3)

    self.btn_poke = QPushButton(self)
    self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png'))
    self.btn_poke.setToolTip('Poke new value for item slot')
    self.btn_poke.setStyleSheet('background-color: white')
    self.btn_poke.clicked.connect(self.onPokeSlot)

    self.layout = QGridLayout(self)
    self.layout.addWidget(self.lbl_label, 0, 0)
    self.layout.addWidget(self.btn_read_slots, 0, 1)
    self.layout.addWidget(self.btn_search_cache, 0, 2)
    self.layout.addWidget(self.cmb_slots, 0, 3)
    self.layout.addWidget(self.btn_read, 0, 4)
    self.layout.addWidget(self.cmb_names, 1, 0)
    self.layout.addWidget(self.txt_id, 1, 1)
    self.layout.addWidget(self.btn_rename, 1, 2)
    self.layout.addWidget(self.txt_amount, 1, 3)
    self.layout.addWidget(self.btn_poke, 1, 4)

    self.layout.setColumnStretch(0, 7)
    self.layout.setColumnStretch(1, 3)
    self.layout.setColumnStretch(2, 3)
    self.layout.setColumnStretch(3, 3)
    self.layout.setColumnStretch(4, 1)
    self.layout.setContentsMargins(0, 2, 0, 2)

    icon_height = self.lbl_label.height()*8/15
    icon_size = QSize(icon_height, icon_height)
    self.btn_read_slots.setIconSize(icon_size)
    self.btn_search_cache.setIconSize(icon_size)
    self.btn_rename.setIconSize(icon_size)
    self.btn_read.setIconSize(icon_size)
    self.btn_poke.setIconSize(icon_size)
    btn_size = QSize(icon_height*1.5, icon_height*1.5)
    self.btn_read.setFixedSize(btn_size)
    self.btn_poke.setFixedSize(btn_size)

    self.updateUI()

  def updateUI(self):
    # Disable editing if cache missing
    if not (0 <= self.cur_slot_idx < len(self.slots_cache)):
      self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME)
      self.cmb_names.setDisabled(True)
      self.txt_id.setText('')
      self.txt_id.setDisabled(True)
      return

    # Validate current value
    cur_val = self.slots_cache[self.cur_slot_idx][3]
    (type_val, id_val, amount) = parse_item_word(cur_val)
    if type_val != self.type_val and type_val != 0:
      self.log.emit('Coding error: val(%s)=%08X, type (%02X) != expected (%02X)' %
                    (self.cur_addr_str, cur_val, type_val, self.type_val), 'red')
      return

    # Update UI
    self.txt_id.setDisabled(False)
    self.txt_id.setText('%03X' % id_val)
    self.cmb_names.setDisabled(False)
    self.fetchName()
    self.txt_amount.setText(str(amount))

  def setAlternateBGColor(self):
    self.setStyleSheet('ItemEntriesFrame { background-color:rgb(248,248,248) }')

  @pyqtSlot()
  def onRename(self):
    id_txt = str(self.txt_id.text())
    if len(id_txt) != 3:
      return
    dialog = FixItemNameDialog('%02X' % self.type_val, id_txt, self)
    dialog.log.connect(self.log)
    dialog.exec_()

  @pyqtSlot()
  def onReadSlots(self):
    self.read_block.emit(self.addr_start, self.max_num_slots*4*3)

  @pyqtSlot(int, int, QByteArray)
  def onBlockRead(self, addr_start, num_bytes, raw_bytes):
    # Determine whether block has cache or single slot
    if addr_start == self.addr_start and num_bytes == self.max_num_slots*4*3:
      self.onCacheRead(addr_start, raw_bytes)
    elif num_bytes == 4: # Assume read slot
      # Ignore if no cache
      if not (0 <= self.cur_slot_idx < len(self.slots_cache)):
        return
      self.onSlotRead(addr_start, raw_bytes)

  def onCacheRead(self, addr_start, raw_bytes):
    slot_bytes = str(raw_bytes)
    self.slots_cache = []
    slots_txt = []
    for slot_i in xrange(self.max_num_slots):
      byte_offset = slot_i*3*4
      cur_slot_bytes = slot_bytes[byte_offset:(byte_offset+4)]
      if len(cur_slot_bytes) != 4:
        continue
      cur_slot_val = struct.unpack('>I', cur_slot_bytes)[0]
      (type_val, id_val, amount) = parse_item_word(cur_slot_val)
      if type_val == 0 or amount == 0:
        continue
      elif type_val != self.type_val:
        self.log.emit('val(%08X)=%08X, type_val(%02X) unexpected(%02X)' %
                      (addr_start+byte_offset, cur_slot_val, type_val, self.type_val),
                      'red')
        continue
      else:
        addr_val = addr_start + byte_offset
        addr_hex = '%08X' % addr_val
        slot_number = slot_i+1
        self.slots_cache.append((addr_hex, addr_val, slot_number, cur_slot_val))
        slots_txt.append('Slot %03d' % slot_number)

    # Update UI
    self.log.emit('Found %d %s slots in memory' % (len(self.slots_cache), self.label), 'black')
    self.cmb_slots.clear()
    if len(self.slots_cache) <= 0:
      self.cmb_slots.setDisabled(True)
      self.cur_slot_idx = -1
    else:
      self.cmb_slots.setDisabled(False)
      self.cmb_slots.addItems(slots_txt)
      self.cur_slot_idx = 0
    self.updateUI()

  def onSlotRead(self, addr_word, raw_bytes):
    addr_cur_slot = self.slots_cache[self.cur_slot_idx][1]
    if addr_word == addr_cur_slot:
      cur_cache = self.slots_cache[self.cur_slot_idx]
      new_val = struct.unpack('>I', str(raw_bytes))[0]
      new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val)
      self.slots_cache[self.cur_slot_idx] = new_cache
      self.updateUI()
    else: # Update cached value of other slots
      addr_first_slot = self.slots_cache[0][1]
      addr_last_slot = self.slots_cache[-1][1]
      if (addr_first_slot <= addr_word <= addr_last_slot) and \
         ((addr_word - addr_first_slot) % 12 == 0):
        for slot_i in xrange(len(self.slots_cache)):
          addr_cur_slot = self.slots_cache[slot_i][1]
          if addr_word == addr_cur_slot:
            cur_cache = self.slots_cache[slot_i]
            new_val = struct.unpack('>I', str(raw_bytes))[0]
            new_cache = (cur_cache[0], cur_cache[1], cur_cache[2], new_val)
            self.slots_cache[slot_i] = new_cache
            return

  @pyqtSlot()
  def onSearchCacheForID(self):
    # Stop if no cache
    if not (0 <= self.cur_slot_idx < len(self.slots_cache)):
      self.log.emit('Must cache slots before searching', 'red')
      return

    # Fetch and validate target ID
    try:
      target_id_val = int(str(self.txt_id.text()), 16)
      if target_id_val < 0 or target_id_val > Item.MAX_ID_VAL:
        self.log.emit('Item ID out of [0, 0x%03X] range' % Item.MAX_ID_VAL)
        return
    except ValueError:
      self.log.emit('Failed to parse item ID, expecting XXX', 'red')
      return

    # Search ID in cache
    for cand_slot_idx in xrange(len(self.slots_cache)):
      (type_val, id_val, amount) = parse_item_word(self.slots_cache[cand_slot_idx][3])
      if id_val == target_id_val and type_val == self.type_val:
        self.cur_slot_idx = cand_slot_idx
        self.cmb_slots.setCurrentIndex(self.cur_slot_idx)
        self.updateUI()
        return
    self.log.emit('Did not find ID=%03X in %d cached %s slots' %
                  (target_id_val, len(self.slots_cache), self.label), 'red')

  @pyqtSlot(int)
  def onChangeSlot(self, new_slot_idx):
    # Validate new_slot_idx
    if not (0 <= new_slot_idx < len(self.slots_cache)):
      return

    # Update slot idx and read value from memory
    self.cur_slot_idx = new_slot_idx
    cur_addr_hex = self.slots_cache[self.cur_slot_idx][0]
    self.cmb_slots.setToolTip(cur_addr_hex)
    self.cmb_names.lineEdit().setText(ItemEntriesFrame.MISSING_ITEM_NAME)
    self.cmb_names.setDisabled(True)
    self.txt_id.setText('')
    self.txt_id.setDisabled(True)
    self.onReadSlot()

  @pyqtSlot()
  def fetchName(self):
    try:
      id_val = int(str(self.txt_id.text()), 16)
    except ValueError:
      return
    name = self.MISSING_ITEM_NAME
    if id_val in self.id2name:
      name = self.id2name[id_val]
    self.cmb_names.lineEdit().setText(name)

  @pyqtSlot(int)
  def fetchID(self, cmb_idx):
    if cmb_idx < 0 or cmb_idx >= len(self.idx2id):
      self.txt_id.setText('')
    else:
      self.txt_id.setText(self.idx2id[cmb_idx])

  @pyqtSlot()
  def onReadSlot(self):
    try:
      if not (0 <= self.cur_slot_idx < len(self.slots_cache)):
        raise ValueError('must cache slots before reading')
      addr_cur_slot = self.slots_cache[self.cur_slot_idx][1]
      self.read_block.emit(addr_cur_slot, 4)
    except ValueError, e:
      cur_slot_num = self.slots_cache[self.cur_slot_idx][2]
      self.log.emit('READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red')
    except BaseException, e:
      cur_slot_num = self.slots_cache[self.cur_slot_idx][2]
      self.log.emit('READ %s Slot %03d failed: %s' % (self.label, cur_slot_num, str(e)), 'red')
      traceback.print_exc()
Exemple #10
0
class PlotExportSettingsWidget(QWidget):
    def __init__(self, parent, slice_view_widget, context):
        super(PlotExportSettingsWidget, self).__init__(parent)

        self._slice_view_widget = slice_view_widget
        self._context = context

        self._dpi_units = ["in", "cm", "px"]

        if parent is None:
            w, h, dpi = 11.7, 8.3, 100
        else:
            fig = self._slice_view_widget.layout_figure()
            w, h = fig.get_size_inches()
            dpi = fig.dpi

        self._label = QLabel()
        self._label.setDisabled(True)
        self._set_label_txt(w, h, self._dpi_units[0])

        self._fix_size = QCheckBox()
        self._fix_width = QDoubleSpinBox()
        self._fix_width.setDisabled(True)

        self._fix_height = QDoubleSpinBox()
        self._fix_height.setDisabled(True)

        self._fix_dpi_units = QComboBox()
        self._fix_dpi_units.setDisabled(True)

        self._fix_width.setMinimum(1)
        self._fix_width.setMaximum(32000)
        self._fix_width.setValue(w)

        self._fix_height.setMinimum(1)
        self._fix_height.setMaximum(32000)
        self._fix_height.setValue(h)

        self._fix_width.valueChanged.connect(self._fixed_image)
        self._fix_height.valueChanged.connect(self._fixed_image)

        self._fix_dpi_units.addItems(self._dpi_units)
        self._fix_dpi_units.activated.connect(self._fixed_image)
        self._fix_size.toggled.connect(self._fixed_image)

        self._label_widget = self._label
        self._enable_widget = self._fix_size
        self._dpi_widget = self._fix_dpi_units
        self._height_widget = self._fix_height
        self._width_widget = self._fix_width

    @property
    def label(self):
        return self._label_widget

    @property
    def checkbox(self):
        return self._enable_widget

    @property
    def width_spinbox(self):
        return self._width_widget

    @property
    def height_spinbox(self):
        return self._height_widget

    @property
    def units_combobox(self):
        return self._dpi_widget

    @staticmethod
    def to_inches(width, height, dpi, scale):
        if scale == "in":
            return (width, height, dpi)
        elif scale == "cm":
            return (width / 2.54, height / 2.54, dpi)
        elif scale == "px":
            return (width / dpi, height / dpi, dpi)
        else:
            raise NotImplementedError

    def _set_label_txt(self, w, h, scale):
        self._label.setText("{0} x {1} {2}".format(w, h, scale))

    def _fixed_image(self):
        ctx = self._context

        # toggle disabled
        self._fix_height.setDisabled(not self._fix_size.isChecked())
        self._fix_width.setDisabled(not self._fix_size.isChecked())
        self._fix_dpi_units.setDisabled(not self._fix_size.isChecked())
        self._label.setDisabled(not self._fix_size.isChecked())

        if not self._fix_size.isChecked():
            ctx.set_image_size(None)
            return

        w = self._fix_width.value()
        h = self._fix_height.value()
        dpi = 100
        scale = self._fix_dpi_units.currentText()

        self._set_label_txt(w, h, scale)
        ctx.set_image_size(*self.to_inches(w, h, dpi, scale))