diff -r cff1c67f7dc1 -r 1ff6dcf50215 PluginSplitMergeCamelCase.py --- a/PluginSplitMergeCamelCase.py Sat Dec 21 13:04:13 2013 +0100 +++ b/PluginSplitMergeCamelCase.py Sat Dec 21 15:26:24 2013 +0100 @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the split, merge or convert camel case plug-in. +""" + +import os +import re + +from PyQt4.QtCore import QObject, QTranslator +from PyQt4.QtGui import QMenu + +from E5Gui.E5Application import e5App + +# Start-Of-Header +name = "Camel Case Handling Plug-in" +author = "Detlev Offenbach <detlev@die-offenbachs.de>" +autoactivate = True +deactivateable = True +version = "0.1.0" +className = "SplitMergeCamelCasePlugin" +packageName = "SplitMergeCamelCase" +shortDescription = "Split, merge or convert camel case text" +longDescription = \ + """This plug-in implements a tool to split, merge or convert""" \ + """ camel case text. It works with the text of the current""" \ + """ editor. The menu entries will only be selectable, if the""" \ + """ current editor has some selected text.""" +needsRestart = False +pyqtApi = 2 +# End-Of-Header + +error = "" + + +class SplitMergeCamelCasePlugin(QObject): + """ + Class implementing the split, merge or convert camel case plug-in. + """ + def __init__(self, ui): + """ + Constructor + + @param ui reference to the user interface object (UI.UserInterface) + """ + QObject.__init__(self, ui) + self.__ui = ui + + self.__translator = None + self.__loadTranslator() + + self.__initMenu() + + def activate(self): + """ + Public method to activate this plugin. + + @return tuple of None and activation status (boolean) + """ + global error + error = "" # clear previous error + + self.__ui.showMenu.connect(self.__populateMenu) + + return None, True + + def deactivate(self): + """ + Public method to deactivate this plugin. + """ + self.__ui.showMenu.disconnect(self.__populateMenu) + + 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__), "SplitMergeCamelCase", "i18n") + translation = "splitmergecamelcase_{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 __initMenu(self): + """ + Private method to initialize the camel case handling menu. + """ + self.__menu = QMenu(self.tr("CamelCase Handling")) + self.__menu.addAction(self.tr("Split from CamelCase"), + self.__splitCamelCase) + self.__menu.addAction(self.tr("Merge to CamelCase"), + self.__mergeCamelCase) + self.__menu.addAction(self.tr("CamelCase to under_score"), + self.__camelCaseToUnderscore) + self.__menu.addAction(self.tr("under_score to CamelCase"), + self.__underscoreToCamelCase) + self.__menu.addAction( + self.tr("under_score to CamelCase (upper case first)"), + self.__underscoreToCamelCaseUppercaseFirst) + + def __populateMenu(self, name, menu): + """ + Private slot to populate the tools menu with our entries. + + @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 editor is None: + return + + if not menu.isEmpty(): + menu.addSeparator() + + act = menu.addMenu(self.__menu) + act.setEnabled(editor.hasSelectedText()) + + def __applyChange(self, newText, editor): + """ + Private method to change the selected text. + + @param newText new (converted) text (string) + @param editor reference to the editor to apply the text + change to (Editor) + """ + editor.beginUndoAction() + editor.replaceSelectedText(newText) + editor.endUndoAction() + + def __splitCamelCase(self): + """ + Private slot to split the selected camel case text. + """ + editor = e5App().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + newText = re.sub(r"([A-Z])", r" \1", text) + if newText.startswith(" "): + newText = newText[1:] + if newText != text: + self.__applyChange(newText, editor) + + def __mergeCamelCase(self): + """ + Private slot to merge the selected text to camel case. + """ + editor = e5App().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + newText = "".join(text.split()) + if newText != text: + self.__applyChange(newText, editor) + + def __camelCaseToUnderscore(self): + """ + Private slot to convert camel case text to underscore separated text. + """ + editor = e5App().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + newText = re.sub(r"([A-Z])", r"_\1", text).lower() + if newText.startswith("_"): + newText = newText[1:] + if newText != text: + self.__applyChange(newText, editor) + + def __underscoreToCamelCase(self, uppercaseFirst=False): + """ + Private slot to convert underscore separated text to camel case. + + @param uppercaseFirst flag indicating to upper case the + first character (boolean) + """ + editor = e5App().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + newText = "".join([s.capitalize() for s in text.split("_")]) + if not uppercaseFirst: + newText = newText[0].lower() + newText[1:] + if newText != text: + self.__applyChange(newText, editor) + + def __underscoreToCamelCaseUppercaseFirst(self): + """ + Private slot to convert underscore separated text to camel case + upper casing the first character. + """ + self.__underscoreToCamelCase(True)