class PluginsDialog( QDialog ): " Codimension plugins dialog " def __init__( self, pluginManager, parent = None ): QDialog.__init__( self, parent ) self.setWindowTitle( "Plugin Manager" ) self.__pluginManager = pluginManager self.__configFuncs = {} # int -> callable self.__createLayout() self.__populate() self.__pluginsView.setFocus() self.__inItemChange = False return def __createLayout( self ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors( True ) self.__pluginsView.setRootIsDecorated( False ) self.__pluginsView.setItemsExpandable( False ) self.__pluginsView.setSortingEnabled( True ) self.__pluginsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__pluginsView.setUniformRowHeights( True ) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( [ "", "", "", "Name", "Version", "" ] ) self.__pluginsView.setHeaderItem( self.__pluginsHeader ) self.__pluginsView.header().setSortIndicator( NAME_COL, Qt.AscendingOrder ) self.connect( self.__pluginsView, SIGNAL( "itemSelectionChanged()" ), self.__pluginSelectionChanged ) self.connect( self.__pluginsView, SIGNAL( "itemChanged(QTreeWidgetItem*,int)" ), self.__onItemChanged ) layout.addWidget( self.__pluginsView ) # Detailed information detailsLabel = QLabel( "Detailed information" ) layout.addWidget( detailsLabel ) self.__details = QTreeWidget() self.__details.setAlternatingRowColors( False ) self.__details.setRootIsDecorated( False ) self.__details.setItemsExpandable( False ) self.__details.setSortingEnabled( False ) self.__details.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__details.setUniformRowHeights( True ) detailsHeader = QTreeWidgetItem( [ "", "" ] ) self.__details.setHeaderItem( detailsHeader ) self.__details.setHeaderHidden( True ) metrics = QFontMetrics( self.__details.font() ) rect = metrics.boundingRect( "X" ) self.__details.setFixedHeight( rect.height() * 6 + 5 ) layout.addWidget( self.__details ) # Errors/warnings errorsLabel = QLabel( "Errors / warnings" ) layout.addWidget( errorsLabel ) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly( True ) self.__errorsText.setAcceptRichText( False ) metrics = QFontMetrics( self.__errorsText.font() ) rect = metrics.boundingRect( "X" ) self.__errorsText.setFixedHeight( rect.height() * 4 + 5 ) layout.addWidget( self.__errorsText ) # Buttons box buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok ) self.__OKButton = buttonBox.button( QDialogButtonBox.Ok ) self.__OKButton.setDefault( True ) self.connect( buttonBox, SIGNAL( "accepted()" ), self.close ) self.connect( buttonBox, SIGNAL( "rejected()" ), self.close ) layout.addWidget( buttonBox ) self.setLayout( layout ) return def __createConfigButton( self ): " Creates a configure button for a plugin " button = SettingsButton() self.connect( button, SIGNAL( 'CustomClick' ), self.onPluginSettings ) return button def __populate( self ): " Populates the list with the plugins " index = 0 for category in self.__pluginManager.activePlugins: for cdmPlugin in self.__pluginManager.activePlugins[ category ]: newItem = PluginItem( self.__pluginManager, cdmPlugin, True, category ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring" ) settingsButton.setEnabled( False ) else: settingsButton.setToolTip( "Click to configure" ) settingsButton.setEnabled( True ) self.__configFuncs[ index ] = configFunction settingsButton.index = index index += 1 except Exception: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received." ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) for category in self.__pluginManager.inactivePlugins: for cdmPlugin in self.__pluginManager.inactivePlugins[ category ]: newItem = PluginItem( self.__pluginManager, cdmPlugin, False, category ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring" ) settingsButton.setEnabled( False ) else: settingsButton.setToolTip( "Enable plugin and then click to configure" ) settingsButton.setEnabled( False ) self.__configFuncs[ index ] = configFunction settingsButton.index = index index += 1 except: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received." ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) for cdmPlugin in self.__pluginManager.unknownPlugins: newItem = PluginItem( self.__pluginManager, cdmPlugin, False, None ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() settingsButton.setToolTip( "Unknown plugins are not configurable" ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) self.__sortPlugins() self.__resizePlugins() return def __sortPlugins( self ): " Sorts the plugins table " self.__pluginsView.sortItems( self.__pluginsView.sortColumn(), self.__pluginsView.header().sortIndicatorOrder() ) return def __resizePlugins( self ): " Resizes the plugins table " self.__pluginsView.header().setStretchLastSection( False ) self.__pluginsView.header().resizeSections( QHeaderView.ResizeToContents ) self.__pluginsView.header().resizeSection( STATE_COL, 28 ) self.__pluginsView.header().setResizeMode( STATE_COL, QHeaderView.Fixed ) self.__pluginsView.header().resizeSection( CONFLICT_COL, 28 ) self.__pluginsView.header().setResizeMode( CONFLICT_COL, QHeaderView.Fixed ) self.__pluginsView.header().resizeSection( TYPE_COL, 28 ) self.__pluginsView.header().setResizeMode( TYPE_COL, QHeaderView.Fixed ) self.__pluginsView.header().setResizeMode( VERSION_COL, QHeaderView.Stretch ) self.__pluginsView.header().resizeSection( SETTINGS_COL, 24 ) self.__pluginsView.header().setResizeMode( SETTINGS_COL, QHeaderView.Fixed ) return def __pluginSelectionChanged( self ): " Triggered when an item is selected " selected = list( self.__pluginsView.selectedItems() ) if selected: self.__updateDetails( selected[ 0 ] ) else: self.__updateDetails( None ) return def __updateDetails( self, item ): " Updates the content of the details and the error boxes " self.__details.clear() self.__errorsText.setText( "" ) if item is None: return self.__details.addTopLevelItem( QTreeWidgetItem( [ "Author", item.plugin.getAuthor() ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Path", os.path.normpath( item.plugin.getPath() ) ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Description", item.plugin.getDescription() ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Web site", item.plugin.getWebsite() ] ) ) copyright = item.plugin.getCopyright() if copyright is not None: if copyright.lower() != "unknown": self.__details.addTopLevelItem( QTreeWidgetItem( [ "Copyright", copyright ] ) ) for name in item.plugin.getDetails(): value = item.plugin.getDetails()[ name ] self.__details.addTopLevelItem( QTreeWidgetItem( [ name, value ] ) ) self.__errorsText.setText( item.plugin.conflictMessage ) return def __onItemChanged( self, item, column ): " Triggered when an item is changed " if self.__inItemChange: return if item.active: self.__inItemChange = True item.plugin.disable() item.active = False settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL ) settingsButton.setEnabled( False ) if settingsButton.index != -1: settingsButton.setToolTip( "Enable plugin and then click to configure" ) if item.category in self.__pluginManager.inactivePlugins: self.__pluginManager.inactivePlugins[ item.category ].append( item.plugin ) else: self.__pluginManager.inactivePlugins[ item.category ] = [ item.plugin ] self.__pluginManager.activePlugins[ item.category ].remove( item.plugin ) self.__pluginManager.saveDisabledPlugins() self.__inItemChange = False self.__pluginManager.sendPluginDeactivated( item.plugin ) return self.__inItemChange = True message = self.__pluginManager.checkConflict( item.plugin ) if message is not None: item.setCheckState( STATE_COL, Qt.Unchecked ) self.__errorsText.setText( message ) self.__inItemChange = False return try: item.plugin.enable() item.active = True if item.category in self.__pluginManager.activePlugins: self.__pluginManager.activePlugins[ item.category ].append( item.plugin ) else: self.__pluginManager.activePlugins[ item.category ] = [ item.plugin ] self.__pluginManager.inactivePlugins[ item.category ].remove( item.plugin ) self.__pluginManager.saveDisabledPlugins() self.__errorsText.setText( "" ) item.setIcon( CONFLICT_COL, PixmapCache().getIcon( 'empty.png' ) ) item.setToolTip( CONFLICT_COL, "" ) settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL ) if settingsButton.index != -1: settingsButton.setToolTip( "Click to configure" ) settingsButton.setEnabled( True ) self.__pluginManager.sendPluginActivated( item.plugin ) except: item.setCheckState( STATE_COL, Qt.Unchecked ) self.__errorsText.setText( "Error activating the plugin - exception is generated" ) self.__inItemChange = False return def onPluginSettings( self, index ): " Triggered when a configuring function is called " if index not in self.__configFuncs: return try: self.__configFuncs[ index ]() except Exception, exc: logging.error( "Error calling the plugin configuration function. " "Message: " + str( exc ) ) return
class PluginsDialog(QDialog): " Codimension plugins dialog " def __init__(self, pluginManager, parent=None): QDialog.__init__(self, parent) self.setWindowTitle("Plugin Manager") self.__pluginManager = pluginManager self.__configFuncs = {} # int -> callable self.__createLayout() self.__populate() self.__pluginsView.setFocus() self.__inItemChange = False return def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors(True) self.__pluginsView.setRootIsDecorated(False) self.__pluginsView.setItemsExpandable(False) self.__pluginsView.setSortingEnabled(True) self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__pluginsView.setUniformRowHeights(True) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( ["", "", "", "Name", "Version", ""]) self.__pluginsView.setHeaderItem(self.__pluginsHeader) self.__pluginsView.header().setSortIndicator(NAME_COL, Qt.AscendingOrder) self.connect(self.__pluginsView, SIGNAL("itemSelectionChanged()"), self.__pluginSelectionChanged) self.connect(self.__pluginsView, SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.__onItemChanged) layout.addWidget(self.__pluginsView) # Detailed information detailsLabel = QLabel("Detailed information") layout.addWidget(detailsLabel) self.__details = QTreeWidget() self.__details.setAlternatingRowColors(False) self.__details.setRootIsDecorated(False) self.__details.setItemsExpandable(False) self.__details.setSortingEnabled(False) self.__details.setItemDelegate(NoOutlineHeightDelegate(4)) self.__details.setUniformRowHeights(True) detailsHeader = QTreeWidgetItem(["", ""]) self.__details.setHeaderItem(detailsHeader) self.__details.setHeaderHidden(True) metrics = QFontMetrics(self.__details.font()) rect = metrics.boundingRect("X") self.__details.setFixedHeight(rect.height() * 6 + 5) layout.addWidget(self.__details) # Errors/warnings errorsLabel = QLabel("Errors / warnings") layout.addWidget(errorsLabel) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly(True) self.__errorsText.setAcceptRichText(False) metrics = QFontMetrics(self.__errorsText.font()) rect = metrics.boundingRect("X") self.__errorsText.setFixedHeight(rect.height() * 4 + 5) layout.addWidget(self.__errorsText) # Buttons box buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setDefault(True) self.connect(buttonBox, SIGNAL("accepted()"), self.close) self.connect(buttonBox, SIGNAL("rejected()"), self.close) layout.addWidget(buttonBox) self.setLayout(layout) return def __createConfigButton(self): " Creates a configure button for a plugin " button = SettingsButton() self.connect(button, SIGNAL('CustomClick'), self.onPluginSettings) return button def __populate(self): " Populates the list with the plugins " index = 0 for category in self.__pluginManager.activePlugins: for cdmPlugin in self.__pluginManager.activePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, True, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except Exception: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for category in self.__pluginManager.inactivePlugins: for cdmPlugin in self.__pluginManager.inactivePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip( "Enable plugin and then click to configure") settingsButton.setEnabled(False) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for cdmPlugin in self.__pluginManager.unknownPlugins: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, None) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() settingsButton.setToolTip("Unknown plugins are not configurable") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) self.__sortPlugins() self.__resizePlugins() return def __sortPlugins(self): " Sorts the plugins table " self.__pluginsView.sortItems( self.__pluginsView.sortColumn(), self.__pluginsView.header().sortIndicatorOrder()) return def __resizePlugins(self): " Resizes the plugins table " self.__pluginsView.header().setStretchLastSection(False) self.__pluginsView.header().resizeSections( QHeaderView.ResizeToContents) self.__pluginsView.header().resizeSection(STATE_COL, 28) self.__pluginsView.header().setResizeMode(STATE_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(CONFLICT_COL, 28) self.__pluginsView.header().setResizeMode(CONFLICT_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(TYPE_COL, 28) self.__pluginsView.header().setResizeMode(TYPE_COL, QHeaderView.Fixed) self.__pluginsView.header().setResizeMode(VERSION_COL, QHeaderView.Stretch) self.__pluginsView.header().resizeSection(SETTINGS_COL, 24) self.__pluginsView.header().setResizeMode(SETTINGS_COL, QHeaderView.Fixed) return def __pluginSelectionChanged(self): " Triggered when an item is selected " selected = list(self.__pluginsView.selectedItems()) if selected: self.__updateDetails(selected[0]) else: self.__updateDetails(None) return def __updateDetails(self, item): " Updates the content of the details and the error boxes " self.__details.clear() self.__errorsText.setText("") if item is None: return self.__details.addTopLevelItem( QTreeWidgetItem(["Author", item.plugin.getAuthor()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Path", os.path.normpath(item.plugin.getPath())])) self.__details.addTopLevelItem( QTreeWidgetItem(["Description", item.plugin.getDescription()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Web site", item.plugin.getWebsite()])) copyright = item.plugin.getCopyright() if copyright is not None: if copyright.lower() != "unknown": self.__details.addTopLevelItem( QTreeWidgetItem(["Copyright", copyright])) for name in item.plugin.getDetails(): value = item.plugin.getDetails()[name] self.__details.addTopLevelItem(QTreeWidgetItem([name, value])) self.__errorsText.setText(item.plugin.conflictMessage) return def __onItemChanged(self, item, column): " Triggered when an item is changed " if self.__inItemChange: return if item.active: self.__inItemChange = True item.plugin.disable() item.active = False settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) settingsButton.setEnabled(False) if settingsButton.index != -1: settingsButton.setToolTip( "Enable plugin and then click to configure") if item.category in self.__pluginManager.inactivePlugins: self.__pluginManager.inactivePlugins[item.category].append( item.plugin) else: self.__pluginManager.inactivePlugins[item.category] = [ item.plugin ] self.__pluginManager.activePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__inItemChange = False self.__pluginManager.sendPluginDeactivated(item.plugin) return self.__inItemChange = True message = self.__pluginManager.checkConflict(item.plugin) if message is not None: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText(message) self.__inItemChange = False return try: item.plugin.enable() item.active = True if item.category in self.__pluginManager.activePlugins: self.__pluginManager.activePlugins[item.category].append( item.plugin) else: self.__pluginManager.activePlugins[item.category] = [ item.plugin ] self.__pluginManager.inactivePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__errorsText.setText("") item.setIcon(CONFLICT_COL, PixmapCache().getIcon('empty.png')) item.setToolTip(CONFLICT_COL, "") settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) if settingsButton.index != -1: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__pluginManager.sendPluginActivated(item.plugin) except: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText( "Error activating the plugin - exception is generated") self.__inItemChange = False return def onPluginSettings(self, index): " Triggered when a configuring function is called " if index not in self.__configFuncs: return try: self.__configFuncs[index]() except Exception, exc: logging.error("Error calling the plugin configuration function. " "Message: " + str(exc)) return