示例#1
0
    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)
示例#2
0
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)
示例#3
0
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)
示例#4
0
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()
示例#6
0
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)
示例#7
0
 def clear_list(tree: QTreeWidget):
     tree.clear()
示例#8
0
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)
示例#9
0
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)))
示例#10
0
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)