diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e7886c3386..bb29503f77 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -110,6 +110,7 @@ from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager from cura.UI import CuraSplashScreen, MachineActionManager, PrintInformation from cura.UI.MachineSettingsManager import MachineSettingsManager from cura.UI.ObjectsModel import ObjectsModel +from cura.UI.TextManager import TextManager from cura.UI.WelcomePagesModel import WelcomePagesModel from .SingleInstance import SingleInstance @@ -215,6 +216,7 @@ class CuraApplication(QtApplication): self._discovered_printer_model = DiscoveredPrintersModel(self) self._first_start_machine_actions_model = FirstStartMachineActionsModel(self) self._welcome_pages_model = WelcomePagesModel(self) + self._text_manager = TextManager(self) self._quality_profile_drop_down_menu_model = None self._custom_quality_profile_drop_down_menu_model = None @@ -874,6 +876,10 @@ class CuraApplication(QtApplication): def getMachineSettingsManager(self, *args) -> "MachineSettingsManager": return self._machine_settings_manager + @pyqtSlot(result = QObject) + def getTextManager(self, *args) -> "TextManager": + return self._text_manager + def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions": if self._cura_formula_functions is None: self._cura_formula_functions = CuraFormulaFunctions(self) @@ -1007,6 +1013,7 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) qmlRegisterType(WelcomePagesModel, "Cura", 1, 0, "WelcomePagesModel") + qmlRegisterType(TextManager, "Cura", 1, 0, "TextManager") qmlRegisterType(NetworkMJPGImage, "Cura", 1, 0, "NetworkMJPGImage") diff --git a/cura/UI/TextManager.py b/cura/UI/TextManager.py new file mode 100644 index 0000000000..a2708801bb --- /dev/null +++ b/cura/UI/TextManager.py @@ -0,0 +1,64 @@ +# Copyright (c) 2019 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +import collections +from typing import Optional + +from PyQt5.QtCore import QObject, pyqtSlot + +from UM.Resources import Resources +from UM.Version import Version + + +# +# This manager provides means to load texts to QML. +# +class TextManager(QObject): + + def __init__(self, parent: Optional["QObject"] = None) -> None: + super().__init__(parent) + + self._change_log_text = "" + + @pyqtSlot(result = str) + def getChangeLogText(self) -> str: + if not self._change_log_text: + self._change_log_text = self._loadChangeLogText() + return self._change_log_text + + def _loadChangeLogText(self) -> str: + # Load change log texts and organize them with a dict + file_path = Resources.getPath(Resources.Texts, "change_log.txt") + change_logs_dict = {} + with open(file_path, "r", encoding = "utf-8") as f: + open_version = None + open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog + for line in f: + line = line.replace("\n", "") + if "[" in line and "]" in line: + line = line.replace("[", "") + line = line.replace("]", "") + open_version = Version(line) + open_header = "" + change_logs_dict[open_version] = collections.OrderedDict() + elif line.startswith("*"): + open_header = line.replace("*", "") + change_logs_dict[open_version][open_header] = [] + elif line != "": + if open_header not in change_logs_dict[open_version]: + change_logs_dict[open_version][open_header] = [] + change_logs_dict[open_version][open_header].append(line) + + # Format changelog text + content = "" + for version in change_logs_dict: + content += "

" + str(version) + "


" + content += "" + for change in change_logs_dict[version]: + if str(change) != "": + content += "" + str(change) + "
" + for line in change_logs_dict[version][change]: + content += str(line) + "
" + content += "
" + + return content diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py index eeec5edf9b..241d7a8953 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.py +++ b/plugins/ChangeLogPlugin/ChangeLog.py @@ -1,20 +1,20 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import os.path + +from PyQt5.QtCore import QObject + from UM.i18n import i18nCatalog from UM.Extension import Extension from UM.Application import Application from UM.PluginRegistry import PluginRegistry from UM.Version import Version -from PyQt5.QtCore import pyqtSlot, QObject - -import os.path -import collections - catalog = i18nCatalog("cura") -class ChangeLog(Extension, QObject,): + +class ChangeLog(Extension, QObject): def __init__(self, parent = None): QObject.__init__(self, parent) Extension.__init__(self) @@ -26,55 +26,11 @@ class ChangeLog(Extension, QObject,): else: self._current_app_version = None - self._change_logs = None Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated) Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium self.setMenuName(catalog.i18nc("@item:inmenu", "Changelog")) self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog) - def getChangeLogs(self): - if not self._change_logs: - self.loadChangeLogs() - return self._change_logs - - @pyqtSlot(result = str) - def getChangeLogString(self): - logs = self.getChangeLogs() - result = "" - for version in logs: - result += "

" + str(version) + "


" - result += "" - for change in logs[version]: - if str(change) != "": - result += "" + str(change) + "
" - for line in logs[version][change]: - result += str(line) + "
" - result += "
" - - pass - return result - - def loadChangeLogs(self): - self._change_logs = collections.OrderedDict() - with open(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.txt"), "r", encoding = "utf-8") as f: - open_version = None - open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog - for line in f: - line = line.replace("\n","") - if "[" in line and "]" in line: - line = line.replace("[","") - line = line.replace("]","") - open_version = Version(line) - open_header = "" - self._change_logs[open_version] = collections.OrderedDict() - elif line.startswith("*"): - open_header = line.replace("*","") - self._change_logs[open_version][open_header] = [] - elif line != "": - if open_header not in self._change_logs[open_version]: - self._change_logs[open_version][open_header] = [] - self._change_logs[open_version][open_header].append(line) - def _onEngineCreated(self): if not self._current_app_version: return #We're on dev branch. diff --git a/plugins/ChangeLogPlugin/ChangeLog.qml b/plugins/ChangeLogPlugin/ChangeLog.qml index 512687f15a..7089a56caf 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.qml +++ b/plugins/ChangeLogPlugin/ChangeLog.qml @@ -6,7 +6,9 @@ import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 -import UM 1.1 as UM +import UM 1.3 as UM +import Cura 1.0 as Cura + UM.Dialog { @@ -20,7 +22,7 @@ UM.Dialog TextArea { anchors.fill: parent - text: manager.getChangeLogString() + text: CuraApplication.getTextManager().getChangeLogText() readOnly: true; textFormat: TextEdit.RichText } diff --git a/resources/qml/WelcomePages/WhatsNewContent.qml b/resources/qml/WelcomePages/WhatsNewContent.qml index 06b8642e49..298aaa7d4d 100644 --- a/resources/qml/WelcomePages/WhatsNewContent.qml +++ b/resources/qml/WelcomePages/WhatsNewContent.qml @@ -50,18 +50,7 @@ Item TextArea { id: whatsNewTextArea - text: catalog.i18nc("@text", "

Ultimaker Cura 4.0

- -

New features

- -

Brand new user interface. Ultimaker Cura is a very powerful tool with many features to support users’ needs. In the new UI, we present these features in a better, more intuitive way based on the workflow of our users. The Marketplace and user account control have been integrated into the main interface to easily access material profiles and plugins. Within the UI, three stages are shown in the header to give a clear guidance of the flow. The stage menu is populated with collapsible panels that allow users to focus on the 3D view when needed, while still showing important information at the same time, such as slicing configuration and settings. Users can now easily go to the preview stage to examine the layer view after slicing the model, which previously was less obvious or hidden. The new UI also creates more distinction between recommended and custom mode. Novice users or users who are not interested in all the settings can easily prepare a file without diving into details. Expert users can use custom mode with a resizable settings panel to make more settings visible, and the set position will persist between sessions.

- -

Cloud printing. Pair your Ultimaker printer with an Ultimaker account so you can send and monitor print jobs from outside your local network.

- -

Redesigned "Add Printer" dialog. Updated one of the first dialogs a new user is presented with. The layout is loosely modeled on the layout of the Ultimaker 3/Ultimaker S5 "Connect to Network" dialog, and adds some instructions and intention to the dialog. Contributed by fieldOfView.

- -

Integrated backups. Cura backups has been integrated into Ultimaker Cura and can be found in the 'extensions' menu. With this feature, users can backup their Ultimaker Cura configurations to the cloud.

- ") + text: CuraApplication.getTextManager().getChangeLogText() textFormat: Text.RichText wrapMode: Text.WordWrap readOnly: true diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/resources/texts/change_log.txt old mode 100755 new mode 100644 similarity index 100% rename from plugins/ChangeLogPlugin/ChangeLog.txt rename to resources/texts/change_log.txt