PluginSelectionEncloser.py

Sat, 12 Jul 2014 14:59:56 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 12 Jul 2014 14:59:56 +0200
branch
eric5
changeset 15
f4bd4b3a9c28
parent 13
2d4785f57db3
child 16
d5eee7835f33
permissions
-rw-r--r--

Created new branch <eric5>.

# -*- coding: utf-8 -*-

# Copyright (c) 2014 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the Selection Encloser plug-in.
"""

from __future__ import unicode_literals

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 = "1.0.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. 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 = {}
    
    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:
            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, self.__encloseSelection)
                        act.setData(encString)
                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
        
        if '%s' in string:
            newText = string % editor.selectedText()
        elif '{0}' in string:
            newText = string.format(editor.selectedText())
        else:
            newText = string + editor.selectedText() + string
        editor.beginUndoAction()
        editor.replaceSelectedText(newText)
        editor.endUndoAction()

eric ide

mercurial