class View: def __init__(self, issues): self.json = issues.get_json() self.issues_object = issues self.issues = issues.get_issues() self.scanner_issues = issues.get_scanner_issues() self.scanner_panes = {} self.scanner_tables = {} self.is_scanner_panes = [] self.set_vuln_tree() self.set_tree() self.set_scanner_panes() self.set_pane() self.set_tsl() def set_callbacks(self, callbacks): self.callbacks = callbacks def set_helpers(self, helpers): self.helpers = helpers def get_helpers(self): return self.helpers def get_issues(self): return self.issues def get_scanner_issues(self): return self.scanner_issues def set_scanner_count(self, is_checked, issue_name, issue_param): self.issues_object.set_scanner_count(self, is_checked, issue_name, issue_param) def set_is_scanner_pane(self, scanner_pane): self.is_scanner_panes.append(scanner_pane) def get_is_scanner_pane(self, scanner_pane): for pane in self.get_is_scanner_panes(): if pane == scanner_pane: return True return False def get_is_scanner_panes(self): return self.is_scanner_panes def set_vuln_tree(self): self.vuln_tree = DefaultMutableTreeNode("Vulnerability Classes") vulns = self.json["issues"] # TODO: Sort the functionality by name and by vuln class for vuln_name in vulns: vuln = DefaultMutableTreeNode(vuln_name) self.vuln_tree.add(vuln) parameters = self.json["issues"][vuln_name]["params"] for parameter in parameters: param_node = DefaultMutableTreeNode(parameter) vuln.add(param_node) # Creates a JTree object from the checklist def set_tree(self): self.tree = JTree(self.vuln_tree) self.tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ) def get_tree(self): return self.tree # Creates the tabs dynamically using data from the JSON file def set_scanner_panes(self): issues = self.issues for issue in issues: issue_name = issue["name"] issue_param = issue["param"] key = issue_name + "." + issue_param top_pane = self.create_request_list_pane(issue_name) bottom_pane = self.create_tabbed_pane() scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT, top_pane, bottom_pane) self.scanner_panes[key] = scanner_pane def get_scanner_panes(self): return self.scanner_panes def create_request_list_pane(self, issue_name): request_list_pane = JScrollPane() return request_list_pane # Creates a JTabbedPane for each vulnerability per functionality def create_tabbed_pane(self): tabbed_pane = JTabbedPane() tabbed_pane.add("Advisory", JScrollPane()) tabbed_pane.add("Request", JScrollPane()) tabbed_pane.add("Response", JScrollPane()) self.tabbed_pane = tabbed_pane return tabbed_pane def set_tsl(self): tsl = TSL(self) self.tree.addTreeSelectionListener(tsl) return def set_pane(self): status = JTextArea() status.setLineWrap(True) status.setText("Nothing selected") self.status = status request_list_pane = JScrollPane() scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT, request_list_pane, self.tabbed_pane ) self.pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(self.tree), scanner_pane ) self.pane.setDividerLocation(310) self.pane.getLeftComponent().setMinimumSize(Dimension(310, 300)) def get_pane(self): return self.pane def set_scanner_table(self, scanner_pane, scanner_table): self.scanner_tables[scanner_pane] = scanner_table def get_scanner_table(self, scanner_pane): return self.scanner_tables[scanner_pane] def set_scanner_pane(self, scanner_pane): request_table_pane = scanner_pane.getTopComponent() scanner_table = self.get_scanner_table(scanner_pane) request_table_pane.getViewport().setView(scanner_table) request_table_pane.revalidate() request_table_pane.repaint() def create_scanner_pane(self, scanner_pane, issue_name, issue_param): scanner_issues = self.get_scanner_issues() request_table_pane = scanner_pane.getTopComponent() scanner_table_model = ScannerTableModel() scanner_table_model.addColumn("Checked") scanner_table_model.addColumn("Host") scanner_table_model.addColumn("Path") # Search all issues for the correct issue. Once found, add it into # the scanner table model to be showed in the UI. for scanner_issue in scanner_issues: is_same_name = scanner_issue.getIssueName() == issue_name is_same_param = scanner_issue.getParameter() == issue_param is_same_issue = is_same_name and is_same_param if is_same_issue: scanner_table_model.addRow([ False, scanner_issue.getHttpService().getHost(), scanner_issue.getUrl() ]) scanner_table = JTable(scanner_table_model) scanner_table.getColumnModel().getColumn(0).setCellEditor(DefaultCellEditor(JCheckBox())) scanner_table.putClientProperty("terminateEditOnFocusLost", True) scanner_table_listener = ScannerTableListener(self, scanner_table, issue_name, issue_param) scanner_table_model.addTableModelListener(scanner_table_listener) scanner_table_list_listener = IssueListener(self, scanner_table, scanner_pane, issue_name, issue_param) scanner_table.getSelectionModel().addListSelectionListener(scanner_table_list_listener) self.set_scanner_table(scanner_pane, scanner_table) request_table_pane.getViewport().setView(scanner_table) request_table_pane.revalidate() request_table_pane.repaint() def set_tabbed_pane(self, scanner_pane, request_list, issue_url, issue_name, issue_param): tabbed_pane = scanner_pane.getBottomComponent() scanner_issues = self.get_scanner_issues() for scanner_issue in scanner_issues: is_same_url = scanner_issue.getUrl() == issue_url is_same_name = scanner_issue.getIssueName() == issue_name is_same_param = scanner_issue.getParameter() == issue_param is_same_issue = is_same_url and is_same_name and is_same_param if is_same_issue: current_issue = scanner_issue self.set_context_menu(request_list, scanner_issue) break advisory_tab_pane = self.set_advisory_tab_pane(current_issue) tabbed_pane.setComponentAt(0, advisory_tab_pane) request_tab_pane = self.set_request_tab_pane(current_issue) tabbed_pane.setComponentAt(1, request_tab_pane) response_tab_pane = self.set_response_tab_pane(current_issue) tabbed_pane.setComponentAt(2, response_tab_pane) def set_advisory_tab_pane(self, scanner_issue): advisory_pane = JEditorPane() advisory_pane.setEditable(False) advisory_pane.setEnabled(True) advisory_pane.setContentType("text/html") link_listener = LinkListener() advisory_pane.addHyperlinkListener(link_listener) advisory_pane.setText("<html>" + "<b>Location</b>: " + scanner_issue.getUrl() + "<br><br>" + scanner_issue.getIssueDetail() + "</html>" ) # Set a context menu self.set_context_menu(advisory_pane, scanner_issue) return JScrollPane(advisory_pane) def set_request_tab_pane(self, scanner_issue): raw_request = scanner_issue.getRequestResponse().getRequest() request_body = StringUtil.fromBytes(raw_request) request_body = request_body.encode("utf-8") request_tab_textarea = JTextArea(request_body) request_tab_textarea.setLineWrap(True) # Set a context menu self.set_context_menu(request_tab_textarea, scanner_issue) return JScrollPane(request_tab_textarea) def set_response_tab_pane(self, scanner_issue): raw_response = scanner_issue.getRequestResponse().getResponse() response_body = StringUtil.fromBytes(raw_response) response_body = response_body.encode("utf-8") response_tab_textarea = JTextArea(response_body) response_tab_textarea.setLineWrap(True) # Set a context menu self.set_context_menu(response_tab_textarea, scanner_issue) return JScrollPane(response_tab_textarea) # Pass scanner_issue as argument def set_context_menu(self, component, scanner_issue): self.context_menu = JPopupMenu() repeater = JMenuItem("Send to Repeater") repeater.addActionListener(PopupListener(scanner_issue, self.callbacks)) intruder = JMenuItem("Send to Intruder") intruder.addActionListener(PopupListener(scanner_issue, self.callbacks)) hunt = JMenuItem("Send to HUNT") self.context_menu.add(repeater) self.context_menu.add(intruder) context_menu_listener = ContextMenuListener(component, self.context_menu) component.addMouseListener(context_menu_listener) def get_context_menu(self): return self.context_menu
class View: def __init__(self): self.data = Data() self.checklist = self.data.get_checklist() self.issues = self.data.get_issues() self.set_checklist_tree() self.set_tree() self.set_pane() self.set_tabbed_panes() self.set_settings() self.set_tsl() def set_checklist(self, file_name): self.data.set_checklist(file_name) self.checklist = self.data.get_checklist() def get_checklist(self): return self.checklist def get_issues(self): return self.issues # TODO: Create the checklist dynamically for all nodes based on JSON structure # Creates a DefaultMutableTreeNode using the JSON file data def set_checklist_tree(self): self.checklist_tree = DefaultMutableTreeNode("HUNT - Methodology") for item in self.checklist: node = DefaultMutableTreeNode(item) self.checklist_tree.add(node) is_functionality = node.toString() == "Functionality" if is_functionality: functionality_node = node functionality = self.checklist["Functionality"] # TODO: Sort the functionality by name and by test name for functionality_name in functionality: tests = functionality[functionality_name]["tests"] node = DefaultMutableTreeNode(functionality_name) for test_name in tests: node.add(DefaultMutableTreeNode(test_name)) functionality_node.add(node) def get_checklist_tree(self): return self.checklist_tree # Creates a JTree object from the checklist def set_tree(self): self.tree = JTree(self.checklist_tree) self.tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION) def get_tree(self): return self.tree # TODO: Change to briefcase icon for brief, P1-P5 icons for vulns, # bullseye icon for Targets, etc # Create a JSplitPlane with a JTree to the left and JTabbedPane to right def set_pane(self): status = JTextArea() status.setLineWrap(True) status.setText("Nothing selected") self.status = status self.pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(self.tree), JTabbedPane()) self.pane.setDividerLocation(310) self.pane.getLeftComponent().setMinimumSize(Dimension(310, 300)) def get_pane(self): return self.pane # Creates the tabs dynamically using data from the JSON file def set_tabbed_panes(self): functionality = self.checklist["Functionality"] self.tabbed_panes = {} for functionality_name in functionality: tests = functionality[functionality_name]["tests"] for test_name in tests: key = functionality_name + "." + test_name tabbed_pane = self.set_tabbed_pane(functionality_name, test_name) self.tabbed_panes[key] = self.tabbed_pane def get_tabbed_panes(self): return self.tabbed_panes # Creates a JTabbedPane for each vulnerability per functionality def set_tabbed_pane(self, functionality_name, test_name): description_tab = self.set_description_tab(functionality_name, test_name) bugs_tab = self.set_bugs_tab() resources_tab = self.set_resource_tab(functionality_name, test_name) notes_tab = self.set_notes_tab() self.tabbed_pane = JTabbedPane() self.tabbed_pane.add("Description", description_tab) self.tabbed_pane.add("Bugs", bugs_tab) self.tabbed_pane.add("Resources", resources_tab) self.tabbed_pane.add("Notes", notes_tab) # Creates the description panel def set_description_tab(self, fn, vn): description_text = str( self.checklist["Functionality"][fn]["tests"][vn]["description"]) description_textarea = JTextArea() description_textarea.setLineWrap(True) description_textarea.setText(description_text) description_panel = JScrollPane(description_textarea) return description_panel # TODO: Add functionality to remove tabs # Creates the bugs panel def set_bugs_tab(self): bugs_tab = JTabbedPane() return bugs_tab # Creates the resources panel def set_resource_tab(self, fn, vn): resource_urls = self.checklist["Functionality"][fn]["tests"][vn][ "resources"] resource_text = "" for url in resource_urls: resource_text = resource_text + str(url) + "\n" resource_textarea = JTextArea() resource_textarea.setLineWrap(True) resource_textarea.setWrapStyleWord(True) resource_textarea.setText(resource_text) resources_panel = JScrollPane(resource_textarea) return resources_panel def set_notes_tab(self): notes_textarea = JTextArea() return notes_textarea def set_tsl(self): self.tsl = TSL(self) self.tree.addTreeSelectionListener(self.tsl) return def get_tsl(self): return self.tsl def set_settings(self): self.settings = JPanel() layout = GroupLayout(self.settings) self.settings.setLayout(layout) layout.setAutoCreateGaps(True) load_file_button = JButton("Load JSON File") load_file_button.setActionCommand("load") load_file_button.addActionListener( SettingsAction(self, load_file_button, None)) save_file_button = JButton("Save JSON File") save_file_button.setActionCommand("save") save_file_button.addActionListener( SettingsAction(None, save_file_button, self.tabbed_panes)) horizontal_group1 = layout.createParallelGroup( GroupLayout.Alignment.LEADING) horizontal_group1.addComponent(load_file_button) horizontal_group1.addComponent(save_file_button) horizontal_group = layout.createSequentialGroup() horizontal_group.addGroup(horizontal_group1) layout.setHorizontalGroup(horizontal_group) vertical_group1 = layout.createParallelGroup( GroupLayout.Alignment.BASELINE) vertical_group1.addComponent(load_file_button) vertical_group2 = layout.createParallelGroup( GroupLayout.Alignment.BASELINE) vertical_group2.addComponent(save_file_button) vertical_group = layout.createSequentialGroup() vertical_group.addGroup(vertical_group1) vertical_group.addGroup(vertical_group2) layout.setVerticalGroup(vertical_group) def get_settings(self): return self.settings def set_request_tab_pane(self, request_response): raw_request = request_response.getRequest() request_body = StringUtil.fromBytes(raw_request) request_body = request_body.encode("utf-8") request_tab_textarea = JTextArea(request_body) request_tab_textarea.setLineWrap(True) return JScrollPane(request_tab_textarea) def set_response_tab_pane(self, request_response): raw_response = request_response.getResponse() response_body = StringUtil.fromBytes(raw_response) response_body = response_body.encode("utf-8") response_tab_textarea = JTextArea(response_body) response_tab_textarea.setLineWrap(True) return JScrollPane(response_tab_textarea) def set_bugs_tabbed_pane(self, request_tab, response_tab): bugs_tabbed_pane = JTabbedPane() bugs_tabbed_pane.add("Request", request_tab) bugs_tabbed_pane.add("Response", response_tab) return bugs_tabbed_pane
class View: def __init__(self, issues): self.json = issues.get_json() self.issues_object = issues self.issues = issues.get_issues() self.scanner_issues = issues.get_scanner_issues() self.scanner_panes = {} self.scanner_table_models = {} self.scanner_tables = {} self.is_scanner_panes = [] self.set_vuln_tree() self.set_tree() self.set_scanner_table_models() self.set_scanner_panes() self.set_pane() self.set_settings() self.set_tsl() def get_issues_object(self): return self.issues_object def set_callbacks(self, callbacks): self.callbacks = callbacks def set_helpers(self, helpers): self.helpers = helpers def get_helpers(self): return self.helpers def get_issues(self): return self.issues def get_scanner_issues(self): return self.scanner_issues def set_is_scanner_pane(self, scanner_pane): self.is_scanner_panes.append(scanner_pane) def get_is_scanner_pane(self, scanner_pane): for pane in self.get_is_scanner_panes(): if pane == scanner_pane: return True return False def get_is_scanner_panes(self): return self.is_scanner_panes def set_vuln_tree(self): self.vuln_tree = DefaultMutableTreeNode("HUNT Scanner") vulns = self.json["issues"] # TODO: Sort the functionality by name and by vuln class for vuln_name in sorted(vulns): vuln = DefaultMutableTreeNode(vuln_name) self.vuln_tree.add(vuln) parameters = self.json["issues"][vuln_name]["params"] for parameter in sorted(parameters): param_node = DefaultMutableTreeNode(parameter) vuln.add(param_node) self.vuln_tree.add(DefaultMutableTreeNode("Settings")) # Creates a JTree object from the checklist def set_tree(self): self.tree = JTree(self.vuln_tree) self.tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION) def get_tree(self): return self.tree def set_scanner_table_models(self): issues = self.issues for issue in issues: issue_name = issue["name"] issue_param = issue["param"] self.create_scanner_table_model(issue_name, issue_param) # Creates the tabs dynamically using data from the JSON file def set_scanner_panes(self): for issue in self.issues: issue_name = issue["name"] issue_param = issue["param"] key = issue_name + "." + issue_param top_pane = self.create_request_list_pane(issue_name) bottom_pane = self.create_tabbed_pane() scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT, top_pane, bottom_pane) self.scanner_panes[key] = scanner_pane def get_scanner_panes(self): return self.scanner_panes def create_request_list_pane(self, issue_name): request_list_pane = JScrollPane() return request_list_pane # Creates a JTabbedPane for each vulnerability per functionality def create_tabbed_pane(self): tabbed_pane = JTabbedPane() tabbed_pane.add("Advisory", JScrollPane()) tabbed_pane.add("Request", JScrollPane()) tabbed_pane.add("Response", JScrollPane()) self.tabbed_pane = tabbed_pane return tabbed_pane def get_settings(self): return self.settings def set_settings(self): self.settings = JPanel() layout = GroupLayout(self.settings) self.settings.setLayout(layout) layout.setAutoCreateGaps(True) load_file_button = JButton("Load JSON File") load_file_button.setActionCommand("load") load_file_button.addActionListener( SettingsAction(self, load_file_button, None)) save_file_button = JButton("Save JSON File") save_file_button.setActionCommand("save") save_file_button.addActionListener( SettingsAction(self, save_file_button, self.scanner_panes)) horizontal_group1 = layout.createParallelGroup( GroupLayout.Alignment.LEADING) horizontal_group1.addComponent(load_file_button) horizontal_group1.addComponent(save_file_button) horizontal_group = layout.createSequentialGroup() horizontal_group.addGroup(horizontal_group1) layout.setHorizontalGroup(horizontal_group) vertical_group1 = layout.createParallelGroup( GroupLayout.Alignment.BASELINE) vertical_group1.addComponent(load_file_button) vertical_group2 = layout.createParallelGroup( GroupLayout.Alignment.BASELINE) vertical_group2.addComponent(save_file_button) vertical_group = layout.createSequentialGroup() vertical_group.addGroup(vertical_group1) vertical_group.addGroup(vertical_group2) layout.setVerticalGroup(vertical_group) def set_tsl(self): tsl = TSL(self) self.tree.addTreeSelectionListener(tsl) return def set_pane(self): status = JTextArea() status.setLineWrap(True) status.setText("Nothing selected") self.status = status request_list_pane = JScrollPane() scanner_pane = JSplitPane(JSplitPane.VERTICAL_SPLIT, request_list_pane, self.tabbed_pane) self.pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(self.tree), scanner_pane) self.pane.setDividerLocation(310) self.pane.getLeftComponent().setMinimumSize(Dimension(310, 300)) def get_pane(self): return self.pane # TODO: Move all scanner table functions into its own ScannerTable class # as well as ScannerTableModel for all scanner table model functions def create_scanner_table_model(self, issue_name, issue_param): key = issue_name + "." + issue_param is_model_exists = key in self.scanner_table_models if is_model_exists: return scanner_table_model = ScannerTableModel() scanner_table_model.addColumn("") scanner_table_model.addColumn("Parameter") scanner_table_model.addColumn("Host") scanner_table_model.addColumn("Path") scanner_table_model.addColumn("ID") self.scanner_table_models[key] = scanner_table_model def set_scanner_table_model(self, scanner_issue, issue_name, issue_param, vuln_param): key = issue_name + "." + vuln_param scanner_issue_id = str( scanner_issue.getRequestResponse()).split("@")[1] scanner_table_model = self.scanner_table_models[key] # Using the addRow() method requires that the data type being passed to be of type # Vector() or Object(). Passing a Python object of type list in addRow causes a type # conversion error of sorts which presents as an ArrayOutOfBoundsException. Therefore, # row is an instantiation of Object() to avoid this error. row = Object() row = [ False, issue_param, scanner_issue.getHttpService().getHost(), scanner_issue.getPath(), scanner_issue_id ] scanner_table_model.addRow(row) # Wait for ScannerTableModel to update as to not get an ArrayOutOfBoundsException. Thread.sleep(500) scanner_table_model.fireTableDataChanged() scanner_table_model.fireTableStructureChanged() def get_scanner_table_model(self, issue_name, issue_param): key = issue_name + "." + issue_param return self.scanner_table_models[key] def set_scanner_pane(self, scanner_pane, issue_name, issue_param): key = issue_name + "." + issue_param request_table_pane = scanner_pane.getTopComponent() if key in self.scanner_tables: scanner_table = self.scanner_tables[key] else: scanner_table = self.create_scanner_table(scanner_pane, issue_name, issue_param) self.scanner_tables[key] = scanner_table request_table_pane.getViewport().setView(scanner_table) request_table_pane.revalidate() request_table_pane.repaint() def create_scanner_table(self, scanner_pane, issue_name, issue_param): scanner_table_model = self.get_scanner_table_model( issue_name, issue_param) scanner_table = JTable(scanner_table_model) scanner_table.getColumnModel().getColumn(0).setMaxWidth(10) scanner_table.putClientProperty("terminateEditOnFocusLost", True) scanner_table_listener = ScannerTableListener(self, scanner_table, issue_name, issue_param) scanner_table_model.addTableModelListener(scanner_table_listener) scanner_table_list_listener = IssueListener(self, scanner_table, scanner_pane, issue_name, issue_param) scanner_table.getSelectionModel().addListSelectionListener( scanner_table_list_listener) return scanner_table # Takes into account if there are more than one scanner issues that share the same hostname, path, name, param, and id def set_tabbed_pane(self, scanner_pane, request_list, issue_hostname, issue_path, issue_name, issue_param, scanner_issue_id): tabbed_pane = scanner_pane.getBottomComponent() scanner_issues = self.get_scanner_issues() current_issue = self.set_current_issue(scanner_issues, issue_hostname, issue_path, issue_name, issue_param, scanner_issue_id) advisory_tab_pane = self.set_advisory_tab_pane(current_issue) tabbed_pane.setComponentAt(0, advisory_tab_pane) request_tab_pane = self.set_request_tab_pane(current_issue) tabbed_pane.setComponentAt(1, request_tab_pane) response_tab_pane = self.set_response_tab_pane(current_issue) tabbed_pane.setComponentAt(2, response_tab_pane) def set_current_issue(self, scanner_issues, issue_hostname, issue_path, issue_name, issue_param, scanner_issue_id): for scanner_issue in scanner_issues: is_same_hostname = scanner_issue.getHostname() == issue_hostname is_same_path = scanner_issue.getPath() == issue_path is_same_name = scanner_issue.getIssueName() == issue_name is_same_param = scanner_issue.getParameter() == issue_param is_same_id = str(scanner_issue.getRequestResponse()).split( "@")[1] == scanner_issue_id is_same_issue = is_same_hostname and is_same_path and is_same_name and is_same_param and is_same_id if is_same_issue: return scanner_issue def set_advisory_tab_pane(self, scanner_issue): advisory_pane = JEditorPane() advisory_pane.setEditable(False) advisory_pane.setEnabled(True) advisory_pane.setContentType("text/html") link_listener = LinkListener() advisory_pane.addHyperlinkListener(link_listener) advisory = "<html><b>Location</b>: {}<br><br>{}</html>" advisory_pane.setText( advisory.format(scanner_issue.getUrl().encode("utf-8"), scanner_issue.getIssueDetail())) return JScrollPane(advisory_pane) def set_request_tab_pane(self, scanner_issue): request_response = scanner_issue.getRequestResponse() controller = MessageController(request_response) message_editor = self.callbacks.createMessageEditor(controller, True) message_editor.setMessage(request_response.getRequest(), True) component = message_editor.getComponent() return component def set_response_tab_pane(self, scanner_issue): request_response = scanner_issue.getRequestResponse() controller = MessageController(request_response) message_editor = self.callbacks.createMessageEditor(controller, True) message_editor.setMessage(request_response.getResponse(), False) component = message_editor.getComponent() return component def traverse_tree(self, tree, model, issue_name, issue_param, issue_count, total_count): root = model.getRoot() count = int(root.getChildCount()) traverse = {} for i in range(count): node = model.getChild(root, i) traverse["node"] = node tree_issue_name = node.toString() is_issue_name = re.search(issue_name, tree_issue_name) if is_issue_name: child_count = node.getChildCount() for j in range(child_count): child = node.getChildAt(j) traverse["child"] = child tree_param_name = child.toString() is_param_name = re.search(issue_param, tree_param_name) if is_param_name: traverse["param_text"] = issue_param + " (" + str( issue_count) + ")" break traverse["issue_text"] = issue_name + " (" + str( total_count) + ")" break return traverse def set_scanner_count(self, issue_name, issue_param, issue_count, total_count): tree = self.get_tree() model = tree.getModel() traverse = self.traverse_tree(tree, model, issue_name, issue_param, issue_count, total_count) node = traverse["node"] child = traverse["child"] child.setUserObject(traverse["param_text"]) model.nodeChanged(child) model.reload(node) node.setUserObject(traverse["issue_text"]) model.nodeChanged(node) model.reload(node)