[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Re: [PyKDE] ANNOUNCE: IQtPy for event handling by Python's
From:       Michael Lauer <mickey () tm ! informatik ! uni-frankfurt ! de>
Date:       2003-02-24 9:22:14
[Download RAW message or body]

Am Son, 2003-02-23 um 19.02 schrieb Gerard Vermeulen:
> I am using this little toy for a week and I can't miss it anymore:
> it allows me to use the standard Python interpreter running in an
> xterm/Eterm/konsole to create and control PyQt widgets, and to use
> the widgets at the same time as in a standard GUI program.

This is an interesting approach. I took a slightly different one for
my EPythonShell Widget - see the attached code.



Cheers,

-- 
Michael Lauer <mickey@gandalf.tm.informatik.uni-frankfurt.de>
Institute of Telematics, CS. Dept., Frankfurt University

["pythonshell.py" (pythonshell.py)]

#------------------------------------------------------------------------#
# This file is part of the ELAN environment.
# (C) 2002 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
#
# Licensed under GPL
#------------------------------------------------------------------------#

"""Implements a Python Interpreter embedded in a QMultiLineEditor"""

__revision__ = "$Revision: 1.3 $"
__author__ = "Michael Lauer <mickey@tm.informatik.uni-frankfurt.de>"
__version__ = __revision__.replace('$','').replace('Revision:','').strip()

#------------------------------------------------------------------------#
from Queue import Queue
import sys
#------------------------------------------------------------------------#
import qt
import code
import rlcompleter
#------------------------------------------------------------------------#

class EPythonShell( qt.QMultiLineEdit ):
    """An interactive Python interpreter shell embedded in a QMultiLine editor."""

    class Output:
        def __init__( self, writefunc ):
            self.writefunc = writefunc
        def write( self, line ):
            if line != "\n":
                map( self.writefunc, line.split("\n") )

    def __init__( self, parent, localdict={} ):
        qt.QMultiLineEdit.__init__( self, parent )
        qt.QObject.connect( self, qt.SIGNAL( "returnPressed()" ), \
self.slotReturnPressed )  self.setFont( qt.QFont( "Fixed", 12 ) )
        
        self.history = []
        self.pointer = 0
        self.cmdFromHistory = False
        self.console = code.InteractiveConsole( localdict )
        self.completer = rlcompleter.Completer()
        self.possibleCompletions = []

        # We're overriding the prompts just in case someone set up prompt coloring
        sys.ps1 = ">>> "
        sys.ps2 = "... "

        cprt = 'Type "copyright", "credits" or "license" for more information.'
        self.append( "Python %s on %s\n%s" % ( sys.version, sys.platform, cprt ) )
        self.append( sys.ps1 )
        self.more, self.prompt = 0, sys.ps1
        self.output = EPythonShell.Output( self.writeResult )
        self.stdout = sys.stdout
        self.stderr = sys.stderr

        self.cursorToEnd()

    def isQt3( self ):
        return qt.qVersion()[0] == '3'
    
    def keyPressEvent( self, e ):
        """Intercept certain key press events and handle them to provide
        command line history and attribute name completion."""

        if ( e.key() == qt.Qt.Key_Up ):
            if not self.pointer > 0:
                return    
            row, col = self.getCursorPosition()
            self.home()
            self.killLine()
            if self.pointer > 0:
                self.pointer -= 1
            self.append( "%s" % self.history[self.pointer] )
            self.end()
            self.cmdFromHistory = True
            return
            
        elif ( e.key() == qt.Qt.Key_Down ):
            if not self.pointer < len( self.history )-1:
                return
            self.pointer += 1
            row, col = self.getCursorPosition()
            self.home()
            self.killLine()
            self.append( "%s" % self.history[self.pointer] )
            self.end()
            self.cmdFromHistory = True
            return
            
        elif e.key() == qt.Qt.Key_Return:
            self.end()
        
        elif e.key() == qt.Qt.Key_Tab:
            row, col = self.getCursorPosition()
            line = str( self.textLine( row ) )[4:]
            
            if len( self.possibleCompletions ) == 1:
                self.home()
                self.killLine()
                self.append( ">>> %s" % self.possibleCompletions[0] )
                self.end()
            else:
                print >>sys.stderr, repr( self.possibleCompletions )
            return
        
        self.cmdFromHistory = False
       
        qt.QMultiLineEdit.keyPressEvent( self, e )

    def keyReleaseEvent( self, e ):
        if e.key() == qt.Qt.Key_Up:
            return
        
        #
        # try command line completion
        #
        
        if str( e.key() )[0] in \
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.":  row, col = \
self.getCursorPosition()  line = str( self.textLine( row ) )[4:]
            possibleCompletions = []
            state = 0
            if len( line ) > 1:
                while True:
                    try:
                        nextCompletion = self.completer.complete( line, state )
                    except Exception, why:
                        #print >>sys.stderr, why
                        break
                    if not nextCompletion is None:
                        possibleCompletions.append( nextCompletion )
                        state += 1
                    else:
                        break

                #print >> sys.stderr, "'%s': possible completions: %s" % ( line, \
repr( possibleCompletions ) )  self.possibleCompletions = possibleCompletions

            qt.QMultiLineEdit.keyReleaseEvent( self, e )

    def cursorToEnd( self ):
        """Move the cursor to the end of the view."""
        
        # In Qt3, the QMultiLineEdit is derived from QTextEdit and deals in terms
        # of paragraphs and no longer lines. QTextEdit.setCursorPosition() doesn't
        # work as expected here, so we're faking a CTRL+END key here to achieve the
        # same effect :-)
        
        if self.isQt3():
            event = qt.QKeyEvent( qt.QKeyEvent.KeyPress, qt.Qt.Key_End, 0, \
qt.Qt.ControlButton )  qt.qApp.postEvent( self, event )
        else:
            rows = self.numLines()
            self.setCursorPosition( rows, 4 )
            self.end()

    def removeLastLine( self ):
        self.removeLine( self.numLines()-1 )

    def writeResult( self, result ):
        if result == "":
            return
        #print >> self.stdout, "appending '%s'" % result
        self.append( result )

    def handleInput( self, line ):
    
        if len( line ) > 5 and not self.cmdFromHistory:
            self.history.append( line )
            
        self.pointer = len( self.history )
        sys.stdout, sys.stderr = self.output, self.output
        self.more = self.console.push( line[4:] )
        sys.stdout, sys.stderr = self.stdout, self.stderr

    def slotReturnPressed( self ):
        row, col = self.getCursorPosition()
        self.removeLine( row )
        line = str( self.textLine( row-1 ) )
        #print "text sending to interpreter: '%s'" % line
        self.handleInput( line )
        if self.more:
            self.prompt = sys.ps2
        else:
            self.prompt = sys.ps1
        self.append( self.prompt )
        self.cursorToEnd()

#------------------------------------------------------------------------#
if __name__ == "__main__":
    
    a = qt.QApplication( sys.argv )
    w = EPythonShell( None )
    w.resize( qt.QSize( 640, 480 ) )
    w.show()
    a.setMainWidget( w )
    a.exec_loop()


_______________________________________________
PyKDE mailing list    PyKDE@mats.gmd.de
http://mats.gmd.de/mailman/listinfo/pykde

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic