Continued implementing a manager for color themes. eric7

Thu, 09 Dec 2021 20:07:08 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 09 Dec 2021 20:07:08 +0100
branch
eric7
changeset 8819
982fb074be98
parent 8818
2c14c7a09032
child 8820
149f941d072e

Continued implementing a manager for color themes.

eric7/Preferences/ThemeManager.py file | annotate | diff | comparison | revisions
eric7/QScintilla/Lexers/__init__.py file | annotate | diff | comparison | revisions
eric7/UI/UserInterface.py file | annotate | diff | comparison | revisions
--- a/eric7/Preferences/ThemeManager.py	Wed Dec 08 19:52:51 2021 +0100
+++ b/eric7/Preferences/ThemeManager.py	Thu Dec 09 20:07:08 2021 +0100
@@ -7,10 +7,14 @@
 Module implementing a manager object for color themes.
 """
 
+import json
+import os
 import re
 
 from PyQt6.QtCore import QObject
 
+from EricWidgets import EricMessageBox, EricFileDialog
+
 import Preferences
 
 
@@ -38,7 +42,7 @@
         "UI/NotificationWarningForeground",
     ]
     
-    def __init__(self, parent=None):
+    def __init__(self: "ThemeManager", parent: QObject = None):
         """
         Constructor
         
@@ -47,24 +51,94 @@
         """
         super().__init__(parent)
     
-    def importTheme(self):
+    def importTheme(self: "ThemeManager"):
         """
         Public method to import a theme file and set the colors.
         """
         # TODO: not yet implemented
+        
+        # TODO: add entry for the current QSS file
+        #       - on import save it in the eric configuration directory
+        #         if such file does not exist already
+        #       - on import set stylesheet key to the saved file
     
-    def exportTheme(self):
+    def exportTheme(self: "ThemeManager"):
         """
         Public method to export the current colors to a theme file.
         """
-        # TODO: not yet implemented
-        settings = Preferences.getSettings()
-        keyFilterRe = re.compile("|".join(
-            ThemeManager.KeyPatternList + ThemeManager.KeyList))
-        
-        keys = [k for k in settings.allKeys() if keyFilterRe.match(k)]
-        themeDict = {}
-        for key in keys:
-            themeDict[key] = settings.value(key)
-        
-        # TODO: save to a json file *.ethj
+        filename, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
+            None,
+            self.tr("Export Theme"),
+            os.path.expanduser("~"),
+            self.tr("eric Theme Files (*.ethj);;All Files (*)"),
+            "",
+            EricFileDialog.DontConfirmOverwrite
+        )
+        if filename:
+            ext = os.path.splitext(filename)[1]
+            if not ext:
+                filename = "{0}{1}".format(
+                    filename,
+                    selectedFilter.rsplit(None, 1)[-1][2:-1])
+            
+            ok = (
+                EricMessageBox.yesNo(
+                    None,
+                    self.tr("Export Theme"),
+                    self.tr(
+                        """<p>The theme file <b>{0}</b> exists"""
+                        """ already. Overwrite it?</p>""").format(filename))
+                if os.path.exists(filename) else
+                True
+            )
+            
+            if ok:
+                # step 1: generate a dictionary with all color settings
+                settings = Preferences.getSettings()
+                keyFilterRe = re.compile("|".join(
+                    ThemeManager.KeyPatternList + ThemeManager.KeyList))
+                
+                keys = [k for k in settings.allKeys() if keyFilterRe.match(k)]
+                colorsDict = {}
+                for key in keys:
+                    colorsDict[key] = settings.value(key)
+                
+                # step 2: read the contents of the current stylesheet
+                stylesheetDict = {
+                    "contents": "",
+                    "name": ""
+                }
+                stylesheet = Preferences.getUI("StyleSheet")
+                if stylesheet and os.path.exists(stylesheet):
+                    try:
+                        with open(stylesheet, "r") as f:
+                            stylesheetDict["contents"] = f.read()
+                        stylesheetDict["name"] = os.path.basename(stylesheet)
+                    except OSError as err:
+                        EricMessageBox.critical(
+                            None,
+                            self.tr("Export Theme"),
+                            self.tr(
+                                "<p>The styleshhet file <b>{0}</b> could not"
+                                " be read.</p><p>Reason: {1}</p>"
+                            ).format(stylesheet, str(err))
+                        )
+                
+                themeDict = {
+                    "colors": colorsDict,
+                    "stylesheet": stylesheetDict,
+                }
+                
+                try:
+                    jsonString = json.dumps(themeDict, indent=2)
+                    with open(filename, "w") as f:
+                        f.write(jsonString)
+                except (TypeError, OSError) as err:
+                    EricMessageBox.critical(
+                        None,
+                        self.tr("Export Theme"),
+                        self.tr(
+                            "<p>The theme file <b>{0}</b> could not"
+                            " be written.</p><p>Reason: {1}</p>"
+                        ).format(filename, str(err))
+                    )
--- a/eric7/QScintilla/Lexers/__init__.py	Wed Dec 08 19:52:51 2021 +0100
+++ b/eric7/QScintilla/Lexers/__init__.py	Thu Dec 09 20:07:08 2021 +0100
@@ -913,6 +913,7 @@
         '*.eqj': "JSON",
         '*.esj': "JSON",
         '*.etj': "JSON",
+        '*.ethj': "JSON",
         '*.proto': "Protocol Buffer",
         '*.po': "Gettext",
         '*.coffee': "CoffeeScript",
--- a/eric7/UI/UserInterface.py	Wed Dec 08 19:52:51 2021 +0100
+++ b/eric7/UI/UserInterface.py	Thu Dec 09 20:07:08 2021 +0100
@@ -2840,6 +2840,34 @@
         self.prefImportAct.triggered.connect(self.__importPreferences)
         self.actions.append(self.prefImportAct)
 
+        self.themeExportAct = EricAction(
+            self.tr('Export Theme'),
+##            UI.PixmapCache.getIcon("configureExport"),
+            self.tr('Export Theme...'),
+            0, 0, self, 'export_theme')
+        self.themeExportAct.setStatusTip(self.tr(
+            'Export the current theme'))
+        self.themeExportAct.setWhatsThis(self.tr(
+            """<b>Export Theme</b>"""
+            """<p>Export the current theme to a file.</p>"""
+        ))
+        self.themeExportAct.triggered.connect(self.__exportTheme)
+        self.actions.append(self.themeExportAct)
+
+        self.themeImportAct = EricAction(
+            self.tr('Import Theme'),
+##            UI.PixmapCache.getIcon("configureImport"),
+            self.tr('Import Theme...'),
+            0, 0, self, 'import_theme')
+        self.themeImportAct.setStatusTip(self.tr(
+            'Import a previously exported theme'))
+        self.themeImportAct.setWhatsThis(self.tr(
+            """<b>Import Theme</b>"""
+            """<p>Import a previously exported theme.</p>"""
+        ))
+        self.themeImportAct.triggered.connect(self.__importTheme)
+        self.actions.append(self.themeImportAct)
+
         self.reloadAPIsAct = EricAction(
             self.tr('Reload APIs'),
             self.tr('Reload &APIs'),
@@ -3426,6 +3454,9 @@
         self.__menus["settings"].addAction(self.prefExportAct)
         self.__menus["settings"].addAction(self.prefImportAct)
         self.__menus["settings"].addSeparator()
+        self.__menus["settings"].addAction(self.themeExportAct)
+        self.__menus["settings"].addAction(self.themeImportAct)
+        self.__menus["settings"].addSeparator()
         self.__menus["settings"].addAction(self.reloadAPIsAct)
         self.__menus["settings"].addSeparator()
         self.__menus["settings"].addAction(self.configViewProfilesAct)
@@ -3667,6 +3698,8 @@
             self.importShortcutsAct,
             self.prefExportAct,
             self.prefImportAct,
+            self.themeExportAct,
+            self.themeImportAct,
             self.showExternalToolsAct,
             self.editMessageFilterAct,
             self.clearPrivateDataAct,
@@ -6420,20 +6453,40 @@
             
             self.__configurationDialog.deleteLater()
             self.__configurationDialog = None
-        
+    
+    @pyqtSlot()
     def __exportPreferences(self):
         """
         Private slot to export the current preferences.
         """
         Preferences.exportPreferences()
-        
+    
+    @pyqtSlot()
     def __importPreferences(self):
         """
         Private slot to import preferences.
         """
         Preferences.importPreferences()
         self.__preferencesChanged()
-        
+    
+    @pyqtSlot()
+    def __exportTheme(self):
+        """
+        Private slot to export the current theme to a file.
+        """
+        from Preferences.ThemeManager import ThemeManager
+        ThemeManager().exportTheme()
+    
+    @pyqtSlot()
+    def __importTheme(self):
+        """
+        Private slot to import a previously exported theme.
+        """
+        from Preferences.ThemeManager import ThemeManager
+        ThemeManager().importTheme()
+        self.__preferencesChanged()
+    
+    @pyqtSlot()
     def __preferencesChanged(self):
         """
         Private slot to handle a change of the preferences.

eric ide

mercurial