PluginProjectWeb.py

Tue, 25 Oct 2022 08:38:28 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 25 Oct 2022 08:38:28 +0200
branch
eric7
changeset 44
7d124a753853
parent 43
2bed42620c99
child 46
81fc3aacee19
permissions
-rw-r--r--

Adapted the import statements to the new structure.

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

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

"""
Module implementing the Web project plugin.
"""

import contextlib
import os

from PyQt6.QtCore import QObject, QTranslator
from PyQt6.QtWidgets import QMenu

from eric7.EricWidgets.EricApplication import ericApp

from eric7 import Preferences

try:
    from bs4 import BeautifulSoup  # __IGNORE_EXCEPTION__

    BeautifulSoupAvailable = True
except ImportError:
    BeautifulSoup = None
    BeautifulSoupAvailable = False

# Start-Of-Header
name = "Generic Web Project Plug-in"
author = "Detlev Offenbach <detlev@die-offenbachs.de>"
autoactivate = True
deactivateable = True
version = "10.1.0"
className = "ProjectWebPlugin"
packageName = "ProjectWeb"
shortDescription = "Support for Web projects and web related tools."
longDescription = (
    """This plug-in provides support for ordinary web projects and some web"""
    """ related tools.\n\nIt uses BeautifulSoup4 for some of its"""
    """ functionality."""
)
needsRestart = False
pyqtApi = 2
# End-Of-Header

error = ""


class ProjectWebPlugin(QObject):
    """
    Class implementing the Web project plugin.
    """

    def __init__(self, ui):
        """
        Constructor

        @param ui reference to the user interface object
        @type UserInterface
        """
        super().__init__(ui)
        self.__ui = ui
        self.__initialize()

        self.__translator = None
        self.__loadTranslator()

        self.__initMenu()

    def __initialize(self):
        """
        Private slot to (re)initialize the plugin.
        """
        self.__ericProject = ericApp().getObject("Project")

        self.__editors = {}
        self.__mainActions = []

    def activate(self):
        """
        Public method to activate this plugin.

        @return tuple of None and activation status
        @rtype tuple of (None, bool)
        """
        global error
        error = ""  # clear previous error

        # it is not registered for a specific programming language
        self.__ericProject.registerProjectType(
            "Web", self.tr("Web"), self.fileTypesCallback
        )

        from eric7.Project.ProjectBrowser import (
            SourcesBrowserFlag,
            FormsBrowserFlag,
            OthersBrowserFlag,
        )

        Preferences.setProjectBrowserFlagsDefault(
            "Web",
            SourcesBrowserFlag | FormsBrowserFlag | OthersBrowserFlag,
        )

        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.__ericProject.unregisterProjectType("Web")

        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.__initialize()

    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__), "ProjectWeb", "i18n"
                )
                translation = "web_{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 fileTypesCallback(self):
        """
        Public method to get the filetype associations of the Web project type.

        @return dictionary with file type associations
        @rtype dict
        """
        if self.__ericProject.getProjectType() == "Web":
            return {
                "*.html": "FORMS",
                "*.htm": "FORMS",
                "*.js": "SOURCES",
            }
        else:
            return {}

    def __initMenu(self):
        """
        Private method to initialize the web tools menu.
        """
        self.__menu = QMenu(self.tr("Web"))

        self.__html5ToCss3Act = self.__menu.addAction(
            self.tr("HTML5 to CSS3"), self.__html5ToCss3
        )
        self.__html5ToJsAct = self.__menu.addAction(
            self.tr("HTML5 to JavaScript"), self.__html5ToJs
        )
        self.__menu.addSeparator()
        self.__html5PrettifyAct = self.__menu.addAction(
            self.tr("Prettify HTML"), self.__html5Prettify
        )

        self.__menu.aboutToShow.connect(self.__menuAboutToShow)

    def __menuAboutToShow(self):
        """
        Private slot to prepare the menu before it is shown.
        """
        editor = ericApp().getObject("ViewManager").activeWindow()
        selectionAvailable = bool(editor and editor.selectedText() != "")
        isHtml = bool(editor and editor.getLanguage().lower().startswith("html"))

        self.__html5ToCss3Act.setEnabled(
            selectionAvailable and BeautifulSoupAvailable and isHtml
        )
        self.__html5ToJsAct.setEnabled(
            selectionAvailable and BeautifulSoupAvailable and isHtml
        )
        self.__html5PrettifyAct.setEnabled(BeautifulSoupAvailable and isHtml)

    def __populateMenu(self, name, menu):
        """
        Private slot to populate the tools menu with our entries.

        @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

        if name == "Tools":
            if not menu.isEmpty():
                menu.addSeparator()
            menu.addMenu(self.__menu)

    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.__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]

    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" and 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)

    def __html5ToCss3(self):
        """
        Private slot handling the HTML5 to CSS3 conversion.
        """
        from ProjectWeb.Html5ToCss3Converter import Html5ToCss3Converter

        vm = ericApp().getObject("ViewManager")
        editor = vm.activeWindow()
        html = editor.selectedText()

        converter = Html5ToCss3Converter(html)
        css3 = converter.getCss3()

        if css3:
            vm.newEditor()
            newEditor = vm.activeWindow()
            newEditor.setText(css3)
            newEditor.setLanguage("dummy.css")

    def __html5ToJs(self):
        """
        Private slot handling the HTML5 to JavaScript conversion.
        """
        from ProjectWeb.Html5ToJsConverter import Html5ToJsConverter

        vm = ericApp().getObject("ViewManager")
        editor = vm.activeWindow()
        html = editor.selectedText()

        converter = Html5ToJsConverter(html)
        js = converter.getJavaScript()

        if js:
            vm.newEditor()
            newEditor = vm.activeWindow()
            newEditor.setText(js)
            newEditor.setLanguage("dummy.js")

    def __html5Prettify(self):
        """
        Private slot handling the Prettify HTML action.
        """
        from ProjectWeb.Html5Prettifier import Html5Prettifier

        editor = ericApp().getObject("ViewManager").activeWindow()
        html = editor.text()

        prettifier = Html5Prettifier(html)
        newHtml = prettifier.getPrettifiedHtml()

        if newHtml and newHtml != html:
            cursorLine, cursorIndex = editor.getCursorPosition()

            editor.beginUndoAction()
            editor.selectAll()
            editor.replaceSelectedText(newHtml)
            editor.endUndoAction()

            editor.setCursorPosition(cursorLine, cursorIndex)


def installDependencies(pipInstall):
    """
    Function to install dependencies of this plug-in.

    @param pipInstall function to be called with a list of package names.
    @type function
    """
    try:
        import bs4  # __IGNORE_WARNING__
    except ImportError:
        pipInstall(["beautifulsoup4"])


#
# eflag: noqa = M801

eric ide

mercurial