Adding default canvas settings
All checks were successful
continuous-integration/drone/push Build is passing

+ Getting rid of Qt5COmpat for Icon.
+ Fixing some (non production) bugs.
This commit is contained in:
Adsooi 2024-04-03 21:39:06 +02:00
parent 997a1645a0
commit 54f9802975
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
23 changed files with 558 additions and 235 deletions

View file

@ -33,7 +33,6 @@ import "js/historylib.mjs" as HistoryLib
\sa LogarithmPlotter \sa LogarithmPlotter
*/ */
MenuBar { MenuBar {
property var settingsMenu: settingsSubMenu
Menu { Menu {
title: qsTr("&File") title: qsTr("&File")

View file

@ -168,4 +168,45 @@ Canvas {
} }
}) })
} }
/*!
\qmlmethod double LogGraphCanvas::x2px(double x)
Converts an \c x coordinate to it's relative position on the canvas.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function x2px(x) {
if(logscalex) {
var logxmin = Math.log(xmin)
return (Math.log(x)-logxmin)*xzoom
} else return (x - xmin)*xzoom
}
/*!
\qmlmethod double LogGraphCanvas::y2px(double y)
Converts an \c y coordinate to it's relative position on the canvas.
The y axis not supporting logarithmic scale, it only support linear convertion.
*/
function y2px(y) {
return (ymax-y)*yzoom
}
/*!
\qmlmethod double LogGraphCanvas::px2x(double px)
Converts an x \c px position on the canvas to it's corresponding coordinate on the plot.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function px2x(px) {
if(logscalex) {
return Math.exp(px/xzoom+Math.log(xmin))
} else return (px/xzoom+xmin)
}
/*!
\qmlmethod double LogGraphCanvas::px2x(double px)
Converts an x \c px position on the canvas to it's corresponding coordinate on the plot.
It supports both logarithmic and non logarithmic scale depending on the currently selected mode.
*/
function px2y(px) {
return -(px/yzoom-ymax)
}
} }

View file

@ -20,7 +20,8 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting import eu.ad5001.LogarithmPlotter.Setting 1.0 as Setting
import "../js/setting/common.mjs" as S import "../js/preferences/common.mjs" as S
import "../js/utils.mjs" as Utils
/*! /*!
\qmltype Preferences \qmltype Preferences
@ -60,11 +61,75 @@ Popup {
label: setting.displayName label: setting.displayName
icon: `settings/${setting.icon}.svg` icon: `settings/${setting.icon}.svg`
currentIndex: setting.value() currentIndex: setting.value()
model: setting.values() model: setting.values
onActivated: function(newIndex) { setting.set(newIndex) } onActivated: function(newIndex) { setting.set(newIndex) }
} }
} }
Component {
id: stringSettingComponent
Setting.ComboBoxSetting {
height: 30
label: setting.displayName
icon: `settings/${setting.icon}.svg`
editable: true
currentIndex: find(setting.value())
model: setting.defaultValues
onAccepted: function() {
editText = Utils.parseName(editText, false)
if(find(editText) === -1) model.append(editText)
setting.set(editText)
}
onActivated: function(selectedId) {
setting.set(model[selectedId])
}
Component.onCompleted: editText = setting.value()
}
}
Component {
id: numberSettingComponent
Setting.TextSetting {
height: 30
isDouble: true
label: setting.displayName
min: setting.min()
icon: `settings/${setting.icon}.svg`
value: setting.value()
onChanged: function(newValue) {
if(newValue < setting.max())
setting.set(newValue)
else {
value = setting.max()
setting.set(setting.max())
}
}
}
}
Component {
id: expressionSettingComponent
Setting.ExpressionEditor {
height: 30
label: setting.displayName
icon: `settings/${setting.icon}.svg`
defValue: Utils.simplifyExpression(setting.value())
variables: setting.variables
allowGraphObjects: false
property string propertyName: setting.displayName
onChanged: function(newExpr) {
try {
setting.set(newExpr)
} catch(e) {
errorDialog.showDialog(propertyName, newExpr, e.message)
}
}
}
}
Row { Row {
id: settingPopupRow id: settingPopupRow
height: 300 height: 300
@ -90,7 +155,7 @@ Popup {
clip: true clip: true
Repeater { Repeater {
model: Object.keys(Modules.Settings.categories) model: Object.keys(Modules.Preferences.categories)
Button { Button {
// width: 150 // width: 150
@ -98,8 +163,8 @@ Popup {
text: qsTranslate('settingCategory', modelData) text: qsTranslate('settingCategory', modelData)
onClicked: { onClicked: {
settingList.model = Modules.Settings.categories[modelData] settingView.model = Modules.Preferences.categories[modelData]
settingCategoryName.text = text settingView.name = text
} }
} }
} }
@ -133,50 +198,55 @@ Popup {
width: 1 width: 1
} }
ScrollView { ListView {
id: settingView id: settingView
clip: true clip: true
width: 500 width: 500
height: parent.height spacing: 10
model: Modules.Preferences.categories.general
anchors {
top: parent.top
bottom: parent.bottom
}
ScrollBar.vertical: ScrollBar { }
property string name: qsTranslate('settingCategory', 'general')
Column {
spacing: 10
clip: true
width: settingView.width
Text { header: Text {
id: settingCategoryName id: settingCategoryName
font.pixelSize: 32 font.pixelSize: 32
height: 48
color: sysPalette.windowText
text: settingView.name
Rectangle {
id: bottomSeparator
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
opacity: 0.3
color: sysPalette.windowText color: sysPalette.windowText
text: qsTranslate('settingCategory', 'general') width: settingView.width
height: 1
Rectangle {
id: bottomSeparator
anchors.top: parent.bottom
opacity: 0.3
color: sysPalette.windowText
width: settingView.width
height: 1
}
} }
}
Repeater { delegate: Component {
id: settingList Loader {
model: Modules.Settings.categories.general width: settingView.width * 2 / 3
property var setting: modelData
delegate: Component { sourceComponent: {
Loader { if(setting instanceof S.BoolSetting)
width: settingView.width return boolSettingComponent
property var setting: modelData else if(setting instanceof S.EnumIntSetting)
sourceComponent: { return enumIntSettingComponent
if(setting instanceof S.BoolSetting) else if(setting instanceof S.NumberSetting)
return boolSettingComponent return numberSettingComponent
else if(setting instanceof S.EnumIntSetting) else if(setting instanceof S.ExpressionSetting)
return enumIntSettingComponent return expressionSettingComponent
else else if(setting instanceof S.StringSetting)
console.log('Unknown setting type!', modelData.constructor) return stringSettingComponent
} else
} console.log('Unknown setting type!', modelData.constructor)
} }
} }
} }

View file

@ -114,6 +114,7 @@ Item {
anchors.left: iconLabel.right anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5 anchors.leftMargin: icon == "" ? 0 : 5
height: 30 height: 30
width: Math.max(85, implicitWidth)
anchors.top: parent.top anchors.top: parent.top
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
text: qsTranslate("control", "%1: ").arg(control.label) text: qsTranslate("control", "%1: ").arg(control.label)

View file

@ -80,6 +80,17 @@ Item {
Icon path of the editor. Icon path of the editor.
*/ */
property string icon: "" property string icon: ""
/*!
\qmlproperty bool ExpressionEditor::allowGraphObjects
If true, allows graph objects to be used as part of the expression.
*/
property bool allowGraphObjects: true
/*!
\qmlproperty var ExpressionEditor::errorDialog
Allows to summon the error dialog when using additional external parsing.
*/
readonly property alias errorDialog: parsingErrorDialog
/*! /*!
\qmlproperty string ExpressionEditor::openAndCloseMatches \qmlproperty string ExpressionEditor::openAndCloseMatches
@ -177,8 +188,9 @@ Item {
id: labelItem id: labelItem
anchors.left: iconLabel.right anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5 anchors.leftMargin: icon == "" ? 0 : 5
height: parent.height
anchors.top: parent.top anchors.top: parent.top
height: parent.height
width: Math.max(85, implicitWidth)
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
//color: sysPalette.windowText //color: sysPalette.windowText
text: visible ? qsTranslate("control", "%1: ").arg(control.label) : "" text: visible ? qsTranslate("control", "%1: ").arg(control.label) : ""
@ -380,7 +392,7 @@ Item {
id: objectPropertiesList id: objectPropertiesList
category: qsTr("Object Properties") category: qsTr("Object Properties")
visbilityCondition: doesObjectExist visbilityCondition: control.allowGraphObjects && doesObjectExist
itemStartIndex: 0 itemStartIndex: 0
itemSelected: parent.itemSelected itemSelected: parent.itemSelected
property bool isEnteringProperty: ( property bool isEnteringProperty: (
@ -457,7 +469,7 @@ Item {
id: executableObjectsList id: executableObjectsList
category: qsTr("Executable Objects") category: qsTr("Executable Objects")
visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot visbilityCondition: control.allowGraphObjects && parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: functionsList.itemStartIndex + functionsList.model.length itemStartIndex: functionsList.itemStartIndex + functionsList.model.length
itemSelected: parent.itemSelected itemSelected: parent.itemSelected
categoryItems: Modules.Objects.getObjectsName("ExecutableObject").filter(obj => obj != self) categoryItems: Modules.Objects.getObjectsName("ExecutableObject").filter(obj => obj != self)
@ -472,7 +484,7 @@ Item {
id: objectsList id: objectsList
category: qsTr("Objects") category: qsTr("Objects")
visbilityCondition: parent.currentToken.identifier && !parent.previousToken.dot visbilityCondition: control.allowGraphObjects && parent.currentToken.identifier && !parent.previousToken.dot
itemStartIndex: executableObjectsList.itemStartIndex + executableObjectsList.model.length itemStartIndex: executableObjectsList.itemStartIndex + executableObjectsList.model.length
itemSelected: parent.itemSelected itemSelected: parent.itemSelected
categoryItems: Object.keys(Modules.Objects.currentObjectsByName).filter(obj => obj != self) categoryItems: Object.keys(Modules.Objects.currentObjectsByName).filter(obj => obj != self)

View file

@ -17,7 +17,7 @@
*/ */
import QtQuick import QtQuick
import QtQuick.Window import QtQuick.Window
import Qt5Compat.GraphicalEffects import QtQuick.Controls.impl
/*! /*!
\qmltype Icon \qmltype Icon
@ -41,20 +41,16 @@ Item {
\qmlproperty string Icon::source \qmlproperty string Icon::source
Path of the icon image source. Path of the icon image source.
*/ */
property alias sourceSize: img.sourceSize.width property alias sourceSize: img.sourceS
Image { ColorImage {
id: img id: img
height: parent.height height: parent.height
width: parent.width width: parent.width
visible: false // visible: false
sourceSize.width: width*Screen.devicePixelRatio property int sourceS: width*Screen.devicePixelRatio
sourceSize.height: width*Screen.devicePixelRatio sourceSize.width: sourceS
} sourceSize.height: sourceS
ColorOverlay {
anchors.fill: img
source: img
color: parent.color color: parent.color
} }
} }

View file

@ -100,15 +100,15 @@ Item {
id: labelItem id: labelItem
anchors.left: iconLabel.right anchors.left: iconLabel.right
anchors.leftMargin: icon == "" ? 0 : 5 anchors.leftMargin: icon == "" ? 0 : 5
height: parent.height
anchors.top: parent.top anchors.top: parent.top
height: parent.height
width: Math.max(85, implicitWidth)
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
//color: sysPalette.windowText //color: sysPalette.windowText
text: visible ? qsTranslate("control", "%1: ").arg(control.label) : "" text: visible ? qsTranslate("control", "%1: ").arg(control.label) : ""
visible: control.label != "" visible: control.label != ""
} }
TextField { TextField {
id: input id: input
anchors.top: parent.top anchors.top: parent.top
@ -128,8 +128,10 @@ Item {
onEditingFinished: function() { onEditingFinished: function() {
if(insertButton.focus || insertPopup.focus) return if(insertButton.focus || insertPopup.focus) return
var value = text var value = text
if(control.isInt) value = Math.max(control.min,parseInt(value).toString()=="NaN"?control.min:parseInt(value)) if(control.isInt)
if(control.isDouble) value = Math.max(control.min,parseFloat(value).toString()=="NaN"?control.min:parseFloat(value)) value = isNaN(parseInt(value)) ? control.min : Math.max(control.min,parseInt(value))
if(control.isDouble)
value = isNaN(parseFloat(value)) ? control.min : Math.max(control.min,parseFloat(value))
if(value != "" && value.toString() != defValue) { if(value != "" && value.toString() != defValue) {
control.changed(value) control.changed(value)
defValue = value.toString() defValue = value.toString()

View file

@ -44,83 +44,83 @@ ScrollView {
Zoom on the x axis of the diagram, provided from settings. Zoom on the x axis of the diagram, provided from settings.
\sa Settings \sa Settings
*/ */
property double xzoom: 100 property double xzoom: Helper.getSettingInt('default_graph.xzoom')
/*! /*!
\qmlproperty double Settings::yzoom \qmlproperty double Settings::yzoom
Zoom on the y axis of the diagram, provided from settings. Zoom on the y axis of the diagram, provided from settings.
\sa Settings \sa Settings
*/ */
property double yzoom: 10 property double yzoom: Helper.getSettingInt('default_graph.yzoom')
/*! /*!
\qmlproperty double Settings::xmin \qmlproperty double Settings::xmin
Minimum x of the diagram, provided from settings. Minimum x of the diagram, provided from settings.
\sa Settings \sa Settings
*/ */
property double xmin: 5/10 property double xmin: Helper.getSettingInt('default_graph.xmin')
/*! /*!
\qmlproperty double Settings::ymax \qmlproperty double Settings::ymax
Maximum y of the diagram, provided from settings. Maximum y of the diagram, provided from settings.
\sa Settings \sa Settings
*/ */
property double ymax: 25 property double ymax: Helper.getSettingInt('default_graph.ymax')
/*! /*!
\qmlproperty string Settings::xaxisstep \qmlproperty string Settings::xaxisstep
Step of the x axis graduation, provided from settings. Step of the x axis graduation, provided from settings.
\note: Only available in non-logarithmic mode. \note: Only available in non-logarithmic mode.
\sa Settings \sa Settings
*/ */
property string xaxisstep: "4" property string xaxisstep: Helper.getSetting('default_graph.xaxisstep')
/*! /*!
\qmlproperty string Settings::yaxisstep \qmlproperty string Settings::yaxisstep
Step of the y axis graduation, provided from settings. Step of the y axis graduation, provided from settings.
\sa Settings \sa Settings
*/ */
property string yaxisstep: "4" property string yaxisstep: Helper.getSetting('default_graph.yaxisstep')
/*! /*!
\qmlproperty string Settings::xlabel \qmlproperty string Settings::xlabel
Label used on the x axis, provided from settings. Label used on the x axis, provided from settings.
\sa Settings \sa Settings
*/ */
property string xlabel: "" property string xlabel: Helper.getSetting('default_graph.xlabel')
/*! /*!
\qmlproperty string Settings::ylabel \qmlproperty string Settings::ylabel
Label used on the y axis, provided from settings. Label used on the y axis, provided from settings.
\sa Settings \sa Settings
*/ */
property string ylabel: "" property string ylabel: Helper.getSetting('default_graph.ylabel')
/*! /*!
\qmlproperty double Settings::linewidth \qmlproperty double Settings::linewidth
Width of lines that will be drawn into the canvas, provided from settings. Width of lines that will be drawn into the canvas, provided from settings.
\sa Settings \sa Settings
*/ */
property double linewidth: 1 property double linewidth: Helper.getSettingInt('default_graph.linewidth')
/*! /*!
\qmlproperty double Settings::textsize \qmlproperty double Settings::textsize
Font size of the text that will be drawn into the canvas, provided from settings. Font size of the text that will be drawn into the canvas, provided from settings.
\sa Settings \sa Settings
*/ */
property double textsize: 18 property double textsize: Helper.getSettingInt('default_graph.textsize')
/*! /*!
\qmlproperty bool Settings::logscalex \qmlproperty bool Settings::logscalex
true if the canvas should be in logarithmic mode, false otherwise. true if the canvas should be in logarithmic mode, false otherwise.
Provided from settings. Provided from settings.
\sa Settings \sa Settings
*/ */
property bool logscalex: true property bool logscalex: Helper.getSettingBool('default_graph.logscalex')
/*! /*!
\qmlproperty bool Settings::showxgrad \qmlproperty bool Settings::showxgrad
true if the x graduation should be shown, false otherwise. true if the x graduation should be shown, false otherwise.
Provided from settings. Provided from settings.
\sa Settings \sa Settings
*/ */
property bool showxgrad: true property bool showxgrad: Helper.getSettingBool('default_graph.showxgrad')
/*! /*!
\qmlproperty bool Settings::showygrad \qmlproperty bool Settings::showygrad
true if the y graduation should be shown, false otherwise. true if the y graduation should be shown, false otherwise.
Provided from settings. Provided from settings.
\sa Settings \sa Settings
*/ */
property bool showygrad: true property bool showygrad: Helper.getSettingBool('default_graph.showygrad')
/*! /*!
\qmlproperty bool Settings::saveFilename \qmlproperty bool Settings::saveFilename
Path of the currently opened file. Empty if no file is opened. Path of the currently opened file. Empty if no file is opened.
@ -159,7 +159,7 @@ ScrollView {
height: 30 height: 30
isDouble: true isDouble: true
label: qsTr("X Zoom") label: qsTr("X Zoom")
min: 1 min: 0.1
icon: "settings/xzoom.svg" icon: "settings/xzoom.svg"
width: settings.settingWidth width: settings.settingWidth
value: settings.xzoom.toFixed(2) value: settings.xzoom.toFixed(2)
@ -173,6 +173,7 @@ ScrollView {
id: zoomY id: zoomY
height: 30 height: 30
isDouble: true isDouble: true
min: 0.1
label: qsTr("Y Zoom") label: qsTr("Y Zoom")
icon: "settings/yzoom.svg" icon: "settings/yzoom.svg"
width: settings.settingWidth width: settings.settingWidth
@ -226,10 +227,10 @@ ScrollView {
label: qsTr("Max X") label: qsTr("Max X")
icon: "settings/xmax.svg" icon: "settings/xmax.svg"
width: settings.settingWidth width: settings.settingWidth
value: Modules.Canvas.px2x(canvas.width).toFixed(2) defValue: canvas.px2x(canvas.width).toFixed(2)
onChanged: function(xvaluemax) { onChanged: function(xvaluemax) {
if(xvaluemax > settings.xmin) { if(xvaluemax > settings.xmin) {
settings.xzoom = settings.xzoom * canvas.width/(Modules.Canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point) settings.xzoom = settings.xzoom * canvas.width/(canvas.x2px(xvaluemax)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.changed() settings.changed()
} else { } else {
alert.show("Maximum x value must be superior to minimum.") alert.show("Maximum x value must be superior to minimum.")
@ -245,10 +246,10 @@ ScrollView {
label: qsTr("Min Y") label: qsTr("Min Y")
icon: "settings/ymin.svg" icon: "settings/ymin.svg"
width: settings.settingWidth width: settings.settingWidth
defValue: Modules.Canvas.px2y(canvas.height).toFixed(2) defValue: canvas.px2y(canvas.height).toFixed(2)
onChanged: function(yvaluemin) { onChanged: function(yvaluemin) {
if(yvaluemin < settings.ymax) { if(yvaluemin < settings.ymax) {
settings.yzoom = settings.yzoom * canvas.height/(Modules.Canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point) settings.yzoom = settings.yzoom * canvas.height/(canvas.y2px(yvaluemin)) // Adjusting zoom to fit. = (end)/(px of current point)
settings.changed() settings.changed()
} else { } else {
alert.show("Minimum y value must be inferior to maximum.") alert.show("Minimum y value must be inferior to maximum.")

View file

@ -0,0 +1 @@
../common/label.svg

View file

@ -0,0 +1 @@
../common/text.svg

View file

@ -7,4 +7,4 @@
.import "history/common.mjs" as HistoryCommon .import "history/common.mjs" as HistoryCommon
.import "canvas.mjs" as CanvasAPI .import "canvas.mjs" as CanvasAPI
.import "io.mjs" as IOAPI .import "io.mjs" as IOAPI
.import "settings.mjs" as SettingsAPI .import "preferences.mjs" as PreferencesAPI

View file

@ -377,10 +377,7 @@ class CanvasAPI extends Module {
* @returns {number} * @returns {number}
*/ */
x2px(x) { x2px(x) {
if(this.logscalex) { return this._canvas.x2px(x)
let logxmin = Math.log(this.xmin)
return (Math.log(x)-logxmin)*this.xzoom
} else return (x - this.xmin)*this.xzoom
} }
/** /**
@ -390,7 +387,7 @@ class CanvasAPI extends Module {
* @returns {number} * @returns {number}
*/ */
y2px(y) { y2px(y) {
return (this.ymax-y)*this.yzoom return this._canvas.y2px(y)
} }
/** /**
@ -400,9 +397,7 @@ class CanvasAPI extends Module {
* @returns {number} * @returns {number}
*/ */
px2x(px) { px2x(px) {
if(this.logscalex) { return this._canvas.px2x(px)
return Math.exp(px/this.xzoom+Math.log(this.xmin))
} else return (px/this.xzoom+this.xmin)
} }
/** /**
@ -412,7 +407,7 @@ class CanvasAPI extends Module {
* @returns {number} * @returns {number}
*/ */
px2y(px) { px2y(px) {
return -(px/this.yzoom-this.ymax) return this._canvas.px2y(px)
} }
/** /**

View file

@ -16,12 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Module} from "modules.mjs" import {Module} from "modules.mjs"
import General from "setting/general.mjs" import General from "preferences/general.mjs"
import Editor from "setting/expression.mjs" import Editor from "preferences/expression.mjs"
import DefaultGraph from "preferences/default.mjs"
class SettingsAPI extends Module { class PreferencesAPI extends Module {
constructor() { constructor() {
super('Settings', [ super('Preferences', [
Modules.Canvas, Modules.Canvas,
Modules.Latex Modules.Latex
]) ])
@ -29,11 +30,11 @@ class SettingsAPI extends Module {
this.categories = { this.categories = {
[QT_TRANSLATE_NOOP('settingCategory', 'general')]: General, [QT_TRANSLATE_NOOP('settingCategory', 'general')]: General,
[QT_TRANSLATE_NOOP('settingCategory', 'editor')]: Editor, [QT_TRANSLATE_NOOP('settingCategory', 'editor')]: Editor,
[QT_TRANSLATE_NOOP('settingCategory', 'default')]: [], [QT_TRANSLATE_NOOP('settingCategory', 'default')]: DefaultGraph,
} }
} }
} }
/** @type {CanvasAPI} */ /** @type {CanvasAPI} */
Modules.Settings = Modules.Settings || new SettingsAPI() Modules.Preferences = Modules.Preferences || new PreferencesAPI()
export const API = Modules.Settings export const API = Modules.Preferences

View file

@ -0,0 +1,137 @@
/**
* 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 {Expression} from "../mathlib.mjs"
class Setting {
constructor(type, name, nameInConfig, icon) {
this.type = type
this.name = name
this.displayName = qsTr(name)
this.nameInConfig = nameInConfig
this.icon = icon
}
/**
* Returns the value of the setting.
* @returns {string|boolean|number}
*/
value() {
throw new TypeError(`value of ${this.constructor} not implemented.`)
}
/**
* Sets the value of the setting
* @param {string|boolean|number|Expression} value
*/
set(value) {
throw new TypeError(`value of ${this.constructor} not implemented.`)
}
toString() {
return `Setting<${this.type} ${this.name}>`
}
}
export class BoolSetting extends Setting {
constructor(name, nameInConfig, icon) {
super('bool', name, nameInConfig, icon)
}
value() {
return Helper.getSettingBool(this.nameInConfig)
}
set(value) {
Helper.setSettingBool(this.nameInConfig, value)
}
}
export class NumberSetting extends Setting {
constructor(name, nameInConfig, icon, min = -Infinity, max = +Infinity) {
super('number', name, nameInConfig, icon)
this.min = typeof min == 'number' ? () => min : min
this.max = typeof max == 'number' ? () => max : max
}
value() {
return Helper.getSettingInt(this.nameInConfig)
}
set(value) {
Helper.setSettingInt(this.nameInConfig, value)
}
}
export class EnumIntSetting extends Setting {
constructor(name, nameInConfig, icon, values = []) {
super('enum', name, nameInConfig, icon)
this.values = values
}
value() {
return Helper.getSettingInt(this.nameInConfig)
}
set(value) {
Helper.setSettingInt(this.nameInConfig, value)
}
}
export class ExpressionSetting extends Setting {
constructor(name, nameInConfig, icon, variables = []) {
super('expression', name, nameInConfig, icon)
this.variables = variables
}
value() {
return Helper.getSetting(this.nameInConfig)
}
/**
*
* @param {Expression} value
*/
set(value) {
let vars = value.calc.variables()
if(vars.length === this.variables.length && vars.every(x => this.variables.includes(x)))
Helper.setSetting(this.nameInConfig, value)
else {
let undefinedVars = vars.filter(x => !this.variables.includes(x))
let allowed = ''
if(this.variables.length > 0)
allowed = `Allowed variables: ${this.variables.join(', ')}.`
throw new TypeError(`Cannot use variable(s) ${undefinedVars.join(', or ')} to define ${this.displayName}. ${allowed}`)
}
}
}
export class StringSetting extends Setting {
constructor(name, nameInConfig, icon, defaultValues = []) {
super('string', name, nameInConfig, icon)
this.defaultValues = defaultValues
}
value() {
return Helper.getSetting(this.nameInConfig)
}
set(value) {
Helper.setSetting(this.nameInConfig, value)
}
}

View file

@ -0,0 +1,120 @@
/**
* 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 {BoolSetting, ExpressionSetting, NumberSetting, StringSetting} from "common.mjs"
const XZOOM = new NumberSetting(
QT_TR_NOOP("X Zoom"),
"default_graph.xzoom",
"xzoom",
0.1
)
const YZOOM = new NumberSetting(
QT_TR_NOOP("Y Zoom"),
"default_graph.xzoom",
"yzoom",
0.1
)
const XMIN = new NumberSetting(
QT_TR_NOOP("Min X"),
"default_graph.xmin",
"xmin",
() => Helper.getSettingBool("default_graph.logscalex") ? 1e-100 : -Infinity
)
const YMAX = new NumberSetting(
QT_TR_NOOP("Max Y"),
"default_graph.ymax",
"ymax"
)
const XAXISSTEP = new ExpressionSetting(
QT_TR_NOOP("X Axis Step"),
"default_graph.xaxisstep",
"xaxisstep",
)
const YAXISSTEP = new ExpressionSetting(
QT_TR_NOOP("Y Axis Step"),
"default_graph.yaxisstep",
"yaxisstep",
)
const LINE_WIDTH = new NumberSetting(
QT_TR_NOOP("Line width"),
"default_graph.linewidth",
"linewidth",
1
)
const TEXT_SIZE = new NumberSetting(
QT_TR_NOOP("Text size (px)"),
"default_graph.textsize",
"textsize"
)
const X_LABEL = new StringSetting(
QT_TR_NOOP('X Label'),
"default_graph.xlabel",
"xlabel",
["", "x", "ω (rad/s)"]
)
const Y_LABEL = new StringSetting(
QT_TR_NOOP('Y Label'),
"default_graph.ylabel",
"xlabel",
["", "y", "G (dB)", "φ (°)", "φ (deg)", "φ (rad)"]
)
const LOG_SCALE_X = new BoolSetting(
QT_TR_NOOP('X Log scale'),
"default_graph.logscalex",
"logscalex"
)
const SHOW_X_GRAD = new BoolSetting(
QT_TR_NOOP('Show X graduation'),
"default_graph.showxgrad",
"showxgrad"
)
const SHOW_Y_GRAD = new BoolSetting(
QT_TR_NOOP('Show Y graduation'),
"default_graph.showygrad",
"showygrad"
)
export default [
XZOOM,
YZOOM,
XMIN,
YMAX,
XAXISSTEP,
YAXISSTEP,
LINE_WIDTH,
TEXT_SIZE,
X_LABEL,
Y_LABEL,
LOG_SCALE_X,
SHOW_X_GRAD,
SHOW_Y_GRAD
]

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
import {BoolSetting, EnumIntSetting} from "common.mjs"
const AUTOCLOSE_FORMULA = new BoolSetting(
QT_TR_NOOP("Automatically close parenthesises and brackets"),
'expression_editor.autoclose',
'text'
)
const ENABLE_SYNTAX_HIGHLIGHTING = new BoolSetting(
QT_TR_NOOP("Enable syntax highlighting"),
'expression_editor.colorize',
'appearance'
)
const ENABLE_AUTOCOMPLETE = new BoolSetting(
QT_TR_NOOP("Enable autocompletion"),
'autocompletion.enabled',
'label'
)
const PICK_COLOR_SCHEME = new EnumIntSetting(
QT_TR_NOOP("Color Scheme"),
'expression_editor.color_scheme',
'color',
["Breeze Light", "Breeze Dark", "Solarized", "Github Light", "Github Dark", "Nord", "Monokai"]
)
export default [
AUTOCLOSE_FORMULA,
ENABLE_AUTOCOMPLETE,
ENABLE_SYNTAX_HIGHLIGHTING,
PICK_COLOR_SCHEME
]

View file

@ -18,17 +18,17 @@
import {BoolSetting} from "common.mjs" import {BoolSetting} from "common.mjs"
class CheckForUpdates extends BoolSetting { const CHECK_FOR_UPDATES = new BoolSetting(
constructor() { QT_TR_NOOP("Check for updates on startup"),
super(QT_TR_NOOP("Check for updates on startup"), 'check_for_updates', 'update') 'check_for_updates',
} 'update'
} )
class ResetRedoStack extends BoolSetting { const RESET_REDO_STACK = new BoolSetting(
constructor() { QT_TR_NOOP("Reset redo stack automaticly"),
super(qsTr("Reset redo stack automaticly"), 'reset_redo_stack', 'timeline') 'reset_redo_stack',
} 'timeline'
} )
class EnableLatex extends BoolSetting { class EnableLatex extends BoolSetting {
constructor() { constructor() {
@ -43,7 +43,7 @@ class EnableLatex extends BoolSetting {
} }
export default [ export default [
new CheckForUpdates(), CHECK_FOR_UPDATES,
new ResetRedoStack(), RESET_REDO_STACK,
new EnableLatex() new EnableLatex()
] ]

View file

@ -1,67 +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/>.
*/
class Setting {
constructor(name, nameInConfig, icon) {
this.name = name
this.displayName = qsTr(name)
this.nameInConfig = nameInConfig
this.icon = icon
}
/**
* Returns the value of the setting.
* @returns {string|boolean|number}
*/
value() {
throw new TypeError(`value of ${this.constructor} not implemented.`)
}
/**
* Sets the value of the setting
* @param {string|boolean|number} value
*/
set(value) {
throw new TypeError(`value of ${this.constructor} not implemented.`)
}
}
export class BoolSetting extends Setting {
value() {
return Helper.getSettingBool(this.nameInConfig)
}
set(value) {
Helper.setSettingBool(this.nameInConfig, value)
}
}
export class IntSetting extends Setting {
value() {
return Helper.getSettingInt(this.nameInConfig)
}
set(value) {
Helper.setSettingInt(this.nameInConfig, value)
}
}
export class EnumIntSetting extends IntSetting {
values() {
throw new TypeError(`enumerations of ${this.constructor} not implemented.`)
}
}

View file

@ -1,54 +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 {BoolSetting, EnumIntSetting} from "common.mjs"
class AutocloseFormula extends BoolSetting {
constructor() {
super(qsTr("Automatically close parenthesises and brackets"), 'expression_editor.autoclose', 'Text')
}
}
class EnableSyntaxHighlighting extends BoolSetting {
constructor() {
super(qsTr("Enable syntax highlighting"), 'expression_editor.colorize', 'appearance')
}
}
class EnableAutocomplete extends BoolSetting {
constructor() {
super(qsTr("Enable autocompletion"), 'autocompletion.enabled', 'label')
}
}
class PickColorScheme extends EnumIntSetting {
constructor() {
super(qsTr("Color Scheme"), 'expression_editor.color_scheme', 'color')
}
values() {
return ["Breeze Light", "Breeze Dark", "Solarized", "Github Light", "Github Dark", "Nord", "Monokai"]
}
}
export default [
new AutocloseFormula(),
new EnableAutocomplete(),
new EnableSyntaxHighlighting(),
new PickColorScheme()
]

View file

@ -34,6 +34,21 @@ DEFAULT_SETTINGS = {
}, },
"autocompletion": { "autocompletion": {
"enabled": True "enabled": True
},
"default_graph": {
"xzoom": 100,
"yzoom": 10,
"xmin": 5/10,
"ymax": 25,
"xaxisstep": "4",
"yaxisstep": "4",
"xlabel": "",
"ylabel": "",
"linewidth": 1,
"textsize": 18,
"logscalex": True,
"showxgrad": True,
"showygrad": True
} }
} }

View file

@ -129,8 +129,9 @@ class Helper(QObject):
def getSetting(self, namespace): def getSetting(self, namespace):
return config.getSetting(namespace) return config.getSetting(namespace)
@Slot(str, result=int) @Slot(str, result=float)
def getSettingInt(self, namespace): def getSettingInt(self, namespace):
print('Getting', namespace, config.getSetting(namespace))
return config.getSetting(namespace) return config.getSetting(namespace)
@Slot(str, result=bool) @Slot(str, result=bool)
@ -145,7 +146,7 @@ class Helper(QObject):
def setSettingBool(self, namespace, value): def setSettingBool(self, namespace, value):
return config.setSetting(namespace, value) return config.setSetting(namespace, value)
@Slot(str, int) @Slot(str, float)
def setSettingInt(self, namespace, value): def setSettingInt(self, namespace, value):
return config.setSetting(namespace, value) return config.setSetting(namespace, value)