Sun, 15 Oct 2017 19:40:26 +0200
Continued implementing a viewer for source code documentation extracted by providers to be implemented by plug-ins (like rope and jedi).
# -*- coding: utf-8 -*- # Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a widget to show some source code information provided by plug-ins. """ from __future__ import unicode_literals from PyQt5.QtCore import pyqtSlot, pyqtSignal from PyQt5.QtWidgets import QWidget from .Ui_CodeDocumentationViewer import Ui_CodeDocumentationViewer import Preferences class CodeDocumentationViewer(QWidget, Ui_CodeDocumentationViewer): """ Class implementing a widget to show some source code information provided by plug-ins. """ providerAdded = pyqtSignal() def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget @type QWidget """ super(CodeDocumentationViewer, self).__init__(parent) self.setupUi(self) self.searchWidget.attachTextEdit(self.contents) self.__ui = parent self.__providers = {} self.__selectedProvider = "" self.__disabledProvider = "disabled" self.__shuttingDown = False self.__startingUp = True self.__lastDocumentation = None self.__showMarkdown = Preferences.getDocuViewer("ShowInfoAsMarkdown") self.__noDocumentationString = self.tr("No documentation available") self.__disabledString = self.tr( "No source code documentation provider has been registered or" " this function has been disabled.") self.providerComboBox.addItem(self.tr("<disabled>"), "disabled") font = Preferences.getEditorOtherFonts("MonospacedFont") self.contents.setFontFamily(font.family()) self.contents.setFontPointSize(font.pointSize()) def finalizeSetup(self): """ Public method to finalize the setup of the documentation viewer. """ self.__startingUp = False provider = Preferences.getDocuViewer("Provider") if provider in self.__providers: index = self.providerComboBox.findData(provider) else: index = 0 self.providerComboBox.setCurrentIndex(index) # TODO: document this hook in the plug-in document def registerProvider(self, providerName, providerDisplay, provider): """ Public method register a source docu provider. @param providerName name of the provider (must be unique) @type str @param providerDisplay visible name of the provider @type str @param provider function to be called to determine source docu @type function @exception KeyError raised if a provider with the given name was already registered """ if providerName in self.__providers: raise KeyError( "Provider '{0}' already registered.".format(providerName)) self.__providers[providerName] = provider self.providerComboBox.addItem(providerDisplay, providerName) # TODO: document this hook in the plug-in document def unregisterProvider(self, providerName): """ Public method register a source docu provider. @param providerName name of the provider (must be unique) @type str """ if providerName in self.__providers: if providerName == self.__selectedProvider: self.providerComboBox.setCurrentIndex(0) del self.__providers[providerName] index = self.providerComboBox.findData(providerName) self.providerComboBox.removeItem(index) def showInfo(self, editor): """ Public method to request code documentation data from a provider. @param editor reference to the editor to request code docu for @type Editor """ line, index = editor.getCursorPosition() word = editor.getWord(line, index) if not word: # try again one index before word = editor.getWord(line, index - 1) self.objectLineEdit.setText(word) if self.__selectedProvider != self.__disabledProvider: self.contents.clear() self.__providers[self.__selectedProvider](editor) # TODO: document this hook in the plug-in document def documentationReady(self, documentationInfo): """ Public method to provide the documentation info to the viewer. If documentationInfo is a dictionary, it should contains these keys and data: name: the name of the inspected object argspec: its argspec note: A phrase describing the type of object (function or method) and the module it belongs to. docstring: its documentation string @param documentationInfo dictionary containing the source docu data @type dict or str """ self.__ui.activateCodeDocumentationViewer(switchFocus=False) self.__lastDocumentation = documentationInfo if not documentationInfo: fullText = self.__noDocumentationString elif isinstance(documentationInfo, str): fullText = documentationInfo elif isinstance(documentationInfo, dict): # format the text with markdown syntax name = documentationInfo["name"] if name: title = "".join([name, "\n", "=" * len(name), "\n\n"]) else: title = "" if documentationInfo["argspec"]: if self.__showMarkdown: definition = self.tr("**Definition**: {0}{1}\n", "string with markdown syntax").format( name, documentationInfo["argspec"]) else: definition = self.tr("Definition: {0}{1}\n", "string as plain text").format( name, documentationInfo["argspec"]) else: definition = '' if documentationInfo["note"]: if self.__showMarkdown: note = self.tr("**Info**: _{0}_\n\n----\n\n", "string with markdown syntax").format( documentationInfo["note"]) else: note = self.tr("Info: {0}\n\n----\n\n", "string as plain text").format( documentationInfo["note"]) else: note = "" fullText = "".join([title, definition, note, documentationInfo['docstring']]) self.contents.setPlainText(fullText) @pyqtSlot(int) def on_providerComboBox_currentIndexChanged(self, index): """ Private slot to handle the selection of a provider. @param index index of the selected provider @type int """ if not self.__shuttingDown and not self.__startingUp: provider = self.providerComboBox.itemData(index) if provider == self.__disabledProvider: self.documentationReady(self.__disabledString) elif provider in self.__providers: Preferences.setDocuViewer("Provider", provider) self.__selectedProvider = provider def shutdown(self): """ Public method to perform shutdown actions. """ self.__shuttingDown = True Preferences.setDocuViewer("Provider", self.__selectedProvider) def preferencesChanged(self): """ Public slot to handle a change of preferences. """ showMarkdown = Preferences.getDocuViewer("ShowInfoAsMarkdown") if showMarkdown != self.__showMarkdown: self.__showMarkdown = showMarkdown self.documentationReady(self.__lastDocumentation) provider = Preferences.getDocuViewer("Provider") if provider != self.__selectedProvider: index = self.providerComboBox.findData(provider) if index < 0: index = 0 self.providerComboBox.setCurrentIndex(index) font = Preferences.getEditorOtherFonts("MonospacedFont") self.contents.setFontFamily(font.family()) self.contents.setFontPointSize(font.pointSize())