Continued implementing the "Run Server" function.

Tue, 10 Nov 2020 19:38:00 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 10 Nov 2020 19:38:00 +0100
changeset 5
550e5ea385cb
parent 4
e164b9ad3819
child 6
d491ccab7343

Continued implementing the "Run Server" function.

PluginFlask.e4p file | annotate | diff | comparison | revisions
ProjectFlask/AnsiTools.py file | annotate | diff | comparison | revisions
ProjectFlask/ConfigurationPage/FlaskPage.py file | annotate | diff | comparison | revisions
ProjectFlask/RunServerDialog.py file | annotate | diff | comparison | revisions
ProjectFlask/RunServerDialog.ui file | annotate | diff | comparison | revisions
--- a/PluginFlask.e4p	Mon Nov 09 20:00:56 2020 +0100
+++ b/PluginFlask.e4p	Tue Nov 10 19:38:00 2020 +0100
@@ -15,6 +15,7 @@
   <Eol index="1"/>
   <Sources>
     <Source>PluginProjectFlask.py</Source>
+    <Source>ProjectFlask/AnsiTools.py</Source>
     <Source>ProjectFlask/ConfigurationPage/FlaskPage.py</Source>
     <Source>ProjectFlask/ConfigurationPage/__init__.py</Source>
     <Source>ProjectFlask/Project.py</Source>
@@ -23,8 +24,8 @@
     <Source>__init__.py</Source>
   </Sources>
   <Forms>
+    <Form>ProjectFlask/ConfigurationPage/FlaskPage.ui</Form>
     <Form>ProjectFlask/RunServerDialog.ui</Form>
-    <Form>ProjectFlask/ConfigurationPage/FlaskPage.ui</Form>
   </Forms>
   <Others>
     <Other>.hgignore</Other>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProjectFlask/AnsiTools.py	Tue Nov 10 19:38:00 2020 +0100
@@ -0,0 +1,165 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing functions to work with ANSI escape sequences for colors.
+"""
+
+from PyQt5.QtGui import QColor, QBrush
+
+# ANSI Colors (see https://en.wikipedia.org/wiki/ANSI_escape_code)
+_AnsiColorSchemes = {
+    "Windows 7": {
+        0: QBrush(QColor(0, 0, 0)),
+        1: QBrush(QColor(128, 0, 0)),
+        2: QBrush(QColor(0, 128, 0)),
+        3: QBrush(QColor(128, 128, 0)),
+        4: QBrush(QColor(0, 0, 128)),
+        5: QBrush(QColor(128, 0, 128)),
+        6: QBrush(QColor(0, 128, 128)),
+        7: QBrush(QColor(192, 192, 192)),
+        10: QBrush(QColor(128, 128, 128)),
+        11: QBrush(QColor(255, 0, 0)),
+        12: QBrush(QColor(0, 255, 0)),
+        13: QBrush(QColor(255, 255, 0)),
+        14: QBrush(QColor(0, 0, 255)),
+        15: QBrush(QColor(255, 0, 255)),
+        16: QBrush(QColor(0, 255, 255)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+    "Windows 10": {
+        0: QBrush(QColor(12, 12, 12)),
+        1: QBrush(QColor(197, 15, 31)),
+        2: QBrush(QColor(19, 161, 14)),
+        3: QBrush(QColor(193, 156, 0)),
+        4: QBrush(QColor(0, 55, 218)),
+        5: QBrush(QColor(136, 23, 152)),
+        6: QBrush(QColor(58, 150, 221)),
+        7: QBrush(QColor(204, 204, 204)),
+        10: QBrush(QColor(118, 118, 118)),
+        11: QBrush(QColor(231, 72, 86)),
+        12: QBrush(QColor(22, 198, 12)),
+        13: QBrush(QColor(249, 241, 165)),
+        14: QBrush(QColor(59, 12, 255)),
+        15: QBrush(QColor(180, 0, 158)),
+        16: QBrush(QColor(97, 214, 214)),
+        17: QBrush(QColor(242, 242, 242)),
+    },
+    "PuTTY": {
+        0: QBrush(QColor(0, 0, 0)),
+        1: QBrush(QColor(187, 0, 0)),
+        2: QBrush(QColor(0, 187, 0)),
+        3: QBrush(QColor(187, 187, 0)),
+        4: QBrush(QColor(0, 0, 187)),
+        5: QBrush(QColor(187, 0, 187)),
+        6: QBrush(QColor(0, 187, 187)),
+        7: QBrush(QColor(187, 187, 187)),
+        10: QBrush(QColor(85, 85, 85)),
+        11: QBrush(QColor(255, 85, 85)),
+        12: QBrush(QColor(85, 255, 85)),
+        13: QBrush(QColor(255, 255, 85)),
+        14: QBrush(QColor(85, 85, 255)),
+        15: QBrush(QColor(255, 85, 255)),
+        16: QBrush(QColor(85, 255, 255)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+    "xterm": {
+        0: QBrush(QColor(0, 0, 0)),
+        1: QBrush(QColor(205, 0, 0)),
+        2: QBrush(QColor(0, 205, 0)),
+        3: QBrush(QColor(205, 205, 0)),
+        4: QBrush(QColor(0, 0, 238)),
+        5: QBrush(QColor(205, 0, 205)),
+        6: QBrush(QColor(0, 205, 205)),
+        7: QBrush(QColor(229, 229, 229)),
+        10: QBrush(QColor(127, 127, 127)),
+        11: QBrush(QColor(255, 0, 0)),
+        12: QBrush(QColor(0, 255, 0)),
+        13: QBrush(QColor(255, 255, 0)),
+        14: QBrush(QColor(0, 0, 255)),
+        15: QBrush(QColor(255, 0, 255)),
+        16: QBrush(QColor(0, 255, 255)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+    "Ubuntu": {
+        0: QBrush(QColor(1, 1, 1)),
+        1: QBrush(QColor(222, 56, 43)),
+        2: QBrush(QColor(57, 181, 74)),
+        3: QBrush(QColor(255, 199, 6)),
+        4: QBrush(QColor(0, 11, 184)),
+        5: QBrush(QColor(118, 38, 113)),
+        6: QBrush(QColor(44, 181, 233)),
+        7: QBrush(QColor(204, 204, 204)),
+        10: QBrush(QColor(128, 128, 128)),
+        11: QBrush(QColor(255, 0, 0)),
+        12: QBrush(QColor(0, 255, 0)),
+        13: QBrush(QColor(255, 255, 0)),
+        14: QBrush(QColor(0, 0, 255)),
+        15: QBrush(QColor(255, 0, 255)),
+        16: QBrush(QColor(0, 255, 255)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+    "Ubuntu (dark)": {
+        0: QBrush(QColor(96, 96, 96)),
+        1: QBrush(QColor(235, 58, 45)),
+        2: QBrush(QColor(57, 181, 74)),
+        3: QBrush(QColor(255, 199, 29)),
+        4: QBrush(QColor(25, 56, 230)),
+        5: QBrush(QColor(200, 64, 193)),
+        6: QBrush(QColor(48, 200, 255)),
+        7: QBrush(QColor(204, 204, 204)),
+        10: QBrush(QColor(128, 128, 128)),
+        11: QBrush(QColor(255, 0, 0)),
+        12: QBrush(QColor(0, 255, 0)),
+        13: QBrush(QColor(255, 255, 0)),
+        14: QBrush(QColor(0, 0, 255)),
+        15: QBrush(QColor(255, 0, 255)),
+        16: QBrush(QColor(0, 255, 255)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+    "Breeze (dark)": {
+        0: QBrush(QColor(35, 38, 39)),
+        1: QBrush(QColor(237, 21, 21)),
+        2: QBrush(QColor(17, 209, 22)),
+        3: QBrush(QColor(246, 116, 0)),
+        4: QBrush(QColor(29, 153, 243)),
+        5: QBrush(QColor(155, 89, 182)),
+        6: QBrush(QColor(26, 188, 156)),
+        7: QBrush(QColor(252, 252, 252)),
+        10: QBrush(QColor(127, 140, 141)),
+        11: QBrush(QColor(192, 57, 43)),
+        12: QBrush(QColor(28, 220, 154)),
+        13: QBrush(QColor(253, 188, 75)),
+        14: QBrush(QColor(61, 174, 233)),
+        15: QBrush(QColor(142, 68, 173)),
+        16: QBrush(QColor(22, 160, 133)),
+        17: QBrush(QColor(255, 255, 255)),
+    },
+}
+
+
+def getAvailableColorSchemes():
+    """
+    Function to get a list of available color schemes.
+    
+    @return list containing the names of the supported color schemes
+    @rtype list of str
+    """
+    return list(_AnsiColorSchemes.keys())
+
+
+def getColor(scheme, color):
+    """
+    Function to get the brush for a given scheme and color.
+    
+    @paran scheme name of the color scheme
+    @type str
+    @param color ANSI color code
+    @type int
+    """
+    try:
+        return _AnsiColorSchemes[scheme][color]
+    except KeyError:
+        return QBrush()
--- a/ProjectFlask/ConfigurationPage/FlaskPage.py	Mon Nov 09 20:00:56 2020 +0100
+++ b/ProjectFlask/ConfigurationPage/FlaskPage.py	Tue Nov 10 19:38:00 2020 +0100
@@ -19,6 +19,7 @@
 import UI.PixmapCache
 
 
+# TODO: add selection for the ANSI color scheme (see MicroPython)
 class FlaskPage(ConfigurationPageBase, Ui_FlaskPage):
     """
     Class implementing the Flask configuration page.
--- a/ProjectFlask/RunServerDialog.py	Mon Nov 09 20:00:56 2020 +0100
+++ b/ProjectFlask/RunServerDialog.py	Tue Nov 10 19:38:00 2020 +0100
@@ -7,7 +7,9 @@
 Module implementing a dialog to run the Flask server.
 """
 
-from PyQt5.QtCore import pyqtSlot, QProcess
+import re
+
+from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer
 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
 
 from E5Gui import E5MessageBox
@@ -31,9 +33,13 @@
         
         self.__process = None
         
+        self.__ansiRe = re.compile("(\\x1b\[\d+m)")
+        
         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
         self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
         self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        
+        self.__defaultTextFormat = self.outputEdit.currentCharFormat()
     
     def startServer(self, command, workdir, env):
         """
@@ -48,14 +54,13 @@
         @return flag indicating a successful start
         @rtype bool
         """
-        self.errorsEdit.hide()
-        
         self.__process = QProcess()
-        self.__process.readyReadStandardOutput.connect(self.__readStdOut)
-        self.__process.readyReadStandardError.connect(self.__readStdErr)
-        self.__process.finished.connect(self.__processFinished)
         self.__process.setProcessEnvironment(env)
         self.__process.setWorkingDirectory(workdir)
+        self.__process.setProcessChannelMode(QProcess.MergedChannels)
+        
+        self.__process.readyReadStandardOutput.connect(self.__readStdOut)
+        self.__process.finished.connect(self.__processFinished)
         
         self.__process.start(command, ["run"])
         ok = self.__process.waitForStarted(10000)
@@ -78,7 +83,8 @@
         @param evt reference to the close event
         @type QCloseEvent
         """
-        # TODO: not implemented yet
+        self.__cancel()
+        evt.accept()
     
     @pyqtSlot(QAbstractButton)
     def on_buttonBox_clicked(self, button):
@@ -100,27 +106,38 @@
         """
         if self.__process is not None:
             out = str(self.__process.readAllStandardOutput(), "utf-8")
-            self.outputEdit.appendPlainText(out)
-    
-    @pyqtSlot()
-    def __readStdErr(self):
-        """
-        Private slot to add the server process errors to the errors pane.
-        """
-        if self.__process is not None:
-            err = str(self.__process.readAllStandardError(), "utf-8")
-            self.errorsEdit.appendPlainText(err)
-            
-            self.errorsEdit.show()
+            for txt in self.__ansiRe.split(out):
+                if txt.startswith("\x1b["):
+                    # TODO: process ANSI escape sequences for coloring
+                    pass
+                else:
+                    self.outputEdit.insertPlainText(txt)
     
     @pyqtSlot()
     def __processFinished(self):
-        # TODO: implement it
-        pass
+        """
+        Private slot handling the finishing of the server process.
+        """
+        if (
+            self.__process is not None and
+            self.__process.state() != QProcess.NotRunning
+        ):
+            self.__process.terminate()
+            QTimer.singleShot(2000, self.__process.kill)
+            self.__process.waitForFinished(3000)
+        
+        self.__process = None
+        
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.Close).setFocus(
+            Qt.OtherFocusReason)
     
     @pyqtSlot()
     def __cancel(self):
         """
         Private slot to cancel the running server.
         """
-        # TODO: not implemented yet
+        self.__processFinished()
--- a/ProjectFlask/RunServerDialog.ui	Mon Nov 09 20:00:56 2020 +0100
+++ b/ProjectFlask/RunServerDialog.ui	Tue Nov 10 19:38:00 2020 +0100
@@ -19,12 +19,6 @@
   <layout class="QVBoxLayout" name="verticalLayout_3">
    <item>
     <widget class="QGroupBox" name="groupBox">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>2</verstretch>
-      </sizepolicy>
-     </property>
      <property name="title">
       <string>Output</string>
      </property>
@@ -49,37 +43,6 @@
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox_2">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-       <horstretch>0</horstretch>
-       <verstretch>1</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="title">
-      <string>Errors</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
-      <item>
-       <widget class="QPlainTextEdit" name="errorsEdit">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="lineWrapMode">
-         <enum>QPlainTextEdit::NoWrap</enum>
-        </property>
-        <property name="readOnly">
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
     <widget class="QDialogButtonBox" name="buttonBox">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>

eric ide

mercurial