mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 06:05:52 +08:00
Merge branch 'master' into CURA-4253_psp
This commit is contained in:
commit
205ac7c50c
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,6 +42,7 @@ plugins/FlatProfileExporter
|
|||||||
plugins/ProfileFlattener
|
plugins/ProfileFlattener
|
||||||
plugins/cura-god-mode-plugin
|
plugins/cura-god-mode-plugin
|
||||||
plugins/cura-big-flame-graph
|
plugins/cura-big-flame-graph
|
||||||
|
plugins/cura-siemensnx-plugin
|
||||||
|
|
||||||
#Build stuff
|
#Build stuff
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import platform
|
import platform
|
||||||
import traceback
|
import traceback
|
||||||
import webbrowser
|
|
||||||
import faulthandler
|
import faulthandler
|
||||||
import tempfile
|
import tempfile
|
||||||
import os
|
import os
|
||||||
import urllib
|
import os.path
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
import ssl
|
||||||
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
|
|
||||||
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QCoreApplication
|
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
|
||||||
from PyQt5.QtGui import QPixmap
|
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QPushButton
|
||||||
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit
|
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.View.GL.OpenGL import OpenGL
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from UM.Platform import Platform
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
MYPY = False
|
MYPY = False
|
||||||
@ -35,83 +44,238 @@ fatal_exception_types = [
|
|||||||
SystemError,
|
SystemError,
|
||||||
]
|
]
|
||||||
|
|
||||||
def show(exception_type, value, tb):
|
class CrashHandler:
|
||||||
Logger.log("c", "An uncaught exception has occurred!")
|
crash_url = "https://stats.ultimaker.com/api/cura"
|
||||||
for line in traceback.format_exception(exception_type, value, tb):
|
|
||||||
for part in line.rstrip("\n").split("\n"):
|
|
||||||
Logger.log("c", part)
|
|
||||||
|
|
||||||
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
def __init__(self, exception_type, value, tb):
|
||||||
return
|
|
||||||
|
|
||||||
application = QCoreApplication.instance()
|
self.exception_type = exception_type
|
||||||
if not application:
|
self.value = value
|
||||||
sys.exit(1)
|
self.traceback = tb
|
||||||
|
|
||||||
dialog = QDialog()
|
# While we create the GUI, the information will be stored for sending afterwards
|
||||||
dialog.setMinimumWidth(640)
|
self.data = dict()
|
||||||
dialog.setMinimumHeight(640)
|
self.data["time_stamp"] = time.time()
|
||||||
dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
Logger.log("c", "An uncaught exception has occurred!")
|
||||||
|
for line in traceback.format_exception(exception_type, value, tb):
|
||||||
|
for part in line.rstrip("\n").split("\n"):
|
||||||
|
Logger.log("c", part)
|
||||||
|
|
||||||
#label = QLabel(dialog)
|
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
||||||
#pixmap = QPixmap()
|
return
|
||||||
#try:
|
|
||||||
# data = urllib.request.urlopen("http://www.randomkittengenerator.com/cats/rotator.php").read()
|
|
||||||
# pixmap.loadFromData(data)
|
|
||||||
#except:
|
|
||||||
# try:
|
|
||||||
# from UM.Resources import Resources
|
|
||||||
# path = Resources.getPath(Resources.Images, "kitten.jpg")
|
|
||||||
# pixmap.load(path)
|
|
||||||
# except:
|
|
||||||
# pass
|
|
||||||
#pixmap = pixmap.scaled(150, 150)
|
|
||||||
#label.setPixmap(pixmap)
|
|
||||||
#label.setAlignment(Qt.AlignCenter)
|
|
||||||
#layout.addWidget(label)
|
|
||||||
|
|
||||||
label = QLabel(dialog)
|
application = QCoreApplication.instance()
|
||||||
layout.addWidget(label)
|
if not application:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
#label.setScaledContents(True)
|
self._createDialog()
|
||||||
label.setText(catalog.i18nc("@label", """<p>A fatal exception has occurred that we could not recover from!</p>
|
|
||||||
<p>Please use the information below to post a bug report at <a href=\"http://github.com/Ultimaker/Cura/issues\">http://github.com/Ultimaker/Cura/issues</a></p>
|
|
||||||
"""))
|
|
||||||
|
|
||||||
textarea = QTextEdit(dialog)
|
## Creates a modal dialog.
|
||||||
layout.addWidget(textarea)
|
def _createDialog(self):
|
||||||
|
|
||||||
try:
|
self.dialog = QDialog()
|
||||||
from UM.Application import Application
|
self.dialog.setMinimumWidth(640)
|
||||||
version = Application.getInstance().getVersion()
|
self.dialog.setMinimumHeight(640)
|
||||||
except:
|
self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
||||||
version = "Unknown"
|
|
||||||
|
|
||||||
trace = "".join(traceback.format_exception(exception_type, value, tb))
|
layout = QVBoxLayout(self.dialog)
|
||||||
|
|
||||||
crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}"
|
layout.addWidget(self._messageWidget())
|
||||||
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace)
|
layout.addWidget(self._informationWidget())
|
||||||
|
layout.addWidget(self._exceptionInfoWidget())
|
||||||
|
layout.addWidget(self._logInfoWidget())
|
||||||
|
layout.addWidget(self._userDescriptionWidget())
|
||||||
|
layout.addWidget(self._buttonsWidget())
|
||||||
|
|
||||||
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
|
def _messageWidget(self):
|
||||||
os.close(tmp_file_fd)
|
label = QLabel()
|
||||||
with open(tmp_file_path, "w") as f:
|
label.setText(catalog.i18nc("@label crash message", """<p><b>A fatal exception has occurred. Please send us this Crash Report to fix the problem</p></b>
|
||||||
faulthandler.dump_traceback(f, all_threads=True)
|
<p>Please use the "Send report" button to post a bug report automatically to our servers</p>
|
||||||
with open(tmp_file_path, "r") as f:
|
"""))
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
msg = "-------------------------\n"
|
return label
|
||||||
msg += data
|
|
||||||
crash_info += "\n\n" + msg
|
|
||||||
|
|
||||||
textarea.setText(crash_info)
|
def _informationWidget(self):
|
||||||
|
group = QGroupBox()
|
||||||
|
group.setTitle(catalog.i18nc("@title:groupbox", "System information"))
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
label = QLabel()
|
||||||
|
|
||||||
buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog)
|
try:
|
||||||
layout.addWidget(buttons)
|
from UM.Application import Application
|
||||||
buttons.addButton(catalog.i18nc("@action:button", "Open Web Page"), QDialogButtonBox.HelpRole)
|
self.cura_version = Application.getInstance().getVersion()
|
||||||
buttons.rejected.connect(dialog.close)
|
except:
|
||||||
buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
|
self.cura_version = catalog.i18nc("@label unknown version of Cura", "Unknown")
|
||||||
|
|
||||||
dialog.exec_()
|
crash_info = catalog.i18nc("@label Cura version", "<b>Cura version:</b> {version}<br/>").format(version = self.cura_version)
|
||||||
sys.exit(1)
|
crash_info += catalog.i18nc("@label Platform", "<b>Platform:</b> {platform}<br/>").format(platform = platform.platform())
|
||||||
|
crash_info += catalog.i18nc("@label Qt version", "<b>Qt version:</b> {qt}<br/>").format(qt = QT_VERSION_STR)
|
||||||
|
crash_info += catalog.i18nc("@label PyQt version", "<b>PyQt version:</b> {pyqt}<br/>").format(pyqt = PYQT_VERSION_STR)
|
||||||
|
crash_info += catalog.i18nc("@label OpenGL", "<b>OpenGL:</b> {opengl}<br/>").format(opengl = self._getOpenGLInfo())
|
||||||
|
label.setText(crash_info)
|
||||||
|
|
||||||
|
layout.addWidget(label)
|
||||||
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
self.data["cura_version"] = self.cura_version
|
||||||
|
self.data["os"] = {"type": platform.system(), "version": platform.version()}
|
||||||
|
self.data["qt_version"] = QT_VERSION_STR
|
||||||
|
self.data["pyqt_version"] = PYQT_VERSION_STR
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
def _getOpenGLInfo(self):
|
||||||
|
info = "<ul>"
|
||||||
|
info += catalog.i18nc("@label OpenGL version", "<li>OpenGL Version: {version}</li>").format(version = OpenGL.getInstance().getOpenGLVersion())
|
||||||
|
info += catalog.i18nc("@label OpenGL vendor", "<li>OpenGL Vendor: {vendor}</li>").format(vendor = OpenGL.getInstance().getGPUVendorName())
|
||||||
|
info += catalog.i18nc("@label OpenGL renderer", "<li>OpenGL Renderer: {renderer}</li>").format(renderer = OpenGL.getInstance().getGPUType())
|
||||||
|
info += "</ul>"
|
||||||
|
|
||||||
|
self.data["opengl"] = {"version": OpenGL.getInstance().getOpenGLVersion(), "vendor": OpenGL.getInstance().getGPUVendorName(), "type": OpenGL.getInstance().getGPUType()}
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
def _exceptionInfoWidget(self):
|
||||||
|
group = QGroupBox()
|
||||||
|
group.setTitle(catalog.i18nc("@title:groupbox", "Exception traceback"))
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
text_area = QTextEdit()
|
||||||
|
trace_dict = traceback.format_exception(self.exception_type, self.value, self.traceback)
|
||||||
|
trace = "".join(trace_dict)
|
||||||
|
text_area.setText(trace)
|
||||||
|
text_area.setReadOnly(True)
|
||||||
|
|
||||||
|
layout.addWidget(text_area)
|
||||||
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
# Parsing all the information to fill the dictionary
|
||||||
|
summary = trace_dict[len(trace_dict)-1].rstrip("\n")
|
||||||
|
module = trace_dict[len(trace_dict)-2].rstrip("\n").split("\n")
|
||||||
|
module_split = module[0].split(", ")
|
||||||
|
filepath = module_split[0].split("\"")[1]
|
||||||
|
directory, filename = os.path.split(filepath)
|
||||||
|
line = int(module_split[1].lstrip("line "))
|
||||||
|
function = module_split[2].lstrip("in ")
|
||||||
|
code = module[1].lstrip(" ")
|
||||||
|
|
||||||
|
# Using this workaround for a cross-platform path splitting
|
||||||
|
split_path = []
|
||||||
|
folder_name = ""
|
||||||
|
# Split until reach folder "cura"
|
||||||
|
while folder_name != "cura":
|
||||||
|
directory, folder_name = os.path.split(directory)
|
||||||
|
if not folder_name:
|
||||||
|
break
|
||||||
|
split_path.append(folder_name)
|
||||||
|
|
||||||
|
# Look for plugins. If it's not a plugin, the current cura version is set
|
||||||
|
isPlugin = False
|
||||||
|
module_version = self.cura_version
|
||||||
|
module_name = "Cura"
|
||||||
|
if split_path.__contains__("plugins"):
|
||||||
|
isPlugin = True
|
||||||
|
# Look backwards until plugin.json is found
|
||||||
|
directory, name = os.path.split(filepath)
|
||||||
|
while not os.listdir(directory).__contains__("plugin.json"):
|
||||||
|
directory, name = os.path.split(directory)
|
||||||
|
|
||||||
|
json_metadata_file = os.path.join(directory, "plugin.json")
|
||||||
|
try:
|
||||||
|
with open(json_metadata_file, "r") as f:
|
||||||
|
try:
|
||||||
|
metadata = json.loads(f.read())
|
||||||
|
module_version = metadata["version"]
|
||||||
|
module_name = metadata["name"]
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
# Not throw new exceptions
|
||||||
|
Logger.logException("e", "Failed to parse plugin.json for plugin %s", name)
|
||||||
|
except:
|
||||||
|
# Not throw new exceptions
|
||||||
|
pass
|
||||||
|
|
||||||
|
exception_dict = dict()
|
||||||
|
exception_dict["traceback"] = {"summary": summary, "full_trace": trace}
|
||||||
|
exception_dict["location"] = {"path": filepath, "file": filename, "function": function, "code": code, "line": line,
|
||||||
|
"module_name": module_name, "version": module_version, "is_plugin": isPlugin}
|
||||||
|
self.data["exception"] = exception_dict
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
def _logInfoWidget(self):
|
||||||
|
group = QGroupBox()
|
||||||
|
group.setTitle(catalog.i18nc("@title:groupbox", "Logs"))
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
text_area = QTextEdit()
|
||||||
|
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
|
||||||
|
os.close(tmp_file_fd)
|
||||||
|
with open(tmp_file_path, "w") as f:
|
||||||
|
faulthandler.dump_traceback(f, all_threads=True)
|
||||||
|
with open(tmp_file_path, "r") as f:
|
||||||
|
logdata = f.read()
|
||||||
|
|
||||||
|
text_area.setText(logdata)
|
||||||
|
text_area.setReadOnly(True)
|
||||||
|
|
||||||
|
layout.addWidget(text_area)
|
||||||
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
self.data["log"] = logdata
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
|
||||||
|
def _userDescriptionWidget(self):
|
||||||
|
group = QGroupBox()
|
||||||
|
group.setTitle(catalog.i18nc("@title:groupbox", "User description"))
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# When sending the report, the user comments will be collected
|
||||||
|
self.user_description_text_area = QTextEdit()
|
||||||
|
self.user_description_text_area.setFocus(True)
|
||||||
|
|
||||||
|
layout.addWidget(self.user_description_text_area)
|
||||||
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
def _buttonsWidget(self):
|
||||||
|
buttons = QDialogButtonBox()
|
||||||
|
buttons.addButton(QDialogButtonBox.Close)
|
||||||
|
buttons.addButton(catalog.i18nc("@action:button", "Send report"), QDialogButtonBox.AcceptRole)
|
||||||
|
buttons.rejected.connect(self.dialog.close)
|
||||||
|
buttons.accepted.connect(self._sendCrashReport)
|
||||||
|
|
||||||
|
return buttons
|
||||||
|
|
||||||
|
def _sendCrashReport(self):
|
||||||
|
# Before sending data, the user comments are stored
|
||||||
|
self.data["user_info"] = self.user_description_text_area.toPlainText()
|
||||||
|
|
||||||
|
# Convert data to bytes
|
||||||
|
binary_data = json.dumps(self.data).encode("utf-8")
|
||||||
|
|
||||||
|
# Submit data
|
||||||
|
kwoptions = {"data": binary_data, "timeout": 5}
|
||||||
|
|
||||||
|
if Platform.isOSX():
|
||||||
|
kwoptions["context"] = ssl._create_unverified_context()
|
||||||
|
|
||||||
|
Logger.log("i", "Sending crash report info to [%s]...", self.crash_url)
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = urllib.request.urlopen(self.crash_url, **kwoptions)
|
||||||
|
Logger.log("i", "Sent crash report info.")
|
||||||
|
f.close()
|
||||||
|
except urllib.error.HTTPError:
|
||||||
|
Logger.logException("e", "An HTTP error occurred while trying to send crash report")
|
||||||
|
except Exception: # We don't want any exception to cause problems
|
||||||
|
Logger.logException("e", "An exception occurred while trying to send crash report")
|
||||||
|
|
||||||
|
os._exit(1)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
self.dialog.exec_()
|
||||||
|
os._exit(1)
|
@ -10,7 +10,6 @@ from UM.Application import Application
|
|||||||
import UM.FlameProfiler
|
import UM.FlameProfiler
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
from cura.Settings.ExtruderStack import ExtruderStack #To listen to changes on the extruders.
|
from cura.Settings.ExtruderStack import ExtruderStack #To listen to changes on the extruders.
|
||||||
from cura.Settings.MachineManager import MachineManager #To listen to changes on the extruders of the currently active machine.
|
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -41,8 +41,9 @@ if "PYTHONPATH" in os.environ.keys(): # If PYTHONPATH is u
|
|||||||
sys.path.insert(1, PATH_real) # Insert it at 1 after os.curdir, which is 0.
|
sys.path.insert(1, PATH_real) # Insert it at 1 after os.curdir, which is 0.
|
||||||
|
|
||||||
def exceptHook(hook_type, value, traceback):
|
def exceptHook(hook_type, value, traceback):
|
||||||
import cura.CrashHandler
|
from cura.CrashHandler import CrashHandler
|
||||||
cura.CrashHandler.show(hook_type, value, traceback)
|
_crash_handler = CrashHandler(hook_type, value, traceback)
|
||||||
|
_crash_handler.show()
|
||||||
|
|
||||||
sys.excepthook = exceptHook
|
sys.excepthook = exceptHook
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class MachineSettingsAction(MachineAction):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def onFinishAction(self):
|
def onFinishAction(self):
|
||||||
# Restore autoslicing when the machineaction is dismissed
|
# Restore autoslicing when the machineaction is dismissed
|
||||||
if self._backend.determineAutoSlicing():
|
if self._backend and self._backend.determineAutoSlicing():
|
||||||
self._backend.tickle()
|
self._backend.tickle()
|
||||||
|
|
||||||
def _onActiveExtruderStackChanged(self):
|
def _onActiveExtruderStackChanged(self):
|
||||||
|
@ -118,24 +118,23 @@ class VersionUpgrade27to30(VersionUpgrade):
|
|||||||
if not parser.has_section("general"):
|
if not parser.has_section("general"):
|
||||||
parser.add_section("general")
|
parser.add_section("general")
|
||||||
|
|
||||||
# Need to exclude the following names:
|
# The ultimaker 2 family
|
||||||
# - ultimaker2_plus
|
ultimaker2_prefix_list = ["ultimaker2_extended_",
|
||||||
# - ultimaker2_go
|
"ultimaker2_go_",
|
||||||
# - ultimaker2_extended
|
"ultimaker2_"]
|
||||||
# - ultimaker2_extended_plus
|
# ultimaker 2+ is a different family, so don't do anything with those
|
||||||
exclude_prefix_list = ["ultimaker2_plus_",
|
exclude_prefix_list = ["ultimaker2_extended_plus_",
|
||||||
"ultimaker2_go_",
|
"ultimaker2_plus_"]
|
||||||
"ultimaker2_extended_",
|
|
||||||
"ultimaker2_extended_plus_"]
|
# set machine definition to "ultimaker2" for the custom quality profiles that can be for the ultimaker 2 family
|
||||||
file_base_name = os.path.basename(filename)
|
file_base_name = os.path.basename(filename)
|
||||||
if file_base_name.startswith("ultimaker2_"):
|
is_ultimaker2_family = False
|
||||||
skip_this = False
|
if not any(file_base_name.startswith(ep) for ep in exclude_prefix_list):
|
||||||
for exclude_prefix in exclude_prefix_list:
|
is_ultimaker2_family = any(file_base_name.startswith(ep) for ep in ultimaker2_prefix_list)
|
||||||
if file_base_name.startswith(exclude_prefix):
|
|
||||||
skip_this = True
|
# ultimaker2 family quality profiles used to set as "fdmprinter" profiles
|
||||||
break
|
if is_ultimaker2_family and parser["general"]["definition"] == "fdmprinter":
|
||||||
if not skip_this:
|
parser["general"]["definition"] = "ultimaker2"
|
||||||
parser["general"]["definition"] = "ultimaker2"
|
|
||||||
|
|
||||||
# Update version numbers
|
# Update version numbers
|
||||||
parser["general"]["version"] = "2"
|
parser["general"]["version"] = "2"
|
||||||
|
@ -63,6 +63,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Druck vollendet"
|
msgstr "Druck vollendet"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Plugins"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Plugins durchsuchen..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Installierte plugins..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Impresión terminada"
|
msgstr "Impresión terminada"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Complementos"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Examinar complementos..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Complementos instalados..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Tulosta valmis"
|
msgstr "Tulosta valmis"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Lisäosat"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Selaa lisäosia..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Asennetut lisäoset..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Impression terminée"
|
msgstr "Impression terminée"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Plug-ins"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Parcourir les plug-ins..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Plug-ins installés..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Stampa finita"
|
msgstr "Stampa finita"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Plugin"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Sfoglia plugin..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Plugin installati..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Print klaar"
|
msgstr "Print klaar"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Plugins"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Door invoegtoepassingen bladeren..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Geïnstalleerde plugins..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -63,6 +63,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Drukowanie zakończone"
|
msgstr "Drukowanie zakończone"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "W&tyczki"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Przeglądaj wtyczki..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Zainstalowane wtyczki..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -62,6 +62,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Impressão Concluída"
|
msgstr "Impressão Concluída"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Complementos"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Navegar complementos..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Complementos instalados..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -63,6 +63,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Печать завершена"
|
msgstr "Печать завершена"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "Плагины"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Просмотр плагинов..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Установленные плагины..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -61,6 +61,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "Baskı tamamlandı"
|
msgstr "Baskı tamamlandı"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "&Eklentiler"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "Eklentilere göz at..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "Yüklü eklentiler..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -63,6 +63,21 @@ msgctxt "@info:status"
|
|||||||
msgid "Print finished"
|
msgid "Print finished"
|
||||||
msgstr "打印完成"
|
msgstr "打印完成"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Cura.qml
|
||||||
|
msgctxt "@title:menu menubar:toplevel"
|
||||||
|
msgid "P&lugins"
|
||||||
|
msgstr "插件"
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Browse plugins..."
|
||||||
|
msgstr "浏览插件..."
|
||||||
|
|
||||||
|
#: Manually added for resources/Cura/Actions.qml
|
||||||
|
msgctxt "@action:menu"
|
||||||
|
msgid "Installed plugins..."
|
||||||
|
msgstr "已安装插件..."
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user