Thu, 09 Dec 2021 20:07:08 +0100
Continued implementing a manager for color themes.
--- 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.