diff --git a/common/src/history/position.mjs b/common/src/history/position.mjs
index 4c1af60..3bf2fe8 100644
--- a/common/src/history/position.mjs
+++ b/common/src/history/position.mjs
@@ -19,7 +19,7 @@
import Objects from "../module/objects.mjs"
import Latex from "../module/latex.mjs"
import * as MathLib from "../math/index.mjs"
-import { escapeHTML } from "../utils.mjs"
+import { escapeHTML } from "../utils/index.mjs"
import { Action } from "./common.mjs"
/**
diff --git a/common/src/index.mjs b/common/src/index.mjs
index c19e2fe..9b5684c 100644
--- a/common/src/index.mjs
+++ b/common/src/index.mjs
@@ -18,10 +18,11 @@
import js from "./lib/polyfills/js.mjs"
-import * as Modules from "./module/index.mjs"
+export * as Utils from "./utils/index.mjs"
+
import * as ObjsAutoload from "./objs/autoload.mjs"
+export * as Modules from "./module/index.mjs"
export * as MathLib from "./math/index.mjs"
export * as HistoryLib from "./history/index.mjs"
export * as Parsing from "./parsing/index.mjs"
-export * as Utils from "./utils.mjs"
diff --git a/common/src/math/expression.mjs b/common/src/math/expression.mjs
index 5701ac6..7c7170b 100644
--- a/common/src/math/expression.mjs
+++ b/common/src/math/expression.mjs
@@ -17,11 +17,11 @@
*/
-import * as Utils from "../utils.mjs"
+import * as Utils from "../utils/index.mjs"
+import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs"
import Latex from "../module/latex.mjs"
import ExprParser from "../module/expreval.mjs"
import Objects from "../module/objects.mjs"
-import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs"
const NUMBER_MATCHER = /^\d*\.\d+(e[+-]\d+)?$/
diff --git a/common/src/math/sequence.mjs b/common/src/math/sequence.mjs
index 5394237..b295708 100644
--- a/common/src/math/sequence.mjs
+++ b/common/src/math/sequence.mjs
@@ -17,7 +17,7 @@
*/
import * as Expr from "./expression.mjs"
-import * as Utils from "../utils.mjs"
+import * as Utils from "../utils/index.mjs"
import Latex from "../module/latex.mjs"
import Objects from "../module/objects.mjs"
import ExprParser from "../module/expreval.mjs"
diff --git a/common/src/module/canvas.mjs b/common/src/module/canvas.mjs
index 5736cfc..dcc3f33 100644
--- a/common/src/module/canvas.mjs
+++ b/common/src/module/canvas.mjs
@@ -18,7 +18,7 @@
import { Module } from "./common.mjs"
import { CanvasInterface, DialogInterface } from "./interface.mjs"
-import { textsup } from "../utils.mjs"
+import { textsup } from "../utils/index.mjs"
import { Expression } from "../math/index.mjs"
import Latex from "./latex.mjs"
import Objects from "./objects.mjs"
diff --git a/common/src/module/latex.mjs b/common/src/module/latex.mjs
index 65ce689..3b48ebc 100644
--- a/common/src/module/latex.mjs
+++ b/common/src/module/latex.mjs
@@ -97,6 +97,7 @@ class LatexAPI extends Module {
* true if latex has been enabled by the user, false otherwise.
*/
this.enabled = false
+ this.promises = new Set()
}
/**
@@ -139,9 +140,12 @@ class LatexAPI extends Module {
if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!")
let render
if(this.#latex.supportsAsyncRender) {
- console.trace()
this.emit(new AsyncRenderStartedEvent(markup, fontSize, color))
- render = await this.#latex.renderAsync(markup, fontSize, color)
+ // Storing promise so that it does not get dereferenced.
+ const promise = this.#latex.renderAsync(markup, fontSize, color)
+ this.promises.add(promise)
+ render = await promise
+ this.promises.delete(promise)
this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color))
} else {
render = this.#latex.renderSync(markup, fontSize, color)
diff --git a/common/src/module/objects.mjs b/common/src/module/objects.mjs
index 23801be..979dba4 100644
--- a/common/src/module/objects.mjs
+++ b/common/src/module/objects.mjs
@@ -17,7 +17,7 @@
*/
import { Module } from "./common.mjs"
-import { textsub } from "../utils.mjs"
+import { textsub } from "../utils/index.mjs"
class ObjectsAPI extends Module {
diff --git a/common/src/objs/common.mjs b/common/src/objs/common.mjs
index 1534a9a..380ac5d 100644
--- a/common/src/objs/common.mjs
+++ b/common/src/objs/common.mjs
@@ -16,9 +16,9 @@
* along with this program. If not, see .
*/
-import { getRandomColor } from "../utils.mjs"
import Objects from "../module/objects.mjs"
import Latex from "../module/latex.mjs"
+import { getRandomColor } from "../utils/index.mjs"
import { ensureTypeSafety, serializesByPropertyType } from "../parameters.mjs"
// This file contains the default data to be imported from all other objects
diff --git a/common/src/objs/function.mjs b/common/src/objs/function.mjs
index b056cc3..70d0b69 100644
--- a/common/src/objs/function.mjs
+++ b/common/src/objs/function.mjs
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { textsub } from "../utils.mjs"
+import { textsub } from "../utils/index.mjs"
import Objects from "../module/objects.mjs"
import { ExecutableObject } from "./common.mjs"
import { parseDomain, Expression, SpecialDomain } from "../math/index.mjs"
diff --git a/common/src/utils.mjs b/common/src/utils/expression.mjs
similarity index 72%
rename from common/src/utils.mjs
rename to common/src/utils/expression.mjs
index 5c51f62..ef20b27 100644
--- a/common/src/utils.mjs
+++ b/common/src/utils/expression.mjs
@@ -16,151 +16,7 @@
* along with this program. If not, see .
*/
-// Add string methods
-/**
- * Replaces latin characters with their uppercase versions.
- * @return {string}
- */
-String.prototype.toLatinUppercase = function() {
- return this.replace(/[a-z]/g, function(match) {
- return match.toUpperCase()
- })
-}
-
-/**
- * Removes the first and last character of a string
- * Used to remove enclosing characters like quotes, parentheses, brackets...
- * @note Does NOT check for their existence ahead of time.
- * @return {string}
- */
-String.prototype.removeEnclosure = function() {
- return this.substring(1, this.length - 1)
-}
-
-/**
- * Rounds to a certain number of decimal places.
- * From https://stackoverflow.com/a/48764436
- *
- * @param {number} decimalPlaces
- * @return {number}
- */
-Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) {
- const p = Math.pow(10, decimalPlaces)
- const n = (this * p) * (1 + Number.EPSILON)
- return Math.round(n) / p
-}
-
-const CHARACTER_TO_POWER = new Map([
- ["-", "⁻"],
- ["+", "⁺"],
- ["=", "⁼"],
- [" ", " "],
- ["(", "⁽"],
- [")", "⁾"],
- ["0", "⁰"],
- ["1", "¹"],
- ["2", "²"],
- ["3", "³"],
- ["4", "⁴"],
- ["5", "⁵"],
- ["6", "⁶"],
- ["7", "⁷"],
- ["8", "⁸"],
- ["9", "⁹"],
- ["a", "ᵃ"],
- ["b", "ᵇ"],
- ["c", "ᶜ"],
- ["d", "ᵈ"],
- ["e", "ᵉ"],
- ["f", "ᶠ"],
- ["g", "ᵍ"],
- ["h", "ʰ"],
- ["i", "ⁱ"],
- ["j", "ʲ"],
- ["k", "ᵏ"],
- ["l", "ˡ"],
- ["m", "ᵐ"],
- ["n", "ⁿ"],
- ["o", "ᵒ"],
- ["p", "ᵖ"],
- ["r", "ʳ"],
- ["s", "ˢ"],
- ["t", "ᵗ"],
- ["u", "ᵘ"],
- ["v", "ᵛ"],
- ["w", "ʷ"],
- ["x", "ˣ"],
- ["y", "ʸ"],
- ["z", "ᶻ"]
-])
-
-const CHARACTER_TO_INDICE = new Map([
- ["-", "₋"],
- ["+", "₊"],
- ["=", "₌"],
- ["(", "₍"],
- [")", "₎"],
- [" ", " "],
- ["0", "₀"],
- ["1", "₁"],
- ["2", "₂"],
- ["3", "₃"],
- ["4", "₄"],
- ["5", "₅"],
- ["6", "₆"],
- ["7", "₇"],
- ["8", "₈"],
- ["9", "₉"],
- ["a", "ₐ"],
- ["e", "ₑ"],
- ["h", "ₕ"],
- ["i", "ᵢ"],
- ["j", "ⱼ"],
- ["k", "ₖ"],
- ["l", "ₗ"],
- ["m", "ₘ"],
- ["n", "ₙ"],
- ["o", "ₒ"],
- ["p", "ₚ"],
- ["r", "ᵣ"],
- ["s", "ₛ"],
- ["t", "ₜ"],
- ["u", "ᵤ"],
- ["v", "ᵥ"],
- ["x", "ₓ"]
-])
-
-const EXPONENTS = [
- "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
-]
-
-const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g")
-
-/**
- * Put a text in sup position
- * @param {string} text
- * @return {string}
- */
-export function textsup(text) {
- let ret = ""
- text = text.toString()
- for(let letter of text)
- ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter
- return ret
-}
-
-/**
- * Put a text in sub position
- * @param {string} text
- * @return {string}
- */
-export function textsub(text) {
- let ret = ""
- text = text.toString()
- for(let letter of text)
- ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter
- return ret
-}
+import { textsub, textsup } from "./subsup.mjs"
/**
* Simplifies (mathematically) a mathematical expression.
@@ -400,35 +256,3 @@ export function parseName(str, removeUnallowed = true) {
return str
}
-
-/**
- * Creates a randomized color string.
- * @returns {string}
- */
-export function getRandomColor() {
- let clrs = "0123456789ABCDEF"
- let color = "#"
- for(let i = 0; i < 6; i++) {
- color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))]
- }
- return color
-}
-
-/**
- * Escapes text to html entities.
- * @param {string} str
- * @returns {string}
- */
-export function escapeHTML(str) {
- return str.replace(/&/g, "&").replace(//g, ">")
-}
-
-
-/**
- * Parses exponents and replaces them with expression values
- * @param {string} expression - The expression to replace in.
- * @return {string} The parsed expression
- */
-export function exponentsToExpression(expression) {
- return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join(""))
-}
diff --git a/common/src/utils/index.mjs b/common/src/utils/index.mjs
new file mode 100644
index 0000000..02adfd6
--- /dev/null
+++ b/common/src/utils/index.mjs
@@ -0,0 +1,22 @@
+/**
+ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
+ * Copyright (C) 2021-2024 Ad5001
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+export * from "./prototype.mjs"
+export * from "./subsup.mjs"
+export * from "./expression.mjs"
+export * from "./other.mjs"
diff --git a/common/src/utils/other.mjs b/common/src/utils/other.mjs
new file mode 100644
index 0000000..bcafd6b
--- /dev/null
+++ b/common/src/utils/other.mjs
@@ -0,0 +1,41 @@
+/**
+ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
+ * Copyright (C) 2021-2024 Ad5001
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+
+
+/**
+ * Creates a randomized color string.
+ * @returns {string}
+ */
+export function getRandomColor() {
+ let clrs = "0123456789ABCDEF"
+ let color = "#"
+ for(let i = 0; i < 6; i++) {
+ color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))]
+ }
+ return color
+}
+
+/**
+ * Escapes text to html entities.
+ * @param {string} str
+ * @returns {string}
+ */
+export function escapeHTML(str) {
+ return str.replace(/&/g, "&").replace(//g, ">")
+}
diff --git a/common/src/utils/prototype.mjs b/common/src/utils/prototype.mjs
new file mode 100644
index 0000000..cb2cc15
--- /dev/null
+++ b/common/src/utils/prototype.mjs
@@ -0,0 +1,51 @@
+/**
+ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
+ * Copyright (C) 2021-2024 Ad5001
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+// Add string methods
+/**
+ * Replaces latin characters with their uppercase versions.
+ * @return {string}
+ */
+String.prototype.toLatinUppercase = function() {
+ return this.replace(/[a-z]/g, function(match) {
+ return match.toUpperCase()
+ })
+}
+
+/**
+ * Removes the first and last character of a string
+ * Used to remove enclosing characters like quotes, parentheses, brackets...
+ * @note Does NOT check for their existence ahead of time.
+ * @return {string}
+ */
+String.prototype.removeEnclosure = function() {
+ return this.substring(1, this.length - 1)
+}
+
+/**
+ * Rounds to a certain number of decimal places.
+ * From https://stackoverflow.com/a/48764436
+ *
+ * @param {number} decimalPlaces
+ * @return {number}
+ */
+Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) {
+ const p = Math.pow(10, decimalPlaces)
+ const n = (this * p) * (1 + Number.EPSILON)
+ return Math.round(n) / p
+}
diff --git a/common/src/utils/subsup.mjs b/common/src/utils/subsup.mjs
new file mode 100644
index 0000000..ff6ed50
--- /dev/null
+++ b/common/src/utils/subsup.mjs
@@ -0,0 +1,140 @@
+/**
+ * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
+ * Copyright (C) 2021-2024 Ad5001
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+const CHARACTER_TO_POWER = new Map([
+ ["-", "⁻"],
+ ["+", "⁺"],
+ ["=", "⁼"],
+ [" ", " "],
+ ["(", "⁽"],
+ [")", "⁾"],
+ ["0", "⁰"],
+ ["1", "¹"],
+ ["2", "²"],
+ ["3", "³"],
+ ["4", "⁴"],
+ ["5", "⁵"],
+ ["6", "⁶"],
+ ["7", "⁷"],
+ ["8", "⁸"],
+ ["9", "⁹"],
+ ["a", "ᵃ"],
+ ["b", "ᵇ"],
+ ["c", "ᶜ"],
+ ["d", "ᵈ"],
+ ["e", "ᵉ"],
+ ["f", "ᶠ"],
+ ["g", "ᵍ"],
+ ["h", "ʰ"],
+ ["i", "ⁱ"],
+ ["j", "ʲ"],
+ ["k", "ᵏ"],
+ ["l", "ˡ"],
+ ["m", "ᵐ"],
+ ["n", "ⁿ"],
+ ["o", "ᵒ"],
+ ["p", "ᵖ"],
+ ["r", "ʳ"],
+ ["s", "ˢ"],
+ ["t", "ᵗ"],
+ ["u", "ᵘ"],
+ ["v", "ᵛ"],
+ ["w", "ʷ"],
+ ["x", "ˣ"],
+ ["y", "ʸ"],
+ ["z", "ᶻ"]
+])
+
+const CHARACTER_TO_INDICE = new Map([
+ ["-", "₋"],
+ ["+", "₊"],
+ ["=", "₌"],
+ ["(", "₍"],
+ [")", "₎"],
+ [" ", " "],
+ ["0", "₀"],
+ ["1", "₁"],
+ ["2", "₂"],
+ ["3", "₃"],
+ ["4", "₄"],
+ ["5", "₅"],
+ ["6", "₆"],
+ ["7", "₇"],
+ ["8", "₈"],
+ ["9", "₉"],
+ ["a", "ₐ"],
+ ["e", "ₑ"],
+ ["h", "ₕ"],
+ ["i", "ᵢ"],
+ ["j", "ⱼ"],
+ ["k", "ₖ"],
+ ["l", "ₗ"],
+ ["m", "ₘ"],
+ ["n", "ₙ"],
+ ["o", "ₒ"],
+ ["p", "ₚ"],
+ ["r", "ᵣ"],
+ ["s", "ₛ"],
+ ["t", "ₜ"],
+ ["u", "ᵤ"],
+ ["v", "ᵥ"],
+ ["x", "ₓ"]
+])
+
+const EXPONENTS = [
+ "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
+]
+
+const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g")
+
+/**
+ * Put a text in sup position
+ * @param {string} text
+ * @return {string}
+ */
+export function textsup(text) {
+ let ret = ""
+ text = text.toString()
+ for(let letter of text)
+ ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter
+ return ret
+}
+
+/**
+ * Put a text in sub position
+ * @param {string} text
+ * @return {string}
+ */
+export function textsub(text) {
+ let ret = ""
+ text = text.toString()
+ for(let letter of text)
+ ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter
+ return ret
+}
+
+
+/**
+ * Parses exponents and replaces them with expression values
+ * @param {string} expression - The expression to replace in.
+ * @return {string} The parsed expression
+ */
+export function exponentsToExpression(expression) {
+ return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join(""))
+}
+
diff --git a/common/test/basics/utils.mjs b/common/test/basics/utils.mjs
index aab2cf5..42adead 100644
--- a/common/test/basics/utils.mjs
+++ b/common/test/basics/utils.mjs
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils.mjs"
+import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils/index.mjs"
import { describe, it } from "mocha"
diff --git a/common/test/math/expression.mjs b/common/test/math/expression.mjs
index a0ee113..0c15f9c 100644
--- a/common/test/math/expression.mjs
+++ b/common/test/math/expression.mjs
@@ -178,4 +178,4 @@ describe("Math/Expression", function() {
expect(() => executeExpression("x+n")).to.throw("Undefined variable n.")
})
})
-})
\ No newline at end of file
+})
diff --git a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py
index c4c16b9..8940e56 100644
--- a/runtime-pyside6/LogarithmPlotter/logarithmplotter.py
+++ b/runtime-pyside6/LogarithmPlotter/logarithmplotter.py
@@ -21,9 +21,10 @@ from platform import system as os_name, release as OS_RELEASE
from sys import path as sys_path
from sys import argv, exit
from tempfile import TemporaryDirectory
+from math import ceil
from time import time
-from PySide6.QtCore import QTranslator, QLocale
+from PySide6.QtCore import QTranslator, QLocale, QThreadPool, QThread
from PySide6.QtGui import QIcon
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtQuickControls2 import QQuickStyle
@@ -162,7 +163,11 @@ def run():
dep_time = time()
print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.")
-
+
+ # Maxing thread count to half the computer's thread count to avoid maxing CPU
+ # with too many threads (and also leaving some for rendering).
+ QThreadPool.globalInstance().setMaxThreadCount(int(ceil(QThread.idealThreadCount() / 2)))
+
register_icon_directories()
app = create_qapp()
translator = install_translation(app)
diff --git a/runtime-pyside6/LogarithmPlotter/util/promise.py b/runtime-pyside6/LogarithmPlotter/util/promise.py
index c917660..f4f21c2 100644
--- a/runtime-pyside6/LogarithmPlotter/util/promise.py
+++ b/runtime-pyside6/LogarithmPlotter/util/promise.py
@@ -22,6 +22,8 @@ from PySide6.QtQml import QJSValue
from LogarithmPlotter.util.js import PyJSValue
+NO_RETURN = [None, QJSValue.SpecialValue.UndefinedValue]
+
def check_callable(function: Callable|QJSValue) -> Callable|None:
"""
@@ -153,13 +155,12 @@ class PyPromise(QObject):
@Slot(QObject)
def _fulfill(self, data):
self._state = "fulfilled"
- no_return = [None, QJSValue.SpecialValue.UndefinedValue]
print("Finished", self._runner.args)
for i in range(len(self._fulfills)):
try:
result = self._fulfills[i](data)
result = result.qjs_value if isinstance(result, PyJSValue) else result
- data = result if result not in no_return else data # Forward data.
+ data = result if result not in NO_RETURN else data # Forward data.
except Exception as e:
self._reject(repr(e), start_at=i)
break
@@ -168,8 +169,7 @@ class PyPromise(QObject):
@Slot(str)
def _reject(self, error, start_at=0):
self._state = "rejected"
- no_return = [None, QJSValue.SpecialValue.UndefinedValue]
for i in range(start_at, len(self._rejects)):
result = self._rejects[i](error)
result = result.qjs_value if isinstance(result, PyJSValue) else result
- error = result if result not in no_return else error # Forward data.
+ error = result if result not in NO_RETURN else error # Forward data.