Changing version, making Helper objects globals, adding their polyfills.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
08fea34366
commit
861bb001c9
7 changed files with 77 additions and 71 deletions
|
@ -17,8 +17,8 @@
|
||||||
"""
|
"""
|
||||||
from shutil import which
|
from shutil import which
|
||||||
|
|
||||||
__VERSION__ = "0.5.0"
|
__VERSION__ = "0.5.1"
|
||||||
is_release = True
|
is_release = False
|
||||||
|
|
||||||
|
|
||||||
# Check if development version, if so get the date of the latest git patch
|
# Check if development version, if so get the date of the latest git patch
|
||||||
|
|
|
@ -112,9 +112,12 @@ def run():
|
||||||
global tmpfile
|
global tmpfile
|
||||||
helper = Helper(pwd, tmpfile)
|
helper = Helper(pwd, tmpfile)
|
||||||
latex = Latex(tempdir)
|
latex = Latex(tempdir)
|
||||||
engine.globalObject().setProperty('Runtime', engine.newObject())
|
modules = engine.newObject()
|
||||||
engine.rootContext().setContextProperty("Helper", helper)
|
engine.globalObject().setProperty('Runtime', modules)
|
||||||
engine.rootContext().setContextProperty("Latex", latex)
|
engine.globalObject().setProperty('Helper', engine.newQObject(helper))
|
||||||
|
engine.globalObject().setProperty("Latex", engine.newQObject(latex))
|
||||||
|
# engine.rootContext().setContextProperty("Helper", helper)
|
||||||
|
# engine.rootContext().setContextProperty("Latex", latex)
|
||||||
engine.rootContext().setContextProperty("TestBuild", "--test-build" in argv)
|
engine.rootContext().setContextProperty("TestBuild", "--test-build" in argv)
|
||||||
engine.rootContext().setContextProperty("StartTime", dep_time)
|
engine.rootContext().setContextProperty("StartTime", dep_time)
|
||||||
|
|
||||||
|
|
|
@ -44,16 +44,7 @@ ApplicationWindow {
|
||||||
color: sysPalette.window
|
color: sysPalette.window
|
||||||
title: "LogarithmPlotter " + (settings.saveFilename != "" ? " - " + settings.saveFilename.split('/').pop() : "") + (history.saved ? "" : "*")
|
title: "LogarithmPlotter " + (settings.saveFilename != "" ? " - " + settings.saveFilename.split('/').pop() : "") + (history.saved ? "" : "*")
|
||||||
|
|
||||||
SystemPalette {
|
SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active }
|
||||||
id: sysPalette; colorGroup: SystemPalette.Active
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
// LatexJS initialization.
|
|
||||||
Runtime.Latex.enabled = Helper.getSettingBool("enable_latex")
|
|
||||||
Runtime.Latex.Renderer = Latex
|
|
||||||
Runtime.Latex.defaultColor = sysPalette.windowText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SystemPalette { id: sysPaletteIn; colorGroup: SystemPalette.Disabled }
|
SystemPalette { id: sysPaletteIn; colorGroup: SystemPalette.Disabled }
|
||||||
|
|
||||||
menuBar: appMenu.trueItem
|
menuBar: appMenu.trueItem
|
||||||
|
|
|
@ -108,7 +108,7 @@ export class Action {
|
||||||
if(!Latex.enabled)
|
if(!Latex.enabled)
|
||||||
throw new Error("Cannot render an item as LaTeX when LaTeX is disabled.")
|
throw new Error("Cannot render an item as LaTeX when LaTeX is disabled.")
|
||||||
let imgDepth = Runtime.History.imageDepth
|
let imgDepth = Runtime.History.imageDepth
|
||||||
let [src, width, height] = Latex.Renderer.render(
|
let [src, width, height] = Latex.render(
|
||||||
latexString,
|
latexString,
|
||||||
imgDepth * (Runtime.History.fontSize + 2),
|
imgDepth * (Runtime.History.fontSize + 2),
|
||||||
Runtime.History.themeTextColor
|
Runtime.History.themeTextColor
|
||||||
|
|
|
@ -27,4 +27,29 @@ qsTr = qsTr || function(string) { throw new Error('qsTr not implemented.'); }
|
||||||
/** @type {function(string, string): string} */
|
/** @type {function(string, string): string} */
|
||||||
QT_TRANSLATE_NOOP = QT_TRANSLATE_NOOP || function(string, string) { throw new Error('QT_TRANSLATE_NOOP not implemented.'); }
|
QT_TRANSLATE_NOOP = QT_TRANSLATE_NOOP || function(string, string) { throw new Error('QT_TRANSLATE_NOOP not implemented.'); }
|
||||||
/** @type {function(string|boolean|int): string} */
|
/** @type {function(string|boolean|int): string} */
|
||||||
String.prototype.arg = String.prototype.arg || function(parameter) { throw new Error('arg not implemented.'); }
|
String.prototype.arg = String.prototype.arg || function(parameter) { throw new Error('arg not implemented.'); }
|
||||||
|
|
||||||
|
/** Typehints for Helper. */
|
||||||
|
const Helper = {
|
||||||
|
/** @type {function(string): boolean} */
|
||||||
|
getSettingBool: (setting) => true,
|
||||||
|
/** @type {function(string): int} */
|
||||||
|
getSettingInt: (setting) => 0,
|
||||||
|
/** @type {function(string): string} */
|
||||||
|
getSetting: (setting) => '',
|
||||||
|
/** @type {function(string, boolean)} */
|
||||||
|
setSettingBool: (setting, value) => {},
|
||||||
|
/** @type {function(string, int)} */
|
||||||
|
setSettingInt: (setting, value) => 0,
|
||||||
|
/** @type {function(string, string)} */
|
||||||
|
setSetting: (setting, value) => '',
|
||||||
|
/** @type {function(string, string)} */
|
||||||
|
write: (filename, data) => {},
|
||||||
|
/** @type {function(string): string} */
|
||||||
|
load: (filename) => '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const Latex = {
|
||||||
|
/** @type {function(string, number, string): string} */
|
||||||
|
render: (latex_markup, font_size, color) => '',
|
||||||
|
}
|
|
@ -50,11 +50,12 @@ class LatexAPI extends RuntimeAPI {
|
||||||
/**
|
/**
|
||||||
* true if latex has been enabled by the user, false otherwise.
|
* true if latex has been enabled by the user, false otherwise.
|
||||||
*/
|
*/
|
||||||
this.enabled = false
|
this.enabled = Helper.getSettingBool("enable_latex")
|
||||||
/**
|
/**
|
||||||
* LaTeX python backend QObject.
|
* Mirror method for Python object.
|
||||||
|
* @type {function(string, number, string): string}.
|
||||||
*/
|
*/
|
||||||
this.Renderer = null
|
this.render = Latex.render
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,17 +51,19 @@ $$$$ $markup $$$$
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
class Latex(QObject):
|
class Latex(QObject):
|
||||||
"""
|
"""
|
||||||
Base class to convert Latex equations into PNG images with custom font color and size.
|
Base class to convert Latex equations into PNG images with custom font color and size.
|
||||||
It doesn't have any python dependency, but requires a working latex installation and
|
It doesn't have any python dependency, but requires a working latex installation and
|
||||||
dvipng to be installed on the system.
|
dvipng to be installed on the system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, tempdir: TemporaryDirectory):
|
def __init__(self, tempdir: TemporaryDirectory):
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
self.tempdir = tempdir
|
self.tempdir = tempdir
|
||||||
|
|
||||||
def check_latex_install(self):
|
def check_latex_install(self):
|
||||||
"""
|
"""
|
||||||
Checks if the current latex installation is valid.
|
Checks if the current latex installation is valid.
|
||||||
|
@ -69,22 +71,23 @@ class Latex(QObject):
|
||||||
if LATEX_PATH is None:
|
if LATEX_PATH is None:
|
||||||
print("No Latex installation found.")
|
print("No Latex installation found.")
|
||||||
if "--test-build" not in argv:
|
if "--test-build" not in argv:
|
||||||
QMessageBox.warning(None, "LogarithmPlotter - Latex setup", QCoreApplication.translate("latex", "No Latex installation found.\nIf you already have a latex distribution installed, make sure it's installed on your path.\nOtherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/."))
|
QMessageBox.warning(None, "LogarithmPlotter - Latex setup",
|
||||||
|
QCoreApplication.translate("latex", "No Latex installation found.\nIf you already have a latex distribution installed, make sure it's installed on your path.\nOtherwise, you can download a Latex distribution like TeX Live at https://tug.org/texlive/."))
|
||||||
elif DVIPNG_PATH is None:
|
elif DVIPNG_PATH is None:
|
||||||
print("DVIPNG not found.")
|
print("DVIPNG not found.")
|
||||||
if "--test-build" not in argv:
|
if "--test-build" not in argv:
|
||||||
QMessageBox.warning(None, "LogarithmPlotter - Latex setup", QCoreApplication.translate("latex", "DVIPNG was not found. Make sure you include it from your Latex distribution."))
|
QMessageBox.warning(None, "LogarithmPlotter - Latex setup", QCoreApplication.translate("latex", "DVIPNG was not found. Make sure you include it from your Latex distribution."))
|
||||||
|
|
||||||
@Property(bool)
|
@Property(bool)
|
||||||
def latexSupported(self):
|
def latexSupported(self):
|
||||||
return LATEX_PATH is not None and DVIPNG_PATH is not None
|
return LATEX_PATH is not None and DVIPNG_PATH is not None
|
||||||
|
|
||||||
@Slot(str, float, QColor, result=str)
|
@Slot(str, float, QColor, result=str)
|
||||||
def render(self, latex_markup: str, font_size: float, color: QColor) -> str:
|
def render(self, latex_markup: str, font_size: float, color: QColor) -> str:
|
||||||
"""
|
"""
|
||||||
Prepares and renders a latex string into a png file.
|
Prepares and renders a latex string into a png file.
|
||||||
"""
|
"""
|
||||||
markup_hash = "render"+str(hash(latex_markup))
|
markup_hash = "render" + str(hash(latex_markup))
|
||||||
export_path = path.join(self.tempdir.name, f'{markup_hash}_{int(font_size)}_{color.rgb()}')
|
export_path = path.join(self.tempdir.name, f'{markup_hash}_{int(font_size)}_{color.rgb()}')
|
||||||
if self.latexSupported and not path.exists(export_path + ".png"):
|
if self.latexSupported and not path.exists(export_path + ".png"):
|
||||||
print("Rendering", latex_markup, export_path)
|
print("Rendering", latex_markup, export_path)
|
||||||
|
@ -101,21 +104,21 @@ class Latex(QObject):
|
||||||
# self.convert_dvi_to_png(latex_path, export_path+"@2", font_size*2, color)
|
# self.convert_dvi_to_png(latex_path, export_path+"@2", font_size*2, color)
|
||||||
# self.convert_dvi_to_png(latex_path, export_path+"@3", font_size*3, color)
|
# self.convert_dvi_to_png(latex_path, export_path+"@3", font_size*3, color)
|
||||||
# self.convert_dvi_to_png(latex_path, export_path+"@4", font_size*4, color)
|
# self.convert_dvi_to_png(latex_path, export_path+"@4", font_size*4, color)
|
||||||
except Exception as e: # One of the processes failed. A message will be sent every time.
|
except Exception as e: # One of the processes failed. A message will be sent every time.
|
||||||
raise e
|
raise e
|
||||||
img = QImage(export_path);
|
img = QImage(export_path)
|
||||||
# Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded
|
# Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded
|
||||||
return f'{export_path}.png,{img.width()},{img.height()}'
|
return f'{export_path}.png,{img.width()},{img.height()}'
|
||||||
|
|
||||||
def create_latex_doc(self, export_path: str, latex_markup: str):
|
def create_latex_doc(self, export_path: str, latex_markup: str):
|
||||||
"""
|
"""
|
||||||
Creates a temporary latex document with base file_hash as file name and a given expression markup latex_markup.
|
Creates a temporary latex document with base file_hash as file name and a given expression markup latex_markup.
|
||||||
"""
|
"""
|
||||||
ltx_path = export_path + ".tex"
|
ltx_path = export_path + ".tex"
|
||||||
f = open(export_path + ".tex", 'w')
|
f = open(export_path + ".tex", 'w')
|
||||||
f.write(DEFAULT_LATEX_DOC.substitute(markup = latex_markup))
|
f.write(DEFAULT_LATEX_DOC.substitute(markup=latex_markup))
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def convert_latex_to_dvi(self, export_path: str):
|
def convert_latex_to_dvi(self, export_path: str):
|
||||||
"""
|
"""
|
||||||
Converts a TEX file to a DVI file.
|
Converts a TEX file to a DVI file.
|
||||||
|
@ -124,7 +127,7 @@ class Latex(QObject):
|
||||||
LATEX_PATH,
|
LATEX_PATH,
|
||||||
export_path + ".tex"
|
export_path + ".tex"
|
||||||
])
|
])
|
||||||
|
|
||||||
def convert_dvi_to_png(self, dvi_path: str, export_path: str, font_size: float, color: QColor):
|
def convert_dvi_to_png(self, dvi_path: str, export_path: str, font_size: float, color: QColor):
|
||||||
"""
|
"""
|
||||||
Converts a DVI file to a PNG file.
|
Converts a DVI file to a PNG file.
|
||||||
|
@ -135,61 +138,44 @@ class Latex(QObject):
|
||||||
depth = int(font_size * 72.27 / 100) * 10
|
depth = int(font_size * 72.27 / 100) * 10
|
||||||
self.run([
|
self.run([
|
||||||
DVIPNG_PATH,
|
DVIPNG_PATH,
|
||||||
'-T', 'tight', # Make sure image borders are as tight around the equation as possible to avoid blank space.
|
'-T', 'tight', # Make sure image borders are as tight around the equation as possible to avoid blank space.
|
||||||
'--truecolor', # Make sure it's rendered in 24 bit colors.
|
'--truecolor', # Make sure it's rendered in 24 bit colors.
|
||||||
'-D',f'{depth}', # Depth of the image
|
'-D', f'{depth}', # Depth of the image
|
||||||
'-bg', 'Transparent', # Transparent background
|
'-bg', 'Transparent', # Transparent background
|
||||||
'-fg',f'{fg}', # Foreground of the wanted color.
|
'-fg', f'{fg}', # Foreground of the wanted color.
|
||||||
f'{dvi_path}.dvi', # Input file
|
f'{dvi_path}.dvi', # Input file
|
||||||
'-o',f'{export_path}.png', # Output file
|
'-o', f'{export_path}.png', # Output file
|
||||||
])
|
])
|
||||||
|
|
||||||
def run(self, process: list):
|
def run(self, process: list):
|
||||||
"""
|
"""
|
||||||
Runs a subprocess and handles exceptions and messages them to the user.
|
Runs a subprocess and handles exceptions and messages them to the user.
|
||||||
"""
|
"""
|
||||||
proc = Popen(process, stdout=PIPE, stderr=PIPE, cwd=self.tempdir.name)
|
proc = Popen(process, stdout=PIPE, stderr=PIPE, cwd=self.tempdir.name)
|
||||||
try:
|
try:
|
||||||
out, err = proc.communicate(timeout=2) # 2 seconds is already FAR too long.
|
out, err = proc.communicate(timeout=2) # 2 seconds is already FAR too long.
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
# Process errored
|
# Process errored
|
||||||
QMessageBox.warning(None, "LogarithmPlotter - Latex",
|
QMessageBox.warning(None, "LogarithmPlotter - Latex",
|
||||||
QCoreApplication.translate("latex", "An exception occured within the creation of the latex formula.\nProcess '{}' ended with a non-zero return code {}:\n\n{}\nPlease make sure your latex installation is correct and report a bug if so.")
|
QCoreApplication.translate("latex", "An exception occured within the creation of the latex formula.\nProcess '{}' ended with a non-zero return code {}:\n\n{}\nPlease make sure your latex installation is correct and report a bug if so.")
|
||||||
.format(" ".join(process), proc.returncode, str(out, 'utf8')+"\n"+str(err,'utf8')))
|
.format(" ".join(process), proc.returncode,
|
||||||
raise Exception(" ".join(process) + " process exited with return code " + str(proc.returncode) + ":\n" + str(out, 'utf8')+"\n"+str(err,'utf8'))
|
str(out, 'utf8') + "\n" + str(err, 'utf8')))
|
||||||
|
raise Exception(
|
||||||
|
" ".join(process) + " process exited with return code " + str(proc.returncode) + ":\n" + str(out,
|
||||||
|
'utf8') + "\n" + str(
|
||||||
|
err, 'utf8'))
|
||||||
except TimeoutExpired as e:
|
except TimeoutExpired as e:
|
||||||
# Process timed out
|
# Process timed out
|
||||||
proc.kill()
|
proc.kill()
|
||||||
out, err = proc.communicate()
|
out, err = proc.communicate()
|
||||||
QMessageBox.warning(None, "LogarithmPlotter - Latex",
|
QMessageBox.warning(None, "LogarithmPlotter - Latex",
|
||||||
QCoreApplication.translate("latex", "An exception occured within the creation of the latex formula.\nProcess '{}' took too long to finish:\n{}\nPlease make sure your latex installation is correct and report a bug if so.")
|
QCoreApplication.translate("latex", "An exception occured within the creation of the latex formula.\nProcess '{}' took too long to finish:\n{}\nPlease make sure your latex installation is correct and report a bug if so.")
|
||||||
.format(" ".join(process), str(out, 'utf8')+"\n"+str(err,'utf8')))
|
.format(" ".join(process), str(out, 'utf8') + "\n" + str(err, 'utf8')))
|
||||||
raise Exception(" ".join(process) + " process timed out:\n" + str(out, 'utf8')+"\n"+str(err,'utf8'))
|
raise Exception(" ".join(process) + " process timed out:\n" + str(out, 'utf8') + "\n" + str(err, 'utf8'))
|
||||||
|
|
||||||
def cleanup(self, export_path):
|
def cleanup(self, export_path):
|
||||||
"""
|
"""
|
||||||
Removes auxiliary, logs and Tex temporary files.
|
Removes auxiliary, logs and Tex temporary files.
|
||||||
"""
|
"""
|
||||||
for i in [".tex", ".aux", ".log"]:
|
for i in [".tex", ".aux", ".log"]:
|
||||||
remove(export_path + i)
|
remove(export_path + i)
|
||||||
|
|
||||||
"""
|
|
||||||
@Slot(str, float, QColor, result=str)
|
|
||||||
def render_legacy(self, latexstring, font_size, color = True):
|
|
||||||
exprpath = path.join(self.tempdir.name, f'{hash(latexstring)}_{font_size}_{color.rgb()}.png')
|
|
||||||
print("Rendering", latexstring, exprpath)
|
|
||||||
if not path.exists(exprpath):
|
|
||||||
fg = color.convertTo(QColor.Rgb)
|
|
||||||
fg = f'rgb {fg.redF()} {fg.greenF()} {fg.blueF()}'
|
|
||||||
preview('$${' + latexstring + '}$$', viewer='file', filename=exprpath, dvioptions=[
|
|
||||||
"-T", "tight",
|
|
||||||
"-z", "0",
|
|
||||||
"--truecolor",
|
|
||||||
f"-D {int(font_size * 72.27 / 100) * 10}", # See https://linux.die.net/man/1/dvipng#-D for convertion
|
|
||||||
"-bg", "Transparent",
|
|
||||||
"-fg", fg],
|
|
||||||
euler=False)
|
|
||||||
img = QImage(exprpath);
|
|
||||||
# Small hack, not very optimized since we load the image twice, but you can't pass a QImage to QML and expect it to be loaded
|
|
||||||
return f'{exprpath},{img.width()},{img.height()}'
|
|
||||||
"""
|
|
||||||
|
|
Loading…
Reference in a new issue