Sun, 22 Nov 2020 14:06:00 +0100
Added code ot create template web pages of selectable kinds.
--- 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>
--- 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 = [
--- /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"]
--- /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 &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>
--- 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")