commit
55f8d70687
|
@ -9,7 +9,9 @@ charset = utf-8
|
|||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
max_line_length = 90
|
||||
max_line_length = 180
|
||||
indent_size = 2
|
||||
|
||||
|
||||
[**.py]
|
||||
indent_size = 4
|
||||
|
|
|
@ -12,4 +12,7 @@ dist
|
|||
.vscode
|
||||
.vscode/**
|
||||
|
||||
thunder-tests
|
||||
thunder-tests
|
||||
vscode.env
|
||||
.venv
|
||||
OctoKlipper.egg-info
|
|
@ -19,7 +19,7 @@ This plugin assists in managing and monitoring the [Klipper](https://github.com/
|
|||
- PID Tuning Dialog.
|
||||
- Dialog to set a coordinate offset for future GCODE move commands.
|
||||
- Message log displaying messages from Klipper prepended with "//" and "!!".
|
||||
- Basic Klipper configuration editor
|
||||
- Klipper configuration editor
|
||||
- Performance graph displaying key parameters extracted from the Klipper logs.
|
||||
|
||||
## Installation
|
||||
|
@ -46,7 +46,7 @@ Also for the moment this plugin does what I wanted it to do, it is far from fini
|
|||
|
||||
* The [devel](https://github.com/thelastWallE/OctoprintKlipperPlugin/tree/devel) branch is the branch to merge new features and bugfixes to.
|
||||
* The [rc](https://github.com/thelastWallE/OctoprintKlipperPlugin/tree/rc) branch is for Release Candidates and bugfixing them.
|
||||
* The [master](https://github.com/thelastWallE/OctoprintKlipperPlugin/tree/master) branch is for Stable Releases.
|
||||
* The [master](https://github.com/thelastWallE/OctoprintKlipperPlugin/tree/master) branch is for Stable Releases.
|
||||
|
||||
|
||||
## Screenshots
|
||||
|
|
|
@ -14,35 +14,38 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import datetime
|
||||
import logging
|
||||
import octoprint.plugin
|
||||
import octoprint.plugin.core
|
||||
import glob
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import io
|
||||
|
||||
from octoprint.server import NO_CONTENT
|
||||
from octoprint.util import is_hidden_path
|
||||
from octoprint.util import get_formatted_size
|
||||
from . import util, cfgUtils, logger
|
||||
from octoprint.util.comm import parse_firmware_line
|
||||
from octoprint.access.permissions import Permissions, ADMIN_GROUP, USER_GROUP
|
||||
from octoprint.access.permissions import Permissions, ADMIN_GROUP
|
||||
from .modules import KlipperLogAnalyzer
|
||||
from octoprint.server.util.flask import restricted_access
|
||||
import flask
|
||||
from flask_babel import gettext
|
||||
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import ConfigParser as configparser
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
import StringIO
|
||||
|
||||
MAX_UPLOAD_SIZE = 5 * 1024 * 1024 # 5Mb
|
||||
|
||||
class KlipperPlugin(
|
||||
octoprint.plugin.StartupPlugin,
|
||||
octoprint.plugin.TemplatePlugin,
|
||||
octoprint.plugin.SettingsPlugin,
|
||||
octoprint.plugin.AssetPlugin,
|
||||
octoprint.plugin.SimpleApiPlugin,
|
||||
octoprint.plugin.EventHandlerPlugin):
|
||||
octoprint.plugin.EventHandlerPlugin,
|
||||
octoprint.plugin.BlueprintPlugin):
|
||||
|
||||
_parsing_response = False
|
||||
_parsing_check_response = True
|
||||
|
@ -75,8 +78,10 @@ class KlipperPlugin(
|
|||
self._settings.global_set(
|
||||
["serial", "additionalPorts"], additional_ports)
|
||||
self._settings.save()
|
||||
self.log_info(
|
||||
"Added klipper serial port {} to list of additional ports.".format(klipper_port))
|
||||
logger.log_info(
|
||||
self,
|
||||
"Added klipper serial port {} to list of additional ports.".format(klipper_port)
|
||||
)
|
||||
|
||||
# -- Settings Plugin
|
||||
|
||||
|
@ -101,6 +106,7 @@ class KlipperPlugin(
|
|||
]
|
||||
|
||||
def get_settings_defaults(self):
|
||||
# TODO #69 put some settings on the localStorage
|
||||
return dict(
|
||||
connection=dict(
|
||||
port="/tmp/printer",
|
||||
|
@ -125,103 +131,20 @@ class KlipperPlugin(
|
|||
),
|
||||
configuration=dict(
|
||||
debug_logging=False,
|
||||
configpath="~/printer.cfg",
|
||||
old_config="",
|
||||
config_path="~/",
|
||||
baseconfig="printer.cfg",
|
||||
logpath="/tmp/klippy.log",
|
||||
reload_command="RESTART",
|
||||
restart_onsave=True,
|
||||
confirm_reload=True,
|
||||
shortStatus_navbar=True,
|
||||
shortStatus_sidebar=True,
|
||||
parse_check=False,
|
||||
fontsize=9
|
||||
fontsize=12
|
||||
)
|
||||
)
|
||||
|
||||
def on_settings_load(self):
|
||||
data = octoprint.plugin.SettingsPlugin.on_settings_load(self)
|
||||
|
||||
configpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "configpath"])
|
||||
)
|
||||
try:
|
||||
with io.open(configpath, "r", encoding="utf8") as f:
|
||||
data["config"] = f.read()
|
||||
f.close()
|
||||
except IOError:
|
||||
self.log_error(
|
||||
"Error: Klipper config file not found at: {}".format(
|
||||
configpath)
|
||||
)
|
||||
except UnicodeDecodeError as e:
|
||||
self.log_debug(
|
||||
"Loading config with utf-8 failed. Trying to load config file with ISO-8859-1 now."
|
||||
)
|
||||
try:
|
||||
with io.open(configpath, "r", encoding="ISO-8859-1") as f:
|
||||
data["config"] = f.read()
|
||||
f.close()
|
||||
except UnicodeDecodeError as e:
|
||||
self.log_error(
|
||||
"Error: Klipper config file cannot be decoded: {}".format(e)
|
||||
)
|
||||
else:
|
||||
self.log_debug(
|
||||
"Loading config with ISO-8859-1 finished."
|
||||
)
|
||||
self.send_message("reload", "config", "", data["config"])
|
||||
# send the configdata to frontend to update ace editor
|
||||
else:
|
||||
self.send_message("reload", "config", "", data["config"])
|
||||
# send the configdata to frontend to update ace editor
|
||||
return data
|
||||
|
||||
def on_settings_save(self, data):
|
||||
|
||||
self.log_debug(
|
||||
"Save klipper configs"
|
||||
)
|
||||
|
||||
if "config" in data:
|
||||
if self.key_exist(data, "configuration", "parse_check"):
|
||||
check_parse = data["configuration"]["parse_check"]
|
||||
else:
|
||||
check_parse = self._settings.get(["configuration", "parse_check"])
|
||||
|
||||
|
||||
# check for configpath if it was changed during changing of the configfile
|
||||
if self.key_exist(data, "configuration", "configpath"):
|
||||
configpath = os.path.expanduser(
|
||||
data["configuration"]["configpath"]
|
||||
)
|
||||
else:
|
||||
# if the configpath was not changed during changing the printer.cfg. Then the configpath would not be in data[]
|
||||
configpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "configpath"])
|
||||
)
|
||||
if self.file_exist(configpath) and (self._parsing_check_response or not check_parse):
|
||||
try:
|
||||
with io.open(configpath, "w", encoding="utf-8") as f:
|
||||
f.write(data["config"])
|
||||
f.close()
|
||||
self.log_debug("Writing Klipper config to {}".format(configpath))
|
||||
except IOError:
|
||||
self.log_error("Error: Couldn't write Klipper config file: {}".format(configpath))
|
||||
else:
|
||||
#load the reload command from changed data if it is not existing load the saved setting
|
||||
if self.key_exist(data, "configuration", "reload_command"):
|
||||
reload_command = os.path.expanduser(
|
||||
data["configuration"]["reload_command"]
|
||||
)
|
||||
else:
|
||||
reload_command = self._settings.get(["configuration", "reload_command"])
|
||||
|
||||
if reload_command != "manually":
|
||||
# Restart klippy to reload config
|
||||
self._printer.commands(reload_command)
|
||||
self.log_info("Restarting Klipper.")
|
||||
# we don't want to write the klipper conf to the octoprint settings
|
||||
data.pop("config", None)
|
||||
|
||||
# save the rest of changed settings into config.yaml of octoprint
|
||||
old_debug_logging = self._settings.get_boolean(["configuration", "debug_logging"])
|
||||
|
||||
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
|
||||
|
@ -237,7 +160,7 @@ class KlipperPlugin(
|
|||
return dict(
|
||||
admin=[
|
||||
["connection", "port"],
|
||||
["configuration", "configpath"],
|
||||
["configuration", "config_path"],
|
||||
["configuration", "replace_connection_panel"]
|
||||
],
|
||||
user=[
|
||||
|
@ -247,66 +170,61 @@ class KlipperPlugin(
|
|||
)
|
||||
|
||||
def get_settings_version(self):
|
||||
return 3
|
||||
# Settings_Versionhistory:
|
||||
# 3 = add shortstatus on navbar. migrate the navbar setting for this
|
||||
# 4 = -change of configpath to config_path with only path without filename
|
||||
# -parse configpath into config_path and baseconfig
|
||||
# -switch setting for 'restart on editor save' to true if it was not set to manually
|
||||
# -remove old_config
|
||||
# -remove config on root settingsdirectory
|
||||
return 4
|
||||
|
||||
#migrate Settings
|
||||
def on_settings_migrate(self, target, current):
|
||||
settings = self._settings
|
||||
if current is None:
|
||||
settings = self._settings
|
||||
util.migrate_old_settings(settings)
|
||||
|
||||
if settings.has(["serialport"]):
|
||||
settings.set(["connection", "port"],
|
||||
settings.get(["serialport"]))
|
||||
settings.remove(["serialport"])
|
||||
if current is not None and current < 3:
|
||||
self.migrate_settings_3(settings)
|
||||
|
||||
if settings.has(["replace_connection_panel"]):
|
||||
settings.set(
|
||||
["connection", "replace_connection_panel"],
|
||||
settings.get(["replace_connection_panel"])
|
||||
)
|
||||
settings.remove(["replace_connection_panel"])
|
||||
if current is not None and current < 4:
|
||||
self.migrate_settings_4(settings)
|
||||
|
||||
if settings.has(["probeHeight"]):
|
||||
settings.set(["probe", "height"],
|
||||
settings.get(["probeHeight"]))
|
||||
settings.remove(["probeHeight"])
|
||||
def migrate_settings_3(self, settings):
|
||||
util.migrate_settings_configuration(
|
||||
settings,
|
||||
"shortStatus_navbar",
|
||||
"navbar",
|
||||
)
|
||||
|
||||
if settings.has(["probeLift"]):
|
||||
settings.set(["probe", "lift"], settings.get(["probeLift"]))
|
||||
settings.remove(["probeLift"])
|
||||
def migrate_settings_4(self, settings):
|
||||
if settings.has(["configuration", "configpath"]):
|
||||
cfg_path = settings.get(["configuration", "configpath"])
|
||||
new_cfg_path, baseconfig = os.path.split(cfg_path)
|
||||
logger.log_info(self, "migrate setting for 'configuration/config_path': " + cfg_path + " -> " + new_cfg_path)
|
||||
logger.log_info(self, "migrate setting for 'configuration/baseconfig': printer.cfg -> " + baseconfig)
|
||||
settings.set(["configuration", "config_path"], new_cfg_path)
|
||||
settings.set(["configuration", "baseconfig"], baseconfig)
|
||||
settings.remove(["configuration", "configpath"])
|
||||
if (
|
||||
settings.has(["configuration", "reload_command"])
|
||||
and settings.get(["configuration", "reload_command"]) == "manually"
|
||||
):
|
||||
logger.log_info(self, "migrate setting for 'configuration/restart_onsave': True -> False")
|
||||
settings.set(["configuration", "restart_onsave"], False)
|
||||
settings.remove(["configuration", "reload_command"])
|
||||
|
||||
if settings.has(["probeSpeedXy"]):
|
||||
settings.set(["probe", "speed_xy"],
|
||||
settings.get(["probeSpeedXy"]))
|
||||
settings.remove(["probeSpeedXy"])
|
||||
if settings.has(["config"]):
|
||||
logger.log_info(self, "remove old setting for 'config'")
|
||||
settings.remove(["config"])
|
||||
|
||||
if settings.has(["probeSpeedZ"]):
|
||||
settings.set(["probe", "speed_z"],
|
||||
settings.get(["probeSpeedZ"]))
|
||||
settings.remove(["probeSpeedZ"])
|
||||
if settings.has(["configuration", "old_config"]):
|
||||
logger.log_info(self, "remove old setting for 'configuration/old_config'")
|
||||
settings.remove(["configuration", "old_config"])
|
||||
|
||||
if settings.has(["probePoints"]):
|
||||
points = settings.get(["probePoints"])
|
||||
points_new = []
|
||||
for p in points:
|
||||
points_new.append(
|
||||
dict(name="", x=int(p["x"]), y=int(p["y"]), z=0))
|
||||
settings.set(["probe", "points"], points_new)
|
||||
settings.remove(["probePoints"])
|
||||
|
||||
if settings.has(["configPath"]):
|
||||
self.log_info("migrate setting for: configPath")
|
||||
settings.set(["config_path"], settings.get(["configPath"]))
|
||||
settings.remove(["configPath"])
|
||||
|
||||
if target is 3 and current is 2:
|
||||
settings = self._settings
|
||||
if settings.has(["configuration", "navbar"]):
|
||||
self.log_info("migrate setting for: configuration/navbar")
|
||||
settings.set(["configuration", "shortStatus_navbar"], settings.get(["configuration", "navbar"]))
|
||||
settings.remove(["configuration", "navbar"])
|
||||
|
||||
# -- Template Plugin
|
||||
|
||||
def get_template_configs(self):
|
||||
return [
|
||||
dict(type="navbar", custom_bindings=True),
|
||||
|
@ -337,17 +255,29 @@ class KlipperPlugin(
|
|||
custom_bindings=True
|
||||
),
|
||||
dict(type="sidebar",
|
||||
custom_bindings=True,
|
||||
icon="rocket",
|
||||
replaces="connection" if self._settings.get_boolean(
|
||||
["connection", "replace_connection_panel"]) else ""
|
||||
),
|
||||
custom_bindings=True,
|
||||
icon="rocket",
|
||||
replaces="connection" if self._settings.get_boolean(
|
||||
["connection", "replace_connection_panel"]) else ""
|
||||
),
|
||||
dict(
|
||||
type="generic",
|
||||
name="Performance Graph",
|
||||
template="klipper_graph_dialog.jinja2",
|
||||
custom_bindings=True
|
||||
),
|
||||
dict(
|
||||
type="generic",
|
||||
name="Config Backups",
|
||||
template="klipper_backups_dialog.jinja2",
|
||||
custom_bindings=True
|
||||
),
|
||||
dict(
|
||||
type="generic",
|
||||
name="Config Editor",
|
||||
template="klipper_editor.jinja2",
|
||||
custom_bindings=True
|
||||
),
|
||||
dict(
|
||||
type="generic",
|
||||
name="Macro Dialog",
|
||||
|
@ -356,6 +286,12 @@ class KlipperPlugin(
|
|||
)
|
||||
]
|
||||
|
||||
def get_template_vars(self):
|
||||
return {
|
||||
"max_upload_size": MAX_UPLOAD_SIZE,
|
||||
"max_upload_size_str": get_formatted_size(MAX_UPLOAD_SIZE),
|
||||
}
|
||||
|
||||
# -- Asset Plugin
|
||||
|
||||
def get_assets(self):
|
||||
|
@ -366,51 +302,66 @@ class KlipperPlugin(
|
|||
"js/klipper_pid_tuning.js",
|
||||
"js/klipper_offset.js",
|
||||
"js/klipper_param_macro.js",
|
||||
"js/klipper_graph.js"
|
||||
],
|
||||
"js/klipper_graph.js",
|
||||
"js/klipper_backup.js",
|
||||
"js/klipper_editor.js"
|
||||
],
|
||||
clientjs=["clientjs/klipper.js"],
|
||||
css=["css/klipper.css"]
|
||||
)
|
||||
|
||||
# -- Event Handler Plugin
|
||||
|
||||
def on_event(self, event, payload):
|
||||
if "UserLoggedIn" == event:
|
||||
self.update_status("info", "Klipper: Standby")
|
||||
if "Connecting" == event:
|
||||
self.update_status("info", "Klipper: Connecting ...")
|
||||
elif "Connected" == event:
|
||||
self.update_status("info", "Klipper: Connected to host")
|
||||
self.log_info(
|
||||
if event == "UserLoggedIn":
|
||||
logger.log_info(self, "Klipper: Standby")
|
||||
if event == "Connecting":
|
||||
logger.log_info(self, "Klipper: Connecting ...")
|
||||
elif event == "Connected":
|
||||
logger.log_info(self, "Klipper: Connected to host")
|
||||
logger.log_info(
|
||||
self,
|
||||
"Connected to host via {} @{}bps".format(payload["port"], payload["baudrate"]))
|
||||
elif "Disconnected" == event:
|
||||
self.update_status("info", "Klipper: Disconnected from host")
|
||||
elif "Error" == event:
|
||||
self.update_status("error", "Klipper: Error")
|
||||
self.log_error(payload["error"])
|
||||
elif event == "Disconnected":
|
||||
logger.log_info(self, "Klipper: Disconnected from host")
|
||||
|
||||
elif event == "Error":
|
||||
logger.log_error(self, payload["error"])
|
||||
|
||||
def processAtCommand(self, comm_instance, phase, command, parameters, tags=None, *args, **kwargs):
|
||||
if command != "SWITCHCONFIG":
|
||||
return
|
||||
|
||||
config = parameters
|
||||
logger.log_info(self, "SWITCHCONFIG detected config:{}".format(config))
|
||||
return None
|
||||
|
||||
# -- GCODE Hook
|
||||
def process_sent_GCODE(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
|
||||
if cmd == "SAVE_CONFIG":
|
||||
logger.log_info(self, "SAVE_CONFIG detected")
|
||||
util.send_message(self, type = "reload", subtype = "config")
|
||||
|
||||
def on_parse_gcode(self, comm, line, *args, **kwargs):
|
||||
|
||||
if "FIRMWARE_VERSION" in line:
|
||||
printerInfo = parse_firmware_line(line)
|
||||
if "FIRMWARE_VERSION" in printerInfo:
|
||||
self.log_info("Firmware version: {}".format(
|
||||
logger.log_info(self, "Firmware version: {}".format(
|
||||
printerInfo["FIRMWARE_VERSION"]))
|
||||
elif "// probe" in line or "// Failed to verify BLTouch" in line:
|
||||
msg = line.strip('/')
|
||||
self.log_info(msg)
|
||||
logger.log_info(self, msg)
|
||||
self.write_parsing_response_buffer()
|
||||
elif "//" in line:
|
||||
# add lines with // to a buffer
|
||||
self._message = self._message + line.strip('/')
|
||||
if not self._parsing_response:
|
||||
self.update_status("info", self._message)
|
||||
util.update_status(self, "info", self._message)
|
||||
self._parsing_response = True
|
||||
elif "!!" in line:
|
||||
msg = line.strip('!')
|
||||
self.update_status("error", msg)
|
||||
self.log_error(msg)
|
||||
logger.log_error(self, msg)
|
||||
self.write_parsing_response_buffer()
|
||||
else:
|
||||
self.write_parsing_response_buffer()
|
||||
|
@ -420,15 +371,13 @@ class KlipperPlugin(
|
|||
# write buffer with // lines after a gcode response without //
|
||||
if self._parsing_response:
|
||||
self._parsing_response = False
|
||||
self.log_info(self._message)
|
||||
logger.log_info(self, self._message)
|
||||
self._message = ""
|
||||
|
||||
def get_api_commands(self):
|
||||
return dict(
|
||||
listLogFiles=[],
|
||||
getStats=["logFile"],
|
||||
reloadConfig=[],
|
||||
checkConfig=["config"]
|
||||
getStats=["logFile"]
|
||||
)
|
||||
|
||||
def on_api_command(self, command, data):
|
||||
|
@ -437,70 +386,182 @@ class KlipperPlugin(
|
|||
logpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "logpath"])
|
||||
)
|
||||
if self.file_exist(logpath):
|
||||
if util.file_exist(self, logpath):
|
||||
for f in glob.glob(self._settings.get(["configuration", "logpath"]) + "*"):
|
||||
filesize = os.path.getsize(f)
|
||||
filemdate = time.strftime("%d.%m.%Y %H:%M",time.localtime(os.path.getctime(f)))
|
||||
files.append(dict(
|
||||
name=os.path.basename(
|
||||
f) + " ({:.1f} KB)".format(filesize / 1000.0),
|
||||
name=os.path.basename(f) + " (" + filemdate + ")",
|
||||
file=f,
|
||||
size=filesize
|
||||
))
|
||||
return flask.jsonify(data=files)
|
||||
else:
|
||||
return flask.jsonify(data=files)
|
||||
return flask.jsonify(data=files)
|
||||
elif command == "getStats":
|
||||
if "logFile" in data:
|
||||
log_analyzer = KlipperLogAnalyzer.KlipperLogAnalyzer(
|
||||
data["logFile"])
|
||||
return flask.jsonify(log_analyzer.analyze())
|
||||
elif command == "reloadConfig":
|
||||
data = octoprint.plugin.SettingsPlugin.on_settings_load(self)
|
||||
|
||||
configpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "configpath"])
|
||||
)
|
||||
def is_blueprint_protected(self):
|
||||
return False
|
||||
|
||||
def route_hook(self, server_routes, *args, **kwargs):
|
||||
from octoprint.server.util.tornado import LargeResponseHandler, path_validation_factory
|
||||
from octoprint.util import is_hidden_path
|
||||
configpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
bak_path = os.path.join(self.get_plugin_data_folder(), "configs", "")
|
||||
|
||||
return [
|
||||
(r"/download/configs/(.*)", LargeResponseHandler, dict(path=configpath,
|
||||
as_attachment=True,
|
||||
path_validation=path_validation_factory(lambda path: not is_hidden_path(path),
|
||||
status_code=404))),
|
||||
(r"/download/backup/(.*)", LargeResponseHandler, dict(path=bak_path,
|
||||
as_attachment=True,
|
||||
path_validation=path_validation_factory(lambda path: not is_hidden_path(path),
|
||||
status_code=404)))
|
||||
]
|
||||
|
||||
# API for Backups
|
||||
# Get Content of a Backupconfig
|
||||
@octoprint.plugin.BlueprintPlugin.route("/backup/<filename>", methods=["GET"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def get_backup(self, filename):
|
||||
data_folder = self.get_plugin_data_folder()
|
||||
full_path = os.path.realpath(os.path.join(data_folder, "configs", filename))
|
||||
response = cfgUtils.get_cfg(self, full_path)
|
||||
return flask.jsonify(response = response)
|
||||
|
||||
# Delete a Backupconfig
|
||||
@octoprint.plugin.BlueprintPlugin.route("/backup/<filename>", methods=["DELETE"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def delete_backup(self, filename):
|
||||
data_folder = self.get_plugin_data_folder()
|
||||
full_path = os.path.realpath(os.path.join(data_folder, "configs", filename))
|
||||
if (
|
||||
full_path.startswith(data_folder)
|
||||
and os.path.exists(full_path)
|
||||
and not is_hidden_path(full_path)
|
||||
):
|
||||
try:
|
||||
with io.open(configpath, "r", encoding="utf-8") as f:
|
||||
data["config"] = f.read()
|
||||
f.close()
|
||||
except IOError:
|
||||
self.log_error(
|
||||
"Error: Klipper config file not found at: {}".format(
|
||||
configpath)
|
||||
)
|
||||
except UnicodeDecodeError as e:
|
||||
self.log_debug(
|
||||
"Loading config with utf-8 failed. Trying to load config file with ISO-8859-1 now."
|
||||
)
|
||||
try:
|
||||
with io.open(configpath, "r", encoding="ISO-8859-1") as f:
|
||||
data["config"] = f.read()
|
||||
f.close()
|
||||
except UnicodeDecodeError as e:
|
||||
self.log_error(
|
||||
"Error: Klipper config file cannot be decoded: {}".format(e)
|
||||
)
|
||||
else:
|
||||
self.log_debug(
|
||||
"Loading config with ISO-8859-1 finished."
|
||||
)
|
||||
self._settings.set(["config"], data["config"])
|
||||
return flask.jsonify(data=data["config"])
|
||||
else:
|
||||
os.remove(full_path)
|
||||
except Exception:
|
||||
self._octoklipper_logger.exception("Could not delete {}".format(filename))
|
||||
raise
|
||||
return NO_CONTENT
|
||||
|
||||
# Get a list of all backed up configfiles
|
||||
@octoprint.plugin.BlueprintPlugin.route("/backup/list", methods=["GET"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def list_backups(self):
|
||||
files = cfgUtils.list_cfg_files(self, "backup")
|
||||
return flask.jsonify(files = files)
|
||||
|
||||
# restore a backed up configfile
|
||||
@octoprint.plugin.BlueprintPlugin.route("/backup/restore/<filename>", methods=["GET"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def restore_backup(self, filename):
|
||||
configpath = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
data_folder = self.get_plugin_data_folder()
|
||||
backupfile = os.path.realpath(os.path.join(data_folder, "configs", filename))
|
||||
return flask.jsonify(restored = cfgUtils.copy_cfg(self, backupfile, configpath))
|
||||
|
||||
# API for Configs
|
||||
# Get Content of a Configfile
|
||||
@octoprint.plugin.BlueprintPlugin.route("/config/<filename>", methods=["GET"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def get_config(self, filename):
|
||||
cfg_path = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
full_path = os.path.realpath(os.path.join(cfg_path, filename))
|
||||
response = cfgUtils.get_cfg(self, full_path)
|
||||
return flask.jsonify(response = response)
|
||||
|
||||
# Delete a Configfile
|
||||
@octoprint.plugin.BlueprintPlugin.route("/config/<filename>", methods=["DELETE"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def delete_config(self, filename):
|
||||
cfg_path = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
full_path = os.path.realpath(os.path.join(cfg_path, filename))
|
||||
if (
|
||||
full_path.startswith(cfg_path)
|
||||
and os.path.exists(full_path)
|
||||
and not is_hidden_path(full_path)
|
||||
):
|
||||
try:
|
||||
os.remove(full_path)
|
||||
except Exception:
|
||||
self._octoklipper_logger.exception("Could not delete {}".format(filename))
|
||||
raise
|
||||
return NO_CONTENT
|
||||
|
||||
# Get a list of all configfiles
|
||||
@octoprint.plugin.BlueprintPlugin.route("/config/list", methods=["GET"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def list_configs(self):
|
||||
files = cfgUtils.list_cfg_files(self, "")
|
||||
path = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
return flask.jsonify(files = files, path = path, max_upload_size = MAX_UPLOAD_SIZE)
|
||||
|
||||
# check syntax of a given data
|
||||
@octoprint.plugin.BlueprintPlugin.route("/config/check", methods=["POST"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def check_config(self):
|
||||
data = flask.request.json
|
||||
data_to_check = data.get("DataToCheck", [])
|
||||
response = cfgUtils.check_cfg_ok(self, data_to_check)
|
||||
return flask.jsonify(is_syntax_ok = response)
|
||||
|
||||
# save a configfile
|
||||
@octoprint.plugin.BlueprintPlugin.route("/config/save", methods=["POST"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def save_config(self):
|
||||
data = flask.request.json
|
||||
filename = data.get("filename", [])
|
||||
if filename == []:
|
||||
flask.abort(
|
||||
400,
|
||||
description="Invalid request, the filename is not set",
|
||||
)
|
||||
Filecontent = data.get("DataToSave", [])
|
||||
saved = cfgUtils.save_cfg(self, Filecontent, filename)
|
||||
if saved == True:
|
||||
util.send_message(self, type = "reload", subtype = "configlist")
|
||||
return flask.jsonify(saved = saved)
|
||||
|
||||
# restart klipper
|
||||
@octoprint.plugin.BlueprintPlugin.route("/restart", methods=["POST"])
|
||||
@restricted_access
|
||||
@Permissions.PLUGIN_KLIPPER_CONFIG.require(403)
|
||||
def restart_klipper(self):
|
||||
reload_command = self._settings.get(["configuration", "reload_command"])
|
||||
|
||||
if reload_command != "manually":
|
||||
|
||||
# Restart klippy to reload config
|
||||
self._printer.commands(reload_command)
|
||||
logger.log_info(self, "Restarting Klipper.")
|
||||
return flask.jsonify(command = reload_command)
|
||||
# APIs end
|
||||
|
||||
self._settings.set(["config"], data["config"])
|
||||
return flask.jsonify(data=data["config"])
|
||||
elif command == "checkConfig":
|
||||
if "config" in data:
|
||||
if not self.validate_configfile(data["config"]):
|
||||
self.log_debug("validateConfig not ok")
|
||||
self._settings.set(["configuration", "old_config"], data["config"])
|
||||
return flask.jsonify(checkConfig="not OK")
|
||||
else:
|
||||
self.log_debug("validateConfig ok")
|
||||
self._settings.set(["configuration", "old_config"], "")
|
||||
return flask.jsonify(checkConfig="OK")
|
||||
|
||||
def get_update_information(self):
|
||||
return dict(
|
||||
|
@ -526,129 +587,28 @@ class KlipperPlugin(
|
|||
)
|
||||
)
|
||||
|
||||
#-- Helpers
|
||||
def send_message(self, type, subtype, title, payload):
|
||||
self._plugin_manager.send_plugin_message(
|
||||
self._identifier,
|
||||
dict(
|
||||
time=datetime.datetime.now().strftime("%H:%M:%S"),
|
||||
type=type,
|
||||
subtype=subtype,
|
||||
title=title,
|
||||
payload=payload
|
||||
)
|
||||
)
|
||||
|
||||
def poll_status(self):
|
||||
self._printer.commands("STATUS")
|
||||
|
||||
def update_status(self, type, status):
|
||||
self.send_message("status", type, status, status)
|
||||
|
||||
def log_info(self, message):
|
||||
self._octoklipper_logger.info(message)
|
||||
self.send_message("log", "info", message, message)
|
||||
|
||||
def log_debug(self, message):
|
||||
self._octoklipper_logger.debug(message)
|
||||
self._logger.info(message)
|
||||
# sends a message to frontend(in klipper.js -> self.onDataUpdaterPluginMessage) and write it to the console.
|
||||
# _mtype, subtype=debug/info, title of message, message)
|
||||
self.send_message("console", "debug", message, message)
|
||||
|
||||
def log_error(self, error):
|
||||
self._octoklipper_logger.error(error)
|
||||
self._logger.info(error)
|
||||
self.send_message("log", "error", error, error)
|
||||
|
||||
def file_exist(self, filepath):
|
||||
if not os.path.isfile(filepath):
|
||||
self.send_message("PopUp", "warning", "OctoKlipper Settings",
|
||||
"Klipper " + filepath + " does not exist!")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def key_exist(self, dict, key1, key2):
|
||||
try:
|
||||
dict[key1][key2]
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def validate_configfile(self, dataToBeValidated):
|
||||
"""
|
||||
--->SyntaxCheck for a given data<----
|
||||
"""
|
||||
|
||||
try:
|
||||
dataToValidated = configparser.RawConfigParser(strict=False)
|
||||
#
|
||||
if sys.version_info[0] < 3:
|
||||
buf = StringIO.StringIO(dataToBeValidated)
|
||||
dataToValidated.readfp(buf)
|
||||
else:
|
||||
dataToValidated.read_string(dataToBeValidated)
|
||||
|
||||
sections_search_list = ["bltouch",
|
||||
"probe"]
|
||||
value_search_list = [ "x_offset",
|
||||
"y_offset",
|
||||
"z_offset"]
|
||||
try:
|
||||
# cycle through sections and then values
|
||||
for y in sections_search_list:
|
||||
for x in value_search_list:
|
||||
if dataToValidated.has_option(y, x):
|
||||
a_float = dataToValidated.getfloat(y, x)
|
||||
except ValueError as error:
|
||||
self.log_error(
|
||||
"Error: Invalid Value for <b>"+x+"</b> in Section: <b>"+y+"</b>\n" +
|
||||
"{}".format(str(error))
|
||||
)
|
||||
self.send_message("PopUp", "warning", "OctoKlipper: Invalid Config\n",
|
||||
"Config got not saved!\n" +
|
||||
"You can reload your last changes\n" +
|
||||
"on the 'Klipper Configuration' tab.\n\n" +
|
||||
"Invalid Value for <b>"+x+"</b> in Section: <b>"+y+"</b>\n" + "{}".format(str(error)))
|
||||
self._parsing_check_response = False
|
||||
return False
|
||||
except configparser.Error as error:
|
||||
if sys.version_info[0] < 3:
|
||||
error.message = error.message.replace("\\n","")
|
||||
error.message = error.message.replace("file: u","Klipper Configuration", 1)
|
||||
error.message = error.message.replace("'","", 2)
|
||||
error.message = error.message.replace("u'","'", 1)
|
||||
|
||||
else:
|
||||
error.message = error.message.replace("\\n","")
|
||||
error.message = error.message.replace("file:","Klipper Configuration", 1)
|
||||
error.message = error.message.replace("'","", 2)
|
||||
self.log_error(
|
||||
"Error: Invalid Klipper config file:\n" +
|
||||
"{}".format(str(error))
|
||||
)
|
||||
self.send_message("PopUp", "warning", "OctoKlipper: Invalid Config data\n",
|
||||
"Config got not saved!\n" +
|
||||
"You can reload your last changes\n" +
|
||||
"on the 'Klipper Configuration' tab.\n\n" + str(error))
|
||||
self._parsing_check_response = False
|
||||
return False
|
||||
else:
|
||||
self._parsing_check_response = True
|
||||
return True
|
||||
|
||||
__plugin_name__ = "OctoKlipper"
|
||||
__plugin_pythoncompat__ = ">=2.7,<4"
|
||||
|
||||
__plugin_settings_overlay__ = {
|
||||
'system': {
|
||||
'actions': [{
|
||||
'action': 'octoklipper_restart',
|
||||
'command': 'sudo service klipper restart',
|
||||
'name': gettext('Restart Klipper'),
|
||||
'confirm': '<h3><center><b>' + gettext("You are about to restart Klipper!") + '<br>' + gettext("This will stop ongoing prints!") + '</b></center></h3><br>Command = "sudo service klipper restart"'
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
def __plugin_load__():
|
||||
global __plugin_implementation__
|
||||
global __plugin_hooks__
|
||||
__plugin_implementation__ = KlipperPlugin()
|
||||
__plugin_hooks__ = {
|
||||
"octoprint.server.http.routes": __plugin_implementation__.route_hook,
|
||||
"octoprint.access.permissions": __plugin_implementation__.get_additional_permissions,
|
||||
"octoprint.comm.protocol.atcommand.sending": __plugin_implementation__.processAtCommand,
|
||||
"octoprint.comm.protocol.gcode.sent": __plugin_implementation__.process_sent_GCODE,
|
||||
"octoprint.comm.protocol.gcode.received": __plugin_implementation__.on_parse_gcode,
|
||||
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
|
||||
}
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import glob
|
||||
import os, time, sys
|
||||
import io
|
||||
import flask
|
||||
|
||||
from . import util, logger
|
||||
from flask_babel import gettext
|
||||
from shutil import copy, copyfile
|
||||
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import ConfigParser as configparser
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
import StringIO
|
||||
|
||||
|
||||
def list_cfg_files(self, path):
|
||||
"""Generate list of config files.
|
||||
|
||||
Args:
|
||||
path (str): Path to the config files.
|
||||
|
||||
Returns:
|
||||
list: for every file a dict with keys for name, file, size, mdate, url.
|
||||
"""
|
||||
|
||||
files = []
|
||||
if path=="backup":
|
||||
cfg_path = os.path.join(self.get_plugin_data_folder(), "configs", "*")
|
||||
else:
|
||||
cfg_path = os.path.expanduser(
|
||||
self._settings.get(["configuration", "config_path"])
|
||||
)
|
||||
cfg_path = os.path.join(cfg_path, "*.cfg")
|
||||
cfg_files = glob.glob(cfg_path)
|
||||
logger.log_debug(self, "list_cfg_files Path: " + cfg_path)
|
||||
|
||||
for f in cfg_files:
|
||||
filesize = os.path.getsize(f)
|
||||
filemdate = time.localtime(os.path.getmtime(f))
|
||||
if path != "backup":
|
||||
url = flask.url_for("index") + "plugin/klipper/download/configs/" + os.path.basename(f)
|
||||
else:
|
||||
url = flask.url_for("index") + "plugin/klipper/download/backup/" + os.path.basename(f)
|
||||
files.append(dict(
|
||||
name= os.path.basename(f),
|
||||
file= f,
|
||||
size= " ({:.1f} KB)".format(filesize / 1000.0),
|
||||
mdate= time.strftime("%d.%m.%Y %H:%M", filemdate),
|
||||
url= url,
|
||||
))
|
||||
logger.log_debug(self, "list_cfg_files " + str(len(files)) + ": " + f)
|
||||
return files
|
||||
|
||||
|
||||
def get_cfg(self, file):
|
||||
"""Get the content of a configuration file.
|
||||
|
||||
Args:
|
||||
file (str): The name of the file to read
|
||||
|
||||
Returns:
|
||||
dict:
|
||||
config (str): The configuration of the file
|
||||
text (str): The text of the error
|
||||
"""
|
||||
|
||||
response = {"config":"",
|
||||
"text": ""}
|
||||
if not file:
|
||||
cfg_path = os.path.expanduser(
|
||||
self._settings.get(["configuration", "configpath"])
|
||||
)
|
||||
file = os.path.join(cfg_path, self._settings.get(["configuration", "baseconfig"]))
|
||||
if util.file_exist(self, file):
|
||||
logger.log_debug(self, "get_cfg_files Path: " + file)
|
||||
try:
|
||||
with io.open(file, "r", encoding='utf-8') as f:
|
||||
response['config'] = f.read()
|
||||
except IOError as Err:
|
||||
logger.log_error(
|
||||
self,
|
||||
gettext("Error: Klipper config file not found at:")
|
||||
+ " {}".format(file)
|
||||
+ "\n"
|
||||
+ gettext("IOError:") + " {}".format(Err)
|
||||
)
|
||||
response['text'] = Err
|
||||
return response
|
||||
except UnicodeDecodeError as Err:
|
||||
logger.log_error(
|
||||
self,
|
||||
gettext("Decode Error:")
|
||||
+"\n"
|
||||
+ "{}".format(Err)
|
||||
+ "\n\n"
|
||||
+ gettext("Please convert your config files to utf-8!")
|
||||
+ "\n"
|
||||
+ gettext("Or you can also paste your config \ninto the Editor and save it.")
|
||||
)
|
||||
response['text'] = Err
|
||||
return response
|
||||
else:
|
||||
return response
|
||||
else:
|
||||
response['text'] = gettext("File not found!")
|
||||
return response
|
||||
|
||||
|
||||
def save_cfg(self, content, filename):
|
||||
"""Save the configuration file to given file.
|
||||
|
||||
Args:
|
||||
content (str): The content of the configuration.
|
||||
filename (str): The filename of the configuration file. Default is "printer.cfg"
|
||||
|
||||
Returns:
|
||||
bool: True if the configuration file was saved successfully. Otherwise False
|
||||
"""
|
||||
|
||||
logger.log_debug(
|
||||
self,
|
||||
"Save klipper config"
|
||||
)
|
||||
|
||||
|
||||
configpath = os.path.expanduser(self._settings.get(["configuration", "config_path"]))
|
||||
if filename == "":
|
||||
filename = self._settings.get(["configuration", "baseconfig"])
|
||||
if filename[-4:] != ".cfg":
|
||||
filename += ".cfg"
|
||||
|
||||
filepath = os.path.join(configpath, filename)
|
||||
|
||||
logger.log_debug(self, "Writing Klipper config to {}".format(filepath))
|
||||
try:
|
||||
with io.open(filepath, "w", encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
except IOError:
|
||||
logger.log_error(self, "Error: Couldn't open Klipper config file: {}".format(filepath))
|
||||
return False
|
||||
else:
|
||||
logger.log_debug(self, "Written Klipper config to {}".format(filepath))
|
||||
return True
|
||||
finally:
|
||||
copy_cfg_to_backup(self, filepath)
|
||||
|
||||
|
||||
def check_cfg_ok(self, data):
|
||||
"""Checks the given data on parsing errors.
|
||||
|
||||
Args:
|
||||
data (str): Content to be validated.
|
||||
|
||||
Returns:
|
||||
bool: True if the data is valid. False if it is not.
|
||||
"""
|
||||
try:
|
||||
dataToValidated = configparser.RawConfigParser(strict=False)
|
||||
if sys.version_info[0] < 3:
|
||||
import StringIO
|
||||
buf = StringIO.StringIO(data)
|
||||
dataToValidated.readfp(buf)
|
||||
else:
|
||||
dataToValidated.read_string(data)
|
||||
except configparser.Error as error:
|
||||
show_error_message(self, error)
|
||||
logger.log_debug(self, 'check_cfg: NOK!')
|
||||
return False
|
||||
else:
|
||||
if not is_float_ok(self, dataToValidated):
|
||||
logger.log_debug(self, "check_cfg: NOK!")
|
||||
return False
|
||||
logger.log_debug(self, "check_cfg: OK")
|
||||
return True
|
||||
|
||||
|
||||
def show_error_message(self, error):
|
||||
error.message = error.message.replace('\\n', '')
|
||||
if sys.version_info[0] < 3:
|
||||
error.message = error.message.replace('file: u', 'Klipper Configuration', 1)
|
||||
error.message = error.message.replace("'", '', 2)
|
||||
error.message = error.message.replace("u'", "'", 1)
|
||||
else:
|
||||
error.message = error.message.replace('file:', 'Klipper Configuration', 1)
|
||||
error.message = error.message.replace("'", '', 2)
|
||||
logger.log_error(
|
||||
self,
|
||||
('Error: Invalid Klipper config file:\n' + '{}'.format(str(error))),
|
||||
)
|
||||
|
||||
|
||||
def is_float_ok(self, dataToValidated):
|
||||
|
||||
sections_search_list = [
|
||||
"bltouch",
|
||||
"probe"
|
||||
]
|
||||
value_search_list = [
|
||||
"x_offset",
|
||||
"y_offset",
|
||||
"z_offset"
|
||||
]
|
||||
try:
|
||||
# cycle through sections and then values
|
||||
for y in sections_search_list:
|
||||
for x in value_search_list:
|
||||
if dataToValidated.has_option(y, x):
|
||||
a_float = dataToValidated.getfloat(y, x)
|
||||
except ValueError as error:
|
||||
logger.log_error(
|
||||
self,
|
||||
"Error: Invalid Value for <b>" + x + "</b> in Section: <b>" + y + "</b>\n"
|
||||
+ "{}".format(str(error))
|
||||
)
|
||||
util.send_message(
|
||||
self,
|
||||
type = "PopUp",
|
||||
subtype = "warning",
|
||||
title = "Invalid Config data\n",
|
||||
payload = "\n"
|
||||
+ "Invalid Value for <b>" + x + "</b> in Section: <b>" + y + "</b>\n"
|
||||
+ "{}".format(str(error))
|
||||
)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def copy_cfg(self, file, dst):
|
||||
"""Copy the config file to the destination.
|
||||
|
||||
Args:
|
||||
file (str): Filepath of the config file to copy.
|
||||
dst (str): Path to copy the config file to.
|
||||
|
||||
Returns:
|
||||
bool: True if the copy succeeded, False otherwise.
|
||||
"""
|
||||
|
||||
if os.path.isfile(file):
|
||||
try:
|
||||
copy(file, dst)
|
||||
except IOError:
|
||||
logger.log_error(
|
||||
self,
|
||||
"Error: Klipper config file not found at: {}".format(file)
|
||||
)
|
||||
return False
|
||||
else:
|
||||
logger.log_debug(
|
||||
self,
|
||||
"File copied: "
|
||||
+ file
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def copy_cfg_to_backup(self, src):
|
||||
"""Copy the config file to backup directory of OctoKlipper.
|
||||
|
||||
Args:
|
||||
src (str): Path to the config file to copy.
|
||||
|
||||
Returns:
|
||||
bool: True if the config file was copied successfully. False otherwise.
|
||||
"""
|
||||
|
||||
if not os.path.isfile(src):
|
||||
return False
|
||||
|
||||
cfg_path = os.path.join(self.get_plugin_data_folder(), "configs", "")
|
||||
filename = os.path.basename(src)
|
||||
if not os.path.exists(cfg_path):
|
||||
try:
|
||||
os.mkdir(cfg_path)
|
||||
except OSError:
|
||||
logger.log_error(self, "Error: Creation of the backup directory {} failed".format(cfg_path))
|
||||
return False
|
||||
else:
|
||||
logger.log_debug(self, "Directory {} created".format(cfg_path))
|
||||
|
||||
dst = os.path.join(cfg_path, filename)
|
||||
logger.log_debug(self, "copy_cfg_to_backup:" + src + " to " + dst)
|
||||
if src == dst:
|
||||
return False
|
||||
try:
|
||||
copyfile(src, dst)
|
||||
except IOError:
|
||||
logger.log_error(
|
||||
self,
|
||||
"Error: Couldn't copy Klipper config file to {}".format(dst)
|
||||
)
|
||||
return False
|
||||
else:
|
||||
logger.log_debug(self, "CfgBackup " + dst + " written")
|
||||
return True
|
|
@ -0,0 +1,33 @@
|
|||
from . import util
|
||||
|
||||
def log_info(self, message):
|
||||
self._octoklipper_logger.info(message)
|
||||
util.send_message(
|
||||
self,
|
||||
type = "log",
|
||||
subtype = "info",
|
||||
title = message,
|
||||
payload = message
|
||||
)
|
||||
|
||||
def log_debug(self, message):
|
||||
self._octoklipper_logger.debug(message)
|
||||
self._logger.info(message)
|
||||
util.send_message(
|
||||
self,
|
||||
type = "console",
|
||||
subtype = "debug",
|
||||
title = message,
|
||||
payload = message
|
||||
)
|
||||
|
||||
def log_error(self, error):
|
||||
self._octoklipper_logger.error(error)
|
||||
self._logger.error(error)
|
||||
util.send_message(
|
||||
self,
|
||||
type = "log",
|
||||
subtype = "error",
|
||||
title = error,
|
||||
payload = error
|
||||
)
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import flask
|
||||
import optparse, datetime
|
||||
from .. import logger
|
||||
|
||||
class KlipperLogAnalyzer():
|
||||
MAXBANDWIDTH=25000.
|
||||
|
@ -81,6 +82,7 @@ class KlipperLogAnalyzer():
|
|||
out.append(keyparts)
|
||||
f.close()
|
||||
except IOError:
|
||||
logger.log_error(self, "Couldn't open log file: {}".format(logname))
|
||||
print("Couldn't open log file")
|
||||
return out
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["OctoPrintClient"], factory);
|
||||
} else {
|
||||
factory(global.OctoPrintClient);
|
||||
}
|
||||
})(this, function (OctoPrintClient) {
|
||||
var OctoKlipperClient = function (base) {
|
||||
this.base = base;
|
||||
this.url = this.base.getBlueprintUrl("klipper");
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.restartKlipper = function (opts) {
|
||||
return this.base.post(this.url + "restart", opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.getCfg = function (config, opts) {
|
||||
return this.base.get(this.url + "config/" + config, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.getCfgBak = function (backup, opts) {
|
||||
return this.base.get(this.url + "backup/" + backup, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.listCfg = function (opts) {
|
||||
return this.base.get(this.url + "config/list", opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.listCfgBak = function (opts) {
|
||||
return this.base.get(this.url + "backup/list", opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.checkCfg = function (content, opts) {
|
||||
content = content || [];
|
||||
|
||||
var data = {
|
||||
DataToCheck: content,
|
||||
};
|
||||
|
||||
return this.base.postJson(this.url + "config/check", data, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.saveCfg = function (content, filename, opts) {
|
||||
content = content || [];
|
||||
filename = filename || [];
|
||||
|
||||
var data = {
|
||||
DataToSave: content,
|
||||
filename: filename,
|
||||
};
|
||||
|
||||
return this.base.postJson(this.url + "config/save", data, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.deleteCfg = function (config, opts) {
|
||||
return this.base.delete(this.url + "config/" + config, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.deleteBackup = function (backup, opts) {
|
||||
return this.base.delete(this.url + "backup/" + backup, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.restoreBackup = function (backup, opts) {
|
||||
return this.base.get(this.url + "backup/restore/" + backup, opts);
|
||||
};
|
||||
|
||||
OctoKlipperClient.prototype.restoreBackupFromUpload = function (file, data) {
|
||||
data = data || {};
|
||||
|
||||
var filename = data.filename || undefined;
|
||||
return this.base.upload(this.url + "restore", file, filename, data);
|
||||
};
|
||||
|
||||
OctoPrintClient.registerPluginComponent("klipper", OctoKlipperClient);
|
||||
return OctoKlipperClient;
|
||||
});
|
|
@ -1,238 +1,384 @@
|
|||
.plugin-klipper-sidebar {
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
border: 1px solid #aaa;
|
||||
width: 98%;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
margin: auto;
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
border: 1px solid #aaa;
|
||||
width: 98%;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
li#navbar_plugin_klipper {
|
||||
cursor: pointer;
|
||||
max-width:360px;
|
||||
max-height:80px;
|
||||
word-break: break-all;
|
||||
cursor: pointer;
|
||||
max-width: 360px;
|
||||
max-height: 80px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.plugin-klipper-sidebar a {
|
||||
padding: 2px 2px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
padding: 2px 2px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.plugin-klipper-sidebar a:hover, .plugin-klipper-sidebar a:active {
|
||||
cursor: pointer;
|
||||
}
|
||||
.plugin-klipper-sidebar a:hover,
|
||||
.plugin-klipper-sidebar a:active {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.plugin-klipper-log {
|
||||
padding: 0px;
|
||||
overflow-y: scroll;
|
||||
height: 400px;
|
||||
border: 1px solid #eee;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
padding: 0px;
|
||||
overflow-y: scroll;
|
||||
height: 400px;
|
||||
border: 1px solid #eee;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.plugin-klipper-log .log-item {
|
||||
margin: 3px auto 0 auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
background-color: #efefef;
|
||||
color: #333;
|
||||
margin: 3px auto 0 auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
background-color: #efefef;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.plugin-klipper-log .error {
|
||||
background-color: #eebabb;
|
||||
background-color: #eebabb;
|
||||
}
|
||||
|
||||
.plugin-klipper-log .log-item .ts {
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
font-size: 0.8em;
|
||||
padding: 0 0 0 5px;
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
font-size: 0.8em;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
.plugin-klipper-log .log-item .msg {
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
#level .controls {
|
||||
padding: 1px;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
ul#klipper-settings {
|
||||
margin: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#klipper-settings a{
|
||||
margin: 5px;
|
||||
#klipper-settings a {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
#tab_plugin_klipper_main .row-fluid {
|
||||
display: flex;
|
||||
flex: row wrap;
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
@media all and (max-width: 940px) {
|
||||
#tab_plugin_klipper_main .row-fluid {
|
||||
/* On small screens, we are no longer using row direction but column */
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
#tab_plugin_klipper_main .row-fluid {
|
||||
/* On small screens, we are no longer using row direction but column */
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
#tab_plugin_klipper_main #left-side {
|
||||
flex: 3 1;
|
||||
padding-right: 10px;
|
||||
flex: 3 1;
|
||||
padding-right: 10px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#tab_plugin_klipper_main .span8 label {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#tab_plugin_klipper_main #right-side {
|
||||
flex: 1 1;
|
||||
max-width: 200px;
|
||||
min-width: 100px;
|
||||
flex: 1 1;
|
||||
max-width: 200px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.klipper-row-fluid {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.klipper-column-fluid {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.klipper-fluid-item-1 {
|
||||
flex: 1 auto;
|
||||
}
|
||||
|
||||
.klipper-fluid-item-2 {
|
||||
flex: 2 auto;
|
||||
}
|
||||
|
||||
.klipper-fluid-item-3 {
|
||||
flex: 3 auto;
|
||||
}
|
||||
|
||||
.gap {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
@media all and (max-width: 940px) {
|
||||
.klipper-row-fluid {
|
||||
/* On small screens, we are no longer using row direction but column */
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
#settings_plugin_klipper {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
height: -webkit-fill-available;
|
||||
}
|
||||
|
||||
div#klipper_backups_dialog {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
div#klipper_backups_dialog div.modal-body {
|
||||
min-height: 350px;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
div#klipper_backups_dialog .editor-controls {
|
||||
flex: 0 auto;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
div#klipper_backups_dialog div.modal-body .textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div#klipper_backups_dialog div.modal-body textarea {
|
||||
margin-bottom: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* UIcustomizer fix */
|
||||
body.UICResponsiveMode #settings_dialog_content {
|
||||
height: calc(100% - 60px);
|
||||
margin-right: -18px;
|
||||
margin-top: 50px;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper form {
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper form .tab-content {
|
||||
height: calc(100% - 40px);
|
||||
overflow: auto;
|
||||
div#settings_plugin_klipper div.tab-content {
|
||||
height: calc(100% - 76px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content .border{
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-footer {
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
top: 10px;
|
||||
position: relative;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content div#conf.tab-pane {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
min-height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content div#conf.tab-pane div.control-group {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content div#conf.tab-pane div.control-group div.editor-controls{
|
||||
margin-bottom: 0px;
|
||||
height: 26px;
|
||||
.klipper-settings-tab {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content div#conf.tab-pane div.control-group div.conf-editor {
|
||||
height: 95%;
|
||||
height: calc(100% - 28px);
|
||||
width: 99%;
|
||||
width: calc(100% - 4px);
|
||||
padding-top: 2px;
|
||||
flex: 1 1;
|
||||
overflow: auto;
|
||||
#settings_plugin_klipper .m-0 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper div.tab-content div#conf.tab-pane div.control-group div.conf-editor div#plugin-klipper-config {
|
||||
font-family: monospace;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
height: -webkit-fill-available;
|
||||
#settings_plugin_klipper .scroll-y {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div#conf.tab-pane.active button.btn.btn-small {
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
margin: 0px 2px 2px 2px;
|
||||
#settings_plugin_klipper table {
|
||||
table-layout: unset !important;
|
||||
}
|
||||
|
||||
#settings_plugin_klipper .table-fixed thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background-color: rgba(12, 5, 5, 0.85);
|
||||
color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
#settings_plugin_klipper .pagination-mini {
|
||||
margin: 5;
|
||||
}
|
||||
|
||||
@media (max-width: 979px) {
|
||||
|
||||
/* div#klipper_editor.modal {
|
||||
height: unset !important;
|
||||
} */
|
||||
|
||||
div#klipper_editor .modal-footer .btn {
|
||||
margin-bottom: 1px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.octoprint-container.UICMainCont.container-fluid {
|
||||
margin-top:0px !important;
|
||||
}
|
||||
|
||||
div#klipper_editor .modal-header div button.btn + button.btn {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
div#klipper_editor .modal-body {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.klipper-btn-group {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div#klipper_editor .modal-footer input[type="text"] {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
|
||||
div#klipper_editor .modal-footer .editor-controls {
|
||||
flex: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
div#klipper_editor div.conf-editor {
|
||||
width: 99%;
|
||||
width: calc(100% - 4px);
|
||||
margin-top: 5px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div#klipper_editor div.conf-editor div#plugin-klipper-config {
|
||||
font-family: monospace;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/*checkboxes*/
|
||||
div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div.tab-pane.active input.inline-checkbox {
|
||||
vertical-align: -0.2em;
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div.tab-pane.active label.inline {
|
||||
display: inline;
|
||||
.klipper-inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div.tab-pane.active div.controls input.controls-checkbox {
|
||||
margin-top: 8px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/*macros*/
|
||||
div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div#macros.tab-pane.active div div#item.control-group label.control-label {
|
||||
width: 80px;
|
||||
div#settings_plugin_klipper div#macros label.control-label {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
#macros #item.control-group {
|
||||
margin-bottom: 2px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 3px;
|
||||
background-color: #eeeeee;
|
||||
color: #333;
|
||||
padding-bottom: 2px;
|
||||
padding-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 3px;
|
||||
background-color: #eeeeee;
|
||||
color: #333;
|
||||
padding-bottom: 2px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog {
|
||||
width: 1050px;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog .full-sized-box{
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
#klipper_graph_dialog .full-sized-box {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog form {
|
||||
margin: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog select {
|
||||
width: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog .graph-footer {
|
||||
bottom:0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog input {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog .status-label {
|
||||
display: block;
|
||||
position: absolute;
|
||||
margin: 5px 0 0 10px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
margin: 5px 0 0 10px;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog .fill-checkbox {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
#klipper_graph_dialog .help-inline {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#klipper_graph_canvas {
|
||||
margin-top: 15px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
|
|
@ -14,251 +14,337 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
$(function () {
|
||||
function KlipperViewModel(parameters) {
|
||||
var self = this;
|
||||
function KlipperViewModel(parameters) {
|
||||
var self = this;
|
||||
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache"
|
||||
});
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache",
|
||||
});
|
||||
|
||||
self.apiUrl = OctoPrint.getSimpleApiUrl("klipper");
|
||||
self.apiUrl = OctoPrint.getSimpleApiUrl("klipper");
|
||||
self.Url = OctoPrint.getBlueprintUrl("klipper");
|
||||
|
||||
self.settings = parameters[0];
|
||||
self.loginState = parameters[1];
|
||||
self.connectionState = parameters[2];
|
||||
self.levelingViewModel = parameters[3];
|
||||
self.paramMacroViewModel = parameters[4];
|
||||
self.access = parameters[5];
|
||||
self.settings = parameters[0];
|
||||
self.loginState = parameters[1];
|
||||
self.connectionState = parameters[2];
|
||||
self.levelingViewModel = parameters[3];
|
||||
self.paramMacroViewModel = parameters[4];
|
||||
self.access = parameters[5];
|
||||
|
||||
self.shortStatus_navbar = ko.observable();
|
||||
self.shortStatus_sidebar = ko.observable();
|
||||
self.logMessages = ko.observableArray();
|
||||
self.shortStatus_navbar = ko.observable();
|
||||
self.shortStatus_navbar_hover = ko.observable();
|
||||
self.shortStatus_sidebar = ko.observable();
|
||||
self.logMessages = ko.observableArray();
|
||||
|
||||
self.showPopUp = function(popupType, popupTitle, message){
|
||||
var title = popupType.toUpperCase() + ": " + popupTitle;
|
||||
new PNotify({
|
||||
title: title,
|
||||
text: message,
|
||||
type: popupType,
|
||||
hide: false
|
||||
});
|
||||
};
|
||||
self.showPopUp = function (popupType, popupTitle, message) {
|
||||
var title = "OctoKlipper: <br />" + popupTitle + "<br />";
|
||||
var hide = false;
|
||||
if (popupType == "success") {
|
||||
hide = true
|
||||
}
|
||||
new PNotify({
|
||||
title: title,
|
||||
text: message,
|
||||
type: popupType,
|
||||
hide: hide,
|
||||
icon: true
|
||||
});
|
||||
};
|
||||
|
||||
self.onSettingsShown = function () {
|
||||
self.reloadConfig();
|
||||
}
|
||||
|
||||
self.showLevelingDialog = function () {
|
||||
var dialog = $("#klipper_leveling_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
keyboard: false
|
||||
});
|
||||
self.levelingViewModel.initView();
|
||||
};
|
||||
|
||||
self.showPidTuningDialog = function () {
|
||||
var dialog = $("#klipper_pid_tuning_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
keyboard: false
|
||||
});
|
||||
};
|
||||
|
||||
self.showOffsetDialog = function () {
|
||||
var dialog = $("#klipper_offset_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static"
|
||||
});
|
||||
};
|
||||
|
||||
self.showGraphDialog = function () {
|
||||
var dialog = $("#klipper_graph_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
minHeight: "500px",
|
||||
maxHeight: "600px"
|
||||
});
|
||||
};
|
||||
|
||||
self.executeMacro = function (macro) {
|
||||
var paramObjRegex = /{(.*?)}/g;
|
||||
|
||||
if (!self.hasRight("MACRO")) return;
|
||||
|
||||
if (macro.macro().match(paramObjRegex) == null) {
|
||||
OctoPrint.control.sendGcode(
|
||||
// Use .split to create an array of strings which is sent to
|
||||
// OctoPrint.control.sendGcode instead of a single string.
|
||||
macro.macro().split(/\r\n|\r|\n/)
|
||||
);
|
||||
} else {
|
||||
self.paramMacroViewModel.process(macro);
|
||||
|
||||
var dialog = $("#klipper_macro_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.navbarClicked = function () {
|
||||
$("#tab_plugin_klipper_main_link").find("a").click();
|
||||
};
|
||||
|
||||
self.onGetStatus = function () {
|
||||
OctoPrint.control.sendGcode("Status");
|
||||
};
|
||||
|
||||
self.onRestartFirmware = function () {
|
||||
OctoPrint.control.sendGcode("FIRMWARE_RESTART");
|
||||
};
|
||||
|
||||
self.onRestartHost = function () {
|
||||
OctoPrint.control.sendGcode("RESTART");
|
||||
};
|
||||
|
||||
self.onAfterBinding = function () {
|
||||
self.connectionState.selectedPort(
|
||||
self.settings.settings.plugins.klipper.connection.port()
|
||||
);
|
||||
};
|
||||
|
||||
self.onDataUpdaterPluginMessage = function(plugin, data) {
|
||||
if(plugin == "klipper") {
|
||||
switch(data.type) {
|
||||
case "PopUp":
|
||||
self.showPopUp(data.subtype, data.title, data.payload);
|
||||
break;
|
||||
case "reload":
|
||||
break;
|
||||
case "console":
|
||||
self.consoleMessage(data.subtype, data.payload);
|
||||
break;
|
||||
case "status":
|
||||
if (data.payload.length > 36) {
|
||||
var shortText = data.payload.substring(0, 31) + " [..]"
|
||||
self.shortStatus_navbar(shortText);
|
||||
} else {
|
||||
self.shortStatus_navbar(data.payload);
|
||||
}
|
||||
self.shortStatus_sidebar(data.payload);
|
||||
break;
|
||||
default:
|
||||
self.logMessage(data.time, data.subtype, data.payload);
|
||||
self.consoleMessage(data.subtype, data.payload);
|
||||
}
|
||||
|
||||
//if ("warningPopUp" == data.type){
|
||||
// self.showPopUp(data.subtype, data.title, data.payload);
|
||||
// return;
|
||||
//} else if ("errorPopUp" == data.type){
|
||||
// self.showPopUp(data.subtype, data.title, data.payload);
|
||||
// return;
|
||||
//} else if ("reload" == data.type){
|
||||
// return;
|
||||
//} else if ("console" == data.type) {
|
||||
// self.consoleMessage(data.subtype, data.payload);
|
||||
//} else if (data.type == "status") {
|
||||
// self.shortStatus(data.payload);
|
||||
//} else {
|
||||
// self.logMessage(data.time, data.subtype, data.payload);
|
||||
//}
|
||||
}
|
||||
};
|
||||
|
||||
self.logMessage = function (timestamp, type="info", message) {
|
||||
if (!timestamp) {
|
||||
var today = new Date();
|
||||
var timestamp = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
|
||||
}
|
||||
self.logMessages.push({
|
||||
time: timestamp,
|
||||
type: type,
|
||||
msg: message.replace(/\n/gi, "<br>")
|
||||
});
|
||||
};
|
||||
|
||||
self.consoleMessage = function (type, message) {
|
||||
if (self.settings.settings.plugins.klipper.configuration.debug_logging() === true) {
|
||||
if (type == "info"){
|
||||
console.info("OctoKlipper : " + message);
|
||||
} else if (type == "debug"){
|
||||
console.debug("OctoKlipper : " + message);
|
||||
} else {
|
||||
console.error("OctoKlipper : " + message);
|
||||
}
|
||||
}
|
||||
return
|
||||
};
|
||||
|
||||
self.reloadConfig = function() {
|
||||
var settings = {
|
||||
"crossDomain": true,
|
||||
"url": self.apiUrl,
|
||||
"method": "POST",
|
||||
"headers": self.header,
|
||||
"processData": false,
|
||||
"dataType": "json",
|
||||
"data": JSON.stringify({command: "reloadConfig"})
|
||||
}
|
||||
|
||||
$.ajax(settings).done(function (response) {
|
||||
self.consoleMessage(
|
||||
"debug",
|
||||
"Reloaded config file from Backend");
|
||||
});
|
||||
}
|
||||
|
||||
self.onClearLog = function () {
|
||||
self.logMessages.removeAll();
|
||||
};
|
||||
|
||||
self.isActive = function () {
|
||||
return self.connectionState.isOperational();
|
||||
};
|
||||
|
||||
self.hasRight = function (right_role, type) {
|
||||
var arg = eval("self.access.permissions.PLUGIN_KLIPPER_" + right_role);
|
||||
|
||||
if (type == "Ko") {
|
||||
return self.loginState.hasPermissionKo(arg);
|
||||
}
|
||||
return self.loginState.hasPermission(arg);
|
||||
};
|
||||
|
||||
// OctoKlipper settings link
|
||||
self.openOctoKlipperSettings = function (profile_type) {
|
||||
if (!self.hasRight("CONFIG")) return;
|
||||
|
||||
$("a#navbar_show_settings").click();
|
||||
$("li#settings_plugin_klipper_link a").click();
|
||||
if (profile_type) {
|
||||
var query = "#klipper-settings a[data-profile-type='" + profile_type + "']";
|
||||
$(query).click();
|
||||
}
|
||||
};
|
||||
self.showEditorDialog = function () {
|
||||
if (!self.hasRight("CONFIG")) return;
|
||||
var editorDialog = $("#klipper_editor");
|
||||
editorDialog.modal({
|
||||
show: "true",
|
||||
width: "90%",
|
||||
backdrop: "static",
|
||||
});
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperViewModel,
|
||||
dependencies: [
|
||||
"settingsViewModel",
|
||||
"loginStateViewModel",
|
||||
"connectionViewModel",
|
||||
"klipperLevelingViewModel",
|
||||
"klipperMacroDialogViewModel",
|
||||
"accessViewModel"
|
||||
],
|
||||
elements: [
|
||||
"#tab_plugin_klipper_main",
|
||||
"#sidebar_plugin_klipper",
|
||||
"#navbar_plugin_klipper"
|
||||
]
|
||||
});
|
||||
self.showLevelingDialog = function () {
|
||||
var dialog = $("#klipper_leveling_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
self.levelingViewModel.initView();
|
||||
};
|
||||
|
||||
self.showPidTuningDialog = function () {
|
||||
var dialog = $("#klipper_pid_tuning_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
keyboard: false,
|
||||
});
|
||||
};
|
||||
|
||||
self.showOffsetDialog = function () {
|
||||
var dialog = $("#klipper_offset_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
});
|
||||
};
|
||||
|
||||
self.showGraphDialog = function () {
|
||||
var dialog = $("#klipper_graph_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
width: "90%",
|
||||
minHeight: "500px",
|
||||
maxHeight: "600px",
|
||||
});
|
||||
};
|
||||
|
||||
self.executeMacro = function (macro) {
|
||||
var paramObjRegex = /{(.*?)}/g;
|
||||
|
||||
if (!self.hasRight("MACRO")) return;
|
||||
|
||||
if (macro.macro().match(paramObjRegex) == null) {
|
||||
OctoPrint.control.sendGcode(
|
||||
// Use .split to create an array of strings which is sent to
|
||||
// OctoPrint.control.sendGcode instead of a single string.
|
||||
macro.macro().split(/\r\n|\r|\n/)
|
||||
);
|
||||
} else {
|
||||
self.paramMacroViewModel.process(macro);
|
||||
|
||||
var dialog = $("#klipper_macro_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
backdrop: "static",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.navbarClicked = function () {
|
||||
$("#tab_plugin_klipper_main_link").find("a").click();
|
||||
};
|
||||
|
||||
self.onGetStatus = function () {
|
||||
OctoPrint.control.sendGcode("Status");
|
||||
};
|
||||
|
||||
self.onRestartFirmware = function () {
|
||||
OctoPrint.control.sendGcode("FIRMWARE_RESTART");
|
||||
};
|
||||
|
||||
self.onRestartHost = function () {
|
||||
OctoPrint.control.sendGcode("RESTART");
|
||||
};
|
||||
|
||||
self.onAfterBinding = function () {
|
||||
self.connectionState.selectedPort(
|
||||
self.settings.settings.plugins.klipper.connection.port()
|
||||
);
|
||||
};
|
||||
|
||||
self.onDataUpdaterPluginMessage = function (plugin, data) {
|
||||
|
||||
if (plugin == "klipper") {
|
||||
switch (data.type) {
|
||||
case "PopUp":
|
||||
self.showPopUp(data.subtype, data.title, data.payload);
|
||||
break;
|
||||
case "reload":
|
||||
break;
|
||||
case "console":
|
||||
self.consoleMessage(data.subtype, data.payload);
|
||||
break;
|
||||
case "status":
|
||||
self.shortStatus(data.payload, data.subtype);
|
||||
break;
|
||||
default:
|
||||
self.logMessage(data.time, data.subtype, data.payload);
|
||||
self.shortStatus(data.payload, data.subtype)
|
||||
self.consoleMessage(data.subtype, data.payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
self.shortStatus = function(msg, type) {
|
||||
|
||||
var baseText = gettext("Go to OctoKlipper Tab");
|
||||
if (msg.length > 36) {
|
||||
var shortText = msg.substring(0, 31) + " [..]";
|
||||
self.shortStatus_navbar(shortText);
|
||||
self.shortStatus_navbar_hover(msg);
|
||||
} else {
|
||||
self.shortStatus_navbar(msg);
|
||||
self.shortStatus_navbar_hover(baseText);
|
||||
}
|
||||
message = msg.replace(/\n/gi, "<br />");
|
||||
self.shortStatus_sidebar(message);
|
||||
};
|
||||
|
||||
|
||||
self.logMessage = function (timestamp, type = "info", message) {
|
||||
|
||||
if (!timestamp) {
|
||||
var today = new Date();
|
||||
var timestamp =
|
||||
today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
|
||||
}
|
||||
|
||||
if (type == "error") {
|
||||
self.showPopUp(type, "Error:", message);
|
||||
}
|
||||
|
||||
self.logMessages.push({
|
||||
time: timestamp,
|
||||
type: type,
|
||||
msg: message.replace(/\n/gi, "<br />"),
|
||||
});
|
||||
};
|
||||
|
||||
self.consoleMessage = function (type, message) {
|
||||
if (
|
||||
self.settings.settings.plugins.klipper.configuration.debug_logging() === true
|
||||
) {
|
||||
if (type == "info") {
|
||||
console.info("OctoKlipper : " + message);
|
||||
} else if (type == "debug") {
|
||||
console.debug("OctoKlipper : " + message);
|
||||
} else {
|
||||
console.error("OctoKlipper : " + message);
|
||||
}
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
self.onClearLog = function () {
|
||||
self.logMessages.removeAll();
|
||||
};
|
||||
|
||||
self.isActive = function () {
|
||||
return self.connectionState.isOperational();
|
||||
};
|
||||
|
||||
self.hasRight = function (right_role) {
|
||||
//if (self.loginState.isAdmin) return true;
|
||||
if (right_role == "CONFIG") {
|
||||
return self.loginState.hasPermission(
|
||||
self.access.permissions.PLUGIN_KLIPPER_CONFIG
|
||||
);
|
||||
} else if (right_role == "MACRO") {
|
||||
return self.loginState.hasPermission(
|
||||
self.access.permissions.PLUGIN_KLIPPER_MACRO
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
self.hasRightKo = function (right_role) {
|
||||
//if (self.loginState.isAdmin) return true;
|
||||
if (right_role == "CONFIG") {
|
||||
return self.loginState.hasPermissionKo(
|
||||
self.access.permissions.PLUGIN_KLIPPER_CONFIG
|
||||
);
|
||||
} else if (right_role == "MACRO") {
|
||||
return self.loginState.hasPermissionKo(
|
||||
self.access.permissions.PLUGIN_KLIPPER_MACRO
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
self.saveOption = function(dir, option, value) {
|
||||
if (! (_.includes(["fontsize", "confirm_reload", "parse_check"], option)) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (option && dir) {
|
||||
let data = {
|
||||
plugins: {
|
||||
klipper:{
|
||||
[dir]: {
|
||||
[option]: value
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
OctoPrint.settings
|
||||
.save(data);
|
||||
} else if (option) {
|
||||
let data = {
|
||||
plugins: {
|
||||
klipper:{
|
||||
[option]: value
|
||||
}
|
||||
}
|
||||
};
|
||||
OctoPrint.settings
|
||||
.save(data);
|
||||
}
|
||||
}
|
||||
|
||||
self.requestRestart = function () {
|
||||
if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return;
|
||||
|
||||
var request = function (index) {
|
||||
OctoPrint.plugins.klipper.restartKlipper().done(function (response) {
|
||||
self.consoleMessage("debug", "restartingKlipper");
|
||||
self.showPopUp("success", gettext("Restarted Klipper"), "command: " + response.command);
|
||||
});
|
||||
if (index == 1) {
|
||||
self.saveOption("configuration", "confirm_reload", false);
|
||||
}
|
||||
};
|
||||
|
||||
var html = "<h4>" +
|
||||
gettext("All ongoing Prints will be stopped!") +
|
||||
"</h4>";
|
||||
|
||||
if (self.settings.settings.plugins.klipper.configuration.confirm_reload() == true) {
|
||||
showConfirmationDialog({
|
||||
title: gettext("Restart Klipper?"),
|
||||
html: html,
|
||||
proceed: [gettext("Restart"), gettext("Restart and don't ask this again.")],
|
||||
onproceed: function (idx) {
|
||||
if (idx > -1) {
|
||||
request(idx);
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
request(0);
|
||||
}
|
||||
};
|
||||
|
||||
// OctoKlipper settings link
|
||||
self.openOctoKlipperSettings = function (profile_type) {
|
||||
if (!self.hasRight("CONFIG")) return;
|
||||
|
||||
$("a#navbar_show_settings").click();
|
||||
$("li#settings_plugin_klipper_link a").click();
|
||||
if (profile_type) {
|
||||
var query = "#klipper-settings a[data-profile-type='" + profile_type + "']";
|
||||
$(query).click();
|
||||
}
|
||||
};
|
||||
|
||||
self.sleep = function (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
};
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperViewModel,
|
||||
dependencies: [
|
||||
"settingsViewModel",
|
||||
"loginStateViewModel",
|
||||
"connectionViewModel",
|
||||
"klipperLevelingViewModel",
|
||||
"klipperMacroDialogViewModel",
|
||||
"accessViewModel",
|
||||
],
|
||||
elements: [
|
||||
"#tab_plugin_klipper_main",
|
||||
"#sidebar_plugin_klipper",
|
||||
"#navbar_plugin_klipper",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
// <Octoprint Klipper Plugin>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
$(function () {
|
||||
function KlipperBackupViewModel(parameters) {
|
||||
var self = this;
|
||||
|
||||
self.loginState = parameters[0];
|
||||
self.klipperViewModel = parameters[1];
|
||||
self.access = parameters[2];
|
||||
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache",
|
||||
});
|
||||
|
||||
self.apiUrl = OctoPrint.getSimpleApiUrl("klipper");
|
||||
self.Url = OctoPrint.getBlueprintUrl("klipper");
|
||||
|
||||
self.markedForFileRestore = ko.observableArray([]);
|
||||
|
||||
self.CfgContent = ko.observable();
|
||||
|
||||
//uploads
|
||||
self.maxUploadSize = ko.observable(0);
|
||||
self.backupUploadData = undefined;
|
||||
self.backupUploadName = ko.observable();
|
||||
self.isAboveUploadSize = function (data) {
|
||||
return data.size > self.maxUploadSize();
|
||||
};
|
||||
|
||||
self.onStartupComplete = function () {
|
||||
$('#klipper_backups_dialog').css('display', 'none');
|
||||
if (self.loginState.loggedIn()) {
|
||||
self.listBakFiles();
|
||||
}
|
||||
};
|
||||
|
||||
// initialize list helper
|
||||
self.backups = new ItemListHelper(
|
||||
"klipperBakFiles",
|
||||
{
|
||||
name: function (a, b) {
|
||||
// sorts ascending
|
||||
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
|
||||
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
|
||||
return 0;
|
||||
},
|
||||
date: function (a, b) {
|
||||
// sorts descending
|
||||
if (a["date"] > b["date"]) return -1;
|
||||
if (a["date"] < b["date"]) return 1;
|
||||
return 0;
|
||||
},
|
||||
size: function (a, b) {
|
||||
// sorts descending
|
||||
if (a["bytes"] > b["bytes"]) return -1;
|
||||
if (a["bytes"] < b["bytes"]) return 1;
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
{},
|
||||
"name",
|
||||
[],
|
||||
[],
|
||||
5
|
||||
);
|
||||
|
||||
self.listBakFiles = function () {
|
||||
self.klipperViewModel.consoleMessage("debug", "listBakFiles");
|
||||
|
||||
OctoPrint.plugins.klipper.listCfgBak()
|
||||
.done(function (response) {
|
||||
self.backups.updateItems(response.files);
|
||||
self.backups.resetPage();
|
||||
});
|
||||
};
|
||||
|
||||
self.showCfg = function (backup) {
|
||||
if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return;
|
||||
|
||||
OctoPrint.plugins.klipper.getCfgBak(backup).done(function (response) {
|
||||
$('#klipper_backups_dialog textarea').attr('rows', response.response.config.split(/\r\n|\r|\n/).length);
|
||||
self.CfgContent(response.response.config);
|
||||
});
|
||||
};
|
||||
|
||||
self.removeCfg = function (backup) {
|
||||
if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return;
|
||||
|
||||
var perform = function () {
|
||||
OctoPrint.plugins.klipper
|
||||
.deleteBackup(backup)
|
||||
.done(function () {
|
||||
self.listBakFiles();
|
||||
})
|
||||
.fail(function (response) {
|
||||
var html = "<p>" + _.sprintf(gettext("Failed to remove config %(name)s.</p><p>Please consult octoprint.log for details.</p>"), { name: _.escape(backup) });
|
||||
html += pnotifyAdditionalInfo('<pre style="overflow: auto">' + _.escape(response.responseText) + "</pre>");
|
||||
new PNotify({
|
||||
title: gettext("Could not remove config"),
|
||||
text: html,
|
||||
type: "error",
|
||||
hide: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
showConfirmationDialog(
|
||||
_.sprintf(gettext('You are about to delete backed config file "%(name)s".'), {
|
||||
name: _.escape(backup),
|
||||
}),
|
||||
perform
|
||||
);
|
||||
};
|
||||
|
||||
self.restoreBak = function (backup) {
|
||||
if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return;
|
||||
|
||||
var restore = function () {
|
||||
OctoPrint.plugins.klipper.restoreBackup(backup).done(function (response) {
|
||||
self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + backup + " / " + response.restored);
|
||||
});
|
||||
};
|
||||
|
||||
var html = "<p>" + gettext("This will overwrite any file with the same name on the configpath.") + "</p>" + "<p>" + backup + "</p>";
|
||||
|
||||
showConfirmationDialog({
|
||||
title: gettext("Are you sure you want to restore now?"),
|
||||
html: html,
|
||||
proceed: gettext("Proceed"),
|
||||
onproceed: restore,
|
||||
});
|
||||
};
|
||||
|
||||
self.markFilesOnPage = function () {
|
||||
self.markedForFileRestore(_.uniq(self.markedForFileRestore().concat(_.map(self.backups.paginatedItems(), "file"))));
|
||||
};
|
||||
|
||||
self.markAllFiles = function () {
|
||||
self.markedForFileRestore(_.map(self.backups.allItems, "file"));
|
||||
};
|
||||
|
||||
self.clearMarkedFiles = function () {
|
||||
self.markedForFileRestore.removeAll();
|
||||
};
|
||||
|
||||
self.restoreMarkedFiles = function () {
|
||||
var perform = function () {
|
||||
self._bulkRestore(self.markedForFileRestore()).done(function () {
|
||||
self.markedForFileRestore.removeAll();
|
||||
});
|
||||
};
|
||||
|
||||
showConfirmationDialog(
|
||||
_.sprintf(gettext("You are about to restore %(count)d backed config files."), {
|
||||
count: self.markedForFileRestore().length,
|
||||
}),
|
||||
perform
|
||||
);
|
||||
};
|
||||
|
||||
self.removeMarkedFiles = function () {
|
||||
var perform = function () {
|
||||
self._bulkRemove(self.markedForFileRestore()).done(function () {
|
||||
self.markedForFileRestore.removeAll();
|
||||
});
|
||||
};
|
||||
|
||||
showConfirmationDialog(
|
||||
_.sprintf(gettext("You are about to delete %(count)d backed config files."), {
|
||||
count: self.markedForFileRestore().length,
|
||||
}),
|
||||
perform
|
||||
);
|
||||
};
|
||||
|
||||
self._bulkRestore = function (files) {
|
||||
var title, message, handler;
|
||||
|
||||
title = gettext("Restoring klipper config files");
|
||||
self.klipperViewModel.consoleMessage("debug", title);
|
||||
message = _.sprintf(gettext("Restoring %(count)d backed config files..."), {
|
||||
count: files.length,
|
||||
});
|
||||
|
||||
handler = function (filename) {
|
||||
return OctoPrint.plugins.klipper
|
||||
.restoreBackup(filename)
|
||||
.done(function (response) {
|
||||
deferred.notify(
|
||||
_.sprintf(gettext("Restored %(filename)s..."), {
|
||||
filename: _.escape(filename),
|
||||
}),
|
||||
true
|
||||
);
|
||||
self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + filename + " / " + response);
|
||||
self.markedForFileRestore.remove(function (item) {
|
||||
return item.name == filename;
|
||||
});
|
||||
})
|
||||
.fail(function () {
|
||||
deferred.notify(_.sprintf(gettext("Restoring of %(filename)s failed, continuing..."), { filename: _.escape(filename) }), false);
|
||||
});
|
||||
};
|
||||
|
||||
var deferred = $.Deferred();
|
||||
|
||||
var promise = deferred.promise();
|
||||
|
||||
var options = {
|
||||
title: title,
|
||||
message: message,
|
||||
max: files.length,
|
||||
output: true,
|
||||
};
|
||||
showProgressModal(options, promise);
|
||||
|
||||
var requests = [];
|
||||
|
||||
_.each(files, function (filename) {
|
||||
var request = handler(filename);
|
||||
requests.push(request);
|
||||
});
|
||||
|
||||
$.when.apply($, _.map(requests, wrapPromiseWithAlways)).done(function () {
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
self._bulkRemove = function (files) {
|
||||
var title, message, handler;
|
||||
|
||||
title = gettext("Deleting backup files");
|
||||
message = _.sprintf(gettext("Deleting %(count)d backed files..."), {
|
||||
count: files.length,
|
||||
});
|
||||
|
||||
handler = function (filename) {
|
||||
return OctoPrint.plugins.klipper
|
||||
.deleteBackup(filename)
|
||||
.done(function () {
|
||||
deferred.notify(_.sprintf(gettext("Deleted %(filename)s..."), { filename: _.escape(filename) }), true);
|
||||
self.markedForFileRestore.remove(function (item) {
|
||||
return item.name == filename;
|
||||
});
|
||||
})
|
||||
.fail(function () {
|
||||
deferred.notify(_.sprintf(gettext("Deleting of %(filename)s failed, continuing..."), { filename: _.escape(filename) }), false);
|
||||
});
|
||||
};
|
||||
|
||||
var deferred = $.Deferred();
|
||||
var promise = deferred.promise();
|
||||
var options = {
|
||||
title: title,
|
||||
message: message,
|
||||
max: files.length,
|
||||
output: true,
|
||||
};
|
||||
showProgressModal(options, promise);
|
||||
|
||||
var requests = [];
|
||||
_.each(files, function (filename) {
|
||||
var request = handler(filename);
|
||||
requests.push(request);
|
||||
});
|
||||
|
||||
$.when.apply($, _.map(requests, wrapPromiseWithAlways)).done(function () {
|
||||
deferred.resolve();
|
||||
self.listBakFiles();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperBackupViewModel,
|
||||
dependencies: ["loginStateViewModel", "klipperViewModel", "accessViewModel"],
|
||||
elements: ["#klipper_backups_dialog"],
|
||||
});
|
||||
});
|
|
@ -0,0 +1,398 @@
|
|||
// <Octoprint Klipper Plugin>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
$(function () {
|
||||
function KlipperEditorViewModel(parameters) {
|
||||
var self = this;
|
||||
var editor = null;
|
||||
var editordialog = $("#klipper_editor");
|
||||
|
||||
self.settings = parameters[0];
|
||||
self.klipperViewModel = parameters[1];
|
||||
|
||||
self.CfgFilename = ko.observable("");
|
||||
self.CfgContent = ko.observable("");
|
||||
self.loadedConfig = "";
|
||||
self.CfgChangedExtern = false;
|
||||
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache",
|
||||
});
|
||||
|
||||
$(window).on('resize', function() {
|
||||
self.klipperViewModel.sleep(200).then(
|
||||
function () {
|
||||
self.setEditorDivSize();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
self.onShown = function () {
|
||||
self.checkExternChange();
|
||||
editor.focus();
|
||||
self.setEditorDivSize();
|
||||
};
|
||||
|
||||
self.close_selection = function (index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
editordialog.modal('hide');
|
||||
break;
|
||||
case 1:
|
||||
self.editorFocusDelay(1000);
|
||||
break;
|
||||
case 2:
|
||||
self.saveCfg({closing: true});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
self.closeEditor = function () {
|
||||
self.CfgContent(editor.getValue());
|
||||
if (self.loadedConfig != self.CfgContent()) {
|
||||
|
||||
var opts = {
|
||||
title: gettext("Closing without saving"),
|
||||
message: gettext("Your file seems to have changed.")
|
||||
+ "<br />"
|
||||
+ gettext("Do you really want to close it?"),
|
||||
selections: [gettext("Close"), gettext("Do not close"), gettext("Save & Close")],
|
||||
maycancel: false,
|
||||
onselect: function (index) {
|
||||
if (index > -1) {
|
||||
self.close_selection(index);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
showSelectionDialog(opts);
|
||||
} else {
|
||||
editordialog.modal('hide');
|
||||
}
|
||||
};
|
||||
|
||||
self.addStyleAttribute = function ($element, styleAttribute) {
|
||||
$element.attr('style', styleAttribute);
|
||||
};
|
||||
|
||||
self.setEditorDivSize = function () {
|
||||
var klipper_modal_body= $('#klipper_editor .modal-body');
|
||||
var klipper_config= $('#plugin-klipper-config');
|
||||
|
||||
var height = $(window).height() - $('#klipper_editor .modal-header').outerHeight() - $('#klipper_editor .modal-footer').outerHeight() - 118;
|
||||
self.addStyleAttribute(klipper_modal_body, 'height: ' + height + 'px !important;');
|
||||
klipper_config.css('height', height);
|
||||
if (editor) {
|
||||
editor.resize();
|
||||
}
|
||||
};
|
||||
|
||||
//initialize the modal window and return done when finished
|
||||
self.process = function (config) {
|
||||
return new Promise(function (resolve) {
|
||||
self.loadedConfig = config.content;
|
||||
self.CfgFilename(config.file);
|
||||
self.CfgContent(config.content);
|
||||
|
||||
if (editor) {
|
||||
editor.session.setValue(self.CfgContent());
|
||||
self.CfgChangedExtern = false;
|
||||
editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize());
|
||||
editor.clearSelection();
|
||||
self.klipperViewModel.sleep(500).then(
|
||||
function() {
|
||||
self.setEditorDivSize();
|
||||
resolve("done");
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
self.onDataUpdaterPluginMessage = function (plugin, data) {
|
||||
//receive from backend after a SAVE_CONFIG
|
||||
if (plugin == "klipper" && data.type == "reload" && data.subtype == "config") {
|
||||
self.klipperViewModel.consoleMessage("debug", "onDataUpdaterPluginMessage klipper reload baseconfig");
|
||||
self.ConfigChangedAfterSave_Config();
|
||||
}
|
||||
};
|
||||
|
||||
//set externally changed config flag if the current file is the base config
|
||||
self.ConfigChangedAfterSave_Config = function () {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
|
||||
if (self.CfgFilename() == self.settings.settings.plugins.klipper.configuration.baseconfig()) {
|
||||
self.CfgChangedExtern = true;
|
||||
self.checkExternChange();
|
||||
}
|
||||
};
|
||||
|
||||
//check if the config was externally changed and ask for a reload
|
||||
self.checkExternChange = function() {
|
||||
var baseconfig = self.settings.settings.plugins.klipper.configuration.baseconfig();
|
||||
if (self.CfgChangedExtern && self.CfgFilename() == baseconfig) {
|
||||
if (editordialog.is(":visible")) {
|
||||
|
||||
var perform = function () {
|
||||
self.reloadFromFile();
|
||||
}
|
||||
|
||||
var html = "<p>" + gettext("Reload Configfile after SAVE_CONFIG?") + "</p>";
|
||||
|
||||
showConfirmationDialog({
|
||||
title: gettext("Externally changed config") + " " + baseconfig,
|
||||
html: html,
|
||||
proceed: gettext("Proceed"),
|
||||
onproceed: perform,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.askSaveFaulty = function () {
|
||||
return new Promise(function (resolve) {
|
||||
var html = "<h5>" +
|
||||
gettext("Your configuration seems to be faulty.") +
|
||||
"</h5>";
|
||||
|
||||
showConfirmationDialog({
|
||||
title: gettext("Save faulty Configuration?"),
|
||||
html: html,
|
||||
cancel: gettext("Do not save!"),
|
||||
proceed: [gettext("Save anyway!"), gettext("Save anyway and don't ask this again.")],
|
||||
onproceed: function (idx) {
|
||||
if (idx == 0) {
|
||||
resolve(true);
|
||||
} else {
|
||||
self.klipperViewModel.saveOption("configuration", "parse_check", false);
|
||||
resolve(true);
|
||||
}
|
||||
},
|
||||
oncancel: function () {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
self.checkSyntax = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (editor.session) {
|
||||
self.klipperViewModel.consoleMessage("debug", "checkSyntax started");
|
||||
|
||||
OctoPrint.plugins.klipper.checkCfg(editor.session.getValue())
|
||||
.done(function (response) {
|
||||
if (response.is_syntax_ok == true) {
|
||||
self.klipperViewModel.showPopUp("success", gettext("SyntaxCheck"), gettext("SyntaxCheck OK"));
|
||||
self.editorFocusDelay(1000);
|
||||
resolve(true);
|
||||
} else {
|
||||
self.editorFocusDelay(1000);
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
reject(false);
|
||||
});
|
||||
} else { reject(false); }
|
||||
});
|
||||
};
|
||||
|
||||
self.saveCfg = function (options) {
|
||||
var options = options || {};
|
||||
var closing = options.closing || false;
|
||||
|
||||
if (self.CfgFilename() != "") {
|
||||
if (editor.session) {
|
||||
if (self.settings.settings.plugins.klipper.configuration.parse_check() == true) {
|
||||
|
||||
// check Syntax and wait for response
|
||||
self.checkSyntax().then((syntaxOK) => {
|
||||
if (syntaxOK === false) {
|
||||
|
||||
// Ask if we should save a faulty config anyway
|
||||
self.askSaveFaulty().then((areWeSaving) => {
|
||||
if (areWeSaving === false) {
|
||||
// Not saving
|
||||
showMessageDialog(
|
||||
gettext('Faulty config not saved!'),
|
||||
{
|
||||
title: gettext("Save Config"),
|
||||
onclose: function () { self.editorFocusDelay(1000); }
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Save anyway
|
||||
self.saveRequest(closing);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Syntax is ok
|
||||
self.saveRequest(closing);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self.saveRequest(closing);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showMessageDialog(
|
||||
gettext("No filename set"),
|
||||
{
|
||||
title: gettext("Save Config")
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
self.minusFontsize = function () {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize() - 1
|
||||
);
|
||||
|
||||
if (self.settings.settings.plugins.klipper.configuration.fontsize() < 9) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(9);
|
||||
}
|
||||
|
||||
var fontsize = self.settings.settings.plugins.klipper.configuration.fontsize();
|
||||
if (editor) {
|
||||
editor.setFontSize(fontsize);
|
||||
editor.resize();
|
||||
}
|
||||
|
||||
self.klipperViewModel.saveOption("configuration", "fontsize", fontsize);
|
||||
};
|
||||
|
||||
self.plusFontsize = function () {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize() + 1
|
||||
);
|
||||
|
||||
if (self.settings.settings.plugins.klipper.configuration.fontsize() > 20) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(20);
|
||||
}
|
||||
|
||||
var fontsize = self.settings.settings.plugins.klipper.configuration.fontsize();
|
||||
if (editor) {
|
||||
editor.setFontSize(fontsize);
|
||||
editor.resize();
|
||||
}
|
||||
self.klipperViewModel.saveOption("configuration", "fontsize", fontsize);
|
||||
};
|
||||
|
||||
self.reloadFromFile = function () {
|
||||
if (self.CfgFilename() != "") {
|
||||
OctoPrint.plugins.klipper.getCfg(self.CfgFilename())
|
||||
.done(function (response) {
|
||||
self.klipperViewModel.consoleMessage("debug", "reloadFromFile done");
|
||||
if (response.response.text != "") {
|
||||
showMessageDialog(
|
||||
response.response.text,
|
||||
{
|
||||
title: gettext("Reload File")
|
||||
}
|
||||
);
|
||||
} else {
|
||||
self.klipperViewModel.showPopUp("success", gettext("Reload Config"), gettext("File reloaded."));
|
||||
self.CfgChangedExtern = false;
|
||||
if (editor) {
|
||||
editor.session.setValue(response.response.config);
|
||||
self.loadedConfig = response.response.config;
|
||||
editor.clearSelection();
|
||||
editor.focus();
|
||||
}
|
||||
}
|
||||
})
|
||||
.fail(function (response) {
|
||||
showMessageDialog(
|
||||
response,
|
||||
{
|
||||
title: gettext("Reload File")
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
showMessageDialog(
|
||||
gettext("No filename set"),
|
||||
{
|
||||
title: gettext("Reload File")
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
self.onStartup = function () {
|
||||
ace.config.set("basePath", "plugin/klipper/static/js/lib/ace/");
|
||||
editor = ace.edit("plugin-klipper-config");
|
||||
editor.setTheme("ace/theme/monokai");
|
||||
editor.session.setMode("ace/mode/klipper_config");
|
||||
editor.clearSelection();
|
||||
|
||||
editor.setOptions({
|
||||
hScrollBarAlwaysVisible: false,
|
||||
vScrollBarAlwaysVisible: false,
|
||||
autoScrollEditorIntoView: true,
|
||||
showPrintMargin: false,
|
||||
//maxLines: "Infinity"
|
||||
});
|
||||
|
||||
editor.session.on('change', function (delta) {
|
||||
self.CfgContent(editor.getValue());
|
||||
editor.resize();
|
||||
});
|
||||
};
|
||||
|
||||
self.editorFocusDelay = function (delay) {
|
||||
self.klipperViewModel.sleep(delay).then(
|
||||
function () {
|
||||
editor.focus();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
self.saveRequest = function (closing) {
|
||||
self.klipperViewModel.consoleMessage("debug", "SaveCfg start");
|
||||
|
||||
OctoPrint.plugins.klipper.saveCfg(editor.session.getValue(), self.CfgFilename())
|
||||
.done(function (response) {
|
||||
if (response.saved === true) {
|
||||
self.klipperViewModel.showPopUp("success", gettext("Save Config"), gettext("File saved."));
|
||||
self.loadedConfig = editor.session.getValue(); //set loaded config to current for resetting dirtyEditor
|
||||
if (closing) {
|
||||
editordialog.modal('hide');
|
||||
}
|
||||
if (self.settings.settings.plugins.klipper.configuration.restart_onsave() == true) {
|
||||
self.klipperViewModel.requestRestart();
|
||||
}
|
||||
} else {
|
||||
showMessageDialog(
|
||||
gettext('File not saved!'),
|
||||
{
|
||||
title: gettext("Save Config"),
|
||||
onclose: function () { self.editorFocusDelay(1000); }
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperEditorViewModel,
|
||||
dependencies: ["settingsViewModel", "klipperViewModel"],
|
||||
elements: ["#klipper_editor"],
|
||||
});
|
||||
});
|
|
@ -13,220 +13,320 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
$(function() {
|
||||
$('#klipper-settings a:first').tab('show');
|
||||
function KlipperSettingsViewModel(parameters) {
|
||||
var self = this;
|
||||
var obKlipperConfig = null;
|
||||
var editor = null;
|
||||
$(function () {
|
||||
$("#klipper-settings a:first").tab("show");
|
||||
function KlipperSettingsViewModel(parameters) {
|
||||
var self = this;
|
||||
|
||||
self.settings = parameters[0];
|
||||
self.klipperViewModel = parameters[1];
|
||||
self.settings = parameters[0];
|
||||
self.klipperViewModel = parameters[1];
|
||||
self.klipperEditorViewModel = parameters[2];
|
||||
self.klipperBackupViewModel = parameters[3];
|
||||
self.access = parameters[4];
|
||||
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache"
|
||||
});
|
||||
self.header = OctoPrint.getRequestHeaders({
|
||||
"content-type": "application/json",
|
||||
"cache-control": "no-cache",
|
||||
});
|
||||
|
||||
self.apiUrl = OctoPrint.getSimpleApiUrl("klipper");
|
||||
self.markedForFileRemove = ko.observableArray([]);
|
||||
self.PathToConfigs = ko.observable("");
|
||||
|
||||
self.onSettingsBeforeSave = function () {
|
||||
if (editor.session && self.settings.settings.plugins.klipper.configuration.parse_check() === true) {
|
||||
self.klipperViewModel.consoleMessage("debug", "onSettingsBeforeSave:")
|
||||
var settings = {
|
||||
"crossDomain": true,
|
||||
"url": self.apiUrl,
|
||||
"method": "POST",
|
||||
"headers": self.header,
|
||||
"processData": false,
|
||||
"dataType": "json",
|
||||
"data": JSON.stringify({command: "checkConfig",
|
||||
config: editor.session.getValue()})
|
||||
}
|
||||
$(document).on('shown.bs.modal','#klipper_editor', function () {
|
||||
self.klipperEditorViewModel.onShown();
|
||||
});
|
||||
|
||||
$.ajax(settings).done(function (response) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.addMacro = function() {
|
||||
self.settings.settings.plugins.klipper.macros.push({
|
||||
name: 'Macro',
|
||||
macro: '',
|
||||
sidebar: true,
|
||||
tab: true
|
||||
});
|
||||
}
|
||||
|
||||
self.removeMacro = function(macro) {
|
||||
self.settings.settings.plugins.klipper.macros.remove(macro);
|
||||
}
|
||||
|
||||
self.moveMacroUp = function(macro) {
|
||||
self.moveItemUp(self.settings.settings.plugins.klipper.macros, macro)
|
||||
}
|
||||
|
||||
self.moveMacroDown = function(macro) {
|
||||
self.moveItemDown(self.settings.settings.plugins.klipper.macros, macro)
|
||||
}
|
||||
|
||||
self.addProbePoint = function() {
|
||||
self.settings.settings.plugins.klipper.probe.points.push(
|
||||
{
|
||||
name: 'point-#',
|
||||
x:0, y:0, z:0
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
self.removeProbePoint = function(point) {
|
||||
self.settings.settings.plugins.klipper.probe.points.remove(point);
|
||||
}
|
||||
|
||||
self.moveProbePointUp = function(macro) {
|
||||
self.moveItemUp(self.settings.settings.plugins.klipper.probe.points, macro)
|
||||
}
|
||||
|
||||
self.moveProbePointDown = function(macro) {
|
||||
self.moveItemDown(self.settings.settings.plugins.klipper.probe.points, macro)
|
||||
}
|
||||
|
||||
self.moveItemDown = function(list, item) {
|
||||
var i = list().indexOf(item);
|
||||
if (i < list().length - 1) {
|
||||
var rawList = list();
|
||||
list.splice(i, 2, rawList[i + 1], rawList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
self.moveItemUp = function(list, item) {
|
||||
var i = list().indexOf(item);
|
||||
if (i > 0) {
|
||||
var rawList = list();
|
||||
list.splice(i-1, 2, rawList[i], rawList[i-1]);
|
||||
}
|
||||
}
|
||||
|
||||
self.minusFontsize = function () {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(self.settings.settings.plugins.klipper.configuration.fontsize() - 1);
|
||||
if (self.settings.settings.plugins.klipper.configuration.fontsize() < 9) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(9);
|
||||
}
|
||||
if (editor) {
|
||||
editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize());
|
||||
editor.resize();
|
||||
}
|
||||
}
|
||||
|
||||
self.plusFontsize = function () {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(self.settings.settings.plugins.klipper.configuration.fontsize() + 1);
|
||||
if (self.settings.settings.plugins.klipper.configuration.fontsize() > 20) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(20);
|
||||
}
|
||||
if (editor) {
|
||||
editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize());
|
||||
editor.resize();
|
||||
}
|
||||
}
|
||||
|
||||
self.loadLastSession = function () {
|
||||
if (self.settings.settings.plugins.klipper.configuration.old_config() != "") {
|
||||
self.klipperViewModel.consoleMessage("info","lastSession:" + self.settings.settings.plugins.klipper.configuration.old_config())
|
||||
if (editor.session) {
|
||||
editor.session.setValue(self.settings.settings.plugins.klipper.configuration.old_config());
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.reloadFromFile = function () {
|
||||
if (editor.session) {
|
||||
var settings = {
|
||||
"crossDomain": true,
|
||||
"url": self.apiUrl,
|
||||
"method": "POST",
|
||||
"headers": self.header,
|
||||
"processData": false,
|
||||
"dataType": "json",
|
||||
"data": JSON.stringify({command: "reloadConfig"})
|
||||
}
|
||||
|
||||
$.ajax(settings).done(function (response) {
|
||||
editor.session.setValue(response["data"]);
|
||||
editor.clearSelection();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.configBound = function (config) {
|
||||
config.withSilence = function() {
|
||||
this.notifySubscribers = function() {
|
||||
if (!this.isSilent) {
|
||||
ko.subscribable.fn.notifySubscribers.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
this.silentUpdate = function(newValue) {
|
||||
this.isSilent = true;
|
||||
this(newValue);
|
||||
this.isSilent = false;
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
obKlipperConfig = config.withSilence();
|
||||
if (editor) {
|
||||
editor.setValue(obKlipperConfig());
|
||||
editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize());
|
||||
editor.resize();
|
||||
editor.clearSelection();
|
||||
}
|
||||
return obKlipperConfig;
|
||||
}
|
||||
|
||||
ace.config.set("basePath", "plugin/klipper/static/js/lib/ace/");
|
||||
editor = ace.edit("plugin-klipper-config");
|
||||
editor.setTheme("ace/theme/monokai");
|
||||
editor.session.setMode("ace/mode/klipper_config");
|
||||
editor.setOptions({
|
||||
hScrollBarAlwaysVisible: false,
|
||||
vScrollBarAlwaysVisible: false,
|
||||
autoScrollEditorIntoView: true,
|
||||
showPrintMargin: false,
|
||||
maxLines: "Infinity"
|
||||
})
|
||||
|
||||
editor.session.on('change', function(delta) {
|
||||
if (obKlipperConfig) {
|
||||
obKlipperConfig.silentUpdate(editor.getValue());
|
||||
editor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
// Uncomment this if not using maxLines: "Infinity"...
|
||||
// setInterval(function(){ editor.resize(); }, 500);
|
||||
self.onDataUpdaterPluginMessage = function(plugin, data) {
|
||||
if(plugin == "klipper") {
|
||||
if ("reload" == data.type){
|
||||
if ("config" == data.subtype){
|
||||
if (editor.session) {
|
||||
editor.session.setValue(data.payload);
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
self.checkFontsize = function () {
|
||||
if (self.settings.settings.plugins.klipper.configuration.fontsize() > 20) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(20)
|
||||
} else if (self.settings.settings.plugins.klipper.configuration.fontsize()< 9) {
|
||||
self.settings.settings.plugins.klipper.configuration.fontsize(9)
|
||||
}
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperSettingsViewModel,
|
||||
dependencies: [
|
||||
"settingsViewModel",
|
||||
"klipperViewModel"
|
||||
],
|
||||
elements: ["#settings_plugin_klipper"]
|
||||
});
|
||||
// initialize list helper
|
||||
self.configs = new ItemListHelper(
|
||||
"klipperCfgFiles",
|
||||
{
|
||||
name: function (a, b) {
|
||||
// sorts ascending
|
||||
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
|
||||
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
|
||||
return 0;
|
||||
},
|
||||
date: function (a, b) {
|
||||
// sorts descending
|
||||
if (a["date"] > b["date"]) return -1;
|
||||
if (a["date"] < b["date"]) return 1;
|
||||
return 0;
|
||||
},
|
||||
size: function (a, b) {
|
||||
// sorts descending
|
||||
if (a["bytes"] > b["bytes"]) return -1;
|
||||
if (a["bytes"] < b["bytes"]) return 1;
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
{},
|
||||
"name",
|
||||
[],
|
||||
[],
|
||||
15
|
||||
);
|
||||
|
||||
self.onStartupComplete = function () {
|
||||
self.listCfgFiles();
|
||||
self.loadBaseConfig();
|
||||
};
|
||||
|
||||
self.listCfgFiles = function () {
|
||||
self.klipperViewModel.consoleMessage("debug", "listCfgFiles started");
|
||||
|
||||
OctoPrint.plugins.klipper.listCfg().done(function (response) {
|
||||
self.klipperViewModel.consoleMessage("debug", "listCfgFiles done");
|
||||
self.configs.updateItems(response.files);
|
||||
self.PathToConfigs(gettext("Path: ") + response.path);
|
||||
self.configs.resetPage();
|
||||
});
|
||||
};
|
||||
|
||||
self.loadBaseConfig = function () {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
|
||||
var baseconfig = self.settings.settings.plugins.klipper.configuration.baseconfig();
|
||||
if (baseconfig != "") {
|
||||
self.klipperViewModel.consoleMessage("debug", "loadBaseConfig:" + baseconfig);
|
||||
OctoPrint.plugins.klipper.getCfg(baseconfig).done(function (response) {
|
||||
var config = {
|
||||
content: response.response.config,
|
||||
file: baseconfig,
|
||||
};
|
||||
self.klipperEditorViewModel.process(config).then();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.removeCfg = function (config) {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
|
||||
var perform = function () {
|
||||
OctoPrint.plugins.klipper
|
||||
.deleteCfg(config)
|
||||
.done(function () {
|
||||
self.listCfgFiles();
|
||||
})
|
||||
.fail(function (response) {
|
||||
var html = "<p>" + _.sprintf(gettext("Failed to remove config %(name)s.</p><p>Please consult octoprint.log for details.</p>"), { name: _.escape(config) });
|
||||
html += pnotifyAdditionalInfo('<pre style="overflow: auto">' + _.escape(response.responseText) + "</pre>");
|
||||
new PNotify({
|
||||
title: gettext("Could not remove config"),
|
||||
text: html,
|
||||
type: "error",
|
||||
hide: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
showConfirmationDialog(
|
||||
_.sprintf(gettext('You are about to delete config file "%(name)s".'), {
|
||||
name: _.escape(config),
|
||||
}),
|
||||
perform
|
||||
);
|
||||
};
|
||||
|
||||
self.markFilesOnPage = function () {
|
||||
self.markedForFileRemove(_.uniq(self.markedForFileRemove().concat(_.map(self.configs.paginatedItems(), "file"))));
|
||||
};
|
||||
|
||||
self.markAllFiles = function () {
|
||||
self.markedForFileRemove(_.map(self.configs.allItems, "file"));
|
||||
};
|
||||
|
||||
self.clearMarkedFiles = function () {
|
||||
self.markedForFileRemove.removeAll();
|
||||
};
|
||||
|
||||
self.removeMarkedFiles = function () {
|
||||
var perform = function () {
|
||||
self._bulkRemove(self.markedForFileRemove()).done(function () {
|
||||
self.markedForFileRemove.removeAll();
|
||||
});
|
||||
};
|
||||
|
||||
showConfirmationDialog(
|
||||
_.sprintf(gettext("You are about to delete %(count)d config files."), {
|
||||
count: self.markedForFileRemove().length,
|
||||
}),
|
||||
perform
|
||||
);
|
||||
};
|
||||
|
||||
self._bulkRemove = function (files) {
|
||||
var title, message, handler;
|
||||
|
||||
title = gettext("Deleting config files");
|
||||
message = _.sprintf(gettext("Deleting %(count)d config files..."), {
|
||||
count: files.length,
|
||||
});
|
||||
|
||||
handler = function (filename) {
|
||||
return OctoPrint.plugins.klipper
|
||||
.deleteCfg(filename)
|
||||
.done(function () {
|
||||
deferred.notify(
|
||||
_.sprintf(gettext("Deleted %(filename)s..."), {
|
||||
filename: _.escape(filename),
|
||||
}),
|
||||
true
|
||||
);
|
||||
self.markedForFileRemove.remove(function (item) {
|
||||
return item.name == filename;
|
||||
});
|
||||
})
|
||||
.fail(function () {
|
||||
deferred.notify(_.sprintf(gettext("Deleting of %(filename)s failed, continuing..."), { filename: _.escape(filename) }), false);
|
||||
});
|
||||
};
|
||||
|
||||
var deferred = $.Deferred();
|
||||
var promise = deferred.promise();
|
||||
var options = {
|
||||
title: title,
|
||||
message: message,
|
||||
max: files.length,
|
||||
output: true,
|
||||
};
|
||||
showProgressModal(options, promise);
|
||||
|
||||
var requests = [];
|
||||
_.each(files, function (filename) {
|
||||
var request = handler(filename);
|
||||
requests.push(request);
|
||||
});
|
||||
|
||||
$.when.apply($, _.map(requests, wrapPromiseWithAlways)).done(function () {
|
||||
deferred.resolve();
|
||||
self.listCfgFiles();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
self.showBackupsDialog = function () {
|
||||
self.klipperViewModel.consoleMessage("debug", "showBackupsDialog");
|
||||
self.klipperBackupViewModel.listBakFiles();
|
||||
var dialog = $("#klipper_backups_dialog");
|
||||
dialog.modal({
|
||||
show: "true",
|
||||
});
|
||||
};
|
||||
|
||||
self.showEditor = function () {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
|
||||
var editorDialog = $("#klipper_editor");
|
||||
editorDialog.modal({
|
||||
show: "true",
|
||||
width: "90%",
|
||||
backdrop: "static",
|
||||
});
|
||||
}
|
||||
|
||||
self.newFile = function () {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
var config = {
|
||||
content: "",
|
||||
file: "Change Filename",
|
||||
};
|
||||
self.klipperEditorViewModel.process(config).then(
|
||||
function() { self.showEditor(); }
|
||||
);
|
||||
};
|
||||
|
||||
self.openConfig = function (file) {
|
||||
if (!self.klipperViewModel.hasRight("CONFIG")) return;
|
||||
|
||||
OctoPrint.plugins.klipper.getCfg(file).done(function (response) {
|
||||
var config = {
|
||||
content: response.response.config,
|
||||
file: file,
|
||||
};
|
||||
self.klipperEditorViewModel.process(config).then(
|
||||
function() { self.showEditor(); }
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
self.addMacro = function () {
|
||||
self.settings.settings.plugins.klipper.macros.push({
|
||||
name: "Macro",
|
||||
macro: "",
|
||||
sidebar: true,
|
||||
tab: true,
|
||||
});
|
||||
};
|
||||
|
||||
self.removeMacro = function (macro) {
|
||||
self.settings.settings.plugins.klipper.macros.remove(macro);
|
||||
};
|
||||
|
||||
self.moveMacroUp = function (macro) {
|
||||
self.moveItemUp(self.settings.settings.plugins.klipper.macros, macro);
|
||||
};
|
||||
|
||||
self.moveMacroDown = function (macro) {
|
||||
self.moveItemDown(self.settings.settings.plugins.klipper.macros, macro);
|
||||
};
|
||||
|
||||
self.addProbePoint = function () {
|
||||
self.settings.settings.plugins.klipper.probe.points.push({
|
||||
name: "point-#",
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0,
|
||||
});
|
||||
};
|
||||
|
||||
self.removeProbePoint = function (point) {
|
||||
self.settings.settings.plugins.klipper.probe.points.remove(point);
|
||||
};
|
||||
|
||||
self.moveProbePointUp = function (macro) {
|
||||
self.moveItemUp(self.settings.settings.plugins.klipper.probe.points, macro);
|
||||
};
|
||||
|
||||
self.moveProbePointDown = function (macro) {
|
||||
self.moveItemDown(self.settings.settings.plugins.klipper.probe.points, macro);
|
||||
};
|
||||
|
||||
self.moveItemDown = function (list, item) {
|
||||
var i = list().indexOf(item);
|
||||
if (i < list().length - 1) {
|
||||
var rawList = list();
|
||||
list.splice(i, 2, rawList[i + 1], rawList[i]);
|
||||
}
|
||||
};
|
||||
|
||||
self.moveItemUp = function (list, item) {
|
||||
var i = list().indexOf(item);
|
||||
if (i > 0) {
|
||||
var rawList = list();
|
||||
list.splice(i - 1, 2, rawList[i], rawList[i - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
self.onDataUpdaterPluginMessage = function (plugin, data) {
|
||||
if (plugin == "klipper" && data.type == "reload" && data.subtype == "configlist") {
|
||||
self.klipperViewModel.consoleMessage("debug", "onDataUpdaterPluginMessage klipper reload configlist");
|
||||
self.listCfgFiles();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperSettingsViewModel,
|
||||
dependencies: ["settingsViewModel", "klipperViewModel", "klipperEditorViewModel", "klipperBackupViewModel", "accessViewModel"],
|
||||
elements: ["#settings_plugin_klipper"],
|
||||
});
|
||||
});
|
||||
|
|
|
@ -160,7 +160,7 @@ ace.define("ace/mode/klipper_config_highlight_rules",[], function(require, expor
|
|||
caseInsensitive: true
|
||||
}, {
|
||||
token: "support.type",
|
||||
regex: /[\^~!]*(?:z:)?[a-zA-Z]{1,2}\d{1,2}(?:\.\d{1,2})?/,
|
||||
regex: /[\^~!]*(?:z:)?[a-zA-Z]{1,4}(?:gpio)?\d{1,2}(?:\.\d{1,2})?/,
|
||||
caseInsensitive: true
|
||||
}],
|
||||
"#config_line_start_gcode": [{
|
||||
|
@ -192,8 +192,8 @@ ace.define("ace/mode/klipper_config_highlight_rules",[], function(require, expor
|
|||
}]
|
||||
}],
|
||||
"#config_line": [{
|
||||
token: ["variable.name", "variable.name"],
|
||||
regex: /(?!gcode|sensor_type|rpi:)(\w+)(\s*[:]\s*)/,
|
||||
token: ["variable.name", "variable.name", "variable.name", "variable.name"],
|
||||
regex: /(?!gcode|sensor_type|rpi:)(\w+)(\s*[:]\s*\w+[:])|(?!gcode|sensor_type|rpi:)(\w+)(\s*[:]\s*)/,
|
||||
push: [{
|
||||
token: "text",
|
||||
regex: /$/,
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<div id="klipper_backups_dialog" class="modal hide fade large" tabindex="-1" role="dialog" aria-labelledby="klipper_backups_dialog_label"
|
||||
aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_dialog_label">{{ _('Backups') }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="editor-controls">
|
||||
<div class="klipper-btn-group klipper-fluid-item-1" data-bind="visible: $root.klipperViewModel.hasRightKo('CONFIG')">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="far fa-square"></i>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="javascript:void(0)" data-bind="click: markFilesOnPage">{{ _('Select all on this page') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript:void(0)" data-bind="click: markAllFiles">{{ _('Select all') }}</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript:void(0)" data-bind="click: clearMarkedFiles">{{ _('Clear selection') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button class="btn btn-small" data-bind="click: listBakFiles" title="{{ _('Refresh file list') }}">
|
||||
<i class="icon-refresh"></i> {{ _('Refresh Files') }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-small"
|
||||
data-bind="click: restoreMarkedFiles, enable: markedForFileRestore().length > 0">{{ _('Restore selected') }}</button>
|
||||
<button class="btn btn-small"
|
||||
data-bind="click: removeMarkedFiles, enable: markedForFileRestore().length > 0">{{ _('Delete selected') }}</button>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fas fa-wrench"></i>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { backups.changeSorting('name'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: backups.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> {{ _('Sort by name') }}
|
||||
({{ _('ascending') }})</a>
|
||||
</li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { backups.changeSorting('date'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: backups.currentSorting() == 'date' ? 'visible' : 'hidden'}"></i> {{ _('Sort by date') }}
|
||||
({{ _('descending') }})</a>
|
||||
</li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { backups.changeSorting('size'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: backups.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> {{ _('Sort by file size') }}
|
||||
({{ _('descending') }})</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-condensed table-hover" id="klipper_bak_files">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="klipper_baks_checkbox"></th>
|
||||
<th class="klipper_baks_name">{{ _('Name') }}</th>
|
||||
<th class="klipper_baks_size">{{ _('Size') }}</th>
|
||||
<th class="klipper_baks_action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: backups.paginatedItems">
|
||||
<tr data-bind="attr: {title: name}">
|
||||
<td class="klipper_baks_checkbox"><input type="checkbox"
|
||||
data-bind="value: file, checked: $root.markedForFileRestore, invisible: !$root.klipperViewModel.hasRightKo('CONFIG')" />
|
||||
</td>
|
||||
<td class="klipper_baks_name" data-bind="text: name"></td>
|
||||
<td class="klipper_baks_size" data-bind="text: size"></td>
|
||||
<td class="klipper_baks_action">
|
||||
<a href="javascript:void(0)" class="far fa-trash-alt" title="{{ _('Delete') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, click: function() { $parent.removeCfg($data.name); }"></a>
|
||||
|
|
||||
<a href="javascript:void(0)" class="fas fa-undo" title="{{ _('Restore') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, click: function() { $parent.restoreBak($data.name); }"></a>
|
||||
|
|
||||
<a href="javascript:void(0)" class="fas fa-download" title="{{ _('Download') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, attr: { href: ($root.klipperViewModel.hasRightKo('CONFIG')()) ? $data.url : 'javascript:void(0)'}"></a>
|
||||
|
|
||||
<a href="javascript:void(0)" class="fas fa-eye" title="{{ _('Preview') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, click: function() { $parent.showCfg($data.name); }"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pagination pagination-mini pagination-centered">
|
||||
<ul>
|
||||
<li data-bind="css: {disabled: backups.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: backups.prevPage">«</a></li>
|
||||
</ul>
|
||||
<ul data-bind="foreach: backups.pages">
|
||||
<li data-bind="css: { active: $data.number === $root.backups.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)"
|
||||
data-bind="text: $data.text, click: function() { $root.backups.changePage($data.number); }"></a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li data-bind="css: {disabled: backups.currentPage() === backups.lastPage()}"><a href="javascript:void(0)"
|
||||
data-bind="click: backups.nextPage">»</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="textarea">
|
||||
<textarea rows="21" readonly data-bind="value: CfgContent" id="klipper_bak_text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,46 @@
|
|||
<div id="klipper_editor" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="klipper_editor_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="click: closeEditor">×</button>
|
||||
<h3 id="klipper_dialog_label">Editor
|
||||
<div class="pull-right">
|
||||
<button data-bind="click: minusFontsize" title="{{ _('Decrease Fontsize') }}" class="btn">
|
||||
<i class="fas fa-search-minus"></i>
|
||||
</button>
|
||||
<button data-bind="click: plusFontsize" title="{{ _('Increase Fontsize') }}" class="btn">
|
||||
<i class="fas fa-search-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<script src="plugin/klipper/static/js/lib/ace/ace.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="plugin/klipper/static/js/lib/ace/theme-monokai.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="plugin/klipper/static/js/lib/ace/mode-klipper_config.js" type="text/javascript"></script>
|
||||
<div class="full-sized-box">
|
||||
<div class="conf-editor" id="conf_editor">
|
||||
<input id="hdnLoadKlipperConfig" type="hidden" data-bind="value: CfgContent">
|
||||
<div id="plugin-klipper-config"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="editor-controls">
|
||||
<span class="control-label">{{ _('Filename') }}:</span>
|
||||
<input type="text" data-bind="value: CfgFilename">
|
||||
<div class="klipper-btn-group klipper-fluid-item-2">
|
||||
<button class="btn btn-small" data-bind="click: reloadFromFile" title="{{ _('Reload from file') }}">
|
||||
<i class="fas fa-upload"></i> {{ _('Reload from file') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind="click: checkSyntax" title="{{ _('Check Syntax') }}">
|
||||
<i class="fas fa-spell-check"></i> {{ _('Check Syntax') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind="click: function() { $root.saveCfg({closing: true}) }" title="{{ _('Save Config and Close') }}">
|
||||
<i class="fas fa-save"></i> {{ _('Save & Close') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind="click: saveCfg" title="{{ _('Save Config') }}">
|
||||
<i class="fas fa-save"></i> {{ _('Save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,12 +1,12 @@
|
|||
<div id="klipper_graph_dialog" class="modal hide fade large" tabindex="-1" role="dialog" aria-labelledby="klipper_graph_dialog_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_pid_tuning_dialog_label">{{ _('Performance Graph') }}</h3>
|
||||
<h3 id="klipper_dialog_label">{{ _('Performance Graph') }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="full-sized-box">
|
||||
<span class="help-inline" style="display:block; position: absolute">
|
||||
<em>Click labels to hide/show dataset</em>
|
||||
<em>{{ _('Click labels to hide/show dataset') }}</em>
|
||||
</span>
|
||||
<script src="plugin/klipper/static/js/lib/Chart.bundle.min.js" type="text/javascript" defer></script>
|
||||
<canvas id="klipper_graph_canvas"></canvas>
|
||||
|
@ -32,6 +32,6 @@
|
|||
<div id="klipper_graph_spinner" class="modal hide fade small" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<img src="plugin/klipper/static/img/spinner.gif" width="100" height="100">
|
||||
<span class="help-inline">
|
||||
Depending on the size of the log file this might take a while.
|
||||
{{ _('Depending on the size of the log file this might take a while.') }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<!-- ko if: settings.settings.plugins.klipper.configuration.shortStatus_navbar -->
|
||||
<a title="Go to OctoKlipper Tab" data-bind="text: shortStatus_navbar, click: navbarClicked"></a>
|
||||
<a data-bind="attr: { title: shortStatus_navbar_hover }, text: shortStatus_navbar, click: navbarClicked"></a>
|
||||
<!-- /ko -->
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="klipper_offset_dialog" class="modal hide fade small" tabindex="-1" role="dialog" aria-labelledby="klipper_offset_dialog_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_pid_tuning_dialog_label">{{ _('Coordinate Offset') }}</h3>
|
||||
<h3 id="klipper_dialog_label">{{ _('Coordinate Offset') }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row-fluid" style="margin-bottom: 15px">
|
||||
|
@ -10,15 +10,15 @@
|
|||
<div class="row-fluid" style="margin-bottom: 15px">
|
||||
<div class="input-append span3">
|
||||
<input type="text" class="input-block-level span6" data-bind="value: offsetX">
|
||||
<span class="add-on">{{ _('X') }}</span>
|
||||
<span class="add-on">X</span>
|
||||
</div>
|
||||
<div class="input-append span3">
|
||||
<input type="text" class="input-block-level span6" data-bind="value: offsetY">
|
||||
<span class="add-on">{{ _('Y') }}</span>
|
||||
<span class="add-on">Y</span>
|
||||
</div>
|
||||
<div class="input-append span3">
|
||||
<input type="text" class="input-block-level span6" data-bind="value: offsetZ">
|
||||
<span class="add-on">{{ _('Z') }}</span>
|
||||
<span class="add-on">Z</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid" style="margin-bottom: 15px">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="klipper_macro_dialog" class="modal hide fade small" tabindex="-1" role="dialog" aria-labelledby="klipper_macro_dialog_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_pid_tuning_dialog_label">{{ _('Run - ') }}<span data-bind="text: macroName"></span></h3>
|
||||
<h3 id="klipper_dialog_label">{{ _('Run - ') }}<span data-bind="text: macroName"></span></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="control-group" data-bind="foreach: parameters">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="klipper_pid_tuning_dialog" class="modal hide fade small" tabindex="-1" role="dialog" aria-labelledby="klipper_pid_tuning_dialog_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_pid_tuning_dialog_label">{{ _('PID Tuning') }}</h3>
|
||||
<h3 id="klipper_dialog_label">{{ _('PID Tuning') }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="control-group">
|
||||
|
|
|
@ -1,231 +1,347 @@
|
|||
<form class="form-horizontal">
|
||||
<ul class="nav nav-pills" id="klipper-settings">
|
||||
<li><a href="#basic" data-toggle="tab" data-profile-type="klipper-basic">Basic</a></li>
|
||||
<li><a href="#macros" data-toggle="tab" data-profile-type="klipper-macros">Macros</a></li>
|
||||
<li><a href="#level" data-toggle="tab" data-profile-type="klipper-bed">Bed Leveling</a></li>
|
||||
<li><a href="#conf" data-toggle="tab" data-profile-type="klipper-config">Klipper Configuration</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<!-- Basics -->
|
||||
<div class="tab-pane active" id="basic">
|
||||
<div class="control-group">
|
||||
<ul class="nav nav-pills" id="klipper-settings">
|
||||
<li><a href="#basic" data-toggle="tab" data-profile-type="klipper-basic">{{ _('Basic') }}</a></li>
|
||||
<li><a href="#macros" data-toggle="tab" data-profile-type="klipper-macros">{{ _('Macros') }}</a></li>
|
||||
<li><a href="#level" data-toggle="tab" data-profile-type="klipper-bed">{{ _('Bed Leveling') }}</a></li>
|
||||
<li><a href="#conf" data-toggle="tab" data-profile-type="klipper-config">{{ _('Klipper Configuration') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<!-- Basics -->
|
||||
<div class="tab-pane active" id="basic">
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Serial Port') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.connection.port">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.connection.port" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Replace Connection Panel') }}</label>
|
||||
<div class="controls">
|
||||
<input class="controls-checkbox" title="{{ _('Replace Connection Panel') }}" type="checkbox" data-bind="checked: settings.settings.plugins.klipper.connection.replace_connection_panel">
|
||||
<input class="controls-checkbox" title="{{ _('Replace Connection Panel') }}" type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.connection.replace_connection_panel">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
</div>
|
||||
<div class="control-group border">
|
||||
<label class="control-label">{{ _('Show Short Messages') }}</label>
|
||||
<div class="controls">
|
||||
<label class="checkbox" title="{{ _('on NavBar') }}"><input type="checkbox" data-bind="checked: settings.settings.plugins.klipper.configuration.shortStatus_navbar"> {{ _('on NavBar') }}</label>
|
||||
<label class="checkbox" title="{{ _('on SideBar') }}"><input type="checkbox" data-bind="checked: settings.settings.plugins.klipper.configuration.shortStatus_sidebar"> {{ _('on SideBar') }}</label>
|
||||
<label class="checkbox" title="{{ _('on NavBar') }}"><input type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.shortStatus_navbar" /> {{ _('on NavBar') }}</label>
|
||||
<label class="checkbox" title="{{ _('on SideBar') }}"><input type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.shortStatus_sidebar" /> {{ _('on SideBar') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Enable debug logging') }}</label>
|
||||
<div class="controls">
|
||||
<input class="controls-checkbox" title="{{ _('Enable debug logging') }}" type="checkbox" data-bind="checked: settings.settings.plugins.klipper.configuration.debug_logging">
|
||||
<input class="controls-checkbox" title="{{ _('Enable debug logging') }}" type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.debug_logging" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Klipper Config File') }}</label>
|
||||
</div>
|
||||
<div class="control-group border">
|
||||
<label class="control-label">{{ _('Config Editor') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.configuration.configpath">
|
||||
<label class="checkbox" title="{{ _('Check parsing on save') }}"><input type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.parse_check" /> {{ _('Check parsing on save') }}
|
||||
</label>
|
||||
<label title="{{ _('Fontsize') }}"><input type="text"
|
||||
class="input-block-level span1" data-bind="value: settings.settings.plugins.klipper.configuration.fontsize,
|
||||
event: { change: checkFontsize}" /> {{ _('Fontsize') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Klipper Config Directory') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.configuration.config_path" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" title="{{ _('The filename of the base config that Klipper is loading. (default is printer.cfg)') }}">{{ _('Klipper Base Config Filename') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.configuration.baseconfig" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Klipper Log File') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.configuration.logpath">
|
||||
<input type="text" class="input-block-level" data-bind="value: settings.settings.plugins.klipper.configuration.logpath" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Configuration Reload Command') }}</label>
|
||||
</div>
|
||||
<div class="control-group border">
|
||||
<label class="control-label">{{ _('Configuration Restart Command') }}</label>
|
||||
<div class="controls">
|
||||
<select data-bind="value: settings.settings.plugins.klipper.configuration.reload_command">
|
||||
<option value="RESTART">RESTART</option>
|
||||
<option value="FIRMWARE_RESTART">FIRMWARE_RESTART</option>
|
||||
<option value="manually">Manually</option>
|
||||
</select>
|
||||
<span class="help-block">
|
||||
The command that is executed when the Klipper configuration changed and needs to be reloaded.<br>
|
||||
Set this to "Manually" if you don't want to immediately restart klipper.
|
||||
</span>
|
||||
<select data-bind="value: settings.settings.plugins.klipper.configuration.reload_command">
|
||||
<option value="RESTART">RESTART</option>
|
||||
<option value="FIRMWARE_RESTART">FIRMWARE_RESTART</option>
|
||||
</select>
|
||||
<span class="help-block" style="margin-top:5px;">
|
||||
{{ _('The command that is executed if you want to restart klipper.') }}
|
||||
</span>
|
||||
<label class="checkbox" title="{{ _('Restart klipper on editor save?') }}"><input type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.restart_onsave" /> {{ _('Restart Klipper on editor save?') }}
|
||||
</label>
|
||||
<label class="checkbox" title="{{ _('Show Confirmation before restarting Klipper?') }}"><input type="checkbox"
|
||||
data-bind="checked: settings.settings.plugins.klipper.configuration.confirm_reload" /> {{ _('Confirmation before restarting Klipper?') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Config Backup') }}</label>
|
||||
<div class="controls">
|
||||
<button class="btn btn-small" data-bind='click: showBackupsDialog' title="{{ _('Show Backups') }}">
|
||||
<i class="fas fa-upload"></i> {{ _('Show Backups') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Macros -->
|
||||
<div class="tab-pane" id="macros">
|
||||
<div class="control-group" style="margin-bottom: 0px;">
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<!-- Macros -->
|
||||
<div class="tab-pane" id="macros">
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
{{ _('These macros are only meant to be used in OctoPrint.') }}
|
||||
{{ _('They are not the ones that can be defined in the printer.cfg.') }}<br />
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group" style="margin-bottom: 0px;">
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<div class="row-fluid">
|
||||
<div class="span8" style="text-align: right"><small>{{ _('Add macro button to:') }}</small></div>
|
||||
<div class="span1" style="margin: auto;text-align: center"><small>{{ _('Klipper Tab') }}</small></div>
|
||||
<div class="span2" style="margin: auto;"><small>{{ _('Sidebar') }}</small></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.macros">
|
||||
<div class="control-group" id="item">
|
||||
<label class="control-label">{{ _('Name') }}</label>
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<div class="row-fluid">
|
||||
<div class="span8">
|
||||
<input type="text" class="input-block-level" data-bind="value: name"/>
|
||||
</div>
|
||||
<div class="span1" style="margin: auto; text-align: center;">
|
||||
<input title="{{ _('Klipper Tab') }}" style="margin: auto;" type="checkbox" class="input-block-level" data-bind="checked: tab"/>
|
||||
</div>
|
||||
<div class="span1" style="margin: auto; text-align: center;">
|
||||
<input title="{{ _('Sidebar') }}" style="margin: auto;" type="checkbox" class="input-block-level" data-bind="checked: sidebar"/>
|
||||
</div>
|
||||
<div class="span2" style="margin: auto; text-align: center;">
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.moveMacroUp' class="fa fa-chevron-up"></a>
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.moveMacroDown' class="fa fa-chevron-down"></a>
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.removeMacro' class="fa fa-trash-o"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="control-label">{{ _('Command') }}</label>
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<div class="row-fluid">
|
||||
<div class="span12" style="margin-top:2px;">
|
||||
<textarea rows="2" class="block" data-bind="value: macro">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a href='#' data-bind='click: addMacro' title="{{ _('Add Macro') }}" class="fa fa-plus-circle"></a> {{ _('Add Macro') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
To show a dialog that asks for parameters you can write your macro like in the following example:<br>
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<pre>
|
||||
PID_CALIBRATE
|
||||
HEATER={label:Heater, default:extruder, options:extruder|extruder1}
|
||||
TARGET={label:Target Temperature, unit:°C, default:190}
|
||||
WRITE_FILE={label:Write to File, default:0, options:0|1}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Leveling -->
|
||||
<div class="tab-pane" id="level">
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
This feature assists in manually leveling you print bed by moving the head to the defined points in sequence.<br>
|
||||
If you use a piece of paper for leveling, set "Probe Height" to the paper thickness eg. "0.1".
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Height') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.height">
|
||||
<span class="add-on">mm</span>
|
||||
</div>
|
||||
<span class="help-inline">{{ _('Z-height to probe at') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Lift') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.lift">
|
||||
<span class="add-on">mm</span>
|
||||
</div>
|
||||
<span class="help-inline">{{ _('Lift Head by this amount before moving.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Feedrate Z') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.speed_z">
|
||||
<span class="add-on">mm/min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Feedrate X/Y') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.speed_xy">
|
||||
<span class="add-on">mm/min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<h5>{{ _('Probe Points') }}</h5>
|
||||
<div class="controls">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">name</div>
|
||||
<div class="span3">x(mm)</div>
|
||||
<div class="span3">y(mm)</div>
|
||||
<div class="span3"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.probe.points" class="control-group">
|
||||
<label class="control-label" data-bind="text: $index"></label>
|
||||
<div class="controls">
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: name"></div>
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: x"></div>
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: y"></div>
|
||||
<div class="span3">
|
||||
<a href='#' data-bind='click: $parent.moveProbePointUp' class="fa fa-chevron-up"></a>
|
||||
<a href='#' data-bind='click: $parent.moveProbePointDown' class="fa fa-chevron-down"></a>
|
||||
<a href='#' data-bind='click: $parent.removeProbePoint' class="fa fa-trash-o"></a>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.macros">
|
||||
<div class="control-group" id="item">
|
||||
<label class="control-label">{{ _('Name') }}</label>
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<div class="row-fluid">
|
||||
<div class="span8">
|
||||
<input type="text" class="input-block-level" data-bind="value: name" />
|
||||
</div>
|
||||
<div class="span1" style="margin: auto; text-align: center;">
|
||||
<input title="{{ _('Klipper Tab') }}" style="margin: auto;" type="checkbox" class="input-block-level" data-bind="checked: tab" />
|
||||
</div>
|
||||
<div class="span1" style="margin: auto; text-align: center;">
|
||||
<input title="{{ _('Sidebar') }}" style="margin: auto;" type="checkbox" class="input-block-level" data-bind="checked: sidebar" />
|
||||
</div>
|
||||
<div class="span2" style="margin: auto; text-align: center;">
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.moveMacroUp' class="fa fa-chevron-up"></a>
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.moveMacroDown' class="fa fa-chevron-down"></a>
|
||||
<a href='#' style="vertical-align: bottom;" data-bind='click: $parent.removeMacro' class="fa fa-trash-o"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="control-label">{{ _('Command') }}</label>
|
||||
<div class="controls" style="margin-left: 82px;">
|
||||
<div class="row-fluid">
|
||||
<div class="span12" style="margin-top:2px;">
|
||||
<textarea rows="2" class="block" data-bind="value: macro">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a href='#' data-bind='click: addMacro' title="{{ _('Add Macro') }}" class="fa fa-plus-circle"></a> {{ _('Add Macro') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
{{ _('To show a dialog that asks for parameters you can write your macro like in the following example:') }}<br />
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<pre>
|
||||
PID_CALIBRATE
|
||||
HEATER={label:Heater, default:extruder, options:extruder|extruder1}
|
||||
TARGET={label:Target Temperature, unit:°C, default:190}
|
||||
WRITE_FILE={label:Write to File, default:0, options:0|1}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a href='#' data-bind="click: addProbePoint" title="{{ _('Add Point') }}" class="fa fa-plus-circle"></a> {{ _('Add Point') }}
|
||||
<!-- Leveling -->
|
||||
<div class="tab-pane" id="level">
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
{{ _('This feature assists in manually leveling your print bed by moving the head to the defined points in sequence.<br />If you use a piece of paper for leveling, set "Probe Height" to the paper thickness eg. "0.1".') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Height') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.height" />
|
||||
<span class="add-on">mm</span>
|
||||
</div>
|
||||
<span class="help-inline">{{ _('Z-height to probe at') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Lift') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.lift" />
|
||||
<span class="add-on">mm</span>
|
||||
</div>
|
||||
<span class="help-inline">{{ _('Lift Head by this amount before moving.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Probe Feedrate Z') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.speed_z" />
|
||||
<span class="add-on">mm/min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Feedrate X/Y') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span3" data-bind="value: settings.settings.plugins.klipper.probe.speed_xy" />
|
||||
<span class="add-on">mm/min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<h5>{{ _('Probe Points') }}</h5>
|
||||
<div class="controls">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">name</div>
|
||||
<div class="span3">x(mm)</div>
|
||||
<div class="span3">y(mm)</div>
|
||||
<div class="span3"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.probe.points" class="control-group">
|
||||
<label class="control-label" data-bind="text: $index"></label>
|
||||
<div class="controls">
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: name" /></div>
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: x" /></div>
|
||||
<div class="span3"><input type="text" class="input-block-level" data-bind="value: y" /></div>
|
||||
<div class="span3">
|
||||
<a href='#' data-bind='click: $parent.moveProbePointUp' class="fa fa-chevron-up"></a>
|
||||
<a href='#' data-bind='click: $parent.moveProbePointDown' class="fa fa-chevron-down"></a>
|
||||
<a href='#' data-bind='click: $parent.removeProbePoint' class="fa fa-trash-o"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a href='#' data-bind="click: addProbePoint" title="{{ _('Add Point') }}" class="fa fa-plus-circle"></a> {{_ ('Add Point') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Klipper Conf -->
|
||||
<div class="tab-pane" id="conf">
|
||||
<div class="klipper-column-fluid klipper-settings-tab">
|
||||
<h3 class="text-center m-0">{{ _('Config Files') }}</h3>
|
||||
<div class="klipper-row-fluid">
|
||||
<div class="klipper-fluid-item-2" data-bind="visible: $root.klipperViewModel.hasRightKo('CONFIG')">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="far fa-square"></i>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:void(0)" data-bind="click: markFilesOnPage">{{ _('Select all on this page') }}</a></li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: markAllFiles">{{ _('Select all') }}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: clearMarkedFiles">{{ _('Clear selection') }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button class="btn btn-small" data-bind="click: newFile" title="{{ _('Add new File') }}">
|
||||
<i class="far fa-file"></i> {{ _('New File') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind="click: showEditor" title="{{ _('Open last config') }}">
|
||||
<i class="fas fa-file-code"></i> {{ _('Open last Editor') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind="click: listCfgFiles" title="{{ _('Refresh file list') }}">
|
||||
<i class="icon-refresh"></i> {{ _('Refresh Files') }}
|
||||
</button>
|
||||
<button class="btn btn-small"
|
||||
data-bind="click: removeMarkedFiles, enable: markedForFileRemove().length > 0">{{ _('Delete selected') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fas fa-wrench"></i> <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { configs.changeSorting('name'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: configs.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> {{ _('Sort by name') }}
|
||||
({{ _('ascending') }})</a></li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { configs.changeSorting('date'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: configs.currentSorting() == 'date' ? 'visible' : 'hidden'}"></i> {{ _('Sort by date') }}
|
||||
({{ _('descending') }})</a></li>
|
||||
<li><a href="javascript:void(0)" data-bind="click: function() { configs.changeSorting('size'); }"><i class="fas fa-check"
|
||||
data-bind="style: {visibility: configs.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> {{ _('Sort by file size') }}
|
||||
({{ _('descending') }})</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="klipper-inline" data-bind="text: PathToConfigs" title="{{ _('Path to the config files.')}}"></p>
|
||||
<div class="scroll-y">
|
||||
<table class="table table-striped table-hover table-condensed table-hover table-fixed" id="klipper_cfg_files">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="klipper_cfgs_checkbox span1"></th>
|
||||
<th class="klipper_cfgs_name">{{ _('Name') }}</th>
|
||||
<th class="klipper_cfgs_size">{{ _('Size') }}</th>
|
||||
<th class="klipper_cfgs_action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: configs.paginatedItems">
|
||||
<tr data-bind="attr: {title: name}">
|
||||
<td class="klipper_cfgs_checkbox">
|
||||
<input type="checkbox"
|
||||
data-bind="value: name, checked: $root.markedForFileRemove, invisible: !$root.klipperViewModel.hasRightKo('CONFIG')">
|
||||
</td>
|
||||
<td class="klipper_cfgs_name" data-bind="text: name"></td>
|
||||
<td class="klipper_cfgs_size" data-bind="text: size"></td>
|
||||
<td class="klipper_cfgs_action">
|
||||
<a href="javascript:void(0)" class="far fa-trash-alt" title="{{ _('Delete') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, click: function() { $parent.removeCfg($data.name);}"></a>
|
||||
|
|
||||
<a href="javascript:void(0)" class="fas fa-download" title="{{ _('Download') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, attr: { href: ($root.klipperViewModel.hasRightKo('CONFIG')()) ? $data.url : 'javascript:void(0)'}"></a>
|
||||
|
|
||||
<a href="javascript:void(0)" class="fas fa-pencil-alt" title="{{ _('Edit') }}"
|
||||
data-bind="css: {disabled: !$root.klipperViewModel.hasRightKo('CONFIG')()}, click: function() { $parent.openConfig($data.name);}"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination pagination-mini pagination-centered">
|
||||
<ul>
|
||||
<li data-bind="css: {disabled: configs.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: configs.prevPage">«</a></li>
|
||||
</ul>
|
||||
<ul data-bind="foreach: configs.pages">
|
||||
<li data-bind="css: {active: $data.number === $root.configs.currentPage(), disabled: $data.number === -1 }">
|
||||
<a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.configs.changePage($data.number); }"></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li data-bind="css: {disabled: configs.currentPage() === configs.lastPage()}">
|
||||
<a href="javascript:void(0)"
|
||||
data-bind="click: configs.nextPage">»
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Klipper Conf -->
|
||||
<div class="tab-pane" id="conf">
|
||||
<div class="control-group">
|
||||
<script src="plugin/klipper/static/js/lib/ace/ace.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="plugin/klipper/static/js/lib/ace/theme-monokai.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="plugin/klipper/static/js/lib/ace/mode-klipper_config.js" type="text/javascript"></script>
|
||||
<div class="editor-controls">
|
||||
<button class="btn btn-small" data-bind="click: loadLastSession"
|
||||
title="{{ _('Reload last changes') }}">
|
||||
<i class="fas fa-redo"></i> {{ _('Reload last changes') }}
|
||||
</button>
|
||||
<button class="btn btn-small" data-bind='click: reloadFromFile'
|
||||
title="{{ _('Reload from file') }}">
|
||||
<i class="fas fa-upload"></i> {{ _('Reload from file') }}
|
||||
</button>
|
||||
<label class="inline"><input class="inline-checkbox" type="checkbox" data-bind="checked: settings.settings.plugins.klipper.configuration.parse_check"> {{ _('Check parsing on save') }}</label>
|
||||
|
||||
<a href='#' data-bind="click: minusFontsize" title="{{ _('Decrease Fontsize') }}" class="fas fa-search-minus"></a>
|
||||
<a href='#' data-bind="click: plusFontsize" title="{{ _('Increase Fontsize') }}" class="fas fa-search-plus"></a>
|
||||
</div>
|
||||
<div class="conf-editor">
|
||||
<input id="hdnLoadKlipperConfig" type="hidden" data-bind="value: configBound(settings.settings.plugins.klipper.config)" />
|
||||
<div id="plugin-klipper-config"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-footer">
|
||||
<a href="https://www.paypal.com/donate/?business=7P63W664NF8LA&item_name=OctoKlipper" class="btn btn-mini" target="_blank">
|
||||
<i class="fab fa-paypal"> {{ _('Donate') }}</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -3,15 +3,17 @@
|
|||
<label for="connection_printers" data-bind="css: {disabled: !connectionState.isErrorOrClosed()}, enable: connectionState.isErrorOrClosed() && loginState.isUser()">{{ _('Printer Profile') }}</label>
|
||||
<select id="connection_printers" data-bind="options: connectionState.printerOptions, optionsText: 'name', optionsValue: 'id', value: connectionState.selectedPrinter, css: {disabled: !connectionState.isErrorOrClosed()}, enable: connectionState.isErrorOrClosed() && loginState.isUser()"></select>
|
||||
<button class="btn btn-block" data-bind="click: connectionState.connect, text: connectionState.buttonText(), enable: loginState.isUser()">{{ _('Connect') }}</button>
|
||||
<button class="btn btn-block" data-bind="visible: hasRight('CONFIG', 'Ko'), click: function() {openOctoKlipperSettings('klipper-config');}">{{ _('Open Klipper config') }}</button>
|
||||
<button class="btn btn-block" title="{{ _('Open Editor') }}" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PLUGIN_KLIPPER_CONFIG), click: showEditorDialog">{{ _('Open Editor') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ko if: settings.settings.plugins.klipper.configuration.shortStatus_sidebar -->
|
||||
<div class="plugin-klipper-sidebar">
|
||||
<a title="Go to OctoKlipper Tab" data-bind="text: shortStatus_sidebar, click: navbarClicked"></a>
|
||||
<div id="shortStatus_SideBar" class="plugin-klipper-sidebar">
|
||||
<a title="{{ _('Go to OctoKlipper Tab') }}" data-bind="click: navbarClicked">
|
||||
<div data-bind="html: shortStatus_sidebar" class="msg"></div>
|
||||
</a>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<div class="control-group" data-bind="visible: hasRight('MACRO', 'Ko')">
|
||||
<div class="control-group" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PLUGIN_KLIPPER_MACRO)">
|
||||
<div class="controls">
|
||||
<label class="control-label small"><i class="icon-list-alt"></i> {{ _('Macros') }}</label>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.macros">
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<div class="row-fluid">
|
||||
<div id="left-side">
|
||||
<label> <i class="icon-tasks"></i> {{ _("Messages") }} </label>
|
||||
<label class="klipper-inline"> <i class="icon-tasks"></i> {{ _("Messages") }} </label>
|
||||
<button class="btn btn-small pull-right"
|
||||
data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PLUGIN_KLIPPER_CONFIG), click: openOctoKlipperSettings('klipper-basic')"
|
||||
title="{{ _('Open the OctoKlipper Settings') }}">
|
||||
<i class="fa icon-black fa-wrench"></i>
|
||||
</button>
|
||||
<div class="plugin-klipper-log" data-bind="foreach: logMessages">
|
||||
<div class="log-item" data-bind="css: type">
|
||||
<div data-bind="text: time" class="ts"></div>
|
||||
|
@ -8,12 +13,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="btn btn-mini pull-right clear-btn"
|
||||
data-bind="click: onClearLog"
|
||||
title="Clear Log"
|
||||
>
|
||||
<i class="fa fa-trash"></i> {{ _("Clear") }}
|
||||
<button class="btn btn-mini pull-right clear-btn" data-bind="click: onClearLog" title="{{ _('Clear Log') }}">
|
||||
<i class="fa fa-trash"></i> {{ _('Clear Log') }}
|
||||
</button>
|
||||
</div>
|
||||
<div id="right-side">
|
||||
|
@ -21,89 +22,58 @@
|
|||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="control-label"></label>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: onGetStatus, enable: isActive()"
|
||||
title="Query Klipper for its current status"
|
||||
>
|
||||
<button class="btn btn-block btn-small" data-bind="click: onGetStatus, enable: isActive()"
|
||||
title="{{ _('Query Klipper for its current status') }}">
|
||||
<i class="fa icon-black fa-info-circle"></i> {{ _("Get Status") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="visible: hasRight('CONFIG', 'Ko'), click: function() {openOctoKlipperSettings('klipper-config');}"
|
||||
title="Open the Klipper configurationfile"
|
||||
>
|
||||
<button class="btn btn-block btn-small"
|
||||
data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PLUGIN_KLIPPER_CONFIG), click: showEditorDialog"
|
||||
title="{{ _('Show the Editor') }}">
|
||||
<i class="fa icon-black fa-file-code-o"></i>
|
||||
{{ _("Open Klipper config") }}
|
||||
{{ _("Show Editor") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="control-label small"
|
||||
><i class="icon-refresh"></i> {{ _("Restart") }}</label
|
||||
>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: onRestartHost, enable: isActive()"
|
||||
title="This will cause the host software to reload its config and perform an internal reset"
|
||||
>
|
||||
<label class="control-label small"><i class="icon-refresh"></i> {{ _("Restart") }}</label>
|
||||
<button class="btn btn-block btn-small" data-bind="click: onRestartHost, enable: isActive()"
|
||||
title="{{ _('This will cause the host software to reload its config and perform an internal reset') }}">
|
||||
{{ _("Host") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: onRestartFirmware, enable: isActive()"
|
||||
title="Similar to a host restart, but also clears any error state from the micro-controller"
|
||||
>
|
||||
<button class="btn btn-block btn-small" data-bind="click: onRestartFirmware, enable: isActive()"
|
||||
title="{{ _('Similar to a host restart, but also clears any error state from the micro-controller') }}">
|
||||
{{ _("Firmware") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="control-label"
|
||||
><i class="icon-wrench"></i> {{ _("Tools") }}</label
|
||||
>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: showLevelingDialog, enable: isActive()"
|
||||
title="Assists in manually leveling your printbed by moving the head to a configurable set of positions in sequence."
|
||||
>
|
||||
<label class="control-label"><i class="icon-wrench"></i> {{ _("Tools") }}</label>
|
||||
<button class="btn btn-block btn-small" data-bind="click: showLevelingDialog, enable: isActive()"
|
||||
title="{{ _('Assists in manually leveling your printbed by moving the head to a configurable set of positions in sequence.') }}">
|
||||
{{ _("Assisted Bed Leveling") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: showPidTuningDialog, enable: isActive()"
|
||||
title="Determines optimal PID parameters by heat cycling the hotend/bed."
|
||||
>
|
||||
<button class="btn btn-block btn-small" data-bind="click: showPidTuningDialog, enable: isActive()"
|
||||
title="{{ _('Determines optimal PID parameters by heat cycling the hotend/bed.') }}">
|
||||
{{ _("PID Tuning") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: showOffsetDialog, enable: isActive()"
|
||||
title="Sets a offset for subsequent GCODE coordinates."
|
||||
>
|
||||
<button class="btn btn-block btn-small" data-bind="click: showOffsetDialog, enable: isActive()"
|
||||
title="{{ _('Sets a offset for subsequent GCODE coordinates.') }}">
|
||||
{{ _("Coordinate Offset") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="click: showGraphDialog"
|
||||
title="Assists in debugging performance issues by analyzing the Klipper log files."
|
||||
>
|
||||
<button class="btn btn-block btn-small" data-bind="click: showGraphDialog"
|
||||
title="{{ _('Assists in debugging performance issues by analyzing the Klipper log files.') }}">
|
||||
{{ _("Analyze Klipper Log") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="visible: hasRight('MACRO', 'Ko')">
|
||||
<label class="control-label"
|
||||
><i class="icon-list-alt"></i> {{ _("Macros") }}</label
|
||||
>
|
||||
<div class="controls" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PLUGIN_KLIPPER_MACRO)">
|
||||
<label class="control-label"><i class="icon-list-alt"></i> {{ _("Macros") }}</label>
|
||||
<div data-bind="foreach: settings.settings.plugins.klipper.macros">
|
||||
<!-- ko if: tab -->
|
||||
<button
|
||||
class="btn btn-block btn-small"
|
||||
data-bind="text: name, click: $parent.executeMacro, enable: $parent.isActive()"
|
||||
></button>
|
||||
<button class="btn btn-block btn-small" data-bind="text: name, click: $parent.executeMacro, enable: $parent.isActive()">
|
||||
</button>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,854 @@
|
|||
# German translations for OctoKlipper.
|
||||
# Copyright (C) 2021 The OctoPrint Project
|
||||
# This file is distributed under the same license as the OctoKlipper
|
||||
# project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OctoKlipper 0.3.8.2\n"
|
||||
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
|
||||
"POT-Creation-Date: 2021-11-12 17:52+0100\n"
|
||||
"PO-Revision-Date: 2021-05-13 17:32+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: de\n"
|
||||
"Language-Team: de <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: octoprint_klipper/__init__.py:93
|
||||
msgid "Allows to config klipper"
|
||||
msgstr "Erlaubt Klipper zu konfigurieren"
|
||||
|
||||
#: octoprint_klipper/__init__.py:101
|
||||
msgid "Allows to use klipper macros"
|
||||
msgstr "Erlaubt Makros zu benutzen"
|
||||
|
||||
#: octoprint_klipper/__init__.py:597
|
||||
msgid "Restart Klipper"
|
||||
msgstr "Klipper Neustart"
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "You are about to restart Klipper!"
|
||||
msgstr "Sie sind dabei Klipper neu zu starten!"
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "This will stop ongoing prints!"
|
||||
msgstr "Dies wird laufende Aufträge abbrechen!"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:86
|
||||
msgid "Error: Klipper config file not found at:"
|
||||
msgstr "Fehler: Klipper Konfigurationsdatei nicht gefunden:"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:89
|
||||
msgid "IOError:"
|
||||
msgstr "IOFehler"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:96
|
||||
msgid "Decode Error:"
|
||||
msgstr "Dekodierungsfehler:"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:100
|
||||
msgid "Please convert your config files to utf-8!"
|
||||
msgstr "Bitte die Konfigurationsdateien nach utf-8 konvertieren!"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:102
|
||||
msgid ""
|
||||
"Or you can also paste your config \n"
|
||||
"into the Editor and save it."
|
||||
msgstr ""
|
||||
"Sie können auch die Konfiguration \n"
|
||||
"in den Editor einfügen und dann speichern."
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:109
|
||||
msgid "File not found!"
|
||||
msgstr "Datei nicht gefunden!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:172
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:11
|
||||
msgid "Go to OctoKlipper Tab"
|
||||
msgstr "Gehe zum OctoKlipper Reiter"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:290
|
||||
msgid "Restarted Klipper"
|
||||
msgstr "Klipper neu gestartet"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:298
|
||||
msgid "All ongoing Prints will be stopped!"
|
||||
msgstr "Alle laufende Drucke werden gestoppt!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:303
|
||||
msgid "Restart Klipper?"
|
||||
msgstr "Klipper neu starten?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:39
|
||||
msgid "Restart"
|
||||
msgstr "Neustart"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
msgid "Restart and don't ask this again."
|
||||
msgstr "Neu starten und dies nicht wieder nachfragen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:110
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:119
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Failed to remove config %(name)s.</p><p>Please consult octoprint.log for "
|
||||
"details.</p>"
|
||||
msgstr ""
|
||||
"Konnte config %(name)s nicht löschen. </p><p> Bitte im octoprint.log "
|
||||
"nachsehen für weitere Details.</p>"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:113
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:122
|
||||
msgid "Could not remove config"
|
||||
msgstr "Konnte Konfiguration nicht löschen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:122
|
||||
#, python-format
|
||||
msgid "You are about to delete backed config file \"%(name)s\"."
|
||||
msgstr "Sie sind dabei die gesicherte Konfigurationsdatei \"%(name)s\" zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:138
|
||||
msgid "This will overwrite any file with the same name on the configpath."
|
||||
msgstr ""
|
||||
"Dies wird jede Datei mit dem gleichen Namen im Konfigurationsordner "
|
||||
"überschreiben."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:141
|
||||
msgid "Are you sure you want to restore now?"
|
||||
msgstr "Sind sie sicher jetzt wiederherzustellen?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:143
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:158
|
||||
msgid "Proceed"
|
||||
msgstr "Weiter"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:168
|
||||
#, python-format
|
||||
msgid "You are about to restore %(count)d backed config files."
|
||||
msgstr ""
|
||||
"Sie sind dabei %(count)d gesicherte Konfigurationsdateien "
|
||||
"wiederherzustellen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:183
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d backed config files."
|
||||
msgstr "Sie sind dabei %(count)d gesicherte Konfigurationsdateien zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:193
|
||||
msgid "Restoring klipper config files"
|
||||
msgstr "Stelle Klipper Konfigdatei wieder her"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:195
|
||||
#, python-format
|
||||
msgid "Restoring %(count)d backed config files..."
|
||||
msgstr "Stelle %(count)d gesicherte Konfigurationsdateien wieder her."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:204
|
||||
#, python-format
|
||||
msgid "Restored %(filename)s..."
|
||||
msgstr "%(filename)s wiederhergestellt..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:215
|
||||
#, python-format
|
||||
msgid "Restoring of %(filename)s failed, continuing..."
|
||||
msgstr "Wiederherstellung von Datei %(filename)s gescheitert, setze fort..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:248
|
||||
msgid "Deleting backup files"
|
||||
msgstr "Lösche gesicherte Dateien"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:249
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d backed files..."
|
||||
msgstr "Lösche %(count)d gesicherte Konfigurationsdateien..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:257
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:178
|
||||
#, python-format
|
||||
msgid "Deleted %(filename)s..."
|
||||
msgstr "%(filename)s gelöscht..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:263
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:188
|
||||
#, python-format
|
||||
msgid "Deleting of %(filename)s failed, continuing..."
|
||||
msgstr "Löschung von Datei %(filename)s gescheitert, setze fort... "
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:68
|
||||
msgid "Closing without saving"
|
||||
msgstr "Schließen ohne zu Speichern?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:69
|
||||
msgid "Your file seems to have changed."
|
||||
msgstr "Datei scheint geändert worden zu sein."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:71
|
||||
msgid "Do you really want to close it?"
|
||||
msgstr "Wollen sie wirklich schließen?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:27
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
msgid "Do not close"
|
||||
msgstr "Nicht schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:38
|
||||
msgid "Save & Close"
|
||||
msgstr "Speichern & Schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:153
|
||||
msgid "Reload Configfile after SAVE_CONFIG?"
|
||||
msgstr "Konfiguration neuladen nach SAVE_CONFIG?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:156
|
||||
msgid "Externally changed config"
|
||||
msgstr "Extern geänderte Konfiguration"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:168
|
||||
msgid "Your configuration seems to be faulty."
|
||||
msgstr "Ihre Konfiguration sieht fehlerhaft aus."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:172
|
||||
msgid "Save faulty Configuration?"
|
||||
msgstr "Speichere fehlerhafte Konfiguration?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:174
|
||||
msgid "Do not save!"
|
||||
msgstr "Datei nicht speichern!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway!"
|
||||
msgstr "Speichere trotzdem!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway and don't ask this again."
|
||||
msgstr "Speichere trotzdem und dies nicht wieder nachfragen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck"
|
||||
msgstr "Syntaxprüfung"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck OK"
|
||||
msgstr "Syntaxprüfung OK"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:231
|
||||
msgid "Faulty config not saved!"
|
||||
msgstr "Fehlerhafte Datei nicht gespeichert!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:233
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:255
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:384
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:40
|
||||
msgid "Save Config"
|
||||
msgstr "Speichere Konfig"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:253
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:329
|
||||
msgid "No filename set"
|
||||
msgstr "Dateiname nicht angegeben"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:305
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:323
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:331
|
||||
msgid "Reload File"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "Reload Config"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "File reloaded."
|
||||
msgstr "Datei neugeladen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
msgid "File saved."
|
||||
msgstr "Datei gespeichert."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:382
|
||||
msgid "File not saved!"
|
||||
msgstr "Datei nicht gespeichert."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:88
|
||||
msgid "Path: "
|
||||
msgstr "Pfad: "
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:131
|
||||
#, python-format
|
||||
msgid "You are about to delete config file \"%(name)s\"."
|
||||
msgstr "Sie sind dabei Konfigurationsdatei \"%(name)s\" zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:158
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d config files."
|
||||
msgstr "Sie sind dabei %(count)d Konfigurationsdateien zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:168
|
||||
msgid "Deleting config files"
|
||||
msgstr "Lösche Konfigurationsdateien"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:169
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d config files..."
|
||||
msgstr "Lösche %(count)d Konfigurationsdateien..."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:5
|
||||
msgid "Backups"
|
||||
msgstr "Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:17
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:253
|
||||
msgid "Select all on this page"
|
||||
msgstr "Wähle alle auf dieser Seite aus"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:20
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:254
|
||||
msgid "Select all"
|
||||
msgstr "Alles Auswählen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:25
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:256
|
||||
msgid "Clear selection"
|
||||
msgstr "Auswahl zurücksetzen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:265
|
||||
msgid "Refresh file list"
|
||||
msgstr "Aktualisiere Dateiliste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:30
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:266
|
||||
msgid "Refresh Files"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:34
|
||||
msgid "Restore selected"
|
||||
msgstr "Ausgewählte wiederherstellen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:36
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:269
|
||||
msgid "Delete selected"
|
||||
msgstr "Ausgewählte löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:277
|
||||
msgid "Sort by name"
|
||||
msgstr "Sortiere nach Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:47
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:278
|
||||
msgid "ascending"
|
||||
msgstr "aufsteigend"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:50
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:280
|
||||
msgid "Sort by date"
|
||||
msgstr "Sortiere nach Datum"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:51
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:55
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:281
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:284
|
||||
msgid "descending"
|
||||
msgstr "absteigend"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:54
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:283
|
||||
msgid "Sort by file size"
|
||||
msgstr "Sortiere nach Dateigröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:65
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:116
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:295
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:66
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:296
|
||||
msgid "Size"
|
||||
msgstr "Größe"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:67
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:297
|
||||
msgid "Action"
|
||||
msgstr "Aktion"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:78
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:309
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:81
|
||||
msgid "Restore"
|
||||
msgstr "Wiederherstellen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:84
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:312
|
||||
msgid "Download"
|
||||
msgstr "Runterladen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:87
|
||||
msgid "Preview"
|
||||
msgstr "Vorschau"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:6
|
||||
msgid "Decrease Fontsize"
|
||||
msgstr "Verringere Schriftgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:9
|
||||
msgid "Increase Fontsize"
|
||||
msgstr "Vergrößere Schriftgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:28
|
||||
msgid "Filename"
|
||||
msgstr "Dateiname"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:31
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:32
|
||||
msgid "Reload from file"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:35
|
||||
msgid "Check Syntax"
|
||||
msgstr "Syntax prüfen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:37
|
||||
msgid "Save Config and Close"
|
||||
msgstr "Speichern und schließen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:41
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:4
|
||||
msgid "Performance Graph"
|
||||
msgstr "Performancediagramm"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:9
|
||||
msgid "Click labels to hide/show dataset"
|
||||
msgstr "Auf Labels klicken zum verstecken/anzeigen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:15
|
||||
msgid "Fill Datasets"
|
||||
msgstr "Fülle Flächen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:22
|
||||
msgid "Select"
|
||||
msgstr "Auswählen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:26
|
||||
msgid "Analyze Log"
|
||||
msgstr "Log analysieren"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:35
|
||||
msgid "Depending on the size of the log file this might take a while."
|
||||
msgstr "Abhängig von der Größe der Logdatei kann es etwas dauern."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:55
|
||||
msgid "Assisted Bed Leveling"
|
||||
msgstr "Unterstützte Druckbett-Nivellierung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:14
|
||||
msgid "Home"
|
||||
msgstr "Grundstellung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:42
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:43
|
||||
msgid "Previous"
|
||||
msgstr "Vorheriger"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:44
|
||||
msgid "Next"
|
||||
msgstr "Nächster"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:45
|
||||
msgid "Stop"
|
||||
msgstr "Stop"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:63
|
||||
msgid "Coordinate Offset"
|
||||
msgstr "Koordinaten Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:8
|
||||
msgid "Set an offset for all future GCODE move commands in mm."
|
||||
msgstr "Setze einen Versatz in mm für alle zukünftigen GCODE Bewegungskommandos"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:26
|
||||
msgid "Add to existing offset"
|
||||
msgstr "Hinzufügen zum existierenden Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:31
|
||||
msgid "Set Offset"
|
||||
msgstr "Setze Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:4
|
||||
msgid "Run - "
|
||||
msgstr "Ausführen - "
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:27
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:59
|
||||
msgid "PID Tuning"
|
||||
msgstr "PID Abstimmung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:8
|
||||
msgid "Heater / Extruder Name (from config file)"
|
||||
msgstr "Heizer / Extruder Name (von Konfigdatei)"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:12
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:17
|
||||
msgid "Target Temperature"
|
||||
msgstr "Zieltemperatur"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:25
|
||||
msgid "The result of the tuning cycle is reported in the message log."
|
||||
msgstr "Die Ergebnisse der Abstimmung werden im Nachrichtenlog ausgegeben."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:28
|
||||
msgid "Start Tuning"
|
||||
msgstr "Starte Abstimmung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:3
|
||||
msgid "Basic"
|
||||
msgstr "Haupteinstellungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:72
|
||||
msgid "Macros"
|
||||
msgstr "Makros"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:5
|
||||
msgid "Bed Leveling"
|
||||
msgstr "Druckbett-Nivellierung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:6
|
||||
msgid "Klipper Configuration"
|
||||
msgstr "Klipper Konfiguration"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:12
|
||||
msgid "Serial Port"
|
||||
msgstr "Serieller Port"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:18
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:20
|
||||
msgid "Replace Connection Panel"
|
||||
msgstr "Ersetze Verbindungsmenu"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:25
|
||||
msgid "Show Short Messages"
|
||||
msgstr "Zeige Kurzmeldungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:27
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:28
|
||||
msgid "on NavBar"
|
||||
msgstr "auf Nav-leiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:30
|
||||
msgid "on SideBar"
|
||||
msgstr "auf Seitenleiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:36
|
||||
msgid "Enable debug logging"
|
||||
msgstr "Aktiviere Debugloging"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:41
|
||||
msgid "Config Editor"
|
||||
msgstr "Konfig Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:43
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:44
|
||||
msgid "Check parsing on save"
|
||||
msgstr "Prüfe Syntax beim speichern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:48
|
||||
msgid "Fontsize"
|
||||
msgstr "Fontgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:53
|
||||
msgid "Klipper Config Directory"
|
||||
msgstr "Klipper Konfig Pfad"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid ""
|
||||
"The filename of the base config that Klipper is loading. (default is "
|
||||
"printer.cfg)"
|
||||
msgstr ""
|
||||
"Der Dateiname der Haupt-Konfigurationsdatei, die Klipper läd.(Standard "
|
||||
"ist printer.cfg)"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid "Klipper Base Config Filename"
|
||||
msgstr "Klipper Haupt-Konfigurationsdatei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:65
|
||||
msgid "Klipper Log File"
|
||||
msgstr "Klipper Logdatei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:71
|
||||
msgid "Configuration Restart Command"
|
||||
msgstr "Konfiguration Neustart Befehl"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:78
|
||||
msgid "The command that is executed if you want to restart klipper."
|
||||
msgstr "Der Befehl, der ausgeführt wird, um Klipper neu zu starten."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:80
|
||||
msgid "Restart klipper on editor save?"
|
||||
msgstr "Klipper neu starten nach speichern im Editor?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:81
|
||||
msgid "Restart Klipper on editor save?"
|
||||
msgstr "Klipper neu starten nach speichern im Editor?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:83
|
||||
msgid "Show Confirmation before restarting Klipper?"
|
||||
msgstr "Zeige Bestätigung vor Klipper Neustart?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:84
|
||||
msgid "Confirmation before restarting Klipper?"
|
||||
msgstr "Bestätigung vor Klipper Neustart?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:89
|
||||
msgid "Config Backup"
|
||||
msgstr "Konfig Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:91
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:92
|
||||
msgid "Show Backups"
|
||||
msgstr "Zeige Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:101
|
||||
msgid "These macros are only meant to be used in OctoPrint."
|
||||
msgstr "Diese Makros sind nur für OctoPrint gedacht."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:102
|
||||
msgid "They are not the ones that can be defined in the printer.cfg."
|
||||
msgstr "Es sind nicht die, die in der printer.cfg definiert werden können."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:108
|
||||
msgid "Add macro button to:"
|
||||
msgstr "Zeige Makroschaltfläche auf:"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:109
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:123
|
||||
msgid "Klipper Tab"
|
||||
msgstr "Klipper Reiter"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:110
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:126
|
||||
msgid "Sidebar"
|
||||
msgstr "Seitenleiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:135
|
||||
msgid "Command"
|
||||
msgstr "Befehl"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:148
|
||||
msgid "Add Macro"
|
||||
msgstr "Makro hinzufügen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:153
|
||||
msgid ""
|
||||
"To show a dialog that asks for parameters you can write your macro like "
|
||||
"in the following example:"
|
||||
msgstr ""
|
||||
"Um ein Dialog anzeigen zu lassen, welches nach Parametern fragt, kann man"
|
||||
" ein Makro wie im nächsten Beispiel schreiben:"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:169
|
||||
msgid ""
|
||||
"This feature assists in manually leveling your print bed by moving the "
|
||||
"head to the defined points in sequence.<br />If you use a piece of paper "
|
||||
"for leveling, set \"Probe Height\" to the paper thickness eg. \"0.1\"."
|
||||
msgstr ""
|
||||
"Diese Funktion hilft beim Einstellen des Druckbettes, da "
|
||||
"es die angegebenen Punkte automatisch nacheinander anfährt. <br />"
|
||||
"Wenn man ein Papier zum messen nimmt, setzt man \"Messhöhe\" "
|
||||
"auf die Papierstärke zBsp.: \"0.1\"."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:173
|
||||
msgid "Probe Height"
|
||||
msgstr "Messhöhe"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:179
|
||||
msgid "Z-height to probe at"
|
||||
msgstr "Höhe bei der gemessen wird"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:183
|
||||
msgid "Probe Lift"
|
||||
msgstr "Höhe für Seitenbewegung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:189
|
||||
msgid "Lift Head by this amount before moving."
|
||||
msgstr "Hebe Druckkopf auf diese Höhe vor einer Seitenbewegung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:193
|
||||
msgid "Probe Feedrate Z"
|
||||
msgstr "Geschwindigkeit Z"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:202
|
||||
msgid "Feedrate X/Y"
|
||||
msgstr "Geschwindigkeit X/Y"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:211
|
||||
msgid "Probe Points"
|
||||
msgstr "Messpunkte"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:238
|
||||
msgid "Add Point"
|
||||
msgstr "Füge Messpunkt hinzu"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:245
|
||||
msgid "Config Files"
|
||||
msgstr "Konfig Dateien"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:259
|
||||
msgid "Add new File"
|
||||
msgstr "Erstelle neue Datei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:260
|
||||
msgid "New File"
|
||||
msgstr "Neue Datei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:262
|
||||
msgid "Open last config"
|
||||
msgstr "Öffne letzte Konfig"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:263
|
||||
msgid "Open last Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:289
|
||||
msgid "Path to the config files."
|
||||
msgstr "Pfad zu den Konfigurationsdateien"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:315
|
||||
msgid "Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:344
|
||||
msgid "Donate"
|
||||
msgstr "Spenden"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:3
|
||||
msgid "Printer Profile"
|
||||
msgstr "Druckerprofil"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:5
|
||||
msgid "Connect"
|
||||
msgstr "Verbinde"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:6
|
||||
msgid "Open Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:3
|
||||
msgid "Messages"
|
||||
msgstr "Nachricht"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:6
|
||||
msgid "Open the OctoKlipper Settings"
|
||||
msgstr "Öffne die OctoKlipper Einstellungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:17
|
||||
msgid "Clear Log"
|
||||
msgstr "Log löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:26
|
||||
msgid "Query Klipper for its current status"
|
||||
msgstr "Aktuellen Status von Klipper anfordern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:27
|
||||
msgid "Get Status"
|
||||
msgstr "Statusabfrage"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:31
|
||||
msgid "Show the Editor"
|
||||
msgstr "Öffne den Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:33
|
||||
msgid "Show Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:41
|
||||
msgid ""
|
||||
"This will cause the host software to reload its config and perform an "
|
||||
"internal reset"
|
||||
msgstr "Das wird die Konfigurationsdatei neuladen und die Hostsoftware neu starten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:42
|
||||
msgid "Host"
|
||||
msgstr "Host"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:45
|
||||
msgid ""
|
||||
"Similar to a host restart, but also clears any error state from the "
|
||||
"micro-controller"
|
||||
msgstr "Wie der Host Neustart, aber zusätzlich wird die Firmware neu gestartet"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:46
|
||||
msgid "Firmware"
|
||||
msgstr "Firmware"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:52
|
||||
msgid "Tools"
|
||||
msgstr "Tools"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:54
|
||||
msgid ""
|
||||
"Assists in manually leveling your printbed by moving the head to a "
|
||||
"configurable set of positions in sequence."
|
||||
msgstr ""
|
||||
"Unterstützt beim manuellem Bettnivellieren, <br>\n"
|
||||
"da der Druckkopf nacheinander einstellbare Punkte anfährt."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:58
|
||||
msgid "Determines optimal PID parameters by heat cycling the hotend/bed."
|
||||
msgstr ""
|
||||
"Findet optimale PID Parameter beim zyklischen Heizen des "
|
||||
"Druckkopfes/-bettes."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:62
|
||||
msgid "Sets a offset for subsequent GCODE coordinates."
|
||||
msgstr "Setze einen Versatz für alle weiteren GCODE Koordinaten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:66
|
||||
msgid ""
|
||||
"Assists in debugging performance issues by analyzing the Klipper log "
|
||||
"files."
|
||||
msgstr ""
|
||||
"Unterstützt, mit dem analysieren des Klipperlogs, beim Suchen von "
|
||||
"Performanceproblemen."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:67
|
||||
msgid "Analyze Klipper Log"
|
||||
msgstr "Analysiere Klipperlog"
|
|
@ -0,0 +1,104 @@
|
|||
from . import logger
|
||||
|
||||
def migrate_old_settings(self, settings):
|
||||
'''
|
||||
For Old settings
|
||||
'''
|
||||
migrate_settings(settings, "serialport", "connection", "port")
|
||||
migrate_settings(settings, "replace_connection_panel", "connection", "replace_connection_panel")
|
||||
migrate_settings(settings, "probeHeight", "probe", "height")
|
||||
migrate_settings(settings, "probeLift", "probe", "lift")
|
||||
migrate_settings(settings, "probeSpeedXy", "probe", "speed_xy")
|
||||
migrate_settings(settings, "probeSpeedZ", "probe", "speed_z")
|
||||
migrate_settings(settings, "configPath", "configuration", "configpath")
|
||||
|
||||
if settings.has(["probePoints"]):
|
||||
points = settings.get(["probePoints"])
|
||||
points_new = [dict(name="", x=int(p["x"]), y=int(p["y"]), z=0) for p in points]
|
||||
settings.set(["probe", "points"], points_new)
|
||||
settings.remove(["probePoints"])
|
||||
|
||||
def migrate_settings(self, settings, old, new, new2=""):
|
||||
"""migrate setting to setting with an additional path
|
||||
|
||||
Args:
|
||||
settings (any): instance of self._settings
|
||||
old (str): the old setting to migrate
|
||||
new (str): group or only new setting if there is no new2
|
||||
new2 (str, optional): the new setting to migrate to. Defaults to "".
|
||||
""" ''''''
|
||||
if settings.has(old):
|
||||
if new2 != "":
|
||||
logger.log_info(self, "migrate setting for '" + old + "' -> '" + new + "/" + new2 + "'")
|
||||
settings.set([new, new2], settings.get(old))
|
||||
else:
|
||||
logger.log_info(self, "migrate setting for '" + old + "' -> '" + new + "'")
|
||||
settings.set([new], settings.get(old))
|
||||
settings.remove(old)
|
||||
|
||||
def migrate_settings_configuration(self, settings, new, old):
|
||||
"""migrate setting in path configuration to new name
|
||||
|
||||
:param settings: the class of the mixin
|
||||
:type settings: class
|
||||
:param new: new name
|
||||
:type new: str
|
||||
:param old: the old name
|
||||
:type old: str
|
||||
"""
|
||||
|
||||
if settings.has(["configuration", old]):
|
||||
logger.log_info(self, "migrate setting for 'configuration/" + old + "' -> 'configuration/" + new + "'")
|
||||
settings.set(["configuration", new], settings.get(["configuration", old]))
|
||||
settings.remove(["configuration", old])
|
||||
|
||||
def poll_status(self):
|
||||
self._printer.commands("STATUS")
|
||||
|
||||
def update_status(self, subtype, status):
|
||||
send_message(
|
||||
self,
|
||||
type = "status",
|
||||
subtype = subtype,
|
||||
payload = status)
|
||||
|
||||
def file_exist(self, filepath):
|
||||
'''
|
||||
Returns if a file exists and shows PopUp if not
|
||||
'''
|
||||
from os import path
|
||||
if not path.isfile(filepath):
|
||||
logger.log_debug(self, "File: <br />" + filepath + "<br /> does not exist!")
|
||||
send_message(
|
||||
self,
|
||||
type = "PopUp",
|
||||
subtype = "warning",
|
||||
title = "OctoKlipper Settings",
|
||||
payload = "File: <br />" + filepath + "<br /> does not exist!")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def key_exist(dict, key1, key2):
|
||||
try:
|
||||
dict[key1][key2]
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def send_message(self, type, subtype, title = "", payload = ""):
|
||||
"""
|
||||
Send Message over API to FrontEnd
|
||||
"""
|
||||
import datetime
|
||||
self._plugin_manager.send_plugin_message(
|
||||
self._identifier,
|
||||
dict(
|
||||
time = datetime.datetime.now().strftime("%H:%M:%S"),
|
||||
type = type,
|
||||
subtype = subtype,
|
||||
title = title,
|
||||
payload = payload
|
||||
)
|
||||
)
|
2
setup.py
2
setup.py
|
@ -19,7 +19,7 @@ plugin_package = "octoprint_klipper"
|
|||
|
||||
plugin_name = "OctoKlipper"
|
||||
|
||||
plugin_version = "0.3.8.4"
|
||||
plugin_version = "0.3.9"
|
||||
|
||||
plugin_description = """A plugin for OctoPrint to configure,control and monitor the Klipper 3D printer software."""
|
||||
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,854 @@
|
|||
# German translations for OctoKlipper.
|
||||
# Copyright (C) 2021 The OctoPrint Project
|
||||
# This file is distributed under the same license as the OctoKlipper
|
||||
# project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OctoKlipper 0.3.8.2\n"
|
||||
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
|
||||
"POT-Creation-Date: 2021-11-12 17:52+0100\n"
|
||||
"PO-Revision-Date: 2021-05-13 17:32+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: de\n"
|
||||
"Language-Team: de <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: octoprint_klipper/__init__.py:93
|
||||
msgid "Allows to config klipper"
|
||||
msgstr "Erlaubt Klipper zu konfigurieren"
|
||||
|
||||
#: octoprint_klipper/__init__.py:101
|
||||
msgid "Allows to use klipper macros"
|
||||
msgstr "Erlaubt Makros zu benutzen"
|
||||
|
||||
#: octoprint_klipper/__init__.py:597
|
||||
msgid "Restart Klipper"
|
||||
msgstr "Klipper Neustart"
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "You are about to restart Klipper!"
|
||||
msgstr "Sie sind dabei Klipper neu zu starten!"
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "This will stop ongoing prints!"
|
||||
msgstr "Dies wird laufende Aufträge abbrechen!"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:86
|
||||
msgid "Error: Klipper config file not found at:"
|
||||
msgstr "Fehler: Klipper Konfigurationsdatei nicht gefunden:"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:89
|
||||
msgid "IOError:"
|
||||
msgstr "IOFehler"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:96
|
||||
msgid "Decode Error:"
|
||||
msgstr "Dekodierungsfehler:"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:100
|
||||
msgid "Please convert your config files to utf-8!"
|
||||
msgstr "Bitte die Konfigurationsdateien nach utf-8 konvertieren!"
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:102
|
||||
msgid ""
|
||||
"Or you can also paste your config \n"
|
||||
"into the Editor and save it."
|
||||
msgstr ""
|
||||
"Sie können auch die Konfiguration \n"
|
||||
"in den Editor einfügen und dann speichern."
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:109
|
||||
msgid "File not found!"
|
||||
msgstr "Datei nicht gefunden!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:172
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:11
|
||||
msgid "Go to OctoKlipper Tab"
|
||||
msgstr "Gehe zum OctoKlipper Reiter"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:290
|
||||
msgid "Restarted Klipper"
|
||||
msgstr "Klipper neu gestartet"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:298
|
||||
msgid "All ongoing Prints will be stopped!"
|
||||
msgstr "Alle laufende Drucke werden gestoppt!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:303
|
||||
msgid "Restart Klipper?"
|
||||
msgstr "Klipper neu starten?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:39
|
||||
msgid "Restart"
|
||||
msgstr "Neustart"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
msgid "Restart and don't ask this again."
|
||||
msgstr "Neu starten und dies nicht wieder nachfragen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:110
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:119
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Failed to remove config %(name)s.</p><p>Please consult octoprint.log for "
|
||||
"details.</p>"
|
||||
msgstr ""
|
||||
"Konnte config %(name)s nicht löschen. </p><p> Bitte im octoprint.log "
|
||||
"nachsehen für weitere Details.</p>"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:113
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:122
|
||||
msgid "Could not remove config"
|
||||
msgstr "Konnte Konfiguration nicht löschen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:122
|
||||
#, python-format
|
||||
msgid "You are about to delete backed config file \"%(name)s\"."
|
||||
msgstr "Sie sind dabei die gesicherte Konfigurationsdatei \"%(name)s\" zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:138
|
||||
msgid "This will overwrite any file with the same name on the configpath."
|
||||
msgstr ""
|
||||
"Dies wird jede Datei mit dem gleichen Namen im Konfigurationsordner "
|
||||
"überschreiben."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:141
|
||||
msgid "Are you sure you want to restore now?"
|
||||
msgstr "Sind sie sicher jetzt wiederherzustellen?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:143
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:158
|
||||
msgid "Proceed"
|
||||
msgstr "Weiter"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:168
|
||||
#, python-format
|
||||
msgid "You are about to restore %(count)d backed config files."
|
||||
msgstr ""
|
||||
"Sie sind dabei %(count)d gesicherte Konfigurationsdateien "
|
||||
"wiederherzustellen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:183
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d backed config files."
|
||||
msgstr "Sie sind dabei %(count)d gesicherte Konfigurationsdateien zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:193
|
||||
msgid "Restoring klipper config files"
|
||||
msgstr "Stelle Klipper Konfigdatei wieder her"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:195
|
||||
#, python-format
|
||||
msgid "Restoring %(count)d backed config files..."
|
||||
msgstr "Stelle %(count)d gesicherte Konfigurationsdateien wieder her."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:204
|
||||
#, python-format
|
||||
msgid "Restored %(filename)s..."
|
||||
msgstr "%(filename)s wiederhergestellt..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:215
|
||||
#, python-format
|
||||
msgid "Restoring of %(filename)s failed, continuing..."
|
||||
msgstr "Wiederherstellung von Datei %(filename)s gescheitert, setze fort..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:248
|
||||
msgid "Deleting backup files"
|
||||
msgstr "Lösche gesicherte Dateien"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:249
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d backed files..."
|
||||
msgstr "Lösche %(count)d gesicherte Konfigurationsdateien..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:257
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:178
|
||||
#, python-format
|
||||
msgid "Deleted %(filename)s..."
|
||||
msgstr "%(filename)s gelöscht..."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:263
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:188
|
||||
#, python-format
|
||||
msgid "Deleting of %(filename)s failed, continuing..."
|
||||
msgstr "Löschung von Datei %(filename)s gescheitert, setze fort... "
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:68
|
||||
msgid "Closing without saving"
|
||||
msgstr "Schließen ohne zu Speichern?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:69
|
||||
msgid "Your file seems to have changed."
|
||||
msgstr "Datei scheint geändert worden zu sein."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:71
|
||||
msgid "Do you really want to close it?"
|
||||
msgstr "Wollen sie wirklich schließen?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:27
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
msgid "Do not close"
|
||||
msgstr "Nicht schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:38
|
||||
msgid "Save & Close"
|
||||
msgstr "Speichern & Schließen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:153
|
||||
msgid "Reload Configfile after SAVE_CONFIG?"
|
||||
msgstr "Konfiguration neuladen nach SAVE_CONFIG?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:156
|
||||
msgid "Externally changed config"
|
||||
msgstr "Extern geänderte Konfiguration"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:168
|
||||
msgid "Your configuration seems to be faulty."
|
||||
msgstr "Ihre Konfiguration sieht fehlerhaft aus."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:172
|
||||
msgid "Save faulty Configuration?"
|
||||
msgstr "Speichere fehlerhafte Konfiguration?"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:174
|
||||
msgid "Do not save!"
|
||||
msgstr "Datei nicht speichern!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway!"
|
||||
msgstr "Speichere trotzdem!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway and don't ask this again."
|
||||
msgstr "Speichere trotzdem und dies nicht wieder nachfragen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck"
|
||||
msgstr "Syntaxprüfung"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck OK"
|
||||
msgstr "Syntaxprüfung OK"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:231
|
||||
msgid "Faulty config not saved!"
|
||||
msgstr "Fehlerhafte Datei nicht gespeichert!"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:233
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:255
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:384
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:40
|
||||
msgid "Save Config"
|
||||
msgstr "Speichere Konfig"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:253
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:329
|
||||
msgid "No filename set"
|
||||
msgstr "Dateiname nicht angegeben"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:305
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:323
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:331
|
||||
msgid "Reload File"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "Reload Config"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "File reloaded."
|
||||
msgstr "Datei neugeladen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
msgid "File saved."
|
||||
msgstr "Datei gespeichert."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:382
|
||||
msgid "File not saved!"
|
||||
msgstr "Datei nicht gespeichert."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:88
|
||||
msgid "Path: "
|
||||
msgstr "Pfad: "
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:131
|
||||
#, python-format
|
||||
msgid "You are about to delete config file \"%(name)s\"."
|
||||
msgstr "Sie sind dabei Konfigurationsdatei \"%(name)s\" zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:158
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d config files."
|
||||
msgstr "Sie sind dabei %(count)d Konfigurationsdateien zu löschen."
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:168
|
||||
msgid "Deleting config files"
|
||||
msgstr "Lösche Konfigurationsdateien"
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:169
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d config files..."
|
||||
msgstr "Lösche %(count)d Konfigurationsdateien..."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:5
|
||||
msgid "Backups"
|
||||
msgstr "Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:17
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:253
|
||||
msgid "Select all on this page"
|
||||
msgstr "Wähle alle auf dieser Seite aus"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:20
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:254
|
||||
msgid "Select all"
|
||||
msgstr "Alles Auswählen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:25
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:256
|
||||
msgid "Clear selection"
|
||||
msgstr "Auswahl zurücksetzen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:265
|
||||
msgid "Refresh file list"
|
||||
msgstr "Aktualisiere Dateiliste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:30
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:266
|
||||
msgid "Refresh Files"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:34
|
||||
msgid "Restore selected"
|
||||
msgstr "Ausgewählte wiederherstellen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:36
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:269
|
||||
msgid "Delete selected"
|
||||
msgstr "Ausgewählte löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:277
|
||||
msgid "Sort by name"
|
||||
msgstr "Sortiere nach Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:47
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:278
|
||||
msgid "ascending"
|
||||
msgstr "aufsteigend"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:50
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:280
|
||||
msgid "Sort by date"
|
||||
msgstr "Sortiere nach Datum"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:51
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:55
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:281
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:284
|
||||
msgid "descending"
|
||||
msgstr "absteigend"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:54
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:283
|
||||
msgid "Sort by file size"
|
||||
msgstr "Sortiere nach Dateigröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:65
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:116
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:295
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:66
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:296
|
||||
msgid "Size"
|
||||
msgstr "Größe"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:67
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:297
|
||||
msgid "Action"
|
||||
msgstr "Aktion"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:78
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:309
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:81
|
||||
msgid "Restore"
|
||||
msgstr "Wiederherstellen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:84
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:312
|
||||
msgid "Download"
|
||||
msgstr "Runterladen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:87
|
||||
msgid "Preview"
|
||||
msgstr "Vorschau"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:6
|
||||
msgid "Decrease Fontsize"
|
||||
msgstr "Verringere Schriftgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:9
|
||||
msgid "Increase Fontsize"
|
||||
msgstr "Vergrößere Schriftgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:28
|
||||
msgid "Filename"
|
||||
msgstr "Dateiname"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:31
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:32
|
||||
msgid "Reload from file"
|
||||
msgstr "Datei neuladen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:35
|
||||
msgid "Check Syntax"
|
||||
msgstr "Syntax prüfen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:37
|
||||
msgid "Save Config and Close"
|
||||
msgstr "Speichern und schließen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:41
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:4
|
||||
msgid "Performance Graph"
|
||||
msgstr "Performancediagramm"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:9
|
||||
msgid "Click labels to hide/show dataset"
|
||||
msgstr "Auf Labels klicken zum verstecken/anzeigen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:15
|
||||
msgid "Fill Datasets"
|
||||
msgstr "Fülle Flächen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:22
|
||||
msgid "Select"
|
||||
msgstr "Auswählen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:26
|
||||
msgid "Analyze Log"
|
||||
msgstr "Log analysieren"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:35
|
||||
msgid "Depending on the size of the log file this might take a while."
|
||||
msgstr "Abhängig von der Größe der Logdatei kann es etwas dauern."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:55
|
||||
msgid "Assisted Bed Leveling"
|
||||
msgstr "Unterstützte Druckbett-Nivellierung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:14
|
||||
msgid "Home"
|
||||
msgstr "Grundstellung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:42
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:43
|
||||
msgid "Previous"
|
||||
msgstr "Vorheriger"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:44
|
||||
msgid "Next"
|
||||
msgstr "Nächster"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:45
|
||||
msgid "Stop"
|
||||
msgstr "Stop"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:63
|
||||
msgid "Coordinate Offset"
|
||||
msgstr "Koordinaten Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:8
|
||||
msgid "Set an offset for all future GCODE move commands in mm."
|
||||
msgstr "Setze einen Versatz in mm für alle zukünftigen GCODE Bewegungskommandos"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:26
|
||||
msgid "Add to existing offset"
|
||||
msgstr "Hinzufügen zum existierenden Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:31
|
||||
msgid "Set Offset"
|
||||
msgstr "Setze Versatz"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:4
|
||||
msgid "Run - "
|
||||
msgstr "Ausführen - "
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:27
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:59
|
||||
msgid "PID Tuning"
|
||||
msgstr "PID Abstimmung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:8
|
||||
msgid "Heater / Extruder Name (from config file)"
|
||||
msgstr "Heizer / Extruder Name (von Konfigdatei)"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:12
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:17
|
||||
msgid "Target Temperature"
|
||||
msgstr "Zieltemperatur"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:25
|
||||
msgid "The result of the tuning cycle is reported in the message log."
|
||||
msgstr "Die Ergebnisse der Abstimmung werden im Nachrichtenlog ausgegeben."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:28
|
||||
msgid "Start Tuning"
|
||||
msgstr "Starte Abstimmung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:3
|
||||
msgid "Basic"
|
||||
msgstr "Haupteinstellungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:72
|
||||
msgid "Macros"
|
||||
msgstr "Makros"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:5
|
||||
msgid "Bed Leveling"
|
||||
msgstr "Druckbett-Nivellierung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:6
|
||||
msgid "Klipper Configuration"
|
||||
msgstr "Klipper Konfiguration"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:12
|
||||
msgid "Serial Port"
|
||||
msgstr "Serieller Port"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:18
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:20
|
||||
msgid "Replace Connection Panel"
|
||||
msgstr "Ersetze Verbindungsmenu"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:25
|
||||
msgid "Show Short Messages"
|
||||
msgstr "Zeige Kurzmeldungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:27
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:28
|
||||
msgid "on NavBar"
|
||||
msgstr "auf Nav-leiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:30
|
||||
msgid "on SideBar"
|
||||
msgstr "auf Seitenleiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:36
|
||||
msgid "Enable debug logging"
|
||||
msgstr "Aktiviere Debugloging"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:41
|
||||
msgid "Config Editor"
|
||||
msgstr "Konfig Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:43
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:44
|
||||
msgid "Check parsing on save"
|
||||
msgstr "Prüfe Syntax beim speichern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:48
|
||||
msgid "Fontsize"
|
||||
msgstr "Fontgröße"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:53
|
||||
msgid "Klipper Config Directory"
|
||||
msgstr "Klipper Konfig Pfad"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid ""
|
||||
"The filename of the base config that Klipper is loading. (default is "
|
||||
"printer.cfg)"
|
||||
msgstr ""
|
||||
"Der Dateiname der Haupt-Konfigurationsdatei, die Klipper läd.(Standard "
|
||||
"ist printer.cfg)"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid "Klipper Base Config Filename"
|
||||
msgstr "Klipper Haupt-Konfigurationsdatei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:65
|
||||
msgid "Klipper Log File"
|
||||
msgstr "Klipper Logdatei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:71
|
||||
msgid "Configuration Restart Command"
|
||||
msgstr "Konfiguration Neustart Befehl"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:78
|
||||
msgid "The command that is executed if you want to restart klipper."
|
||||
msgstr "Der Befehl, der ausgeführt wird, um Klipper neu zu starten."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:80
|
||||
msgid "Restart klipper on editor save?"
|
||||
msgstr "Klipper neu starten nach speichern im Editor?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:81
|
||||
msgid "Restart Klipper on editor save?"
|
||||
msgstr "Klipper neu starten nach speichern im Editor?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:83
|
||||
msgid "Show Confirmation before restarting Klipper?"
|
||||
msgstr "Zeige Bestätigung vor Klipper Neustart?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:84
|
||||
msgid "Confirmation before restarting Klipper?"
|
||||
msgstr "Bestätigung vor Klipper Neustart?"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:89
|
||||
msgid "Config Backup"
|
||||
msgstr "Konfig Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:91
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:92
|
||||
msgid "Show Backups"
|
||||
msgstr "Zeige Sicherungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:101
|
||||
msgid "These macros are only meant to be used in OctoPrint."
|
||||
msgstr "Diese Makros sind nur für OctoPrint gedacht."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:102
|
||||
msgid "They are not the ones that can be defined in the printer.cfg."
|
||||
msgstr "Es sind nicht die, die in der printer.cfg definiert werden können."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:108
|
||||
msgid "Add macro button to:"
|
||||
msgstr "Zeige Makroschaltfläche auf:"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:109
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:123
|
||||
msgid "Klipper Tab"
|
||||
msgstr "Klipper Reiter"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:110
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:126
|
||||
msgid "Sidebar"
|
||||
msgstr "Seitenleiste"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:135
|
||||
msgid "Command"
|
||||
msgstr "Befehl"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:148
|
||||
msgid "Add Macro"
|
||||
msgstr "Makro hinzufügen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:153
|
||||
msgid ""
|
||||
"To show a dialog that asks for parameters you can write your macro like "
|
||||
"in the following example:"
|
||||
msgstr ""
|
||||
"Um ein Dialog anzeigen zu lassen, welches nach Parametern fragt, kann man"
|
||||
" ein Makro wie im nächsten Beispiel schreiben:"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:169
|
||||
msgid ""
|
||||
"This feature assists in manually leveling your print bed by moving the "
|
||||
"head to the defined points in sequence.<br />If you use a piece of paper "
|
||||
"for leveling, set \"Probe Height\" to the paper thickness eg. \"0.1\"."
|
||||
msgstr ""
|
||||
"Diese Funktion hilft beim Einstellen des Druckbettes, da "
|
||||
"es die angegebenen Punkte automatisch nacheinander anfährt. <br />"
|
||||
"Wenn man ein Papier zum messen nimmt, setzt man \"Messhöhe\" "
|
||||
"auf die Papierstärke zBsp.: \"0.1\"."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:173
|
||||
msgid "Probe Height"
|
||||
msgstr "Messhöhe"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:179
|
||||
msgid "Z-height to probe at"
|
||||
msgstr "Höhe bei der gemessen wird"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:183
|
||||
msgid "Probe Lift"
|
||||
msgstr "Höhe für Seitenbewegung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:189
|
||||
msgid "Lift Head by this amount before moving."
|
||||
msgstr "Hebe Druckkopf auf diese Höhe vor einer Seitenbewegung"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:193
|
||||
msgid "Probe Feedrate Z"
|
||||
msgstr "Geschwindigkeit Z"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:202
|
||||
msgid "Feedrate X/Y"
|
||||
msgstr "Geschwindigkeit X/Y"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:211
|
||||
msgid "Probe Points"
|
||||
msgstr "Messpunkte"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:238
|
||||
msgid "Add Point"
|
||||
msgstr "Füge Messpunkt hinzu"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:245
|
||||
msgid "Config Files"
|
||||
msgstr "Konfig Dateien"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:259
|
||||
msgid "Add new File"
|
||||
msgstr "Erstelle neue Datei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:260
|
||||
msgid "New File"
|
||||
msgstr "Neue Datei"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:262
|
||||
msgid "Open last config"
|
||||
msgstr "Öffne letzte Konfig"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:263
|
||||
msgid "Open last Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:289
|
||||
msgid "Path to the config files."
|
||||
msgstr "Pfad zu den Konfigurationsdateien"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:315
|
||||
msgid "Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:344
|
||||
msgid "Donate"
|
||||
msgstr "Spenden"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:3
|
||||
msgid "Printer Profile"
|
||||
msgstr "Druckerprofil"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:5
|
||||
msgid "Connect"
|
||||
msgstr "Verbinde"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:6
|
||||
msgid "Open Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:3
|
||||
msgid "Messages"
|
||||
msgstr "Nachricht"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:6
|
||||
msgid "Open the OctoKlipper Settings"
|
||||
msgstr "Öffne die OctoKlipper Einstellungen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:17
|
||||
msgid "Clear Log"
|
||||
msgstr "Log löschen"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:26
|
||||
msgid "Query Klipper for its current status"
|
||||
msgstr "Aktuellen Status von Klipper anfordern"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:27
|
||||
msgid "Get Status"
|
||||
msgstr "Statusabfrage"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:31
|
||||
msgid "Show the Editor"
|
||||
msgstr "Öffne den Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:33
|
||||
msgid "Show Editor"
|
||||
msgstr "Öffne Editor"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:41
|
||||
msgid ""
|
||||
"This will cause the host software to reload its config and perform an "
|
||||
"internal reset"
|
||||
msgstr "Das wird die Konfigurationsdatei neuladen und die Hostsoftware neu starten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:42
|
||||
msgid "Host"
|
||||
msgstr "Host"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:45
|
||||
msgid ""
|
||||
"Similar to a host restart, but also clears any error state from the "
|
||||
"micro-controller"
|
||||
msgstr "Wie der Host Neustart, aber zusätzlich wird die Firmware neu gestartet"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:46
|
||||
msgid "Firmware"
|
||||
msgstr "Firmware"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:52
|
||||
msgid "Tools"
|
||||
msgstr "Tools"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:54
|
||||
msgid ""
|
||||
"Assists in manually leveling your printbed by moving the head to a "
|
||||
"configurable set of positions in sequence."
|
||||
msgstr ""
|
||||
"Unterstützt beim manuellem Bettnivellieren, <br>\n"
|
||||
"da der Druckkopf nacheinander einstellbare Punkte anfährt."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:58
|
||||
msgid "Determines optimal PID parameters by heat cycling the hotend/bed."
|
||||
msgstr ""
|
||||
"Findet optimale PID Parameter beim zyklischen Heizen des "
|
||||
"Druckkopfes/-bettes."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:62
|
||||
msgid "Sets a offset for subsequent GCODE coordinates."
|
||||
msgstr "Setze einen Versatz für alle weiteren GCODE Koordinaten"
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:66
|
||||
msgid ""
|
||||
"Assists in debugging performance issues by analyzing the Klipper log "
|
||||
"files."
|
||||
msgstr ""
|
||||
"Unterstützt, mit dem analysieren des Klipperlogs, beim Suchen von "
|
||||
"Performanceproblemen."
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:67
|
||||
msgid "Analyze Klipper Log"
|
||||
msgstr "Analysiere Klipperlog"
|
|
@ -0,0 +1,832 @@
|
|||
# Translations template for OctoKlipper.
|
||||
# Copyright (C) 2021 The OctoPrint Project
|
||||
# This file is distributed under the same license as the OctoKlipper
|
||||
# project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OctoKlipper 0.3.9rc6\n"
|
||||
"Report-Msgid-Bugs-To: i18n@octoprint.org\n"
|
||||
"POT-Creation-Date: 2021-11-12 17:52+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: octoprint_klipper/__init__.py:93
|
||||
msgid "Allows to config klipper"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/__init__.py:101
|
||||
msgid "Allows to use klipper macros"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/__init__.py:597
|
||||
msgid "Restart Klipper"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "You are about to restart Klipper!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/__init__.py:598
|
||||
msgid "This will stop ongoing prints!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:86
|
||||
msgid "Error: Klipper config file not found at:"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:89
|
||||
msgid "IOError:"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:96
|
||||
msgid "Decode Error:"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:100
|
||||
msgid "Please convert your config files to utf-8!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:102
|
||||
msgid ""
|
||||
"Or you can also paste your config \n"
|
||||
"into the Editor and save it."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/cfgUtils.py:109
|
||||
msgid "File not found!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:172
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:11
|
||||
msgid "Go to OctoKlipper Tab"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:290
|
||||
msgid "Restarted Klipper"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:298
|
||||
msgid "All ongoing Prints will be stopped!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:303
|
||||
msgid "Restart Klipper?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:39
|
||||
msgid "Restart"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper.js:305
|
||||
msgid "Restart and don't ask this again."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:110
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:119
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Failed to remove config %(name)s.</p><p>Please consult octoprint.log for "
|
||||
"details.</p>"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:113
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:122
|
||||
msgid "Could not remove config"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:122
|
||||
#, python-format
|
||||
msgid "You are about to delete backed config file \"%(name)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:138
|
||||
msgid "This will overwrite any file with the same name on the configpath."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:141
|
||||
msgid "Are you sure you want to restore now?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:143
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:158
|
||||
msgid "Proceed"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:168
|
||||
#, python-format
|
||||
msgid "You are about to restore %(count)d backed config files."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:183
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d backed config files."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:193
|
||||
msgid "Restoring klipper config files"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:195
|
||||
#, python-format
|
||||
msgid "Restoring %(count)d backed config files..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:204
|
||||
#, python-format
|
||||
msgid "Restored %(filename)s..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:215
|
||||
#, python-format
|
||||
msgid "Restoring of %(filename)s failed, continuing..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:248
|
||||
msgid "Deleting backup files"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:249
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d backed files..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:257
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:178
|
||||
#, python-format
|
||||
msgid "Deleted %(filename)s..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_backup.js:263
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:188
|
||||
#, python-format
|
||||
msgid "Deleting of %(filename)s failed, continuing..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:68
|
||||
msgid "Closing without saving"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:69
|
||||
msgid "Your file seems to have changed."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:71
|
||||
msgid "Do you really want to close it?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:27
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
msgid "Do not close"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:72
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:38
|
||||
msgid "Save & Close"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:153
|
||||
msgid "Reload Configfile after SAVE_CONFIG?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:156
|
||||
msgid "Externally changed config"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:168
|
||||
msgid "Your configuration seems to be faulty."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:172
|
||||
msgid "Save faulty Configuration?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:174
|
||||
msgid "Do not save!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:175
|
||||
msgid "Save anyway and don't ask this again."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:199
|
||||
msgid "SyntaxCheck OK"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:231
|
||||
msgid "Faulty config not saved!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:233
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:255
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:384
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:40
|
||||
msgid "Save Config"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:253
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:329
|
||||
msgid "No filename set"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:305
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:323
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:331
|
||||
msgid "Reload File"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "Reload Config"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:309
|
||||
msgid "File reloaded."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:372
|
||||
msgid "File saved."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_editor.js:382
|
||||
msgid "File not saved!"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:88
|
||||
msgid "Path: "
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:131
|
||||
#, python-format
|
||||
msgid "You are about to delete config file \"%(name)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:158
|
||||
#, python-format
|
||||
msgid "You are about to delete %(count)d config files."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:168
|
||||
msgid "Deleting config files"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/static/js/klipper_settings.js:169
|
||||
#, python-format
|
||||
msgid "Deleting %(count)d config files..."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:5
|
||||
msgid "Backups"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:17
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:253
|
||||
msgid "Select all on this page"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:20
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:254
|
||||
msgid "Select all"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:25
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:256
|
||||
msgid "Clear selection"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:265
|
||||
msgid "Refresh file list"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:30
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:266
|
||||
msgid "Refresh Files"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:34
|
||||
msgid "Restore selected"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:36
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:269
|
||||
msgid "Delete selected"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:277
|
||||
msgid "Sort by name"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:47
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:278
|
||||
msgid "ascending"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:50
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:280
|
||||
msgid "Sort by date"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:51
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:55
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:281
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:284
|
||||
msgid "descending"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:54
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:283
|
||||
msgid "Sort by file size"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:65
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:116
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:295
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:66
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:296
|
||||
msgid "Size"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:67
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:297
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:78
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:309
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:81
|
||||
msgid "Restore"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:84
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:312
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_backups_dialog.jinja2:87
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:6
|
||||
msgid "Decrease Fontsize"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:9
|
||||
msgid "Increase Fontsize"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:28
|
||||
msgid "Filename"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:31
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:32
|
||||
msgid "Reload from file"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:35
|
||||
msgid "Check Syntax"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:37
|
||||
msgid "Save Config and Close"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_editor.jinja2:41
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:4
|
||||
msgid "Performance Graph"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:9
|
||||
msgid "Click labels to hide/show dataset"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:15
|
||||
msgid "Fill Datasets"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:22
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:26
|
||||
msgid "Analyze Log"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_graph_dialog.jinja2:35
|
||||
msgid "Depending on the size of the log file this might take a while."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:55
|
||||
msgid "Assisted Bed Leveling"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:14
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:42
|
||||
msgid "Start"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:43
|
||||
msgid "Previous"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:44
|
||||
msgid "Next"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_leveling_dialog.jinja2:45
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:63
|
||||
msgid "Coordinate Offset"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:8
|
||||
msgid "Set an offset for all future GCODE move commands in mm."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:26
|
||||
msgid "Add to existing offset"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_offset_dialog.jinja2:31
|
||||
msgid "Set Offset"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:4
|
||||
msgid "Run - "
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_param_macro_dialog.jinja2:27
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:59
|
||||
msgid "PID Tuning"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:8
|
||||
msgid "Heater / Extruder Name (from config file)"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:12
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:17
|
||||
msgid "Target Temperature"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:25
|
||||
msgid "The result of the tuning cycle is reported in the message log."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_pid_tuning_dialog.jinja2:28
|
||||
msgid "Start Tuning"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:3
|
||||
msgid "Basic"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:4
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:72
|
||||
msgid "Macros"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:5
|
||||
msgid "Bed Leveling"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:6
|
||||
msgid "Klipper Configuration"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:12
|
||||
msgid "Serial Port"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:18
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:20
|
||||
msgid "Replace Connection Panel"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:25
|
||||
msgid "Show Short Messages"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:27
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:28
|
||||
msgid "on NavBar"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:29
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:30
|
||||
msgid "on SideBar"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:34
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:36
|
||||
msgid "Enable debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:41
|
||||
msgid "Config Editor"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:43
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:44
|
||||
msgid "Check parsing on save"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:46
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:48
|
||||
msgid "Fontsize"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:53
|
||||
msgid "Klipper Config Directory"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid ""
|
||||
"The filename of the base config that Klipper is loading. (default is "
|
||||
"printer.cfg)"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:59
|
||||
msgid "Klipper Base Config Filename"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:65
|
||||
msgid "Klipper Log File"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:71
|
||||
msgid "Configuration Restart Command"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:78
|
||||
msgid "The command that is executed if you want to restart klipper."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:80
|
||||
msgid "Restart klipper on editor save?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:81
|
||||
msgid "Restart Klipper on editor save?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:83
|
||||
msgid "Show Confirmation before restarting Klipper?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:84
|
||||
msgid "Confirmation before restarting Klipper?"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:89
|
||||
msgid "Config Backup"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:91
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:92
|
||||
msgid "Show Backups"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:101
|
||||
msgid "These macros are only meant to be used in OctoPrint."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:102
|
||||
msgid "They are not the ones that can be defined in the printer.cfg."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:108
|
||||
msgid "Add macro button to:"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:109
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:123
|
||||
msgid "Klipper Tab"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:110
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:126
|
||||
msgid "Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:135
|
||||
msgid "Command"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:148
|
||||
msgid "Add Macro"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:153
|
||||
msgid ""
|
||||
"To show a dialog that asks for parameters you can write your macro like "
|
||||
"in the following example:"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:169
|
||||
msgid ""
|
||||
"This feature assists in manually leveling your print bed by moving the "
|
||||
"head to the defined points in sequence.<br />If you use a piece of paper "
|
||||
"for leveling, set \"Probe Height\" to the paper thickness eg. \"0.1\"."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:173
|
||||
msgid "Probe Height"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:179
|
||||
msgid "Z-height to probe at"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:183
|
||||
msgid "Probe Lift"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:189
|
||||
msgid "Lift Head by this amount before moving."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:193
|
||||
msgid "Probe Feedrate Z"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:202
|
||||
msgid "Feedrate X/Y"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:211
|
||||
msgid "Probe Points"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:238
|
||||
msgid "Add Point"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:245
|
||||
msgid "Config Files"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:259
|
||||
msgid "Add new File"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:260
|
||||
msgid "New File"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:262
|
||||
msgid "Open last config"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:263
|
||||
msgid "Open last Editor"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:289
|
||||
msgid "Path to the config files."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:315
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_settings.jinja2:344
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:3
|
||||
msgid "Printer Profile"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:5
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_sidebar.jinja2:6
|
||||
msgid "Open Editor"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:3
|
||||
msgid "Messages"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:6
|
||||
msgid "Open the OctoKlipper Settings"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:16
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:17
|
||||
msgid "Clear Log"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:26
|
||||
msgid "Query Klipper for its current status"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:27
|
||||
msgid "Get Status"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:31
|
||||
msgid "Show the Editor"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:33
|
||||
msgid "Show Editor"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:41
|
||||
msgid ""
|
||||
"This will cause the host software to reload its config and perform an "
|
||||
"internal reset"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:42
|
||||
msgid "Host"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:45
|
||||
msgid ""
|
||||
"Similar to a host restart, but also clears any error state from the "
|
||||
"micro-controller"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:46
|
||||
msgid "Firmware"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:52
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:54
|
||||
msgid ""
|
||||
"Assists in manually leveling your printbed by moving the head to a "
|
||||
"configurable set of positions in sequence."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:58
|
||||
msgid "Determines optimal PID parameters by heat cycling the hotend/bed."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:62
|
||||
msgid "Sets a offset for subsequent GCODE coordinates."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:66
|
||||
msgid ""
|
||||
"Assists in debugging performance issues by analyzing the Klipper log "
|
||||
"files."
|
||||
msgstr ""
|
||||
|
||||
#: octoprint_klipper/templates/klipper_tab_main.jinja2:67
|
||||
msgid "Analyze Klipper Log"
|
||||
msgstr ""
|
||||
|
Loading…
Reference in New Issue