Просмотр исходного кода

Merge branch 'master' into CURA-6856_signed_plugins_and_packages

Remco Burema 5 лет назад
Родитель
Сommit
3dabd6023b

+ 12 - 11
.github/ISSUE_TEMPLATE.md

@@ -11,23 +11,24 @@ Information about how to find the log file can be found at https://github.com/Ul
 Thank you for using Cura!
 -->
 
-**Application Version**
-<!-- The version of the application this issue occurs with -->
+**Application version**
+(The version of the application this issue occurs with.)
 
 **Platform**
-<!-- Information about the operating system the issue occurs on -->
+(Information about the operating system the issue occurs on. Include at least the operating system. In the case of visual glitches/issues, also include information about your graphics drivers and GPU.)
 
 **Printer**
-<!-- Which printer was selected in Cura. Please attach project file as .curaproject.3mf.zip -->
+(Which printer was selected in Cura? If possible, please attach project file as .curaproject.3mf.zip.)
 
-**Steps to Reproduce**
-<!-- Add the steps needed that lead up to the issue -->
+**Reproduction steps**
+1. Something you did.
+2. Something you did next.
 
-**Actual Results**
-<!-- What happens after the above steps have been followed -->
+**Actual results**
+(What happens after the above steps have been followed.)
 
 **Expected results**
-<!-- What should happen after the above steps have been followed -->
+(What should happen after the above steps have been followed.)
 
-**Additional Information**
-<!-- Extra information relevant to the issue, like screenshots -->
+**Additional information**
+(Extra information relevant to the issue, like screenshots. Don't forget to attach the log files with this issue report.)

+ 8 - 7
.github/ISSUE_TEMPLATE/bug-report.md

@@ -22,22 +22,23 @@ Thank you for using Cura!
 -->
 
 **Application version**
-<!-- The version of the application this issue occurs with -->
+(The version of the application this issue occurs with.)
 
 **Platform**
-<!-- Information about the operating system the issue occurs on. Include at least the operating system. In the case of visual glitches/issues, also include information about your graphics drivers and GPU. -->
+(Information about the operating system the issue occurs on. Include at least the operating system. In the case of visual glitches/issues, also include information about your graphics drivers and GPU.)
 
 **Printer**
-<!-- Which printer was selected in Cura? If possible, please attach project file as .curaproject.3mf.zip -->
+(Which printer was selected in Cura? If possible, please attach project file as .curaproject.3mf.zip.)
 
 **Reproduction steps**
-<!-- How did you encounter the bug? -->
+1. Something you did.
+2. Something you did next.
 
 **Actual results**
-<!-- What happens after the above steps have been followed -->
+(What happens after the above steps have been followed.)
 
 **Expected results**
-<!-- What should happen after the above steps have been followed -->
+(What should happen after the above steps have been followed.)
 
 **Additional information**
-<!-- Extra information relevant to the issue, like screenshots. Don't forget to attach the log files with this issue report. -->
+(Extra information relevant to the issue, like screenshots. Don't forget to attach the log files with this issue report.)

+ 6 - 5
.github/ISSUE_TEMPLATE/feature_request.md

@@ -8,15 +8,16 @@ assignees: ''
 ---
 
 **Is your feature request related to a problem? Please describe.**
-<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
+(A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
 
 **Describe the solution you'd like**
-<!--A clear and concise description of what you want to happen. If possible, describe why you think this is a good solution.-->
+(A clear and concise description of what you want to happen. If possible, describe why you think this is a good solution.)
 
 **Describe alternatives you've considered**
-<!-- A clear and concise description of any alternative solutions or features you've considered. Again, if possible, think about why these alternatives are not working out. -->
+(A clear and concise description of any alternative solutions or features you've considered. Again, if possible, think about why these alternatives are not working out.)
 
 **Affected users and/or printers**
-<!-- Who do you think will benefit from this? Is everyone going to benefit from these changes? Only a few people? --> 
+(Who do you think will benefit from this? Is everyone going to benefit from these changes? Or specific kinds of users?)
+
 **Additional context**
-<!-- Add any other context or screenshots about the feature request here. -->
+(Add any other context or screenshots about the feature request here.)

+ 3 - 3
CMakeLists.txt

@@ -49,7 +49,7 @@ endif()
 
 
 if(NOT ${URANIUM_DIR} STREQUAL "")
-    set(CMAKE_MODULE_PATH "${URANIUM_DIR}/cmake")
+    set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${URANIUM_DIR}/cmake")
 endif()
 if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
     list(APPEND CMAKE_MODULE_PATH ${URANIUM_DIR}/cmake)
@@ -63,8 +63,8 @@ endif()
 
 install(DIRECTORY resources
         DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
-install(DIRECTORY plugins
-        DESTINATION lib${LIB_SUFFIX}/cura)
+
+include(CuraPluginInstall)
 
 if(NOT APPLE AND NOT WIN32)
     install(FILES cura_app.py

+ 99 - 0
cmake/CuraPluginInstall.cmake

@@ -0,0 +1,99 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# CuraPluginInstall.cmake is released under the terms of the LGPLv3 or higher.
+
+#
+# This module detects all plugins that need to be installed and adds them using the CMake install() command.
+# It detects all plugin folder in the path "plugins/*" where there's a "plugin.json" in it.
+#
+# Plugins can be configured to NOT BE INSTALLED via the variable "CURA_NO_INSTALL_PLUGINS" as a list of string in the
+# form of "a;b;c" or "a,b,c". By default all plugins will be installed.
+#
+
+# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
+# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
+# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
+if(${CMAKE_VERSION} VERSION_LESS 3.12)
+    # Use FindPythonInterp and FindPythonLibs for CMake <3.12
+    find_package(PythonInterp 3 REQUIRED)
+
+    set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
+else()
+    # Use FindPython3 for CMake >=3.12
+    find_package(Python3 REQUIRED COMPONENTS Interpreter)
+endif()
+
+# Options or configuration variables
+set(CURA_NO_INSTALL_PLUGINS "" CACHE STRING "A list of plugins that should not be installed, separated with ';' or ','.")
+
+file(GLOB_RECURSE _plugin_json_list ${CMAKE_SOURCE_DIR}/plugins/*/plugin.json)
+list(LENGTH _plugin_json_list _plugin_json_list_len)
+
+# Sort the lists alphabetically so we can handle cases like this:
+#   - plugins/my_plugin/plugin.json
+#   - plugins/my_plugin/my_module/plugin.json
+# In this case, only "plugins/my_plugin" should be added via install().
+set(_no_install_plugin_list ${CURA_NO_INSTALL_PLUGINS})
+# Sanitize the string so the comparison will be case-insensitive.
+string(STRIP   "${_no_install_plugin_list}" _no_install_plugin_list)
+string(TOLOWER "${_no_install_plugin_list}" _no_install_plugin_list)
+
+# WORKAROUND counterpart of what's in cura-build.
+string(REPLACE "," ";" _no_install_plugin_list "${_no_install_plugin_list}")
+
+list(LENGTH _no_install_plugin_list _no_install_plugin_list_len)
+
+if(_no_install_plugin_list_len GREATER 0)
+    list(SORT _no_install_plugin_list)
+endif()
+if(_plugin_json_list_len GREATER 0)
+    list(SORT _plugin_json_list)
+endif()
+
+# Check all plugin directories and add them via install() if needed.
+set(_install_plugin_list "")
+foreach(_plugin_json_path ${_plugin_json_list})
+    get_filename_component(_plugin_dir ${_plugin_json_path} DIRECTORY)
+    file(RELATIVE_PATH _rel_plugin_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_plugin_dir})
+    get_filename_component(_plugin_dir_name ${_plugin_dir} NAME)
+
+    # Make plugin name comparison case-insensitive
+    string(TOLOWER "${_plugin_dir_name}" _plugin_dir_name_lowercase)
+
+    # Check if this plugin needs to be skipped for installation
+    set(_add_plugin ON)  # Indicates if this plugin should be added to the build or not.
+    set(_is_no_install_plugin OFF)  # If this plugin will not be added, this indicates if it's because the plugin is
+                                    # specified in the NO_INSTALL_PLUGINS list.
+    if(_no_install_plugin_list)
+        if("${_plugin_dir_name_lowercase}" IN_LIST _no_install_plugin_list)
+            set(_add_plugin OFF)
+            set(_is_no_install_plugin ON)
+        endif()
+    endif()
+
+    # Make sure this is not a subdirectory in a plugin that's already in the install list
+    if(_add_plugin)
+        foreach(_known_install_plugin_dir ${_install_plugin_list})
+            if(_plugin_dir MATCHES "${_known_install_plugin_dir}.+")
+                set(_add_plugin OFF)
+                break()
+            endif()
+        endforeach()
+    endif()
+
+    if(_add_plugin)
+        message(STATUS "[+] PLUGIN TO INSTALL: ${_rel_plugin_dir}")
+        get_filename_component(_rel_plugin_parent_dir ${_rel_plugin_dir} DIRECTORY)
+        install(DIRECTORY ${_rel_plugin_dir}
+                DESTINATION lib${LIB_SUFFIX}/cura/${_rel_plugin_parent_dir}
+                PATTERN "__pycache__" EXCLUDE
+                PATTERN "*.qmlc" EXCLUDE
+                )
+        list(APPEND _install_plugin_list ${_plugin_dir})
+    elseif(_is_no_install_plugin)
+        message(STATUS "[-] PLUGIN TO REMOVE : ${_rel_plugin_dir}")
+        execute_process(COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mod_bundled_packages_json.py
+                        -d ${CMAKE_CURRENT_SOURCE_DIR}/resources/bundled_packages
+                        ${_plugin_dir_name}
+                        RESULT_VARIABLE _mod_json_result)
+    endif()
+endforeach()

+ 69 - 0
cmake/mod_bundled_packages_json.py

@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# This script removes the given package entries in the bundled_packages JSON files. This is used by the PluginInstall
+# CMake module.
+#
+
+import argparse
+import collections
+import json
+import os
+import sys
+
+
+## Finds all JSON files in the given directory recursively and returns a list of those files in absolute paths.
+#
+#  \param work_dir The directory to look for JSON files recursively.
+#  \return A list of JSON files in absolute paths that are found in the given directory.
+def find_json_files(work_dir: str) -> list:
+    json_file_list = []
+    for root, dir_names, file_names in os.walk(work_dir):
+        for file_name in file_names:
+            abs_path = os.path.abspath(os.path.join(root, file_name))
+            json_file_list.append(abs_path)
+    return json_file_list
+
+
+## Removes the given entries from the given JSON file. The file will modified in-place.
+#
+#  \param file_path The JSON file to modify.
+#  \param entries A list of strings as entries to remove.
+#  \return None
+def remove_entries_from_json_file(file_path: str, entries: list) -> None:
+    try:
+        with open(file_path, "r", encoding = "utf-8") as f:
+            package_dict = json.load(f, object_hook = collections.OrderedDict)
+    except Exception as e:
+        msg = "Failed to load '{file_path}' as a JSON file. This file will be ignored Exception: {e}"\
+            .format(file_path = file_path, e = e)
+        sys.stderr.write(msg + os.linesep)
+        return
+
+    for entry in entries:
+        if entry in package_dict:
+            del package_dict[entry]
+            print("[INFO] Remove entry [{entry}] from [{file_path}]".format(file_path = file_path, entry = entry))
+
+    try:
+        with open(file_path, "w", encoding = "utf-8", newline = "\n") as f:
+            json.dump(package_dict, f, indent = 4)
+    except Exception as e:
+        msg = "Failed to write '{file_path}' as a JSON file. Exception: {e}".format(file_path = file_path, e = e)
+        raise IOError(msg)
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser("mod_bundled_packages_json")
+    parser.add_argument("-d", "--dir", dest = "work_dir",
+                        help = "The directory to look for bundled packages JSON files, recursively.")
+    parser.add_argument("entries", metavar = "ENTRIES", type = str, nargs = "+")
+
+    args = parser.parse_args()
+
+    json_file_list = find_json_files(args.work_dir)
+    for json_file_path in json_file_list:
+        remove_entries_from_json_file(json_file_path, args.entries)
+
+
+if __name__ == "__main__":
+    main()

+ 7 - 2
cura/CuraApplication.py

@@ -224,7 +224,7 @@ class CuraApplication(QtApplication):
         self._quality_management_model = None
 
         self._discovered_printer_model = DiscoveredPrintersModel(self, parent = self)
-        self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
+        self._first_start_machine_actions_model = None
         self._welcome_pages_model = WelcomePagesModel(self, parent = self)
         self._add_printer_pages_model = AddPrinterPagesModel(self, parent = self)
         self._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
@@ -517,7 +517,8 @@ class CuraApplication(QtApplication):
         with self._container_registry.lockFile():
             self._container_registry.loadAllMetadata()
 
-        # set the setting version for Preferences
+        self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up preferences..."))
+        # Set the setting version for Preferences
         preferences = self.getPreferences()
         preferences.addPreference("metadata/setting_version", 0)
         preferences.setValue("metadata/setting_version", self.SettingVersion) #Don't make it equal to the default so that the setting version always gets written to the file.
@@ -879,6 +880,10 @@ class CuraApplication(QtApplication):
 
     @pyqtSlot(result = QObject)
     def getFirstStartMachineActionsModel(self, *args) -> "FirstStartMachineActionsModel":
+        if self._first_start_machine_actions_model is None:
+            self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
+            if self.started:
+                self._first_start_machine_actions_model.initialize()
         return self._first_start_machine_actions_model
 
     @pyqtSlot(result = QObject)

+ 2 - 2
cura/Machines/Models/FirstStartMachineActionsModel.py

@@ -33,11 +33,11 @@ class FirstStartMachineActionsModel(ListModel):
         self._current_action_index = 0
 
         self._application = application
-        self._application.initializationFinished.connect(self._initialize)
+        self._application.initializationFinished.connect(self.initialize)
 
         self._previous_global_stack = None
 
-    def _initialize(self) -> None:
+    def initialize(self) -> None:
         self._application.getMachineManager().globalContainerChanged.connect(self._update)
         self._update()
 

+ 19 - 7
cura/Machines/Models/IntentCategoryModel.py

@@ -1,7 +1,7 @@
 #Copyright (c) 2019 Ultimaker B.V.
 #Cura is released under the terms of the LGPLv3 or higher.
 
-from PyQt5.QtCore import Qt
+from PyQt5.QtCore import Qt, QTimer
 import collections
 from typing import TYPE_CHECKING, Optional, Dict
 
@@ -35,16 +35,20 @@ class IntentCategoryModel(ListModel):
     _translations["default"] = {
         "name": catalog.i18nc("@label", "Default")
     }
+    _translations["visual"] = {
+        "name": catalog.i18nc("@label", "Visual"),
+        "description": catalog.i18nc("@text", "Optimized for appearance")
+    }
     _translations["engineering"] = {
         "name": catalog.i18nc("@label", "Engineering"),
-        "description": catalog.i18nc("@text", "Suitable for engineering work")
-
+        "description": catalog.i18nc("@text", "Optimized for higher accuracy")
     }
-    _translations["smooth"] = {
-        "name": catalog.i18nc("@label", "Smooth"),
-        "description": catalog.i18nc("@text", "Optimized for a smooth surfaces")
+    _translations["quick"] = {
+        "name": catalog.i18nc("@label", "Draft"),
+        "description": catalog.i18nc("@text", "Optimized for fast results")
     }
 
+
     ##  Creates a new model for a certain intent category.
     #   \param The category to list the intent profiles for.
     def __init__(self, intent_category: str) -> None:
@@ -69,6 +73,11 @@ class IntentCategoryModel(ListModel):
         extruder_manager = application.getExtruderManager()
         extruder_manager.extrudersChanged.connect(self.update)
 
+        self._update_timer = QTimer()
+        self._update_timer.setInterval(500)
+        self._update_timer.setSingleShot(True)
+        self._update_timer.timeout.connect(self._update)
+
         self.update()
 
     ##  Updates the list of intents if an intent profile was added or removed.
@@ -76,8 +85,11 @@ class IntentCategoryModel(ListModel):
         if container.getMetaDataEntry("type") == "intent":
             self.update()
 
+    def update(self):
+        self._update_timer.start()
+
     ##  Updates the list of intents.
-    def update(self) -> None:
+    def _update(self) -> None:
         available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
         result = []
         for category in available_categories:

+ 1 - 1
cura/Machines/VariantNode.py

@@ -83,7 +83,7 @@ class VariantNode(ContainerNode):
     #   if there is no match.
     def preferredMaterial(self, approximate_diameter: int) -> MaterialNode:
         for base_material, material_node in self.materials.items():
-            if self.machine.preferred_material in base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
+            if self.machine.preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
                 return material_node
         # First fallback: Choose any material with matching diameter.
         for material_node in self.materials.values():

Некоторые файлы не были показаны из-за большого количества измененных файлов