def __createLayout( self ): " Helper to create the viewer layout " self.funcViewer = FunctionsBrowser() # Toolbar part - buttons self.definitionButton = QAction( PixmapCache().getIcon( 'definition.png' ), 'Jump to highlighted item definition', self ) self.definitionButton.triggered.connect( self.__goToDefinition ) self.findButton = QAction( PixmapCache().getIcon( 'findusage.png' ), 'Find highlighted item occurences', self ) self.findButton.triggered.connect( self.__findWhereUsed ) self.copyPathButton = QAction( PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self ) self.copyPathButton.triggered.connect( self.funcViewer.copyToClipboard ) self.findNotUsedButton = QAction( PixmapCache().getIcon( 'notused.png' ), 'Unused function analysis', self ) self.findNotUsedButton.triggered.connect( self.__findNotUsed ) self.findNotUsedButton.setEnabled( False ) self.toolbar = QToolBar( self ) self.toolbar.setMovable( False ) self.toolbar.setAllowedAreas( Qt.TopToolBarArea ) self.toolbar.setIconSize( QSize( 16, 16 ) ) self.toolbar.setFixedHeight( 28 ) self.toolbar.setContentsMargins( 0, 0, 0, 0 ) self.toolbar.addAction( self.definitionButton ) self.toolbar.addAction( self.findButton ) self.toolbar.addAction( self.copyPathButton ) filterLabel = QLabel( " Filter " ) self.toolbar.addWidget( filterLabel ) self.filterEdit = CDMComboBox( True, self.toolbar ) self.filterEdit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.filterEdit.lineEdit().setToolTip( "Space separated regular expressions" ) self.toolbar.addWidget( self.filterEdit ) self.toolbar.addAction( self.findNotUsedButton ) self.filterEdit.editTextChanged.connect( self.__filterChanged ) self.filterEdit.itemAdded.connect( self.__filterItemAdded ) self.filterEdit.enterClicked.connect( self.__enterInFilter ) layout = QVBoxLayout() layout.setContentsMargins( 0, 0, 0, 0 ) layout.setSpacing( 0 ) layout.addWidget( self.toolbar ) layout.addWidget( self.funcViewer ) self.setLayout( layout ) return
class FunctionsViewer( QWidget ): """ The free functions (including nested) viewer widget """ def __init__( self, parent = None ): QWidget.__init__( self, parent ) self.filterEdit = None self.definitionButton = None self.findButton = None self.copyPathButton = None self.funcViewer = None self.__createLayout() # create the context menu self.__menu = QMenu( self ) self.__jumpMenuItem = self.__menu.addAction( PixmapCache().getIcon( 'definition.png' ), 'Jump to definition', self.__goToDefinition ) self.__menu.addSeparator() self.__findMenuItem = self.__menu.addAction( PixmapCache().getIcon( 'findusage.png' ), 'Find occurences', self.__findWhereUsed ) self.__menu.addSeparator() self.__disasmMenuItem = self.__menu.addAction( PixmapCache().getIcon( 'disasmmenu.png' ), 'Disassemble', self.__onDisassemble ) self.__menu.addSeparator() self.__copyMenuItem = self.__menu.addAction( PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self.funcViewer.copyToClipboard ) self.funcViewer.setContextMenuPolicy( Qt.CustomContextMenu ) self.funcViewer.customContextMenuRequested.connect( self.__handleShowContextMenu ) GlobalData().project.projectChanged.connect( self.__onProjectChanged ) self.connect( self.funcViewer, SIGNAL( "selectionChanged" ), self.__selectionChanged ) self.funcViewer.openingItem.connect( self.itemActivated ) self.connect( self.funcViewer, SIGNAL( "modelFilesChanged" ), self.modelFilesChanged ) self.filterEdit.lineEdit().setFocus() self.__contextItem = None return def setTooltips( self, switchOn ): " Triggers showing python objects tooltips " self.funcViewer.model().sourceModel().setTooltips( switchOn ) return def __createLayout( self ): " Helper to create the viewer layout " self.funcViewer = FunctionsBrowser() # Toolbar part - buttons self.definitionButton = QAction( PixmapCache().getIcon( 'definition.png' ), 'Jump to highlighted item definition', self ) self.definitionButton.triggered.connect( self.__goToDefinition ) self.findButton = QAction( PixmapCache().getIcon( 'findusage.png' ), 'Find highlighted item occurences', self ) self.findButton.triggered.connect( self.__findWhereUsed ) self.copyPathButton = QAction( PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self ) self.copyPathButton.triggered.connect( self.funcViewer.copyToClipboard ) self.findNotUsedButton = QAction( PixmapCache().getIcon( 'notused.png' ), 'Unused function analysis', self ) self.findNotUsedButton.triggered.connect( self.__findNotUsed ) self.findNotUsedButton.setEnabled( False ) self.toolbar = QToolBar( self ) self.toolbar.setMovable( False ) self.toolbar.setAllowedAreas( Qt.TopToolBarArea ) self.toolbar.setIconSize( QSize( 16, 16 ) ) self.toolbar.setFixedHeight( 28 ) self.toolbar.setContentsMargins( 0, 0, 0, 0 ) self.toolbar.addAction( self.definitionButton ) self.toolbar.addAction( self.findButton ) self.toolbar.addAction( self.copyPathButton ) filterLabel = QLabel( " Filter " ) self.toolbar.addWidget( filterLabel ) self.filterEdit = CDMComboBox( True, self.toolbar ) self.filterEdit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.filterEdit.lineEdit().setToolTip( "Space separated regular expressions" ) self.toolbar.addWidget( self.filterEdit ) self.toolbar.addAction( self.findNotUsedButton ) self.filterEdit.editTextChanged.connect( self.__filterChanged ) self.filterEdit.itemAdded.connect( self.__filterItemAdded ) self.filterEdit.enterClicked.connect( self.__enterInFilter ) layout = QVBoxLayout() layout.setContentsMargins( 0, 0, 0, 0 ) layout.setSpacing( 0 ) layout.addWidget( self.toolbar ) layout.addWidget( self.funcViewer ) self.setLayout( layout ) return def __filterChanged( self, text ): " Triggers when the filter text changed " self.funcViewer.setFilter( text ) self.funcViewer.updateCounter() return def __selectionChanged( self, index ): " Handles the changed selection " if index is None: self.__contextItem = None else: self.__contextItem = self.funcViewer.model().item( index ) self.__updateButtons() return def getItemCount( self ): " Provides the number of items in the model - total, not only visible " return self.funcViewer.model().sourceModel().rowCount() def itemActivated( self, path, line ): " Handles the item activation " self.filterEdit.addItem( self.filterEdit.lineEdit().text() ) return def __filterItemAdded( self ): " The filter item has been added " project = GlobalData().project if project.fileName != "": project.setFindFuncHistory( self.filterEdit.getItems() ) return def __enterInFilter( self ): " ENTER key has been clicked in the filter " # check if there any records displayed if self.funcViewer.model().rowCount() == 0: return # Move the focus to the list and select the first row self.funcViewer.clearSelection() flags = QItemSelectionModel.SelectCurrent | QItemSelectionModel.Rows self.funcViewer.setSelection( QRect( 0, 0, self.funcViewer.width(), 1 ), flags ) self.funcViewer.setFocus() return 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.findFuncHistory ) self.filterEdit.editTextChanged.connect( self.__filterChanged ) self.findNotUsedButton.setEnabled( self.getItemCount() > 0 ) else: self.findNotUsedButton.setEnabled( False ) self.filterEdit.clearEditText() return def __handleShowContextMenu( self, coord ): """ Show the context menu """ index = self.funcViewer.indexAt( coord ) if not index.isValid(): return # This will update the __contextItem self.__selectionChanged( index ) if self.__contextItem is None: return self.__jumpMenuItem.setEnabled( self.definitionButton.isEnabled() ) self.__findMenuItem.setEnabled( self.findButton.isEnabled() ) self.__copyMenuItem.setEnabled( self.copyPathButton.isEnabled() ) canDisassemble = self.__contextItem.canGetDisassembler() self.__disasmMenuItem.setEnabled( canDisassemble ) self.__menu.popup( QCursor.pos() ) return def __goToDefinition( self ): " Jump to definition context menu handler " if self.__contextItem is not None: self.funcViewer.openItem( self.__contextItem ) return def __findWhereUsed( self ): """ Find where used context menu handler """ if self.__contextItem is not None: GlobalData().mainWindow.findWhereUsed( \ self.__contextItem.getPath(), self.__contextItem.sourceObj ) return def __findNotUsed( self ): " Runs the unused function analysis " GlobalData().mainWindow.onNotUsedFunctions() return def __updateButtons( self ): " Updates the toolbar buttons depending on what is selected " self.definitionButton.setEnabled( False ) self.findButton.setEnabled( False ) self.copyPathButton.setEnabled( False ) if self.__contextItem is None: return if self.__contextItem.itemType == DecoratorItemType: self.definitionButton.setEnabled( True ) self.copyPathButton.setEnabled( True ) return if self.__contextItem.itemType in [ FunctionItemType, ClassItemType, AttributeItemType, GlobalItemType ]: self.definitionButton.setEnabled( True ) self.findButton.setEnabled( True ) self.copyPathButton.setEnabled( True ) return def onFileUpdated( self, fileName, uuid ): " Triggered when the file is updated " self.funcViewer.onFileUpdated( fileName ) self.findNotUsedButton.setEnabled( GlobalData().project.isLoaded() and \ self.getItemCount() > 0 ) return def modelFilesChanged( self ): " Triggered when the source model has a file or files added or deleted " self.findNotUsedButton.setEnabled( GlobalData().project.isLoaded() and \ self.getItemCount() > 0 ) return def __onDisassemble( self ): " Disassembling has been requested " if self.__contextItem is not None: self.funcViewer.getDisassembled( self.__contextItem )