class SetTempVTICommand():
    def __init__(self):
        self.regexp_str="Set VTI Loop (\d+) to "+Regexfloat+" K(?: @ "+Regexfloat+" K/min)?"
        self.label="Set VTI Loop X to X K (@ X K/min)"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        ##get the loop index and setpoint value
        loop=float(values[1])
        setpoint=float(values[2])
        #if a ramp rate was also provided, go to this setpoint at this rate
        VTI=main.instr_9
        if values[3]!='':
            rate=float(values[3])
            with main.reserved_access_to_instr:
                VTI.conf_ramp(loop,rate,'on')
                VTI.set_setpoint(loop,setpoint)
        else:
            with main.reserved_access_to_instr:
                VTI.switch_ramp(loop,'off')
                VTI.set_setpoint(loop,setpoint)
        #go to next line of macro after stdwtime (give some time to process other events)
        self.next_move=1
        self.wait_time=500
class WaitForTPPMSStableCommand():
    def __init__(self):
        self.regexp_str="Wait(?: at most "+Regexfloat+" secs)? for PPMS Temp to reach "+Regexfloat+" K"
        self.label="Wait(at most X secs) for PPMS Temp to reach X K"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        #Wait for the temperature measurement to be stable and
        #within 5% of specified temperature
        #(and lock only when accessing the instrument)
        with main.reserved_access_to_instr:
            Terror, T, status = main.ppms.get_temperature()
        if self.waiting==False:
            self.waiting=True
            self.waiting_start=time.clock()
        if status == 'Stable' and abs(T-float(values[2]))<abs(float(values[2])*0.05):
            #Temperature is stable, go to next line of macro
            self.waiting=False
            self.next_move=1
            self.wait_time=500
        elif values[1]!='' and time.clock()-self.waiting_start>float(values[1]):
            #time limit is reached, go to next line of macro
            self.waiting=False
            self.next_move=1
            self.wait_time=500
        else:
            #wait 10s and check again
            self.next_move=0
            self.wait_time=10000
Esempio n. 3
0
 def __autoIncFilename(self):
     """
     Private method to auto-increment the file name.
     """
     # Extract the file name
     name = os.path.basename(self.__filename)
     
     # If the name contains a number, then increment it.
     numSearch = QRegExp("(^|[^\\d])(\\d+)")
     # We want to match as far left as possible, and when the number is
     # at the start of the name.
     
     # Does it have a number?
     start = numSearch.lastIndexIn(name)
     if start != -1:
         # It has a number, increment it.
         start = numSearch.pos(2)    # Only the second group is of interest.
         numAsStr = numSearch.capturedTexts()[2]
         number = "{0:0{width}d}".format(
             int(numAsStr) + 1, width=len(numAsStr))
         name = name[:start] + number + name[start + len(numAsStr):]
     else:
         # no number
         start = name.rfind('.')
         if start != -1:
             # has a '.' somewhere, e.g. it has an extension
             name = name[:start] + '1' + name[start:]
         else:
             # no extension, just tack it on to the end
             name += '1'
     
     self.__filename = os.path.join(os.path.dirname(self.__filename), name)
     self.__updateCaption()
class SetPPMSFieldCommand():
    def __init__(self):
        self.regexp_str="Set PPMS Field to "+Regexfloat+" Oe @ "+Regexfloat+" Oe/s (Linear|NoOvershoot|Oscillate)? (Persistent|Driven)?"
        self.label="Set PPMS Field to X Oe @ X Oe/s (Linear|NoOvershoot|Oscillate) (Persistent|Driven)"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        ##get the loop index and setpoint value
        setpoint=float(values[1])
        rate=float(values[2])
        #if an approach was also provided, go to this setpoint at this rate
        approach = 'Linear'
        mode = 'Persistent'
        if values[3]!='':approach = values[3]
        if values[4]!='':mode = values[4]
        with main.reserved_access_to_instr:
            main.ppms.set_field(setpoint,rate,approach,mode)

        #go to next line of macro after stdwtime (give some time to process other events)
        self.next_move=1
        self.wait_time=100
class WaitForHStableCommand():
    def __init__(self):
        self.regexp_str="Wait(?: at most "+Regexfloat+" secs)? for magnet (X|Y|Z) to finish ramping"
        self.label="Wait (at most X secs) for magnet (X|Y|Z) to finish ramping"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        #wait for field to stabilize (and lock only when accessing the instrument)
        with main.reserved_access_to_instr:
            magnet=eval("main.magnet_"+values[2])
            stat=magnet.query_status()
        if self.waiting==False:
            self.waiting=True
            self.waiting_start=time.clock()
        if not(stat=='RAMPING to programmed current/field') or (values[1]!='' and time.clock()-self.waiting_start>float(values[1])):
            #ramping is finished or time limit is reached, go to next line of macro
            self.waiting=False
            self.next_move=1
            self.wait_time=500
        else:
            #wait 5s and check again
            self.next_move=0
            self.wait_time=5000
Esempio n. 6
0
    def __autoIncFilename(self):
        """
        Private method to auto-increment the file name.
        """
        # Extract the file name
        name = os.path.basename(self.__filename)

        # If the name contains a number, then increment it.
        numSearch = QRegExp("(^|[^\\d])(\\d+)")
        # We want to match as far left as possible, and when the number is
        # at the start of the name.

        # Does it have a number?
        start = numSearch.lastIndexIn(name)
        if start != -1:
            # It has a number, increment it.
            start = numSearch.pos(2)  # Only the second group is of interest.
            numAsStr = numSearch.capturedTexts()[2]
            number = "{0:0{width}d}".format(int(numAsStr) + 1,
                                            width=len(numAsStr))
            name = name[:start] + number + name[start + len(numAsStr):]
        else:
            # no number
            start = name.rfind('.')
            if start != -1:
                # has a '.' somewhere, e.g. it has an extension
                name = name[:start] + '1' + name[start:]
            else:
                # no extension, just tack it on to the end
                name += '1'

        self.__filename = os.path.join(os.path.dirname(self.__filename), name)
        self.__updateCaption()
class AngleCommand():
    def __init__(self):
        #Text that will appear in the list of commands on the right side of the Macro editor
        self.label="Set start|stop|step angle to FLOAT"
        #Regular expression which may or may not catch parameters
        self.regexp_str="Set (start|stop|step) angle to "+Regexfloat
        #Add this to the beginning and end of the regular expression
        #so that whitespaces before and after will not prevent the regex from matching
        self.regexp_str="^ *"+self.regexp_str+" *$"
        #instantiate regex
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        #what to do when the regex defined just above in __init__
        #has matched the current line of the Macro
        #get the captured parameters
        values=self.regexp.capturedTexts()
        #set the corresponding angle box
        if values[1] in ['stop','step','start']:
            anglebox=eval("main.ui.angle"+values[1])
            anglebox.setValue(float(values[2]))
        #Finally go to next line of macro...
        self.next_move=1
        #...after 10 milliseconds
        self.wait_time=10
class WaitCommand():
    def __init__(self):
        self.regexp_str="Wait "+Regexfloat+" secs"
        self.label="Wait X secs"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #self.values[1]!=''
        #go to next line of macro after 'values[1]' seconds
        self.next_move=1
        self.wait_time=float(values[1])*1000
class SetSaveFileCommand():
    def __init__(self):
        self.regexp_str="Set Save file to "+Regexsimplefile+""
        self.label="Set Save file to X"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        main.ui.savefile_txt_input.setText(values[1])
        #new file name is set, go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetVTIHeaterCommand():
    def __init__(self):
        self.regexp_str="Set VTI heater range to (\d)"
        self.label="Set VTI heater range to DIGIT"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the heater range
        with main.reserved_access_to_instr:
            main.instr_9.set_heater_range(int(values[1]))
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetLR700VCommand():
    def __init__(self):
        self.regexp_str="Set LR700 excitation to "+Regexfloat+" V"
        self.label="Set LR700 excitation to FLOAT V"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the voltage
        V_source_setpoint=eval("main.ui.V_LR700")
        V_source_setpoint.setValue(float(values[1])*1e6)
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetLR700IntegRateCommand():
    def __init__(self):
        self.regexp_str="Set LR700 integration rate to "+Regexfloat+" secs"
        self.label="Set LR700 integration rate to FLOAT secs"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the voltage
        setpoint=eval("main.ui.integ_rate_LR700")
        setpoint.setValue(float(values[1]))
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class WaitForEpoch():
    def __init__(self):
        self.regexp_str="Wait for Epoch \+ "+Regexfloat+" secs"
        self.label="Wait for Epoch + X secs"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #test if the current time is greater than the time provided in the macro (in Epoch seconds)
        if float(values[1])>time.time():
            self.next_move=0
            self.wait_time=5000
        else:
            self.next_move=1
            self.wait_time=100
class StartMeasureCommand():
    def __init__(self):
        #type name_of_program() to start it
        self.regexp_str="Start "+Regexprogramfile+"\((.*)\)"
        self.label="Start PROGRAM()"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        main.ui.measMode.setCurrentIndex(main.ui.measMode.findText(values[1]))
        #start measurements
        main.start_measurements()
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetVCommand():
    def __init__(self):
        self.regexp_str="Set voltage (\d) to "+Regexfloat+" V"
        self.label="Set voltage DIGIT to FLOAT V"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the voltage
        if values[1] in ['1','2','3']:
            V_source_setpoint=eval("main.ui.V_setpoint_"+values[1])
            V_source_setpoint.setValue(float(values[2]))
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetUICommand():
    def __init__(self,main):
#        print "|".join(dir(main.ui))
        self.regexp_str="Set UI ("+"|".join(dir(main.ui))+") to "+Regexfloat
        self.label="Set UI PROPERTY to FLOAT"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the property
        prop = eval("main.ui."+values[1])
        prop.setValue(float(values[2]))
        #go to next line of macro
        self.next_move=1
        self.wait_time=10
class SetICommand():
    def __init__(self):
        self.regexp_str="Set current (\d) to "+Regexfloat+" A"
        self.label="Set current DIGIT to FLOAT A"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        #set the current
        if values[1]=='1':
            main.ui.I_source_setpoint.setValue(float(values[2])*1e6)
        elif values[1] in ['2','3']:
            I_source_setpoint=eval("main.ui.I_source_setpoint_"+values[1])
            I_source_setpoint.setValue(float(values[2])*1e6)
        #go to next line of macro
        self.next_move=1
        self.wait_time=10
class EmailCommand():
    def __init__(self):
        self.regexp_str="E-mail message: "+Regexsimplefile
        self.label="E-mail message: MESSAGE"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        msg=values[1]
        try:
            email_alert=Email_alert(message=msg,address=main.ui.email_address.text(),subject="Message from PyGMI",smtpadd=main.mainconf['smtpadd'],login=main.mainconf['login'],mdp=main.mainconf['mdp'],smtpport=main.mainconf['smtpport'])
            print("message successfully sent by e-mail")
        except:
            print("Exception: message could not be sent by e-mail")
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class SetPersistFieldCommand():
    def __init__(self):
        self.regexp_str="Set persistent field in magnet (X|Y|Z) to "+Regexfloat+" T"
        self.label="Set persistent field in magnet X|Y|Z to x T"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        ##set the loop index and setpoint value
        magnet_setpoint=eval("main.ui.B_"+values[1]+"_setpoint")
        magnet_setpoint.setValue(float(values[2]))
        time.sleep(1)
        main.ui.measMode.setCurrentIndex(main.ui.measMode.findText("Change_persistent_"+values[1]+"_field"))
        #start measurements
        main.start_measurements()
        #go to next line of macro after stdwtime (give some time to process other events)
        self.next_move=1
        self.wait_time=500
class EmailDirCommand():
    def __init__(self):
        self.regexp_str="E-mail directory: "+Regexsimplefile
        self.label="E-mail directory: DIRECTORY"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        dir_path=values[1]
        try:
            message="Hi,\n\nat your request, here is the directory: "+os.path.normpath(os.path.abspath(dir_path.strip()))+"\n\n PyGMI"
            email_alert=Email_directory(directory=dir_path.strip(),address=main.ui.email_address.text(),message=message,subject="Data directory from PyGMI",smtpadd=main.mainconf['smtpadd'],login=main.mainconf['login'],mdp=main.mainconf['mdp'],smtpport=main.mainconf['smtpport'])
            print("directory successfully sent by e-mail")
        except:
            print("Exception: directory could not be sent by e-mail")
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class WaitForTStableCommand():
    def __init__(self):
        self.regexp_str="Wait(?: at most "+Regexfloat+" secs)? for channel (\w) to reach "+Regexfloat+" \+/\- "+Regexfloat+" K"
        self.label="Wait(at most X secs) for channel X to reach X +/- X K"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        #wait for temperature to stabilize (and lock only when accessing the instrument)
        with main.reserved_access_to_instr:
            T=main.temp_controller.query_temp(values[2])
        if self.waiting==False:
            self.waitTcounter=0
            self.waiting=True
            self.waiting_start=time.clock()
        if values[1]!='' and time.clock()-self.waiting_start>float(values[1]):
            #time limit is reached, go to next line of macro
            self.waiting=False
            self.next_move=1
            self.wait_time=500
        elif abs(T-float(values[3]))<float(values[4]):
            #Wait for the temperature measurement to be ten times
            #within the specified limits, in a row, to consider it stable
            if self.waitTcounter<10:
                #count one, wait 0.5 secs and measure T again
                self.waitTcounter+=1
                self.next_move=0
                self.wait_time=500
            else:
                #Temperature is stable, go to next line of macro
                self.waitTcounter=0
                self.waiting=False
                self.next_move=1
                self.wait_time=500
        else:
            #wait 10s and check again, but reset the stable temperature counter
            self.waitTcounter=0
            self.next_move=0
            self.wait_time=10000
class SetFieldCommand():
    def __init__(self):
        self.regexp_str="Set Field of magnet (X|Y|Z) to "+Regexfloat+" G(?: @ "+Regexfloat+" G/s)?"
        self.label="Set Field of magnet X|Y|Z to X G (@ X G/s)"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)

    def run(self,main):
        values=self.regexp.capturedTexts()
        with main.reserved_access_to_instr:
            magnet=eval("main.magnet_"+values[1])
            if values[3]!='':
                #if a ramp rate was also provided, go to this setpoint at this rate
                magnet.program_ramp_rate_in_Gauss_per_second(float(values[3]))
            #print "Setting Field to ",
            magnet.program_field_in_kG(float(values[2])*1e-3)
            magnet.ramp_to_programmed_field()
        #go to next line of macro
        self.next_move=1
        self.wait_time=500
class WaitForMeasureCommand():
    def __init__(self):
        self.regexp_str="Wait(?: at most "+Regexfloat+" secs)? for measurements completion"
        self.label="Wait(at most X secs) for measurements completion"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        if self.waiting==False:
            self.waiting=True
            self.waiting_start=time.clock()
        if not(main.measurements_thread.isAlive()) or (values[1]!='' and time.clock()-self.waiting_start>float(values[1])):
            #Measurements are complete or time limit was reached, go to next line of macro
            self.waiting=False
            self.next_move=1
            self.wait_time=500
        else:
            #wait 1s and check again if measurements are complete
            self.next_move=0
            self.wait_time=1000
class SetPPMSTempCommand():
    def __init__(self):
        self.regexp_str="Set PPMS Temperature to "+Regexfloat+" K @ "+Regexfloat+" K/min (FastSettle|NoOvershoot)?"
        self.label="Set PPMS Temperature to X K @ X K/min (FastSettle/NoOvershoot)"
        self.regexp_str="^ *"+self.regexp_str+" *$" #so that the same string with heading and trailing whitespaces also matches
        self.regexp=QRegExp(self.regexp_str)
        self.waiting=False
        self.waiting_start=0

    def run(self,main):
        values=self.regexp.capturedTexts()
        ##get the loop index and setpoint value
        setpoint=float(values[1])
        rate=float(values[2])
        #if an approach was also provided, go to this setpoint at this rate
        approach = 'FastSettle'
        if values[3]!='':approach = values[3]
        with main.reserved_access_to_instr:
            main.ppms.set_temperature(setpoint,rate,approach)

        #go to next line of macro after stdwtime (give some time to process other events)
        self.next_move=1
        self.wait_time=100
Esempio n. 25
0
class CallTraceViewer(QWidget, Ui_CallTraceViewer):
    """
    Class implementing the Call Trace viewer widget.
    
    @signal sourceFile(str, int) emitted to show the source of a call/return
        point
    """
    sourceFile = pyqtSignal(str, int)
    
    def __init__(self, debugServer, parent=None):
        """
        Constructor
        
        @param debugServer reference to the debug server object (DebugServer)
        @param parent reference to the parent widget (QWidget)
        """
        super(CallTraceViewer, self).__init__(parent)
        self.setupUi(self)
        
        self.__dbs = debugServer
        
        self.startTraceButton.setIcon(
            UI.PixmapCache.getIcon("callTraceStart.png"))
        self.stopTraceButton.setIcon(
            UI.PixmapCache.getIcon("callTraceStop.png"))
        self.resizeButton.setIcon(UI.PixmapCache.getIcon("resizeColumns.png"))
        self.clearButton.setIcon(UI.PixmapCache.getIcon("editDelete.png"))
        self.saveButton.setIcon(UI.PixmapCache.getIcon("fileSave.png"))
        
        self.__headerItem = QTreeWidgetItem(
            ["", self.tr("From"), self.tr("To")])
        self.__headerItem.setIcon(0, UI.PixmapCache.getIcon("callReturn.png"))
        self.callTrace.setHeaderItem(self.__headerItem)
        
        self.__callStack = []
        
        self.__entryFormat = "{0}:{1} ({2})"
        self.__entryRe = QRegExp(r"""(.+):(\d+)\s\((.*)\)""")
        
        self.__projectMode = False
        self.__project = None
        
        self.__callTraceEnabled = Preferences.toBool(
            Preferences.Prefs.settings.value("CallTrace/Enabled", False))
        if self.__callTraceEnabled:
            self.startTraceButton.setEnabled(False)
        else:
            self.stopTraceButton.setEnabled(False)
        
        self.__dbs.callTraceInfo.connect(self.__addCallTraceInfo)
    
    def __setCallTraceEnabled(self, enabled):
        """
        Private slot to set the call trace enabled status.
        
        @param enabled flag indicating the new state (boolean)
        """
        self.__dbs.setCallTraceEnabled(enabled)
        self.stopTraceButton.setEnabled(enabled)
        self.startTraceButton.setEnabled(not enabled)
        self.__callTraceEnabled = enabled
        Preferences.Prefs.settings.setValue("CallTrace/Enabled", enabled)
    
    @pyqtSlot()
    def on_startTraceButton_clicked(self):
        """
        Private slot to start call tracing.
        """
        self.__setCallTraceEnabled(True)
    
    @pyqtSlot()
    def on_stopTraceButton_clicked(self):
        """
        Private slot to start call tracing.
        """
        self.__setCallTraceEnabled(False)
    
    @pyqtSlot()
    def on_resizeButton_clicked(self):
        """
        Private slot to resize the columns of the call trace to their contents.
        """
        for column in range(self.callTrace.columnCount()):
            self.callTrace.resizeColumnToContents(column)
    
    @pyqtSlot()
    def on_clearButton_clicked(self):
        """
        Private slot to clear the call trace.
        """
        self.clear()
    
    @pyqtSlot()
    def on_saveButton_clicked(self):
        """
        Private slot to save the call trace info to a file.
        """
        if self.callTrace.topLevelItemCount() > 0:
            fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
                self,
                self.tr("Save Call Trace Info"),
                "",
                self.tr("Text Files (*.txt);;All Files (*)"),
                None,
                E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
            if fname:
                ext = QFileInfo(fname).suffix()
                if not ext:
                    ex = selectedFilter.split("(*")[1].split(")")[0]
                    if ex:
                        fname += ex
                if QFileInfo(fname).exists():
                    res = E5MessageBox.yesNo(
                        self,
                        self.tr("Save Call Trace Info"),
                        self.tr("<p>The file <b>{0}</b> already exists."
                                " Overwrite it?</p>").format(fname),
                        icon=E5MessageBox.Warning)
                    if not res:
                        return
                    fname = Utilities.toNativeSeparators(fname)
                
                try:
                    f = open(fname, "w", encoding="utf-8")
                    itm = self.callTrace.topLevelItem(0)
                    while itm is not None:
                        isCall = itm.data(0, Qt.UserRole)
                        if isCall:
                            call = "->"
                        else:
                            call = "<-"
                        f.write("{0} {1} || {2}\n".format(
                            call,
                            itm.text(1), itm.text(2)))
                        itm = self.callTrace.itemBelow(itm)
                    f.close()
                except IOError as err:
                    E5MessageBox.critical(
                        self,
                        self.tr("Error saving Call Trace Info"),
                        self.tr("""<p>The call trace info could not"""
                                """ be written to <b>{0}</b></p>"""
                                """<p>Reason: {1}</p>""")
                        .format(fname, str(err)))
    
    @pyqtSlot(QTreeWidgetItem, int)
    def on_callTrace_itemDoubleClicked(self, item, column):
        """
        Private slot to open the double clicked file in an editor.
        
        @param item reference to the double clicked item (QTreeWidgetItem)
        @param column column that was double clicked (integer)
        """
        if item is not None and column > 0:
            columnStr = item.text(column)
            if self.__entryRe.exactMatch(columnStr.strip()):
                filename, lineno, func = self.__entryRe.capturedTexts()[1:]
                try:
                    lineno = int(lineno)
                except ValueError:
                    # do nothing, if the line info is not an integer
                    return
                if self.__projectMode:
                    filename = self.__project.getAbsolutePath(filename)
                self.sourceFile.emit(filename, lineno)
    
    def clear(self):
        """
        Public slot to clear the call trace info.
        """
        self.callTrace.clear()
        self.__callStack = []
    
    def setProjectMode(self, enabled):
        """
        Public slot to set the call trace viewer to project mode.
        
        In project mode the call trace info is shown with project relative
        path names.
        
        @param enabled flag indicating to enable the project mode (boolean)
        """
        self.__projectMode = enabled
        if enabled and self.__project is None:
            self.__project = e5App().getObject("Project")
    
    def __addCallTraceInfo(self, isCall, fromFile, fromLine, fromFunction,
                           toFile, toLine, toFunction):
        """
        Private method to add an entry to the call trace viewer.
        
        @param isCall flag indicating a 'call' (boolean)
        @param fromFile name of the originating file (string)
        @param fromLine line number in the originating file (string)
        @param fromFunction name of the originating function (string)
        @param toFile name of the target file (string)
        @param toLine line number in the target file (string)
        @param toFunction name of the target function (string)
        """
        if isCall:
            icon = UI.PixmapCache.getIcon("forward.png")
        else:
            icon = UI.PixmapCache.getIcon("back.png")
        parentItem = \
            self.__callStack[-1] if self.__callStack else self.callTrace
        
        if self.__projectMode:
            fromFile = self.__project.getRelativePath(fromFile)
            toFile = self.__project.getRelativePath(toFile)
        
        itm = QTreeWidgetItem(
            parentItem,
            ["",
             self.__entryFormat.format(fromFile, fromLine, fromFunction),
             self.__entryFormat.format(toFile, toLine, toFunction)])
        itm.setIcon(0, icon)
        itm.setData(0, Qt.UserRole, isCall)
        itm.setExpanded(True)
        
        if isCall:
            self.__callStack.append(itm)
        else:
            if self.__callStack:
                self.__callStack.pop(-1)
    
    def isCallTraceEnabled(self):
        """
        Public method to get the state of the call trace function.
        
        @return flag indicating the state of the call trace function (boolean)
        """
        return self.__callTraceEnabled
Esempio n. 26
0
class Highlighter(QSyntaxHighlighter):
    """ Syntax Highlighting

    This class defines rules, a rule consists of a QRegExp pattern and a
    QTextCharFormat instance.
    """

    # Keywords
    KEYWORDS = [
        "select", "project", "rename", "product", "njoin", "louter", "router",
        "fouter", "difference", "intersect", "union", "and", "or"
    ]

    def __init__(self, editor):
        super(Highlighter, self).__init__(editor)
        # Keywords format
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#222"))
        keyword_format.setFontWeight(QFont.Bold)

        # Rules
        self._rules = [(QRegExp("\\b" + pattern + "\\b"), keyword_format)
                       for pattern in Highlighter.KEYWORDS]

        # vars
        var_format = QTextCharFormat()
        var_pattern = QRegExp("\w+\s*\:\=")
        var_format.setFontWeight(QFont.Bold)
        var_format.setForeground(QColor("#dd1144"))

        self._rules.append((var_pattern, var_format))

        op_format = QTextCharFormat()
        op_pattern = QRegExp("(\\:=|\\(|\\))|=|<|>")
        op_format.setForeground(QColor("#222"))
        op_format.setFontWeight(QFont.Bold)
        self._rules.append((op_pattern, op_format))
        # Number format
        number_format = QTextCharFormat()
        number_pattern = QRegExp(r"\b([A-Z0-9]+)(?:[ _-](\d+))?\b")
        number_pattern.setMinimal(True)
        number_format.setForeground(QColor("orange"))
        self._rules.append((number_pattern, number_format))

        # String format
        string_format = QTextCharFormat()
        string_pattern = QRegExp("\'.*\'")
        string_pattern.setMinimal(True)
        string_format.setForeground(Qt.darkGreen)
        self._rules.append((string_pattern, string_format))

        # Comment format
        comment_format = QTextCharFormat()
        comment_pattern = QRegExp("%[^\n]*")
        comment_format.setForeground(QColor("#999988"))
        comment_format.setFontItalic(True)
        self._rules.append((comment_pattern, comment_format))

        # Paren
        self.paren = QRegExp('\(|\)')

    def highlightBlock(self, text):
        """ Reimplementation """

        block_data = TextBlockData()
        # Paren
        index = self.paren.indexIn(text, 0)
        while index >= 0:
            matched_paren = str(self.paren.capturedTexts()[0])
            info = ParenInfo(matched_paren, index)
            block_data.insert_paren_info(info)
            index = self.paren.indexIn(text, index + 1)

        self.setCurrentBlockUserData(block_data)

        for pattern, _format in self._rules:
            expression = QRegExp(pattern)
            index = expression.indexIn(text)
            while index >= 0:
                length = expression.matchedLength()
                self.setFormat(index, length, _format)
                index = expression.indexIn(text, index + length)

        self.setCurrentBlockState(0)
Esempio n. 27
0
class CallTraceViewer(QWidget, Ui_CallTraceViewer):
    """
    Class implementing the Call Trace viewer widget.
    
    @signal sourceFile(str, int) emitted to show the source of a call/return
        point
    """
    sourceFile = pyqtSignal(str, int)

    def __init__(self, debugServer, parent=None):
        """
        Constructor
        
        @param debugServer reference to the debug server object (DebugServer)
        @param parent reference to the parent widget (QWidget)
        """
        super(CallTraceViewer, self).__init__(parent)
        self.setupUi(self)

        self.__dbs = debugServer

        self.startTraceButton.setIcon(
            UI.PixmapCache.getIcon("callTraceStart.png"))
        self.stopTraceButton.setIcon(
            UI.PixmapCache.getIcon("callTraceStop.png"))
        self.resizeButton.setIcon(UI.PixmapCache.getIcon("resizeColumns.png"))
        self.clearButton.setIcon(UI.PixmapCache.getIcon("editDelete.png"))
        self.saveButton.setIcon(UI.PixmapCache.getIcon("fileSave.png"))

        self.__headerItem = QTreeWidgetItem(
            ["", self.tr("From"), self.tr("To")])
        self.__headerItem.setIcon(0, UI.PixmapCache.getIcon("callReturn.png"))
        self.callTrace.setHeaderItem(self.__headerItem)

        self.__callStack = []

        self.__entryFormat = "{0}:{1} ({2})"
        self.__entryRe = QRegExp(r"""(.+):(\d+)\s\((.*)\)""")

        self.__projectMode = False
        self.__project = None

        self.__callTraceEnabled = Preferences.toBool(
            Preferences.Prefs.settings.value("CallTrace/Enabled", False))
        if self.__callTraceEnabled:
            self.startTraceButton.setEnabled(False)
        else:
            self.stopTraceButton.setEnabled(False)

        self.__dbs.callTraceInfo.connect(self.__addCallTraceInfo)

    def __setCallTraceEnabled(self, enabled):
        """
        Private slot to set the call trace enabled status.
        
        @param enabled flag indicating the new state (boolean)
        """
        self.__dbs.setCallTraceEnabled(enabled)
        self.stopTraceButton.setEnabled(enabled)
        self.startTraceButton.setEnabled(not enabled)
        self.__callTraceEnabled = enabled
        Preferences.Prefs.settings.setValue("CallTrace/Enabled", enabled)

    @pyqtSlot()
    def on_startTraceButton_clicked(self):
        """
        Private slot to start call tracing.
        """
        self.__setCallTraceEnabled(True)

    @pyqtSlot()
    def on_stopTraceButton_clicked(self):
        """
        Private slot to start call tracing.
        """
        self.__setCallTraceEnabled(False)

    @pyqtSlot()
    def on_resizeButton_clicked(self):
        """
        Private slot to resize the columns of the call trace to their contents.
        """
        for column in range(self.callTrace.columnCount()):
            self.callTrace.resizeColumnToContents(column)

    @pyqtSlot()
    def on_clearButton_clicked(self):
        """
        Private slot to clear the call trace.
        """
        self.clear()

    @pyqtSlot()
    def on_saveButton_clicked(self):
        """
        Private slot to save the call trace info to a file.
        """
        if self.callTrace.topLevelItemCount() > 0:
            fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
                self, self.tr("Save Call Trace Info"), "",
                self.tr("Text Files (*.txt);;All Files (*)"), None,
                E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
            if fname:
                ext = QFileInfo(fname).suffix()
                if not ext:
                    ex = selectedFilter.split("(*")[1].split(")")[0]
                    if ex:
                        fname += ex
                if QFileInfo(fname).exists():
                    res = E5MessageBox.yesNo(
                        self,
                        self.tr("Save Call Trace Info"),
                        self.tr("<p>The file <b>{0}</b> already exists."
                                " Overwrite it?</p>").format(fname),
                        icon=E5MessageBox.Warning)
                    if not res:
                        return
                    fname = Utilities.toNativeSeparators(fname)

                try:
                    f = open(fname, "w", encoding="utf-8")
                    itm = self.callTrace.topLevelItem(0)
                    while itm is not None:
                        isCall = itm.data(0, Qt.UserRole)
                        if isCall:
                            call = "->"
                        else:
                            call = "<-"
                        f.write("{0} {1} || {2}\n".format(
                            call, itm.text(1), itm.text(2)))
                        itm = self.callTrace.itemBelow(itm)
                    f.close()
                except IOError as err:
                    E5MessageBox.critical(
                        self, self.tr("Error saving Call Trace Info"),
                        self.tr("""<p>The call trace info could not"""
                                """ be written to <b>{0}</b></p>"""
                                """<p>Reason: {1}</p>""").format(
                                    fname, str(err)))

    @pyqtSlot(QTreeWidgetItem, int)
    def on_callTrace_itemDoubleClicked(self, item, column):
        """
        Private slot to open the double clicked file in an editor.
        
        @param item reference to the double clicked item (QTreeWidgetItem)
        @param column column that was double clicked (integer)
        """
        if item is not None and column > 0:
            columnStr = item.text(column)
            if self.__entryRe.exactMatch(columnStr.strip()):
                filename, lineno, func = self.__entryRe.capturedTexts()[1:]
                try:
                    lineno = int(lineno)
                except ValueError:
                    # do nothing, if the line info is not an integer
                    return
                if self.__projectMode:
                    filename = self.__project.getAbsolutePath(filename)
                self.sourceFile.emit(filename, lineno)

    def clear(self):
        """
        Public slot to clear the call trace info.
        """
        self.callTrace.clear()
        self.__callStack = []

    def setProjectMode(self, enabled):
        """
        Public slot to set the call trace viewer to project mode.
        
        In project mode the call trace info is shown with project relative
        path names.
        
        @param enabled flag indicating to enable the project mode (boolean)
        """
        self.__projectMode = enabled
        if enabled and self.__project is None:
            self.__project = e5App().getObject("Project")

    def __addCallTraceInfo(self, isCall, fromFile, fromLine, fromFunction,
                           toFile, toLine, toFunction):
        """
        Private method to add an entry to the call trace viewer.
        
        @param isCall flag indicating a 'call' (boolean)
        @param fromFile name of the originating file (string)
        @param fromLine line number in the originating file (string)
        @param fromFunction name of the originating function (string)
        @param toFile name of the target file (string)
        @param toLine line number in the target file (string)
        @param toFunction name of the target function (string)
        """
        if isCall:
            icon = UI.PixmapCache.getIcon("forward.png")
        else:
            icon = UI.PixmapCache.getIcon("back.png")
        parentItem = \
            self.__callStack[-1] if self.__callStack else self.callTrace

        if self.__projectMode:
            fromFile = self.__project.getRelativePath(fromFile)
            toFile = self.__project.getRelativePath(toFile)

        itm = QTreeWidgetItem(parentItem, [
            "",
            self.__entryFormat.format(fromFile, fromLine, fromFunction),
            self.__entryFormat.format(toFile, toLine, toFunction)
        ])
        itm.setIcon(0, icon)
        itm.setData(0, Qt.UserRole, isCall)
        itm.setExpanded(True)

        if isCall:
            self.__callStack.append(itm)
        else:
            if self.__callStack:
                self.__callStack.pop(-1)

    def isCallTraceEnabled(self):
        """
        Public method to get the state of the call trace function.
        
        @return flag indicating the state of the call trace function (boolean)
        """
        return self.__callTraceEnabled
Esempio n. 28
0
class Highlighter(QSyntaxHighlighter):
    """ Syntax Highlighting

    This class defines rules, a rule consists of a QRegExp pattern and a
    QTextCharFormat instance.
    """

    # Keywords
    KEYWORDS = [
        "select",
        "project",
        "rename",
        "product",
        "njoin",
        "louter",
        "router",
        "fouter",
        "difference",
        "intersect",
        "union",
        "and",
        "or"
    ]

    def __init__(self, editor):
        super(Highlighter, self).__init__(editor)
        # Keywords format
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#222"))
        keyword_format.setFontWeight(QFont.Bold)

        # Rules
        self._rules = [(QRegExp("\\b" + pattern + "\\b"), keyword_format)
                       for pattern in Highlighter.KEYWORDS]

        # vars
        var_format = QTextCharFormat()
        var_pattern = QRegExp("\w+\s*\:\=")
        var_format.setFontWeight(QFont.Bold)
        var_format.setForeground(QColor("#dd1144"))

        self._rules.append((var_pattern, var_format))

        op_format = QTextCharFormat()
        op_pattern = QRegExp("(\\:=|\\(|\\))|=|<|>")
        op_format.setForeground(QColor("#222"))
        op_format.setFontWeight(QFont.Bold)
        self._rules.append((op_pattern, op_format))
        # Number format
        number_format = QTextCharFormat()
        number_pattern = QRegExp(r"\b([A-Z0-9]+)(?:[ _-](\d+))?\b")
        number_pattern.setMinimal(True)
        number_format.setForeground(QColor("orange"))
        self._rules.append((number_pattern, number_format))

        # String format
        string_format = QTextCharFormat()
        string_pattern = QRegExp("\'.*\'")
        string_pattern.setMinimal(True)
        string_format.setForeground(Qt.darkGreen)
        self._rules.append((string_pattern, string_format))

        # Comment format
        comment_format = QTextCharFormat()
        comment_pattern = QRegExp("%[^\n]*")
        comment_format.setForeground(QColor("#999988"))
        comment_format.setFontItalic(True)
        self._rules.append((comment_pattern, comment_format))

        # Paren
        self.paren = QRegExp('\(|\)')

    def highlightBlock(self, text):
        """ Reimplementation """

        block_data = TextBlockData()
        # Paren
        index = self.paren.indexIn(text, 0)
        while index >= 0:
            matched_paren = str(self.paren.capturedTexts()[0])
            info = ParenInfo(matched_paren, index)
            block_data.insert_paren_info(info)
            index = self.paren.indexIn(text, index + 1)

        self.setCurrentBlockUserData(block_data)

        for pattern, _format in self._rules:
            expression = QRegExp(pattern)
            index = expression.indexIn(text)
            while index >= 0:
                length = expression.matchedLength()
                self.setFormat(index, length, _format)
                index = expression.indexIn(text, index + length)

        self.setCurrentBlockState(0)