Compare commits

..

No commits in common. "727dda26235ecb57829d97667e2305610b5185bf" and "8da10497d232c38bcf0805308028c19449530f50" have entirely different histories.

31 changed files with 72 additions and 245 deletions

View file

@ -22,7 +22,7 @@ import { babel } from "@rollup/plugin-babel"
import cleanup from "rollup-plugin-cleanup"
const src = "./src/index.mjs"
const dest = "../build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Common/index.mjs"
const dest = "../build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/index.mjs"
export default {
input: src,

View file

@ -95,15 +95,11 @@ export class Action {
if(!Latex.enabled)
throw new Error("Cannot render an item as LaTeX when LaTeX is disabled.")
const imgDepth = History.imageDepth
const renderArguments = [
const { source, width, height } = await Latex.requestAsyncRender(
latexString,
imgDepth * (History.fontSize + 2),
History.themeTextColor
]
let render = Latex.findPrerendered(...renderArguments)
if(render === null)
render = await Latex.requestAsyncRender(...renderArguments)
const { source, width, height } = render
)
return `<img src="${source}" width="${width / imgDepth}" height="${height / imgDepth}" style="vertical-align: middle"/>`
}

View file

@ -25,10 +25,7 @@ import Objects from "./objects.mjs"
import History from "./history.mjs"
import Settings from "./settings.mjs"
class CanvasAPI extends Module {
/** @type {CanvasInterface} */
#canvas = null
/** @type {CanvasRenderingContext2D} */

View file

@ -17,7 +17,6 @@
*/
import { Module } from "./common.mjs"
import { BaseEvent } from "../events.mjs"
import * as Instruction from "../lib/expr-eval/instruction.mjs"
import { escapeValue } from "../lib/expr-eval/expression.mjs"
import { HelperInterface, LatexInterface } from "./interface.mjs"
@ -45,28 +44,6 @@ const equivalchars = ["\\pi", "\\infty",
"{}_{4}", "{}_{5}", "{}_{6}", "{}_{7}", "{}_{8}", "{}_{9}", "{}_{0}",
]
class AsyncRenderStartedEvent extends BaseEvent {
constructor(markup, fontSize, color) {
super("async-render-started")
this.markup = markup
this.fontSize = fontSize
this.color = color
}
}
class AsyncRenderFinishedEvent extends BaseEvent {
constructor(markup, fontSize, color) {
super("async-render-finished")
this.markup = markup
this.fontSize = fontSize
this.color = color
}
}
/**
* Class containing the result of a LaTeX render.
*
@ -83,8 +60,6 @@ class LatexRenderResult {
}
class LatexAPI extends Module {
static emits = ["async-render-started", "async-render-finished"]
/** @type {LatexInterface} */
#latex = null
@ -138,14 +113,10 @@ class LatexAPI extends Module {
async requestAsyncRender(markup, fontSize, color) {
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))
if(this.#latex.supportsAsyncRender)
render = await this.#latex.renderAsync(markup, fontSize, color)
this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color))
} else {
else
render = this.#latex.renderSync(markup, fontSize, color)
}
const args = render.split(",")
return new LatexRenderResult(...args)
}

View file

@ -122,9 +122,7 @@ export default class Function extends ExecutableObject {
*/
static drawFunction(canvas, expr, definitionDomain, destinationDomain, drawPoints = true, drawDash = true) {
let pxprecision = 10
const startDrawFrom = canvas.x2px(1)%pxprecision-pxprecision
let previousX = canvas.px2x(startDrawFrom)
// console.log("Starting draw from", previousX, startDrawFrom, canvas.x2px(1))
let previousX = canvas.px2x(0)
let previousY = null
if(definitionDomain instanceof SpecialDomain && definitionDomain.moveSupported) {
// Point based functions.
@ -162,7 +160,7 @@ export default class Function extends ExecutableObject {
// Calculate the previousY at the start of the canvas
if(definitionDomain.includes(previousX))
previousY = expr.execute(previousX)
for(let px = pxprecision; px-pxprecision < canvas.width; px += pxprecision) {
for(let px = pxprecision; px < canvas.width; px += pxprecision) {
let currentX = canvas.px2x(px)
if(!definitionDomain.includes(previousX) && definitionDomain.includes(currentX)) {
// Should draw up to currentX, but NOT at previousX.
@ -171,7 +169,7 @@ export default class Function extends ExecutableObject {
do {
tmpPx++
previousX = canvas.px2x(tmpPx)
} while(!definitionDomain.includes(previousX) && currentX > previousX)
} while(!definitionDomain.includes(previousX))
// Recaclulate previousY
previousY = expr.execute(previousX)
} else if(!definitionDomain.includes(currentX)) {
@ -181,7 +179,7 @@ export default class Function extends ExecutableObject {
do {
tmpPx--
currentX = canvas.px2x(tmpPx)
} while(!definitionDomain.includes(currentX) && currentX > previousX)
} while(!definitionDomain.includes(currentX) && currentX !== previousX)
}
// This max variation is needed for functions with asymptotical vertical lines (e.g. 1/x, tan x...)
let maxvariation = (canvas.px2y(0) - canvas.px2y(canvas.height))

View file

@ -47,8 +47,8 @@ class EnableLatex extends BoolSetting {
}
const ENABLE_LATEX_ASYNC = new BoolSetting(
qsTranslate("general", "Enable threaded LaTeX renderer (experimental)"),
"enable_latex_threaded",
qsTranslate("general", "Enable asynchronous LaTeX renderer"),
"enable_latex_async",
"new"
)

View file

@ -23,7 +23,7 @@ const DEFAULT_SETTINGS = {
"reset_redo_stack": true,
"last_install_greet": "0",
"enable_latex": true,
"enable_latex_threaded": true,
"enable_latex_async": true,
"expression_editor": {
"autoclose": true,
"colorize": true,
@ -113,4 +113,4 @@ export class MockHelper {
throw new Error(`File not found.`)
}
}
}

View file

@ -20,7 +20,7 @@ import QtQuick
import Qt.labs.platform as Native
//import QtQuick.Controls 2.15
import eu.ad5001.MixedMenu 1.1
import eu.ad5001.LogarithmPlotter.Common
import "js/index.mjs" as JS
/*!

View file

@ -1,3 +0,0 @@
module eu.ad5001.LogarithmPlotter.Common
JS 1.0 index.mjs

View file

@ -24,7 +24,7 @@ import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
/*!
\qmltype Browser
\qmltype HistoryBrowser
\inqmlmodule eu.ad5001.LogarithmPlotter.History
\brief Tab of the drawer that allows to navigate through the undo and redo history.
@ -95,7 +95,7 @@ Item {
Repeater {
model: historyBrowser.redoCount
SingleItem {
HistoryItem {
id: redoButton
width: historyBrowser.actionWidth
//height: actionHeight
@ -147,7 +147,7 @@ Item {
model: historyBrowser.undoCount
SingleItem {
HistoryItem {
id: undoButton
width: historyBrowser.actionWidth
//height: actionHeight

View file

@ -22,7 +22,7 @@ import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
/*!
\qmltype SingleItem
\qmltype HistoryItem
\inqmlmodule eu.ad5001.LogarithmPlotter.History
\brief Item representing an history action.

View file

@ -1,4 +1,4 @@
module eu.ad5001.LogarithmPlotter.History
Browser 1.0 Browser.qml
SingleItem 1.0 SingleItem.qml
HistoryBrowser 1.0 HistoryBrowser.qml
HistoryItem 1.0 HistoryItem.qml

View file

@ -17,17 +17,16 @@
*/
import QtQml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts 1.12
import eu.ad5001.MixedMenu 1.1
import QtQuick.Layouts 1.12
import QtQuick
// Auto loading all modules.
import eu.ad5001.LogarithmPlotter.Common
import "js/index.mjs" as JS
import eu.ad5001.LogarithmPlotter.History 1.0 as History
import eu.ad5001.LogarithmPlotter.History 1.0
import eu.ad5001.LogarithmPlotter.ObjectLists 1.0
import eu.ad5001.LogarithmPlotter.Overlay 1.0 as Overlay
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
/*!
@ -121,16 +120,16 @@ ApplicationWindow {
ObjectLists {
id: objectLists
onChanged: Modules.Canvas.requestPaint()
onChanged: drawCanvas.requestPaint()
}
Settings {
id: settings
canvas: drawCanvas
onChanged: Modules.Canvas.requestPaint()
onChanged: drawCanvas.requestPaint()
}
History.Browser {
HistoryBrowser {
id: historyBrowser
}
}
@ -155,21 +154,19 @@ ApplicationWindow {
}
}
Overlay.ViewPositionChange {
ViewPositionChangeOverlay {
id: viewPositionChanger
anchors.fill: parent
canvas: parent
settingsInstance: settings
}
Overlay.PickLocation {
PickLocationOverlay {
id: positionPicker
anchors.fill: parent
canvas: parent
}
}
Overlay.Loading {
id: loadingOverlay
anchors.fill: parent
}
Timer {
id: delayRefreshTimer

View file

@ -20,7 +20,7 @@ import QtQuick
import QtQuick.Controls
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Common
import "../../js/index.mjs" as JS
/*!
\qmltype CustomPropertyList

View file

@ -18,10 +18,11 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Dialogs as D
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
import eu.ad5001.LogarithmPlotter.Common
import "../../js/index.mjs" as JS
/*!
\qmltype Dialog

View file

@ -19,7 +19,7 @@
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Common
import "../js/index.mjs" as JS
/*!

View file

@ -56,7 +56,7 @@ ScrollView {
property var editingRows: []
model: Modules.Objects.currentObjects[objType]
width: objectsListView.width
height: contentItem.childrenRect.height + 10
implicitHeight: contentItem.childrenRect.height
visible: model != undefined && model.length > 0
interactive: false

View file

@ -21,7 +21,7 @@ import QtQuick.Dialogs
import QtQuick.Controls
import QtQuick.Window
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Common
import "../js/index.mjs" as JS
/*!

View file

@ -1,130 +0,0 @@
/**
* 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
/*!
\qmltype Loading
\inqmlmodule eu.ad5001.LogarithmPlotter.Overlay
\brief Overlay notifiying the user when a file is loading.
Provides an overlay over the canvas that is shown when the user loads a new file, both to lock the ViewPositionChange
overlay and inform the user of what is loading and how much remains.
\sa Common, ViewPositionChange
*/
Item {
id: loadingRoot
opacity: 0
visible: opacity !== 0
clip: true
property int currentlyLoading: 0
property int maxCurrentLoadingSteps: 0
Behavior on opacity { PropertyAnimation {} }
Rectangle {
anchors.fill: parent
color: sysPalette.window
opacity: 0.85
}
Column {
spacing: 5
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
right: parent.right
}
Text {
id: loadingTitle
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 20
color: sysPalette.windowText
}
ProgressBar {
id: progress
anchors.horizontalCenter: parent.horizontalCenter
width: 300
from: 0
value: loadingRoot.maxCurrentLoadingSteps - loadingRoot.currentlyLoading
to: loadingRoot.maxCurrentLoadingSteps
}
Text {
id: lastFinishedStep
anchors.horizontalCenter: parent.horizontalCenter
color: sysPalette.windowText
}
}
MouseArea {
id: picker
anchors.fill: parent
hoverEnabled: parent.visible
cursorShape: Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
}
/*!
\qmlmethod void Loading::addedLoadingStep()
Registers one new loading step that will eventually call \c finishedLoadingStep.
*/
function addedLoadingStep() {
if(loadingRoot.maxCurrentLoadingSteps === 1) {
// Only when several ones need to be loaded.
const fileName = Modules.Settings.saveFilename.split('/').pop().split('\\').pop()
loadingTitle.text = qsTr("Loading...")
loadingRoot.opacity = 1
}
loadingRoot.currentlyLoading++
loadingRoot.maxCurrentLoadingSteps++
}
/*!
\qmlmethod void Loading::finishedLoadingStep()
Marks a loading step as finished and displays the message to the user.
*/
function finishedLoadingStep(message) {
loadingRoot.currentlyLoading--
const current = loadingRoot.maxCurrentLoadingSteps - loadingRoot.currentlyLoading
lastFinishedStep.text = `${message} (${current}/${loadingRoot.maxCurrentLoadingSteps})`
if(loadingRoot.currentlyLoading === 0) {
loadingRoot.maxCurrentLoadingSteps = 0
loadingRoot.opacity = 0
}
}
Component.onCompleted: function() {
Modules.Latex.on("async-render-started", (e) => {
addedLoadingStep()
})
Modules.Latex.on("async-render-finished", (e) => {
const markup = e.markup.length > 20 ? e.markup.substring(0, 15)+"..." : e.markup
finishedLoadingStep(qsTr("Finished rendering of %1").arg(markup))
})
}
}

View file

@ -1,5 +0,0 @@
module eu.ad5001.LogarithmPlotter.Overlay
Loading 1.0 Loading.qml
PickLocation 1.0 PickLocation.qml
ViewPositionChange 1.0 ViewPositionChange.qml

View file

@ -18,12 +18,12 @@
import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting as Setting
import eu.ad5001.LogarithmPlotter.Common
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "js/index.mjs" as JS
/*!
\qmltype PickLocation
\inqmlmodule eu.ad5001.LogarithmPlotter.Overlay
\qmltype PickLocationOverlay
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Overlay used to pick a new location for an object.
Provides an overlay over the canvas that can be shown when the user clicks the "Set position" button
@ -36,7 +36,7 @@ Item {
id: pickerRoot
visible: false
clip: true
/*!
\qmlsignal PickLocationOverlay::picked(var obj)
@ -97,9 +97,9 @@ Item {
readonly property bool userPickY: pickY && pickYCheckbox.checked
Rectangle {
anchors.fill: parent
color: sysPalette.window
opacity: 0.35
anchors.fill: parent
}
MouseArea {

View file

@ -20,7 +20,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Common
import "../js/index.mjs" as JS
/*!
\qmltype Preferences

View file

@ -20,7 +20,7 @@ import QtQuick.Controls
import QtQuick
import Qt.labs.platform as Native
import eu.ad5001.LogarithmPlotter.Popup 1.0 as P
import eu.ad5001.LogarithmPlotter.Common
import "../js/index.mjs" as JS
/*!

View file

@ -20,7 +20,7 @@ import QtQuick
import QtQuick.Controls
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import eu.ad5001.LogarithmPlotter.Popup 1.0 as Popup
import eu.ad5001.LogarithmPlotter.Common
import "js/index.mjs" as JS
/*!
\qmltype Settings

View file

@ -19,7 +19,7 @@
import QtQuick
/*!
\qmltype ViewPositionChange.Overlay
\qmltype ViewPositionChangeOverlay
\inqmlmodule eu.ad5001.LogarithmPlotter
\brief Overlay used allow the user to drag the canvas' position and change the zoom level.
@ -57,6 +57,16 @@ Item {
*/
signal endPositionChange(int deltaX, int deltaY)
/*!
\qmlproperty var ViewPositionChangeOverlay::canvas
LogGraphCanvas instance.
*/
property var canvas
/*!
\qmlproperty var ViewPositionChangeOverlay::settingsInstance
Settings instance.
*/
property var settingsInstance
/*!
\qmlproperty int ViewPositionChangeOverlay::prevX
The x coordinate (on the mousearea) at the last change of the canvas position.

View file

@ -2,4 +2,6 @@ module eu.ad5001.LogarithmPlotter
AppMenuBar 1.0 AppMenuBar.qml
LogGraphCanvas 1.0 LogGraphCanvas.qml
PickLocationOverlay 1.0 PickLocationOverlay.qml
Settings 1.0 Settings.qml
ViewPositionChangeOverlay 1.0 ViewPositionChangeOverlay.qml

View file

@ -28,7 +28,7 @@ DEFAULT_SETTINGS = {
"reset_redo_stack": True,
"last_install_greet": "0",
"enable_latex": which("latex") is not None and which("dvipng") is not None,
"enable_latex_threaded": True,
"enable_latex_async": True,
"expression_editor": {
"autoclose": True,
"colorize": True,

View file

@ -22,9 +22,9 @@ from os import path
from re import compile
CURRENT_PATH = path.dirname(path.realpath(__file__))
SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/Common/index.mjs.map")
SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/js/index.mjs.map")
SOURCEMAP_INDEX = None
INDEX_REG = compile(r"build\/runtime-pyside6\/LogarithmPlotter\/qml\/eu\/ad5001\/LogarithmPlotter\/Common\/index.mjs:(\d+)")
INDEX_REG = compile(r"build\/runtime-pyside6\/LogarithmPlotter\/qml\/eu\/ad5001\/LogarithmPlotter\/js\/index.mjs:(\d+)")
class LOG_COLORS:

View file

@ -91,7 +91,7 @@ class Latex(QObject):
@Property(bool)
def supportsAsyncRender(self) -> bool:
return config.getSetting("enable_latex_threaded")
return config.getSetting("enable_latex_async")
@Slot(result=bool)
def checkLatexInstallation(self) -> bool:
@ -181,6 +181,7 @@ class Latex(QObject):
"""
markup_hash, render_hash, export_path = self.create_export_path(latex_markup, font_size, color)
if self.latexSupported and not path.exists(export_path + ".png"):
print("Rendering", latex_markup)
# Generating file
latex_path = path.join(self.tempdir, str(markup_hash))
# If the formula is just recolored or the font is just changed, no need to recreate the DVI.

View file

@ -100,7 +100,6 @@ class PyPromise(QObject):
Starts the thread that will run the promise.
"""
if not self._started: # Avoid getting started twice.
print("Starting", self._runner.args)
QThreadPool.globalInstance().start(self._runner)
self._started = True
@ -154,7 +153,6 @@ class PyPromise(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)

View file

@ -22,10 +22,6 @@
DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$DIR/.." || exit 1
BUILD_DIR="build/runtime-pyside6"
BUILD_QML_DIR="$BUILD_DIR/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter"
box() {
len=${#1}
echo "┌─$(printf '─%.0s' $(seq 1 "$len"))─┐"
@ -34,22 +30,20 @@ box() {
}
rm -rf build
mkdir -p "$BUILD_DIR"
mkdir -p build/runtime-pyside6
# Copy python
box "Copying pyside6 python runtime..."
cp -r runtime-pyside6/{setup.py,LogarithmPlotter} "$BUILD_DIR"
cp -r runtime-pyside6/{setup.py,LogarithmPlotter} build/runtime-pyside6
box "Building ecmascript modules..."
mkdir -p "$BUILD_QML_DIR/js"
cd common && \
(npm run build || exit) && \
cd ..
mkdir -p build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js
cd common && (npm run build || exit) && cd ..
box "Building translations..."
cd assets/i18n/ && (bash release.sh || exit) && cd ../../
mkdir -p "$BUILD_DIR/LogarithmPlotter/i18n" && cp assets/i18n/*.qm "$BUILD_DIR/LogarithmPlotter/i18n/"
mkdir -p build/runtime-pyside6/LogarithmPlotter/i18n && cp assets/i18n/*.qm build/runtime-pyside6/LogarithmPlotter/i18n/
box "Building icons..."
cp -r assets/icons "$BUILD_QML_DIR"
cp assets/logarithmplotter.svg "$BUILD_DIR/LogarithmPlotter/"
cp -r assets/icons build/runtime-pyside6/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/
cp assets/logarithmplotter.svg build/runtime-pyside6/LogarithmPlotter/