mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-03 20:13:56 -06:00
CURA-5137 Add filtering for materials and plugins and change the
behavior of switching tabs.
This commit is contained in:
parent
1ad34495b4
commit
b621b5ef6b
7 changed files with 85 additions and 51 deletions
|
@ -1,6 +1,7 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import re
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
|
||||||
|
@ -33,7 +34,7 @@ class CuraPackageModel(ListModel):
|
||||||
self.addRoleName(CuraPackageModel.ImageURLsRole, "image_urls")
|
self.addRoleName(CuraPackageModel.ImageURLsRole, "image_urls")
|
||||||
|
|
||||||
# List of filters for queries. The result is the union of the each list of results.
|
# List of filters for queries. The result is the union of the each list of results.
|
||||||
self._filter = None # type: Dict[str,str]
|
self._filter = {} # type: Dict[str,str]
|
||||||
|
|
||||||
def setPackagesMetaData(self, data):
|
def setPackagesMetaData(self, data):
|
||||||
self._packages_metadata = data
|
self._packages_metadata = data
|
||||||
|
@ -54,18 +55,46 @@ class CuraPackageModel(ListModel):
|
||||||
"image_urls": package["image_urls"]
|
"image_urls": package["image_urls"]
|
||||||
})
|
})
|
||||||
|
|
||||||
items.sort(key = lambda k: k["name"])
|
# Filter on all the key-word arguments.
|
||||||
self.setItems(items)
|
for key, value in self._filter.items():
|
||||||
|
if "*" in value:
|
||||||
|
key_filter = lambda candidate, key = key, value = value: self._matchRegExp(candidate, key, value)
|
||||||
|
else:
|
||||||
|
key_filter = lambda candidate, key = key, value = value: self._matchString(candidate, key, value)
|
||||||
|
items = filter(key_filter, items)
|
||||||
|
|
||||||
filterChanged = pyqtSignal()
|
# Execute all filters.
|
||||||
|
filtered_items = list(items)
|
||||||
|
|
||||||
|
filtered_items.sort(key = lambda k: k["name"])
|
||||||
|
self.setItems(filtered_items)
|
||||||
|
|
||||||
## Set the filter of this model based on a string.
|
## Set the filter of this model based on a string.
|
||||||
# \param filter_dict \type{Dict} Dictionary to do the filtering by.
|
# \param filter_dict \type{Dict} Dictionary to do the filtering by.
|
||||||
def setFilter(self, filter_dict: Dict[str, str]) -> None:
|
def setFilter(self, filter_dict: Dict[str, str]) -> None:
|
||||||
if filter_dict != self._filter:
|
if filter_dict != self._filter:
|
||||||
self._filter = filter_dict
|
self._filter = filter_dict
|
||||||
self.filterChanged.emit()
|
self._update()
|
||||||
|
|
||||||
@pyqtProperty("QVariantMap", fset = setFilter, notify = filterChanged)
|
@pyqtProperty("QVariantMap", fset = setFilter, constant = True)
|
||||||
def filter(self) -> Dict[str, str]:
|
def filter(self) -> Dict[str, str]:
|
||||||
return self._filter
|
return self._filter
|
||||||
|
|
||||||
|
# Check to see if a container matches with a regular expression
|
||||||
|
def _matchRegExp(self, metadata, property_name, value):
|
||||||
|
if property_name not in metadata:
|
||||||
|
return False
|
||||||
|
value = re.escape(value) #Escape for regex patterns.
|
||||||
|
value = "^" + value.replace("\\*", ".*") + "$" #Instead of (now escaped) asterisks, match on any string. Also add anchors for a complete match.
|
||||||
|
if self._ignore_case:
|
||||||
|
value_pattern = re.compile(value, re.IGNORECASE)
|
||||||
|
else:
|
||||||
|
value_pattern = re.compile(value)
|
||||||
|
|
||||||
|
return value_pattern.match(str(metadata[property_name]))
|
||||||
|
|
||||||
|
# Check to see if a container matches with a string
|
||||||
|
def _matchString(self, metadata, property_name, value):
|
||||||
|
if property_name not in metadata:
|
||||||
|
return False
|
||||||
|
return value.lower() == str(metadata[property_name]).lower()
|
||||||
|
|
|
@ -43,12 +43,12 @@ class Toolbox(QObject, Extension):
|
||||||
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
||||||
self._packages_version_number = self._plugin_registry.APIVersion
|
self._packages_version_number = self._plugin_registry.APIVersion
|
||||||
|
|
||||||
self._packages_metadata = []
|
self._packages_metadata = [] # Stores the remote information of the packages
|
||||||
self._packages_model = None
|
self._packages_model = None # Model that list the remote available packages
|
||||||
|
|
||||||
# Can be 'installed' or 'available'
|
# Nowadays can be 'plugins', 'materials' or 'installed'
|
||||||
self._view = "available"
|
self._current_view = "plugins"
|
||||||
self._detail_view = ""
|
self._detail_view = False
|
||||||
|
|
||||||
self._restart_required = False
|
self._restart_required = False
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ class Toolbox(QObject, Extension):
|
||||||
restartRequiredChanged = pyqtSignal()
|
restartRequiredChanged = pyqtSignal()
|
||||||
viewChanged = pyqtSignal()
|
viewChanged = pyqtSignal()
|
||||||
detailViewChanged = pyqtSignal()
|
detailViewChanged = pyqtSignal()
|
||||||
|
filterChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtSlot(result = str)
|
@pyqtSlot(result = str)
|
||||||
def getLicenseDialogPluginName(self):
|
def getLicenseDialogPluginName(self):
|
||||||
|
@ -282,28 +283,31 @@ class Toolbox(QObject, Extension):
|
||||||
self.setIsDownloading(False)
|
self.setIsDownloading(False)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setView(self, view = "available"):
|
def filterPackagesByType(self, type):
|
||||||
self._view = view
|
if not self._packages_model:
|
||||||
|
return
|
||||||
|
self._packages_model.setFilter({"type": type})
|
||||||
|
self.filterChanged.emit()
|
||||||
|
|
||||||
|
def setCurrentView(self, view = "plugins"):
|
||||||
|
self._current_view = view
|
||||||
self.viewChanged.emit()
|
self.viewChanged.emit()
|
||||||
self.packagesMetadataChanged.emit()
|
|
||||||
|
|
||||||
@pyqtProperty(str, notify = viewChanged)
|
@pyqtProperty(str, fset = setCurrentView, notify = viewChanged)
|
||||||
def viewing(self):
|
def currentView(self):
|
||||||
return self._view
|
return self._current_view
|
||||||
|
|
||||||
@pyqtSlot(str)
|
def setDetailView(self, item = False):
|
||||||
def setDetailView(self, item = ""):
|
|
||||||
self._detail_view = item
|
self._detail_view = item
|
||||||
self.detailViewChanged.emit()
|
self.detailViewChanged.emit()
|
||||||
self.packagesMetadataChanged.emit()
|
|
||||||
|
|
||||||
@pyqtProperty(str, notify = detailViewChanged)
|
@pyqtProperty(bool, fset = setDetailView, notify = detailViewChanged)
|
||||||
def detailView(self):
|
def detailView(self):
|
||||||
return self._detail_view
|
return self._detail_view
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = packagesMetadataChanged)
|
@pyqtProperty(QObject, notify = packagesMetadataChanged)
|
||||||
def pluginsModel(self):
|
def pluginsModel(self):
|
||||||
self._plugins_model = PluginsModel(None, self._view)
|
self._plugins_model = PluginsModel(None, self._current_view)
|
||||||
# self._plugins_model.update()
|
# self._plugins_model.update()
|
||||||
|
|
||||||
# Check each plugin the registry for matching plugin from server
|
# Check each plugin the registry for matching plugin from server
|
||||||
|
@ -383,10 +387,10 @@ class Toolbox(QObject, Extension):
|
||||||
json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
||||||
|
|
||||||
# Add metadata to the manager:
|
# Add metadata to the manager:
|
||||||
self._packages_metadata = json_data
|
self._packages_metadata = json_data["data"]
|
||||||
if not self._packages_model:
|
if not self._packages_model:
|
||||||
self._packages_model = CuraPackageModel()
|
self._packages_model = CuraPackageModel()
|
||||||
self._packages_model.setPackagesMetaData(self._packages_metadata["data"])
|
self._packages_model.setPackagesMetaData(self._packages_metadata)
|
||||||
# self._plugin_registry.addExternalPlugins(self._packages_metadata)
|
# self._plugin_registry.addExternalPlugins(self._packages_metadata)
|
||||||
self.packagesMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
|
|
|
@ -14,7 +14,8 @@ import UM 1.1 as UM
|
||||||
Window
|
Window
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
title: catalog.i18nc("@title:tab", "Plugins");
|
title: catalog.i18nc("@title:tab", "Toolbox");
|
||||||
|
modality: Qt.ApplicationModal
|
||||||
width: 800 * screenScaleFactor
|
width: 800 * screenScaleFactor
|
||||||
height: 640 * screenScaleFactor
|
height: 640 * screenScaleFactor
|
||||||
minimumWidth: 800 * screenScaleFactor
|
minimumWidth: 800 * screenScaleFactor
|
||||||
|
@ -42,18 +43,17 @@ Window
|
||||||
ToolboxViewDownloads
|
ToolboxViewDownloads
|
||||||
{
|
{
|
||||||
id: viewDownloads
|
id: viewDownloads
|
||||||
visible: manager.viewing == "available" && manager.detailView == "" ? true : false
|
visible: manager.currentView != "installed" && !manager.detailView
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolboxViewDetail
|
ToolboxViewDetail
|
||||||
{
|
{
|
||||||
id: viewDetail
|
id: viewDetail
|
||||||
visible: manager.viewing == "available" && manager.detailView != "" ? true : false
|
visible: manager.currentView != "installed" && manager.detailView
|
||||||
}
|
}
|
||||||
ToolboxViewInstalled
|
ToolboxViewInstalled
|
||||||
{
|
{
|
||||||
id: installedPluginList
|
id: installedPluginList
|
||||||
visible: manager.viewing == "installed" ? true : false
|
visible: manager.currentView == "installed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SectionShadow
|
SectionShadow
|
||||||
|
|
|
@ -39,13 +39,10 @@ Rectangle
|
||||||
columnSpacing: UM.Theme.getSize("base_unit").width
|
columnSpacing: UM.Theme.getSize("base_unit").width
|
||||||
rowSpacing: UM.Theme.getSize("base_unit").height
|
rowSpacing: UM.Theme.getSize("base_unit").height
|
||||||
|
|
||||||
ToolboxGridTile {}
|
Repeater
|
||||||
ToolboxGridTile {}
|
{
|
||||||
ToolboxGridTile {}
|
model: manager.packagesModel
|
||||||
ToolboxGridTile {}
|
delegate: ToolboxGridTile {}
|
||||||
ToolboxGridTile {}
|
}
|
||||||
ToolboxGridTile {}
|
|
||||||
ToolboxGridTile {}
|
|
||||||
ToolboxGridTile {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ Item
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: name
|
id: name
|
||||||
text: "Auto Orientation"
|
text: model.name
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
height: UM.Theme.getSize("base_unit").height * 2
|
height: UM.Theme.getSize("base_unit").height * 2
|
||||||
|
@ -44,7 +44,7 @@ Item
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: info
|
id: info
|
||||||
text: "Automatically orientate your model."
|
text: model.description
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
@ -55,8 +55,6 @@ Item
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: manager.detailView = true
|
||||||
manager.setDetailView("thingy")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Rectangle {
|
||||||
implicitWidth: 96
|
implicitWidth: 96
|
||||||
implicitHeight: 48
|
implicitHeight: 48
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: manager.viewing == "available" ? true : false
|
visible: manager.currentView == "plugins"
|
||||||
color: UM.Theme.getColor("primary")
|
color: UM.Theme.getColor("primary")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -49,7 +49,11 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked: manager.setView("available")
|
onClicked:
|
||||||
|
{
|
||||||
|
manager.filterPackagesByType("plugin")
|
||||||
|
manager.currentView = "plugins"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
@ -60,7 +64,7 @@ Rectangle {
|
||||||
implicitWidth: 96
|
implicitWidth: 96
|
||||||
implicitHeight: 48
|
implicitHeight: 48
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: manager.viewing == "available" ? true : false
|
visible: manager.currentView == "materials"
|
||||||
color: UM.Theme.getColor("primary")
|
color: UM.Theme.getColor("primary")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -77,7 +81,11 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked: manager.setView("available")
|
onClicked:
|
||||||
|
{
|
||||||
|
manager.filterPackagesByType("material")
|
||||||
|
manager.currentView = "materials"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +99,7 @@ Rectangle {
|
||||||
implicitWidth: 96
|
implicitWidth: 96
|
||||||
implicitHeight: 48
|
implicitHeight: 48
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: manager.viewing == "installed" ? true : false
|
visible: manager.currentView == "installed"
|
||||||
color: UM.Theme.getColor("primary")
|
color: UM.Theme.getColor("primary")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -108,6 +116,6 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked: manager.setView("installed")
|
onClicked: manager.currentView = "installed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,7 @@ Item
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
text: "Back"
|
text: "Back"
|
||||||
onClicked: {
|
onClicked: manager.detailView = false
|
||||||
manager.setDetailView("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScrollView
|
ScrollView
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue