Started implementing a format button bar and provider classes for various markup languages.

Sun, 01 Jan 2017 18:09:48 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 01 Jan 2017 18:09:48 +0100
changeset 5394
b2c6179184f6
parent 5393
9db3fd0b1c72
child 5395
56efc13e456e

Started implementing a format button bar and provider classes for various markup languages.

QScintilla/EditorAssembly.py file | annotate | diff | comparison | revisions
QScintilla/EditorButtonsWidget.py file | annotate | diff | comparison | revisions
QScintilla/MarkupProviders/MarkdownProvider.py file | annotate | diff | comparison | revisions
QScintilla/MarkupProviders/MarkupBase.py file | annotate | diff | comparison | revisions
QScintilla/MarkupProviders/__init__.py file | annotate | diff | comparison | revisions
UI/Previewers/PreviewerHTML.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
icons/default/formatTextBold.png file | annotate | diff | comparison | revisions
icons/default/formatTextItalic.png file | annotate | diff | comparison | revisions
icons/default/formatTextStrikethrough.png file | annotate | diff | comparison | revisions
--- a/QScintilla/EditorAssembly.py	Sat Dec 31 17:52:23 2016 +0100
+++ b/QScintilla/EditorAssembly.py	Sun Jan 01 18:09:48 2017 +0100
@@ -41,14 +41,18 @@
         self.__layout.setContentsMargins(0, 0, 0, 0)
         self.__layout.setSpacing(1)
         
+        from .EditorButtonsWidget import EditorButtonsWidget
+        from .Editor import Editor
+        
+        self.__editor = Editor(dbs, fn, vm, filetype, editor, tv)
+        self.__buttonsWidget = EditorButtonsWidget(self.__editor)
         self.__globalsCombo = QComboBox()
         self.__membersCombo = QComboBox()
-        from .Editor import Editor
-        self.__editor = Editor(dbs, fn, vm, filetype, editor, tv)
         
-        self.__layout.addWidget(self.__globalsCombo, 0, 0)
-        self.__layout.addWidget(self.__membersCombo, 0, 1)
-        self.__layout.addWidget(self.__editor, 1, 0, 1, -1)
+        self.__layout.addWidget(self.__buttonsWidget, 1, 0, -1, 1)
+        self.__layout.addWidget(self.__globalsCombo, 0, 1)
+        self.__layout.addWidget(self.__membersCombo, 0, 2)
+        self.__layout.addWidget(self.__editor, 1, 1, 1, -1)
         
         self.__module = None
         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QScintilla/EditorButtonsWidget.py	Sun Jan 01 18:09:48 2017 +0100
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a widget containing various buttons for accessing
+editor actions.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtWidgets import QWidget, QVBoxLayout, QToolButton
+
+import UI.PixmapCache
+
+from . import MarkupProviders
+
+
+class EditorButtonsWidget(QWidget):
+    """
+    Class implementing a widget containing various buttons for accessing
+    editor actions.
+    """
+    def __init__(self, editor, parent=None):
+        """
+        Constructor
+        
+        @param editor reference to the editor
+        @type Editor
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(EditorButtonsWidget, self).__init__(parent)
+        
+        self.__layout = QVBoxLayout(self)
+        self.__layout.setContentsMargins(1, 1, 1, 1)
+        self.__layout.setSpacing(1)
+        
+        self.__provider = None
+        
+        self.__editor = editor
+        self.__editor.languageChanged.connect(self.__updateButtonStates)
+        self.__editor.editorSaved.connect(self.__updateButtonStates)
+        self.__editor.editorRenamed.connect(self.__updateButtonStates)
+        
+        self.__createButtons()
+        
+        self.__layout.addStretch()
+        self.setMaximumWidth(self.__buttons["bold"].sizeHint().width() + 2)
+        
+        self.__updateButtonStates()
+    
+    def __createButtons(self):
+        """
+        Private slot to create the various tool buttons.
+        """
+        self.__buttons = {}
+        
+        button = QToolButton(self)
+        button.setIcon(UI.PixmapCache.getIcon("formatTextBold.png"))
+        button.clicked.connect(lambda: self.__formatClicked("bold"))
+        self.__layout.addWidget(button)
+        self.__buttons["bold"] = button
+        
+        button = QToolButton(self)
+        button.setIcon(UI.PixmapCache.getIcon("formatTextItalic.png"))
+        button.clicked.connect(lambda: self.__formatClicked("italic"))
+        self.__layout.addWidget(button)
+        self.__buttons["italic"] = button
+        
+        button = QToolButton(self)
+        button.setIcon(UI.PixmapCache.getIcon("formatTextStrikethrough.png"))
+        button.clicked.connect(lambda: self.__formatClicked("strikethrough"))
+        self.__layout.addWidget(button)
+        self.__buttons["strikethrough"] = button
+    
+    @pyqtSlot()
+    def __updateButtonStates(self):
+        """
+        Private slot to change tzhe button states.
+        """
+        self.__provider = MarkupProviders.getMarkupProvider(self.__editor)
+        
+        self.__buttons["bold"].setEnabled(self.__provider.hasBold())
+        self.__buttons["italic"].setEnabled(self.__provider.hasItalic())
+        self.__buttons["strikethrough"].setEnabled(
+            self.__provider.hasStrikethrough())
+    
+    def __formatClicked(self, format):
+        """
+        Private slot to handle a format button being clicked.
+        
+        @param format format type of the button
+        @type str
+        """
+        if format == "bold":
+            self.__provider.bold(self.__editor)
+        elif format == "italic":
+            self.__provider.italic(self.__editor)
+        elif format == "strikethrough":
+            self.__provider.strikethrough(self.__editor)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QScintilla/MarkupProviders/MarkdownProvider.py	Sun Jan 01 18:09:48 2017 +0100
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the base class for the markup providers.
+"""
+
+from __future__ import unicode_literals
+
+from .MarkupBase import MarkupBase
+
+
+class MarkdownProvider(MarkupBase):
+    """
+    Class implementing the base class for the markup providers.
+    
+    Note: Derived classes need only implement those method they provide
+    functionality for. This base class implements do nothing variants for
+    all methods.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        super(MarkdownProvider, self).__init__()
+    
+    def hasBold(self):
+        """
+        Public method to indicate the availability of bold markup.
+        
+        @return flag indicating the availability of bold markup
+        @rtype bool
+        """
+        return True
+    
+    def hasItalic(self):
+        """
+        Public method to indicate the availability of italic markup.
+        
+        @return flag indicating the availability of italic markup
+        @rtype bool
+        """
+        return True
+    
+    def hasStrikethrough(self):
+        """
+        Public method to indicate the availability of strikethrough markup.
+        
+        @return flag indicating the availability of strikethrough markup
+        @rtype bool
+        """
+        return True
+    
+    def bold(self, editor):
+        """
+        Public method to generate bold text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        self.__insertMarkup("**", editor)
+    
+    def italic(self, editor):
+        """
+        Public method to generate italic text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        self.__insertMarkup("_", editor)
+    
+    def strikethrough(self, editor):
+        """
+        Public method to generate strikethrough text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        self.__insertMarkup("~~", editor)
+    
+    def __insertMarkup(self, markup, editor):
+        """
+        Private method to insert the specified markup.
+        
+        If the editor has selected text, this text is enclosed by the given
+        markup. If no text is selected, the markup is inserted at the cursor
+        position and the cursor is positioned in between.
+        
+        @param markup markup string to be inserted
+        @type str
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        if editor is None:
+            return
+        
+        editor.beginUndoAction()
+        if editor.hasSelectedText():
+            newText = "{0}{1}{0}".format(markup, editor.selectedText())
+            editor.replaceSelectedText(newText)
+        else:
+            editor.insert(2 * markup)
+            cline, cindex = editor.getCursorPosition()
+            editor.setCursorPosition(cline, cindex + len(markup))
+        editor.endUndoAction()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QScintilla/MarkupProviders/MarkupBase.py	Sun Jan 01 18:09:48 2017 +0100
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the base class for the markup providers.
+"""
+
+from __future__ import unicode_literals
+
+
+class MarkupBase(object):
+    """
+    Class implementing the base class for the markup providers.
+    
+    Note: Derived classes need only implement those method they provide
+    functionality for. This base class implements do nothing variants for
+    all methods.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        pass
+    
+    def hasBold(self):
+        """
+        Public method to indicate the availability of bold markup.
+        
+        @return flag indicating the availability of bold markup
+        @rtype bool
+        """
+        return False
+    
+    def hasItalic(self):
+        """
+        Public method to indicate the availability of italic markup.
+        
+        @return flag indicating the availability of italic markup
+        @rtype bool
+        """
+        return False
+    
+    def hasStrikethrough(self):
+        """
+        Public method to indicate the availability of strikethrough markup.
+        
+        @return flag indicating the availability of strikethrough markup
+        @rtype bool
+        """
+        return False
+    
+    def bold(self, editor):
+        """
+        Public method to generate bold text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        pass
+    
+    def italic(self, editor):
+        """
+        Public method to generate italic text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        pass
+    
+    def strikethrough(self, editor):
+        """
+        Public method to generate strikethrough text.
+        
+        @param editor reference to the editor to work on
+        @type Editor
+        """
+        pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QScintilla/MarkupProviders/__init__.py	Sun Jan 01 18:09:48 2017 +0100
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package providing various markup providers.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+import Preferences
+
+
+def getMarkupProvider(editor):
+    """
+    Public method to get a markup provider for the given editor.
+    
+    @param editor reference to the editor to get the markup provider for
+    @type Editor
+    @return markup provider
+    @rtype MarkupBase
+    """
+    if editor is not None:
+        fn = editor.getFileName()
+        
+        if fn:
+            extension = os.path.normcase(os.path.splitext(fn)[1][1:])
+        else:
+            extension = ""
+        if extension in \
+            Preferences.getEditor("PreviewHtmlFileNameExtensions") or \
+                editor.getLanguage() == "HTML":
+            # TODO: implement this
+            pass
+        elif extension in \
+            Preferences.getEditor("PreviewMarkdownFileNameExtensions") or \
+                editor.getLanguage().lower() == "markdown":
+            from .MarkdownProvider import MarkdownProvider
+            return MarkdownProvider()
+        elif extension in \
+            Preferences.getEditor("PreviewRestFileNameExtensions") or \
+                editor.getLanguage().lower() == "restructuredtext":
+            # TODO: implement this
+            pass
+    
+    # no supported markup provider identified
+    from .MarkupBase import MarkupBase
+    return MarkupBase()
--- a/UI/Previewers/PreviewerHTML.py	Sat Dec 31 17:52:23 2016 +0100
+++ b/UI/Previewers/PreviewerHTML.py	Sun Jan 01 18:09:48 2017 +0100
@@ -591,7 +591,8 @@
         except ImportError:
             return self.tr(
                 """<p>Markdown preview requires the <b>python-markdown</b> """
-                """package.<br/>Install it with your package manager or see """
+                """package.<br/>Install it with your package manager,"""
+                """ 'pip install docutils' or see """
                 """<a href="http://pythonhosted.org/Markdown/install.html">"""
                 """installation instructions.</a></p>""")
         
--- a/eric6.e4p	Sat Dec 31 17:52:23 2016 +0100
+++ b/eric6.e4p	Sun Jan 01 18:09:48 2017 +0100
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
 <!-- eric project file for project eric6 -->
-<!-- Copyright (C) 2016 Detlev Offenbach, detlev@die-offenbachs.de -->
+<!-- Copyright (C) 2017 Detlev Offenbach, detlev@die-offenbachs.de -->
 <Project version="5.1">
   <Language>en_US</Language>
   <ProjectWordList>Dictionaries/words.dic</ProjectWordList>
@@ -833,6 +833,7 @@
     <Source>QScintilla/APIsManager.py</Source>
     <Source>QScintilla/Editor.py</Source>
     <Source>QScintilla/EditorAssembly.py</Source>
+    <Source>QScintilla/EditorButtonsWidget.py</Source>
     <Source>QScintilla/EditorMarkerMap.py</Source>
     <Source>QScintilla/Exporters/ExporterBase.py</Source>
     <Source>QScintilla/Exporters/ExporterHTML.py</Source>
@@ -881,6 +882,9 @@
     <Source>QScintilla/Lexers/LexerXML.py</Source>
     <Source>QScintilla/Lexers/LexerYAML.py</Source>
     <Source>QScintilla/Lexers/__init__.py</Source>
+    <Source>QScintilla/MarkupProviders/MarkdownProvider.py</Source>
+    <Source>QScintilla/MarkupProviders/MarkupBase.py</Source>
+    <Source>QScintilla/MarkupProviders/__init__.py</Source>
     <Source>QScintilla/MiniEditor.py</Source>
     <Source>QScintilla/Printer.py</Source>
     <Source>QScintilla/QsciScintillaCompat.py</Source>
Binary file icons/default/formatTextBold.png has changed
Binary file icons/default/formatTextItalic.png has changed
Binary file icons/default/formatTextStrikethrough.png has changed

eric ide

mercurial