CURA-5035 Added fake material showcase model

This commit is contained in:
Ian Paschal 2018-04-12 12:49:31 +02:00
parent 594e9aa414
commit 87c194178d
20 changed files with 95 additions and 110 deletions

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
@ -14,7 +14,6 @@ import UM 1.1 as UM
Window Window
{ {
id: base id: base
property bool dataReady: manager.dataReady
title: catalog.i18nc("@title:tab", "Toolbox"); title: catalog.i18nc("@title:tab", "Toolbox");
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
width: 720 * screenScaleFactor width: 720 * screenScaleFactor

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
@ -43,6 +43,7 @@ Item
{ {
manager.viewPage = "overview" manager.viewPage = "overview"
manager.filterPackages("type", manager.viewCategory) manager.filterPackages("type", manager.viewCategory)
manager.filterAuthors("type", manager.viewCategory)
} }
style: ButtonStyle style: ButtonStyle
{ {

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
@ -34,7 +34,16 @@ Column
Repeater Repeater
{ {
model: manager.pluginsShowcaseModel model: {
if ( manager.viewCategory == "plugin" )
{
return manager.pluginsShowcaseModel
}
if ( manager.viewCategory == "material" )
{
return manager.materialsShowcaseModel
}
}
delegate: ToolboxDownloadsShowcaseTile {} delegate: ToolboxDownloadsShowcaseTile {}
} }
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
@ -51,19 +51,20 @@ Item
{ {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
if ( manager.viewCategory == "material" ) switch(manager.viewCategory)
{ {
case "material":
manager.viewSelection = model.name manager.viewSelection = model.name
manager.viewPage = "author" manager.viewPage = "author"
manager.filterAuthors("name", model.name) manager.filterAuthors("name", model.name)
manager.filterPackages("author_name", model.name) manager.filterPackages("author_name", model.name)
} break
else default:
{
manager.viewSelection = model.id manager.viewSelection = model.id
manager.viewPage = "detail" manager.viewPage = "detail"
manager.filterAuthors("name", model.author_name) manager.filterAuthors("name", model.author_name)
manager.filterPackages("id", model.id) manager.filterPackages("id", model.id)
break
} }
} }
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
@ -157,20 +157,18 @@ Item
ProgressBar ProgressBar
{ {
id: progressbar id: progressbar
minimumValue: 0;
maximumValue: 100
anchors.left: installButton.left anchors.left: installButton.left
anchors.right: installButton.right anchors.right: installButton.right
anchors.top: installButton.bottom anchors.top: installButton.bottom
anchors.topMargin: 4 anchors.topMargin: 4
value: manager.isDownloading ? manager.downloadProgress : 0 value: manager.isDownloading ? manager.downloadProgress : 0
visible: manager.isDownloading && pluginList.activePlugin == model visible: manager.isDownloading
style: ProgressBarStyle style: ProgressBarStyle
{ {
background: Rectangle background: Rectangle
{ {
color: "lightgray" color: UM.Theme.getColor("lining")
implicitHeight: 6 implicitHeight: Math.floor(UM.Theme.getSize("base_unit").height / 2)
} }
progress: Rectangle progress: Rectangle
{ {

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,13 +1,9 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Dialogs 1.1
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 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
Rectangle Rectangle
{ {

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// PluginBrowser is released under the terms of the LGPLv3 or higher. // Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2

View file

@ -48,7 +48,17 @@ class Toolbox(QObject, Extension):
self._is_downloading = False self._is_downloading = False
self._network_manager = None self._network_manager = None
self._request_header = [
b"User-Agent",
str.encode(
"%s/%s (%s %s)" % (
Application.getInstance().getApplicationName(),
Application.getInstance().getVersion(),
platform.system(),
platform.machine(),
)
)
]
self._packages_metadata = [] self._packages_metadata = []
self._packages_model = None self._packages_model = None
@ -58,19 +68,15 @@ class Toolbox(QObject, Extension):
self._materials_installed_model = None self._materials_installed_model = None
self._authors_model = None self._authors_model = None
# These properties are for keeping track of the UI state: # These properties are for keeping track of the UI state:
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# View category defines which filter to use, and therefore effectively # View category defines which filter to use, and therefore effectively
# which category is currently being displayed. For example, possible # which category is currently being displayed. For example, possible
# values include "plugin" or "material", but also "installed". # values include "plugin" or "material", but also "installed".
# Formerly self._current_view.
self._view_category = "plugin" self._view_category = "plugin"
# View page defines which type of page layout to use. For example, # View page defines which type of page layout to use. For example,
# possible values include "overview", "detail" or "author". # possible values include "overview", "detail" or "author".
# Formerly self._detail_view.
self._view_page = "loading" self._view_page = "loading"
# View selection defines what is currently selected and should be # View selection defines what is currently selected and should be
@ -82,55 +88,40 @@ class Toolbox(QObject, Extension):
# installed, or otherwise modified. # installed, or otherwise modified.
self._active_package = None self._active_package = None
# Nowadays can be 'plugins', 'materials' or 'installed'
self._current_view = "plugins"
self._detail_data = {} # Extraneous since can just use the data prop of the model.
self._restart_required = False
self._dialog = None self._dialog = None
self._restartDialog = None self._restartDialog = None
self._restart_required = False
self._request_header = [b"User-Agent",
str.encode("%s/%s (%s %s)" % (Application.getInstance().getApplicationName(),
Application.getInstance().getVersion(),
platform.system(),
platform.machine(),
)
)
]
# Installed plugins are really installed after reboot. In order to # Installed plugins are really installed after reboot. In order to
# prevent the user from downloading the same file over and over again, # prevent the user from downloading the same file over and over again,
# we keep track of the upgraded plugins. # we keep track of the upgraded plugins.
self._newly_installed_plugin_ids = [] self._newly_installed_plugin_ids = []
self._newly_uninstalled_plugin_ids = [] self._newly_uninstalled_plugin_ids = []
self._plugin_statuses = {} # type: Dict[str, str]
# variables for the license agreement dialog # variables for the license agreement dialog
self._license_dialog_plugin_name = "" self._license_dialog_plugin_name = ""
self._license_dialog_license_content = "" self._license_dialog_license_content = ""
self._license_dialog_plugin_file_location = "" self._license_dialog_plugin_file_location = ""
self._restart_dialog_message = "" self._restart_dialog_message = ""
showLicenseDialog = pyqtSignal() # Metadata changes
showRestartDialog = pyqtSignal()
packagesMetadataChanged = pyqtSignal() packagesMetadataChanged = pyqtSignal()
authorsMetadataChanged = pyqtSignal() authorsMetadataChanged = pyqtSignal()
showcaseMetadataChanged = pyqtSignal() pluginsShowcaseMetadataChanged = pyqtSignal()
materialsShowcaseMetadataChanged = pyqtSignal()
# Downloading changes
activePackageChanged = pyqtSignal() activePackageChanged = pyqtSignal()
onDownloadProgressChanged = pyqtSignal() onDownloadProgressChanged = pyqtSignal()
onIsDownloadingChanged = pyqtSignal() onIsDownloadingChanged = pyqtSignal()
restartRequiredChanged = pyqtSignal() restartRequiredChanged = pyqtSignal()
# UI changes
viewChanged = pyqtSignal() viewChanged = pyqtSignal()
detailViewChanged = pyqtSignal() detailViewChanged = pyqtSignal()
filterChanged = pyqtSignal() filterChanged = pyqtSignal()
showLicenseDialog = pyqtSignal()
showRestartDialog = pyqtSignal()
@pyqtSlot(result = str) @pyqtSlot(result = str)
def getLicenseDialogPluginName(self): def getLicenseDialogPluginName(self):
@ -223,7 +214,7 @@ class Toolbox(QObject, Extension):
@pyqtProperty(QObject, notify = packagesMetadataChanged) @pyqtProperty(QObject, notify = packagesMetadataChanged)
def pluginsModel(self): def pluginsModel(self):
self._plugins_model = PluginsModel(None, self._current_view) self._plugins_model = PluginsModel(None, self._view_category)
# 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
@ -238,10 +229,14 @@ class Toolbox(QObject, Extension):
plugin["update_url"] = item["file_location"] plugin["update_url"] = item["file_location"]
return self._plugins_model return self._plugins_model
@pyqtProperty(QObject, notify = showcaseMetadataChanged) @pyqtProperty(QObject, notify = pluginsShowcaseMetadataChanged)
def pluginsShowcaseModel(self): def pluginsShowcaseModel(self):
return self._plugins_showcase_model return self._plugins_showcase_model
@pyqtProperty(QObject, notify = materialsShowcaseMetadataChanged)
def materialsShowcaseModel(self):
return self._materials_showcase_model
@pyqtProperty(QObject, notify = packagesMetadataChanged) @pyqtProperty(QObject, notify = packagesMetadataChanged)
def packagesModel(self): def packagesModel(self):
return self._packages_model return self._packages_model
@ -344,6 +339,7 @@ class Toolbox(QObject, Extension):
self._download_reply.abort() self._download_reply.abort()
self._download_reply = None self._download_reply = None
# TODO: This function is sooooo ugly. Needs a rework:
def _onRequestFinished(self, reply): def _onRequestFinished(self, reply):
reply_url = reply.url().toString() reply_url = reply.url().toString()
if reply.error() == QNetworkReply.TimeoutError: if reply.error() == QNetworkReply.TimeoutError:
@ -384,6 +380,28 @@ class Toolbox(QObject, Extension):
self._authors_model.setMetaData(self._authors_metadata) self._authors_model.setMetaData(self._authors_metadata)
self.authorsMetadataChanged.emit() self.authorsMetadataChanged.emit()
self.setViewPage("overview") self.setViewPage("overview")
# TODO: Also replace this with a proper API call:
if not self._materials_showcase_model:
self._materials_showcase_model = AuthorsModel()
# TODO: Remove this hacky code once there's an API call for this.
self._materials_showcase_model.setMetaData([
{
"name": "DSM",
"email": "contact@dsm.nl",
"website": "www.dsm.nl",
"type": "material"
},
{
"name": "BASF",
"email": "contact@basf.de",
"website": "www.basf.de",
"type": "material"
}
])
self.materialsShowcaseMetadataChanged.emit()
self.setViewPage("overview")
except json.decoder.JSONDecodeError: except json.decoder.JSONDecodeError:
Logger.log("w", "Toolbox: Received invalid JSON for package list.") Logger.log("w", "Toolbox: Received invalid JSON for package list.")
return return
@ -400,7 +418,7 @@ class Toolbox(QObject, Extension):
self._plugins_showcase_model.setPackagesMetaData(self._showcase_metadata) self._plugins_showcase_model.setPackagesMetaData(self._showcase_metadata)
for package in self._plugins_showcase_model.items: for package in self._plugins_showcase_model.items:
print(package) print(package)
self.showcaseMetadataChanged.emit() self.pluginsShowcaseMetadataChanged.emit()
except json.decoder.JSONDecodeError: except json.decoder.JSONDecodeError:
Logger.log("w", "Toolbox: Received invalid JSON for showcase.") Logger.log("w", "Toolbox: Received invalid JSON for showcase.")
return return
@ -433,43 +451,6 @@ class Toolbox(QObject, Extension):
else: else:
Logger.log("w", "Toolbox: Package was not a valid CuraPackage.") Logger.log("w", "Toolbox: Package was not a valid CuraPackage.")
# with zipfile.ZipFile(file_path, "r") as zip_ref:
# plugin_id = None
# for file in zip_ref.infolist():
# if file.filename.endswith("/"):
# plugin_id = file.filename.strip("/")
# break
#
# if plugin_id is None:
# msg = i18n_catalog.i18nc("@info:status", "Failed to get plugin ID from <filename>{0}</filename>", file_path)
# msg_title = i18n_catalog.i18nc("@info:tile", "Warning")
# self._progress_message = Message(msg, lifetime=0, dismissable=False, title = msg_title)
# return
#
# # find a potential license file
# plugin_root_dir = plugin_id + "/"
# license_file = None
# for f in zip_ref.infolist():
# # skip directories (with file_size = 0) and files not in the plugin directory
# if f.file_size == 0 or not f.filename.startswith(plugin_root_dir):
# continue
# file_name = os.path.basename(f.filename).lower()
# file_base_name, file_ext = os.path.splitext(file_name)
# if file_base_name in ["license", "licence"]:
# license_file = f.filename
# break
#
# # show a dialog for user to read and accept/decline the license
# if license_file is not None:
# Logger.log("i", "Found license file for plugin [%s], showing the license dialog to the user", plugin_id)
# license_content = zip_ref.read(license_file).decode('utf-8')
# self.openLicenseDialog(plugin_id, license_content, file_path)
# return
#
# # there is no license file, directly install the plugin
# self.installPlugin(file_path)
# return
# Getter & Setters # Getter & Setters