Cura-5296 Use separate packages.json files in app and user data

This commit is contained in:
Ian Paschal 2018-05-08 11:54:19 +02:00
parent 6dbbfe91db
commit 0accdc6320
9 changed files with 1278 additions and 83 deletions

View file

@ -15,28 +15,6 @@ from UM.Logger import Logger
from UM.Resources import Resources
from UM.Version import Version
BUNDLED = [
"DagomaChromatikPLA",
"FABtotumABS",
"FABtotumNylon",
"FABtotumPLA",
"FABtotumTPU",
"FiberlogyHDPLA",
"Filo3DPLA",
"IMADE3DJellyBOXPETG",
"IMADE3DJellyBOXPLA",
"UltimakerABS",
"UltimakerCPE",
"UltimakerNylon",
"UltimakerPC",
"UltimakerPLA",
"UltimakerPVA",
"VertexDeltaABS",
"VertexDeltaPET",
"VertexDeltaPLA",
"VertexDeltaTPU"
]
class CuraPackageManager(QObject):
Version = 1
@ -51,8 +29,14 @@ class CuraPackageManager(QObject):
self._plugin_registry = self._application.getPluginRegistry()
# JSON file that keeps track of all installed packages.
self._package_management_file_path = os.path.join(os.path.abspath(Resources.getDataStoragePath()),
"packages.json")
self._bundled_package_management_file_path = os.path.join(
Application.getInstallPrefix(),
Application.getInstance().getApplicationName(),
"resources",
"packages.json"
)
self._user_package_management_file_path = os.path.join(os.path.abspath(Resources.getDataStoragePath()), "packages.json")
self._bundled_package_dict = {} # A dict of all bundled packages
self._installed_package_dict = {} # A dict of all installed packages
@ -68,36 +52,42 @@ class CuraPackageManager(QObject):
# (for initialize) Loads the package management file if exists
def _loadManagementData(self) -> None:
if not os.path.exists(self._package_management_file_path):
Logger.log("i", "Package management file %s doesn't exist, do nothing", self._package_management_file_path)
if not os.path.exists(self._bundled_package_management_file_path):
Logger.log("w", "Bundled package management file could not be found!")
return
if not os.path.exists(self._user_package_management_file_path):
Logger.log("i", "User package management file %s doesn't exist, do nothing", self._user_package_management_file_path)
return
# Need to use the file lock here to prevent concurrent I/O from other processes/threads
container_registry = self._application.getContainerRegistry()
with container_registry.lockFile():
with open(self._package_management_file_path, "r", encoding = "utf-8") as f:
management_dict = json.load(f, encoding = "utf-8")
self._bundled_package_dict = management_dict.get("bundled", {})
# Load the bundled packages:
with open(self._bundled_package_management_file_path, "r", encoding = "utf-8") as f:
self._bundled_package_dict = json.load(f, encoding = "utf-8")
Logger.log("i", "Loaded bundled packages data from %s", self._bundled_package_management_file_path)
# Load the user packages:
with open(self._user_package_management_file_path, "r", encoding="utf-8") as f:
management_dict = json.load(f, encoding="utf-8")
self._installed_package_dict = management_dict.get("installed", {})
self._to_remove_package_set = set(management_dict.get("to_remove", []))
self._to_install_package_dict = management_dict.get("to_install", {})
Logger.log("i", "Package management file %s is loaded", self._package_management_file_path)
Logger.log("i", "Loaded user packages management file from %s", self._user_package_management_file_path)
def _saveManagementData(self) -> None:
# Need to use the file lock here to prevent concurrent I/O from other processes/threads
container_registry = self._application.getContainerRegistry()
with container_registry.lockFile():
with open(self._package_management_file_path, "w", encoding = "utf-8") as f:
with open(self._user_package_management_file_path, "w", encoding = "utf-8") as f:
data_dict = {"version": CuraPackageManager.Version,
"bundled": self._bundled_package_dict,
"installed": self._installed_package_dict,
"to_remove": list(self._to_remove_package_set),
"to_install": self._to_install_package_dict}
data_dict["to_remove"] = list(data_dict["to_remove"])
json.dump(data_dict, f, sort_keys = True, indent = 4)
Logger.log("i", "Package management file %s is saved", self._package_management_file_path)
Logger.log("i", "Package management file %s was saved", self._user_package_management_file_path)
# (for initialize) Removes all packages that have been scheduled to be removed.
def _removeAllScheduledPackages(self) -> None:
@ -136,8 +126,12 @@ class CuraPackageManager(QObject):
# Add bundled, installed, and to-install packages to the set of installed package IDs
all_installed_ids = set()
if self._bundled_package_dict.keys():
all_installed_ids = all_installed_ids.union(set(self._bundled_package_dict.keys()))
if self._installed_package_dict.keys():
all_installed_ids = all_installed_ids.union(set(self._installed_package_dict.keys()))
if self._to_install_package_dict.keys():
all_installed_ids = all_installed_ids.union(set(self._to_install_package_dict.keys()))
all_installed_ids = all_installed_ids.difference(self._to_remove_package_set)
@ -162,15 +156,23 @@ class CuraPackageManager(QObject):
package_info = self._to_install_package_dict[package_id]["package_info"]
# We also need to get information from the plugin registry such as if a plugin is active
if package_info["package_type"] == "plugin":
package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id)
else:
package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id)
# If the package ID is in bundled, label it as such
if package_info["package_id"] in self._bundled_package_dict.keys():
package_info["is_bundled"] = True
else:
package_info["is_bundled"] = False
# If there is not a section in the dict for this type, add it
package_type = package_info["package_type"]
if package_type not in installed_packages_dict:
installed_packages_dict[package_type] = []
if package_info["package_type"] not in installed_packages_dict:
installed_packages_dict[package_info["package_type"]] = []
# Finally, add the data
installed_packages_dict[package_type].append( package_info )
installed_packages_dict[package_info["package_type"]].append( package_info )
return installed_packages_dict

View file

@ -2,7 +2,7 @@
"name": "Machine Settings action",
"author": "fieldOfView",
"version": "1.0.0",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc)",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
"api": 4,
"i18n-catalog": "cura"
}

View file

@ -0,0 +1,29 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
ButtonStyle
{
background: Rectangle
{
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
color: "transparent"
border
{
width: UM.Theme.getSize("default_lining").width
color: UM.Theme.getColor("lining")
}
}
label: Label
{
text: control.text
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}

View file

@ -26,7 +26,7 @@ Item
Column
{
id: pluginInfo
property var color: isEnabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
property var color: model.package_type === "plugin" && !isEnabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("text")
height: parent.height
anchors
{
@ -49,12 +49,11 @@ Item
Text
{
text: model.description
maximumLineCount: 3
elide: Text.ElideRight
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
clip: true
wrapMode: Text.WordWrap
color: pluginInfo.color
elide: Text.ElideRight
}
}
Column
@ -104,19 +103,11 @@ Item
right: parent.right
topMargin: UM.Theme.getSize("default_margin").height
}
Button {
id: removeButton
text:
Button
{
if (model.is_bundled)
{
return isEnabled ? catalog.i18nc("@action:button", "Disable") : catalog.i18nc("@action:button", "Enable")
}
else
{
return catalog.i18nc("@action:button", "Uninstall")
}
}
id: disableButton
text: isEnabled ? catalog.i18nc("@action:button", "Disable") : catalog.i18nc("@action:button", "Enable")
visible: model.type == "plugin"
enabled: !toolbox.isDownloading
style: ButtonStyle
{
@ -139,24 +130,36 @@ Item
horizontalAlignment: Text.AlignHCenter
}
}
onClicked:
{
if (model.is_bundled)
{
if (toolbox.isEnabled(model.id))
{
toolbox.disable(model.id)
onClicked: toolbox.isEnabled(model.id) ? toolbox.disable(model.id) : toolbox.enable(model.id)
}
else
Button
{
toolbox.enable(model.id)
id: removeButton
text: catalog.i18nc("@action:button", "Uninstall")
visible: !model.is_bundled
enabled: !toolbox.isDownloading
style: ButtonStyle
{
background: Rectangle
{
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
color: "transparent"
border
{
width: UM.Theme.getSize("default_lining").width
color: UM.Theme.getColor("lining")
}
}
else
label: Label
{
toolbox.uninstall(model.id)
text: control.text
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
onClicked: toolbox.uninstall(model.id)
}
Button
{
@ -180,10 +183,7 @@ Item
font: UM.Theme.getFont("default_bold")
}
}
onClicked:
{
toolbox.update(model.id);
}
onClicked: toolbox.update(model.id)
}
ProgressBar
{

View file

@ -28,8 +28,9 @@ class PackagesModel(ListModel):
self.addRoleName(Qt.UserRole + 11, "download_url")
self.addRoleName(Qt.UserRole + 12, "last_updated")
self.addRoleName(Qt.UserRole + 13, "is_bundled")
self.addRoleName(Qt.UserRole + 14, "has_configs")
self.addRoleName(Qt.UserRole + 15, "supported_configs")
self.addRoleName(Qt.UserRole + 14, "is_enabled")
self.addRoleName(Qt.UserRole + 15, "has_configs")
self.addRoleName(Qt.UserRole + 16, "supported_configs")
# List of filters for queries. The result is the union of the each list of results.
self._filter = {} # type: Dict[str, str]
@ -52,20 +53,26 @@ class PackagesModel(ListModel):
configs_model = ConfigsModel()
configs_model.setConfigs(package["data"]["supported_configs"])
if "author_id" not in package["author"] or "display_name" not in package["author"]:
package["author"]["author_id"] = ""
package["author"]["display_name"] = ""
# raise Exception("Detected a package with malformed author data.")
items.append({
"id": package["package_id"],
"type": package["package_type"],
"name": package["display_name"],
"version": package["package_version"],
"author_id": package["author"]["author_id"] if "author_id" in package["author"] else package["author"]["name"],
"author_name": package["author"]["display_name"] if "display_name" in package["author"] else package["author"]["name"],
"author_id": package["author"]["author_id"],
"author_name": package["author"]["display_name"],
"author_email": package["author"]["email"] if "email" in package["author"] else None,
"description": package["description"],
"description": package["description"] if "description" in package else None,
"icon_url": package["icon_url"] if "icon_url" in package else None,
"image_urls": package["image_urls"] if "image_urls" in package else None,
"download_url": package["download_url"] if "download_url" in package else None,
"last_updated": package["last_updated"] if "last_updated" in package else None,
"is_bundled": package["is_bundled"] if "is_bundled" in package else False,
"is_enabled": package["is_enabled"] if "is_enabled" in package else False,
"has_configs": has_configs,
"supported_configs": configs_model
})

View file

@ -1,7 +1,7 @@
{
"name": "UM3 Network Connection",
"author": "Ultimaker B.V.",
"description": "Manages network connections to Ultimaker 3 printers",
"description": "Manages network connections to Ultimaker 3 printers.",
"version": "1.0.0",
"api": 4,
"i18n-catalog": "cura"

View file

@ -2,7 +2,7 @@
"name": "Ultimaker machine actions",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc)",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
"api": 4,
"i18n-catalog": "cura"
}

View file

@ -2,7 +2,7 @@
"name": "UserAgreement",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Ask the user once if he/she agrees with our license",
"description": "Ask the user once if he/she agrees with our license.",
"api": 4,
"i18n-catalog": "cura"
}

1157
resources/packages.json Normal file

File diff suppressed because it is too large Load diff