class ListDialog(DwarfDialog): def __init__(self, parent=None, setup_list_cb=None, setup_list_cb_args=None, double_click_to_accept=False, checkable=False): super(ListDialog, self).__init__(parent) self.right_click_handler = None layout = QVBoxLayout(self) self.list = DwarfListView() # QListWidget() self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) if double_click_to_accept: self.list.doubleClicked.connect(self.accept) if setup_list_cb is not None: setup_list_cb(self.list, setup_list_cb_args) layout.addWidget(self.list) if checkable: buttons = QHBoxLayout() select_all = QPushButton('select all') select_all.clicked.connect(self.select_all) buttons.addWidget(select_all) unselect_all = QPushButton('unselect all') unselect_all.clicked.connect(self.unselect_all) buttons.addWidget(unselect_all) ok = QPushButton('ok') ok.clicked.connect(self.accept) buttons.addWidget(ok) cancel = QPushButton('cancel') cancel.clicked.connect(self.close) buttons.addWidget(cancel) layout.addLayout(buttons) def get_checked_items(self): ret = [] for i in range(0, self.list.count()): item = self.list.item(i) if item.checkState() == Qt.Checked: ret.append(item) return ret def select_all(self): for i in range(0, self.list.count()): item = self.list.item(i) item.setCheckState(Qt.Checked) def unselect_all(self): for i in range(0, self.list.count()): item = self.list.item(i) item.setCheckState(Qt.Unchecked) def keyPressEvent(self, event): super(ListDialog, self).keyPressEvent(event) if event.key() == Qt.Key_Return: self.accept() @staticmethod def build_and_show(setup_list_cb, setup_list_cb_args, double_click_to_accept=False, checkable=False): dialog = ListDialog(setup_list_cb=setup_list_cb, setup_list_cb_args=setup_list_cb_args, double_click_to_accept=double_click_to_accept, checkable=checkable) if dialog.list.count() > 0: result = dialog.exec_() if checkable: if result == QDialog.Accepted: checked_items = dialog.get_checked_items() else: checked_items = [] return result == QDialog.Accepted, checked_items return result == QDialog.Accepted, dialog.list.selectedItems() return None
class JavaTracePanel(QWidget): def __init__(self, app, *__args): super().__init__(app) self.app = app self.app.dwarf.onJavaTraceEvent.connect(self.on_event) self.app.dwarf.onEnumerateJavaClassesStart.connect(self.on_enumeration_start) self.app.dwarf.onEnumerateJavaClassesMatch.connect(self.on_enumeration_match) self.app.dwarf.onEnumerateJavaClassesComplete.connect(self.on_enumeration_complete) self.tracing = False self.trace_classes = [] self.trace_depth = 0 layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self._record_icon = QIcon(utils.resource_path('assets/icons/record.png')) self._pause_icon = QIcon(utils.resource_path('assets/icons/pause.png')) self._stop_icon = QIcon(utils.resource_path('assets/icons/stop.png')) self._tool_bar = QToolBar() self._tool_bar.addAction('Start', self.start_trace) self._tool_bar.addAction('Pause', self.pause_trace) self._tool_bar.addAction('Stop', self.stop_trace) self._tool_bar.addSeparator() self._entries_lbl = QLabel('Entries: 0') self._entries_lbl.setStyleSheet('color: #ef5350;') self._entries_lbl.setContentsMargins(10, 0, 10, 2) self._entries_lbl.setAttribute(Qt.WA_TranslucentBackground, True) # keep this self._entries_lbl.setAlignment(Qt.AlignRight| Qt.AlignVCenter) self._entries_lbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self._tool_bar.addWidget(self._entries_lbl) layout.addWidget(self._tool_bar) self.setup_splitter = QSplitter() self.events_list = JavaTraceView(self) self.events_list.setVisible(False) self.trace_list = DwarfListView() self.trace_list_model = QStandardItemModel(0, 1) self.trace_list_model.setHeaderData(0, Qt.Horizontal, 'Traced') self.trace_list.setModel(self.trace_list_model) self.trace_list.doubleClicked.connect(self.trace_list_double_click) self.class_list = DwarfListView() self.class_list_model = QStandardItemModel(0, 1) self.class_list_model.setHeaderData(0, Qt.Horizontal, 'Classes') self.class_list.setModel(self.class_list_model) self.class_list.setContextMenuPolicy(Qt.CustomContextMenu) self.class_list.customContextMenuRequested.connect(self.show_class_list_menu) self.class_list.doubleClicked.connect(self.class_list_double_click) self.current_class_search = '' bar = QScrollBar() bar.setFixedWidth(0) bar.setFixedHeight(0) self.trace_list.setHorizontalScrollBar(bar) bar = QScrollBar() bar.setFixedWidth(0) bar.setFixedHeight(0) self.class_list.setHorizontalScrollBar(bar) self.setup_splitter.addWidget(self.trace_list) self.setup_splitter.addWidget(self.class_list) layout.addWidget(self.setup_splitter) layout.addWidget(self.events_list) self.setLayout(layout) def class_list_double_click(self, item): item = self.class_list_model.itemFromIndex(item) try: if self.trace_classes.index(item.text()) >= 0: return except: pass self.trace_classes.append(item.text()) self.trace_list_model.appendRow([QStandardItem(item.text())]) self.trace_list_model.sort(0, Qt.AscendingOrder) def on_enumeration_start(self): self.class_list_model.setRowCount(0) def on_enumeration_match(self, java_class): try: if PREFIXED_CLASS.index(java_class) >= 0: try: if self.trace_classes.index(java_class) >= 0: return except: pass self.trace_list_model.appendRow(QStandardItem(java_class)) self.trace_classes.append(java_class) except: pass self.class_list_model.appendRow([QStandardItem(java_class)]) def on_enumeration_complete(self): self.class_list_model.sort(0, Qt.AscendingOrder) self.trace_list_model.sort(0, Qt.AscendingOrder) def on_event(self, data): trace, event, clazz, data = data if trace == 'java_trace': self.events_list.add_event( { 'event': event, 'class': clazz, 'data': data.replace(',', ', ') } ) self._entries_lbl.setText('Events: %d' % len(self.events_list.data)) def pause_trace(self): self.app.dwarf.dwarf_api('stopJavaTracer') self.tracing = False def search(self): accept, input = InputDialog.input(self.app, hint='Search', input_content=self.current_class_search, placeholder='Search something...') if accept: self.current_class_search = input.lower() for i in range(0, self.class_list.count()): try: if self.class_list.item(i).text().lower().index(self.current_class_search.lower()) >= 0: self.class_list.setRowHidden(i, False) except: self.class_list.setRowHidden(i, True) def show_class_list_menu(self, pos): menu = QMenu() search = menu.addAction('Search') action = menu.exec_(self.class_list.mapToGlobal(pos)) if action: if action == search: self.search() def start_trace(self): self.app.dwarf.dwarf_api('startJavaTracer', [self.trace_classes]) self.trace_depth = 0 self.tracing = True self.setup_splitter.setVisible(False) self.events_list.setVisible(True) def stop_trace(self): self.app.dwarf.dwarf_api('stopJavaTracer') self.tracing = False self.setup_splitter.setVisible(True) self.events_list.setVisible(False) self.events_list.clear() def trace_list_double_click(self, item): try: index = self.trace_classes.index(item.text()) except: return if index < 0: return self.trace_classes.pop(index) self.trace_list.takeItem(self.trace_list.row(item)) def keyPressEvent(self, event): if event.modifiers() & Qt.ControlModifier: if event.key() == Qt.Key_F: self.search() super(JavaTracePanel, self).keyPressEvent(event)