コード例 #1
0
    def __init__(self,
                 fileName=None,
                 lineNumber=None,
                 condition="",
                 temporary=False,
                 enabled=True,
                 ignoreCount=0):
        if fileName is None:
            self.__fileName = fileName
        elif os.path.isabs(fileName):
            project = GlobalData().project
            if project.isLoaded():
                if project.isProjectFile(fileName):
                    # This is a project file; strip the project dir
                    self.__fileName = fileName.replace(project.getProjectDir(),
                                                       "")
                else:
                    # Not a project file, save as is
                    self.__fileName = fileName
            else:
                # Pretty much impossible
                self.__fileName = fileName
        else:
            # Relative path, i.e. a project file
            self.__fileName = fileName

        self.__lineNumber = lineNumber
        self.__condition = condition
        self.__temporary = temporary
        self.__enabled = enabled
        self.__ignoreCount = ignoreCount
コード例 #2
0
def getJediScript(source, line, column, srcPath, needSysPath=True):
    """Provides the jedi Script object considering the current project"""
    jedi.settings.additional_dynamic_modules = []
    paths = GlobalData().originalSysPath[:] if needSysPath else []

    # This make relative imports resolvable
    if os.path.isabs(srcPath):
        dirName = os.path.dirname(srcPath)
        if dirName not in paths:
            paths.append(dirName)

    project = GlobalData().project
    if not project.isLoaded():
        # Add the other opened files if so
        mainWindow = GlobalData().mainWindow
        for path in mainWindow.editorsManager().getOpenedList():
            if path[0]:
                if path[0].lower().endswith('.py'):
                    jedi.settings.additional_dynamic_modules.append(path[0])
        return jedi.Script(source, line, column, srcPath, sys_path=paths)

    for path in project.getImportDirsAsAbsolutePaths():
        if path not in paths:
            paths.append(path)
    projectDir = project.getProjectDir()
    if projectDir not in paths:
        paths.append(projectDir)

    return jedi.Script(source, line, column, srcPath, sys_path=paths)
コード例 #3
0
ファイル: bpointviewer.py プロジェクト: eaglexmw/codimension
    def __onProjectChanged( self, what ):
        " Triggered when a project is changed "
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        model = self.bpointsList.model().sourceModel()
        project = GlobalData().project
        if project.isLoaded():
            bpoints = project.breakpoints
        else:
            bpoints = Settings().breakpoints

        for bp in bpoints:
            newBpoint = Breakpoint()
            try:
                if not newBpoint.deserialize( bp ):
                    # Non valid
                    continue
            except:
                continue
            # Need to check if it still points to a breakable line
            line = newBpoint.getLineNumber()
            fileName = newBpoint.getAbsoluteFileName()
            breakableLines = getBreakpointLines( fileName, None, True )
            if breakableLines is not None and line in breakableLines:
                model.addBreakpoint( newBpoint )
            else:
                logging.warning( "Breakpoint at " + fileName + ":" +
                                 str( line ) + " does not point to a breakable "
                                 "line anymore (the file is invalid or was "
                                 "modified outside of the "
                                 "IDE etc.). The breakpoint is deleted." )
        return
コード例 #4
0
    def __init__(self,
                 scriptName,
                 params,
                 reportTime,
                 dataFile,
                 stats,
                 parent=None):
        QWidget.__init__(self, parent)

        self.__dataFile = dataFile
        self.__script = scriptName
        self.__reportTime = reportTime
        self.__params = params
        self.__stats = stats

        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname(project.fileName)
        else:
            self.__projectPrefix = os.path.dirname(scriptName)
        if not self.__projectPrefix.endswith(os.path.sep):
            self.__projectPrefix += os.path.sep

        self.__createLayout()
        self.__getDiagramLayout()

        self.__viewer.setScene(self.__scene)
コード例 #5
0
ファイル: notused.py プロジェクト: udpsunil/codimension
    def __init__(self, path, newSearch=True):
        QDialog.__init__(self, GlobalData().mainWindow)

        path = os.path.abspath(path)
        if not os.path.exists(path):
            raise Exception('Dead code analysis path must exist. '
                            'The provide path "' + path + '" does not.')

        self.__path = path

        self.__newSearch = newSearch
        self.candidates = None
        self.__cancelRequest = False
        self.__inProgress = False

        self.__infoLabel = None
        self.__foundLabel = None
        self.__found = 0  # Number of found

        self.__createLayout()
        title = 'Dead code analysis for '
        if os.path.isdir(path):
            project = GlobalData().project
            if project.isLoaded() and project.getProjectDir() == path:
                title += 'all project files'
            else:
                title += 'dir ' + os.path.basename(os.path.normpath(path))
        else:
            title += os.path.basename(path)

        if not self.__newSearch:
            title += ' (do again)'

        self.setWindowTitle(title)
        self.__updateFoundLabel()
コード例 #6
0
def getJediProject(force=False):
    """Provides a jedi project"""
    global jediProject

    if force or jediProject is None:
        project = GlobalData().project
        if project.isLoaded():
            jPath = project.getProjectDir()

            addedPaths = []
            for path in project.getImportDirsAsAbsolutePaths():
                if path not in addedPaths:
                    addedPaths.append(path)
            projectDir = project.getProjectDir()
            if projectDir not in addedPaths:
                addedPaths.append(projectDir)

        else:
            jPath = os.path.realpath(QDir.homePath())
            addedPaths = ()

        jediProject = Project(jPath,
                              sys_path=GlobalData().originalSysPath[:],
                              added_sys_path=addedPaths)

    return jediProject
コード例 #7
0
ファイル: bpointviewer.py プロジェクト: topin89/codimension
    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        model = self.bpointsList.model().sourceModel()
        project = GlobalData().project
        if project.isLoaded():
            bpoints = project.breakpoints
        else:
            bpoints = Settings().breakpoints

        for bpoint in bpoints:
            newBpoint = Breakpoint()
            try:
                if not newBpoint.deserialize(bpoint):
                    # Non valid
                    continue
            except:
                continue
            # Need to check if it still points to a breakable line
            line = newBpoint.getLineNumber()
            fileName = newBpoint.getAbsoluteFileName()
            breakableLines = getBreakpointLines(fileName, None, True)
            if breakableLines is not None and line in breakableLines:
                model.addBreakpoint(newBpoint)
            else:
                logging.warning("Breakpoint at " + fileName + ":" + str(line) +
                                " does not point to a breakable "
                                "line anymore (the file is invalid or was "
                                "modified outside of the "
                                "IDE etc.). The breakpoint is deleted.")
コード例 #8
0
ファイル: breakpoint.py プロジェクト: eaglexmw/codimension
    def __init__( self, fileName = None, lineNumber = None, condition = "",
                        temporary = False, enabled = True, ignoreCount = 0 ):

        if fileName is None:
            self.__fileName = fileName
        elif os.path.isabs( fileName ):
            project = GlobalData().project
            if project.isLoaded():
                if project.isProjectFile( fileName ):
                    # This is a project file; strip the project dir
                    self.__fileName = fileName.replace( project.getProjectDir(),
                                                        "" )
                else:
                    # Not a project file, save as is
                    self.__fileName = fileName
            else:
                # Pretty much impossible
                self.__fileName = fileName
        else:
            # Relative path, i.e. a project file
            self.__fileName = fileName

        self.__lineNumber = lineNumber
        self.__condition = condition
        self.__temporary = temporary
        self.__enabled = enabled
        self.__ignoreCount = ignoreCount

        return
コード例 #9
0
    def __onRemoveAllFromIgnore(self):
        """Triggered when all the ignored exceptions should be deleted"""
        self.clear()

        project = GlobalData().project
        if project.isLoaded():
            project.setExceptionFilters([])
        else:
            Settings().setExceptionFilters([])
コード例 #10
0
ファイル: bpointviewer.py プロジェクト: topin89/codimension
    def __serializeBreakpoints(self):
        """Saves the breakpoints into a file"""
        model = self.bpointsList.model().sourceModel()

        project = GlobalData().project
        if project.isLoaded():
            project.breakpoints = model.serialize()
        else:
            Settings().breakpoints = model.serialize()
コード例 #11
0
ファイル: bpointviewer.py プロジェクト: eaglexmw/codimension
    def __serializeBreakpoints( self ):
        " Saves the breakpoints into a file "
        model = self.bpointsList.model().sourceModel()

        project = GlobalData().project
        if project.isLoaded():
            project.setBreakpoints( model.serialize() )
        else:
            Settings().breakpoints = model.serialize()
        return
コード例 #12
0
    def __onRemoveAllFromIgnore( self ):
        " Triggered when all the ignored exceptions should be deleted "
        self.clear()

        project = GlobalData().project
        if project.isLoaded():
            project.setExceptionFilters( [] )
        else:
            Settings().setExceptionFilters( [] )
        return
コード例 #13
0
    def getAbsoluteFileName(self):
        """Provides the absolute file name"""
        if self.__fileName is None:
            return None
        if os.path.isabs(self.__fileName):
            return self.__fileName

        project = GlobalData().project
        if project.isLoaded():
            return project.getProjectDir() + self.__fileName
        return os.path.abspath(self.__fileName)
コード例 #14
0
ファイル: breakpoint.py プロジェクト: eaglexmw/codimension
    def getAbsoluteFileName( self ):
        " Provides the absolute file name "
        if self.__fileName is None:
            return None
        if os.path.isabs( self.__fileName ):
            return self.__fileName

        project = GlobalData().project
        if project.isLoaded():
            return project.getProjectDir() + self.__fileName
        return os.path.abspath( self.__fileName )
コード例 #15
0
    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what == CodimensionProject.CompleteProject:
            self.__contextItem = None
            self.__updateButtons()
            self.filterEdit.clear()

            project = GlobalData().project
            if project.isLoaded():
                self.filterEdit.editTextChanged.disconnect(
                    self.__filterChanged)
                self.filterEdit.addItems(project.findGlobalHistory)
                self.filterEdit.editTextChanged.connect(self.__filterChanged)
            self.filterEdit.clearEditText()
コード例 #16
0
    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        project = GlobalData().project
        if project.isLoaded():
            self.__ignored = list(project.exceptionFilters)
        else:
            self.__ignored = Settings()['ignoredExceptions']

        for exceptionType in self.__ignored:
            item = QTreeWidgetItem(self.exceptionsList)
            item.setText(0, exceptionType)
        self.__updateTitle()
コード例 #17
0
    def __onProjectChanged( self, what ):
        " Triggered when a project is changed "
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        project = GlobalData().project
        if project.isLoaded():
            self.__ignored = list( project.ignoredExcpt )
        else:
            self.__ignored = list( Settings().ignoredExceptions )

        for exceptionType in self.__ignored:
            item = QTreeWidgetItem( self.exceptionsList )
            item.setText( 0, exceptionType )
        self.__updateTitle()
        return
コード例 #18
0
    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what == CodimensionProject.CompleteProject:
            self.__contextItem = None
            self.__updateButtons()
            self.filterEdit.clear()

            project = GlobalData().project
            if project.isLoaded():
                self.filterEdit.editTextChanged.disconnect(
                    self.__filterChanged)
                self.filterEdit.addItems(project.findFunctionHistory)
                self.filterEdit.editTextChanged.connect(self.__filterChanged)
                self.findNotUsedButton.setEnabled(self.getItemCount() > 0)
            else:
                self.findNotUsedButton.setEnabled(False)
            self.filterEdit.clearEditText()
コード例 #19
0
ファイル: globalsviewer.py プロジェクト: eaglexmw/codimension
    def __onProjectChanged( self, what ):
        " Triggered when a project is changed "

        if what == CodimensionProject.CompleteProject:
            self.__contextItem = None
            self.__updateButtons()
            self.filterEdit.clear()

            project = GlobalData().project
            if project.isLoaded():
                self.filterEdit.editTextChanged.disconnect( self.__filterChanged )
                self.filterEdit.addItems( project.findGlobalHistory )
                self.filterEdit.editTextChanged.connect( self.__filterChanged )
                self.findNotUsedButton.setEnabled( self.getItemCount() > 0 )
            else:
                self.findNotUsedButton.setEnabled( False )
            self.filterEdit.clearEditText()
        return
コード例 #20
0
    def isValid(self):
        """True if the breakpoint is valid"""
        if self.__fileName is None:
            return False

        if os.path.isabs(self.__fileName):
            if not os.path.exists(self.__fileName):
                return False
        else:
            project = GlobalData().project
            if project.isLoaded():
                path = project.getProjectDir() + self.__fileName
                if not os.path.exists(path):
                    return False
            else:
                if not os.path.exists(self.__fileName):
                    return False

        return self.__lineNumber is not None and self.__lineNumber > 0
コード例 #21
0
    def addExceptionFilter(self, excType):
        """Adds a new item into the ignored exceptions list"""
        if excType == "":
            return
        if " " in excType:
            return
        if excType in self.__ignored:
            return

        item = QTreeWidgetItem(self.exceptionsList)
        item.setText(0, excType)

        project = GlobalData().project
        if project.isLoaded():
            project.addExceptionFilter(excType)
        else:
            Settings().addExceptionFilter(excType)
        self.__ignored.append(excType)
        self.__updateTitle()
コード例 #22
0
ファイル: breakpoint.py プロジェクト: eaglexmw/codimension
    def isValid( self ):
        " True if the breakpoint is valid "
        if self.__fileName is None:
            return False

        if os.path.isabs( self.__fileName ):
            if not os.path.exists( self.__fileName ):
                return False
        else:
            project = GlobalData().project
            if project.isLoaded():
                path = project.getProjectDir() + self.__fileName
                if not os.path.exists( path ):
                    return False
            else:
                if not os.path.exists( self.__fileName ):
                    return False

        return self.__lineNumber is not None and \
               self.__lineNumber > 0
コード例 #23
0
    def addExceptionFilter( self, excType ):
        " Adds a new item into the ignored exceptions list "
        if excType == "":
            return
        if " " in excType:
            return
        if excType in self.__ignored:
            return

        item = QTreeWidgetItem( self.exceptionsList )
        item.setText( 0, excType )

        project = GlobalData().project
        if project.isLoaded():
            project.addExceptionFilter( excType )
        else:
            Settings().addExceptionFilter( excType )
        self.__ignored.append( excType )
        self.__updateTitle()
        return
コード例 #24
0
    def __onRemoveFromIgnore(self):
        """Removes an item from the ignored exception types list"""
        if self.__currentItem is None:
            return

        text = self.__currentItem.text(0)

        # Find the item index and remove it
        index = 0
        while True:
            if self.exceptionsList.topLevelItem(index).text(0) == text:
                self.exceptionsList.takeTopLevelItem(index)
                break
            index += 1

        project = GlobalData().project
        if project.isLoaded():
            project.deleteExceptionFilter(text)
        else:
            Settings().deleteExceptionFilter(text)
        self.__ignored.remove(text)
        self.__updateTitle()
コード例 #25
0
    def __onRemoveFromIgnore( self ):
        " Removes an item from the ignored exception types list "
        if self.__currentItem is None:
            return

        text = self.__currentItem.text( 0 )

        # Find the item index and remove it
        index = 0
        while True:
            if self.exceptionsList.topLevelItem( index ).text( 0 ) == text:
                self.exceptionsList.takeTopLevelItem( index )
                break
            index += 1

        project = GlobalData().project
        if project.isLoaded():
            project.deleteExceptionFilter( text )
        else:
            Settings().deleteExceptionFilter( text )
        self.__ignored.remove( text )
        self.__updateTitle()
        return
コード例 #26
0
ファイル: profgraph.py プロジェクト: eaglexmw/codimension
    def __init__( self, scriptName, params, reportTime,
                        dataFile, stats, parent = None ):
        QWidget.__init__( self, parent )

        self.__dataFile = dataFile
        self.__script = scriptName
        self.__reportTime = reportTime
        self.__params = params
        self.__stats = stats

        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname( project.fileName )
        else:
            self.__projectPrefix = os.path.dirname( scriptName )
        if not self.__projectPrefix.endswith( os.path.sep ):
            self.__projectPrefix += os.path.sep

        self.__createLayout()
        self.__getDiagramLayout()

        self.__viewer.setScene( self.__scene )
        return
コード例 #27
0
 def __filterItemAdded(self):
     """The filter item has been added"""
     project = GlobalData().project
     if project.isLoaded():
         project.findGlobalHistory = self.filterEdit.getItems()
コード例 #28
0
ファイル: flowuiwidget.py プロジェクト: fukanchik/codimension
 def __getDefaultSaveDir( self ):
     " Provides the default directory to save files to "
     project = GlobalData().project
     if project.isLoaded():
         return project.getProjectDir()
     return QDir.currentPath()
コード例 #29
0
    def __selectFile(self, extension):
        """Picks a file of a certain extension"""
        dialog = QFileDialog(self, 'Save flowchart as')
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setLabelText(QFileDialog.Accept, "Save")
        dialog.setNameFilter(extension.upper() + " files (*." +
                             extension.lower() + ")")
        urls = []
        for dname in QDir.drives():
            urls.append(QUrl.fromLocalFile(dname.absoluteFilePath()))
        urls.append(QUrl.fromLocalFile(QDir.homePath()))
        project = GlobalData().project
        if project.isLoaded():
            urls.append(QUrl.fromLocalFile(project.getProjectDir()))
        dialog.setSidebarUrls(urls)

        suggestedFName = self.__parentWidget.getFileName()
        if '.' in suggestedFName:
            dotIndex = suggestedFName.rindex('.')
            suggestedFName = suggestedFName[:dotIndex]

        dialog.setDirectory(self.__getDefaultSaveDir())
        dialog.selectFile(suggestedFName + "." + extension.lower())
        dialog.setOption(QFileDialog.DontConfirmOverwrite, False)
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        if dialog.exec_() != QDialog.Accepted:
            return None

        fileNames = dialog.selectedFiles()
        fileName = os.path.abspath(str(fileNames[0]))
        if os.path.isdir(fileName):
            logging.error("A file must be selected")
            return None

        if "." not in fileName:
            fileName += "." + extension.lower()

        # Check permissions to write into the file or to a directory
        if os.path.exists(fileName):
            # Check write permissions for the file
            if not os.access(fileName, os.W_OK):
                logging.error("There is no write permissions for " + fileName)
                return None
        else:
            # Check write permissions to the directory
            dirName = os.path.dirname(fileName)
            if not os.access(dirName, os.W_OK):
                logging.error("There is no write permissions for the "
                              "directory " + dirName)
                return None

        if os.path.exists(fileName):
            res = QMessageBox.warning(
                self, "Save flowchart as",
                "<p>The file <b>" + fileName + "</b> already exists.</p>",
                QMessageBox.StandardButtons(QMessageBox.Abort |
                                            QMessageBox.Save),
                QMessageBox.Abort)
            if res == QMessageBox.Abort or res == QMessageBox.Cancel:
                return None

        # All prerequisites are checked, return a file name
        return fileName
コード例 #30
0
 def __getDefaultSaveDir():
     """Provides the default directory to save files to"""
     project = GlobalData().project
     if project.isLoaded():
         return project.getProjectDir()
     return QDir.currentPath()
コード例 #31
0
ファイル: flowuiwidget.py プロジェクト: fukanchik/codimension
    def __selectFile( self, extension ):
        " Picks a file of a certain extension "
        dialog = QFileDialog( self, 'Save flowchart as' )
        dialog.setFileMode( QFileDialog.AnyFile )
        dialog.setLabelText( QFileDialog.Accept, "Save" )
        dialog.setNameFilter( extension.upper() + " files (*." +
                              extension.lower() + ")" )
        urls = []
        for dname in QDir.drives():
            urls.append( QUrl.fromLocalFile( dname.absoluteFilePath() ) )
        urls.append( QUrl.fromLocalFile( QDir.homePath() ) )
        project = GlobalData().project
        if project.isLoaded():
            urls.append( QUrl.fromLocalFile( project.getProjectDir() ) )
        dialog.setSidebarUrls( urls )

        suggestedFName = self.__parentWidget.getFileName()
        if '.' in suggestedFName:
            dotIndex = suggestedFName.rindex( '.' )
            suggestedFName = suggestedFName[ : dotIndex ]

        dialog.setDirectory( self.__getDefaultSaveDir() )
        dialog.selectFile( suggestedFName + "." + extension.lower() )
        dialog.setOption( QFileDialog.DontConfirmOverwrite, False )
        if dialog.exec_() != QDialog.Accepted:
            return None

        fileNames = dialog.selectedFiles()
        fileName = os.path.abspath( str( fileNames[0] ) )
        if os.path.isdir( fileName ):
            logging.error( "A file must be selected" )
            return None

        if "." not in fileName:
            fileName += "." + extension.lower()

        # Check permissions to write into the file or to a directory
        if os.path.exists( fileName ):
            # Check write permissions for the file
            if not os.access( fileName, os.W_OK ):
                logging.error( "There is no write permissions for " + fileName )
                return None
        else:
            # Check write permissions to the directory
            dirName = os.path.dirname( fileName )
            if not os.access( dirName, os.W_OK ):
                logging.error( "There is no write permissions for the "
                               "directory " + dirName )
                return None

        if os.path.exists( fileName ):
            res = QMessageBox.warning( self, "Save flowchart as",
                    "<p>The file <b>" + fileName + "</b> already exists.</p>",
                    QMessageBox.StandardButtons( QMessageBox.Abort |
                                                 QMessageBox.Save ),
                    QMessageBox.Abort )
            if res == QMessageBox.Abort or res == QMessageBox.Cancel:
                return None

        # All prerequisites are checked, return a file name
        return fileName
コード例 #32
0
    def __init__( self, scriptName, params, reportTime,
                        dataFile, stats, parent = None ):
        QWidget.__init__( self, parent )

        self.__table = ProfilerTreeWidget( self )
        self.__table.escapePressed.connect( self.__onEsc )

        self.__script = scriptName
        self.__stats = stats
        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname( project.fileName )
        else:
            self.__projectPrefix = os.path.dirname( scriptName )
        if not self.__projectPrefix.endswith( os.path.sep ):
            self.__projectPrefix += os.path.sep

        self.__table.setAlternatingRowColors( True )
        self.__table.setRootIsDecorated( False )
        self.__table.setItemsExpandable( False )
        self.__table.setSortingEnabled( True )
        self.__table.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__table.setUniformRowHeights( True )
        self.__table.setSelectionMode( QAbstractItemView.SingleSelection )
        self.__table.setSelectionBehavior( QAbstractItemView.SelectRows )

        headerLabels = [ "", "Calls", "Total time", "Per call",
                         "Cum. time", "Per call", "File name:line",
                         "Function", "Callers", "Callees" ]
        self.__table.setHeaderLabels( headerLabels )

        headerItem = self.__table.headerItem()
        headerItem.setToolTip( 0, "Indication if it is an outside function" )
        headerItem.setToolTip( 1, "Actual number of calls/primitive calls "
                                  "(not induced via recursion)" )
        headerItem.setToolTip( 2, "Total time spent in function "
                                  "(excluding time made in calls "
                                  "to sub-functions)" )
        headerItem.setToolTip( 3, "Total time divided by number "
                                  "of actual calls" )
        headerItem.setToolTip( 4, "Total time spent in function and all "
                                  "subfunctions (from invocation till exit)" )
        headerItem.setToolTip( 5, "Cumulative time divided by number "
                                  "of primitive calls" )
        headerItem.setToolTip( 6, "Function location" )
        headerItem.setToolTip( 7, "Function name" )
        headerItem.setToolTip( 8, "Function callers" )
        headerItem.setToolTip( 9, "Function callees" )

        self.__table.itemActivated.connect( self.__activated )

        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + params.arguments + "<br>" \
              "<b>Run at:</b> " + reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel( txt )
        summary.setToolTip( txt )
        summary.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        summary.setFrameStyle( QFrame.StyledPanel )
        summary.setAutoFillBackground( True )
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color( QPalette.Background )
        summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ),
                                  min( summaryBackground.green() + 30, 255 ),
                                  min( summaryBackground.blue() + 30, 255 ) )
        summaryPalette.setColor( QPalette.Background, summaryBackground )
        summary.setPalette( summaryPalette )

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins( 0, 0, 0, 0 )
        vLayout.setSpacing( 0 )
        vLayout.addWidget( summary )
        vLayout.addWidget( self.__table )

        self.setLayout( vLayout )
        self.__createContextMenu()

        self.__populate( totalTime )
        return