epicyon/theme.py

453 lines
15 KiB
Python
Raw Normal View History

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-05-28 21:30:40 +00:00
from shutil import copyfile
2019-11-23 13:04:11 +00:00
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-29 15:19:45 +00:00
return ('Default', 'Blue', 'Hacker', 'HighVis',
2020-05-29 16:20:41 +00:00
'LCD', 'Light', 'Purple', 'Zen')
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
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:
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 + "')")
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)
2020-05-29 10:00:05 +00:00
def setThemeDefault(baseDir: str):
removeTheme(baseDir)
setThemeInConfig(baseDir, 'default')
themeParams = {
"dummyValue": "1234"
}
setThemeFromDict(baseDir, 'default', themeParams)
def setThemeBlue(baseDir: str):
removeTheme(baseDir)
setThemeInConfig(baseDir, 'blue')
themeParams = {
2020-05-29 10:11:02 +00:00
"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-29 10:00:05 +00:00
"main-bg-color": "#002365",
"text-entry-background": "#002365",
2020-05-29 10:08:56 +00:00
"link-bg-color": "#002365",
2020-05-29 10:00:05 +00:00
"main-bg-color-reply": "#002365",
"main-bg-color-report": "#002365",
"day-number2": "#002365",
"*font-family": "'Domestic_Manners'",
"*src": "url('./fonts/Domestic_Manners.ttf') format('truetype')"
}
setThemeFromDict(baseDir, 'blue', themeParams)
2020-05-29 16:20:41 +00:00
def setThemeZen(baseDir: str):
removeTheme(baseDir)
setThemeInConfig(baseDir, 'zen')
themeParams = {
"main-bg-color": "#5c4e41",
"text-entry-background": "#5c4e41",
"link-bg-color": "#5c4e41",
"main-bg-color-reply": "#5c4e41",
"main-bg-color-report": "#5c4e41",
2020-05-29 16:52:53 +00:00
"day-number2": "#5c4e41",
"border-color": "#463b35",
"border-width": "7px",
"main-link-color": "#dddddd",
2020-05-29 17:53:51 +00:00
"main-visited-color": "#dddddd",
"button-background": "#463b35",
"button-selected": "#26201d",
"main-bg-color-dm": "#5c4a40",
"main-header-color-roles": "#5c4e41",
2020-05-29 17:56:47 +00:00
"cw-background": "#463b35",
"dropdown-bg-color": "#463b35"
2020-05-29 16:20:41 +00:00
}
setThemeFromDict(baseDir, 'zen', themeParams)
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 14:39:26 +00:00
"text-entry-foreground": "#33390d",
"text-entry-background": "#9fb42b",
2020-05-28 13:27:25 +00:00
"main-bg-color-reply": "#9fb42b",
2020-05-28 20:04:37 +00:00
"main-bg-color-report": "#9fb42b",
2020-05-28 14:39:26 +00:00
"main-bg-color-dm": "#5fb42b",
2020-05-28 20:04:37 +00:00
"main-header-color-roles": "#9fb42b",
2020-05-28 12:25:56 +00:00
"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",
2020-05-28 17:27:16 +00:00
"button-selected": "black",
"button-highlighted": "green",
"button-background": "#33390d",
"button-text": "#9fb42b",
2020-05-28 12:25:56 +00:00
"color: #FFFFFE;": "color: #9fb42b;",
"calendar-bg-color": "#eee",
"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",
2020-05-28 21:30:40 +00:00
"gallery-text-color": "#33390d",
2020-05-28 12:25:56 +00:00
"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 16:16:11 +00:00
"dropdown-bg-color": "#33390d",
2020-05-28 16:26:53 +00:00
"dropdown-bg-color-hover": "#7fb42b",
"dropdown-fg-color-hover": "black",
2020-05-28 16:16:11 +00:00
"dropdown-fg-color": "#9fb42b",
2020-05-28 20:04:37 +00:00
"font-color-header": "#9fb42b",
"lines-color": "#33390d",
"title-background": "#33390d",
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-05-28 21:30:40 +00:00
fontStr = \
"url('./fonts/CheGuevaraTextSans-Regular.ttf') format('truetype')"
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'",
2020-05-28 21:30:40 +00:00
"*src": fontStr
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-29 21:15:11 +00:00
"main-bg-color-dm": "#e3dbf0",
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",
2020-05-29 21:08:24 +00:00
"dropdown-fg-color": "#222",
"dropdown-fg-color-hover": "#222",
2019-11-23 13:04:11 +00:00
"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-05-28 21:39:41 +00:00
def setThemeImages(baseDir: str, name: str) -> None:
"""Changes the profile background image
and banner to the defaults
"""
themeNameLower = name.lower()
if themeNameLower == 'default':
profileImageFilename = \
baseDir + '/img/image.png'
bannerFilename = \
baseDir + '/img/banner.png'
else:
profileImageFilename = \
baseDir + '/img/image_' + themeNameLower + '.png'
bannerFilename = \
baseDir + '/img/banner_' + themeNameLower + '.png'
if os.path.isfile(profileImageFilename) and \
os.path.isfile(bannerFilename):
for subdir, dirs, files in os.walk(baseDir +
'/accounts'):
for acct in dirs:
if '@' not in acct:
continue
if 'inbox@' in acct:
continue
accountDir = \
os.path.join(baseDir + '/accounts', acct)
try:
copyfile(profileImageFilename,
accountDir + '/image.png')
copyfile(bannerFilename,
accountDir + '/banner.png')
except BaseException:
pass
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
2020-05-28 21:30:40 +00:00
prevThemeName = getTheme(baseDir)
2020-05-28 09:11:21 +00:00
themes = getThemesList()
for themeName in themes:
2020-05-28 21:30:40 +00:00
themeNameLower = themeName.lower()
if name == themeNameLower:
2020-05-28 09:26:30 +00:00
globals()['setTheme' + themeName](baseDir)
2020-05-28 21:30:40 +00:00
if prevThemeName:
if prevThemeName.lower() != themeNameLower:
# change the banner and profile image
# to the default for the theme
2020-05-28 21:39:41 +00:00
setThemeImages(baseDir, name)
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