rcCommentPanel.py

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

Generated on Thu Apr 27 20:52:43 2006 for LICOS L02-01-00 by doxygen 1.4.6-NO