Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

from PythonQt import QtCore, QtGui 

from director import lcmUtils 

from director.simpletimer import SimpleTimer 

from director.timercallback import TimerCallback 

import subprocess 

import os 

import sys 

 

class LCMLoggerWidget(object): 

 

    def __init__(self, statusBar=None): 

        self.manager = lcmUtils.LCMLoggerManager() 

        self.statusBar = statusBar 

 

        self.lastActiveLogFile = None 

        self.numProcesses = 0 

        self.numLogFiles = 0 

        self.userTag = '' 

 

        self.button = QtGui.QPushButton('') 

        self.button.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 

        self.button.connect('customContextMenuRequested(const QPoint&)', self.showContextMenu) 

        self.button.connect('clicked()', self.onClick) 

 

        self.timer = TimerCallback(targetFps=0.25) 

        self.timer.callback = self.updateState 

        self.timer.start() 

 

 

    def updateState(self): 

 

        t = SimpleTimer() 

        self.manager.updateExistingLoggerProcesses() 

 

        activeLogFiles = self.manager.getActiveLogFilenames() 

        self.numProcesses = len(self.manager.getActiveLoggerPids()) 

        self.numLogFiles = len(activeLogFiles) 

 

        if self.numLogFiles == 1: 

            self.lastActiveLogFile = activeLogFiles[0] 

 

        if self.numProcesses == 0: 

            self.button.text = 'start logger' 

        elif self.numProcesses == 1: 

            self.button.text = 'stop logger' 

        elif self.numProcesses > 1: 

            self.button.text = 'stop all loggers' 

 

        statusDescription = 'active' if self.numProcesses else 'last' 

        logFileDescription = self.lastActiveLogFile or '<unknown>' 

        self.button.setToolTip('%s log file: %s' % (statusDescription, logFileDescription)) 

 

 

    def onClick(self): 

        if self.numProcesses == 0: 

            self.manager.startNewLogger(tag=self.userTag) 

            self.updateState() 

            self.showStatusMessage('start logging: ' + self.lastActiveLogFile) 

        else: 

            self.manager.killAllLoggingProcesses() 

            self.showStatusMessage('stopped logging') 

            self.updateState() 

 

    def showStatusMessage(self, msg, timeout=2000): 

        if self.statusBar: 

            self.statusBar.showMessage(msg, timeout) 

 

    def showContextMenu(self, clickPosition): 

 

        globalPos = self.button.mapToGlobal(clickPosition) 

 

        menu = QtGui.QMenu() 

 

        action = menu.addAction('Stop logger') 

        action.enabled = (self.numProcesses > 0) 

 

        action = menu.addAction('Stop and delete log file') 

        action.enabled = (self.numProcesses > 0 and self.lastActiveLogFile) 

 

        action = menu.addAction('Set logger tag') 

        action.enabled = (self.numProcesses == 0) 

 

        action = menu.addAction('Copy log filename') 

        action.enabled = (self.lastActiveLogFile is not None) 

 

        action = menu.addAction('Review log') 

        action.enabled = (self.lastActiveLogFile is not None) 

 

 

        selectedAction = menu.exec_(globalPos) 

        if selectedAction is None: 

            return 

 

        if selectedAction.text == 'Copy log filename': 

            clipboard = QtGui.QApplication.instance().clipboard() 

            clipboard.setText(self.lastActiveLogFile) 

            self.showStatusMessage('copy to clipboard: ' + self.lastActiveLogFile) 

 

        elif selectedAction.text == 'Stop logger': 

            self.manager.killAllLoggingProcesses() 

            self.showStatusMessage('stopped logger') 

            self.updateState() 

 

        elif selectedAction.text == 'Stop and delete log file': 

            logFileToRemove = self.lastActiveLogFile 

            self.manager.killAllLoggingProcesses() 

            self.updateState() 

            os.remove(logFileToRemove) 

            self.showStatusMessage('deleted: ' + logFileToRemove) 

 

        elif selectedAction.text == 'Set logger tag': 

            inputDialog = QtGui.QInputDialog() 

            inputDialog.setInputMode(inputDialog.TextInput) 

            inputDialog.setLabelText('Log file tag:') 

            inputDialog.setWindowTitle('Enter tag') 

            inputDialog.setTextValue(self.userTag) 

            result = inputDialog.exec_() 

 

            if result: 

                tag = inputDialog.textValue() 

                self.userTag = tag 

                self.showStatusMessage('Set lcm logger tag: ' + self.userTag) 

 

        elif selectedAction.text == 'Review log': 

            newEnv = dict(os.environ) 

            newEnv['LCM_DEFAULT_URL'] = newEnv['LCM_REVIEW_DEFAULT_URL'] 

            devnull = open(os.devnull, 'w') 

            # Pass entire command line invocation of director to subprocess including cfg and json paths 

            subprocess.Popen(sys.argv, stdout=devnull, stderr=devnull, env=newEnv) 

            subprocess.Popen(['lcm-logplayer-gui', self.lastActiveLogFile], stdout=devnull, stderr=devnull, env=newEnv) 

            subprocess.Popen(['bot-procman-sheriff', '-o'], stdout=devnull, stderr=devnull, env=newEnv)