Added code ot create template web pages of selectable kinds.

Sun, 22 Nov 2020 14:06:00 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 22 Nov 2020 14:06:00 +0100
changeset 18
d76a0939be6a
parent 17
f31df56510a1
child 19
f8e3c1676f9b

Added code ot create template web pages of selectable kinds.

PluginFlask.e4p file | annotate | diff | comparison | revisions
ProjectFlask/FlaskBabelExtension/PyBabelProjectExtension.py file | annotate | diff | comparison | revisions
ProjectFlask/FormSelectionDialog.py file | annotate | diff | comparison | revisions
ProjectFlask/FormSelectionDialog.ui file | annotate | diff | comparison | revisions
ProjectFlask/Project.py file | annotate | diff | comparison | revisions
diff -r f31df56510a1 -r d76a0939be6a PluginFlask.e4p
--- a/PluginFlask.e4p	Sat Nov 21 20:37:54 2020 +0100
+++ b/PluginFlask.e4p	Sun Nov 22 14:06:00 2020 +0100
@@ -24,6 +24,7 @@
     <Source>ProjectFlask/FlaskBabelExtension/PyBabelProjectExtension.py</Source>
     <Source>ProjectFlask/FlaskBabelExtension/__init__.py</Source>
     <Source>ProjectFlask/FlaskCommandDialog.py</Source>
+    <Source>ProjectFlask/FormSelectionDialog.py</Source>
     <Source>ProjectFlask/Project.py</Source>
     <Source>ProjectFlask/RoutesDialog.py</Source>
     <Source>ProjectFlask/RunServerDialog.py</Source>
@@ -35,6 +36,7 @@
     <Form>ProjectFlask/ConfigurationPage/FlaskPage.ui</Form>
     <Form>ProjectFlask/FlaskBabelExtension/PyBabelConfigDialog.ui</Form>
     <Form>ProjectFlask/FlaskCommandDialog.ui</Form>
+    <Form>ProjectFlask/FormSelectionDialog.ui</Form>
     <Form>ProjectFlask/RoutesDialog.ui</Form>
     <Form>ProjectFlask/RunServerDialog.ui</Form>
     <Form>ProjectFlask/ServerStartOptionsDialog.ui</Form>
diff -r f31df56510a1 -r d76a0939be6a ProjectFlask/FlaskBabelExtension/PyBabelProjectExtension.py
--- a/ProjectFlask/FlaskBabelExtension/PyBabelProjectExtension.py	Sat Nov 21 20:37:54 2020 +0100
+++ b/ProjectFlask/FlaskBabelExtension/PyBabelProjectExtension.py	Sun Nov 22 14:06:00 2020 +0100
@@ -251,7 +251,7 @@
                         """ required.""")
             )
             return True
-        except EnvironmentError as err:
+        except OSError as err:
             E5MessageBox.warning(
                 None,
                 self.tr("Generate PyBabel Configuration File"),
@@ -318,7 +318,7 @@
             try:
                 potFilePath = os.path.dirname(potFile)
                 os.makedirs(potFilePath)
-            except EnvironmentError:
+            except OSError:
                 pass
             
             args = [
diff -r f31df56510a1 -r d76a0939be6a ProjectFlask/FormSelectionDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProjectFlask/FormSelectionDialog.py	Sun Nov 22 14:06:00 2020 +0100
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to select the template type.
+"""
+
+from PyQt5.QtCore import pyqtSlot, QCoreApplication
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+
+from .Ui_FormSelectionDialog import Ui_FormSelectionDialog
+
+
+class FormSelectionDialog(QDialog, Ui_FormSelectionDialog):
+    """
+    Class implementing a dialog to select the template type.
+    """
+    Templates = {
+        "html5": {
+            "title": QCoreApplication.translate(
+                "FormSelectionDialog", "Standard HTML 5 template"),
+            "template": '''<!DOCTYPE html>\n'''
+                        '''  <head>\n'''
+                        '''    <title></title>\n'''
+                        '''    <style>\n'''
+                        '''    </style>\n'''
+                        '''  </head>\n'''
+                        '''\n'''
+                        '''  <body>\n'''
+                        '''  </body>\n'''
+                        '''</html>\n''',
+        },
+        "basic_jinja": {
+            "title": QCoreApplication.translate(
+                "FormSelectionDialog", "Basic Jinja template"),
+            "template": '''<!DOCTYPE html>\n'''
+                        '''  <head>\n'''
+                        '''    {% if title %}\n'''
+                        '''    <title>{{ title }}</title>\n'''
+                        '''    {% else %}\n'''
+                        '''    <title>Title</title>\n'''
+                        '''    {% endif %}\n'''
+                        '''  </head>\n'''
+                        '''\n'''
+                        '''  <body>\n'''
+                        '''    <h1>Hello, {{ user.username }}!</h1>\n'''
+                        '''  </body>\n'''
+                        '''</html>\n''',
+        },
+        "jinja_base": {
+            "title": QCoreApplication.translate(
+                "FormSelectionDialog", "Jinja base template"),
+            "template": '''<!DOCTYPE html>\n'''
+                        '''  <head>\n'''
+                        '''    {% if title %}\n'''
+                        '''    <title>{{ title }}</title>\n'''
+                        '''    {% else %}\n'''
+                        '''    <title>Title</title>\n'''
+                        '''    {% endif %}\n'''
+                        '''  </head>\n'''
+                        '''\n'''
+                        '''  <body>\n'''
+                        '''    {% block content %}{% endblock %}\n'''
+                        '''  </body>\n'''
+                        '''</html>\n''',
+        },
+        "jinja_extends": {
+            "title": QCoreApplication.translate(
+                "FormSelectionDialog", "Jinja extension template"),
+            "template": '''{% extends "base.html" %}\n'''
+                        '''\n'''
+                        '''{% block content %}\n'''
+                        '''  <h1>{{ user.username }}</h1>\n'''
+                        '''  {% for item in items %}\n'''
+                        '''  <div><p>{{ item.field1 }}: {{ item.field2 }}'''
+                        '''</p></div>\n'''
+                        '''  {% endfor %}\n'''
+                        '''{% endblock %}\n'''
+        },
+    }
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(FormSelectionDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+        
+        self.typeCombo.addItem("")
+        for templateType in FormSelectionDialog.Templates:
+            self.typeCombo.addItem(
+                FormSelectionDialog.Templates[templateType]["title"],
+                templateType)
+        self.typeCombo.setCurrentIndex(0)
+    
+    @pyqtSlot(int)
+    def on_typeCombo_currentIndexChanged(self, index):
+        """
+        Private slot to act upon a change of the selected template type.
+        
+        @param index selected index
+        @type int
+        """
+        templateType = self.typeCombo.itemData(index)
+        if templateType:
+            self.preview.setPlainText(
+                FormSelectionDialog.Templates[templateType]["template"])
+            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
+        else:
+            self.preview.clear()
+            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+    
+    def getTemplateText(self):
+        """
+        Public method to get the template text.
+        
+        @return text of the template
+        @rtype str
+        """
+        templateType = self.typeCombo.currentData()
+        return FormSelectionDialog.Templates[templateType]["template"]
diff -r f31df56510a1 -r d76a0939be6a ProjectFlask/FormSelectionDialog.ui
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProjectFlask/FormSelectionDialog.ui	Sun Nov 22 14:06:00 2020 +0100
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FormSelectionDialog</class>
+ <widget class="QDialog" name="FormSelectionDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>450</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Template Type Selection</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Template &amp;Type:</string>
+     </property>
+     <property name="buddy">
+      <cstring>typeCombo</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QComboBox" name="typeCombo">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="toolTip">
+      <string>Select the template type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Preview:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QPlainTextEdit" name="preview">
+     <property name="font">
+      <font>
+       <family>Noto Sans Mono</family>
+      </font>
+     </property>
+     <property name="toolTip">
+      <string>Shows the text of the selected template</string>
+     </property>
+     <property name="tabChangesFocus">
+      <bool>true</bool>
+     </property>
+     <property name="lineWrapMode">
+      <enum>QPlainTextEdit::NoWrap</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>typeCombo</tabstop>
+  <tabstop>preview</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>FormSelectionDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>FormSelectionDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff -r f31df56510a1 -r d76a0939be6a ProjectFlask/Project.py
--- a/ProjectFlask/Project.py	Sat Nov 21 20:37:54 2020 +0100
+++ b/ProjectFlask/Project.py	Sun Nov 22 14:06:00 2020 +0100
@@ -10,11 +10,11 @@
 import os
 
 from PyQt5.QtCore import (
-    pyqtSlot, QObject, QProcess, QProcessEnvironment, QTimer
+    pyqtSlot, QObject, QProcess, QProcessEnvironment, QTimer, QFileInfo
 )
-from PyQt5.QtWidgets import QMenu
+from PyQt5.QtWidgets import QMenu, QDialog
 
-from E5Gui import E5MessageBox
+from E5Gui import E5MessageBox, E5FileDialog
 from E5Gui.E5Action import E5Action
 from E5Gui.E5Application import e5App
 
@@ -54,6 +54,7 @@
         self.__virtualEnvManager = e5App().getObject("VirtualEnvManager")
         
         self.__menus = {}   # dictionary with references to menus
+        self.__formsBrowser = None
         self.__hooksInstalled = False
          
         self.__serverDialog = None
@@ -300,17 +301,17 @@
         Public method to add our hook methods.
         """
         if self.__e5project.getProjectType() == "Flask":
-            # TODO: add some methods for standard templates
-##            self.__formsBrowser = (
-##                e5App().getObject("ProjectBrowser")
-##                .getProjectBrowser("forms"))
-##            self.__formsBrowser.addHookMethodAndMenuEntry(
-##                "newForm", self.newForm, self.tr("New template..."))
-##            
+            self.__formsBrowser = (
+                e5App().getObject("ProjectBrowser")
+                .getProjectBrowser("forms"))
+            self.__formsBrowser.addHookMethodAndMenuEntry(
+                "newForm", self.newForm, self.tr("New template..."))
+            
             self.__determineCapabilities()
             
             self.__pybabelProject.projectOpenedHooks()
-##            self.__hooksInstalled = True
+            
+            self.__hooksInstalled = True
     
     def projectClosedHooks(self):
         """
@@ -319,12 +320,68 @@
         self.__pybabelProject.projectClosedHooks()
         
         if self.__hooksInstalled:
-##            self.__formsBrowser.removeHookMethod("newForm")
-##            self.__formsBrowser = None
-            pass
+            self.__formsBrowser.removeHookMethod("newForm")
+            self.__formsBrowser = None
         
         self.__hooksInstalled = False
     
+    def newForm(self, dirPath):
+        """
+        Public method to create a new form.
+        
+        @param dirPath full directory path for the new form file
+        @type str
+        """
+        from .FormSelectionDialog import FormSelectionDialog
+        
+        dlg = FormSelectionDialog()
+        if dlg.exec() == QDialog.Accepted:
+            template = dlg.getTemplateText()
+            
+            fileFilters = self.tr(
+                "HTML Files (*.html);;"
+                "HTML Files (*.htm);;"
+                "All Files (*)")
+            fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
+                self.__ui,
+                self.tr("New Form"),
+                dirPath,
+                fileFilters,
+                None,
+                E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
+            if fname:
+                ext = QFileInfo(fname).suffix()
+                if not ext:
+                    ex = selectedFilter.split("(*")[1].split(")")[0]
+                    if ex:
+                        fname += ex
+                
+                if os.path.exists(fname):
+                    res = E5MessageBox.yesNo(
+                        self.__ui,
+                        self.tr("New Form"),
+                        self.tr("""The file already exists! Overwrite"""
+                                """ it?"""),
+                        icon=E5MessageBox.Warning)
+                    if not res:
+                        # user selected to not overwrite
+                        return
+                
+                try:
+                    with open(fname, "w", encoding="utf-8") as f:
+                        f.write(template)
+                except OSError as err:
+                    E5MessageBox.critical(
+                        self.__ui,
+                        self.tr("New Form"),
+                        self.tr("<p>The new form file <b>{0}</b> could"
+                                " not be created.</p><p>Problem: {1}</p>")
+                        .format(fname, str(err)))
+                    return
+                
+                self.__e5project.appendFile(fname)
+                self.__formsBrowser.sourceFile.emit(fname)
+    
     ##################################################################
     ## slots below implement general functionality
     ##################################################################
@@ -362,7 +419,7 @@
                     try:
                         with open(fullCmd, 'r', encoding='utf-8') as f:
                             l0 = f.readline()
-                    except (IOError, OSError):
+                    except OSError:
                         l0 = ""
                     if self.__isSuitableForVariant("Python3", l0):
                         variants.append("Python3")

eric ide

mercurial