def __init__(self): """Initialize the application Initializes all the different parts of the application. Creates the PugdebugDebugger object, sets up the application UI, connects signals to slots. """ super(Pugdebug, self).__init__() self.debugger = PugdebugDebugger() # UI elements self.main_window = PugdebugMainWindow() self.file_browser = self.main_window.get_file_browser() self.projects_browser = self.main_window.get_projects_browser() self.document_viewer = self.main_window.get_document_viewer() self.variable_viewer = self.main_window.get_variable_viewer() self.stacktrace_viewer = self.main_window.get_stacktrace_viewer() self.breakpoint_viewer = self.main_window.get_breakpoint_viewer() self.expression_viewer = self.main_window.get_expression_viewer() self.documents = PugdebugDocuments() self.connect_signals() signal.signal(signal.SIGINT, signal.SIG_DFL) if settings.get_last_files('project/' + projects.active() + '/recent_files'): for item in settings.get_last_files('project/' + projects.active() + '/recent_files'): self.open_document(item, False)
def __set_debugger_features(self): with settings.open_group('project/' + projects.active()): max_depth = settings.value('debugger/max_depth') max_children = settings.value('debugger/max_children') max_data = settings.value('debugger/max_data') command = 'feature_set -i %d -n max_depth -v %d' % ( self.__get_transaction_id(), max_depth ) self.__send_command(command) command = 'feature_set -i %d -n max_children -v %d' % ( self.__get_transaction_id(), max_children ) self.__send_command(command) command = 'feature_set -i %d -n max_data -v %d' % ( self.__get_transaction_id(), max_data ) self.__send_command(command) return True
def __init__(self, parent=None): super().__init__(parent) model = get_instance() self.setModel(model) self.update_root_path() model.rootPathChanged.connect(self.update_root_path) model.root_path_change_failed.connect(self.update_root_path) self.header().setSectionResizeMode(QHeaderView.ResizeToContents) self.header().setStretchLastSection(False) self.setHeaderHidden(True) # Hide extra columns (Size, Type, Date Modified) self.setColumnHidden(1, True) self.setColumnHidden(2, True) self.setColumnHidden(3, True) self.activated.connect(model.activate_item) for item in settings.get_last_files('project/' + projects.active() + '/last_folders'): self.expand(model.index(item)) self.collapsed.connect(self.remove_last_folder) self.expanded.connect(self.save_last_folder)
def init_connection(self): """Init a new connection Read in the init message from xdebug and decide based on the idekey should this connection be accepted or not. Do note that it is not needed to call it from a new thread, as it is already called from a thread separate from the main application thread and thus should not block the main thread. """ idekey = settings.value('project/' + projects.active() + '/debugger/idekey') response = self.__receive_message() init_message = self.parser.parse_init_message(response) # See if the init message from xdebug is meant for us if idekey != '' and ('idekey' not in init_message or init_message['idekey'] != idekey): return False self.init_message = init_message return True
def __cut_filename(self, filename): with settings.open_group('project/' + projects.active()): path_map = settings.value('path/path_mapping') if len(path_map) > 0: path_map = path_map.rstrip('/') if filename.startswith(path_map): return '~' + filename[len(path_map):] else: root = settings.value('path/project_root') root = root.rstrip('/') if filename.startswith(root): return '~' + filename[len(root):] return filename
def __listen(self, socket_server): """Listen to new incomming connections For every accepted connection, see if it is valid and emit a signal with that new connection. Otherwise silently disregard that connection. """ with settings.open_group('project/' + projects.active()): host = settings.value('debugger/host') port_number = settings.value('debugger/port_number') try: socket_server.bind((host, port_number)) socket_server.listen(5) while self.wait_for_accept: try: sock, address = socket_server.accept() sock.settimeout(None) if sock is not None: connection = PugdebugServerConnection(sock) try: is_valid = connection.init_connection() except OSError as e: # in case the debugged program closes # the connection is_valid = False self.server_error_signal.emit( '%s (during connection initialization)' % e.strerror ) if is_valid and self.wait_for_accept: self.new_connection_established_signal.emit( connection ) else: connection.disconnect() except socket.timeout: pass except OSError as e: self.server_error_signal.emit(e.strerror) finally: socket_server.close() if not self.wait_for_accept: self.server_stopped_signal.emit()
def __get_path_mapped_to_remote(self, path): """Get a path mapped to remote Turns a path like /home/user/local/path to /var/www """ with settings.open_group('project/' + projects.active()): root_path = settings.value('path/project_root') path_map = settings.value('path/path_mapping') if len(path_map) > 0 and path.find(root_path) == 0: path_map = path_map.rstrip('/') root_path = root_path.rstrip('/') path = path[len(root_path):] path = "%s%s" % (path_map, path) return path
def handle_debugging_post_start(self): """Handle post start debugging If the code should not break at first line, run the debugger. """ logging.debug("Post start") break_at_first_line = settings.value('project/' + projects.active() + '/debugger/break_at_first_line') logging.debug("Break at first line: %s" % ('Yes' if break_at_first_line else 'No')) if not break_at_first_line: self.run_debug() else: self.step_into()
def __get_path_mapped_to_local(self, path, map_paths=True): """Get a path mapped to local Turns a path like /var/www into /home/user/local/path """ with settings.open_group('project/' + projects.active()): root_path = settings.value('path/project_root') path_map = settings.value('path/path_mapping') if (len(path_map) > 0 and map_paths is True and path.find(path_map) == 0): path_map = path_map.rstrip('/') path = path[len(path_map):] path = "%s%s" % (root_path, path) if not os.path.isfile(path): return False return path
def close_document(self, tab_index): """Close a document Get the document from the tab. Delete the document. Remove the tab. """ document_widget = self.document_viewer.get_document(tab_index) path = document_widget.get_path() logging.debug("Closing document: %s" % path) self.documents.close_document(path) document_widget.deleteLater() self.document_viewer.close_tab(tab_index) self.remove_stale_breakpoints(path) settings.remove_last_file( 'project/' + projects.active() + '/recent_files', path)
def start_listening(self): """Start listening to new incomming connections Clear the variable viewer. Clear the stacktrace viewer. Remove all line highlights. Start a debugging session. """ logging.debug("Start listening") break_at_first_line = settings.value('project/' + projects.active() + '/debugger/break_at_first_line') logging.debug("Break at first line: %s" % ('Yes' if break_at_first_line else 'No')) start_debugging = True if not break_at_first_line and len(self.breakpoints) == 0: messageBox = QMessageBox() messageBox.setText("There are no breakpoints set and the break at" " first line setting is turned off.") messageBox.setInformativeText("Are you sure you want to start" " debugging?") messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) answer = messageBox.exec_() if answer == QMessageBox.No: start_debugging = False logging.debug("Don't start debugging, no breakpoints") if start_debugging: self.variable_viewer.clear() self.stacktrace_viewer.clear() self.document_viewer.remove_line_highlights() self.debugger.start_listening() self.main_window.set_debugging_status(1)
def update_window_title(self): self.setWindowTitle("pugdebug / " + projects.active())
def open_local_document(self, path): settings.set_last_file( 'project/' + projects.active() + '/recent_files', path) return self.open_document(path, False)
def remove_last_folder(self, index): model = get_instance() settings.remove_last_file( 'project/' + projects.active() + '/last_folders', model.filePath(index))
def update_root_path(self): project_root = settings.value('project/' + projects.active() + '/path/project_root') self.setRootPath(project_root)
def exec(self): self.project_root = settings.value('project/' + projects.active() + '/path/project_root') self.file_search = PugdebugFileSearch(self, self.project_root) super(PugdebugFileSearchWindow, self).exec()