# --------------------------- # Treeにitemに子itemを追加する # --------------------------- import sys from PySide2.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem app = QApplication(sys.argv) qw_tree = QTreeWidget() qw_tree.setHeaderLabels(["name", "tel", "mail"]) qw_tree_parent_item = QTreeWidgetItem(['family']) qw_tree_parent_item.addChild( QTreeWidgetItem(['A', '111-111-111', '*****@*****.**'])) # Itemに子Itemを追加 qw_tree.addTopLevelItem(qw_tree_parent_item) qw_tree.expandAll() # TreeのItemを全て開く qw_tree.show() sys.exit(app.exec_())
class QDecompilationOptions(QWidget): def __init__(self, code_view, instance, options=None, passes=None, peephole_opts=None): super().__init__() self._code_view = code_view self._instance = instance self._options = options self._opti_passes = passes self._peephole_opts = peephole_opts # widgets self._search_box = None # type:QLineEdit self._treewidget = None # type:QTreeWidget self._apply_btn = None # type:QPushButton self._qoptions = [ ] self._qoptipasses = [ ] self._qpeephole_opts = [ ] self._init_widgets() self.reload() def reload(self, force=False): if force or self._options is None: self._options = self.get_default_options() if force or self._opti_passes is None: if not self._instance.project.am_none: self._opti_passes = self.get_all_passes() else: self._opti_passes = [] if force or self._peephole_opts is None: self._peephole_opts = self.get_all_peephole_opts() self._reload_options() @property def selected_passes(self): selected = [ ] for item in self._qoptipasses: if item.checkState(0): selected.append(item.option) return selected @property def selected_peephole_opts(self): selected = [] for item in self._qpeephole_opts: if item.checkState(0): selected.append(item.option) return selected @property def option_and_values(self): ov = [ ] for item in self._qoptions: if item.checkState(0): ov.append((item.option, True)) else: ov.append((item.option, False)) return ov @property def options(self): return self._options @options.setter def options(self, v): self._options = v self._reload_options() def get_default_options(self): return dec_options def get_default_passes(self): if self._instance is None or self._instance.project.am_none: return set() return get_default_optimization_passes(self._instance.project.arch, self._instance.project.simos.name) def get_all_passes(self): return get_optimization_passes(self._instance.project.arch, self._instance.project.simos.name) def get_default_peephole_opts(self): return STMT_OPTS + EXPR_OPTS def get_all_peephole_opts(self): return STMT_OPTS + EXPR_OPTS def _init_widgets(self): # search box self._search_box = QLineEdit() # tree view self._treewidget = QTreeWidget() self._treewidget.setHeaderHidden(True) # refresh button self._apply_btn = QPushButton("Apply") self._apply_btn.clicked.connect(self._code_view.decompile) layout = QVBoxLayout() layout.addWidget(self._search_box) layout.addWidget(self._treewidget) layout.addWidget(self._apply_btn) self.setLayout(layout) def _reload_options(self): self._treewidget.clear() self._qoptions.clear() self._qoptipasses.clear() self._qpeephole_opts.clear() categories = { } # populate the tree widget with new options for option in sorted(self._options, key=lambda x: x.name): if option.category in categories: category = categories[option.category] else: category = QTreeWidgetItem(self._treewidget, [option.category]) w = QDecompilationOption(category, option, OptionType.OPTION, enabled=option.default_value==True) self._qoptions.append(w) passes_category = QTreeWidgetItem(self._treewidget, ["Optimization Passes"]) categories['passes'] = passes_category default_passes = set(self.get_default_passes()) for pass_ in self._opti_passes: w = QDecompilationOption(passes_category, pass_, OptionType.OPTIMIZATION_PASS, enabled=pass_ in default_passes) self._qoptipasses.append(w) po_category = QTreeWidgetItem(self._treewidget, ["Peephole Optimizations"]) categories['peephole_opts'] = po_category default_peephole_opts = self.get_default_peephole_opts() for opt_ in self._peephole_opts: w = QDecompilationOption(po_category, opt_, OptionType.PEEPHOLE_OPTIMIZATION, enabled=opt_ in default_peephole_opts) self._qpeephole_opts.append(w) # expand all self._treewidget.expandAll()
import sys from PySide2.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem app = QApplication(sys.argv) qw_tree = QTreeWidget() qw_tree.setHeaderLabels(["name", "tel", "mail"]) qw_tree_parent_item_1 = QTreeWidgetItem(['family']) qw_tree_parent_item_1.addChild(QTreeWidgetItem(['A', '111-111-111', '*****@*****.**'])) qw_tree_parent_item_1.addChild(QTreeWidgetItem(['B', '222-222-222', '*****@*****.**'])) qw_tree_parent_item_2 = QTreeWidgetItem(['school']) qw_tree_parent_item_2.addChild(QTreeWidgetItem(['C', '333-333-333', '*****@*****.**'])) qw_tree_parent_item_2.addChild(QTreeWidgetItem(['D', '444-444-444', '*****@*****.**'])) qw_tree.addTopLevelItem(qw_tree_parent_item_1) qw_tree.addTopLevelItem(qw_tree_parent_item_2) qw_tree.expandAll() qw_tree.show() sys.exit(app.exec_())
class TraceWindow(QMainWindow): def __init__(self, qmp): QMainWindow.__init__(self) self.qmp = qmp os.system('rm /tmp/errors.log 2>/dev/null') self.trace_events = self.qmp.hmp_command('info trace-events') self.qmp.hmp_command('logfile /tmp/errors.log') self.trace_events = sorted( self.trace_events['return'].split('\r\n'))[1:] self.activated = [] self.length = 100 self.timer = QTimer(self) self.timer.timeout.connect(self.disp_output) self.timer.start(100) self.init_ui() def init_ui(self): self.setWindowTitle('Trace Event Window') self.setGeometry(100, 100, 800, 600) bar = self.menuBar() file_ = bar.addMenu('File') export_log = QAction('Save to File', self, triggered=lambda: self.save_log()) options = bar.addMenu('Options') auto_refresh = QAction( 'Auto Refresh', self, checkable=True, triggered=lambda: self.timer.start(100) if auto_refresh.isChecked() else self.timer.stop()) auto_refresh.setChecked(True) options.addAction(auto_refresh) file_.addAction(export_log) vgrid = QVBoxLayout() grid = QHBoxLayout() self.tree = QTreeWidget() self.tree.setHeaderLabels(['Name']) self.top = [] self.lst = [] for n, event in enumerate(self.trace_events): word = event.split('_')[0] if word not in self.top: self.top.append(word) item = QTreeWidgetItem(self.tree) self.lst.append(item) item.setText(0, word) subitem = QTreeWidgetItem(item) subitem.setText(0, ' ' + event.split(' : ')[0]) # subitem.setCheckState(0, Qt.Unchecked) cbox = QCheckBox() cbox.stateChanged.connect(lambda state, text=subitem.text(0): self. handle_checked(state, text)) self.tree.setItemWidget(subitem, 0, cbox) # self.tree.setColumnWidth(0, 25) self.tracelist = QLabel() self.disp_output() self.traceview = QScrollArea() self.traceview.setWidget(self.tracelist) self.traceview.setWidgetResizable(True) search = QHBoxLayout() self.search_bar = QLineEdit(self) self.completer = QCompleter(self.top, self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.search_bar.setCompleter(self.completer) search_button = QPushButton('Search') search_button.clicked.connect(lambda: self.tree.setCurrentItem( self.lst[self.top.index(self.search_bar.text())])) expand = QPushButton('▼') expand.setFixedSize(QSize(25, 25)) expand.clicked.connect(lambda: self.tree.expandAll()) collapse = QPushButton('▲') collapse.setFixedSize(QSize(25, 25)) collapse.clicked.connect(lambda: self.tree.collapseAll()) self.search_bar.returnPressed.connect(lambda: search_button.click()) search.addWidget(self.search_bar) search.addWidget(search_button) search.addWidget(expand) search.addWidget(collapse) self.digest = QLabel() vgrid.addLayout(search) vgrid.addWidget(self.tree) vgridwid = QWidget() vgridwid.setLayout(vgrid) split = QSplitter(Qt.Horizontal) split.addWidget(vgridwid) split.addWidget(self.traceview) split.setStretchFactor(1, 1) # grid.addLayout(vgrid) grid.addWidget(split) # grid.addWidget(self.tracelist) self.disp_output() center = QWidget() center.setLayout(grid) self.setCentralWidget(center) self.show() def disp_output(self): self.shorten_file() with open('/tmp/errors.log', 'r') as errors: self.digest = [] lines = 0 for line in errors: if re.match(r"\d+@\d+\.\d+:.*", line): self.digest.append(line) lines += 1 if not self.digest: self.digest = ['<font color="grey">Empty...</font>'] self.digest = ''.join(self.digest[-self.length:]) self.tracelist.setText(self.digest) self.tracelist.setFont(QFont('Monospace', 10)) self.tracelist.setTextInteractionFlags(Qt.TextSelectableByMouse) def shorten_file(self): with open('/tmp/errors.log', 'r+') as tracefile: content = ''.join(tracefile.readlines()[-(self.length * 3):]) tracefile.seek(0) tracefile.truncate() tracefile.write(content) def save_log(self): name = QFileDialog.getSaveFileName(self, 'Save File', '', 'Text files (*.txt)') log_file = open(name[0], 'w') log_file.write(self.digest) log_file.close() def handle_checked(self, state, text): if state: self.qmp.hmp_command('trace-event %s on' % text.strip()) self.activated.append(text) else: self.qmp.hmp_command('trace-event %s off' % text.strip()) self.activated.remove(text) def closeEvent(self, event): self.timer.stop() for e in self.activated: self.qmp.hmp_command('trace-event %s off' % e.strip()) os.system('rm /tmp/errors.log') event.accept()
class QDecompilationOptions(QWidget): def __init__(self, code_view, instance, options=None, passes=None, peephole_opts=None): super().__init__() self.dirty = True self._code_view = code_view self._instance = instance self._options = options self._opti_passes = passes self._peephole_opts = peephole_opts # widgets self._search_box = None # type:QLineEdit self._treewidget = None # type:QTreeWidget self._apply_btn = None # type:QPushButton self._qoptions = [ ] self._qoptipasses = [ ] self._qpeephole_opts = [ ] self._init_widgets() self.reload() def reload(self, force=False): if force or self._options is None: self._options = self.get_default_options() if force or self._opti_passes is None: if not self._instance.project.am_none: self._opti_passes = self.get_all_passes() else: self._opti_passes = [] if force or self._peephole_opts is None: self._peephole_opts = self.get_all_peephole_opts() self._reload_options() def _on_item_changed(self, item, _column): if getattr(item.option, 'clears_cache', True): self.dirty = True def _on_apply_pressed(self): if self.dirty: self.dirty = False # clear the cached version self._code_view.decompile(reset_cache=True) else: self._code_view.codegen.reapply_options(self.option_and_values) self._code_view.codegen.am_event() @property def selected_passes(self): selected = [ ] for item in self._qoptipasses: if item.checkState(0): selected.append(item.option) return selected @property def selected_peephole_opts(self): selected = [] for item in self._qpeephole_opts: if item.checkState(0): selected.append(item.option) return selected @property def option_and_values(self): ov = [ ] for item in self._qoptions: if item.checkState(0): ov.append((item.option, True)) else: ov.append((item.option, False)) return ov @property def options(self): return self._options @options.setter def options(self, v): self._options = v self._reload_options() def get_default_options(self): # pylint: disable=no-self-use return dec_options def get_default_passes(self): if self._instance is None or self._instance.project.am_none: return set() return get_default_optimization_passes(self._instance.project.arch, self._instance.project.simos.name) def get_all_passes(self): return get_optimization_passes(self._instance.project.arch, self._instance.project.simos.name) def get_default_peephole_opts(self): # pylint: disable=no-self-use return STMT_OPTS + EXPR_OPTS def get_all_peephole_opts(self): # pylint: disable=no-self-use return STMT_OPTS + EXPR_OPTS def _init_widgets(self): # search box self._search_box = QLineEdit() self._search_box.textChanged.connect(self._on_search_box_text_changed) # tree view self._treewidget = QTreeWidget() self._treewidget.setHeaderHidden(True) self._treewidget.itemChanged.connect(self._on_item_changed) # refresh button self._apply_btn = QPushButton("Apply") self._apply_btn.clicked.connect(self._on_apply_pressed) layout = QVBoxLayout() layout.addWidget(self._search_box) layout.addWidget(self._treewidget) layout.addWidget(self._apply_btn) self.setLayout(layout) def _reload_options(self, filter_by: Optional[str]=None): self._treewidget.clear() self._qoptions.clear() self._qoptipasses.clear() self._qpeephole_opts.clear() categories = { } if filter_by: filter_by = filter_by.lower() # populate the tree widget with new options for option in sorted(self._options, key=lambda x: x.NAME): if filter_by and not (filter_by in option.NAME.lower() or filter_by in option.category.lower()): continue if option.category in categories: category = categories[option.category] else: category = QTreeWidgetItem(self._treewidget, [option.category]) categories[option.category] = category w = QDecompilationOption(category, option, OptionType.OPTION, enabled=option.default_value) self._qoptions.append(w) passes_category = QTreeWidgetItem(self._treewidget, ["Optimization Passes"]) categories['passes'] = passes_category default_passes = set(self.get_default_passes()) for pass_ in self._opti_passes: if filter_by and not (filter_by in pass_.__name__.lower() or filter_by in pass_.NAME.lower()): continue w = QDecompilationOption(passes_category, pass_, OptionType.OPTIMIZATION_PASS, enabled=pass_ in default_passes) self._qoptipasses.append(w) po_category = QTreeWidgetItem(self._treewidget, ["Peephole Optimizations"]) categories['peephole_opts'] = po_category default_peephole_opts = self.get_default_peephole_opts() for opt_ in self._peephole_opts: if filter_by and not (filter_by in opt_.NAME.lower() or filter_by in opt_.DESCRIPTION.lower()): continue w = QDecompilationOption(po_category, opt_, OptionType.PEEPHOLE_OPTIMIZATION, enabled=opt_ in default_peephole_opts) self._qpeephole_opts.append(w) # expand all self._treewidget.expandAll() def _on_search_box_text_changed(self, text: str): self._reload_options(filter_by=text)