Beispiel #1
0
class CollapsibleWidget(QWidget):
    """a dialog to which collapsible sections can be added;
    subclass and reimplement define_sections() to define sections and
        add them as (title, widget) tuples to self.sections
    """
    def __init__(self):
        super().__init__()
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        self.tree.setPalette(get_verifone_color())
        self.setStyleSheet("background-color: rgba(3, 169, 229, 0)")
        layout = QVBoxLayout()
        self.buttonGroup = QButtonGroup()
        layout.addWidget(self.tree)        
        self.setLayout(layout)
        self.tree.setIndentation(0)
        self.setPalette(get_verifone_color())
        self.sections = []
        self.setFixedWidth(500)
    
    def get_tree(self):
        return self.tree
            
    def add_sections(self):
        """adds a collapsible sections for every 
        (title, widget) tuple in self.sections
        """
        for (title, widget) in self.sections:
            button1 = self.add_button(title)
            section1 = self.add_widget(button1, widget)            
            button1.addChild(section1)

    def include_section(self, title, frame):
        """reimplement this to define all your sections
        and add them as (title, widget) tuples to self.sections
        """
        self.sections.append((title, frame))

    def add_button(self, title):
        """creates a QTreeWidgetItem containing a button 
        to expand or collapse its section
        """
        item = QTreeWidgetItem()
        item.setBackgroundColor(0, QColor(3, 169, 229))
        self.tree.addTopLevelItem(item)
        self.tree.setItemWidget(item, 0, SectionExpandButton(item, text = title, group = self.buttonGroup))
        
        return item

    def add_widget(self, button, widget):
        """creates a QWidgetItem containing the widget,
        as child of the button-QWidgetItem
        """
        section = QTreeWidgetItem(button)
        section.setDisabled(True)
        section.setBackgroundColor(0, QColor(3, 169, 229))
        self.tree.setItemWidget(section, 0, widget)
        return section
Beispiel #2
0
class CollapsibleDialog(QDialog):
    """a dialog to which collapsible sections can be added;
    subclass and reimplement define_sections() to define sections and
        add them as (title, widget) tuples to self.sections
    """
    def __init__(self):
        super().__init__()
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        self.setLayout(layout)
        self.tree.setIndentation(0)

        self.sections = []
        self.define_sections()
        self.add_sections()

    def add_sections(self):
        """adds a collapsible sections for every
        (title, widget) tuple in self.sections
        """
        for (title, widget) in self.sections:
            button1 = self.add_button(title)
            section1 = self.add_widget(button1, widget)
            button1.addChild(section1)

    def define_sections(self):
        """reimplement this to define all your sections
        and add them as (title, widget) tuples to self.sections
        """
        widget = QFrame(self.tree)
        layout = QHBoxLayout(widget)
        layout.addWidget(QLabel("Bla"))
        layout.addWidget(QLabel("Blubb"))
        title = "Section 1"
        self.sections.append((title, widget))

    def add_button(self, title):
        """creates a QTreeWidgetItem containing a button
        to expand or collapse its section
        """
        item = QTreeWidgetItem()
        self.tree.addTopLevelItem(item)
        self.tree.setItemWidget(item, 0, SectionExpandButton(item, text=title))
        return item

    def add_widget(self, button, widget):
        """creates a QWidgetItem containing the widget,
        as child of the button-QWidgetItem
        """
        section = QTreeWidgetItem(button)
        section.setDisabled(True)
        self.tree.setItemWidget(section, 0, widget)
        return section
Beispiel #3
0
    def add_tree_no_header(self, parent):
        tw = QTreeWidget()
        parent.addWidget(tw)
        tw.setHeaderHidden(True)
        tw.setAlternatingRowColors(True)

        i1 = QTreeWidgetItem(tw, ['Mammal'])
        i2 = QTreeWidgetItem(i1, ['Rodent'])
        i3 = QTreeWidgetItem(i2, ['Rat'])
        i3 = QTreeWidgetItem(i2, ['Beaver'])
        i2 = QTreeWidgetItem(i1, ['Primate'])
        i3 = QTreeWidgetItem(i2, ['Baboon'])
        i3 = QTreeWidgetItem(i2, ['Human'])
        i1 = QTreeWidgetItem(tw, ['Reptile'])
        i2 = QTreeWidgetItem(i1, ['Snake'])
        i3 = QTreeWidgetItem(i1, ['Crocodile'])

        self.add_expand_collapse_buttons(parent, tw)
    def _init_finds_tab(self, tab):
        finds_list = QTreeWidget()
        finds_list.setHeaderHidden(True)
        self._finds_list = finds_list

        layout = QVBoxLayout()
        layout.addWidget(finds_list)

        frame = QFrame()
        frame.setLayout(layout)

        import_button = QPushButton("Import List")
        import_button.clicked.connect(lambda: self._import_to_list(self._finds_list))
        layout.addWidget(import_button)

        tab.addTab(frame, 'Finds')

        self._finds_list.itemChanged.connect(self._on_explore_addr_changed)
Beispiel #5
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)
Beispiel #6
0
    def _init_widgets(self):
        layout = QGridLayout()
        row = 0

        validation_failures = set()

        # name

        name_label = QLabel(self)
        name_label.setText("Name")

        name_box = QLineEdit(self)
        name_box.setText(NameGenerator.random_name())

        def handle_name(txt):
            nonlocal validation_failures
            key = {'name'}
            if txt and not any(s.gui_data.name == txt
                               for s in self.instance.states):
                validation_failures -= key
            else:
                validation_failures |= key
            validation_update()

        name_box.textEdited.connect(handle_name)

        layout.addWidget(name_label, row, 0)
        layout.addWidget(name_box, row, 1)
        row += 1

        # address

        address_label = QLabel(self)
        address_label.setText("Address")

        address_box = QLineEdit(self)
        address_box.setText(
            hex(self.instance.project.entry
                ) if self._addr is None else hex(self._addr))

        def handle_address(_):
            nonlocal validation_failures
            key = {'addr'}
            if parse_address() is not None:
                validation_failures -= key
            else:
                validation_failures |= key
            validation_update()

        def parse_address():
            txt = address_box.text()
            try:
                return self.instance.project.kb.labels.lookup(txt)
            except KeyError:
                pass

            try:
                return int(txt, 16)
            except ValueError:
                return None

        address_box.textEdited.connect(handle_address)
        layout.addWidget(address_label, row, 0)
        layout.addWidget(address_box, row, 1)
        row += 1

        # template

        template_label = QLabel(self)
        template_label.setText("Template")

        template_combo = QComboBox()
        template_combo.addItem("Blank State", 'blank')
        template_combo.addItem("Call state", 'call')
        template_combo.addItem("Entry state", 'entry')
        template_combo.addItem("Full-init state", 'full')

        def handle_template(_):
            base_allowed = template_combo.currentData() in ('blank', 'call')
            base_state_combo.setHidden(not base_allowed)
            base_state_label.setHidden(not base_allowed)

        template_combo.currentIndexChanged.connect(handle_template)

        layout.addWidget(template_label, row, 0)
        layout.addWidget(template_combo, row, 1)
        row += 1

        # base state

        base_state_label = QLabel(self)
        base_state_label.setText('Base state')

        base_state_combo = QStateComboBox(self.instance, self)
        self._base_state_combo = base_state_combo

        layout.addWidget(base_state_label, row, 0)
        layout.addWidget(base_state_combo, row, 1)
        row += 1

        # mode

        mode_label = QLabel(self)
        mode_label.setText("Mode")

        mode_combo = QComboBox(self)
        mode_combo.addItem("Symbolic", "symbolic")
        mode_combo.addItem("Static", "static")
        mode_combo.addItem("Fast-path", "fastpath")
        mode_combo.addItem("Tracing", "tracing")
        self._mode_combo = mode_combo

        def mode_changed():
            self._options.clear()
            self._options.update(
                angr.sim_options.modes[mode_combo.currentData()])
            for child in children_items:
                child.setCheckState(
                    0, Qt.Checked
                    if child.text(0) in self._options else Qt.Unchecked)

        mode_combo.currentIndexChanged.connect(mode_changed)
        self._options.clear()
        self._options.update(angr.sim_options.modes[mode_combo.currentData()])

        layout.addWidget(mode_label, row, 0)
        layout.addWidget(mode_combo, row, 1)
        row += 1

        # options tree

        options_label = QLabel(self)
        options_label.setText("Options")

        options_tree = QTreeWidget(self)
        options_tree.setHeaderHidden(True)
        children_items = []
        for name, members in angr.sim_options.__dict__.items():
            if type(members) is not set:
                continue
            if name == 'resilience_options':
                continue
            parent = QTreeWidgetItem(options_tree)
            parent.setText(0, name)
            parent.setFlags(parent.flags() | Qt.ItemIsTristate
                            | Qt.ItemIsUserCheckable)
            for option in members:
                child = QTreeWidgetItem(parent)
                child.setText(0, option)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setCheckState(
                    0, Qt.Checked if option in self._options else Qt.Unchecked)
                children_items.append(child)
        parent = QTreeWidgetItem(options_tree)
        parent.setText(0, "All options")
        parent.setFlags(parent.flags() | Qt.ItemIsTristate
                        | Qt.ItemIsUserCheckable)
        for option in {
                x
                for x in angr.sim_options.__dict__.values()
                if type(x) is str and is_option(x)
        }:
            child = QTreeWidgetItem(parent)
            child.setText(0, option)
            child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
            child.setCheckState(
                0, Qt.Checked if option in self._options else Qt.Unchecked)
            children_items.append(child)

        def maintain_model(item: QTreeWidgetItem, _):
            option = item.text(0)
            if not is_option(option):
                return

            checked = item.checkState(0)
            if (option in self._options) == checked:
                return

            if checked:
                self._options.add(option)
            else:
                self._options.remove(option)

            for child in children_items:
                if child is not item and child.text(0) == option:
                    child.setCheckState(0, checked)

        options_tree.itemChanged.connect(maintain_model)

        layout.addWidget(options_label, row, 0)
        layout.addWidget(options_tree, row, 1)
        row += 1

        # options filter

        options_filter_label = QLabel(self)
        options_filter_label.setText("")

        options_filter_box = QLineEdit(self)
        options_filter_box.setPlaceholderText("Filter")

        def do_filter(text):
            for child in children_items:
                child.setHidden(text.upper() not in child.text(0))

        options_filter_box.textEdited.connect(do_filter)

        layout.addWidget(options_filter_label, row, 0)
        layout.addWidget(options_filter_box, row, 1)
        row += 1

        # buttons

        ok_button = QPushButton(self)
        ok_button.setText('OK')

        def do_ok():
            name = name_box.text()
            template = template_combo.currentData()
            addr = parse_address()
            base_state = base_state_combo.state
            mode = mode_combo.currentData()
            if template in ('blank', 'call') and base_state is not None:
                if template == 'blank':
                    self.state = self.instance.project.factory.blank_state(
                        addr=addr,
                        base_state=base_state,
                        options=self._options)
                else:
                    self.state = self.instance.project.factory.call_state(
                        addr, base_state=base_state, options=self._options)
                self.state.gui_data.base_name = base_state.gui_data.name
            else:
                if template == 'blank':
                    self.state = self.instance.project.factory.blank_state(
                        addr=addr, mode=mode, options=self._options)
                elif template == 'call':
                    self.state = self.instance.project.factory.call_state(
                        addr, mode=mode, options=self._options)
                elif template == 'entry':
                    self.state = self.instance.project.factory.entry_state(
                        mode=mode, options=self._options)
                else:
                    self.state = self.instance.project.factory.full_init_state(
                        mode=mode, options=self._options)
                self.state.gui_data.base_name = name
                self.state.gui_data.is_base = True

            self.state.gui_data.name = name
            self.state.gui_data.is_original = True

            if self._create_simgr:
                self.instance.workspace.create_simulation_manager(
                    self.state, name)

            self.close()

        ok_button.clicked.connect(do_ok)

        def validation_update():
            ok_button.setDisabled(bool(validation_failures))

        cancel_button = QPushButton(self)
        cancel_button.setText('Cancel')

        def do_cancel():
            self.close()

        cancel_button.clicked.connect(do_cancel)

        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(ok_button)
        buttons_layout.addWidget(cancel_button)

        self.main_layout.addLayout(layout)
        self.main_layout.addLayout(buttons_layout)
Beispiel #7
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()
Beispiel #9
0
    def initUI(self):
        #Заполнение дерева
        def treeItems():
            categories = Categories().data
            for key in categories:
                parent = QTreeWidgetItem(tree)
                parent.setText(0, key)
                for item in categories[key]:
                    child = QTreeWidgetItem(parent)
                    child.setText(0, item)

        #Базовое окно
        self.setGeometry(0, 0, 1920, 1080)
        self.setWindowTitle('УНЦ ПроектБалтЭнерго')

        #Инициализация дерева
        tree = QTreeWidget(self)
        tree.setHeaderHidden(True)

        #Инициализация объектов
        self.c = Communicate()
        self.c2 = Communicate()
        self.c3 = Communicate()
        self.wid = DataTable()
        self.table = MainTable()

        #Создание кнопок
        font_button = QFont('Helvetica [Cronyx]', 8, QFont.Bold)
        self.clipboard_button = QPushButton('Буфер')
        self.export_button = QPushButton('Экспорт в Excel')
        self.total_button = QPushButton('Итого')
        self.clipboard_button.setFont(font_button)
        self.export_button.setFont(font_button)
        self.total_button.setFont(font_button)

        #Формирование сигналов
        self.c.update_table.connect(self.wid.update_table)
        self.c2.update_main_table.connect(self.table.update_table)
        self.c3.recalculation.connect(self.table.recalculation)

        tree.itemClicked.connect(self.onItemClicked)
        self.wid.cellClicked.connect(self.onTableItemClicked)
        self.table.cellClicked.connect(self.recalc)
        self.export_button.clicked.connect(self.export_excel)
        self.clipboard_button.clicked.connect(self.to_clipboard)

        #Ининциализация слоев
        grid = QGridLayout()
        self.setLayout(grid)
        hbox = QVBoxLayout()
        self.export_button.setFixedSize(100, 20)
        self.total_button.setFixedSize(100, 20)

        #Заполнение слоев
        hbox.addWidget(self.clipboard_button)
        hbox.addWidget(self.export_button)
        hbox.addWidget(self.total_button)
        grid.addWidget(tree, 1, 0)
        grid.addWidget(self.wid, 1, 1)
        grid.addWidget(self.table, 2, 0, 1, 2)
        grid.addLayout(hbox, 3, 2)

        #Заполнить дерево
        treeItems()

        self.show()
Beispiel #10
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)
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)
Beispiel #12
0
    def _init_widgets(self):
        layout = QGridLayout()
        row = 0

        validation_failures = set()

        # name

        name_label = QLabel(self)
        name_label.setText("Name")

        name_box = QLineEdit(self)
        name_box.setText(NameGenerator.random_name())

        def handle_name(txt):
            nonlocal validation_failures
            key = {'name'}
            if txt and not any(s.gui_data.name == txt
                               for s in self.instance.states):
                validation_failures -= key
            else:
                validation_failures |= key
            validation_update()

        name_box.textEdited.connect(handle_name)

        layout.addWidget(name_label, row, 0)
        layout.addWidget(name_box, row, 1)
        row += 1

        # address

        address_label = QLabel(self)
        address_label.setText("Address")

        address_box = QLineEdit(self)
        self._address_box = address_box
        address_box.setText(
            hex(self.instance.project.entry
                ) if self._addr is None else hex(self._addr))

        def handle_address(_):
            nonlocal validation_failures
            key = {'addr'}
            if parse_address() is not None:
                validation_failures -= key
            else:
                validation_failures |= key
            validation_update()

        def parse_address():
            txt = address_box.text()
            try:
                return self.instance.project.kb.labels.lookup(txt)
            except KeyError:
                pass

            try:
                return int(txt, 16)
            except ValueError:
                return None

        address_box.textEdited.connect(handle_address)
        layout.addWidget(address_label, row, 0)
        layout.addWidget(address_box, row, 1)
        row += 1

        # template

        template_label = QLabel(self)
        template_label.setText("Template")

        template_combo = QComboBox()
        template_combo.addItem("Blank State", 'blank')
        template_combo.addItem("Call state", 'call')
        template_combo.addItem("Entry state", 'entry')
        template_combo.addItem("Full-init state", 'full')

        def handle_template(_):
            base_allowed = template_combo.currentData() in ('blank', 'call')
            base_state_combo.setHidden(not base_allowed)
            base_state_label.setHidden(not base_allowed)
            args_allowed = template_combo.currentData() in ("entry", )
            args_label.setHidden(not args_allowed)
            args_edit.setHidden(not args_allowed)

        template_combo.currentIndexChanged.connect(handle_template)

        layout.addWidget(template_label, row, 0)
        layout.addWidget(template_combo, row, 1)
        row += 1

        # base state

        base_state_label = QLabel(self)
        base_state_label.setText('Base state')

        base_state_combo = QStateComboBox(self.instance, self)
        self._base_state_combo = base_state_combo

        layout.addWidget(base_state_label, row, 0)
        layout.addWidget(base_state_combo, row, 1)
        row += 1

        # args
        args_label = QLabel(self)
        args_label.setText('Args')

        args_edit = QLineEdit(self)
        self._args_edit = args_edit

        def handle_args():
            self._args = [
                self.instance.project.filename.encode() or b'dummy_filename'
            ]
            for x in args_edit.text().split():
                if len(x) > 2 and x[0] == "`" and x[-1] == "`":
                    tmp = [
                        symbol for symbol in self.instance.symbols
                        if symbol.args[0].split('_')[0] == x[1:-1]
                    ]
                    if len(tmp) == 1:
                        self._args.append(tmp[0])
                else:
                    self._args.append(x.encode())

        args_edit.editingFinished.connect(handle_args)

        layout.addWidget(args_label, row, 0)
        layout.addWidget(args_edit, row, 1)
        row += 1

        # fs_mount
        fs_label = QLabel(self)
        fs_label.setText('Filesystem')
        fs_button = QPushButton(self)
        fs_button.setText("Change")

        layout.addWidget(fs_label, row, 0)
        layout.addWidget(fs_button, row, 1)

        def fs_edit_button():
            fs_dialog = FilesystemMount(fs_config=self._fs_config,
                                        instance=self.instance,
                                        parent=self)
            fs_dialog.exec_()
            self._fs_config = fs_dialog.fs_config
            fs_button.setText("{} Items".format(len(self._fs_config)))

        fs_button.clicked.connect(fs_edit_button)

        row += 1

        # mode

        mode_label = QLabel(self)
        mode_label.setText("Mode")

        mode_combo = QComboBox(self)
        mode_combo.addItem("Symbolic", "symbolic")
        mode_combo.addItem("Static", "static")
        mode_combo.addItem("Fast-path", "fastpath")
        mode_combo.addItem("Tracing", "tracing")
        self._mode_combo = mode_combo

        def mode_changed():
            if mode_combo.currentData() == "tracing":
                TraceState(self.instance, self._base_state_combo,
                           self._address_box)
            self._options.clear()
            self._options.update(
                angr.sim_options.modes[mode_combo.currentData()])
            for child in children_items:
                child.setCheckState(
                    0, Qt.Checked
                    if child.text(0) in self._options else Qt.Unchecked)

        mode_combo.currentIndexChanged.connect(mode_changed)
        self._options.clear()
        self._options.update(angr.sim_options.modes[mode_combo.currentData()])

        layout.addWidget(mode_label, row, 0)
        layout.addWidget(mode_combo, row, 1)
        row += 1

        # options tree

        options_label = QLabel(self)
        options_label.setText("Options")

        options_tree = QTreeWidget(self)
        options_tree.setHeaderHidden(True)
        children_items = []
        for name, members in angr.sim_options.__dict__.items():
            if type(members) is not set:
                continue
            if name == 'resilience_options':
                continue
            parent = QTreeWidgetItem(options_tree)
            parent.setText(0, name)
            parent.setFlags(parent.flags() | Qt.ItemIsTristate
                            | Qt.ItemIsUserCheckable)
            for option in members:
                child = QTreeWidgetItem(parent)
                child.setText(0, option)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setCheckState(
                    0, Qt.Checked if option in self._options else Qt.Unchecked)
                children_items.append(child)
        parent = QTreeWidgetItem(options_tree)
        parent.setText(0, "All options")
        parent.setFlags(parent.flags() | Qt.ItemIsTristate
                        | Qt.ItemIsUserCheckable)
        for option in {
                x
                for x in angr.sim_options.__dict__.values()
                if type(x) is str and is_option(x)
        }:
            child = QTreeWidgetItem(parent)
            child.setText(0, option)
            child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
            child.setCheckState(
                0, Qt.Checked if option in self._options else Qt.Unchecked)
            children_items.append(child)

        def maintain_model(item: QTreeWidgetItem, _):
            option = item.text(0)
            if not is_option(option):
                return

            checked = item.checkState(0)
            if (option in self._options) == checked:
                return

            if checked:
                self._options.add(option)
            else:
                self._options.remove(option)

            for child in children_items:
                if child is not item and child.text(0) == option:
                    child.setCheckState(0, checked)

        options_tree.itemChanged.connect(maintain_model)

        layout.addWidget(options_label, row, 0)
        layout.addWidget(options_tree, row, 1)
        row += 1

        # options filter

        options_filter_label = QLabel(self)
        options_filter_label.setText("")

        options_filter_box = QLineEdit(self)
        options_filter_box.setPlaceholderText("Filter")

        def do_filter(text):
            for child in children_items:
                child.setHidden(text.upper() not in child.text(0))

        options_filter_box.textEdited.connect(do_filter)

        layout.addWidget(options_filter_label, row, 0)
        layout.addWidget(options_filter_box, row, 1)
        row += 1

        # buttons

        ok_button = QPushButton(self)
        ok_button.setText('OK')

        def do_ok():
            name = name_box.text()
            template = template_combo.currentData()
            addr = parse_address()
            base_state = base_state_combo.state
            mode = mode_combo.currentData()
            if template in ('blank', 'call') and base_state is not None:
                if template == 'blank':
                    self.state = self.instance.project.factory.blank_state(
                        addr=addr,
                        base_state=base_state,
                        options=self._options)
                else:
                    self.state = self.instance.project.factory.call_state(
                        addr, base_state=base_state, options=self._options)
                self.state.gui_data.base_name = base_state.gui_data.name
            else:
                if template == 'blank':
                    self.state = self.instance.project.factory.blank_state(
                        addr=addr, mode=mode, options=self._options)
                elif template == 'call':
                    self.state = self.instance.project.factory.call_state(
                        addr, mode=mode, options=self._options)
                elif template == 'entry':
                    self.state = self.instance.project.factory.entry_state(
                        mode=mode, options=self._options, args=self._args)
                else:
                    self.state = self.instance.project.factory.full_init_state(
                        mode=mode, options=self._options)
                self.state.gui_data.base_name = name
                self.state.gui_data.is_base = True

            self.state.gui_data.name = name
            self.state.gui_data.is_original = True

            # TODO: there should prob be an am_event here
            def attach_addr_annotation(state):
                for i in range(len(state.solver.constraints)):
                    if SrcAddrAnnotation not in [
                            type(a)
                            for a in state.solver.constraints[i].annotations
                    ]:
                        state.solver.constraints[i] = \
                                state.solver.constraints[i].annotate(SrcAddrAnnotation(state.addr))
                return state

            self.state.inspect.b(event_type='constraints',
                                 when=angr.BP_AFTER,
                                 action=attach_addr_annotation)

            # mount fs
            if self._fs_config:
                for path, real in self._fs_config:
                    if os.path.isdir(real):
                        fs = angr.SimHostFilesystem(real)
                        fs.set_state(self.state)
                        self.state.fs.mount(path, fs)

            if self._create_simgr:
                self.instance.workspace.create_simulation_manager(
                    self.state, name)

            self.close()

        ok_button.clicked.connect(do_ok)

        def validation_update():
            ok_button.setDisabled(bool(validation_failures))

        cancel_button = QPushButton(self)
        cancel_button.setText('Cancel')

        def do_cancel():
            self.close()

        cancel_button.clicked.connect(do_cancel)

        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(ok_button)
        buttons_layout.addWidget(cancel_button)

        self.main_layout.addLayout(layout)
        self.main_layout.addLayout(buttons_layout)