00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2002 00004 # by 00005 # The Board of Trustees of the 00006 # Leland Stanford Junior University. 00007 # All rights reserved. 00008 # 00009 00010 __facility__ = "Online" 00011 __abstract__ = "Comment panel for RunControl" 00012 __author__ = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = ("$Date: 2005/08/03 20:25:36 $").split(' ')[1] 00014 __version__ = "$Revision: 2.4 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 from qt import * 00021 import os 00022 import time 00023 00024 class rcCommentPanel(QWidget): 00025 def __init__(self,parent = None,name = None,fl = 0): 00026 QWidget.__init__(self,parent,name,fl) 00027 00028 if not name: 00029 self.setName("rcComments") 00030 00031 00032 Form2Layout = QGridLayout(self,1,1,0,6,"Form2Layout") 00033 00034 self.__teComments = CommentEntryWidget(self) 00035 00036 Form2Layout.addWidget(self.__teComments,0,0) 00037 00038 self.languageChange() 00039 00040 self.resize(QSize(291,219).expandedTo(self.minimumSizeHint())) 00041 00042 def getWidget(self): 00043 return self.__teComments 00044 00045 def languageChange(self): 00046 self.setCaption(self.tr("rcComments")) 00047 00048 class CommentEntryWidget(QTextEdit): 00049 def __init__(self, parent=None): 00050 QTextEdit.__init__(self, parent) 00051 00052 self.__prompt = "--> " 00053 00054 # last line + last incomplete lines 00055 self.line = QString() 00056 self.lines = [] 00057 # the cursor position in the last line 00058 self.point = 0 00059 # flag: readline() is being used for e.g. raw_input() and input() 00060 self.reading = 0 00061 # history 00062 self.__history = [] 00063 self.__timeStamps = [] 00064 self.pointer = 0 00065 self.xLast = 0 00066 self.yLast = 0 00067 self.__xLastBP = 0 00068 self.__yLastBP = 0 00069 self.clip = QApplication.clipboard() 00070 00071 # user interface setup 00072 self.setTextFormat(QTextEdit.PlainText) 00073 self.setWrapPolicy(QTextEdit.Anywhere) 00074 # font 00075 if os.name == 'posix': 00076 font = QFont("Fixed", 12) 00077 elif os.name == 'nt' or os.name == 'dos': 00078 font = QFont("Courier New", 8) 00079 else: 00080 raise SystemExit, "FIXME for 'os2', 'mac', 'ce' or 'riscos'" 00081 font.setFixedPitch(1) 00082 self.setFont(font) 00083 self.connect(self, SIGNAL("clicked(int,int)"), self.handleClicked) 00084 00085 # geometry 00086 height = 40*QFontMetrics(font).lineSpacing() 00087 request = QSize(600, height) 00088 if parent is not None: 00089 request = request.boundedTo(parent.size()) 00090 self.resize(request) 00091 self.setReadOnly(1) 00092 self.clearDisplay() 00093 00094 def getHistory(self): 00095 return self.__history 00096 00097 def getTimestamps(self): 00098 return self.__timeStamps 00099 00100 def clearHistory(self): 00101 self.__history = [] 00102 self.__timeStamps = [] 00103 00104 def clearDisplay(self): 00105 self.clear() 00106 self.write(self.__prompt) 00107 #if self.isReadOnly(): 00108 # self.enterComment('Comment entry is disabled.') 00109 #else: 00110 # self.enterComment('Comment entry is enabled.') 00111 00112 def setPrompt(self, prompt): 00113 self.__prompt = prompt 00114 00115 def getPrompt(self): 00116 return self.__prompt 00117 00118 def flush(self): 00119 """ 00120 Simulate stdin, stdout, and stderr. 00121 """ 00122 pass 00123 00124 def isatty(self): 00125 """ 00126 Simulate stdin, stdout, and stderr. 00127 """ 00128 return 1 00129 00130 def readline(self): 00131 """ 00132 Simulate stdin, stdout, and stderr. 00133 """ 00134 self.reading = 1 00135 self.__clearLine() 00136 self.moveCursor(QTextEdit.MoveEnd, 0) 00137 while self.reading: 00138 qApp.processOneEvent() 00139 if self.line.length() == 0: 00140 return '\n' 00141 else: 00142 return str(self.line) 00143 00144 def write(self, text): 00145 """ 00146 Simulate stdin, stdout, and stderr. 00147 """ 00148 # The output of self.append(text) contains to many newline characters, 00149 # so work around QTextEdit's policy for handling newline characters. 00150 hack = self.text() 00151 hack.append(text) 00152 self.setText(hack) 00153 #self.setText(self.text().append(text)) # segmentation fault 00154 self.moveCursor(QTextEdit.MoveEnd, 0) 00155 self.yLast, self.xLast = self.getCursorPosition() 00156 00157 def writelines(self, text): 00158 """ 00159 Simulate stdin, stdout, and stderr. 00160 """ 00161 map(self.write, text) 00162 print "DO WE EVER GET HERE? IF YES, OPTIMIZATION POSSIBLE" 00163 00164 def enterComment(self, comment, addToHistory=0, source='system'): 00165 """This can be called from a user script to add to comments. 00166 The text is prepended with \a source to indicate that it is a 00167 machine generated comment. 00168 00169 \param comment The text of the comment to be entered 00170 \param addtoHistory Whether this comment will be persistent or not 00171 \param source The text to be prepended before the comment 00172 00173 """ 00174 self.line = comment.rstrip() 00175 if source != "": 00176 self.line = '[' + source + '] ' + self.line 00177 self.line = QString(self.line) 00178 self.write(self.line) 00179 self.__xLastBP, self.__yLastBP = self.xLast, self.yLast 00180 self.__xLastBP += 11 # Add the length of the timestamp 00181 self.write('\n') 00182 self.__run(addToHistory) 00183 00184 def flushComment(self): 00185 if self.line.length() > 0: 00186 self.write('\n') 00187 self.__run() 00188 00189 def __run(self, addToHistory=1): 00190 self.pointer = 0 00191 y, x = self.getCursorPosition() 00192 yFirst = y - len(self.lines) - 1 00193 self.setSelection(yFirst, 0, yFirst, 4) 00194 self.removeSelectedText() 00195 tStamp = time.gmtime() 00196 self.insertAt(time.strftime('[%H:%M:%S] ', tStamp), y - len(self.lines) - 1, 0) 00197 if addToHistory: 00198 self.__history.append(str(self.line)) 00199 self.__timeStamps.append(tStamp) 00200 self.lines.append(str(self.line)) 00201 self.write(self.__prompt) 00202 self.lines = [] 00203 self.__clearLine() 00204 00205 def __clearLine(self): 00206 """ 00207 Clear input line buffer 00208 """ 00209 self.line.truncate(0) 00210 self.point = 0 00211 00212 def insertText(self, text, offsetY=0, absX=0, overwrite=0): 00213 """ 00214 \param text Text to be inserted 00215 \param offsetY The position of the comment text relative to the current position 00216 \param absX The absolute position of the comment text 00217 """ 00218 posy = self.__yLastBP + offsetY 00219 posx = absX + 11 # Skip over the timestamp 00220 self.setCursorPosition(posy, posx) 00221 if overwrite: 00222 self.setSelection(posy, posx, posy, posx+len(text), 0) 00223 self.removeSelectedText() 00224 self.__insertText(QString(text), posy, posx) 00225 00226 def __insertText(self, text, posY=0, posX=0): 00227 """ 00228 Insert text at the current cursor position. 00229 """ 00230 y, x = self.getCursorPosition() 00231 if posX != 0: x = posX 00232 if posY != 0: y = posY 00233 self.insertAt(text, y, x) 00234 self.line.insert(self.point, text) 00235 self.point += text.length() 00236 self.setCursorPosition(y, x + text.length()) 00237 00238 def keyPressEvent(self, e): 00239 """ 00240 Handle user input a key at a time. 00241 """ 00242 00243 if self.isReadOnly() or not self.isEnabled(): 00244 e.ignore() 00245 return 00246 text = e.text() 00247 key = e.key() 00248 ascii = e.ascii() 00249 00250 if text.length() and ascii>=32 and ascii<127: 00251 self.__insertText(text) 00252 return 00253 00254 if e.state() & Qt.ControlButton or e.state() & Qt.ShiftButton: 00255 e.ignore() 00256 return 00257 00258 if key == Qt.Key_Backspace: 00259 if self.point: 00260 self.doKeyboardAction(QTextEdit.ActionBackspace) 00261 self.point -= 1 00262 self.line.remove(self.point, 1) 00263 elif key == Qt.Key_Delete: 00264 self.doKeyboardAction(QTextEdit.ActionDelete) 00265 self.line.remove(self.point, 1) 00266 elif key == Qt.Key_Return or key == Qt.Key_Enter: 00267 self.write('\n') 00268 if self.reading: 00269 self.reading = 0 00270 else: 00271 self.__run() 00272 elif key == Qt.Key_Tab: 00273 self.__insertText(text) 00274 elif key == Qt.Key_Left: 00275 if self.point: 00276 self.moveCursor(QTextEdit.MoveBackward,0) 00277 self.point -= 1 00278 elif key == Qt.Key_Right: 00279 if self.point < self.line.length(): 00280 self.moveCursor(QTextEdit.MoveForward,0) 00281 self.point += 1 00282 elif key == Qt.Key_Home: 00283 self.setCursorPosition(self.yLast, self.xLast) 00284 self.point = 0 00285 elif key == Qt.Key_End: 00286 self.moveCursor(QTextEdit.MoveLineEnd,0) 00287 self.point = self.line.length() 00288 elif key == Qt.Key_Up: 00289 if len(self.__history): 00290 if self.pointer == 0: 00291 self.pointer = len(self.__history) 00292 self.pointer -= 1 00293 self.__recall() 00294 elif key == Qt.Key_Down: 00295 if len(self.__history): 00296 self.pointer += 1 00297 if self.pointer == len(self.__history): 00298 self.pointer = 0 00299 self.__recall() 00300 elif key == Qt.Key_Escape: 00301 self.__deleteLine() 00302 else: 00303 e.ignore() 00304 00305 def __deleteLine(self): 00306 self.setCursorPosition(self.yLast, self.xLast) 00307 self.setSelection(self.yLast, self.xLast, 00308 self.yLast, self.paragraphLength(self.yLast)) 00309 self.removeSelectedText() 00310 self.__clearLine() 00311 00312 def __recall(self): 00313 """ 00314 Display the current item from the command history. 00315 """ 00316 self.__deleteLine() 00317 self.__insertText(QString(self.__history[self.pointer])) 00318 00319 00320 def focusNextPrevChild(self, next): 00321 """ 00322 Suppress tabbing to the next window in multi-line commands. 00323 """ 00324 return QTextEdit.focusNextPrevChild(self, next) 00325 00326 def handleClicked(self, para, pos): 00327 """ 00328 Keep the cursor after the last prompt. 00329 """ 00330 if self.hasSelectedText(): 00331 if len(self.selectedText()) > 0: 00332 self.clip.setText(self.selectedText()) 00333 self.moveCursor(QTextEdit.MoveEnd, 0) 00334 return 00335 00336 def contentsContextMenuEvent(self,ev): 00337 """ 00338 Suppress the right button context menu. 00339 Instead paste the contents of the clipboard. 00340 """ 00341 if not self.isReadOnly(): 00342 self.__insertText(self.clip.text()) 00343 ev.accept() 00344 return 00345