2020-04-04 12:03:28 +00:00
|
|
|
__filename__ = "theme.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
|
|
|
__version__ = "1.1.0"
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
__email__ = "bob@freedombone.net"
|
|
|
|
__status__ = "Production"
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
|
|
import os
|
|
|
|
from utils import loadJson
|
|
|
|
from utils import saveJson
|
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
|
2020-05-28 09:11:21 +00:00
|
|
|
def getThemesList() -> []:
|
|
|
|
"""Returns the list of available themes
|
|
|
|
Note that these should be capitalized, since they're
|
|
|
|
also used to create the web interface dropdown list
|
|
|
|
and to lookup function names
|
|
|
|
"""
|
2020-05-28 12:25:56 +00:00
|
|
|
return ('Default', 'LCD', 'Light', 'Purple', 'Hacker', 'HighVis')
|
2020-05-28 09:11:21 +00:00
|
|
|
|
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
def setThemeInConfig(baseDir: str, name: str) -> bool:
|
|
|
|
configFilename = baseDir + '/config.json'
|
2019-11-23 13:04:11 +00:00
|
|
|
if not os.path.isfile(configFilename):
|
|
|
|
return False
|
2020-04-04 12:03:28 +00:00
|
|
|
configJson = loadJson(configFilename, 0)
|
2019-11-23 13:04:11 +00:00
|
|
|
if not configJson:
|
|
|
|
return False
|
2020-04-04 12:03:28 +00:00
|
|
|
configJson['theme'] = name
|
|
|
|
return saveJson(configJson, configFilename)
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
2020-05-26 20:17:16 +00:00
|
|
|
def getTheme(baseDir: str) -> str:
|
|
|
|
configFilename = baseDir + '/config.json'
|
2020-05-27 13:05:23 +00:00
|
|
|
if os.path.isfile(configFilename):
|
|
|
|
configJson = loadJson(configFilename, 0)
|
|
|
|
if configJson:
|
|
|
|
if configJson.get('theme'):
|
|
|
|
return configJson['theme']
|
2020-05-26 20:17:16 +00:00
|
|
|
return 'default'
|
|
|
|
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
def removeTheme(baseDir: str):
|
2020-04-04 12:03:28 +00:00
|
|
|
themeFiles = ('epicyon.css', 'login.css', 'follow.css',
|
|
|
|
'suspended.css', 'calendar.css', 'blog.css')
|
2019-11-23 13:04:11 +00:00
|
|
|
for filename in themeFiles:
|
2020-04-04 12:03:28 +00:00
|
|
|
if os.path.isfile(baseDir + '/' + filename):
|
|
|
|
os.remove(baseDir + '/' + filename)
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
|
|
def setThemeDefault(baseDir: str):
|
|
|
|
removeTheme(baseDir)
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeInConfig(baseDir, 'default')
|
2020-05-27 13:15:28 +00:00
|
|
|
themeParams = {
|
|
|
|
"dummyValue": "1234",
|
|
|
|
}
|
|
|
|
setThemeFromDict(baseDir, 'default', themeParams)
|
2019-11-23 13:04:11 +00:00
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
|
|
|
|
def setCSSparam(css: str, param: str, value: str) -> str:
|
2019-11-23 13:04:11 +00:00
|
|
|
"""Sets a CSS parameter to a given value
|
|
|
|
"""
|
|
|
|
# is this just a simple string replacement?
|
|
|
|
if ';' in param:
|
2020-04-04 12:03:28 +00:00
|
|
|
return css.replace(param, value)
|
2019-11-23 13:04:11 +00:00
|
|
|
# color replacement
|
|
|
|
if param.startswith('rgba('):
|
2020-04-04 12:03:28 +00:00
|
|
|
return css.replace(param, value)
|
2019-11-23 13:04:11 +00:00
|
|
|
# if the parameter begins with * then don't prepend --
|
|
|
|
if param.startswith('*'):
|
2020-04-04 12:03:28 +00:00
|
|
|
searchStr = param.replace('*', '') + ':'
|
2019-11-23 13:04:11 +00:00
|
|
|
else:
|
2020-04-04 12:03:28 +00:00
|
|
|
searchStr = '--' + param + ':'
|
2019-11-23 13:04:11 +00:00
|
|
|
if searchStr not in css:
|
|
|
|
return css
|
2020-04-04 12:03:28 +00:00
|
|
|
s = css.split(searchStr)
|
|
|
|
newcss = ''
|
2019-11-23 13:04:11 +00:00
|
|
|
for sectionStr in s:
|
|
|
|
if not newcss:
|
|
|
|
if sectionStr:
|
2020-04-04 12:03:28 +00:00
|
|
|
newcss = sectionStr
|
2019-11-23 13:04:11 +00:00
|
|
|
else:
|
2020-04-04 12:03:28 +00:00
|
|
|
newcss = ' '
|
2019-11-23 13:04:11 +00:00
|
|
|
else:
|
|
|
|
if ';' in sectionStr:
|
2020-04-04 12:03:28 +00:00
|
|
|
newcss += \
|
|
|
|
searchStr + ' ' + value + ';' + sectionStr.split(';', 1)[1]
|
2019-11-23 13:04:11 +00:00
|
|
|
else:
|
2020-04-04 12:03:28 +00:00
|
|
|
newcss += searchStr + ' ' + sectionStr
|
2019-11-23 13:04:11 +00:00
|
|
|
return newcss.strip()
|
2020-03-22 21:16:02 +00:00
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
|
2020-05-27 13:15:28 +00:00
|
|
|
def setThemeFromDict(baseDir: str, name: str, themeParams: {}) -> None:
|
2019-11-23 13:04:11 +00:00
|
|
|
"""Uses a dictionary to set a theme
|
|
|
|
"""
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeInConfig(baseDir, name)
|
|
|
|
themeFiles = ('epicyon.css', 'login.css', 'follow.css',
|
|
|
|
'suspended.css', 'calendar.css', 'blog.css')
|
2019-11-23 13:04:11 +00:00
|
|
|
for filename in themeFiles:
|
2020-04-04 12:03:28 +00:00
|
|
|
templateFilename = baseDir + '/epicyon-' + filename
|
|
|
|
if filename == 'epicyon.css':
|
|
|
|
templateFilename = baseDir + '/epicyon-profile.css'
|
2019-11-23 13:04:11 +00:00
|
|
|
if not os.path.isfile(templateFilename):
|
|
|
|
continue
|
|
|
|
with open(templateFilename, 'r') as cssfile:
|
2020-04-04 12:03:28 +00:00
|
|
|
css = cssfile.read()
|
|
|
|
for paramName, paramValue in themeParams.items():
|
|
|
|
css = setCSSparam(css, paramName, paramValue)
|
|
|
|
filename = baseDir + '/' + filename
|
2019-11-23 13:04:11 +00:00
|
|
|
with open(filename, 'w') as cssfile:
|
|
|
|
cssfile.write(css)
|
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
|
2020-05-26 20:17:16 +00:00
|
|
|
def setCustomFont(baseDir: str):
|
|
|
|
"""Uses a dictionary to set a theme
|
|
|
|
"""
|
|
|
|
customFontExt = None
|
|
|
|
customFontType = None
|
|
|
|
fontExtension = {
|
|
|
|
'woff': 'woff',
|
|
|
|
'woff2': 'woff2',
|
|
|
|
'otf': 'opentype',
|
|
|
|
'ttf': 'truetype'
|
|
|
|
}
|
|
|
|
for ext, extType in fontExtension.items():
|
|
|
|
filename = baseDir + '/fonts/custom.' + ext
|
|
|
|
if os.path.isfile(filename):
|
|
|
|
customFontExt = ext
|
|
|
|
customFontType = extType
|
|
|
|
if not customFontExt:
|
|
|
|
return
|
|
|
|
|
|
|
|
themeFiles = ('epicyon.css', 'login.css', 'follow.css',
|
|
|
|
'suspended.css', 'calendar.css', 'blog.css')
|
|
|
|
for filename in themeFiles:
|
2020-05-26 21:35:48 +00:00
|
|
|
templateFilename = baseDir + '/' + filename
|
2020-05-26 20:17:16 +00:00
|
|
|
if not os.path.isfile(templateFilename):
|
|
|
|
continue
|
|
|
|
with open(templateFilename, 'r') as cssfile:
|
|
|
|
css = cssfile.read()
|
|
|
|
css = \
|
|
|
|
setCSSparam(css, "*src",
|
|
|
|
"url('./fonts/custom." +
|
|
|
|
customFontExt +
|
|
|
|
"') format('" +
|
|
|
|
customFontType + "')")
|
2020-05-26 20:23:38 +00:00
|
|
|
css = setCSSparam(css, "*font-family", "'CustomFont'")
|
2020-05-26 20:17:16 +00:00
|
|
|
filename = baseDir + '/' + filename
|
|
|
|
with open(filename, 'w') as cssfile:
|
|
|
|
cssfile.write(css)
|
|
|
|
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
def setThemeHighVis(baseDir: str):
|
2020-04-04 12:03:28 +00:00
|
|
|
themeParams = {
|
2019-11-23 13:04:11 +00:00
|
|
|
"font-size-header": "22px",
|
|
|
|
"font-size": "45px",
|
|
|
|
"font-size2": "45px",
|
|
|
|
"font-size3": "45px",
|
|
|
|
"font-size4": "35px",
|
2019-11-28 11:02:59 +00:00
|
|
|
"font-size5": "29px",
|
|
|
|
"gallery-font-size": "35px",
|
2020-05-28 12:00:19 +00:00
|
|
|
"gallery-font-size-mobile": "55px",
|
2020-05-28 12:05:20 +00:00
|
|
|
"*font-family": "'LinBiolinum_Rah'",
|
|
|
|
"*src": "url('./fonts/LinBiolinum_Rah.ttf') format('truetype')"
|
2019-11-23 13:04:11 +00:00
|
|
|
}
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeFromDict(baseDir, 'highvis', themeParams)
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
2020-05-28 12:25:56 +00:00
|
|
|
def setThemeLCD(baseDir: str):
|
|
|
|
themeParams = {
|
|
|
|
"main-bg-color": "#9fb42b",
|
2020-05-28 13:06:07 +00:00
|
|
|
"link-bg-color": "#33390d",
|
2020-05-28 13:34:52 +00:00
|
|
|
"cw-background": "#13390d",
|
2020-05-28 13:27:25 +00:00
|
|
|
"main-bg-color-reply": "#9fb42b",
|
2020-05-28 12:25:56 +00:00
|
|
|
"main-bg-color-report": "#12152d",
|
|
|
|
"main-header-color-roles": "#1f192d",
|
|
|
|
"main-fg-color": "#33390d",
|
|
|
|
"border-color": "#33390d",
|
2020-05-28 13:27:25 +00:00
|
|
|
"border-width": "5px",
|
2020-05-28 13:06:07 +00:00
|
|
|
"main-link-color": "#9fb42b",
|
|
|
|
"main-visited-color": "#9fb42b",
|
|
|
|
"button-selected": "#01b82b",
|
|
|
|
"button-background": "#65d82b",
|
|
|
|
"button-text": "black",
|
2020-05-28 12:25:56 +00:00
|
|
|
"color: #FFFFFE;": "color: #9fb42b;",
|
|
|
|
"calendar-bg-color": "#eee",
|
|
|
|
"lines-color": "#ff42a0",
|
|
|
|
"day-number": "#3f2145",
|
|
|
|
"day-number2": "#9fb42b",
|
2020-05-28 13:06:07 +00:00
|
|
|
"time-color": "#9fb42b",
|
2020-05-28 12:25:56 +00:00
|
|
|
"place-color": "black",
|
|
|
|
"event-color": "#282c37",
|
|
|
|
"today-foreground": "white",
|
|
|
|
"today-circle": "red",
|
|
|
|
"event-background": "yellow",
|
|
|
|
"event-foreground": "white",
|
|
|
|
"title-text": "white",
|
|
|
|
"title-background": "#ff42a0",
|
|
|
|
"gallery-text-color": "#ccc",
|
|
|
|
"font-size-header": "22px",
|
|
|
|
"font-size": "45px",
|
|
|
|
"font-size2": "45px",
|
|
|
|
"font-size3": "45px",
|
|
|
|
"font-size4": "35px",
|
|
|
|
"font-size5": "29px",
|
|
|
|
"gallery-font-size": "35px",
|
|
|
|
"gallery-font-size-mobile": "55px",
|
2020-05-28 13:06:07 +00:00
|
|
|
"button-corner-radius": "1px",
|
|
|
|
"timeline-border-radius": "1px",
|
2020-05-28 12:25:56 +00:00
|
|
|
"*font-family": "'LcdSolid'",
|
|
|
|
"*src": "url('./fonts/LcdSolid.ttf') format('truetype')"
|
|
|
|
}
|
2020-05-28 13:09:28 +00:00
|
|
|
setThemeFromDict(baseDir, 'lcd', themeParams)
|
2020-05-28 12:25:56 +00:00
|
|
|
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
def setThemePurple(baseDir: str):
|
2020-04-04 12:03:28 +00:00
|
|
|
themeParams = {
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-bg-color": "#1f152d",
|
2020-05-28 13:06:07 +00:00
|
|
|
"link-bg-color": "#1f152d",
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-bg-color-reply": "#1a142d",
|
|
|
|
"main-bg-color-report": "#12152d",
|
|
|
|
"main-header-color-roles": "#1f192d",
|
|
|
|
"main-fg-color": "#f98bb0",
|
|
|
|
"border-color": "#3f2145",
|
|
|
|
"main-link-color": "#ff42a0",
|
|
|
|
"main-visited-color": "#f93bb0",
|
|
|
|
"button-selected": "#c042a0",
|
|
|
|
"button-background": "#ff42a0",
|
|
|
|
"button-text": "white",
|
2020-05-28 13:38:23 +00:00
|
|
|
"cw-background": "#ff42a0",
|
2019-11-23 13:04:11 +00:00
|
|
|
"color: #FFFFFE;": "color: #1f152d;",
|
|
|
|
"calendar-bg-color": "#eee",
|
|
|
|
"lines-color": "#ff42a0",
|
|
|
|
"day-number": "#3f2145",
|
|
|
|
"day-number2": "#1f152d",
|
2019-11-23 14:39:58 +00:00
|
|
|
"time-color": "#ff42a0",
|
2019-11-23 13:04:11 +00:00
|
|
|
"place-color": "black",
|
|
|
|
"event-color": "#282c37",
|
|
|
|
"today-foreground": "white",
|
|
|
|
"today-circle": "red",
|
|
|
|
"event-background": "yellow",
|
|
|
|
"event-foreground": "white",
|
|
|
|
"title-text": "white",
|
2019-11-28 11:02:59 +00:00
|
|
|
"title-background": "#ff42a0",
|
2020-05-28 10:14:57 +00:00
|
|
|
"gallery-text-color": "#ccc",
|
|
|
|
"*font-family": "'CheGuevaraTextSans-Regular'",
|
|
|
|
"*src": "url('./fonts/CheGuevaraTextSans-Regular.ttf') format('truetype')"
|
2019-11-23 13:04:11 +00:00
|
|
|
}
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeFromDict(baseDir, 'purple', themeParams)
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
|
|
def setThemeHacker(baseDir: str):
|
2020-04-04 12:03:28 +00:00
|
|
|
themeParams = {
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-bg-color": "black",
|
2020-05-28 13:06:07 +00:00
|
|
|
"link-bg-color": "black",
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-bg-color-reply": "#030202",
|
|
|
|
"main-bg-color-report": "#050202",
|
|
|
|
"main-header-color-roles": "#1f192d",
|
2020-05-25 18:27:45 +00:00
|
|
|
"main-fg-color": "#00ff00",
|
2020-05-25 17:38:09 +00:00
|
|
|
"border-color": "#035103",
|
2020-05-25 18:27:45 +00:00
|
|
|
"main-link-color": "#2fff2f",
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-visited-color": "#3c8234",
|
|
|
|
"button-selected": "#063200",
|
|
|
|
"button-background": "#062200",
|
2020-05-25 18:27:45 +00:00
|
|
|
"button-text": "#00ff00",
|
2019-11-23 13:04:11 +00:00
|
|
|
"button-corner-radius": "4px",
|
|
|
|
"timeline-border-radius": "4px",
|
2020-05-25 11:33:37 +00:00
|
|
|
"*font-family": "'Bedstead'",
|
2020-05-25 19:49:02 +00:00
|
|
|
"*src": "url('./fonts/bedstead.otf') format('opentype')",
|
2020-05-28 13:38:23 +00:00
|
|
|
"cw-background": "#062200",
|
2019-11-23 13:04:11 +00:00
|
|
|
"color: #FFFFFE;": "color: green;",
|
|
|
|
"calendar-bg-color": "black",
|
|
|
|
"lines-color": "green",
|
|
|
|
"day-number": "green",
|
|
|
|
"day-number2": "darkgreen",
|
|
|
|
"time-color": "darkgreen",
|
|
|
|
"place-color": "green",
|
|
|
|
"event-color": "green",
|
|
|
|
"today-foreground": "white",
|
|
|
|
"today-circle": "red",
|
|
|
|
"event-background": "lightgreen",
|
|
|
|
"event-foreground": "black",
|
|
|
|
"title-text": "black",
|
2019-11-28 11:02:59 +00:00
|
|
|
"title-background": "darkgreen",
|
|
|
|
"gallery-text-color": "green"
|
2019-11-23 13:04:11 +00:00
|
|
|
}
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeFromDict(baseDir, 'hacker', themeParams)
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
|
|
def setThemeLight(baseDir: str):
|
2020-04-04 12:03:28 +00:00
|
|
|
themeParams = {
|
2019-11-23 13:04:11 +00:00
|
|
|
"rgba(0, 0, 0, 0.5)": "rgba(0, 0, 0, 0.0)",
|
|
|
|
"main-bg-color": "#e6ebf0",
|
2020-05-28 13:06:07 +00:00
|
|
|
"link-bg-color": "#e6ebf0",
|
2019-11-23 13:04:11 +00:00
|
|
|
"main-bg-color-reply": "#e0dbf0",
|
|
|
|
"main-bg-color-report": "#e3dbf0",
|
|
|
|
"main-header-color-roles": "#ebebf0",
|
|
|
|
"main-fg-color": "#2d2c37",
|
|
|
|
"border-color": "#c0cdd9",
|
|
|
|
"main-link-color": "#2a2c37",
|
|
|
|
"main-visited-color": "#232c37",
|
|
|
|
"text-entry-foreground": "#111",
|
|
|
|
"text-entry-background": "white",
|
|
|
|
"font-color-header": "black",
|
|
|
|
"dropdown-bg-color": "white",
|
|
|
|
"dropdown-bg-color-hover": "lightgrey",
|
2020-05-28 13:38:23 +00:00
|
|
|
"cw-background": "white",
|
2019-11-23 13:04:11 +00:00
|
|
|
"color: #FFFFFE;": "color: black;",
|
|
|
|
"calendar-bg-color": "#e6ebf0",
|
|
|
|
"lines-color": "darkblue",
|
|
|
|
"day-number": "black",
|
|
|
|
"day-number2": "#282c37",
|
|
|
|
"place-color": "black",
|
|
|
|
"event-color": "#282c37",
|
|
|
|
"today-foreground": "white",
|
|
|
|
"today-circle": "red",
|
|
|
|
"event-background": "lightblue",
|
|
|
|
"event-foreground": "white",
|
|
|
|
"title-text": "#282c37",
|
2019-11-28 11:02:59 +00:00
|
|
|
"title-background": "#ccc",
|
2020-05-28 10:33:22 +00:00
|
|
|
"gallery-text-color": "black",
|
|
|
|
"*font-family": "'ElectrumADFExp-Regular'",
|
|
|
|
"*src": "url('./fonts/ElectrumADFExp-Regular.otf') format('opentype')"
|
2019-11-23 13:04:11 +00:00
|
|
|
}
|
2020-04-04 12:03:28 +00:00
|
|
|
setThemeFromDict(baseDir, 'light', themeParams)
|
|
|
|
|
2020-03-22 21:16:02 +00:00
|
|
|
|
2020-04-04 12:03:28 +00:00
|
|
|
def setTheme(baseDir: str, name: str) -> bool:
|
2020-05-26 20:17:16 +00:00
|
|
|
result = False
|
2020-05-28 09:11:21 +00:00
|
|
|
|
|
|
|
themes = getThemesList()
|
|
|
|
for themeName in themes:
|
|
|
|
if name == themeName.lower():
|
2020-05-28 09:26:30 +00:00
|
|
|
globals()['setTheme' + themeName](baseDir)
|
2020-05-28 09:11:21 +00:00
|
|
|
result = True
|
|
|
|
|
|
|
|
if not result:
|
2020-05-27 11:02:51 +00:00
|
|
|
# default
|
|
|
|
setThemeDefault(baseDir)
|
|
|
|
result = True
|
2020-05-28 09:11:21 +00:00
|
|
|
|
2020-05-26 20:17:16 +00:00
|
|
|
setCustomFont(baseDir)
|
|
|
|
return result
|