Sat, 23 Dec 2023 18:14:27 +0100
Corrected some code style issues.
# -*- coding: utf-8 -*- # Copyright (c) 2014 - 2024 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the Selection Encloser plug-in. """ import contextlib import json import os from PyQt6.QtCore import QCoreApplication, QObject, QTranslator, pyqtSlot from PyQt6.QtGui import QAction from PyQt6.QtWidgets import QMenu from eric7 import Preferences from eric7.EricWidgets.EricApplication import ericApp # Start-Of-Header name = "Selection Encloser Plug-in" author = "Detlev Offenbach <detlev@die-offenbachs.de>" autoactivate = True deactivateable = True version = "10.1.0" className = "SelectionEncloserPlugin" packageName = "SelectionEncloser" shortDescription = "Enclose the selection with a string." longDescription = ( """This plug-in implements a tool to enclose the selection of""" """ the current editor with a string. The enclosing string is""" """ selectable via a configurable menu hierarchy.""" ) needsRestart = False pyqtApi = 2 # End-Of-Header error = "" selectionEncloserPluginObject = None def createSelectionEncloserPage(configDlg): # noqa: U100 """ Module function to create the Selection Encloser configuration page. @param configDlg reference to the configuration dialog @type ConfigurationWidget @return reference to the configuration page @rtype SelectionEncloserPage """ from SelectionEncloser.ConfigurationPage.SelectionEncloserPage import ( SelectionEncloserPage, ) global selectionEncloserPluginObject return SelectionEncloserPage(selectionEncloserPluginObject) def getConfigData(): """ Module function returning data as required by the configuration dialog. @return dictionary containing the relevant data @rtype dict """ usesDarkPalette = ericApp().usesDarkPalette() iconSuffix = "dark" if usesDarkPalette else "light" return { "selectionEncloserPage": [ QCoreApplication.translate("SelectionEncloserPlugin", "Selection Encloser"), os.path.join( "SelectionEncloser", "icons", "selectionEncloser-{0}".format(iconSuffix) ), createSelectionEncloserPage, None, None, ], } def prepareUninstall(): """ Module function to prepare for an uninstallation. """ Preferences.Prefs.settings.remove(SelectionEncloserPlugin.PreferencesKey) class SelectionEncloserPlugin(QObject): """ Class implementing the Selection Encloser plugin. """ PreferencesKey = "SelectionEncloser" def __init__(self, ui): """ Constructor @param ui reference to the user interface object @type UserInterface """ super().__init__(ui) self.__ui = ui # menu is a list of lists; each list consists of a string for the # submenu title and a list of submenu entries. Each submenu entry # consists of another list giving the title and the enclosing string # or formatting string. defaultMenu = [ [ self.tr("Quotes"), [['"', '"'], ["'", "'"], ['"""', '"""'], ["'''", "'''"]], ], [ self.tr("HTML"), [ ["<h1>", "<h1>{0}</h1>"], ["<h2>", "<h2>{0}</h2>"], ["<h3>", "<h3>{0}</h3>"], ["--Separator--", ""], ["<p>", "<p>{0}</p>"], ["<div>", "<div>{0}</div>"], ["<span>", "<span>{0}</span>"], ], ], ] self.__defaults = { "MenuHierarchy": json.dumps(defaultMenu), } self.__translator = None self.__loadTranslator() self.__initMenu() self.__editors = {} self.__mainActions = [] def activate(self): """ Public method to activate this plugin. @return tuple of None and activation status @rtype (None, bool) """ global error error = "" # clear previous error global selectionEncloserPluginObject selectionEncloserPluginObject = self self.__ui.showMenu.connect(self.__populateMenu) menu = self.__ui.getMenu("plugin_tools") if menu is not None: if not menu.isEmpty(): act = menu.addSeparator() self.__mainActions.append(act) act = menu.addMenu(self.__menu) self.__mainActions.append(act) ericApp().getObject("ViewManager").editorOpenedEd.connect(self.__editorOpened) ericApp().getObject("ViewManager").editorClosedEd.connect(self.__editorClosed) for editor in ericApp().getObject("ViewManager").getOpenEditors(): self.__editorOpened(editor) return None, True def deactivate(self): """ Public method to deactivate this plugin. """ self.__ui.showMenu.disconnect(self.__populateMenu) menu = self.__ui.getMenu("plugin_tools") if menu is not None: for act in self.__mainActions: menu.removeAction(act) self.__mainActions = [] ericApp().getObject("ViewManager").editorOpenedEd.disconnect( self.__editorOpened ) ericApp().getObject("ViewManager").editorClosedEd.disconnect( self.__editorClosed ) for editor, acts in self.__editors.items(): editor.showMenu.disconnect(self.__editorShowMenu) menu = editor.getMenu("Tools") if menu is not None: for act in acts: menu.removeAction(act) self.__editors = {} def __loadTranslator(self): """ Private method to load the translation file. """ if self.__ui is not None: loc = self.__ui.getLocale() if loc and loc != "C": locale_dir = os.path.join( os.path.dirname(__file__), "SelectionEncloser", "i18n" ) translation = "selectionencloser_{0}".format(loc) translator = QTranslator(None) loaded = translator.load(translation, locale_dir) if loaded: self.__translator = translator ericApp().installTranslator(self.__translator) else: print( "Warning: translation file '{0}' could not be" " loaded.".format(translation) ) print("Using default.") def getPreferences(self, key): """ Public method to retrieve the various settings. @param key key of the value to get @type str @return value of the requested setting @rtype Any """ if key in ["MenuHierarchy"]: return json.loads( Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) ) else: return Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) def setPreferences(self, key, value): """ Public method to store the various settings. @param key key of the setting to be set @type str @param value value to be set @type Any """ if key in ["MenuHierarchy"]: Preferences.Prefs.settings.setValue( self.PreferencesKey + "/" + key, json.dumps(value) ) else: Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value) def __initMenu(self): """ Private method to initialize the menu. """ self.__menu = QMenu("Enclose Selection") self.__menu.setEnabled(False) self.__menu.aboutToShow.connect(self.__showMenu) def __populateMenu(self, name, menu): """ Private slot to populate the tools menu with our entry. @param name name of the menu @type str @param menu reference to the menu to be populated @type QMenu """ if name not in ["Tools", "PluginTools"]: return editor = ericApp().getObject("ViewManager").activeWindow() if name == "Tools": if not menu.isEmpty(): menu.addSeparator() act = menu.addMenu(self.__menu) act.setEnabled(editor is not None and editor.hasSelectedText()) elif name == "PluginTools" and self.__mainActions: self.__menu.setEnabled(editor is not None and editor.hasSelectedText()) def __editorOpened(self, editor): """ Private slot called, when a new editor was opened. @param editor reference to the new editor @type Editor """ menu = editor.getMenu("Tools") if menu is not None: self.__editors[editor] = [] if not menu.isEmpty(): act = menu.addSeparator() self.__editors[editor].append(act) act = menu.addMenu(self.__menu) self.__menu.setEnabled(True) self.__editors[editor].append(act) editor.showMenu.connect(self.__editorShowMenu) def __editorClosed(self, editor): """ Private slot called, when an editor was closed. @param editor reference to the editor @type Editor """ with contextlib.suppress(KeyError): del self.__editors[editor] if not self.__editors: self.__menu.setEnabled(False) def __editorShowMenu(self, menuName, menu, editor): """ Private slot called, when the the editor context menu or a submenu is about to be shown. @param menuName name of the menu to be shown @type str @param menu reference to the menu @type QMenu @param editor reference to the editor @type Editor """ if menuName == "Tools": if self.__menu.menuAction() not in menu.actions(): # Re-add our menu self.__editors[editor] = [] if not menu.isEmpty(): act = menu.addSeparator() self.__editors[editor].append(act) act = menu.addMenu(self.__menu) self.__editors[editor].append(act) self.__menu.setEnabled(editor.selectedText() != "") def __showMenu(self): """ Private slot to build the menu hierarchy. """ self.__menu.clear() hierarchy = self.getPreferences("MenuHierarchy") for menuTitle, entries in hierarchy: if menuTitle == "--Separator--": self.__menu.addSeparator() else: submenu = QMenu(menuTitle, self.__menu) for title, encString in entries: if title == "--Separator--": submenu.addSeparator() else: act = submenu.addAction(title) act.setData(encString) submenu.triggered.connect(self.__encloseSelection) self.__menu.addMenu(submenu) @pyqtSlot(QAction) def __encloseSelection(self, act): """ Private slot to enclose the selection with the selected string. @param act action that triggered @type QAction """ if act is None: return editor = ericApp().getObject("ViewManager").activeWindow() if editor is None: return if not editor.hasSelectedText(): return encloseString = act.data() if not encloseString: return if "%s" in encloseString: newText = encloseString % editor.selectedText() elif "{0}" in encloseString or "{}" in encloseString: # __IGNORE_WARNING_M613__ newText = encloseString.format(editor.selectedText()) else: newText = encloseString + editor.selectedText() + encloseString editor.beginUndoAction() editor.replaceSelectedText(newText) editor.endUndoAction() # # eflag: noqa = M801, U200