def UpdateFileList(self, baseFolder: Path, fileList: QtWidgets.QTreeWidget): assert (fileList) assert (baseFolder) asset_path = baseFolder / re_project._RE_DCC_APP fileList.clear() for pattern in self.sceneDCCExtensions: filelist_gen = asset_path.glob(pattern) file_list = list(filelist_gen) for file_path in file_list: rel_path: Path = file_path.relative_to(asset_path) #print(rel_path.as_posix()) file_stats: os.stat_result = file_path.stat() mtime = file_stats.st_mtime timestamp_str = datetime.datetime.fromtimestamp( mtime).strftime('%Y-%m-%d-%H:%M') fileList.addTopLevelItem( QtWidgets.QTreeWidgetItem([ rel_path.as_posix(), timestamp_str, ProjectManagerUI.convert_file_size(file_stats.st_size) ])) fileList.resizeColumnToContents(0) fileList.resizeColumnToContents(2)
def update_hint_locations(game: RandovaniaGame, hint_tree_widget: QtWidgets.QTreeWidget): game_description = default_database.game_description_for(game) number_for_hint_type = { hint_type: i + 1 for i, hint_type in enumerate(LoreType) } used_hint_types = set() hint_tree_widget.clear() hint_tree_widget.setSortingEnabled(False) # TODO: This ignores the Dark World names. But there's currently no logbook nodes in Dark World. for world in game_description.world_list.worlds: world_item = QtWidgets.QTreeWidgetItem(hint_tree_widget) world_item.setText(0, world.name) world_item.setExpanded(True) for area in world.areas: hint_types = {} for node in area.nodes: if isinstance(node, LogbookNode): if node.required_translator is not None: hint_types[ node. lore_type] = node.required_translator.short_name else: hint_types[node.lore_type] = "✓" if hint_types: area_item = QtWidgets.QTreeWidgetItem(world_item) area_item.setText(0, area.name) for hint_type, text in hint_types.items(): area_item.setText(number_for_hint_type[hint_type], text) used_hint_types.add(hint_type) hint_tree_widget.resizeColumnToContents(0) hint_tree_widget.setSortingEnabled(True) hint_tree_widget.sortByColumn(0, QtCore.Qt.AscendingOrder) for hint_type in used_hint_types: hint_tree_widget.headerItem().setText(number_for_hint_type[hint_type], hint_type.long_name)
class ComponentsView(BaseView): def __init__(self, workspace, default_docking_position, *args, **kwargs): super().__init__('components', workspace, default_docking_position, *args, **kwargs) self.caption = "Components" self.width_hint = 100 self.height_hint = 100 self._tree: QTreeWidget = None self._init_widgets() def _init_widgets(self): self._tree = QTreeWidget() self._tree.setHeaderHidden(True) self._tree.itemDoubleClicked.connect(self.on_item_doubleclicked) layout = QVBoxLayout() layout.addWidget(self._tree) self.setLayout(layout) def minimumSizeHint(self) -> PySide2.QtCore.QSize: return QSize(100, 100) def load(self, tree: ComponentTree): """ Display a component tree. """ if self.workspace.instance.project is None: return proj = self.workspace.instance.project funcs = self.workspace.instance.kb.functions self._tree.clear() queue: List[Tuple[ComponentTreeNode, Optional[QComponentItem]]] = [(tree.root, None)] while queue: node, parent = queue.pop(0) if parent is None: # this is the root parent = self._tree # create a widget item item = QComponentItem(parent, node) # add all functions for comp_func in node.functions: try: func = funcs.get_by_addr( proj.loader.main_object.mapped_base + comp_func.virtual_addr) except KeyError: func = None func_node = QFunctionItem(self.workspace.instance.project, item, comp_func, function=func) item.function_nodes.append(func_node) # insert all components into the queue for comp in node.components: queue.append((comp, item)) def reset(self): self._tree.clear() # # Event # def on_item_doubleclicked(self, item: QTreeWidgetItem, column: int): if isinstance(item, QFunctionItem): if item.function is not None: # display the function, either in the disassembly view or in the pseudo code view self.workspace.on_function_selected(item.function) else: # jump to the function address self.workspace.jump_to(item.func_addr)
class DataToDrawSelector(QWidget): exampleDataToDraw = { 'OS': {'Original Signal': None}, 'PS-,PS+': {'Processed Signal -' : None, 'Processed Signal +' : None}, 'OS,PS+': {'Original Signal' : None, 'Processed Signal +' : None}} ''' self.chartSelector = QListWidget() for ch in self.charts: self.chartSelector.addItem(ch) self.chartSelector.currentTextChanged.connect(self.setAtiveChart) return self.chartSelector ''' newChannelSelected = Signal(str, str, dict) newSignalSelected = Signal(str, str, dict) newMaskSelected = Signal(str, str) signalColorChanged = Signal(str, str) def __init__(self, dataManager, chartData, charManager, algManager, parent=None): QWidget.__init__(self, parent) self.dataManager = dataManager self.chartData = chartData self.charManager = charManager self.algManager = algManager self._crateSelectors() self.curSelect = None self.signalPressed = False def _crateSelectors(self): self.mLayout = QVBoxLayout(self) wsLayout = QVBoxLayout() alg = self.algManager self.wsSelector = WorkspaceChooser(alg) self.wsSelector.setMaximumHeight(70) groups = self.chartData.getDataGroups() self.wsSelector.addItems(groups) self.wsSelector.currentTextChanged.connect(self._updateAll) self.chartData.dataGroupAdded.connect(self.addNewGroup) self.mLayout.addWidget(QLabel('Workspaces')) self.mLayout.addWidget(self.wsSelector) self.chartData.allRemoved.connect(self._resetWorkspaces) self.chSelector = QTreeWidget() self.chSelector.setHeaderHidden(True) self.chSelector.itemClicked.connect(self.changeCurrentSelect) self.chSelector.itemChanged.connect(self.itemChanged) self.mLayout.addWidget(QLabel('Channels')) self.mLayout.addWidget(self.chSelector) self.sSelector = SignalChooser() self.sSelector.setHeaderHidden(True) self.sSelector.setDragEnabled(True) self.sSelector.setDropIndicatorShown(True) self.sSelector.setContextMenuPolicy(Qt.CustomContextMenu) self.createSignalPopupMenu(self.sSelector) self.sSelector.customContextMenuRequested.connect(self.onSignalContextMenu) self.sSelector.itemClicked.connect(self.changeCurrentSelect) self.sSelector.itemPressed.connect(self.signalPress) self.sSelector.itemChanged.connect(self.itemChanged) self.mLayout.addWidget(QLabel('Signals')) self.mLayout.addWidget(self.sSelector) self.gSelector = SignalGroupsChooser(self.chartData, self.wsSelector) self.mLayout.addWidget(QLabel('Signal Groups')) self.mLayout.addWidget(self.gSelector) self.wsSelector.setCurrentRow(0) self.chartData.signalAdded.connect(self._updateAll) self.chartData.signalRemoved.connect(self._updateAll) self.chartData.signalGroupAdded.connect(self._updateAll) self.chartData.signalGroupRemoved.connect(self._updateAll) self.chartData.signalToGrupAdded.connect(self._updateAll) self.chartData.signalFromGroupRemoved.connect(self._updateAll) def signalPress(self): self.signalPressed = True def createSignalPopupMenu(self, parent=None): self.popupMenu = QMenu(parent) self.popupMenu.addAction("Process...", self.openSignalProcessingDialog) self.popupMenu.addAction("Apply algorithm...", self.openAlgorithmDialog) self.popupMenu.addAction("Set as Current Mask", self.maskSelected) self.popupMenu.addAction("Change color", self.changeSignalColor) self.popupMenu.addSeparator() self.popupMenu.addAction("Delete", self.deleteSignal) def onSignalContextMenu(self, pos): self.clickedItem = self.sSelector.itemAt(pos) if self.clickedItem is None: return if self.clickedItem.parent() is None: self.popupMenu.exec_(self.sSelector.mapToGlobal(pos)) def deleteSignal(self): ws = self.wsSelector.currentItem().text() signalToDel = self.clickedItem.text(0) self.dataManager.removeSignal(ws, signalToDel) def addNewGroup(self, newGroup, gKind): newItem = QListWidgetItem(newGroup) newItem.setData(1, gKind) self.wsSelector.addItem(newItem) self.wsSelector.setCurrentItem(newItem) def _resetWorkspaces(self): self.wsSelector.currentTextChanged.disconnect(self._updateAll) wsCount = self.wsSelector.count() for i in range(wsCount-1, -1, -1): self.wsSelector.takeItem(i) self.wsSelector.currentTextChanged.connect(self._updateAll) def _updateAll(self, newGroup=None): try: self.chSelector.itemChanged.disconnect(self.itemChanged) self.sSelector.itemChanged.disconnect(self.itemChanged) except: pass if newGroup == '': return chStruct = self.chartData[newGroup] sStruct = self.chartData[newGroup].getColStructure() self.chSelector.clear() for ws in chStruct: gparent = QTreeWidgetItem(self.chSelector) gparent.setText(0, ws) gparent.setBackgroundColor(0, Qt.white) gparent.setFlags(Qt.ItemIsEnabled) for key in chStruct[ws]: parent = QTreeWidgetItem(gparent) parent.setText(0, key) if chStruct[ws][key][0] == True: dataNames = chStruct[ws][key][3] sColor = QColor(chStruct[ws][key][4]) sColor.setAlpha(100) parent.setBackgroundColor(0, sColor) else: dataNames = ','.join(chStruct[ws][key][2]) sColor = QColor(chStruct[ws][key][3]) sColor.setAlpha(100) parent.setBackgroundColor(0, sColor) parent.setText(1, dataNames) if chStruct[ws][key][1] == True: parent.setCheckState(0, Qt.Checked) else: parent.setCheckState(0, Qt.Unchecked) parent.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.sSelector.clear() self.gSelector.clear() for ws in sStruct: firstChannel = sStruct[ws][0] isOneSignal = self.chartData[newGroup][firstChannel][ws][0] if isOneSignal: gparent = QTreeWidgetItem(self.sSelector) gparent.setText(0, ws) gparent.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable) if True: ## if chStruct['CH1'][ws][5] == True: gparent.setCheckState(0, Qt.Checked) else: gparent.setCheckState(0, Qt.Unchecked) for key in sStruct[ws]: parent = QTreeWidgetItem(gparent) parent.setText(0, key) if chStruct[key][ws][2] == True: parent.setCheckState(0, Qt.Checked) else: parent.setCheckState(0, Qt.Unchecked) parent.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) sColor = QColor(chStruct[key][ws][4]) sColor.setAlpha(100) sGradient = QLinearGradient(0, 0, 100, 10) sGradient.setColorAt(0, sColor) sGradient.setColorAt(1, Qt.white) sBrush = QBrush(sGradient) sBrush.setStyle(Qt.LinearGradientPattern) sBrush.setColor(sColor) gparent.setBackground(0, sBrush) else: gparent = QTreeWidgetItem(self.gSelector) gparent.setText(0, ws) gparent.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsUserCheckable) if chStruct['CH1'][ws][5] == True: gparent.setCheckState(0, Qt.Checked) else: gparent.setCheckState(0, Qt.Unchecked) signalNames = chStruct[key][ws][2] sColor = QColor(chStruct[key][ws][3]) sColor.setAlpha(100) gparent.setBackgroundColor(0, sColor) for signal in signalNames: parent = QTreeWidgetItem(gparent) parent.setText(0, signal) parent.setFlags(Qt.ItemIsEnabled) for key in sStruct[signal]: sColor = QColor(chStruct[key][signal][4]) sColor.setAlpha(100) parent.setBackgroundColor(0, sColor) break self.chSelector.itemChanged.connect(self.itemChanged) self.sSelector.itemChanged.connect(self.itemChanged) self.curSelect = None def _updateSignalColor(self, signalName, newColor): chIter = QTreeWidgetItemIterator(self.chSelector, QTreeWidgetItemIterator.Checked) while chIter.value(): if chIter.value().text(0) == signalName: sColor = QColor(newColor) sColor.setAlpha(100) chIter.value().setBackgroundColor(0, sColor) chIter += 1 sIter = QTreeWidgetItemIterator(self.sSelector) while sIter.value(): if sIter.value().text(0) == signalName: sColor = QColor(newColor) sColor.setAlpha(100) sGradient = QLinearGradient(0, 0, 100, 10) sGradient.setColorAt(0, sColor) sGradient.setColorAt(1, Qt.white) sBrush = QBrush(sGradient) sBrush.setStyle(Qt.LinearGradientPattern) sBrush.setColor(sColor) sIter.value().setBackground(0, sBrush) if sIter.value() is self.curSelect: self.prevBackGround = sIter.value().background(0) sIter += 1 self.changeCurrentSelect(self.curSelect) def changeCurrentSelect(self, newItem): if newItem is None: print('newItem is None') self.curSelect = None return if (newItem.treeWidget() is self.sSelector and not self.signalPressed): ws = self.wsSelector.currentItem().text() isChecked = [True if newItem.checkState(0) is Qt.Checked else False] channel = 'CH1' signal = newItem.text(0) self.chartData[ws][channel][signal][5] = isChecked[0] return self.signalPressed = False newItem.setSelected(False) if newItem.parent() is None: if self.curSelect is not None: self.curSelect.setFont(0, self.prevFont) self.curSelect.setBackground(0, self.prevBackGround) self.curSelect.setForeground(0, self.prevForeground) self.prevBackGround = newItem.background(0) self.prevForeground = newItem.foreground(0) self.prevFont = newItem.font(0) sBrush = newItem.background(0) sBColor = sBrush.color() sBColor.setAlpha(200) sBrush.setColor(sBColor) sBrush.setStyle(Qt.SolidPattern) sFont = newItem.font(0) sFont.setBold(True) if newItem.treeWidget() is self.chSelector: sBrush.setColor(QColor(56, 211, 255, 120)) newItem.setBackground(0, sBrush) newItem.setForeground(0, QBrush(Qt.white)) newItem.setFont(0, sFont) self.curSelect = newItem if self.curSelect.treeWidget() is self.chSelector: self.ChannelSelected() elif self.curSelect.treeWidget() is self.sSelector: self.SignalSelected() def ChannelSelected(self): dChecked = [] sIter = QTreeWidgetItemIterator(self.sSelector, QTreeWidgetItemIterator.Checked) while sIter.value(): if not sIter.value().parent(): dChecked.append(sIter.value().text(0)) sIter += 1 gIter = QTreeWidgetItemIterator(self.gSelector, QTreeWidgetItemIterator.Checked) while gIter.value(): if not gIter.value().parent(): dChecked.append(gIter.value().text(0)) gIter += 1 chStruct = {} sIter = QTreeWidgetItemIterator(self.curSelect, QTreeWidgetItemIterator.Checked) while (sIter.value() and sIter.value().parent() is self.curSelect and sIter.value().checkState(0) == Qt.Checked): sItem = sIter.value() dataName = sItem.text(0) if dataName in dChecked: chStruct[sItem.text(0)] = None sIter += 1 group = self.wsSelector.currentItem().text() channel = self.curSelect.text(0) self.newChannelSelected.emit(group, channel, chStruct) def SignalSelected(self): sStruct = {} chIter = QTreeWidgetItemIterator(self.curSelect, QTreeWidgetItemIterator.Checked) if not chIter.value().parent(): #Skip signal chIter += 1 while (chIter.value() and chIter.value().parent() is self.curSelect and chIter.value().checkState(0) == Qt.Checked): chItem = chIter.value() sStruct[chItem.text(0)] = None chIter += 1 ws = self.wsSelector.currentItem().text() signal = self.curSelect.text(0) self.newSignalSelected.emit(ws, signal, sStruct) def maskSelected(self): ws = self.wsSelector.currentItem().text() signal = self.clickedItem.text(0) self.newMaskSelected.emit(ws, signal) def changeSignalColor(self): ws = self.wsSelector.currentItem().text() signal = self.clickedItem.text(0) channels = [] sIter = QTreeWidgetItemIterator(self.clickedItem) sIter += 1 # First children while(sIter.value()): if sIter.value().parent() is self.clickedItem: channels.append(sIter.value().text(0)) sIter += 1 else: break sData = self.chartData[ws].getDataFromStructure({signal : channels}, inv=True)[signal] sColor = sData[0][4] newColor = QColorDialog().getColor(QColor(sColor), self) if newColor.isValid(): for sD in sData: sD[4] = newColor.name() self._updateSignalColor(signal, newColor.name()) self.signalColorChanged.emit(ws, signal) def openSignalProcessingDialog(self): ws = self.wsSelector.currentItem().text() signal = self.clickedItem.text(0) dialog = DataProcessingDialog(self.dataManager, self, [ws, signal]) dialog.show() dialog.exec() def openAlgorithmDialog(self): ws = self.wsSelector.currentItem().text() signal = self.clickedItem.text(0) self.algManager.showAlgorithmDialog(ws, signal) def itemChanged(self, item): if item.flags() == (Qt.ItemIsUserCheckable | Qt.ItemIsEnabled): ws = self.wsSelector.currentItem().text() isChecked = [True if item.checkState(0) is Qt.Checked else False] if item.treeWidget() is self.chSelector: channel = item.parent().text(0) signal = item.text(0) self.chartData[ws][channel][signal][1] = isChecked[0] elif item.treeWidget() is self.sSelector: signal = item.parent().text(0) channel = item.text(0) self.chartData[ws][channel][signal][1] = isChecked[0] def addSignalItem(self, group, signal, chList): pass '''
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()
class ObjectsBrowserWindow(QWidget): def __init__(self, parent, title, person, unsorted_objects, autoshow=True, progress_indicator=None): super().__init__(None) act = QAction("close", self) act.triggered.connect(self._do_close) act.setShortcut(QKeySequence("escape")) self.addAction(act) layout = QGridLayout() bar = QMenuBar(self) self._object_actions = bar.addMenu(_("Object actions")) property_actions = bar.addMenu(_("Property actions")) self._create_item(property_actions, _("Copy property value"), "ctrl+c", self.on_copypropvalue_selected) self._create_item(property_actions, _("Copy property name"), "alt+c", self.on_copypropname_selected) self._create_item(property_actions, _("Copy property name and value"), "ctrl+alt+c", self.on_copypropline_selected) objects_label = QLabel(_("Objects"), self) layout.addWidget(objects_label, 0, 0) self._objects_list = QListWidget(self) self._objects_list.setAccessibleName(objects_label.text()) self._objects_list.setContextMenuPolicy(Qt.CustomContextMenu) self._objects_list.currentRowChanged.connect(self.on_objects_listbox) self._objects_list.customContextMenuRequested.connect( self._on_objects_list_menu) objects_label.setBuddy(self._objects_list) layout.addWidget(self._objects_list, 1, 0) props_label = QLabel(_("Object properties"), self) layout.addWidget(props_label, 0, 1) self._props = QTreeWidget(self) self._props.setAccessibleName(props_label.text()) props_label.setBuddy(self._props) layout.addWidget(self._props, 1, 1) goto_button = QPushButton(_("Go to"), self) goto_button.setDefault(True) goto_button.clicked.connect(self.on_goto_clicked) self._objects_list.itemActivated.connect(goto_button.click) layout.addWidget(goto_button, 2, 0) close_button = QPushButton(_("Close"), self) close_button.clicked.connect(self.close) layout.addWidget(close_button, 2, 1) self.setLayout(layout) self.setWindowTitle(title + _(" ({num_objects} objects shown)").format( num_objects=len(unsorted_objects))) self._person = person self._autoshow = autoshow self._progress_indicator = progress_indicator self._all_actions = [] for member in object_actions.__dict__.values(): if inspect.isclass(member) and issubclass(member, ObjectAction): self._all_actions.append(member) self._objects_list.setCurrentRow(0) self._sorter = ObjectsSorter(unsorted_objects, person) self._sorter.objects_sorted.connect(self._objects_sorted) self._sorter.start() def _objects_sorted(self, data): objects, item_data = data self._objects = objects for (desc, dist, rel_bearing) in item_data: self._objects_list.addItem( _("{object}: distance {distance} meters, {rel_bearing}"). format(object=desc, distance=dist, rel_bearing=rel_bearing)) if self._progress_indicator: self._progress_indicator.hide() self._progress_indicator.deleteLater() if self._autoshow: self._objects_list.setCurrentRow(0) self.show() def _create_item(self, menu, label, shortcut, callback): action = menu.addAction(label) action.triggered.connect(callback) action.setShortcut(QKeySequence(shortcut)) def on_goto_clicked(self, evt): self._person.move_to(self.selected_object[2], force=True) def _do_close(self): self.close() self.destroy() windows = QApplication.topLevelWidgets() other_browsers = [ w for w in windows if w is not self and isinstance(w, self.__class__) and w.isVisible() ] if other_browsers: other_browsers[-1].activateWindow() else: menu_service().ensure_key_capturer_focus() def on_objects_listbox(self, current_index): selected = self._objects[current_index][1] self._props.clear() common_item = QTreeWidgetItem([_("Common properties")]) specific_item = QTreeWidgetItem([_("Specific properties")]) other_item = QTreeWidgetItem([ _("Other properties - they can not be searched and are not processed in any way" ) ]) common_fields = list( EntityMetadata.for_discriminator("OSMEntity").fields.keys()) selected_metadata = EntityMetadata.for_discriminator( selected.discriminator) known_fields = selected_metadata.all_fields formatted_values = {} for field_name in selected.defined_field_names(): raw_value = selected.value_of_field(field_name) if field_name not in known_fields: # By the mere fact that the other fields have no defined order, we can add them there without losing anything. other_item.addChild( QTreeWidgetItem([ "%s: %s" % (underscored_to_words(field_name), raw_value) ])) else: value_str = "%s: %s" % ( underscored_to_words(field_name), format_field_value(raw_value, known_fields[field_name].type_name)) formatted_values[field_name] = value_str for common in common_fields: del known_fields[common] common_item.addChild(QTreeWidgetItem([formatted_values[common]])) for specific in known_fields.keys( ): # Because we deleted the common ones in the loop before this, only the specific remain. if specific in formatted_values: specific_item.addChild( QTreeWidgetItem([formatted_values[specific]])) # We add the entity ID mainly for debugging purposes, and that's the reason why it is added the last and so special in the first place. common_item.addChild( QTreeWidgetItem([_("Object id: {}").format(selected.id)])) self._props.addTopLevelItem(common_item) if specific_item.childCount() > 0: self._props.addTopLevelItem(specific_item) self._props.expandItem(specific_item) #self._props.setCurrentItem(specific_item) # Breaks focus behavior slightly, but annoingly enough. if other_item.childCount() > 0: self._props.addTopLevelItem(other_item) self._object_actions.clear() for action in self._all_actions: if action.executable(selected): mi = self._object_actions.addAction(action.label) mi.triggered.connect( action_execution_handler_factory(action, selected, self)) @property def selected_object(self): return self._objects[self._objects_list.currentRow()] def on_copypropvalue_selected(self, evt): prop = self._props.currentItem().text(0) val = prop.split(": ", 1)[1] QApplication.clipboard().setText(val) def on_copypropname_selected(self, evt): prop = self._props.currentItem().text(0) name = prop.split(": ", 1)[0] QApplication.clipboard().setText(name) def on_copypropline_selected(self, evt): prop = self._props.currentItem().text(0) QApplication.clipboard().setText(prop) def _on_objects_list_menu(self, point): self._object_actions.exec_(point)
def clear_list(tree: QTreeWidget): tree.clear()
class QDecompilationOptions(QWidget): def __init__(self, code_view, instance, options=None): super().__init__() self._code_view = code_view self._instance = instance self._options = options if self._options is None: if instance.project is not None: self._options = self.get_default_options() else: self._options = [] # widgets self._search_box = None # type:QLineEdit self._treewidget = None # type:QTreeWidget self._apply_btn = None # type:QPushButton self._qoptions = [] self._init_widgets() self._reload_options() @property def selected_options(self): selected = [] for item in self._qoptions: if item.checkState(0): selected.append(item.option) return selected @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 get_optimization_passes(self._instance.project.arch, self._instance.project.simos.name) 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() # populate the tree widget with new options for option in sorted(self._options, key=lambda x: x.__name__): w = QDecompilationOption(self._treewidget, option) self._qoptions.append(w)
class MemTree(QWidget): def __init__(self, qmp, parent): super().__init__() self.qmp = qmp self.qmp.memoryMap.connect(self.update_tree) self.parent = parent self.tree_sem = QSemaphore(1) self.sending_sem = QSemaphore( 1) # used to prevent sending too many requests at once self.init_ui() self.get_map() def init_ui(self): self.vbox = QVBoxLayout() self.refresh = QPushButton('Refresh') self.refresh.clicked.connect(lambda: self.get_map()) self.vbox.addWidget(self.refresh) self.tree = QTreeWidget() self.tree.itemDoubleClicked.connect(self.open_region) self.tree.setColumnCount(3) self.tree.header().setSectionResizeMode(QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setHeaderLabels( ['Memory Region', 'Start Address', 'End Address']) self.vbox.addWidget(self.tree) self.setLayout(self.vbox) self.setGeometry(100, 100, 500, 300) self.setWindowTitle("Memory Tree") self.show() def get_map(self): self.tree.clear() self.qmp.command('mtree') # finds item with name 'name' in self.tree # self.tree_sem must be acquired before use def find(self, name, node): if node.text(0) == name: return node else: for i in range(node.childCount()): result = self.find(name, node.child(i)) if result: return result return None def update_tree(self, value): if value != None: self.tree_sem.acquire() current_addr_space = '' for region in value: parent_node = self.tree parent = region['parent'] if parent != '': root = self.tree.invisibleRootItem() for i in range(root.childCount()): if root.child(i).text(0) == current_addr_space: root = root.child(i) break parent_node = self.find(parent, root) else: current_addr_space = region['name'] node = QTreeWidgetItem(parent_node) node.setText(0, region['name']) start = region['start'] end = region['end'] if start < 0: start = start + (1 << constants['bits']) if end < 0: end = end + (1 << constants['bits']) node.setText(1, f'{start:016x}') node.setText(2, f'{end:016x}') node.setFont(0, QFont('Courier New')) node.setFont(1, QFont('Courier New')) node.setFont(2, QFont('Courier New')) self.tree_sem.release() def open_region(self, node, col): self.parent.open_new_window( MemDumpWindow(self.qmp, base=int(node.text(1), 16), max=int(node.text(2), 16)))
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)