From 91001455ade8e42d740a11569ad94369b72441c8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 6 Apr 2018 17:26:25 +0200 Subject: [PATCH] Improved structure and enabled display by author --- plugins/Toolbox/resources/qml/Toolbox.qml | 41 +++--- .../resources/qml/ToolboxAuthorPage.qml | 138 ++++++++++++++++++ .../resources/qml/ToolboxDetailList.qml | 36 +++++ ...xDetailsPage.qml => ToolboxDetailPage.qml} | 47 +----- ...xDetailsTile.qml => ToolboxDetailTile.qml} | 12 +- .../qml/ToolboxDownloadsGridTile.qml | 19 ++- .../Toolbox/resources/qml/ToolboxHeader.qml | 16 +- ...lboxLoading.qml => ToolboxLoadingPage.qml} | 0 plugins/Toolbox/src/Toolbox.py | 92 ++++++++++-- 9 files changed, 310 insertions(+), 91 deletions(-) create mode 100644 plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml create mode 100644 plugins/Toolbox/resources/qml/ToolboxDetailList.qml rename plugins/Toolbox/resources/qml/{ToolboxDetailsPage.qml => ToolboxDetailPage.qml} (75%) rename plugins/Toolbox/resources/qml/{ToolboxDetailsTile.qml => ToolboxDetailTile.qml} (90%) rename plugins/Toolbox/resources/qml/{ToolboxLoading.qml => ToolboxLoadingPage.qml} (100%) diff --git a/plugins/Toolbox/resources/qml/Toolbox.qml b/plugins/Toolbox/resources/qml/Toolbox.qml index 3803dff2ab..cfe768e1d1 100644 --- a/plugins/Toolbox/resources/qml/Toolbox.qml +++ b/plugins/Toolbox/resources/qml/Toolbox.qml @@ -25,11 +25,10 @@ Window color: UM.Theme.getColor("sidebar") Item { - id: view anchors.fill: parent ToolboxHeader { - id: topBar + id: header } Rectangle { @@ -38,47 +37,49 @@ Window color: "transparent" anchors { - top: topBar.bottom - bottom: bottomBar.top + top: header.bottom + bottom: footer.top } - ToolboxLoading + // TODO: This could be improved using viewFilter instead of viewCategory + ToolboxLoadingPage { - id: loading - visible: !dataReady && manager.currentView != "installed" + id: viewLoading + visible: manager.viewCategory != "installed" && !dataReady + // TODO: Replace !dataReady with manager.viewPage == "loading" } ToolboxDownloadsPage { id: viewDownloads - visible: manager.currentView != "installed" && !manager.detailView + visible: manager.viewCategory != "installed" && manager.viewPage == "overview" } - ToolboxDetailsPage + ToolboxDetailPage { id: viewDetail - visible: manager.currentView != "installed" && manager.detailView + visible: manager.viewCategory != "installed" && manager.viewPage == "detail" + } + ToolboxAuthorPage + { + id: viewAuthor + visible: manager.viewCategory != "installed" && manager.viewPage == "author" } ToolboxInstalledPage { id: installedPluginList - visible: dataReady && manager.currentView == "installed" + visible: manager.viewCategory == "installed" && dataReady + // TODO: Replace !dataReady with manager.viewPage == "loading" } } ToolboxShadow { - anchors - { - top: topBar.bottom - } + anchors.top: header.bottom } ToolboxFooter { - id: bottomBar + id: footer } ToolboxShadow { - anchors - { - top: bottomBar.top - } + anchors.top: footer.top } UM.I18nCatalog { id: catalog; name: "cura" } diff --git a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml new file mode 100644 index 0000000000..200cac33fa --- /dev/null +++ b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml @@ -0,0 +1,138 @@ +// Copyright (c) 2018 Ultimaker B.V. +// PluginBrowser is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Dialogs 1.1 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import UM 1.1 as UM + +// TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles + +Item +{ + id: base + anchors.fill: parent + Item + { + id: sidebar + height: parent.height + width: UM.Theme.getSize("base_unit").width * 6 + anchors + { + top: parent.top + left: parent.left + topMargin: UM.Theme.getSize("double_margin").height + leftMargin: UM.Theme.getSize("default_margin").width + rightMargin: UM.Theme.getSize("default_margin").width + } + Button + { + text: "Back" + UM.RecolorImage + { + id: backArrow + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: UM.Theme.getColor("text") + source: UM.Theme.getIcon("arrow_left") + } + width: UM.Theme.getSize("base_unit").width * 4 + height: UM.Theme.getSize("base_unit").height * 2 + onClicked: + { + manager.viewPage = "overview" + manager.filterPackages("type", manager.viewCategory) + } + style: ButtonStyle + { + background: Rectangle + { + color: "transparent" + } + label: Label + { + text: control.text + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("default_bold") + horizontalAlignment: Text.AlignRight + width: control.width + } + } + } + } + + Rectangle + { + id: header + anchors + { + left: sidebar.right + right: parent.right + } + height: UM.Theme.getSize("base_unit").height * 12 + Image + { + id: thumbnail + width: UM.Theme.getSize("toolbox_thumbnail_medium").width + height: UM.Theme.getSize("toolbox_thumbnail_medium").height + fillMode: Image.PreserveAspectFit + source: manager.detailData["icon_url"] || "../images/logobot.svg" + anchors + { + top: parent.top + left: parent.left + leftMargin: UM.Theme.getSize("double_margin").width + topMargin: UM.Theme.getSize("double_margin").height + } + } + Column + { + anchors + { + top: thumbnail.top + left: thumbnail.right + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("double_margin").width + } + spacing: Math.floor(UM.Theme.getSize("default_margin").height/2) + Label + { + text: manager.detailData["name"] + font: UM.Theme.getFont("large") + wrapMode: Text.WordWrap + width: parent.width + } + Label + { + text: "HELLO THIS IS AN AUTHOR PAGE" + font: UM.Theme.getFont("default") + wrapMode: Text.WordWrap + width: parent.width + } + Label + { + text: "Author: " + manager.detailData["author"]["name"] + font: UM.Theme.getFont("small") + wrapMode: Text.WordWrap + width: parent.width + // TODO: Add mail icon. + } + } + } + ToolboxDetailList { + anchors + { + right: header.right + top: header.bottom + left: header.left + bottom: base.bottom + } + } +} diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml b/plugins/Toolbox/resources/qml/ToolboxDetailList.qml new file mode 100644 index 0000000000..fe65eed7c4 --- /dev/null +++ b/plugins/Toolbox/resources/qml/ToolboxDetailList.qml @@ -0,0 +1,36 @@ +// Copyright (c) 2018 Ultimaker B.V. +// PluginBrowser is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Dialogs 1.1 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import UM 1.1 as UM + +Item +{ + id: base + anchors + { + topMargin: UM.Theme.getSize("default_margin").height + bottomMargin: UM.Theme.getSize("default_margin").height + leftMargin: UM.Theme.getSize("double_margin").width + rightMargin: UM.Theme.getSize("double_margin").width + } + ScrollView + { + frameVisible: false + anchors.fill: base + style: UM.Theme.styles.scrollview + Column + { + height: childrenRect.height + spacing: UM.Theme.getSize("default_margin").height + Repeater + { + model: manager.packagesModel + delegate: ToolboxDetailTile {} + } + } + } +} diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailsPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml similarity index 75% rename from plugins/Toolbox/resources/qml/ToolboxDetailsPage.qml rename to plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 2f152e5859..6054414405 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailsPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -44,7 +44,11 @@ Item } width: UM.Theme.getSize("base_unit").width * 4 height: UM.Theme.getSize("base_unit").height * 2 - onClicked: manager.detailView = false + onClicked: + { + manager.viewPage = "overview" + manager.filterPackages("type", manager.viewCategory) + } style: ButtonStyle { background: Rectangle @@ -100,7 +104,7 @@ Item spacing: Math.floor(UM.Theme.getSize("default_margin").height/2) Label { - text: manager.detailData["type"] == "material" ? manager.detailData["author"] : manager.detailData["name"] + text: manager.detailData["name"] font: UM.Theme.getFont("large") wrapMode: Text.WordWrap width: parent.width @@ -122,11 +126,7 @@ Item } } } - - ScrollView - { - id: scroll - frameVisible: true + ToolboxDetailList { anchors { right: header.right @@ -134,38 +134,5 @@ Item left: header.left bottom: base.bottom } - height: parent.height - style: UM.Theme.styles.scrollview - - /* - ListView - { - id: contentColumn - spacing: UM.Theme.getSize("base_unit").height - height: childrenRect.height + (UM.Theme.getSize("double_margin").height * 2) - anchors - { - left: scroll.left - right: scroll.right - top: scroll.top - topMargin: UM.Theme.getSize("double_margin").height - bottomMargin: UM.Theme.getSize("double_margin").height - leftMargin: UM.Theme.getSize("double_margin").width - rightMargin: UM.Theme.getSize("double_margin").width - } - - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - ToolboxDetailsTile {} - } - */ } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailsTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml similarity index 90% rename from plugins/Toolbox/resources/qml/ToolboxDetailsTile.qml rename to plugins/Toolbox/resources/qml/ToolboxDetailTile.qml index abe2cdf450..5671e95495 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailsTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml @@ -9,9 +9,9 @@ import UM 1.1 as UM Rectangle { - width: parent.width - height: childrenRect.height - color: "transparent" + width: base.width + height: UM.Theme.getSize("base_unit").height * 12 + color: "steelblue" Column { anchors @@ -27,7 +27,7 @@ Rectangle { width: parent.width height: UM.Theme.getSize("base_unit").height * 2 - text: "DSM Abrasive" + text: model.name wrapMode: Text.WordWrap color: UM.Theme.getColor("text") font: UM.Theme.getFont("default_bold") @@ -35,10 +35,10 @@ Rectangle Label { width: parent.width - text: "DSM abrasive material provides extra stiffness. It’s suitable for printing \"Functional prototypes\" and \"End parts\"." + text: model.description wrapMode: Text.WordWrap color: UM.Theme.getColor("text") - font: UM.Theme.getFont("normal") + font: UM.Theme.getFont("default") } } Rectangle diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml index 9cdcb4e400..e8b4f2453f 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml @@ -50,8 +50,7 @@ Item Label { id: info - text: - { + text: { if (model.description.length > 50) { return model.description.substring(0, 50) + "..." @@ -69,9 +68,19 @@ Item { anchors.fill: parent onClicked: { - console.log(model.id) - manager.detailView = true - manager.setDetailData(model.id) + if ( manager.viewCategory == "material" ) + { + console.log("filtering by " + model.author) + manager.viewSelection = model.author.name + manager.viewPage = "author" + manager.filterPackages("author", model.author) + } + else + { + manager.viewSelection = model.id + manager.viewPage = "detail" + manager.filterPackages("id", model.id) + } } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxHeader.qml b/plugins/Toolbox/resources/qml/ToolboxHeader.qml index 2c097f275b..cedf95fda7 100644 --- a/plugins/Toolbox/resources/qml/ToolboxHeader.qml +++ b/plugins/Toolbox/resources/qml/ToolboxHeader.qml @@ -37,7 +37,7 @@ Rectangle { implicitHeight: 48 Rectangle { - visible: manager.currentView == "plugins" + visible: manager.viewCategory == "plugin" color: UM.Theme.getColor("primary") anchors.bottom: parent.bottom width: parent.width @@ -56,8 +56,8 @@ Rectangle { onClicked: { manager.filterPackagesByType("plugin") - manager.currentView = "plugins" - manager.detailView = false + manager.viewCategory = "plugin" + manager.viewPage = "overview" } } @@ -73,7 +73,7 @@ Rectangle { implicitHeight: 48 Rectangle { - visible: manager.currentView == "materials" + visible: manager.viewCategory == "material" color: UM.Theme.getColor("primary") anchors.bottom: parent.bottom width: parent.width @@ -92,8 +92,8 @@ Rectangle { onClicked: { manager.filterPackagesByType("material") - manager.currentView = "materials" - manager.detailView = false + manager.viewCategory = "material" + manager.viewPage = "overview" } } } @@ -111,7 +111,7 @@ Rectangle { implicitWidth: 96 implicitHeight: 48 Rectangle { - visible: manager.currentView == "installed" + visible: manager.viewCategory == "installed" color: UM.Theme.getColor("primary") anchors.bottom: parent.bottom width: parent.width @@ -127,6 +127,6 @@ Rectangle { horizontalAlignment: Text.AlignHCenter } } - onClicked: manager.currentView = "installed" + onClicked: manager.viewCategory = "installed" } } diff --git a/plugins/Toolbox/resources/qml/ToolboxLoading.qml b/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml similarity index 100% rename from plugins/Toolbox/resources/qml/ToolboxLoading.qml rename to plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index bca58ac4a4..60e43b357e 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -46,10 +46,36 @@ class Toolbox(QObject, Extension): self._packages_metadata = [] # Stores the remote information of the packages self._packages_model = None # Model that list the remote available packages + + # These properties are for keeping track of the UI state: + # ---------------------------------------------------------------------- + + # View category defines which filter to use, and therefore effectively + # which category is currently being displayed. For example, possible + # values include "plugin" or "material", but also "installed". + # Formerly self._current_view. + self._view_category = "plugin" + + # View page defines which type of page layout to use. For example, + # possible values include "overview", "detail" or "author". + # Formerly self._detail_view. + self._view_page = "overview" + + # View selection defines what is currently selected and should be + # used in filtering. This could be an author name (if _view_page is set + # to "author" or a plugin name if it is set to "detail"). + self._view_selection = "" + + # For any view page above, self._packages_model can be filtered. + # For example: + # self._view_category = "material" + # if self._view_page == "author": + # filter with "author == self._view_selection" + # Nowadays can be 'plugins', 'materials' or 'installed' self._current_view = "plugins" self._detail_view = False - self._detail_data = {} + self._detail_data = {} # Extraneous since can just use the data prop of the model. self._restart_required = False @@ -283,13 +309,6 @@ class Toolbox(QObject, Extension): self.setDownloadProgress(0) self.setIsDownloading(False) - @pyqtSlot(str) - def filterPackagesByType(self, type): - 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() @@ -336,10 +355,11 @@ class Toolbox(QObject, Extension): for item in self._packages_metadata: if item["id"] == plugin["id"]: plugin["update_url"] = item["file_location"] - if self._current_view == "plugins": - self.filterPackagesByType("plugin") - elif self._current_view == "materials": - self.filterPackagesByType("material") + + # if self._current_view == "plugins": + # self.filterPackagesByType("plugin") + # elif self._current_view == "materials": + # self.filterPackagesByType("material") return self._plugins_model @pyqtProperty(QObject, notify = packagesMetadataChanged) @@ -447,3 +467,51 @@ class Toolbox(QObject, Extension): @pyqtSlot() def restart(self): CuraApplication.getInstance().windowClosed() + + + # Getter & Setter for self._view_category + def setViewCategory(self, category = "plugins"): + self._view_category = category + self.viewChanged.emit() + @pyqtProperty(str, fset = setViewCategory, notify = viewChanged) + def viewCategory(self): + return self._view_category + + # Getter & Setter for self._view_page + def setViewPage(self, page = "overview"): + self._view_page = page + self.viewChanged.emit() + @pyqtProperty(str, fset = setViewPage, notify = viewChanged) + def viewPage(self): + return self._view_page + + # Getter & Setter for self._view_selection + def setViewSelection(self, selection = ""): + self._view_selection = selection + self.viewChanged.emit() + @pyqtProperty(str, fset = setViewSelection, notify = viewChanged) + def viewSelection(self): + return self._view_selection + + + # Filtering + @pyqtSlot(str) + def filterPackagesByType(self, type): + if not self._packages_model: + return + self._packages_model.setFilter({"type": type}) + self.filterChanged.emit() + + @pyqtSlot(str, str) + def filterPackages(self, filterType, parameter): + if not self._packages_model: + return + self._packages_model.setFilter({filterType: parameter}) + self.filterChanged.emit() + + @pyqtSlot() + def unfilterPackages(self): + if not self._packages_model: + return + self._packages_model.setFilter({}) + self.filterChanged.emit()