75 # add the viewer showing the connected debug backends |
75 # add the viewer showing the connected debug backends |
76 self.__debuggersWidget = QWidget() |
76 self.__debuggersWidget = QWidget() |
77 self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget) |
77 self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget) |
78 self.__debuggersLayout.setContentsMargins(0, 0, 0, 0) |
78 self.__debuggersLayout.setContentsMargins(0, 0, 0, 0) |
79 self.__debuggersLayout.addWidget(QLabel(self.tr("Debuggers:"))) |
79 self.__debuggersLayout.addWidget(QLabel(self.tr("Debuggers:"))) |
80 self.__debuggersCombo = QComboBox(self) |
80 self.__debuggersList = QTreeWidget() |
81 self.__debuggersCombo.setSizePolicy( |
81 self.__debuggersList.setHeaderLabels( |
82 QSizePolicy.Expanding, QSizePolicy.Fixed) |
82 [self.tr("ID"), self.tr("State"), ""]) |
83 self.__debuggersLayout.addWidget(self.__debuggersCombo) |
83 self.__debuggersList.header().setStretchLastSection(True) |
|
84 self.__debuggersList.setSortingEnabled(True) |
|
85 self.__debuggersList.setRootIsDecorated(False) |
|
86 self.__debuggersList.setAlternatingRowColors(True) |
|
87 self.__debuggersLayout.addWidget(self.__debuggersList) |
84 self.__mainSplitter.addWidget(self.__debuggersWidget) |
88 self.__mainSplitter.addWidget(self.__debuggersWidget) |
85 |
89 |
86 self.__debuggersCombo.currentIndexChanged[str].connect( |
90 self.__debuggersList.currentItemChanged.connect( |
87 self.__debuggerSelected) |
91 self.__debuggerSelected) |
88 |
92 |
89 # add the tab widget containing various debug related views |
93 # add the tab widget containing various debug related views |
90 self.__tabWidget = E5TabWidget() |
94 self.__tabWidget = E5TabWidget() |
91 self.__mainSplitter.addWidget(self.__tabWidget) |
95 self.__mainSplitter.addWidget(self.__tabWidget) |
262 self.__threadWidgetLayout.addWidget(QLabel(self.tr("Threads:"))) |
266 self.__threadWidgetLayout.addWidget(QLabel(self.tr("Threads:"))) |
263 self.__threadList = QTreeWidget() |
267 self.__threadList = QTreeWidget() |
264 self.__threadList.setHeaderLabels( |
268 self.__threadList.setHeaderLabels( |
265 [self.tr("Name"), self.tr("State"), ""]) |
269 [self.tr("Name"), self.tr("State"), ""]) |
266 self.__threadList.setSortingEnabled(True) |
270 self.__threadList.setSortingEnabled(True) |
|
271 self.__threadList.setRootIsDecorated(False) |
|
272 self.__threadList.setAlternatingRowColors(True) |
267 self.__threadWidgetLayout.addWidget(self.__threadList) |
273 self.__threadWidgetLayout.addWidget(self.__threadList) |
268 self.__mainSplitter.addWidget(self.__threadWidget) |
274 self.__mainSplitter.addWidget(self.__threadWidget) |
269 |
275 |
270 self.__doThreadListUpdate = True |
276 self.__doThreadListUpdate = True |
271 |
277 |
340 self.currentStack = None |
346 self.currentStack = None |
341 self.stackComboBox.clear() |
347 self.stackComboBox.clear() |
342 self.__threadList.clear() |
348 self.__threadList.clear() |
343 self.__tabWidget.setCurrentWidget(self.glvWidget) |
349 self.__tabWidget.setCurrentWidget(self.glvWidget) |
344 self.breakpointViewer.handleResetUI() |
350 self.breakpointViewer.handleResetUI() |
345 self.__debuggersCombo.clear() |
351 self.__debuggersList.clear() |
346 self.disassemblyViewer.clear() |
352 self.disassemblyViewer.clear() |
347 |
353 |
348 def initCallStackViewer(self, projectMode): |
354 def initCallStackViewer(self, projectMode): |
349 """ |
355 """ |
350 Public method to initialize the call stack viewer. |
356 Public method to initialize the call stack viewer. |
422 line number, function name, formatted argument/values list) |
428 line number, function name, formatted argument/values list) |
423 @type list of tuples of (str, str, str, str) |
429 @type list of tuples of (str, str, str, str) |
424 @param debuggerId ID of the debugger backend |
430 @param debuggerId ID of the debugger backend |
425 @type str |
431 @type str |
426 """ |
432 """ |
427 if debuggerId == self.__debuggersCombo.currentText(): |
433 if debuggerId == self.getSelectedDebuggerId(): |
428 block = self.stackComboBox.blockSignals(True) |
434 block = self.stackComboBox.blockSignals(True) |
429 self.framenr = 0 |
435 self.framenr = 0 |
430 self.stackComboBox.clear() |
436 self.stackComboBox.clear() |
431 self.currentStack = stack |
437 self.currentStack = stack |
432 self.sourceButton.setEnabled(len(stack) > 0) |
438 self.sourceButton.setEnabled(len(stack) > 0) |
447 @param debuggerId ID of the debugger backend |
453 @param debuggerId ID of the debugger backend |
448 @type str |
454 @type str |
449 """ |
455 """ |
450 self.__setDebuggerIconAndState(debuggerId, "break", "broken") |
456 self.__setDebuggerIconAndState(debuggerId, "break", "broken") |
451 if debuggerId != self.getSelectedDebuggerId(): |
457 if debuggerId != self.getSelectedDebuggerId(): |
452 self.__debuggersCombo.setCurrentText(debuggerId) |
458 self.__setCurrentDebugger(debuggerId) |
453 |
459 |
454 @pyqtSlot(str, int, str, bool, str) |
460 @pyqtSlot(str, int, str, bool, str) |
455 def __clientExit(self, program, status, message, quiet, debuggerId): |
461 def __clientExit(self, program, status, message, quiet, debuggerId): |
456 """ |
462 """ |
457 Private method to handle the debugged program terminating. |
463 Private method to handle the debugged program terminating. |
475 self.setLocalsFilter() |
481 self.setLocalsFilter() |
476 self.sourceButton.setEnabled(False) |
482 self.sourceButton.setEnabled(False) |
477 self.currentStack = None |
483 self.currentStack = None |
478 self.stackComboBox.clear() |
484 self.stackComboBox.clear() |
479 self.__threadList.clear() |
485 self.__threadList.clear() |
480 index = self.__debuggersCombo.findText(debuggerId, Qt.MatchExactly) |
486 self.__removeDebugger(debuggerId) |
481 self.__debuggersCombo.removeItem(index) |
|
482 |
487 |
483 def __clientSyntaxError(self, message, filename, lineNo, characterNo, |
488 def __clientSyntaxError(self, message, filename, lineNo, characterNo, |
484 debuggerId): |
489 debuggerId): |
485 """ |
490 """ |
486 Private method to handle a syntax error in the debugged program. |
491 Private method to handle a syntax error in the debugged program. |
616 @param debuggerId ID of the debugger backend |
621 @param debuggerId ID of the debugger backend |
617 @type str |
622 @type str |
618 """ |
623 """ |
619 debugStatus = -1 # i.e. running |
624 debugStatus = -1 # i.e. running |
620 |
625 |
621 if debuggerId == self.__debuggersCombo.currentText(): |
626 if debuggerId == self.getSelectedDebuggerId(): |
622 citm = None |
627 citm = None |
623 |
628 |
624 self.__threadList.clear() |
629 self.__threadList.clear() |
625 for thread in threadList: |
630 for thread in threadList: |
626 if thread.get('except', False): |
631 if thread.get('except', False): |
689 @param frameNo frame number (index) of the selected entry (integer) |
694 @param frameNo frame number (index) of the selected entry (integer) |
690 """ |
695 """ |
691 if frameNo >= 0: |
696 if frameNo >= 0: |
692 self.stackComboBox.setCurrentIndex(frameNo) |
697 self.stackComboBox.setCurrentIndex(frameNo) |
693 |
698 |
694 def __debuggerSelected(self, debuggerId): |
699 def __debuggerSelected(self, current, previous): |
695 """ |
700 """ |
696 Private slot to handle the selection of a debugger backend ID. |
701 Private slot to handle the selection of a debugger backend in the |
697 |
702 debuggers list. |
698 @param debuggerId ID of the selected debugger backend |
703 |
699 @type str |
704 @param current reference to the new current item |
700 """ |
705 @type QTreeWidgetItem |
|
706 @param previous reference to the previous current item |
|
707 @type QTreeWidgetItem |
|
708 """ |
|
709 if current is not None: |
|
710 debuggerId = current.text(0) |
|
711 else: |
|
712 debuggerId = "" |
701 if debuggerId: |
713 if debuggerId: |
702 self.globalsViewer.handleResetUI() |
714 self.globalsViewer.handleResetUI() |
703 self.localsViewer.handleResetUI() |
715 self.localsViewer.handleResetUI() |
704 self.currentStack = None |
716 self.currentStack = None |
705 self.stackComboBox.clear() |
717 self.stackComboBox.clear() |
716 Private slot to receive the ID of a newly connected debugger backend. |
728 Private slot to receive the ID of a newly connected debugger backend. |
717 |
729 |
718 @param debuggerId ID of a newly connected debugger backend |
730 @param debuggerId ID of a newly connected debugger backend |
719 @type str |
731 @type str |
720 """ |
732 """ |
721 self.__debuggersCombo.addItem(debuggerId) |
733 itm = QTreeWidgetItem(self.__debuggersList, [debuggerId]) |
722 self.debugUI.showNotification( |
734 self.debugUI.showNotification( |
723 self.tr("<p>Debugger with ID <b>{0}</b> has been connected.") |
735 self.tr("<p>Debugger with ID <b>{0}</b> has been connected.") |
724 .format(debuggerId)) |
736 .format(debuggerId)) |
|
737 |
|
738 self.__debuggersList.header().resizeSections( |
|
739 QHeaderView.ResizeToContents) |
|
740 |
|
741 if self.__debuggersList.topLevelItemCount() == 1: |
|
742 # it is the only item, select it as the current one |
|
743 self.__debuggersList.setCurrentItem(itm) |
|
744 |
|
745 def __setCurrentDebugger(self, debuggerId): |
|
746 """ |
|
747 Private method to set the current debugger based on the given ID. |
|
748 |
|
749 @param debuggerId ID of the debugger to set as current debugger |
|
750 @type str |
|
751 """ |
|
752 foundItems = self.__debuggersList.findItems(debuggerId, |
|
753 Qt.MatchExactly) |
|
754 if foundItems: |
|
755 self.__debuggersList.setCurrentItem(foundItems[0]) |
725 |
756 |
726 def getSelectedDebuggerId(self): |
757 def getSelectedDebuggerId(self): |
727 """ |
758 """ |
728 Public method to get the currently selected debugger ID. |
759 Public method to get the currently selected debugger ID. |
729 |
760 |
730 @return selected debugger ID |
761 @return selected debugger ID |
731 @rtype str |
762 @rtype str |
732 """ |
763 """ |
733 return self.__debuggersCombo.currentText() |
764 itm = self.__debuggersList.currentItem() |
|
765 if itm: |
|
766 return itm.text(0) |
|
767 else: |
|
768 return "" |
734 |
769 |
735 def getSelectedDebuggerState(self): |
770 def getSelectedDebuggerState(self): |
736 """ |
771 """ |
737 Public method to get the currently selected debugger's state. |
772 Public method to get the currently selected debugger's state. |
738 |
773 |
739 @return selected debugger's state (broken, exception, running) |
774 @return selected debugger's state (broken, exception, running) |
740 @rtype str |
775 @rtype str |
741 """ |
776 """ |
742 return self.__debuggersCombo.currentData() |
777 itm = self.__debuggersList.currentItem() |
|
778 if itm: |
|
779 return itm.data(0, Qt.UserRole) |
|
780 else: |
|
781 return "" |
743 |
782 |
744 def __setDebuggerIconAndState(self, debuggerId, iconName, state): |
783 def __setDebuggerIconAndState(self, debuggerId, iconName, state): |
745 """ |
784 """ |
746 Private method to set the icon for a specific debugger ID. |
785 Private method to set the icon for a specific debugger ID. |
747 |
786 |
751 @param iconName name of the icon to be used |
790 @param iconName name of the icon to be used |
752 @type str |
791 @type str |
753 @param state state of the debugger (broken, exception, running) |
792 @param state state of the debugger (broken, exception, running) |
754 @type str |
793 @type str |
755 """ |
794 """ |
|
795 debuggerItem = None |
756 if debuggerId: |
796 if debuggerId: |
757 index = self.__debuggersCombo.findText(debuggerId, Qt.MatchExactly) |
797 foundItems = self.__debuggersList.findItems( |
758 else: |
798 debuggerId, Qt.MatchExactly) |
759 index = self.__debuggersCombo.currentIndex() |
799 if foundItems: |
760 if index >= 0: |
800 debuggerItem = foundItems[0] |
761 self.__debuggersCombo.setItemIcon( |
801 if debuggerItem is None: |
762 index, UI.PixmapCache.getIcon(iconName)) |
802 debuggerItem = self.__debuggersList.currentItem() |
763 self.__debuggersCombo.setItemData(index, state) |
803 if debuggerItem is not None: |
|
804 debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName)) |
|
805 debuggerItem.setData(0, Qt.UserRole, state) |
|
806 if state == "broken": |
|
807 debuggerItem.setText(1, self.tr("waiting at breakpoint")) |
|
808 elif state == "exception": |
|
809 debuggerItem.setText(1, self.tr("waiting at exception")) |
|
810 elif state == "running": |
|
811 debuggerItem.setText(1, self.tr("running")) |
|
812 else: |
|
813 debuggerItem.setText( |
|
814 1, self.tr("unknown state ({0})").format(state)) |
|
815 |
|
816 self.__debuggersList.header().resizeSections( |
|
817 QHeaderView.ResizeToContents) |
|
818 |
|
819 def __removeDebugger(self, debuggerId): |
|
820 """ |
|
821 Private method to remove a debugger given its ID. |
|
822 |
|
823 @param debuggerId ID of the debugger to be removed from the list |
|
824 @type str |
|
825 """ |
|
826 foundItems = self.__debuggersList.findItems( |
|
827 debuggerId, Qt.MatchExactly) |
|
828 if foundItems: |
|
829 index = self.__debuggersList.indexOfTopLevelItem(foundItems[0]) |
|
830 itm = self.__debuggersList.takeTopLevelItem(index) |
|
831 # __IGNORE_WARNING__ |
|
832 del itm |