Beispiel #1
0
    def __init__(self, overlayId, app):
        Overlay.__init__(self, OVERLAY_APP, overlayId)
        EventHandler.__init__(self)
        self.app = app   # which app is this overlay tied to
        self.bounds.setAll(app.left, app.right, app.top, app.bottom)
        self.displayId = app.getDisplayId()
        self.aspectRatio = self.bounds.getWidth() / float(self.bounds.getHeight())
        self.minAppSize = 300   # min app size in either direction
        self.z = self.app.getZvalue()
        self.__resetOverlay()
        self.capturedCorner = APP
        self.lastClickPos = (0,0)
        self.lastClickDeviceId = None
        self.overCorner = APP
                
        # register for the events that are fired when an app changes
        self.registerForEvent(EVT_APP_INFO, self.__onAppChanged)
        self.registerForEvent(EVT_Z_CHANGE, self.__onZChanged)

        # register for the events that are fired by devices
        self.registerForEvent(EVT_MOVE, self.__onOver)
        self.registerForEvent(EVT_CLICK, self.__onClick)
        self.registerForEvent(EVT_DRAG, self.__onDrag)
        self.registerForEvent(EVT_ROTATE, self.__onRotate)
        self.registerForEvent(EVT_ZOOM, self.__onZoom)
        self.registerForEvent(EVT_ARROW, self.__onArrow)
        self.registerForEvent(EVT_LEFT_WINDOW, self.__onLeftWindow)

        # register for the events from the special devices
        self.registerForEvent(EVT_MOVE_SPECIAL, self.__onSpecialMove)
        self.registerForEvent(EVT_ENTERED_WINDOW_SPECIAL, self.__onEnteredWindowSpecial)
        self.registerForEvent(EVT_LEFT_WINDOW_SPECIAL, self.__onLeftWindowSpecial)
    def __init__(self, engine,localOptions):
        Mgr.__init__(self, engine)
        self.gameStarted = False
        self.winnerIndex = -1
        self.lapsTillWin = localOptions.lapsTillWin
        self.textTint = (0.0,0.0,0.0)
        self.initialCountdownTime = 4
        self.numRaces = 0
        self.allPlayersReady = False

        # create all neccessary overlay panels
        self.mainMenu = Overlay(name = "MainMenu", pos = (0,150), size = (950,950), material = "MainMenu")
        self.finishPanel = Overlay(name = "ExitPanel", pos = (250,100), size = (500,500))
        self.messagePanel = Overlay(name = "MessPanel", pos = (0,0), size = (1000,1000),material = None)

        # initialize values for finish panel
        self.finishPanel.addText("RACE OVER",130,30,30)
        self.finishPanel.addHorizontalDivider(60)
        self.finishPanel.addText("You Placed:",90,80,30)
        self.finalPlacement = self.finishPanel.addText(str(0),350,80,30)
        self.finishPanel.addText("Final Time:",70,120,30)
        self.finalTime = self.finishPanel.addText(str(0),320,120,30)
        self.finishPanel.addText("Press Enter to Play Again",50,380,20)
        self.finishPanel.addText("Press Escape or 'Q' to Exit",50,420,20)
        self.finishPanel.hideAll()

        #initialize values for message panel
        self.countdownText = self.messagePanel.addText(" ", 400,20,40)
        self.noServer = self.messagePanel.addText("No server found, looking...", 125,600,40,(1.0,1.0,1.0),(1.0,0.0,0.0))
        self.waitingText = self.messagePanel.addText("Waiting for Players...", 200,400,40,(1.0,1.0,1.0),(1.0,0.0,0.0))
        self.waitingText.hide()
        self.noServer.hide()
Beispiel #3
0
    def __init__(self, app=None, direction=VERTICAL):
        Overlay.__init__(self, OVERLAY_SPLITTER)
        EventHandler.__init__(self, app)

        self.direction = direction
        self.__enlarged = False
        self.__scaleMultiplier = 4.0
        self._canScale = False
        self.mouseOverScale = 1.0
        self.setTransparency(255)
        self.z = BOTTOM_Z - 10
        self.relPos = 0.5  # relative to the section it splits
        self._preCollapsedPos = self.relPos
        self.__buffer = int(20 * getGlobalScale())
        self._collapsed = False

        self.registerForEvent(EVT_DRAG, self.__onDrag)
        self.registerForEvent(EVT_CLICK, self.__onClick)
        self.registerForEvent(EVT_MOVE, self.__onMove)
        self.registerForEvent(EVT_LEFT_WINDOW, self._onLeftWindow)
        self.registerForEvent(EVT_ENTERED_WINDOW, self._onEnteredWindow)

        if direction == VERTICAL:
            self.__image = opj("images", "vertical_divider.png")
        else:
            self.__image = opj("images", "horizontal_divider.png")
Beispiel #4
0
    def __init__(self, app=None):
        Overlay.__init__(self, OVERLAY_BUTTON)
        EventHandler.__init__(self, app)
        
        # register for the events that are fired by devices
        self.registerForEvent(EVT_CLICK, self._onClick)
        self.registerForEvent(EVT_MOVE, self._onMove)
        self.registerForEvent(EVT_LEFT_WINDOW, self._onLeftWindow)
        self.registerForEvent(EVT_ENTERED_WINDOW, self._onEnteredWindow)

        # paths to images drawn for different button states
        self.__upImage = "images/default_button_up.png"
        self.__downImage = ""
        self.__overImage = ""

        self.__doPlaySound = True

        # button can be a toggle
        self._isToggle = False
        self.__radioFunc = True
        self.__clicked = False
        self._manual = False
        self._radio = False

        # current state of the button
        self.__state = UP_STATE
        
        # callbacks you can register
        self.__onDown = None
        self.__onUp = None
        self._lastDevice = None
        
        self.__minTimeBetweenClicks = 0.5  # by default, allow rapid successive clicks
        self.__lastUp = 0.0
        self.__lastDown = 0.0
Beispiel #5
0
 def __init__(self, app=None, label="", fontSize=NORMAL):
     """ If you pass in None for app, the widget will reside on the top layer
         above all apps but below pointers.
     """
     Overlay.__init__(self, OVERLAY_LABEL)
     EventHandler.__init__(self, app)
     self.setLabel(label, fontSize)
     self.__drawBackground = True
Beispiel #6
0
    def initialize(self, overlayId):
        Overlay.initialize(self, overlayId)

        # force a different initial state
        if self.__state != UP_STATE:
            newState = UP_STATE
            newState, self.__state = self.__state, newState
            self.setState(newState)
 def __init__(self, parentItem, Z=1):
     Overlay.__init__(self, parentItem, Z)
     self.label = MetaItem(parent=self)
     self.label.setText('Empty')
     self.label.setFlags(QtGui.QGraphicsItem.ItemIsSelectable |
                         QtGui.QGraphicsItem.ItemIsFocusable | QtGui.QGraphicsItem.ItemIsMovable |
                         QtGui.QGraphicsItem.ItemIgnoresTransformations)
     self.menu = QtGui.QMenu()
     self.acts = {}
Beispiel #8
0
    def __init__(self, app):
        Overlay.__init__(self, OVERLAY_APP)
        EventHandler.__init__(self, app)
        
        # must set size and pos first
        self._canScale = False
        self.setSize(1.0, 1.0)   # same size as the app
        self.setPos(0.0, 0.0)    # right over the app
        self._zOffset = APP_OVERLAY_Z
        self._allowSelection = True

        # some initial params
        self.minAppSize = 250   # min app size in either direction
        self.capturedCorner = APP
        self.lastClickPos = (0,0)
        self.lastClickDeviceId = None
        self.overCorner = APP
        self.bounds = self.getBounds()  # from EventHandler base class
        self._clickDownTime = 0.0
        self.__startedDrag = False  # for accidental touches...

        # if less than X seconds has passed between two double clicks,
        # maximize to the whole display, otherwise, just within the section
        self._lastDoubleClick = 0.0
        self.__maximizeThreshold = 1.3  # seconds between two double clicks...

        # for closing apps
        self.__multiTouchStartTime = -1

        self.org = getLayoutOrganization()

        # get the filename from appLauncher
        if "imageviewer" in app.getName().lower() or \
            "mplayer" in app.getName().lower() or \
            "stereo3d" in app.getName().lower() or \
            "pdf" in app.getName().lower():
            # get the config info from the right appLauncher
            if app.getLauncherId() != "none":
                appLauncher = xmlrpclib.ServerProxy("http://" + app.getLauncherId())
                try:
                    res = appLauncher.getAppConfigInfo( app.getAppId() )
                except:
                    print "\nUnable to connect to appLauncher on", app.getLauncherId(), "so not saving this app: ", app.getName() 
                else:
                    print "appLauncher.getAppConfigInfo : ", res
                    if res != -1:
                        configName, optionalArgs = res
                        if "imageviewer" in app.getName().lower():
                            # filename at the beginning of the command line for images
                            self.fullpathname = optionalArgs.split()[0].strip('"')
                            self.filename     = os.path.basename( self.fullpathname )
                        else:
                            # filename at the end of the command line for movies
                            self.fullpathname = optionalArgs.split()[-1].strip('"')
                            self.filename = os.path.basename( self.fullpathname )
                        if getShowWindowTitleBar():
                            self.setTooltip(self.filename, LARGER)
Beispiel #9
0
 def __init__(self, app=None, direction=HORIZONTAL):
     """ If you pass in None for app, the widget will reside on the top layer
         above all apps but below pointers.
     """
     Overlay.__init__(self, OVERLAY_SIZER)
     EventHandler.__init__(self, app)
     self.__direction = direction
     
     # let the events pass through since we are transparent
     self._eventTransparent = True  
Beispiel #10
0
 def __init__(self, parentItem, Z=1, startLine=True):
     Overlay.__init__(self, parentItem, Z=Z)
     self.opt = set(
         ['startLine', 'slope', 'const', 'domain', 'roi', 'crop'])
     # Create base and height lines
     self.line = QtGui.QGraphicsLineItem(parent=self)
     if not startLine:
         self.pen.setColor(QtGui.QColor('red'))
     self.line.setPen(self.pen)
     self.startLine = startLine
Beispiel #11
0
 def __init__(self, overlayId):
     Overlay.__init__(self, OVERLAY_POINTER, overlayId)
     self.state = RESET
     self.lastOrientation = 0
     self.inApp = False
     self.__savedState = [self.state, self.lastOrientation, self.inApp]
     
     # some devices only produce one analog event so set it here if so
     # (e.g. a zoom-only puck)
     # this is used when the device enters an application in order to show
     # the correct pointer shape describing what the device can do
     self.onlyAnalogEvent = None   
    def loadScorePanel(self):
        myMesh = self.engine.entMgr.entities[self.engine.entMgr.playerIndex].mesh
        self.scorePanel = Overlay(pos = (50,575), size = (950,100))
        for i in range(1,5):
            self.scorePanel.addVerticalDivider(190* i)
        self.scorePanel.addHorizontalDivider(40)

        # establish partial text color based on color of ship model
        if myMesh.count("blue") > 0:
            self.textTint = (0.0,0.6,1.0)
        elif myMesh.count("purple") > 0:
            self.textTint = (0.25,0.0,0.5)
        elif myMesh.count("tan") > 0:
            self.textTint = (1.0,0.8,0.6)
        elif myMesh.count("green") > 0:
            self.textTint = (0.0,1.0,0.0)
        elif myMesh.count("gray") > 0:
            self.textTint = (0.25,0.25,0.25)
        elif myMesh.count("checkard") > 0:
            self.textTint = (0.0,0.0,0.0)
            
        # initialize all text in panel with the specified color
        self.scorePanel.addText("PLACE:",30,10,30)
        self.placeText = self.scorePanel.addText(str(0),85,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("LAP:",250,10,30)
        self.lapText = self.scorePanel.addText(str(0),255,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("SPEED:",410,10,30)
        self.speedText = self.scorePanel.addText(str(0),400,50,25,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("TIME:",620,10,30)
        self.timeText = self.scorePanel.addText(str(0),640,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("TIME/LAP:",790,15,20)
        self.timePerLapText = self.scorePanel.addText("--",840,50,30,(1.0,1.0,1.0),self.textTint)
Beispiel #13
0
 def __init__(self, port=DEFAULT_MANAGER_PORT):
     signalutil.Runner.__init__(self)
     self.port = port
     self.overlay = Overlay()
     self.name_store = NameStore(self.overlay)
     self.type_store = TypeStore(self.overlay)
     self.migration_store = MigrationStore(self.overlay)
     self.script_store = ScriptStore(self.overlay)
     self.socket_store = SocketStore(self.overlay)
Beispiel #14
0
    def __init__(self, app=None):
        """ If you pass in None for app, the widget will reside on the top layer
            above all apps but below pointers.
        """
        Overlay.__init__(self, OVERLAY_PANEL)
        EventHandler.__init__(self, app)

        self.registerForEvent(EVT_DRAG, self.__onDrag)
        self.registerForEvent(EVT_CLICK, self._onClick)

        self._allowDrag = False  # ONLY USE WITH ABSOLUTE POSITION!!! (wont work when aligned)
        
        self.__fitInWidth = True
        self.__fitInHeight = True

        self.__borderWidth = 0

        self._zOffset -= 0.01  # just below the other widgets

        self.px = self.py = 0
Beispiel #15
0
    def __init__(self, x=0, y=0):
        Overlay.__init__(self, OVERLAY_POINTER)
        EventHandler.__init__(self)

        self.setSize(50,75)
        self.setPos(x,y)
        self.setDrawOrder(POST_DRAW)

        self.state = RESET
        self.lastOrientation = 0
        self.inApp = False
        self.__savedState = [self.state, self.lastOrientation, self.inApp]

        # some devices only produce one analog event so set it here if so
        # (e.g. a zoom-only puck)
        # this is used when the device enters an application in order to show
        # the correct pointer shape describing what the device can do
        self.onlyAnalogEvent = None   
        self._eventTransparent = True  # so that we dont receive our own clicks...

        self.__image = ""
Beispiel #16
0
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.viewport_y = 0 # top visible line
        self.imagemode = False
        self.image = None

        self.scroll_height = 0
        self.scroll_width = 0

        self.timer = QTimer(self)
        self.backuptimer = QTimer(self)
        self.connect(self.timer, SIGNAL("timeout()"), self.analysis_timer)
        self.connect(self.backuptimer, SIGNAL("timeout()"), self.backup_timer)
        self.backuptimer.start(30000)
        self.undotimer = QTimer(self)
        self.connect(self.undotimer, SIGNAL("timeout()"), self.trigger_undotimer)

        self.blinktimer = QTimer(self)
        self.blinktimer.start(500)
        self.connect(self.blinktimer, SIGNAL("timeout()"), self.trigger_blinktimer)
        self.show_cursor = True

        self.boxcolors = [QColor("#DC322F"), QColor("#268BD2"), QColor("#D33682"), QColor("#B58900"), QColor("#2AA198"), QColor("#859900")]
        self.setCursor(Qt.IBeamCursor)

        # Semi-transparent overlay.
        # Used to display heat-map visualisation of profiler info, etc.
        self.overlay = Overlay(self)
        # Start hidden, make (in)visible with self.toggle_overlay().
        self.overlay.hide()

        # Set to True if the user wants to see tool visualisations.
        self.show_tool_visualisations = True

        # Set True if Eco should be running profiler and other tools,
        # continuously in the background.
        self.run_background_tools = False
Beispiel #17
0
import rospy
from math import pi, cos, sin
from eqep import eQEP
from std_msgs.msg import Float32
from nav_msgs.msg import Odometry
from time import sleep
from overlay import Overlay
from tf import transformations

#
# this is probably fine for encoders for now but there are some
# inherent granularity issues with using the eQEPs for velocity
# control; probably want to switch to PRUs at some point
#
# overlay to device tree
Overlay.apply("bone_eqep0")
Overlay.apply("bone_eqep2b")

# ros stuff
rospy.init_node('odom_publisher')
pub_left = rospy.Publisher('/wheel_left/state', Float32, queue_size=1)
pub_right = rospy.Publisher('/wheel_right/state', Float32, queue_size=1)
pub_odom = rospy.Publisher('/wheel_odom', Odometry, queue_size=3)

# initialiaze eQEPs
eqep_left = eQEP(eQEP.eQEP2, eQEP.MODE_ABSOLUTE)
eqep_right = eQEP(eQEP.eQEP0, eQEP.MODE_ABSOLUTE)

# set update frequency
frequency = rospy.get_param('frequency', 30)
period = 1000000000 / frequency
class GameMgr(Mgr):
    def __init__(self, engine,localOptions):
        Mgr.__init__(self, engine)
        self.gameStarted = False
        self.winnerIndex = -1
        self.lapsTillWin = localOptions.lapsTillWin
        self.textTint = (0.0,0.0,0.0)
        self.initialCountdownTime = 4
        self.numRaces = 0
        self.allPlayersReady = False

        # create all neccessary overlay panels
        self.mainMenu = Overlay(name = "MainMenu", pos = (0,150), size = (950,950), material = "MainMenu")
        self.finishPanel = Overlay(name = "ExitPanel", pos = (250,100), size = (500,500))
        self.messagePanel = Overlay(name = "MessPanel", pos = (0,0), size = (1000,1000),material = None)

        # initialize values for finish panel
        self.finishPanel.addText("RACE OVER",130,30,30)
        self.finishPanel.addHorizontalDivider(60)
        self.finishPanel.addText("You Placed:",90,80,30)
        self.finalPlacement = self.finishPanel.addText(str(0),350,80,30)
        self.finishPanel.addText("Final Time:",70,120,30)
        self.finalTime = self.finishPanel.addText(str(0),320,120,30)
        self.finishPanel.addText("Press Enter to Play Again",50,380,20)
        self.finishPanel.addText("Press Escape or 'Q' to Exit",50,420,20)
        self.finishPanel.hideAll()

        #initialize values for message panel
        self.countdownText = self.messagePanel.addText(" ", 400,20,40)
        self.noServer = self.messagePanel.addText("No server found, looking...", 125,600,40,(1.0,1.0,1.0),(1.0,0.0,0.0))
        self.waitingText = self.messagePanel.addText("Waiting for Players...", 200,400,40,(1.0,1.0,1.0),(1.0,0.0,0.0))
        self.waitingText.hide()
        self.noServer.hide()

    def loadScorePanel(self):
        myMesh = self.engine.entMgr.entities[self.engine.entMgr.playerIndex].mesh
        self.scorePanel = Overlay(pos = (50,575), size = (950,100))
        for i in range(1,5):
            self.scorePanel.addVerticalDivider(190* i)
        self.scorePanel.addHorizontalDivider(40)

        # establish partial text color based on color of ship model
        if myMesh.count("blue") > 0:
            self.textTint = (0.0,0.6,1.0)
        elif myMesh.count("purple") > 0:
            self.textTint = (0.25,0.0,0.5)
        elif myMesh.count("tan") > 0:
            self.textTint = (1.0,0.8,0.6)
        elif myMesh.count("green") > 0:
            self.textTint = (0.0,1.0,0.0)
        elif myMesh.count("gray") > 0:
            self.textTint = (0.25,0.25,0.25)
        elif myMesh.count("checkard") > 0:
            self.textTint = (0.0,0.0,0.0)
            
        # initialize all text in panel with the specified color
        self.scorePanel.addText("PLACE:",30,10,30)
        self.placeText = self.scorePanel.addText(str(0),85,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("LAP:",250,10,30)
        self.lapText = self.scorePanel.addText(str(0),255,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("SPEED:",410,10,30)
        self.speedText = self.scorePanel.addText(str(0),400,50,25,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("TIME:",620,10,30)
        self.timeText = self.scorePanel.addText(str(0),640,50,30,(1.0,1.0,1.0),self.textTint)
        self.scorePanel.addText("TIME/LAP:",790,15,20)
        self.timePerLapText = self.scorePanel.addText("--",840,50,30,(1.0,1.0,1.0),self.textTint)

    def tick(self, dtime):
        # if networking is enabled, show text telling player that the game is still giving other players an oppertunnity to join. 
        if self.engine.netMgr.networkingEnabled and not self.gameStarted and self.engine.gfxMgr.cameraMode != "Main Menu" and not self.allPlayersReady:
            if int(self.engine.netMgr.timeToWaitForPlayers) % 2 == 0:
                self.waitingText.hide()
            else:
                self.waitingText.show()
        # before the race starts show a countdown
        elif not self.gameStarted and self.engine.gfxMgr.cameraMode != "Main Menu" and self.allPlayersReady:
            self.waitingText.hide()
            if self.initialCountdownTime == 4 and self.numRaces == 0:
                self.loadScorePanel()
            self.initialCountdownTime -= dtime
            if self.initialCountdownTime <= 1:
                self.countdownText.setCaption(" GO!!! ")
                self.countdownText.setColourTop((0.0,0.0,1.0))
                self.gameStarted = True
            elif self.initialCountdownTime <= 2:
                self.countdownText.setCaption("1  2  3")
                self.countdownText.setColourTop((0.0,1.0,0.0))
            elif self.initialCountdownTime <= 3:
                self.countdownText.setCaption("1  2")
                self.countdownText.setColourTop((1.0,1.0,0.0))
            elif self.initialCountdownTime <= 4:
                self.countdownText.setCaption("1")
                self.countdownText.setColourTop((1.0,0.0,0.0))
        # once the countdown has finished, and as long as no one has won yet, keep performing game operations. 
        elif self.gameStarted and self.winnerIndex == -1:
            placementArray = []
            self.initialCountdownTime -= dtime
            if self.initialCountdownTime <= 0:
                self.countdownText.hide()
            for ent in self.engine.entMgr.entities:
                ent.totalTime += dtime
                ent.positionAngle = math.atan2(ent.pos.z,ent.pos.x)

                # if angle is less than 0, turn it in to it's positive representation
                if ent.positionAngle < 0:
                    ent.positionAngle +=  math.pi *2

                # check to see if this ship has passed first checkpoint
                if ent.positionAngle > (math.pi +  math.pi/2) -.2 and ent.positionAngle < (math.pi +  math.pi/2) and ent.checkpoint == 0:
                    ent.checkpoint =1
                    
                # check to see if this ship has passed second checkpoint
                elif ent.positionAngle > math.pi -.2 and ent.positionAngle < math.pi and ent.checkpoint == 1:
                    ent.checkpoint =2
                    
                # check to see if this ship has passed third checkpoint
                elif ent.positionAngle > (math.pi / 2) -.2 and ent.positionAngle < (math.pi / 2)and ent.checkpoint == 2:
                    ent.checkpoint =3

                # check to see if this ship has completed a lap
                elif ent.positionAngle > (math.pi*2) -.2 and ent.positionAngle < (math.pi*2)and ent.checkpoint == 3:
                    ent.checkpoint = 0
                    ent.lap += 1
                    
                placementArray.append([ent.shipId, ent.lap * 4 + ent.checkpoint *1,ent.positionAngle])

			
                # update score label information
                if ent.shipId == self.engine.entMgr.playerIndex:
                    self.placeText.setCaption(str(ent.placement))
                    self.lapText.setCaption(str(ent.lap) + "/" + str(self.lapsTillWin))
                    # if speed is 500, print MAX
                    if ent.speed < 500:
                        self.speedText.setPosition(400,50)
                        self.speedText.setCaption(str(ent.speed) + " mph")
                    else:
                        self.speedText.setPosition(445,50)
                        self.speedText.setCaption("MAX")
                    # print total time in format (m:ss)
                    minutes = int(ent.totalTime / 60)
                    seconds = int(ent.totalTime % 60)
                    if seconds < 10:
                        self.timeText.setCaption(str(minutes) + ":0" + str(seconds))
                    else:
                        self.timeText.setCaption(str(minutes) + ":" + str(seconds))
                        
                    # print time per lap in format (m:ss)
                    if ent.lap >0:
                        self.timePerLapText.setPosition(815,50)
                        minutes = int(ent.totalTime /ent.lap / 60)
                        seconds = int(ent.totalTime /ent.lap % 60)
                        if seconds < 10:
                            self.timePerLapText.setCaption(str(minutes) + ":0" + str(seconds))
                        else:
                            self.timePerLapText.setCaption(str(minutes) + ":" + str(seconds))
                            
                #check to see if this player has finished there last lap and has won the game
                if ent.lap == self.lapsTillWin:
                    self.engine.gfxMgr.cameraMode = "End View"
                    self.scorePanel.hideAll()
                    self.winnerIndex = ent.shipId
                    
            # establish current placements
            for i in range(len(placementArray)):
                for j in range(len(placementArray) -1):
                    if placementArray[j][1] < placementArray[j+1][1] or (placementArray[j][1] == placementArray[j+1][1] and placementArray[j][2] > placementArray[j+1][2]):
                        temp = placementArray[j+1]
                        placementArray[j+1] = placementArray[j]
                        placementArray[j] = temp
                        
            for i in range(len(placementArray)):
                self.engine.entMgr.entities[placementArray[i][0]].placement = i +1
                            
        # if the game has been won, print result panel to screen
        if self.winnerIndex != -1:
            myEnt = self.engine.entMgr.entities[self.engine.entMgr.playerIndex]
            myEnt.isReady = False
            # display medal
            if myEnt.placement == 1:
                self.finishPanel.panel.setMaterialName("Final-Gold")
            elif myEnt.placement == 2:
                    self.finishPanel.panel.setMaterialName("Final-Silver")
            else:
                self.finishPanel.panel.setMaterialName("Final-Bronze")
            #display final placement and time
            self.finalPlacement.setCaption(str(myEnt.placement))
            minutes = int(myEnt.totalTime / 60)
            seconds = int(myEnt.totalTime % 60)
            if seconds < 10:
                self.finalTime.setCaption(str(minutes) + ":0" + str(seconds))
            else:
                self.finalTime.setCaption(str(minutes) + ":" + str(seconds))
            self.finishPanel.showAll()                


    def resetGame(self):
        # reset game variables
        self.numRaces += 1
        self.winnerIndex = -1
        self.timePerLapText.setCaption("--")
        self.timePerLapText.setPosition(840,50)
        self.initialCountdownTime = 4
        self.gameStarted = False
        self.allPlayersReady = False
        self.countdownText.setCaption("")
        self.countdownText.show()
        self.engine.netMgr.timeToWaitForPlayers = 10
        # reset all values for all entities
        for i in range(len(self.engine.entMgr.entities)):
            self.engine.entMgr.entities[i].pos = ogre.Vector3(const.INNER_RADIUS + 100 +(40*i),50,0)
            self.engine.entMgr.entities[i].dir = ogre.Vector3(0,0,-1)
            self.engine.entMgr.entities[i].speed = 0
            self.engine.entMgr.entities[i].colVel = ogre.Vector3(0,0,0)
            self.engine.entMgr.entities[i].updateQueue = deque(maxlen = 1000)
            self.engine.entMgr.entities[i].placement = 0
            self.engine.entMgr.entities[i].lap = 0
            self.engine.entMgr.entities[i].checkpoint = 0
            self.engine.entMgr.entities[i].positionAngle = 0
            self.engine.entMgr.entities[i].totalTime = 0.0
            self.engine.entMgr.entities[i].pitch = 0.0
            self.engine.entMgr.entities[i].roll = 0.0
Beispiel #19
0
class Grid(object):
    def __init__(self, geometry, grid_update):
        self.x1 = 0
        self.y1 = 0

        self.x2 = geometry.width - 1
        self.y2 = geometry.height - 1

        self.click_type = 0

        self.grid_update = grid_update
        self.overlay = Overlay(geometry, handler=self.key_event)
        self.update_overlay()

    def key_event(self, key, modifiers):
        if key == Qt.Key_Escape:
            self.exit()

        elif key == Qt.Key_Return:
            if Qt.ShiftModifier & modifiers:
                self.click_type = 3
            else:
                self.click_type = 1
            self.exit()

        elif key in KEY_MAP:
            self.resize(*KEY_MAP[key])
            self.update_overlay()

    def exit(self):
        self.overlay.exit()

    def update_overlay(self):
        gridlines = self.make_gridlines()
        self.overlay.set_gridlines(gridlines)
        self.overlay.update()

        self.grid_update(self)

    def click_pos(self):
        xpos = int(round((self.x1 + self.x2) / 2))
        ypos = int(round((self.y1 + self.y2) / 2))

        return xpos, ypos

    def resize(self, xl, yl):
        dx = (self.x2 - self.x1) / 9
        dy = (self.y2 - self.y1) / 9

        xs = [int(round(self.x1 + i * dx)) for i in range(10)]
        ys = [int(round(self.y1 + i * dy)) for i in range(10)]

        if xl is not None:
            self.x1 = xs[xl + 4]
            self.x2 = xs[xl + 5]
        if yl is not None:
            self.y1 = ys[yl + 4]
            self.y2 = ys[yl + 5]

    def make_gridlines(self):
        dx = (self.x2 - self.x1) / 9
        dy = (self.y2 - self.y1) / 9

        for i in range(8):
            x = int(round(self.x1 + i * dx + dx))
            y = int(round(self.y1 + i * dy + dy))

            if i in (2, 5):
                yield MajorLine(x, self.y1, x, self.y2)
                yield MajorLine(self.x1, y, self.x2, y)
            else:
                yield MinorLine(x, self.y1, x, self.y2)
                yield MinorLine(self.x1, y, self.x2, y)
class DrawHandler(threading.Thread):
    def __init__(self, handler):
        threading.Thread.__init__(self)

        self.max_rate = 60
        self.rate = Rate(self.max_rate)
        self.cursor_pos = (0, 0)
        self.image = cv2.imread('test2.jpg')
        self.width = self.image.shape[1]
        self.height = self.image.shape[0]
        self.screen = None
        self.overlay = Overlay()

        self.name = "Roundabout Map"
        cv2.namedWindow(self.name)
        cv2.setMouseCallback(self.name, self.mouse_event)

        self.event = 200

        self.handler = handler
        handler.overlay = self.overlay

    def mouse_event(self, event, x, y, flags, param):
        self.event = 200
        self.cursor_pos = (x, y)
        self.handler.mouse_event(event, x, y)

    def run(self):
        while True:
            key = cv2.waitKey(1) & 0xFF
            if key == 27:
                self.handler.shutdown()
                self.shutdown()
                break
            self.handler.keyboard_event(key)
            self.handler.overlay_event()

            if self.handler.update():
                self.screen = copy.copy(self.image)
                for node in self.handler.graph.nodes:
                    cv2.circle(self.screen, (node.pos[0], node.pos[1]), 2,
                               (0, 0, 255), 2)
                    for lane in node.lanes:
                        cv_ext.draw_arrowed_polyline(self.screen, lane.points,
                                                     (0, 255, 255))

                for lane in self.handler.graph.lanes:
                    cv2.polylines(self.screen, [np.array(lane.polygon)], False,
                                  (0, 255, 255))

                if self.handler.mark is not None:
                    cv2.circle(self.screen,
                               (self.handler.mark[0], self.handler.mark[1]), 5,
                               (0, 0, 255), 1)

                if self.handler.snapy is not None:
                    cv2.circle(self.screen,
                               (self.handler.snapy[0], self.handler.snapy[1]),
                               5, (0, 0, 0), 1)

                for border in self.handler.graph.borders:
                    cv2.line(self.screen,
                             (border.node_a.pos[0], border.node_a.pos[1]),
                             (border.node_b.pos[0], border.node_b.pos[1]),
                             (255, 0, 0), 2)

            vis = copy.copy(self.screen)
            self.overlay.setCursor(self.cursor_pos)
            self.overlay.draw(vis)
            self.overlay.clear()
            if self.event > 1:
                self.event -= 1

            cv2.imshow(self.name, vis)
            self.rate.sleep_rate(self.event)

    def shutdown(self):
        cv2.destroyAllWindows()
Beispiel #21
0
from loader import Loader
from overlay import Overlay
from relocator import Relocator

if __name__ == "__main__":
    loader = Loader("start.exe")
    loader.fetch_header()
    relocator = Relocator(loader)
    program = loader.load_program()
    overlay = Overlay("game.ovr", program)
    overlay.overlay_code()
    header = loader.header
    print(header)

    for instruction in program:
        print("%s %s" % (instruction.address, instruction))
Beispiel #22
0
def run(nsjail_bin,
        chroot,
        source_dir,
        command,
        android_target,
        dist_dir=None,
        build_id=None,
        max_cpus=None,
        user_id=None,
        group_id=None):
  """Run inside an NsJail sandbox.

  Args:
    nsjail_bin: A string with the path to the nsjail binary.
    chroot: A string with the path to the chroot.
    source_dir: A string with the path to the Android platform source.
    command: A list of strings with the command to run.
    android_target: A string with the name of the target to be prepared
      inside the container.
    dist_dir: A string with the path to the dist directory.
    build_id: A string with the build identifier.
    max_cpus: An integer with maximum number of CPUs.
    user_id: An integer with the user ID to run the build process under.
    group_id: An integer with the group ID to run the build process under.

  Returns:
    A list of commands that were executed. Each command is a list of strings.
  """
  executed_commands = []

  if user_id and group_id:
    commands = create_user(user_id, group_id)
    executed_commands.extend(commands)
    os.setgid(group_id)
    os.setuid(user_id)

  overlay = None
  # Apply the overlay for the selected Android target
  # to the source directory if overlays are present
  if os.path.exists(os.path.join(source_dir, 'overlays')):
    overlay = Overlay(android_target, source_dir)

  script_dir = os.path.dirname(os.path.abspath(__file__))
  config_file = os.path.join(script_dir, 'nsjail.cfg')
  nsjail_command = [
      nsjail_bin,
      '--bindmount', source_dir + ':/src',
      '--chroot', chroot,
      '--env', 'USER=android-build',
      '--config', config_file
  ]
  if dist_dir:
    nsjail_command.extend([
        '--bindmount', dist_dir + ':/dist',
        '--env', 'DIST_DIR=/dist'
    ])
  if build_id:
    nsjail_command.extend(['--env', 'BUILD_NUMBER=%s' % build_id])
  if max_cpus:
    nsjail_command.append('--max_cpus=%i' % max_cpus)

  nsjail_command.append('--')
  nsjail_command.extend(command)

  print('NsJail command:')
  print(' '.join(nsjail_command))
  subprocess.check_call(nsjail_command)
  executed_commands.append(nsjail_command)

  # Strip out overlay
  del overlay

  return executed_commands
Beispiel #23
0
 def unscale(self, factor):
     Overlay.unscale(self, factor)
     self.line.setPen(self.pen)
 def unscale(self, factor):
     Overlay.unscale(self, factor)
     self.up()
Beispiel #25
0
class Manager(signalutil.Runner):
    def __init__(self, port=DEFAULT_MANAGER_PORT):
        signalutil.Runner.__init__(self)
        self.port = port
        self.overlay = Overlay()
        self.name_store = NameStore(self.overlay)
        self.type_store = TypeStore(self.overlay)
        self.migration_store = MigrationStore(self.overlay)
        self.script_store = ScriptStore(self.overlay)
        self.socket_store = SocketStore(self.overlay)

    def begin(self):
        loc = ManagerExternalInterface(
            self.overlay, self.name_store, self.type_store, self.migration_store, self.script_store, self.socket_store
        )
        port = self.port
        while port < self.port + 10:
            if self.takeport(port, loc):
                self.port = port
                break
            port = port + 1
        log.debug(self, "listening on port %s" % port)
        here = socket.gethostbyname(socket.gethostname()) + ":%d" % self.port
        ipfinder.create_ip_server(DEFAULT_MANAGER_PORT - 1)
        self.overlay.here(here)
        self.overlay.populate(sys.argv)
        vis.add_manager(here)
        self.shell()

    def takeport(self, port, loc):
        try:
            self.__valve = rpc.RPCValve(port, loc, log)
            self.__valve.listen()
            return True
        except socket.error:
            return False

    def shutdown(self):
        log.debug(self, "shutting down")
        try:
            self.__valve.shutdown()
            print "closing port"
        except socket.error as e:
            print "ERROR:", e.args

    def __str__(self):
        return "Manager"

    def shell(self):
        print "Welcome to Stage#"
        execute = True
        while execute:
            if True:
                print (gethostname() + ":%d>" % self.port),
                command = sys.stdin.readline().strip()
                if command == "exit":
                    execute = False
                else:
                    try:
                        exec (command)
                    except:
                        print "command not found"
        self.shutdown()
        sys.exit()
Beispiel #26
0
def main():
    """
    Sets up all the relevent object needed to run the game. This includes the 
    game engine, player, and all enemies in the game. The player and enemies load
    thier sprites from a list of paths in a json file that is loaded and referenced
    in a dict at the start. Once initalization finishes the game loop is run until
    the user exits. 
    """
    engine = neon_engine.NeonEngine('Neon Souls')

    engine.init_pygame()

    with open('player_sprites.json', 'r') as p_file:
        player_sprites = json.load(p_file)

    with open('sentinal_sprites.json') as file:
        sentinal_sprites = json.load(file)

    player_static = player_sprites['static_sprites']
    player_walking = player_sprites['walking_sprites']
    player_running = player_sprites['running_sprites']

    sentinal_sprites = sentinal_sprites['sprite_list']

    player = Player(player_static, player_walking, player_running, (128, 128),
                    'default', 2, 300, 400)
    engine.player_instance = player

    sentinal1 = SentinalEnemy(sentinal_sprites, (100, 100), [(400, 500),
                                                             (600, 500)],
                              engine.kill_enemy, 2, 300, 475)
    sentinal2 = SentinalEnemy(sentinal_sprites, (100, 100), [(1100, 0),
                                                             (1300, 0)],
                              engine.kill_enemy, 2, 1200, 400)
    sentinal3 = SentinalEnemy(sentinal_sprites, (100, 100), [(1500, 0),
                                                             (1700, 0)],
                              engine.kill_enemy, 2, 1600, 450)

    engine.enemy_list.append(sentinal1)
    engine.enemy_list.append(sentinal2)
    engine.enemy_list.append(sentinal3)
    gravity_manager = GravityManager()
    gravity_manager.add_gravity('default', (0, 15))

    gravity_manager.add_object(player)

    # create background and level
    init_map(engine, player, gravity_manager)

    overlay = Overlay(player)
    engine.objects.append(overlay)
    engine.drawables.add(overlay)

    pygame.time.set_timer(pygame.USEREVENT + 1,
                          1000 // league.Settings.gameTimeFactor)
    engine.movement_function = player.move_player
    engine.action_function = fire
    engine.physics_functions.append(player.process_gravity)

    engine.events[pygame.QUIT] = engine.stop
    engine.run()
def main(args=None):

	overlay = Overlay()
	overlay.setupProtocol()
	overlay.startOverlay()
Beispiel #28
0
from PyQt5.QtCore import QTimer
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from overlay import Overlay

if __name__ == '__main__':
    app_context = ApplicationContext()
    overlay = Overlay(app_context)
    gui_updater_timer = QTimer(overlay)
    gui_updater_timer.timeout.connect(overlay.gui_updater)
    gui_updater_timer.start(100)

    overlay.show()
    app_context.app.exec_()
Beispiel #29
0
class App(Configurable):

    #
    #   CLASS VARIABLES
    #
    # data about this program
    PRG_NAME = 'Scrapless'
    PRG_VERS = '1.0.1.4'

    # path for config file
    SLF_PATH = './data/json/config/config.json'

    # path to manifest folder
    MNF_PATH = 'C:/ProgramData/Epic/EpicGamesLauncher/Data/Manifests/'

    # logging paths
    LOG_PATH = './logging/log/'
    ERR_PATH = './logging/err/'
    IMG_PATH = './logging/img/'

    # max exceptions before abandoning the reading
    MAX_EXC = 5

    # time variables
    LOOP_INTER = 0.2
    BNTY_INTER = 1.5
    LBBY_INTER = 0.25
    LOOT_INTER = 0.5

    def __init__(self):

        # PREPARE LOGGING FIRST TO ENSURE
        # THE ABILITY TO OUTPUT ERROR LOGS
        #
        # create logging folders
        self._makeLogDirs()

        # initialise the logger
        self.logger = self._setLogger()

        # catch exceptions to log them
        try:

            # call parent class constructor
            Configurable.__init__(self, self.SLF_PATH)

            # initialise overlay
            self.overlay = Overlay(f'{self.PRG_NAME.upper()} {self.PRG_VERS}')

            # point pytesseract at tesseract installation
            self._setPyTesseract()

            # initialise a lobby reader
            self.lobby_reader = LobbyReader()

            # initialise a loot reader
            self.loot_reader = LootReader()

            # initialise a bounty reader
            self.bounty_reader = BountyReader()

            # initialise a data sender
            self.data_sender = DataSender()

            # read user from config file
            self.user = self._setUser()

            # read game patch
            self.patch = self._setGamePatch()

            # initialise screen capture as empty
            self.screen_capture = None

            # data holders
            self.bounty_data = {}
            self.lobby_data = {}
            self.loot_data = []

            # exception counter for repeated issue handling
            self.exc_counter = 0

            # welcome the user
            self.welcomeMessage()

        except Exception as e:

            # log the exception
            self.logger.error(str(e))

            # shut down the app
            quit()

    '''
    Capture new screenshot and store it within
    the instance of this class
    '''

    def screenCap(self):

        # take the screencap
        screencap = pyautogui.screenshot(region=(0, 0, 1920, 1080))

        #  overwrite the capture with screencap converted to a numpy array
        self.screen_capture = np.array(screencap)

    '''
    Main method of operation, calls associated readers to detect the screen and read it out
    if recognised.
    '''

    def processScreen(self):

        # process the lobby if needed
        self._processLobby()

        # process the loot if needed
        self._processLoot()

        # process bounty draft if needed
        self._processBounty()

        # submit data if needed
        self._submitData()

    '''
    Method for quickly clearing all data in the app
    '''

    def clearData(self):

        # return data holders to base state
        self.bounty_data = {}
        self.lobby_data = {}
        self.loot_data = []

    '''
    Method for writing out a welcome message in the application
    '''

    def welcomeMessage(self):

        self.logger.info(f'==== WELCOME TO SCRAPLESS {self.PRG_VERS} ====')
        self.logger.info(f'Dauntless ver {self.patch}')
        self.logger.info(f'Username set to {self.user}')

        print('\n')

    '''
    Method for printing out an output to logs and to overlay
    This is a convenience function to reduce clutter and keep 
    user information level high
    '''

    def writeOutput(self, text, colour):

        # only call the overlay method if said overlay is enabled
        if self.overlay:
            self.overlay.writeLine(text.replace('\n', ''), colour)

        # write out to log
        self.logger.info(text)

        # in case of a success
        if colour == 'success':

            # reset exception counter
            self.exc_counter = 0

        # in case of error
        if colour == 'error':

            # save current screen
            cv2.imwrite(f'{self.IMG_PATH}{uuid4()}.png',
                        cv2.cvtColor(self.screen_capture, cv2.COLOR_RGB2BGR))

            # clear data
            self.clearData()

    '''
    Internal method for keeping track of repeating reading issues; clears all data
    after enough issues happened
    '''

    def _incrementException(self):

        # increment exception counter
        self.exc_counter += 1

        # check if exception count exceeded max
        if self.exc_counter >= self.MAX_EXC:

            # write out an error message
            self.writeOutput(
                f'Repeated issues detected. Screenshot saved, all data flushed',
                'error')

            # reset exception counter
            self.exc_counter = 0

    '''
    Method for creating folders for logging
    In: nothing
    Out: nothing
    '''

    def _makeLogDirs(self):

        # iterate over necessary paths
        for path in [self.LOG_PATH, self.ERR_PATH, self.IMG_PATH]:

            # create folder if it does not exist
            if not os.path.exists(path):
                os.makedirs(path)

    '''
    Internal method for detecting and processing bounty draft
    Updates bounty data as a result, unless an exception happens
    '''

    def _processBounty(self):

        # read only if both bounty and loot data is empty
        if len(self.bounty_data) <= 0 and len(self.loot_data) <= 0:

            # proceed if draft can be detected
            if self.bounty_reader.detectDraftStart(self.screen_capture):

                # inform the user about the fact
                self.writeOutput(f'Bounty draft detected, processing...',
                                 'info')

                # wait out the initial animation
                time.sleep(self.BNTY_INTER)

                # enter a loop of attempting to read the bounty
                self._processBountyLoop()

    '''
    Convenience function to keep attempting a bounty read until succeeding or
    detecting that user exited the screen
    '''

    def _processBountyLoop(self):

        # keep looping until valid bounty was read, or the user left the draft screen
        while len(self.bounty_data
                  ) <= 0 and not self.bounty_reader.detectDraftEnd(
                      self.screen_capture):

            # capture a new screenshot
            self.screenCap()

            # attempt to read the bounty
            try:

                # store the data
                self.bounty_data = self.bounty_reader.readScreen(
                    self.screen_capture)

                # inform the user
                self.writeOutput(
                    f'{self.bounty_data["rarity"]} bounty detected. Awaiting draft end...',
                    'success')

            # in case illegal value was found
            except ValueError as e:
                self.writeOutput(str(e), 'warning')

            # wait briefly to get a better screen read
            time.sleep(self.LOOP_INTER)

    '''
    Internal method for detecting and processing lobby screen
    more functional
    Updates lobby data as a result, unless an exception happens
    '''

    def _processLobby(self):

        # try to read lobby only if no hunt data yet
        if len(self.lobby_data) <= 0:

            # detect if the screen is a lobby
            if self.lobby_reader.detectScreen(self.screen_capture):

                # inform about detection
                self.writeOutput(f'Lobby screen detected, processing...',
                                 'info')

                # wait briefly to avoid unnecessary errors
                time.sleep(self.LBBY_INTER)

                # enter the lobby-reading loop
                self._processLobbyLoop()

    '''
    Convenience function to keep attempting a lobby read until succeeding or
    detecting that user exited the screen
    '''

    def _processLobbyLoop(self):

        # while we can still see the lobby and we have no lobby data
        while self.lobby_reader.detectScreen(
                self.screen_capture) and len(self.lobby_data) <= 0:

            # update screen grab
            self.screenCap()

            # attempt reading the screen
            try:

                # process lobby screen and save the data
                self.lobby_data = self.lobby_reader.readScreen(
                    self.screen_capture)

                # write appropriate output
                self._processLobbyOutput()

            # handle an exception
            except ValueError as e:

                # communicate the exception to the user
                self.writeOutput(str(e), 'warning')

            # wait briefly to get a better screen read
            time.sleep(self.LOOP_INTER)

    '''
    Convenience function encompassing all possible text output for
    when the program has read the lobby without any issues
    '''

    def _processLobbyOutput(self):

        # get data to memory briefly, to simplify access
        data = self.lobby_data

        # if trial screen
        if 'Trial' in data['tier']:

            # report on trial tier
            self.writeOutput(f'{data["tier"]} detected', 'success')

        # otherwise, if escalation screen
        elif data['escalation'] != '':

            # report on escalation
            self.writeOutput(
                f'Valid hunt detected: {data["escalation"]}. ' +
                f'Loot data won\'t be recorded.', 'info')

        # otherwise, if actual behemoth
        elif data['behemoth'] != '':

            # report read data
            self.writeOutput(
                f'Valid hunt detected -- T{data["threat"]} ' +
                f'{data["behemoth"] if data["behemoth"] != data["tier"] else ""}'
                + f'{", " if data["behemoth"] != data["tier"] else ""}' +
                f'{data["tier"]} {data["type"]}. ' +
                f'Awaiting loot screen...', 'success')

    '''
    Internal method for detecting and processing loot screen
    Updates loot data as a result, unless an exception happens
    In: none
    Out: none
    '''

    def _processLoot(self):

        # try to read loot only if lobby data present
        if len(self.lobby_data) > 0 and len(self.loot_data) <= 0:

            # if trial, detect for trial end screen
            if 'Trial' in self.lobby_data['tier']:

                # check for trial end screen
                if self.loot_reader.detectTrialEnd(self.screen_capture):

                    # inform the user, abandon processing
                    self.writeOutput(f'{self.lobby_data["tier"]} has ended',
                                     'success')
                    self.clearData()

            # otherwise detect for loot screen
            else:

                # detect if screen is a loot screen
                if self.loot_reader.detectLootScreen(self.screen_capture):

                    # check if the hunt was an Escalation
                    if self.lobby_data['escalation'] != '':

                        # inform the user, abandon processing
                        self.writeOutput(
                            f'Escalation run ended, no data will be submitted',
                            'success')
                        self.clearData()

                    # otherwise enter the loop of reading the screen
                    else:

                        # wait briefly to ensure animation end
                        time.sleep(self.LOOT_INTER)

                        # start the loop
                        self._processLootLoop()

    '''
    Convenience function for loot screen reading loop
    '''

    def _processLootLoop(self):

        # only try reading until we have loot data or until we leave the screen
        while len(self.loot_data) <= 0 and self.loot_reader.detectLootScreen(
                self.screen_capture) and len(self.lobby_data) > 0:

            # take a new screencap
            self.screenCap()

            # process basic loot screen data
            data = self.loot_reader.readScreen(self.screen_capture)

            # check if the party was defeated
            if data['defeat']:

                # inform the user, abandon processing
                self.writeOutput(f'Party defeated, no data will be submitted',
                                 'warning')
                self.clearData()

            # otherwise, check if valid hunt
            elif data['behemoth'] == self.lobby_data[
                    'behemoth'] or self.lobby_data[
                        'behemoth'] in self.lobby_reader.valid_hunts.keys():

                # inform that more in-depth reading will now take place
                self.writeOutput(f'Loot screen detected, verifying...', 'info')

                # update lobby data
                self.lobby_data.update(data)

                # attempt to read the loot
                try:
                    # store loot data in memory
                    self.loot_data = self.loot_reader.readLoot(
                        self.screen_capture, self.lobby_data['behemoth'])
                    self.loot_data = self._processLootData()

                    # inform that everything is okay
                    self.writeOutput(
                        f'Valid loot data read, you may now leave the screen',
                        'success')

                # in case OCR read anomalous stack of items, handle error internally
                except ValueError as e:
                    self.writeOutput(str(e), 'error')

            # inform the reading will be attempted again
            else:
                self.writeOutput(
                    f'Expected behemoth {self.lobby_data["behemoth"]} but found '
                    + f'{data["behemoth"]}, retrying...', 'warning')
                self._incrementException()

            # wait briefly to get a better screenshot
            time.sleep(self.LOOP_INTER)

    '''
    Internal method for sampling the loot data into what will be submitted
    In: nothing
    Out: sampled data
    '''

    def _processLootData(self):

        # determine slay roll count
        slay_rolls = 2 + (3 - self.lobby_data['deaths']) + (
            2 * self.lobby_data['elite'])

        # compensate for a bug with Elite loot display
        slay_rolls -= 2 * (self.lobby_data['tier'] == 'Heroic+'
                           and self.lobby_data['behemoth']
                           not in ['Shrowd', 'Rezakiri']
                           and self.lobby_data['elite'])

        # calculate how many drops to sample out from the data
        # sampling is necessary because of numerous display bugs on loot screen
        sample_count = slay_rolls * 2 if len(
            self.loot_data) >= slay_rolls * 2 else slay_rolls

        # fill submission data with dyes and cells if present -- we always add them to submission data
        # because they can't drop from part break
        submit_data = [
            drop for drop in self.loot_data if drop['rarity'] in
            ['Artifact (Dye)', 'Rare (Cell)', 'Uncommon (Cell)']
        ]

        # data from which to draw samples
        source_data = [
            drop for drop in self.loot_data if drop['rarity'] not in
            ['Artifact (Dye)', 'Rare (Cell)', 'Uncommon (Cell)']
        ]

        # in the event of sample count being higher than valid loot, take number of items
        # in the loot - this is a safeguard against low-level hunts dropping part breaks on
        # slay rolls
        sample_count = min(sample_count, len(self.loot_data))

        # draw the samples, reducing their number by dye drops present
        sample_data = random.sample(source_data,
                                    sample_count - len(submit_data))

        # return sampled data
        return [*submit_data, *sample_data]

    '''
    Method for initialising the logger and returning it
    In: nothing
    Out: logger object
    '''

    def _setLogger(self):

        # compose file name containing date and name of the program
        file_name = f'{datetime.now().date()}_{self.PRG_NAME.lower()}'

        # set some basic information to work from going forward
        LOG_FRMT = '%(asctime)s %(message)s'
        DATE_FMT = '%d/%m/%Y %H:%M:%S'
        LOG_NAME = 'scrapless'
        INF_FILE = f'{self.LOG_PATH}{file_name}.log'
        ERR_FILE = f'{self.ERR_PATH}{file_name}.err'

        # create logger and configure its format
        logger = logging.getLogger(LOG_NAME)
        log_formatter = logging.Formatter(LOG_FRMT)

        # create a stream handler so logging goes to console
        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(log_formatter)
        logger.addHandler(stream_handler)

        # configure the logger for INFO logging
        # appending to files to support multiple sessions in one day
        file_handler_info = logging.FileHandler(INF_FILE, mode='a')
        file_handler_info.setFormatter(log_formatter)
        file_handler_info.setLevel(logging.INFO)
        logger.addHandler(file_handler_info)

        # configure the logger for ERROR logging
        # appending to files to support multiple sessions in one day
        file_handler_error = logging.FileHandler(ERR_FILE, mode='a')
        file_handler_error.setFormatter(log_formatter)
        file_handler_error.setLevel(logging.ERROR)
        logger.addHandler(file_handler_error)

        # set logger level to INFO and higher
        logger.setLevel(logging.INFO)

        return logger

    '''
    Method for configuring PyTesseract from config file
    Reads the path and sets it to a global value
    Raises an exception if the path is missing or does not point to a file
    '''

    def _setPyTesseract(self):

        # retrieve tesseract path from config
        tess_path = self.readKey('tesseract')

        # verify the path is a string
        if type(tess_path) == str:

            # verify path leads to a file
            if os.path.isfile(tess_path):

                # use the path read from config to setup pytesseract
                pytesseract.pytesseract.tesseract_cmd = tess_path

                # return the path
                return tess_path

            # otherwise raise an exception
            raise FileNotFoundError(
                f'file {tess_path} is not a file or could not be read')

    '''
    Internal method to automatically accesses the manifest file created by Epic Games Store
    In: none
    Out: string number of game version
    '''

    def _setGamePatch(self):

        # check if the manifest folder exists
        if os.path.isdir(self.MNF_PATH):

            # get the manifest items in the directory
            manifs = glob(self.MNF_PATH + '*.item')

            # check if there are any manifest items there
            if len(manifs) > 0:

                # iterate over file paths
                for item_path in manifs:

                    # open a manifest file
                    item_file = open(item_path, 'r')

                    # parse file into JSON
                    item = json.load(item_file)

                    # check if the file contains Dauntless data
                    if item['DisplayName'] == 'Dauntless':

                        # get patch version
                        patch_ver = '.'.join(
                            item['AppVersionString'].split('.')[:3])

                        # return patch version
                        return patch_ver

                # raise an exception if we iterated through all items without finding
                # a Dauntless manifest
                raise FileNotFoundError(
                    f'Dauntless manifest file could not be found')

            # if not, raise an exception
            else:
                raise FileNotFoundError(
                    f'no manifest files found in {self.MNF_PATH}')

        # if not, raise exception
        else:
            raise NotADirectoryError(f'{self.MNF_PATH} is not a directory')

    '''
    Internal method for initialising the user and checking all necessary details about them
    In: none
    Out: string name of user
    '''

    def _setUser(self):

        # read the user key from config file
        user = self.readKey('user')

        # check if the user value is empty
        if user == '':

            # replace empty name with random ID string
            user = str(uuid4())

            # create an updated version of the config to over-write current one with
            new_conf = self.conf_file

            # overwrite user value
            new_conf['user'] = user

            # overwrite the file
            with open(self.conf_path, 'w') as write_file:
                json.dump(self.conf_file,
                          write_file,
                          indent=2,
                          separators=(',', ':'))

        # return the user name
        return user

    '''
    Internal method for submitting data, based on what data is filled at the moment
    In: none
    Out: none
    '''

    def _submitData(self):

        # if loot data is not empty, submit loot data
        if len(self.loot_data) > 0:

            # iterate over drops
            for drop in self.loot_data:

                # add game and patch data
                drop['user'] = self.user
                drop['patch'] = self.patch
                drop['behemoth'] = self.lobby_data['behemoth']
                drop['threat'] = self.lobby_data['threat']
                drop['tier'] = self.lobby_data['tier']

                # try submitting the drop
                try:
                    # send POST request
                    self.data_sender.submitData(drop, 'loot')

                # raise exception if encountered
                except HTTPError as e:
                    self.writeOutput(str(e), 'error')

            # inform about data submission
            self.writeOutput(f'Loot data submitted', 'success')

            # clear the data
            self.clearData()

        # if bounty data is not empty
        if len(self.bounty_data) > 0:

            # check if draft screen was closed
            if self.bounty_reader.detectDraftEnd(self.screen_capture):

                # add game and patch data
                self.bounty_data['user'] = self.user
                self.bounty_data['patch'] = self.patch

                # try submitting the bounty
                try:
                    # send a POST request
                    self.data_sender.submitData(self.bounty_data, 'bounty')

                    # inform about data submission
                    self.writeOutput(f'Bounty data submitted', 'success')

                # raise exception if encountered
                except HTTPError as e:
                    self.writeOutput(str(e), 'error')

                # empty the data
                self.clearData()
Beispiel #30
0
    userFolder = str(sys.argv[2])
    ownIP = str(sys.argv[3])
    ownPort = int(sys.argv[4])
    bootstrapIP = str(sys.argv[5])
    bootstrapPort = int(sys.argv[6])
    TCPPortStart = int(sys.argv[7])
    TCPPortCount = int(sys.argv[8])
    watcherIP = str(sys.argv[9])
else:
    userName = "******"          #str(argv[1])
    userFolder = "User1/"       #str(argv[2])
    ownIP = "localhost"         #str(argv[3])
    ownPort = 50001             #int(argv[4])
    bootstrapIP = "localhost"   #str(argv[5])
    bootstrapPort = 50000       #int(argv[6])
    TCPPortStart = 60010        #int(argv[7])
    TCPPortCount = 10           #int(argv[8])
    watcherIP = "localhost"     #str(argv[9])

# initialize and start overlay layer
overlay = Overlay(userName, ownIP, ownPort, bootstrapIP, bootstrapPort, n2o, o2n, a2o, o2a, watcherQ)
application = Application(userFolder, o2a, a2o)
network1 = Network(userFolder, ownIP, ownPort, TCPPortStart, TCPPortCount, n2o, o2n, watcherQ, watcherIP, 2)
network1.run()

while not raw_input() == 'e':
    pass

application.terminate()
overlay.terminate()
network1.terminate()
class NodeEditor(QFrame):

    # ========================== init stuff ========================== #

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.viewport_y = 0  # top visible line
        self.imagemode = False
        self.image = None

        self.scroll_height = 0
        self.scroll_width = 0

        self.timer = QTimer(self)
        self.backuptimer = QTimer(self)
        self.connect(self.timer, SIGNAL("timeout()"), self.analysis_timer)
        self.connect(self.backuptimer, SIGNAL("timeout()"), self.backup_timer)
        self.backuptimer.start(30000)
        self.undotimer = QTimer(self)
        self.connect(self.undotimer, SIGNAL("timeout()"),
                     self.trigger_undotimer)

        self.blinktimer = QTimer(self)
        self.blinktimer.start(500)
        self.connect(self.blinktimer, SIGNAL("timeout()"),
                     self.trigger_blinktimer)
        self.show_cursor = True

        self.boxcolors = [
            QColor("#DC322F"),
            QColor("#268BD2"),
            QColor("#2Ac598"),
            QColor("#D33682"),
            QColor("#B58900"),
            QColor("#859900")
        ]
        self.setCursor(Qt.IBeamCursor)

        # Semi-transparent overlay.
        # Used to display heat-map visualisation of profiler info, etc.
        self.overlay = Overlay(self)
        # Always show the overlay, users hide visualisations with the HUD.
        self.overlay.show()

        # Show / don't show HUD visualisations.
        self.hud_callgraph = False
        self.hud_eval = False
        self.hud_heat_map = False
        self.hud_types = False

        self.autolboxlines = {}

    def hud_show_callgraph(self):
        self.hud_callgraph = True
        self.hud_eval = False
        self.hud_heat_map = False
        self.hud_types = False

    def hud_show_eval(self):
        self.hud_callgraph = False
        self.hud_eval = True
        self.hud_heat_map = False
        self.hud_types = False

    def hud_show_types(self):
        self.hud_callgraph = False
        self.hud_eval = False
        self.hud_heat_map = False
        self.hud_types = True

    def hud_show_heat_map(self):
        self.hud_callgraph = False
        self.hud_eval = False
        self.hud_heat_map = True
        self.hud_types = False

    def hud_off(self):
        self.hud_callgraph = False
        self.hud_eval = False
        self.hud_heat_map = False
        self.hud_types = False

    def focusOutEvent(self, event):
        self.blinktimer.stop()
        self.show_cursor = True
        self.update()

    def focusInEvent(self, event):
        self.blinktimer.start()

    def resizeEvent(self, event):
        self.overlay.resize(event.size())
        event.accept()

    def analysis_timer(self):
        if self.getWindow().show_namebinding():
            if self.tm.analyse() is not False:
                self.update()
                self.getWindow().updateASTOutline()
        self.timer.stop()

        # save swap
        filename = self.getEditorTab().filename
        if filename:
            self.saveToJson(filename + ".swp", True)

    def backup_timer(self):
        filename = self.getEditorTab().filename
        if filename:
            self.saveToJson(filename + ".bak", True)

    def trigger_blinktimer(self):
        if self.timer.isActive():
            self.show_cursor = True
            return
        self.show_cursor ^= True
        self.update()

    def trigger_undotimer(self):
        self.tm.undo_snapshot()
        self.undotimer.stop()

    def setImageMode(self, boolean):
        self.imagemode = boolean

    def reset(self):
        self.update()

    def set_mainlanguage(self, parser, lexer, lang_name):
        self.tm = TreeManager()
        self.tm.add_parser(parser, lexer, lang_name)

    def get_mainlanguage(self):
        return self.tm.parsers[0][2]

    def set_sublanguage(self, language):
        self.sublanguage = language

    def event(self, event):
        if event.type() == QEvent.ToolTip:
            pos = event.pos()
            temp_cursor = self.tm.cursor.copy()
            result = self.coordinate_to_cursor(pos.x(), pos.y())
            node = self.tm.cursor.node
            self.tm.cursor.line = temp_cursor.line
            self.tm.cursor.node = temp_cursor.node
            self.tm.cursor.pos = temp_cursor.pos
            if not result:
                QToolTip.hideText()
                event.ignore()
                return True
            # Draw errors, if there are any.
            msg = self.tm.get_error(node)
            if not msg:
                msg = self.tm.get_error_presentation(node)
            if msg:
                QToolTip.showText(event.globalPos(), msg)
                return True
            # Draw tooltips if there are any. Tooltips can appear with any HUD
            # visualisation.
            elif (self.hud_callgraph or self.hud_eval or self.hud_types
                  or self.hud_heat_map):
                strings = []
                annotes = node.get_annotations_with_hint(ToolTip)
                if self.hud_callgraph:
                    for annote in annotes:
                        if annote.has_hint(HUDCallgraph):
                            strings.append(annote.annotation)
                elif self.hud_eval:
                    for annote in annotes:
                        if annote.has_hint(HUDEval):
                            strings.append(annote.annotation)
                elif self.hud_types:
                    for annote in annotes:
                        if annote.has_hint(HUDTypes):
                            strings.append(annote.annotation)
                elif self.hud_heat_map:
                    for annote in annotes:
                        if annote.has_hint(HUDHeatmap):
                            strings.append(annote.annotation)
                msg = "\n".join(strings)
                if msg.strip() != "":
                    if self.tm.tool_data_is_dirty:
                        msg += "\n[Warning: Information may be out of date.]"
                    QToolTip.showText(event.globalPos(), msg)
                    return True
            QToolTip.hideText()
            event.ignore()
            return True
        return QFrame.event(self, event)

    # ========================== GUI related stuff ========================== #

    def blink(self):
        if self.show_cursor:
            self.show_cursor = 0
        else:
            self.show_cursor = 1
        self.update()

    def sliderChanged(self, value):
        self.viewport_y = value
        self.overlay.start_line = self.viewport_y
        self.update()

    def sliderXChanged(self, value):
        self.move(-value * self.fontwt, 0)
        self.resize(
            self.parentWidget().geometry().width() + value * self.fontwt,
            self.geometry().height())
        if self.x() == 0:
            self.updateGeometry()
        self.update()

    def getScrollSizes(self):
        total_lines = 0
        max_width = 0
        for l in self.lines:
            total_lines += l.height
            max_width = max(max_width, l.width)
        max_visible_lines = self.geometry().height() / self.fontht
        self.scroll_height = max(0, total_lines - max_visible_lines)

        current_width = self.parentWidget().geometry().width() / self.fontwt
        self.scroll_width = max(0, max_width - current_width)

    def paintEvent(self, event):
        # Clear data in the visualisation overlay
        self.overlay.clear_data()
        self.autolboxlines.clear()

        gfont = QApplication.instance().gfont
        self.font = gfont.font
        self.fontwt = gfont.fontwt
        self.fontht = gfont.fontht
        self.fontd = gfont.fontd
        QtGui.QFrame.paintEvent(self, event)
        paint = QtGui.QPainter()
        if self.imagemode:
            self.image = QImage()
            paint.begin(self.image)
        else:
            paint.begin(self)
        paint.setFont(self.font)

        self.longest_column = 0

        # calculate how many lines we need to show
        self.init_height = self.geometry().height()

        self.paintLines(paint, self.viewport_y)

        paint.end()

        total_lines = 0
        max_width = 0
        for l in self.lines:
            total_lines += l.height
            max_width = max(max_width, l.width)
        max_visible_lines = self.geometry().height() / self.fontht
        self.scroll_height = max(0, total_lines - max_visible_lines)

        current_width = self.parentWidget().geometry().width() / self.fontwt
        self.scroll_width = max(0, max_width - current_width)

        railroad_annotations = self.tm.get_all_annotations_with_hint(Railroad)
        self.overlay.add_railroad_data(railroad_annotations)

        self.emit(SIGNAL("painted()"))

    # paint lines using new line manager
    def paintLines(self, paint, startline):

        # find internal line corresponding to visual line
        visual_line = 0
        internal_line = 0
        for l in self.tm.lines:
            if visual_line + l.height > startline:
                break
            visual_line += l.height
            internal_line += 1

        x = 0
        y = visual_line - startline  # start drawing outside of viewport to display partial images
        self.paint_start = (internal_line, y)

        max_y = self.geometry().height() / self.fontht

        line = internal_line
        node = self.tm.lines[line].node

        _, _, self.end_line = self.paint_nodes(paint, node, x, y, line, max_y)

    #XXX if starting node is inside language box, init lbox with amount of language boxes

    def new_paint_nodes(self, paint, node, x, y, line, max_y, lbox=0):
        from nodepainter import NodePainter
        np = NodePainter(paint, node, x, y, line, max_y, lbox)
        np.cursor = self.tm.cursor
        np.repaint()
        self.lines = self.tm.lines
        self.cursor = self.tm.cursor
        return np.x, np.y, np.line

    def paint_nodes(self, paint, node, x, y, line, max_y, lbox=0):

        settings = QSettings("softdev", "Eco")
        colors = self.boxcolors
        if settings.value("app_theme", "Light").toString() in ["Dark"]:
            alpha = 100
            self.highlight_line_color = QColor(250, 250, 250, 20)
        elif settings.value("app_theme", "Light").toString() in ["Gruvbox"]:
            alpha = 100
            self.highlight_line_color = QColor(250, 250, 250, 20)
        else:
            alpha = 60
            self.highlight_line_color = QColor(0, 0, 0, 10)
        self.show_highlight_line = settings.value("highlight_line",
                                                  False).toBool()

        first_node = node
        selected_language = self.tm.mainroot

        highlighter = self.get_highlighter(node)
        selection_start = min(self.tm.selection_start, self.tm.selection_end)
        selection_end = max(self.tm.selection_start, self.tm.selection_end)
        if selection_start.node is not selection_end.node:
            if type(selection_start.node.symbol) is MagicTerminal:
                selection_start = selection_start.copy()
                selection_start.node = selection_start.node.symbol.ast.children[
                    0]
                selection_start.pos = 0
            if type(selection_end.node.symbol) is MagicTerminal:
                selection_end = selection_end.copy()
                selection_end.node = selection_end.node.symbol.ast.children[-1]
                selection_end.pos = 0
                selection_end.jump_left()
        draw_selection_start = (0, 0, 0)
        draw_selection_end = (0, 0, 0)
        start_lbox = self.get_languagebox(node)
        renderer = self.get_renderer(node)

        self.selected_lbox = self.tm.get_languagebox(self.tm.cursor.node)
        #XXX get initial x for langbox

        if start_lbox:
            lbox += 1
        if start_lbox and self.selected_lbox is start_lbox:
            draw_lbox = True
        else:
            draw_lbox = False

        draw_all_boxes = self.getWindow().show_languageboxes()

        self.lines = self.tm.lines
        self.cursor = self.tm.cursor
        self.lines[line].height = 1  # reset height
        draw_cursor = True
        show_namebinding = self.getWindow().show_namebinding()
        while y < max_y:

            # check if node is connected to auto lbox
            if node.autobox:
                if self.autolboxlines.has_key(line):
                    for box in node.autobox:
                        # Avoid duplicate suggestions by comparing the
                        # identities of language box candidates
                        exists = False
                        for b in self.autolboxlines[line]:
                            if b is box:
                                exists = True
                                break
                        if not exists:
                            self.autolboxlines[line].append(box)
                else:
                    self.autolboxlines[line] = list(node.autobox)

            # if we found a language box, continue drawing inside of it
            if isinstance(node.symbol, MagicTerminal):
                if self.tm.is_syntaxerror(node):
                    self.draw_vertical_squiggly_line(paint, x, y)
                lbox += 1
                lbnode = node.symbol.ast
                if self.selected_lbox is node:
                    color = colors[(lbox - 1) % len(colors)]
                    if not self.tm.is_syntaxerror(node):
                        self.draw_lbox_bracket(paint, '[', node, x, y, color)
                    draw_lbox = True
                    selected_language = lbnode
                else:
                    draw_lbox = False
                node = lbnode.children[0]
                highlighter = self.get_highlighter(node)
                renderer = self.get_renderer(node)
                continue

            if isinstance(node, EOS):
                lbnode = self.get_languagebox(node)
                if self.cursor.node is lbnode and self.show_cursor:
                    self.draw_cursor(paint, x, 4 + y * self.fontht)
                if lbnode:
                    color = colors[(lbox - 1) % len(colors)]
                    if lbox > 0:
                        lbox -= 1
                    node = lbnode.next_terminal()
                    highlighter = self.get_highlighter(node)
                    renderer = self.get_renderer(node)
                    if self.selected_lbox is lbnode:
                        # draw bracket
                        self.draw_lbox_bracket(paint, ']', node, x, y, color)
                        draw_lbox = False
                    lbnode = self.get_languagebox(node)
                    if lbnode and self.selected_lbox is lbnode:
                        draw_lbox = True
                    continue
                else:
                    self.lines[line].width = x / self.fontwt
                    break

            if isinstance(node.symbol.name, list):
                node = node.symbol.name[0]
                continue

            # draw language boxes
            if lbox > 0 and (draw_lbox or draw_all_boxes):
                if draw_all_boxes:
                    color = colors[(lbox - 1) % len(colors)]
                    color.setAlpha(alpha)
                else:
                    color = colors[0]
                    color.setAlpha(alpha)
                if draw_lbox and draw_all_boxes:  # we are drawing the currently selected language box
                    color.setAlpha(20)
                renderer.update_image(node)
                if node.symbol.name != "\r" and not isinstance(
                        node.symbol, IndentationTerminal):
                    if not node.image or node.plain_mode:
                        if isinstance(node, BOS) and isinstance(
                                node.next_term, EOS):
                            self.draw_lbox_hints(paint, node, x, y, color)
                        else:
                            paint.fillRect(
                                QRectF(x, 3 + y * self.fontht,
                                       len(node.symbol.name) * self.fontwt,
                                       self.fontht), color)

            # prepare selection drawing
            if node is selection_start.node:
                if node.lookup == "<return>":
                    sel_x = x
                else:
                    sel_x = x + selection_start.pos * self.fontwt
                draw_selection_start = (sel_x, y, line)

            if node is selection_end.node:
                draw_selection_end = (x + selection_end.pos * self.fontwt, y,
                                      line)

            # draw node
            dx, dy = renderer.paint_node(paint, node, x, y, highlighter)
            x += dx
            self.lines[line].height = max(self.lines[line].height, dy)

            # Draw footnotes and add heatmap data to overlay.
            annotes = [
                annote.annotation
                for annote in node.get_annotations_with_hint(Heatmap)
            ]
            # Heatmap data can always be sent to the overlay, it won't be
            # rendered unless the user selects the Heatmap HUD radio button.
            for annote in annotes:
                self.overlay.add_heatmap_datum(line + 1, annote)
            if self.hud_eval or self.hud_types:
                infofont = QApplication.instance().tool_info_font
                annotes = []
                annotes_ = node.get_annotations_with_hint(Footnote)
                if self.hud_eval:
                    for annote in annotes_:
                        if annote.has_hint(HUDEval):
                            annotes.append(annote)
                elif self.hud_types:
                    for annote in annotes_:
                        if annote.has_hint(HUDTypes):
                            annotes.append(annote)
                footnote = " ".join([annote.annotation for annote in annotes])
                if footnote.strip() != "":
                    if not self.tm.tool_data_is_dirty:
                        infofont.font.setBold(True)
                    else:
                        infofont.font.setBold(False)
                    paint.setFont(infofont.font)
                    paint.setPen(
                        QPen(QColor((highlighter.get_default_color()))))
                    start_y = self.fontht + ((y + 1) * self.fontht)
                    paint.drawText(QtCore.QPointF(x - dx, start_y), footnote)
                    self.lines[line].height = max(self.lines[line].height, 2)
                    paint.setFont(self.font)

            # after we drew a return, update line information
            if (node.lookup == "<return>"
                    or node.symbol.name == "\r") and not node is first_node:
                # draw lbox to end of line
                if draw_lbox or (draw_all_boxes and lbox > 0):
                    paint.fillRect(
                        QRectF(x, 3 + y * self.fontht,
                               self.geometry().width() - x, self.fontht),
                        color)

                self.lines[line].width = x / self.fontwt
                x = 0
                y += self.lines[line].height
                line += 1
                self.lines[line].height = 1  # reset height

            if self.show_highlight_line:
                if node.lookup == "<return>" or isinstance(node, BOS):
                    if self.cursor.line == line:
                        self.highlight_line(paint, y)

            # draw cursor
            if node is self.cursor.node and self.show_cursor:
                draw_x = max(0, x - dx)
                cursor_pos = self.cursor.pos

                if node.symbol.name == "\r":
                    cursor_pos = 0
                if node.image and not node.plain_mode:
                    draw_x = x
                    cursor_pos = 0
                self.draw_cursor(paint, draw_x + cursor_pos * self.fontwt,
                                 4 + y * self.fontht)

            if False and line == self.cursor.y and x / self.fontwt >= self.cursor.x and draw_cursor:
                draw_cursor_at = QRect(0 + self.cursor.x * self.fontwt,
                                       5 + y * self.fontht, 0, self.fontht - 3)
                paint.drawRect(draw_cursor_at)

                # set lbox info coordinates
                infobox_coordinates = (self.cursor.x * self.fontwt,
                                       (y + 1) * self.fontht)
                draw_cursor = False

            # draw errors using squiggly lines
            if show_namebinding and self.tm.is_typeerror(node):
                length = len(node.symbol.name) * self.fontwt
                self.draw_squiggly_line(paint, x - length, y, length, "orange")

            if self.tm.has_error_presentation(node):
                length = len(node.symbol.name) * self.fontwt
                self.draw_squiggly_line(paint, x - length, y, length, "blue")

            elif self.tm.is_syntaxerror(node):
                if isinstance(node, EOS):
                    length = self.fontwt
                else:
                    length = len(node.symbol.name) * self.fontwt
                self.draw_squiggly_line(paint, x - length, y, length, "red")

            node = node.next_terminal()

        if selection_start != selection_end:
            self.draw_selection(paint, draw_selection_start,
                                draw_selection_end, max_y)

        # paint infobox
        if False:
            lang_name = self.tm.parsers[selected_language]
            lang_status = self.tm.get_parser[selected_language][0].last_status
            if lang_status is True:
                color = QColor(100, 255, 100)
            else:
                color = QColor(255, 100, 100)
            paint.setFont(infofont)
            paint.fillRect(
                QRect(infobox_coordinates[0], 5 + infobox_coordinates[1],
                      len(lang_name) * infofontwt, infofontht), color)
            paint.drawText(
                QtCore.QPointF(infobox_coordinates[0],
                               -3 + self.fontht + infobox_coordinates[1]),
                lang_name)
            paint.setFont(self.font)

        return x, y, line

    def highlight_line(self, paint, y):
        width = self.parentWidget().geometry().width()
        paint.fillRect(QRect(-5, y * self.fontht + 3, width, self.fontht),
                       self.highlight_line_color)

    def draw_lbox_hints(self, paint, node, x, y, color):
        if node is self.cursor.node:
            return
        alpha = color.alpha()
        color.setAlpha(255)
        path = QPainterPath()
        x = x - 2
        y = y * self.fontht + 4

        path.moveTo(x, y)
        path.lineTo(x + 6, y)
        path.lineTo(x + 3, y + 3)
        path.lineTo(x, y)

        paint.fillPath(path, QBrush(color))
        color.setAlpha(alpha)

    def draw_lbox_bracket(self, paint, bracket, node, x, y, color):
        assert bracket in ['[', ']']
        oldpen = paint.pen()
        newpen = QPen()
        color.setAlpha(255)
        newpen.setColor(color)
        newpen.setWidth(1)
        paint.setPen(newpen)

        # paint brackets
        path = QPainterPath()
        if bracket == '[':
            if x == 0:
                tmpx = x + 2
            else:
                tmpx = x + 1  # adjust bracket position
            path.moveTo(tmpx, 3 + y * self.fontht)
            path.lineTo(tmpx - 2, 3 + y * self.fontht)
            path.moveTo(tmpx - 2, 3 + y * self.fontht)
            path.lineTo(tmpx - 2, 3 + y * self.fontht + self.fontht - 1)
        else:
            tmpx = x - 1
            path.moveTo(tmpx, 3 + y * self.fontht)
            path.lineTo(tmpx + 2, 3 + y * self.fontht)
            path.moveTo(tmpx + 2, 3 + y * self.fontht)
            path.lineTo(tmpx + 2, 3 + y * self.fontht + self.fontht - 1)
        path.lineTo(tmpx, 3 + y * self.fontht + self.fontht - 1)
        paint.drawPath(path)

        paint.setPen(oldpen)

    def draw_cursor(self, paint, x, y):
        pen = paint.pen()
        colorhex = self.palette().color(QPalette.Text)
        pen.setColor(QColor(colorhex))
        paint.setPen(pen)
        draw_cursor_at = QRect(x, y, 0, self.fontht - 3)
        paint.drawRect(draw_cursor_at)

    def draw_vertical_squiggly_line(self, paint, x, y):
        paint.setPen(Qt.CustomDashLine)
        pen = paint.pen()
        pen.setColor(QColor("red"))
        y = 3 + y * self.fontht
        pen.setDashPattern([4, 4])
        paint.setPen(pen)
        paint.drawLine(x - 2, y, x - 2, y + self.fontht)
        pen.setDashPattern([2, 2])
        paint.setPen(pen)
        paint.drawLine(x - 3, y + 3, x - 3, y + self.fontht)
        pen.setDashPattern([4, 4])
        paint.setPen(pen)
        paint.drawLine(x - 4, y + 4, x - 4, y + self.fontht)
        paint.setPen(Qt.SolidLine)

    def draw_squiggly_line(self, paint, x, y, length, color):
        paint.setPen(Qt.CustomDashLine)
        pen = paint.pen()
        pen.setColor(QColor(color))
        paint.setPen(pen)
        y = (y + 1) * self.fontht + 1
        pen.setDashPattern([4, 4])
        paint.setPen(pen)
        paint.drawLine(x, y + 2, x + length, y + 2)
        pen.setDashPattern([2, 2])
        paint.setPen(pen)
        paint.drawLine(x + 3, y + 1, x + length, y + 1)
        pen.setDashPattern([4, 4])
        paint.setPen(pen)
        paint.drawLine(x + 4, y, x + length, y)
        paint.setPen(Qt.SolidLine)

    def draw_selection(self, paint, draw_selection_start, draw_selection_end,
                       max_y):
        x1, y1, line1 = draw_selection_start
        x2, y2, line2 = draw_selection_end
        start = min(self.tm.selection_start, self.tm.selection_end)
        end = max(self.tm.selection_start, self.tm.selection_end)
        if x1 + y1 + line1 + x2 + y2 + line2 == 0:
            # everything out of viewport, draw nothing
            # unless start and end are on opposite sides of the viewport
            if not (start.line <= self.paint_start[0]
                    and end.line >= self.paint_start[0] + max_y):
                return
        if x1 + y1 + line1 == 0:
            # start outside of viewport
            line1 = self.paint_start[0]
        if x2 + y2 + line2 == 0:
            # end outside of viewport
            line2 = self.paint_start[0] + max_y
            y2 = max_y
        if y1 == y2:
            paint.fillRect(
                QRectF(x1, 3 + y1 * self.fontht, x2 - x1, self.fontht),
                QColor(0, 0, 255, 100))
        else:
            width = max(self.fontwt, self.tm.lines[line1].width * self.fontwt)
            paint.fillRect(
                QRectF(x1, 3 + y1 * self.fontht, width - x1, self.fontht),
                QColor(0, 0, 255, 100))
            y = y1 + self.tm.lines[line1].height
            for i in range(line1 + 1, line2):
                width = self.tm.lines[i].width * self.fontwt
                if width == 0:
                    width = self.fontwt
                paint.fillRect(
                    QRectF(0, 3 + y * self.fontht, width, self.fontht),
                    QColor(0, 0, 255, 100))
                y = y + self.tm.lines[i].height
            paint.fillRect(QRectF(0, 3 + y2 * self.fontht, x2, self.fontht),
                           QColor(0, 0, 255, 100))

    def get_highlighter(self, node):
        root = node.get_root()
        base = lang_dict[self.tm.get_language(root)].base
        s = syntaxhighlighter.get_highlighter(base, self.palette())
        return s

    def get_languagebox(self, node):
        root = node.get_root()
        lbox = root.get_magicterminal()
        return lbox

    def get_renderer(self, node):
        root = node.get_root()
        base = lang_dict[self.tm.get_language(root)].base
        return renderers.get_renderer(base, self.fontwt, self.fontht,
                                      self.fontd)

    def focusNextPrevChild(self, b):
        # don't switch to next widget on TAB
        return False

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.tm.input_log.append("# mousePressEvent")
            self.coordinate_to_cursor(e.x(), e.y())
            self.tm.selection_start = self.tm.cursor.copy()
            self.tm.selection_end = self.tm.cursor.copy()
            self.tm.input_log.append(
                "self.selection_start = self.cursor.copy()")
            self.tm.input_log.append("self.selection_end = self.cursor.copy()")
            self.getWindow().showLookahead()
            self.show_cursor = True
            self.blinktimer.start()
            self.update()

    def mouseDoubleClickEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.coordinate_to_cursor(e.x(), e.y())
            node = self.tm.get_node_from_cursor()
            lbox = self.get_languagebox(node)
            if lbox and lbox.symbol.name == "<IPython>":
                if lbox.plain_mode is False:
                    lbox.plain_mode = True
                else:
                    lbox.plain_mode = False
                self.update()
                return
            elif node.image is None:
                self.tm.doubleclick_select()
                self.update()
                return

            if node.plain_mode is False:
                node.plain_mode = True
                self.tm.cursor.pos = len(node.symbol.name)
            else:
                node.plain_mode = False
            self.update()

    def cursor_to_coordinate(self):
        y = 0
        for l in self.tm.lines[:self.cursor.line]:
            y += l.height * self.fontht
        x = self.tm.cursor.get_x() * self.fontwt
        y = y - self.getScrollArea().verticalScrollBar().value() * self.fontht
        return (x, y)

    def coordinate_to_cursor(self, x, y):
        mouse_y = y / self.fontht
        first_line = self.paint_start[0]
        y_offset = self.paint_start[1]

        y = y_offset
        line = first_line
        if mouse_y < 0:
            while line > 0:
                y -= self.tm.lines[line].height
                if y < mouse_y:
                    break
                line -= 1
        else:
            while line < len(self.tm.lines) - 1:
                y += self.tm.lines[line].height
                if y > mouse_y:
                    break
                line += 1

        self.tm.cursor.line = line
        cursor_x = int(round(float(x) / self.fontwt))
        self.tm.cursor.move_to_x(cursor_x)

        self.tm.input_log.append("self.cursor.line = %s" % str(line))
        self.tm.log_input("cursor.move_to_x", str(cursor_x))

        if mouse_y > y or self.tm.cursor.get_x() != cursor_x:
            return False
        return True

    def mouseMoveEvent(self, e):
        # apparently this is only called when a mouse button is clicked while
        # the mouse is moving
        if self.tm.input_log[-2].startswith("self.cursor.move_to_x"):
            # only log the last move event
            self.tm.input_log.pop()
            self.tm.input_log.pop()
            self.tm.input_log.pop()
        self.coordinate_to_cursor(e.x(), e.y())
        self.tm.selection_end = self.tm.cursor.copy()
        self.tm.input_log.append("self.selection_end = self.cursor.copy()")
        self.update()
        self.getEditorTab().keypress()

    def keyPressEvent(self, e):
        self.timer.start(500)
        self.show_cursor = True

        startundotimer = False
        key = KeyPress(e)

        # key presses to ignore
        if key.is_modifier or key.page_up or key.page_down:
            return

        # has been processes in get_nodes_at_pos -> reset
        self.edit_rightnode = False

        reparse = True

        if key.escape:
            self.tm.key_escape()
        elif key.backspace:
            startundotimer = True
            self.tm.key_backspace()
        elif key.home:
            self.tm.key_home(shift=key.m_shift)
        elif key.end:
            self.tm.key_end(shift=key.m_shift)
        elif key.is_arrow:
            if key.jump_word:
                self.tm.ctrl_cursor(key, shift=key.m_shift)
            else:
                self.tm.key_cursors(key, shift=key.m_shift)
                reparse = False
        elif key.delete:
            startundotimer = True
            self.tm.key_delete()
        elif e.key() == Qt.Key_F3:
            self.tm.find_next()
        # User pressed Ctrl- Or Alt- (etc.) i.e. a character we can't
        # sensibly insert into the text.
        elif key.has_action_modifier:
            pass
        # every other normal key press
        else:
            startundotimer = True
            if e.key() == Qt.Key_Tab:
                text = "    "
            else:
                # text is a char array, so we need the first letter
                # to match it against the set
                text = e.text()
                if text.isEmpty() or text.toUtf8()[0] not in whitelist:
                    logging.debug("Key %s not supported" % text)
                    return
            self.tm.key_normal(text)

        if reparse:
            self.getWindow().btReparse([])
        self.update()
        self.emit(SIGNAL("keypress(QKeyEvent)"), e)
        self.getWindow().showLookahead()

        if startundotimer:
            self.undotimer.start(500)

    def showLanguageBoxMenu(self):
        self.showSubgrammarMenu()
        self.create_languagebox()

    def create_languagebox(self):
        if self.sublanguage:
            if self.tm.hasSelection():
                self.tm.surround_with_languagebox(self.sublanguage)
                self.tm.reparse(self.tm.selection_start.node)
            else:
                self.tm.add_languagebox(self.sublanguage)
            self.getWindow().btReparse([])
            self.update()

    def change_languagebox(self):
        if self.sublanguage:
            self.tm.change_languagebox(self.sublanguage)

    def showCodeCompletion(self):
        l = self.tm.getCompletion()
        if l:
            self.showCodeCompletionMenu(l)

    def println(self, prestring, y):
        node = self.lines[y].node.next_term
        x = []
        while node is not None and node.symbol.name != "\r":
            x.append(node.symbol.name)
            node = node.next_term
        print(prestring, "".join(x))

    def print_line(self, y):
        current = self.lines[y].node
        while True:
            print(current)
            current = current.next_term
            if current is None:
                return

    # ========================== AST modification stuff ========================== #

    def insertTextNoSim(self, text):
        self.viewport_y = 0
        self.tm.import_file(text)
        return

    def getTL(self):
        return self.getWindow().tl

    def getPL(self):
        return self.getWindow().pl

    def getLRP(self):
        return self.getWindow().lrp

    def getWindow(self):
        return self.window()

    def getEditorTab(self):
        return self.parent().parent().parent()

    def getScrollArea(self):
        return self.parent().parent()

    def createSubgrammarMenu(self, menu, change=False):
        self.sublanguage = None

        tmp = None
        if change:
            # try and find lbox and set cursor to previous node before getting
            # lookahead list
            root = self.tm.cursor.node.get_root()
            lbox = root.get_magicterminal()
            if lbox:
                tmp = self.tm.cursor.node
                self.tm.cursor.node = lbox.prev_term
        lalist = self.tm.getLookaheadList()
        if tmp:
            # undo cursor change
            self.tm.cursor.node = tmp

        # Filter out languages that are part of this composition.
        todo = [self.get_mainlanguage()]
        comp_langs = []
        while todo:
            l = todo.pop()
            for sl in lang_dict[l].included_langs:
                if lang_dict[sl] not in comp_langs:
                    comp_langs.append(lang_dict[sl])
                    todo.append(sl)

        # Generate list of languages valid at current position
        valid_langs = []
        for l in comp_langs:
            if "<%s>" % l in lalist:
                valid_langs.append(l)
        for l in valid_langs:
            # Don't show languages twice
            comp_langs.remove(l)

        def create_entry(l, menu):
            pass

        bf = QFont()
        bf.setBold(True)
        # Show valid languages first
        if len(valid_langs) > 0:
            for l in sorted(valid_langs, key=lambda x: x.name):
                item = QAction(str(l), menu)
                item.setData(l)
                self._set_icon(item, l)
                item.setFont(bf)
                menu.addAction(item)
            menu.addSeparator()

        # Then show languages that are part of this composition
        for l in sorted(comp_langs, key=lambda x: x.name):
            item = QAction(str(l), menu)
            item.setData(l)
            self._set_icon(item, l)
            menu.addAction(item)

        # Finally add another submenu with all remaining languages
        other_langs = QtGui.QMenu("Other", self)
        for l in sorted(languages, key=lambda x: x.name):
            if l not in comp_langs and l not in valid_langs:
                item = QAction(str(l), other_langs)
                item.setData(l)
                self._set_icon(item, l)
                other_langs.addAction(item)
        menu.addSeparator()
        menu.addMenu(other_langs)

        return menu

    def showSubgrammarMenu(self):
        menu = QtGui.QMenu("Language", self)
        self.createSubgrammarMenu(menu)
        x, y = self.cursor_to_coordinate()
        action = menu.exec_(
            self.mapToGlobal(QPoint(0, 0)) + QPoint(3 + x, y + self.fontht))
        if action:
            self.sublanguage = action.data().toPyObject()
            self.edit_rightnode = True

    def _set_icon(self, mitem, lang):
        if lang.base.lower() == "html":
            icon = QIcon.fromTheme("text-xhtml+xml")
        else:
            icon = QIcon.fromTheme("text-x-" + lang.base.lower())
        if icon.isNull():
            icon = QIcon.fromTheme("application-x-" + lang.base.lower())
            if icon.isNull():
                icon = QIcon.fromTheme("text-x-generic")
        mitem.setIcon(icon)

    def showCodeCompletionMenu(self, l):
        menu = QtGui.QMenu(self)
        # Create actions
        toolbar = QtGui.QToolBar()
        for n in l:
            path = []
            for p in n.path:
                if p and p.name:
                    path.append(p.name)
            if n.vartype:
                vartype = n.vartype
                while vartype.children != []:
                    try:
                        vartype = vartype.children[0]
                    except KeyError:
                        vartype = vartype.children["name"]
                text = "%s : %s - %s (%s)" % (n.name, vartype.symbol.name,
                                              ".".join(path), n.kind)
            elif n.kind == "method":
                text = self.cc_method(n) + " - %s" % (".".join(path))
            else:
                text = "%s - %s (%s)" % (n.name, ".".join(path), n.kind)
            item = toolbar.addAction(text, self.createCCFunc(n.name))
            item.setIcon(QIcon("gui/" + n.kind + ".png"))
            menu.addAction(item)
        x, y = self.cursor_to_coordinate()
        menu.exec_(
            self.mapToGlobal(QPoint(0, 0)) + QPoint(3 + x, y + self.fontht))

    def cc_method(self, n):
        s = [n.name, "("]
        param_ln = n.astnode.children["params"]
        if isinstance(param_ln, ListNode):
            for p in param_ln.children:
                tmp = p.children["type"]
                if isinstance(tmp, AstNode):
                    s.append(tmp.children["name"].symbol.name)
                else:
                    s.append(tmp.symbol.name)
                s.append(" ")
                s.append(p.children["name"].symbol.name)
                if p != param_ln.children[-1]:
                    s.append(", ")
        s.append(")")
        return "".join(s)

    def createMenuFunction(self, l):
        def action():
            self.sublanguage = l
            self.edit_rightnode = True

        return action

    def createCCFunc(self, text):
        def action():
            self.tm.pasteCompletion(text)
            self.update()

        return action

    def selectSubgrammar(self, item):
        pass

    def saveToJson(self, filename, swap=False):
        whitespaces = self.tm.get_mainparser().whitespaces
        root = self.tm.parsers[0][0].previous_version.parent
        language = self.tm.parsers[0][2]
        manager = JsonManager()
        manager.save(root, language, whitespaces, filename)
        if not swap:
            self.tm.changed = False
            self.emit(SIGNAL("painted()"))

    def loadFromJson(self, filename):
        manager = JsonManager()
        language_boxes = manager.load(filename)

        self.tm = TreeManager()

        self.tm.load_file(language_boxes)
        self.reset()

    def export(self, run=False, profile=False, source=None, debug=False):
        return self.tm.export(None, run, profile, source=source, debug=debug)
Beispiel #32
0
class NodeEditor(QFrame):

    # ========================== init stuff ========================== #

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.viewport_y = 0 # top visible line
        self.imagemode = False
        self.image = None

        self.scroll_height = 0
        self.scroll_width = 0

        self.timer = QTimer(self)
        self.backuptimer = QTimer(self)
        self.connect(self.timer, SIGNAL("timeout()"), self.analysis_timer)
        self.connect(self.backuptimer, SIGNAL("timeout()"), self.backup_timer)
        self.backuptimer.start(30000)
        self.undotimer = QTimer(self)
        self.connect(self.undotimer, SIGNAL("timeout()"), self.trigger_undotimer)

        self.blinktimer = QTimer(self)
        self.blinktimer.start(500)
        self.connect(self.blinktimer, SIGNAL("timeout()"), self.trigger_blinktimer)
        self.show_cursor = True

        self.boxcolors = [QColor("#DC322F"), QColor("#268BD2"), QColor("#D33682"), QColor("#B58900"), QColor("#2AA198"), QColor("#859900")]
        self.setCursor(Qt.IBeamCursor)

        # Semi-transparent overlay.
        # Used to display heat-map visualisation of profiler info, etc.
        self.overlay = Overlay(self)
        # Start hidden, make (in)visible with self.toggle_overlay().
        self.overlay.hide()

        # Set to True if the user wants to see tool visualisations.
        self.show_tool_visualisations = True

        # Set True if Eco should be running profiler and other tools,
        # continuously in the background.
        self.run_background_tools = False

    def toggle_overlay(self):
        self.hide_overlay() if self.overlay.isVisible() else self.show_overlay()

    def show_overlay(self):
        self.overlay.show()

    def hide_overlay(self):
        self.overlay.hide()

    def is_overlay_visible(self):
        return self.overlay.isVisible()

    def resizeEvent(self, event):
        self.overlay.resize(event.size())
        event.accept()

    def analysis_timer(self):
        if self.getWindow().show_namebinding():
            self.tm.analyse()
            self.update()
        self.timer.stop()

        # save swap
        filename = self.getEditorTab().filename
        if filename:
            self.saveToJson(filename + ".swp", True)

    def backup_timer(self):
        filename = self.getEditorTab().filename
        if filename:
            self.saveToJson(filename + ".bak", True)

    def trigger_blinktimer(self):
        if self.timer.isActive():
            self.show_cursor = True
            return
        self.show_cursor ^= True
        self.update()

    def trigger_undotimer(self):
        self.tm.save_current_version()
        self.undotimer.stop()

    def setImageMode(self, boolean):
        self.imagemode = boolean

    def reset(self):
        #self.getWindow().ui.scrollArea.horizontalScrollBar().setValue(0)
        #self.getWindow().ui.scrollArea.verticalScrollBar().setValue(0)
        self.update()

    def set_mainlanguage(self, parser, lexer, lang_name):
        self.tm = TreeManager()
        self.tm.add_parser(parser, lexer, lang_name)

    def set_sublanguage(self, language):
        self.sublanguage = language

    def event(self, event):
        if event.type() == QEvent.ToolTip:
            if QToolTip.isVisible():
                QToolTip.hideText()
                event.ignore()
                return True
            pos = event.pos()
            temp_cursor = self.tm.cursor.copy()
            result = self.coordinate_to_cursor(pos.x(), pos.y())
            node = self.tm.cursor.node
            self.tm.cursor.line = temp_cursor.line
            self.tm.cursor.node = temp_cursor.node
            self.tm.cursor.pos = temp_cursor.pos
            if not result:
                event.ignore()
                return True
            # Draw errors, if there are any.
            msg = self.tm.get_error(node)
            if msg:
                QToolTip.showText(event.globalPos(), msg)
            # Draw annotations if there are any.
            elif self.show_tool_visualisations:
                annotes = [annote.annotation for annote in node.get_annotations_with_hint(ToolTip)]
                msg = "\n".join(annotes)
                if msg.strip() != "":
                    if self.tm.tool_data_is_dirty:
                        msg += "\n[Warning: Information may be out of date.]"
                    QToolTip.showText(event.globalPos(), msg)
            return True
        return QFrame.event(self, event)

    # ========================== GUI related stuff ========================== #

    def blink(self):
        if self.show_cursor:
            self.show_cursor = 0
        else:
            self.show_cursor = 1
        self.update()

    def sliderChanged(self, value):
        change = self.viewport_y - value
        self.viewport_y = value
        self.overlay.start_line = self.viewport_y
        self.update()

    def sliderXChanged(self, value):
        self.move(-value*self.fontwt,0)
        self.resize(self.parentWidget().geometry().width() + value*self.fontwt, self.geometry().height())
        if self.x() == 0:
            self.updateGeometry()
        self.update()

    def getScrollSizes(self):
        total_lines = 0
        max_width = 0
        for l in self.lines:
            total_lines += l.height
            max_width = max(max_width, l.width)
        max_visible_lines = self.geometry().height() / self.fontht
        self.scroll_height = max(0, total_lines - max_visible_lines)

        current_width = self.parentWidget().geometry().width() / self.fontwt
        self.scroll_width = max(0, max_width - current_width)

    def paintEvent(self, event):
        # Clear data in the heatmap overlay
        self.overlay.clear_data()

        gfont = QApplication.instance().gfont
        self.font = gfont.font
        self.fontwt = gfont.fontwt
        self.fontht = gfont.fontht
        QtGui.QFrame.paintEvent(self, event)
        paint = QtGui.QPainter()
        if self.imagemode:
            self.image = QImage()
            paint.begin(self.image)
        else:
            paint.begin(self)
        paint.setFont(self.font)

        y = 0
        x = 0

        self.longest_column = 0

        # calculate how many lines we need to show
        self.init_height = self.geometry().height()

        self.paintLines(paint, self.viewport_y)

        paint.end()

        total_lines = 0
        max_width = 0
        for l in self.lines:
            total_lines += l.height
            max_width = max(max_width, l.width)
        max_visible_lines = self.geometry().height() / self.fontht
        self.scroll_height = max(0, total_lines - max_visible_lines)


        current_width = self.parentWidget().geometry().width() / self.fontwt
        self.scroll_width = max(0, max_width - current_width)

        self.emit(SIGNAL("painted()"))

    # paint lines using new line manager
    def paintLines(self, paint, startline):

        # find internal line corresponding to visual line
        visual_line = 0
        internal_line = 0
        for l in self.tm.lines:
            if visual_line + l.height > startline:
                break
            visual_line += l.height
            internal_line += 1

        x = 0
        y = visual_line - startline # start drawing outside of viewport to display partial images
        self.paint_start = (internal_line, y)

        max_y = self.geometry().height() / self.fontht

        line = internal_line
        node = self.tm.lines[line].node

        self.paint_nodes(paint, node, x, y, line, max_y)


    #XXX if starting node is inside language box, init lbox with amout of languge boxes
    def paint_nodes(self, paint, node, x, y, line, max_y, lbox=0):

        settings = QSettings("softdev", "Eco")
        colors = self.boxcolors
        if settings.value("app_theme", "Light").toString() in ["Dark"]:
            alpha = 100
        elif settings.value("app_theme", "Light").toString() in ["Gruvbox"]:
            alpha = 100
        else:
            alpha = 40

        first_node = node
        selected_language = self.tm.mainroot
        error_node = self.tm.get_mainparser().error_node
        error_node = self.fix_errornode(error_node)

        highlighter = self.get_highlighter(node)
        selection_start = min(self.tm.selection_start, self.tm.selection_end)
        selection_end = max(self.tm.selection_start, self.tm.selection_end)
        draw_selection_start = (0,0,0)
        draw_selection_end = (0,0,0)
        start_lbox = self.get_languagebox(node)
        editor = self.get_editor(node)

        self.selected_lbox = self.tm.get_languagebox(self.tm.cursor.node)
        #XXX get initial x for langbox

        if start_lbox:
            lbox += 1
        if start_lbox and self.selected_lbox is start_lbox:
            draw_lbox = True
        else:
            draw_lbox = False

        draw_all_boxes = self.getWindow().show_languageboxes()

        self.lines = self.tm.lines
        self.cursor = self.tm.cursor
        self.lines[line].height = 1 # reset height
        draw_cursor = True
        #l_x = [0]
        while y < max_y:

            # if we found a language box, continue drawing inside of it
            if isinstance(node.symbol, MagicTerminal):
                #l_x.append(x)
                #node.pos = x
                lbox += 1
                lbnode = node.symbol.ast
                if self.selected_lbox is node:
                    self.draw_lbox_bracket(paint, '[', node, x, y)
                    draw_lbox = True
                    selected_language = lbnode
                else:
                    draw_lbox = False
                node = lbnode.children[0]
                highlighter = self.get_highlighter(node)
                editor = self.get_editor(node)
                error_node = self.tm.get_parser(lbnode).error_node
                error_node = self.fix_errornode(error_node)
                continue

            if isinstance(node, EOS):
                lbnode = self.get_languagebox(node)
                if self.cursor.node is lbnode:
                    self.draw_cursor(paint, x, 5 + y * self.fontht)
                if lbnode:
                    #l_x.pop()
                    if lbox > 0:
                        lbox -= 1
                    node = lbnode.next_term
                    highlighter = self.get_highlighter(node)
                    editor = self.get_editor(node)
                    if self.selected_lbox is lbnode:
                        # draw bracket
                        self.draw_lbox_bracket(paint, ']', node, x, y)
                        draw_lbox = False
                    lbnode = self.get_languagebox(node)
                    if lbnode and self.selected_lbox is lbnode:
                        draw_lbox = True
                        error_node = self.tm.get_parser(lbnode.symbol.ast).error_node
                        error_node = self.fix_errornode(error_node)
                    else:
                        error_node = self.tm.get_mainparser().error_node
                        error_node = self.fix_errornode(error_node)
                    continue
                else:
                    self.lines[line].width = x / self.fontwt
                    break

            # draw language boxes
            if lbox > 0 and (draw_lbox or draw_all_boxes):
                #color = self.nesting_colors[lbox % 5]
                if draw_all_boxes:
                    color = colors[(lbox-1) % len(colors)]
                    color.setAlpha(alpha)
                else:
                    color = colors[0]
                    color.setAlpha(alpha)
                if draw_lbox and draw_all_boxes: # we are drawing the currently selected language box
                    color.setAlpha(20)
                editor.update_image(node)
                if node.symbol.name != "\r" and not isinstance(node.symbol, IndentationTerminal):
                    if not node.image or node.plain_mode:
                        paint.fillRect(QRectF(x,3 + y*self.fontht, len(node.symbol.name)*self.fontwt, self.fontht), color)

            # prepare selection drawing
            if node is selection_start.node:
                if node.lookup == "<return>":
                    sel_x = x
                else:
                    sel_x = x + selection_start.pos * self.fontwt
                draw_selection_start = (sel_x, y, line)

            if node is selection_end.node:
                draw_selection_end = (x + selection_end.pos * self.fontwt, y, line)

            # draw node
            dx, dy = editor.paint_node(paint, node, x, y, highlighter)
            x += dx
            #y += dy
            self.lines[line].height = max(self.lines[line].height, dy)

            # Draw footnotes and add data to heatmap.
            annotes = [annote.annotation for annote in node.get_annotations_with_hint(Heatmap)]
            for annote in annotes:
                self.overlay.add_datum(line + 1, annote)
            if self.show_tool_visualisations:
                # Draw footnotes.
                infofont = QApplication.instance().tool_info_font
                annotes = [annote.annotation for annote in node.get_annotations_with_hint(Footnote)]
                footnote = " ".join(annotes)
                if footnote.strip() != "":
                    if not self.tm.tool_data_is_dirty:
                        infofont.font.setBold(True)
                    else:
                        infofont.font.setBold(False)
                    paint.setFont(infofont.font)
                    paint.setPen(QPen(QColor((highlighter.get_default_color()))))
                    start_x = (0 if (x - len(footnote) * infofont.fontwt) < 0
                                 else x - len(footnote) * infofont.fontwt)
                    start_y = self.fontht + ((y + 1) * self.fontht)
                    paint.drawText(QtCore.QPointF(x-dx, start_y), footnote)
                    self.lines[line].height = max(self.lines[line].height, 2)
                    paint.setFont(self.font)

            # after we drew a return, update line information
            if node.lookup == "<return>" and not node is first_node:
                # draw lbox to end of line
                if draw_lbox or (draw_all_boxes and lbox > 0):
                    paint.fillRect(QRectF(x,3+y*self.fontht, self.geometry().width()-x, self.fontht), color)

                self.lines[line].width = x / self.fontwt
                x = 0#l_x[-1]
                y += self.lines[line].height
                line += 1
                self.lines[line].height = 1 # reset height

            # draw cursor
            if node is self.cursor.node and self.show_cursor:
                draw_x = max(0, x-dx)
                cursor_pos = self.cursor.pos

                if node.symbol.name == "\r":
                    cursor_pos = 0
                if node.image and not node.plain_mode:
                    draw_x = x
                    cursor_pos = 0
                self.draw_cursor(paint, draw_x + cursor_pos * self.fontwt, 5 + y * self.fontht)


            if False and line == self.cursor.y and x/self.fontwt >= self.cursor.x and draw_cursor:
                draw_cursor_at = QRect(0 + self.cursor.x * self.fontwt, 5 + y * self.fontht, 0, self.fontht - 3)
                paint.drawRect(draw_cursor_at)

                # set lbox info coordinates
                infobox_coordinates = (self.cursor.x * self.fontwt, (y+1) * self.fontht)
                draw_cursor = False

            # draw squiggly line
            if node is error_node or (self.getWindow().show_namebinding() and self.tm.has_error(node)):
                if isinstance(node, EOS):
                    length = self.fontwt
                else:
                    length = len(node.symbol.name)*self.fontwt
                if isinstance(node.symbol, MagicTerminal):
                    self.draw_vertical_squiggly_line(paint,x,y)
                else:
                    if self.tm.has_error(node):
                        color = "orange"
                    else:
                        color = "red"
                    self.draw_squiggly_line(paint,x-length,y,length, color)

            node = node.next_term

        if selection_start != selection_end:
            self.draw_selection(paint, draw_selection_start, draw_selection_end, max_y)

        # paint infobox
        if False:
            lang_name = self.tm.parsers[selected_language]
            parser = self.tmselected_language
            lang_status = self.tm.get_parser[selected_language][0].last_status
            if lang_status is True:
                color = QColor(100,255,100)
            else:
                color = QColor(255,100,100)
            paint.setFont(infofont)
            paint.fillRect(QRect(infobox_coordinates[0], 5 + infobox_coordinates[1], len(lang_name)*infofontwt, infofontht), color)
            paint.drawText(QtCore.QPointF(infobox_coordinates[0], -3 + self.fontht + infobox_coordinates[1]), lang_name)
            paint.setFont(self.font)

        return x, y, line

    def draw_lbox_bracket(self, paint, bracket, node, x, y):
        assert bracket in ['[',']']
        oldpen = paint.pen()
        newpen = QPen()
        color = self.get_highlighter(node).get_default_color()
        newpen.setColor(color)
        newpen.setWidth(2)
        paint.setPen(newpen)

        # paint brackets
        tmpy = y
        path = QPainterPath()
        if bracket == '[':
            tmpx = x + 1 # adjust bracket position
            path.moveTo(tmpx,   3+y*self.fontht)
            path.lineTo(tmpx-2, 3+y*self.fontht)
            path.moveTo(tmpx-2, 3+y*self.fontht)
            path.lineTo(tmpx-2, 3+y*self.fontht + self.fontht)
        else:
            tmpx = x - 1
            path.moveTo(tmpx,   3+y*self.fontht)
            path.lineTo(tmpx+2, 3+y*self.fontht)
            path.moveTo(tmpx+2, 3+y*self.fontht)
            path.lineTo(tmpx+2, 3+y*self.fontht + self.fontht)
        path.lineTo(tmpx, 3+y*self.fontht + self.fontht)
        paint.drawPath(path)

        paint.setPen(oldpen)

    def fix_errornode(self, error_node):
        if not error_node:
            return
        while isinstance(error_node.symbol, IndentationTerminal):
            error_node = error_node.next_term
        return error_node

    def draw_cursor(self, paint, x, y):
        pen = paint.pen()
        colorhex = self.palette().color(QPalette.Text)
        pen.setColor(QColor(colorhex))
        paint.setPen(pen)
        draw_cursor_at = QRect(x, y, 0, self.fontht - 3)
        paint.drawRect(draw_cursor_at)

    def draw_vertical_squiggly_line(self, paint, x, y):
        paint.setPen(Qt.CustomDashLine)
        pen = paint.pen()
        pen.setDashPattern([2,2])
        pen.setColor(QColor("red"))
        paint.setPen(pen)
        y = 3+y*self.fontht
        paint.drawLine(x-1, y, x-1, y+self.fontht)
        paint.drawLine(x, y+2, x, y+self.fontht)
        paint.setPen(Qt.SolidLine)

    def draw_squiggly_line(self, paint, x, y, length, color):
        paint.setPen(Qt.CustomDashLine)
        pen = paint.pen()
        pen.setDashPattern([2,2])
        pen.setColor(QColor(color))
        paint.setPen(pen)
        #x -= length
        y = (y+1)*self.fontht+1
        paint.drawLine(x, y, x+length, y)
        paint.drawLine(x+2, y+1, x+2+length, y+1)
        paint.setPen(Qt.SolidLine)

    def draw_selection(self, paint, draw_selection_start, draw_selection_end, max_y):
        x1, y1, line1 = draw_selection_start
        x2, y2, line2 = draw_selection_end
        if x1 + y1 + line1 == 0:
            # start outside of viewport
            line1 = self.paint_start[0]
        if line2 == 0:
            # end outside of viewport
            line2 = self.paint_start[0] + max_y
        if y1 + y2 == 0:
            # start and end outside of viewport
            y2 = max_y
        if y1 == y2:
            paint.fillRect(QRectF(x1, 3 + y1 * self.fontht, x2-x1, self.fontht), QColor(0,0,255,100))
        else:
            paint.fillRect(QRectF(x1, 3 + y1 * self.fontht, self.tm.lines[line1].width*self.fontwt - x1, self.fontht), QColor(0,0,255,100))
            y = y1 + self.tm.lines[line1].height
            for i in range(line1+1, line2):
                width = self.tm.lines[i].width*self.fontwt
                if width == 0:
                    width = self.fontwt
                paint.fillRect(QRectF(0, 3 + y * self.fontht, width, self.fontht), QColor(0,0,255,100))
                y = y + self.tm.lines[i].height
            paint.fillRect(QRectF(0, 3 + y2 * self.fontht, x2, self.fontht), QColor(0,0,255,100))

    def get_highlighter(self, node):
        root = node.get_root()
        base = lang_dict[self.tm.get_language(root)].base
        s = syntaxhighlighter.get_highlighter(base, self.palette())
        return s

    def get_languagebox(self, node):
        root = node.get_root()
        lbox = root.get_magicterminal()
        return lbox

    def get_editor(self, node):
        root = node.get_root()
        base = lang_dict[self.tm.get_language(root)].base
        return editor.get_editor(base, self.fontwt, self.fontht)

    def focusNextPrevChild(self, b):
        # don't switch to next widget on TAB
        return False

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.tm.input_log.append("# mousePressEvent")
            self.coordinate_to_cursor(e.x(), e.y())
           # self.tm.cursor = cursor
            self.tm.selection_start = self.tm.cursor.copy()
            self.tm.selection_end = self.tm.cursor.copy()
            self.tm.input_log.append("self.selection_start = self.cursor.copy()")
            self.tm.input_log.append("self.selection_end = self.cursor.copy()")
            #self.tm.fix_cursor_on_image()
            self.getWindow().showLookahead()
            self.update()

    def mouseDoubleClickEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.coordinate_to_cursor(e.x(), e.y())
            node = self.tm.get_node_from_cursor()
            lbox = self.get_languagebox(node)
            if lbox and lbox.symbol.name == "<IPython>":
                if lbox.plain_mode is False:
                    lbox.plain_mode = True
                else:
                    lbox.plain_mode = False
                self.update()
                return
            elif node.image is None:
                self.tm.selection_start = self.tm.cursor.copy()
                self.tm.selection_start.node = self.tm.cursor.find_previous_visible(self.tm.cursor.node)
                self.tm.selection_start.pos = len(self.tm.selection_start.node.symbol.name)
                self.tm.selection_end = self.tm.cursor.copy()
                self.tm.selection_end.pos = len(self.tm.selection_end.node.symbol.name)
                self.tm.cursor.pos = self.tm.selection_end.pos
                self.tm.cursor.node = self.tm.selection_end.node
                self.update()
                return

            if node.plain_mode is False:
                node.plain_mode = True
                self.tm.cursor.pos = len(node.symbol.name)
            else:
                node.plain_mode = False
            self.update()

    def cursor_to_coordinate(self):
        y = 0
        for l in self.tm.lines[:self.cursor.line]:
            y += l.height * self.fontht
        x = self.tm.cursor.get_x() * self.fontwt
        y = y - self.getScrollArea().verticalScrollBar().value() * self.fontht
        return (x,y)

    def coordinate_to_cursor(self, x, y):

        mouse_y = y / self.fontht
        first_line = self.paint_start[0]
        y_offset = self.paint_start[1]

        y = y_offset
        line = first_line
        if mouse_y < 0:
            while line > 0:
                y -= self.tm.lines[line].height
                if y < mouse_y:
                    break
                line -= 1
        else:
            while line < len(self.tm.lines) - 1:
                y += self.tm.lines[line].height
                if y > mouse_y:
                    break
                line += 1

        self.tm.cursor.line = line
        cursor_x = int(round(float(x) / self.fontwt))
        self.tm.cursor.move_to_x(cursor_x, self.tm.lines)

        self.tm.input_log.append("self.cursor.line = %s" % str(line))
        self.tm.log_input("cursor.move_to_x", str(cursor_x), "self.lines")

        if mouse_y > y or self.tm.cursor.get_x() != cursor_x:
            return False
        return True

    def mouseMoveEvent(self, e):
        # apparaently this is only called when a mouse button is clicked while
        # the mouse is moving
        if self.tm.input_log[-2].startswith("self.cursor.move_to_x"):
            # only log the last move event
            self.tm.input_log.pop()
            self.tm.input_log.pop()
            self.tm.input_log.pop()
        self.coordinate_to_cursor(e.x(), e.y())
        self.tm.selection_end = self.tm.cursor.copy()
        self.tm.input_log.append("self.selection_end = self.cursor.copy()")
        self.update()
        self.getEditorTab().keypress()

    def key_to_string(self, key):
        if key == Qt.Key_Up:
            return "up"
        if key == Qt.Key_Down:
            return "down"
        if key == Qt.Key_Left:
            return "left"
        if key == Qt.Key_Right:
            return "right"

    def keyPressEvent(self, e):

        startundotimer = False
        self.timer.start(500)
        self.show_cursor = True

        if e.key() in [Qt.Key_Shift, Qt.Key_Alt, Qt.Key_Control, Qt.Key_Meta, Qt.Key_AltGr]:
            if e.key() == Qt.Key_Shift:
                self.tm.key_shift()
            return

        text = e.text()

        self.edit_rightnode = False # has been processes in get_nodes_at_pos -> reset

        if e.key() == Qt.Key_Escape:
            self.tm.key_escape()
        elif e.key() == Qt.Key_Backspace:
            startundotimer = True
            self.tm.key_backspace()
        elif e.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]:
            if e.modifiers() == Qt.ShiftModifier:
                self.tm.key_cursors(self.key_to_string(e.key()), True)
            elif e.modifiers() == Qt.ControlModifier:
                self.tm.ctrl_cursor(self.key_to_string(e.key()))
            else:
                self.tm.key_cursors(self.key_to_string(e.key()), False)
        elif e.key() == Qt.Key_Home:
            self.tm.key_home(e.modifiers() == Qt.ShiftModifier)
        elif e.key() == Qt.Key_End:
            self.tm.key_end(e.modifiers() == Qt.ShiftModifier)
        elif e.key() == Qt.Key_Delete:
            startundotimer = True
            self.tm.key_delete()
        elif e.key() == Qt.Key_F3:
            self.tm.find_next()
        elif e.key() in [Qt.Key_PageUp, Qt.Key_PageDown]:
            pass # ignore those keys
        elif e.modifiers() in [Qt.ControlModifier, Qt.AltModifier]:
            # User pressed Ctrl- Or Alt- (etc.) i.e. a character we can't
            # sensibly insert into the text.
            pass
        else:
            startundotimer = True
            if e.key() == Qt.Key_Tab:
                text = "    "
            else:
                text = e.text()
                if text.toUtf8() not in whitelist:
                    logging.debug("Key %s not supported" % text)
                    return
            self.tm.key_normal(text)

        self.getWindow().btReparse([])
        self.update()
        self.emit(SIGNAL("keypress(QKeyEvent)"), e)
        self.getWindow().showLookahead()
        if startundotimer:
            self.undotimer.start(500)

    def showLanguageBoxMenu(self):
        self.showSubgrammarMenu()
        self.create_languagebox()

    def create_languagebox(self):
        if self.sublanguage:
            if self.tm.hasSelection():
                self.tm.surround_with_languagebox(self.sublanguage)
            else:
                self.tm.add_languagebox(self.sublanguage)

    def change_languagebox(self):
        if self.sublanguage:
            self.tm.change_languagebox(self.sublanguage)

    def showCodeCompletion(self):
        l = self.tm.getCompletion()
        if l:
            self.showCodeCompletionMenu(l)

    def println(self, prestring, y):
        node = self.lines[y].node.next_term
        x = []
        while node is not None and node.symbol.name != "\r":
            x.append(node.symbol.name)
            node = node.next_term
        print(prestring, "".join(x))

    def print_line(self, y):
        current = self.lines[y].node
        while True:
            print(current)
            current = current.next_term
            if current is None:
                return

    # ========================== AST modification stuff ========================== #

    def insertTextNoSim(self, text):
        self.viewport_y = 0
        self.tm.import_file(text)
        return

    def getTL(self):
        return self.getWindow().tl

    def getPL(self):
        return self.getWindow().pl

    def getLRP(self):
        return self.getWindow().lrp

    def getWindow(self):
        return self.window()

    def getEditorTab(self):
        return self.parent().parent().parent()

    def getScrollArea(self):
        return self.parent().parent()

    def createSubgrammarMenu(self, menu, change=False):
        self.sublanguage = None

        tmp = None
        if change:
            # try and find lbox and set cursor to previous node before getting
            # lookahead list
            root = self.tm.cursor.node.get_root()
            lbox = root.get_magicterminal()
            if lbox:
                tmp = self.tm.cursor.node
                self.tm.cursor.node = lbox.prev_term

        # Create actions
        bf = QFont()
        bf.setBold(True)
        valid_langs = []
        for l in languages:
            if "<%s>" % l in self.tm.getLookaheadList():
                valid_langs.append(l)

        if tmp:
            # undo cursor change
            self.tm.cursor.node = tmp
        if len(valid_langs) > 0:
            for l in valid_langs:
                item = QAction(str(l), menu)
                item.setData(l)
                self._set_icon(item, l)
                item.setFont(bf)
                menu.addAction(item)
            menu.addSeparator()
        for l in languages:
            item = QAction(str(l), menu)
            item.setData(l)
            self._set_icon(item, l)
            menu.addAction(item)
        return menu

    def showSubgrammarMenu(self):
        menu = QtGui.QMenu("Language", self)
        self.createSubgrammarMenu(menu)
        x,y = self.cursor_to_coordinate()
        action = menu.exec_(self.mapToGlobal(QPoint(0,0)) + QPoint(3 + x, y + self.fontht))
        if action:
            self.sublanguage = action.data().toPyObject()
            self.edit_rightnode = True

    def _set_icon(self, mitem, lang):
        if lang.base.lower() == "html":
            icon = QIcon.fromTheme("text-xhtml+xml")
        else:
            icon = QIcon.fromTheme("text-x-" + lang.base.lower())
        if icon.isNull():
            icon = QIcon.fromTheme("application-x-" + lang.base.lower())
            if icon.isNull():
                icon = QIcon.fromTheme("text-x-generic")
        mitem.setIcon(icon)

    def showCodeCompletionMenu(self, l):
        menu = QtGui.QMenu( self )
        # Create actions
        toolbar = QtGui.QToolBar()
        for n in l:
            path = []
            for p in n.path:
                if p and p.name:
                    path.append(p.name)
            if n.vartype:
                vartype = n.vartype
                while vartype.children != []:
                    try:
                        vartype = vartype.children[0]
                    except KeyError:
                        vartype = vartype.children["name"]
                text = "%s : %s - %s (%s)" % (n.name, vartype.symbol.name, ".".join(path), n.kind)
            elif n.kind == "method":
                text = self.cc_method(n) + " - %s" % (".".join(path))
            else:
                text = "%s - %s (%s)" % (n.name, ".".join(path), n.kind)
            item = toolbar.addAction(text, self.createCCFunc(n.name))
            item.setIcon(QIcon("gui/" + n.kind + ".png"))
            menu.addAction(item)
        x,y = self.cursor_to_coordinate()
        menu.exec_(self.mapToGlobal(QPoint(0,0)) + QPoint(3 + x, y + self.fontht))

    def cc_method(self, n):
        s = [n.name, "("]
        param_ln = n.astnode.children["params"]
        if isinstance(param_ln, ListNode):
            for p in param_ln.children:
                tmp = p.children["type"]
                if isinstance(tmp, AstNode):
                    s.append(tmp.children["name"].symbol.name)
                else:
                    s.append(tmp.symbol.name)
                s.append(" ")
                s.append(p.children["name"].symbol.name)
                if p != param_ln.children[-1]:
                    s.append(", ")
        s.append(")")
        return "".join(s)

    def createMenuFunction(self, l):
        def action():
            self.sublanguage = l
            self.edit_rightnode = True
        return action

    def createCCFunc(self, text):
        def action():
            self.tm.pasteCompletion(text)
        return action

    def selectSubgrammar(self, item):
        pass

    def saveToJson(self, filename, swap=False):
        whitespaces = self.tm.get_mainparser().whitespaces
        root = self.tm.parsers[0][0].previous_version.parent
        language = self.tm.parsers[0][2]
        manager = JsonManager()
        manager.save(root, language, whitespaces, filename)
        if not swap:
            self.tm.changed = False
            self.emit(SIGNAL("painted()"))

    def loadFromJson(self, filename):
        manager = JsonManager()
        language_boxes = manager.load(filename)

        self.tm = TreeManager()

        self.tm.load_file(language_boxes)
        self.reset()

    def export(self, run=False, profile=False):
        return self.tm.export(None, run, profile)
Beispiel #33
0
    def __init__(self):

        # PREPARE LOGGING FIRST TO ENSURE
        # THE ABILITY TO OUTPUT ERROR LOGS
        #
        # create logging folders
        self._makeLogDirs()

        # initialise the logger
        self.logger = self._setLogger()

        # catch exceptions to log them
        try:

            # call parent class constructor
            Configurable.__init__(self, self.SLF_PATH)

            # initialise overlay
            self.overlay = Overlay(f'{self.PRG_NAME.upper()} {self.PRG_VERS}')

            # point pytesseract at tesseract installation
            self._setPyTesseract()

            # initialise a lobby reader
            self.lobby_reader = LobbyReader()

            # initialise a loot reader
            self.loot_reader = LootReader()

            # initialise a bounty reader
            self.bounty_reader = BountyReader()

            # initialise a data sender
            self.data_sender = DataSender()

            # read user from config file
            self.user = self._setUser()

            # read game patch
            self.patch = self._setGamePatch()

            # initialise screen capture as empty
            self.screen_capture = None

            # data holders
            self.bounty_data = {}
            self.lobby_data = {}
            self.loot_data = []

            # exception counter for repeated issue handling
            self.exc_counter = 0

            # welcome the user
            self.welcomeMessage()

        except Exception as e:

            # log the exception
            self.logger.error(str(e))

            # shut down the app
            quit()