PluginSelectionEncloser.py

changeset 1
a9f6842a18f6
parent 0
96fac1d8181f
child 3
b26df0282953
diff -r 96fac1d8181f -r a9f6842a18f6 PluginSelectionEncloser.py
--- a/PluginSelectionEncloser.py	Fri Apr 18 16:15:44 2014 +0200
+++ b/PluginSelectionEncloser.py	Fri Apr 18 19:45:32 2014 +0200
@@ -0,0 +1,313 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the Selection Encloser plug-in.
+"""
+
+from __future__ import unicode_literals    # __IGNORE_WARNING__
+
+import os
+import json
+
+from PyQt4.QtCore import QObject, QTranslator, QCoreApplication
+from PyQt4.QtGui import QAction, QMenu
+
+from E5Gui.E5Application import e5App
+
+import Preferences
+
+# Start-Of-Header
+name = "Selection Encloser Plug-in"
+author = "Detlev Offenbach <detlev@die-offenbachs.de>"
+autoactivate = True
+deactivateable = True
+version = "0.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
+python2Compatible = True
+# End-Of-Header
+
+error = ""
+
+selectionEncloserPluginObject = None
+    
+
+def createSelectionEncloserPage(configDlg):
+    """
+    Module function to create the Selection Encloser configuration page.
+    
+    @param configDlg reference to the configuration dialog
+    @return reference to the configuration page
+    """
+    global selectionEncloserPluginObject
+    from SelectionEncloser.ConfigurationPage.SelectionEncloserPage import \
+        SelectionEncloserPage
+    page = SelectionEncloserPage(selectionEncloserPluginObject)
+    return page
+    
+
+def getConfigData():
+    """
+    Module function returning data as required by the configuration dialog.
+    
+    @return dictionary containing the relevant data
+    """
+    if e5App().getObject("UserInterface").versionIsNewer('5.2.99', '20121012'):
+        return {
+            "selectionEncloserPage": [
+                QCoreApplication.translate("SelectionEncloserPlugin",
+                                           "Selection Encloser"),
+                os.path.join("SelectionEncloser", "icons",
+                             "selectionEncloser.png"),
+                createSelectionEncloserPage, None, None],
+        }
+    else:
+        return {}
+
+
+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 (UI.UserInterface)
+        """
+        QObject.__init__(self, 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. The title of the submenu
+        # entry is the enclosing string.
+        defaultMenu = [
+            [self.tr("Quotes"), ['"', "'", '"""', "'''"]],
+        ]
+        self.__defaults = {
+            "MenuHierarchy": json.dumps(defaultMenu),
+        }
+        
+        self.__translator = None
+        self.__loadTranslator()
+        
+        self.__initMenu()
+        
+        self.__editors = {}
+    
+    def activate(self):
+        """
+        Public method to activate this plugin.
+        
+        @return tuple of None and activation status (boolean)
+        """
+        global error
+        error = ""     # clear previous error
+        
+        global selectionEncloserPluginObject
+        selectionEncloserPluginObject = self
+        
+        self.__ui.showMenu.connect(self.__populateMenu)
+        
+        e5App().getObject("ViewManager").editorOpenedEd.connect(
+            self.__editorOpened)
+        e5App().getObject("ViewManager").editorClosedEd.connect(
+            self.__editorClosed)
+        
+        for editor in e5App().getObject("ViewManager").getOpenEditors():
+            self.__editorOpened(editor)
+        
+        return None, True
+    
+    def deactivate(self):
+        """
+        Public method to deactivate this plugin.
+        """
+        self.__ui.showMenu.disconnect(self.__populateMenu)
+        
+        e5App().getObject("ViewManager").editorOpenedEd.disconnect(
+            self.__editorOpened)
+        e5App().getObject("ViewManager").editorClosedEd.disconnect(
+            self.__editorClosed)
+        
+        for editor, acts in self.__editors.items():
+            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
+                    e5App().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 the key of the value to get (string)
+        @return the requested setting
+        """
+        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 the key of the setting to be set (string)
+        @param value the value to be set
+        """
+        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 (string)
+        @param menu reference to the menu to be populated (QMenu)
+        """
+        if name != "Tools":
+            return
+        
+        editor = e5App().getObject("ViewManager").activeWindow()
+        
+        if not menu.isEmpty():
+            menu.addSeparator()
+        
+        act = menu.addMenu(self.__menu)
+        act.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 (QScintilla.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 (QScintilla.Editor)
+        """
+        try:
+            del self.__editors[editor]
+            if not self.__editors:
+                self.__menu.setEnabled(False)
+        except KeyError:
+            pass
+    
+    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 (string)
+        @param menu reference to the menu (QMenu)
+        @param editor reference to the editor
+        """
+        if menuName == "Tools":
+            for act in self.__editors[editor]:
+                if not act.isSeparator():
+                    act.setEnabled(editor.hasSelectedText())
+    
+    def __showMenu(self):
+        """
+        Private slot to build the menu hierarchy.
+        """
+        self.__menu.clear()
+        hierarchy = self.getPreferences("MenuHierarchy")
+        for menuTitle, entries in hierarchy:
+            submenu = QMenu(menuTitle, self.__menu)
+            for entry in entries:
+                act = submenu.addAction(entry, self.__encloseSelection)
+                act.setData(entry)
+            self.__menu.addMenu(submenu)
+    
+    def __encloseSelection(self):
+        """
+        Private slot to enclose the selection with the selected string.
+        """
+        act = self.sender()
+        if act is None or not isinstance(act, QAction):
+            return
+        
+        editor = e5App().getObject("ViewManager").activeWindow()
+        if editor is None:
+            return
+        
+        if not editor.hasSelectedText():
+            return
+        
+        string = act.data()
+        if not string:
+            return
+        
+        newText = string + editor.selectedText() + string
+        editor.beginUndoAction()
+        editor.replaceSelectedText(newText)
+        editor.endUndoAction()

eric ide

mercurial