Coverage for modules/org/openteacher/profileRunners/websiteGenerator/websiteGenerator : 21%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
|
#! /usr/bin/env python3 # -*- coding: utf-8 -*-
# Copyright 2013, Milan Boers # Copyright 2013, 2017, Marten de Vries # # This file is part of OpenTeacher. # # OpenTeacher is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # OpenTeacher is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with OpenTeacher. If not, see <http://www.gnu.org/licenses/>.
"windows": "https://sourceforge.net/projects/openteacher/files/openteacher/3.2/openteacher-3.2-windows-setup.msi/download", "windows-portable": "https://sourceforge.net/projects/openteacher/files/openteacher/3.2/openteacher-3.2-windows-portable.zip/download", "osx": "https://sourceforge.net/projects/openteacher/files/openteacher/3.2/openteacher_3.2_mac.dmg/download", "ubuntu": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3.deb/download", "fedora": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3_fedora.rpm/download", "opensuse": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3_opensuse.rpm/download", "arch": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3_arch.pkg.tar.xz/download", "linux": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3_linux.tar.gz/download", "source": "https://sourceforge.net/projects/openteacher/files/openteacher/3.3/openteacher_3.3_linux.tar.gz/download", }
#image generators super().__init__(*args, **kwargs)
self._hue = hue
for logoPath, outputBasename in logoAndOutputNames: self._generateHoveredAndNormalButtons(logoPath, outputBasename)
gradientTopColor = QtGui.QColor.fromHsv(self._hue, 46, 246) gradientBottomColor = QtGui.QColor.fromHsv(self._hue, 58, 229) self._generateDownloadButton(gradientTopColor, gradientBottomColor, logoPath, basename + ".png")
hoveredGradientTopColor = QtGui.QColor.fromHsv(self._hue, 47, 251) hoveredGradientBottomColor = QtGui.QColor.fromHsv(self._hue, 57, 236) self._generateDownloadButton(hoveredGradientTopColor, hoveredGradientBottomColor, logoPath, basename + "-h.png")
width = 382 height = 66 radius = 9 xMargin = 9 yMargin = 10 logoHeight = 44
borderColor = QtGui.QColor.fromHsv(-1, 0, 146)
gradient = QtGui.QLinearGradient(0, 0, 0, height) gradient.setColorAt(0, gradientTopColor) gradient.setColorAt(1, gradientBottomColor)
logo = QtGui.QImage(logoPath).scaledToHeight(logoHeight, QtCore.Qt.SmoothTransformation)
img = QtGui.QImage(width, height, QtGui.QImage.Format_ARGB32_Premultiplied) img.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(img)
painter.setPen(borderColor) painter.setBrush(gradient) painter.drawRoundedRect(0, 0, width -1, height -1, radius, radius) painter.drawImage(xMargin, yMargin, logo)
painter.end() img.save(path)
super().__init__(*args, **kwargs)
self._hue = hue
"""Generates a half circle filled with a gradient to be used to show which menu item the mouse is at/which page is active.
""" width = 26 height = 13 color = QtGui.QColor.fromHsv(self._hue, 59, 240, 255)
img = QtGui.QImage(width, height, QtGui.QImage.Format_ARGB32_Premultiplied) img.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(img)
gradient = QtGui.QRadialGradient(width / 2, 0, height / 4 * 3) gradient.setColorAt(0, color) gradient.setColorAt(0.4, color) gradient.setColorAt(1, QtCore.Qt.transparent)
painter.setPen(QtCore.Qt.NoPen) painter.setBrush(gradient)
painter.drawRect(0, 0, width, height)
painter.end() img.save(path)
super().__init__(*args, **kwargs)
self._hue = hue self._generateBodyBackgroundImage = generateBodyBackgroundImage
"""Generates the background file: a small bug high file with nothing but a gradient inside.
""" width = 1 height = 1000 startColor = QtGui.QColor.fromHsv(self._hue, 43, 250) endColor = QtGui.QColor.fromHsv(self._hue, 21, 227)
img = QtGui.QImage(width, height, QtGui.QImage.Format_ARGB32_Premultiplied) img.fill(QtCore.Qt.transparent)
gradient = QtGui.QLinearGradient(0, 0, 0, height) gradient.setColorAt(0, startColor) gradient.setColorAt(1, endColor)
painter = QtGui.QPainter(img) painter.setBrush(gradient) painter.setPen(QtCore.Qt.NoPen) painter.drawRect(0, 0, width, height) painter.end() img.save(path)
img = self._generateBodyBackgroundImage()
#and save it. img.save(path)
#style sheet super().__init__(*args, **kwargs)
self._hue = hue self._lineColor = lineColor self._template = template
"""Generates the style sheet of OpenTeacher using ``self._hue`` (which comes from metadata) for the colors.
""" t = pyratemp.Template(filename=self._template) with open(path, "w", encoding='UTF-8') as f: f.write(t(**{ "aLinkColor": QtGui.QColor.fromHsv(self._hue, 63, 101).name(), "aHoverColor": QtGui.QColor.fromHsv(self._hue, 66, 159).name(), "bodyBackgroundColor": QtGui.QColor.fromHsv(self._hue, 30, 228).name(), "bodyTextColor": QtGui.QColor.fromHsv(self._hue, 64, 64).name(), "hrColor": self._lineColor, "downloadTableBorderColor": self._lineColor, "downloadRowBackgroundColor": QtGui.QColor.fromHsv(self._hue, 27, 234).name(), "downloadRowBorderColor": self._lineColor, "codeBlockBackgroundColor": QtGui.QColor.fromHsv(self._hue, 21, 240).name(), }))
self._mm.mods(type="execute"), self._mm.mods(type="ui"), self._mm.mods(type="metadata"), self._mm.mods(type="userDocumentation"), self._mm.mods(type="userDocumentationWrapper"), self._mm.mods(type="backgroundImageGenerator"), self._mm.mods(type="friendlyTranslationNames"), ) self._mm.mods(type="translator"), )
"generate-website": 0, "default": -1, }
for path in self._tempPaths: shutil.rmtree(path)
"""Generates the complete OT website into a directory specified as the first command line argument.
""" self._path = self._makeOutputDir() if not self._path: return
self._copyResources() self._generateResources() self._generateHtml()
print("Writing OpenTeacher website to '%s' is now done." % self._path)
"""Gets the output directory name and creates it. Asks if overwriting it is allowed in case that's needed. Returns True on success, otherwise False.
""" #get path to save to try: path = sys.argv[1] except IndexError: print("Please specify a path to save the website to. (e.g. -p generate-website website-debug)", file=sys.stderr) return #ask if overwrite if os.path.exists(path): confirm = input("There is already a directory at '%s'. Do you want to remove it and continue (y/n). " % path) if confirm != "y": return shutil.rmtree(path)
os.mkdir(path) return path
def _userDocMod(self): return self._modules.default("active", type="userDocumentation")
def _userDocWrapperMod(self): return self._modules.default("active", type="userDocumentationWrapper")
"""Copies all static website resources into place."""
copyTree = lambda name: shutil.copytree( self._mm.resourcePath(name), os.path.join(self._path, name) ) copy = lambda name: shutil.copy( self._mm.resourcePath(name), os.path.join(self._path, name) ) # Copy images, scripts etc. copyTree("images") copyTree("scripts") copyTree("inAppDocs") copyTree("files") copy("index.php") copy("documentation.html")
#Copy user documentation's static files shutil.copytree( self._userDocMod.resourcesPath, os.path.join(self._path, "images/docs/3"), )
"""Generates a few resources."""
toPath = lambda part: os.path.join(self._path, part) fromPath = lambda part: self._mm.resourcePath(os.path.join("images/oslogos/", part))
#stylesheet style = StyleSheet(self._hue, self._lineColor, template=self._mm.resourcePath("style.css")) style.save(toPath("style.css")) #images bgGenerator = BackgroundImagesGenerator(self._hue, self._modules.default("active", type="backgroundImageGenerator").generate) bgGenerator.generateBackground(toPath("images/bg.png")) bgGenerator.generateBodyBackground(toPath("images/body.png")) LightImage(self._hue).save(toPath("images/light.png")) #button backgrounds (which include logos) os.mkdir(toPath('images/downloadbuttons')) ButtonImagesGenerator(self._hue).generateButtons([ (fromPath("fedoralogo.png"), toPath("images/downloadbuttons/fedora-button")), (fromPath("tuxlogo.png"), toPath("images/downloadbuttons/linux-button")), (fromPath("osxlogo.png"), toPath("images/downloadbuttons/osx-button")), (fromPath("ubulogo.png"), toPath("images/downloadbuttons/ubuntu-button")), (fromPath("winlogo.png"), toPath("images/downloadbuttons/windows-button")), ]) #icon shutil.copy(self._iconPath, toPath("images/openteacher-icon.png"))
"""Generates all html files: first for US English and then for all the available translations. If that's done, it generates the in app documentation pages (that are in a separate directory).
""" # The default (US English) (str as translate function) self._tr = str self._langCode = "en" self._generatePages()
try: translator = self._modules.default("active", type="translator") except IndexError: pass else: # All the other languages for moname in os.listdir(self._mm.resourcePath('translations')): if not moname.endswith('.mo'): continue self._langCode = os.path.splitext(moname)[0]
# Set translation function _, ngettext = translator.gettextFunctions(self._mm.resourcePath("translations"), language=self._langCode) self._tr = _
# Generate self._generatePages()
# Generate inAppDocumentation pages. for lang in list(self._userDocMod.availableTranslations) + ["en"]: destination = os.path.join(self._path, "inAppDocs", lang + ".html") html = self._getWrappedUserDocumentation(lang) with open(destination, "w", encoding='UTF-8') as f: f.write(html)
"""Generates all pages in a certain language in a subdirectory of the main output path. First it generates the normal pages, then the documentation ones.
""" self._langDir = os.path.join(self._path, self._langCode) os.mkdir(self._langDir)
templates = ["about.html", "news.html", "download.html", "documentation.html", "index.html", "contribute.html"] for pageName in templates: self._generatePage(pageName)
docsDir = os.path.join(self._langDir, "documentation") os.mkdir(docsDir) documentationTemplatePaths = [ os.path.join(self._docsTemplatesDir, f) for f in os.listdir(self._docsTemplatesDir) ] documentationTemplatePaths.append(self._getUsingOpenTeacher3Path()) for filename in documentationTemplatePaths: self._generateDocumentationPage(filename)
path = tempfile.mkdtemp() #make sure it's cleaned up... self._tempPaths.append(path)
filePath = os.path.join(path, "using-openteacher-3.html") html = self._userDocMod.getHtml("../images/docs/3", self._langCode) with open(filePath, "w", encoding="UTF-8") as f: f.write(html) return filePath
html = self._userDocMod.getHtml("../images/docs/3", lang) return self._userDocWrapperMod.wrap(html)
"""Combines the documentation text, with the stuff shared between all documentation pages, and wraps the result in a page.
""" #the documentation text pageName = "documentation/" + os.path.basename(templatePath) docContent = self._evaluateTemplate(templatePath, pageName)
#the documentation wrapper templatePath = os.path.join(self._templatesDir, "docpage.html") content = self._evaluateTemplate(templatePath, pageName, docContent=docContent)
self._writePage(pageName, content)
"""Gets the content of the page, and writes it into a page."""
filename = os.path.join(self._templatesDir, pageName) content = self._evaluateTemplate(filename, pageName, downloadLinks=DOWNLOAD_LINKS, newsFeedUrl=self._newsFeedUrl, version=self._version)
self._writePage(pageName, content)
"""Wraps content into a page template and writes the result to disk
""" #write content file (used by ajax) with open(os.path.join(self._langDir, os.path.splitext(pageName)[0] + ".contentonly.html"), "w", encoding='UTF-8') as f: f.write(content) page = self._wrapContent(pageName, content)
#write html file (used on first page load) with open(os.path.join(self._langDir, pageName), "w", encoding="UTF-8") as f: f.write(page)
if not cache: translationNames = self._modules.default("active", type="friendlyTranslationNames").friendlyNames
cache["en"] = translationNames["C"] for mofile in glob.glob(self._mm.resourcePath("translations/*.mo")): name = os.path.splitext(os.path.basename(mofile))[0] cache[name] = translationNames.get(name, name) return cache
"""Wraps content into a page template"""
filename = os.path.join(self._templatesDir, "base.html") pageName = os.path.splitext(pageName)[0] return self._evaluateTemplate(filename, pageName, pageName=pageName, currentLanguage=self._langCode, languages=self._languages, content=content, downloadLinksJson=json.dumps(DOWNLOAD_LINKS) )
class EvalPseudoSandbox(pyratemp.EvalPseudoSandbox): def __init__(self2, *args, **kwargs): pyratemp.EvalPseudoSandbox.__init__(self2, *args, **kwargs) self2.register("tr", self._tr) currentDir = os.path.dirname(thisPage) self2.register("url", lambda name: posixpath.relpath(name, currentDir))
t = pyratemp.Template(filename=templatePath, eval_class=EvalPseudoSandbox) return t(**kwargs)
global pyratemp, QtCore, QtGui try: import pyratemp from PyQt5 import QtCore, QtGui except ImportError: sys.stderr.write("For this developer module to work, you need to have pyratemp & PyQt5 installed.\n")
self._modules = next(iter(self._mm.mods(type="modules"))) self._modules.default(type="execute").startRunning.handle(self.generateWebsite)
metadata = self._modules.default("active", type="metadata").metadata self._iconPath = metadata["iconPath"] self._hue = metadata["mainColorHue"] self._newsFeedUrl = metadata["newsFeedUrl"] self._version = metadata["version"] self._lineColor = self._modules.default("active", type="backgroundImageGenerator").lineColor
self.active = True
self.active = False
del self._modules del self._iconPath del self._hue del self._newsFeedUrl del self._version del self._lineColor
|