Organize Toolbox (marketplace) qml files according to type

CURA-6569
This commit is contained in:
Nino van Hooff 2019-11-04 17:35:24 +01:00
parent 7af5f132e0
commit ed7134ded8
31 changed files with 22 additions and 10 deletions

View file

@ -0,0 +1,106 @@
import QtQuick 2.7
import QtQuick.Controls 2.1
import UM 1.0 as UM
import Cura 1.1 as Cura
Item
{
id: ratingWidget
property real rating: 0
property int indexHovered: -1
property string packageId: ""
property int userRating: 0
property bool canRate: false
signal rated(int rating)
width: contentRow.width
height: contentRow.height
MouseArea
{
id: mouseArea
anchors.fill: parent
hoverEnabled: ratingWidget.canRate
acceptedButtons: Qt.NoButton
onExited:
{
if(ratingWidget.canRate)
{
ratingWidget.indexHovered = -1
}
}
Row
{
id: contentRow
height: childrenRect.height
Repeater
{
model: 5 // We need to get 5 stars
Button
{
id: control
hoverEnabled: true
onHoveredChanged:
{
if(hovered && ratingWidget.canRate)
{
indexHovered = index
}
}
ToolTip.visible: control.hovered && !ratingWidget.canRate
ToolTip.text: !Cura.API.account.isLoggedIn ? catalog.i18nc("@label", "You need to login first before you can rate"): catalog.i18nc("@label", "You need to install the package before you can rate")
property bool isStarFilled:
{
// If the entire widget is hovered, override the actual rating.
if(ratingWidget.indexHovered >= 0)
{
return indexHovered >= index
}
if(ratingWidget.userRating > 0)
{
return userRating >= index +1
}
return rating >= index + 1
}
contentItem: Item {}
height: UM.Theme.getSize("rating_star").height
width: UM.Theme.getSize("rating_star").width
background: UM.RecolorImage
{
source: UM.Theme.getIcon(control.isStarFilled ? "star_filled" : "star_empty")
sourceSize.width: width
sourceSize.height: height
// Unfilled stars should always have the default color. Only filled stars should change on hover
color:
{
if(!ratingWidget.canRate)
{
return UM.Theme.getColor("rating_star")
}
if((ratingWidget.indexHovered >= 0 || ratingWidget.userRating > 0) && isStarFilled)
{
return UM.Theme.getColor("primary")
}
return UM.Theme.getColor("rating_star")
}
}
onClicked:
{
if(ratingWidget.canRate)
{
rated(index + 1) // Notify anyone who cares about this.
}
}
}
}
}
}
}

View file

@ -0,0 +1,36 @@
import QtQuick 2.3
import QtQuick.Controls 1.4
import UM 1.1 as UM
import Cura 1.1 as Cura
Row
{
id: rating
height: UM.Theme.getSize("rating_star").height
visible: model.average_rating > 0 //Has a rating at all.
spacing: UM.Theme.getSize("thick_lining").width
width: starIcon.width + spacing + numRatingsLabel.width
UM.RecolorImage
{
id: starIcon
source: UM.Theme.getIcon("star_filled")
color: model.user_rating == 0 ? UM.Theme.getColor("rating_star") : UM.Theme.getColor("primary")
height: UM.Theme.getSize("rating_star").height
width: UM.Theme.getSize("rating_star").width
sourceSize.height: height
sourceSize.width: width
}
Label
{
id: numRatingsLabel
text: model.average_rating != undefined ? model.average_rating.toFixed(1) + " (" + model.num_ratings + " " + catalog.i18nc("@label", "ratings") + ")": ""
verticalAlignment: Text.AlignVCenter
height: starIcon.height
width: contentWidth
anchors.verticalCenter: starIcon.verticalCenter
color: starIcon.color
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}

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

@ -0,0 +1,76 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
Item
{
id: sidebar
height: parent.height
width: UM.Theme.getSize("toolbox_back_column").width
anchors
{
top: parent.top
left: parent.left
topMargin: UM.Theme.getSize("wide_margin").height
leftMargin: UM.Theme.getSize("default_margin").width
rightMargin: UM.Theme.getSize("default_margin").width
}
Button
{
id: button
text: catalog.i18nc("@action:button", "Back")
enabled: !toolbox.isDownloading
UM.RecolorImage
{
id: backArrow
anchors
{
verticalCenter: parent.verticalCenter
left: parent.left
rightMargin: UM.Theme.getSize("default_margin").width
}
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize
{
width: width
height: height
}
color: button.enabled ? (button.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive")
source: UM.Theme.getIcon("arrow_left")
}
width: UM.Theme.getSize("toolbox_back_button").width
height: UM.Theme.getSize("toolbox_back_button").height
onClicked:
{
toolbox.viewPage = "overview"
toolbox.filterModelByProp("packages", "type", toolbox.viewCategory)
}
style: ButtonStyle
{
background: Rectangle
{
color: "transparent"
}
label: Label
{
id: labelStyle
text: control.text
color: control.enabled ? (control.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive")
font: UM.Theme.getFont("medium_bold")
horizontalAlignment: Text.AlignLeft
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
}
width: control.width
renderType: Text.NativeRendering
}
}
}
}

View file

@ -0,0 +1,209 @@
// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import UM 1.1 as UM
Item
{
id: base
property var packageData
property var technicalDataSheetUrl: packageData.links.technicalDataSheet
property var safetyDataSheetUrl: packageData.links.safetyDataSheet
property var printingGuidelinesUrl: packageData.links.printingGuidelines
property var materialWebsiteUrl: packageData.links.website
height: childrenRect.height
onVisibleChanged: packageData.type === "material" && (compatibilityItem.visible || dataSheetLinks.visible)
Column
{
id: compatibilityItem
visible: packageData.has_configs
width: parent.width
// This is a bit of a hack, but the whole QML is pretty messy right now. This needs a big overhaul.
height: visible ? heading.height + table.height: 0
Label
{
id: heading
width: parent.width
text: catalog.i18nc("@label", "Compatibility")
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
TableView
{
id: table
width: parent.width
frameVisible: false
// Workaround for scroll issues (QTBUG-49652)
flickableItem.interactive: false
Component.onCompleted:
{
for (var i = 0; i < flickableItem.children.length; ++i)
{
flickableItem.children[i].enabled = false
}
}
selectionMode: 0
model: packageData.supported_configs
headerDelegate: Rectangle
{
color: UM.Theme.getColor("main_background")
height: UM.Theme.getSize("toolbox_chart_row").height
Label
{
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
text: styleData.value || ""
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default_bold")
renderType: Text.NativeRendering
}
Rectangle
{
anchors.bottom: parent.bottom
height: UM.Theme.getSize("default_lining").height
width: parent.width
color: "black"
}
}
rowDelegate: Item
{
height: UM.Theme.getSize("toolbox_chart_row").height
Label
{
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
text: styleData.value || ""
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
itemDelegate: Item
{
height: UM.Theme.getSize("toolbox_chart_row").height
Label
{
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
text: styleData.value || ""
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
Component
{
id: columnTextDelegate
Label
{
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
text: styleData.value || ""
elide: Text.ElideRight
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
TableViewColumn
{
role: "machine"
title: catalog.i18nc("@label:table_header", "Machine")
width: Math.floor(table.width * 0.25)
delegate: columnTextDelegate
}
TableViewColumn
{
role: "print_core"
title: "Print Core" //This term should not be translated.
width: Math.floor(table.width * 0.2)
}
TableViewColumn
{
role: "build_plate"
title: catalog.i18nc("@label:table_header", "Build Plate")
width: Math.floor(table.width * 0.225)
}
TableViewColumn
{
role: "support_material"
title: catalog.i18nc("@label:table_header", "Support")
width: Math.floor(table.width * 0.225)
}
TableViewColumn
{
role: "quality"
title: catalog.i18nc("@label:table_header", "Quality")
width: Math.floor(table.width * 0.1)
}
}
}
Label
{
id: dataSheetLinks
anchors.top: compatibilityItem.bottom
anchors.topMargin: UM.Theme.getSize("narrow_margin").height
visible: base.technicalDataSheetUrl !== undefined ||
base.safetyDataSheetUrl !== undefined ||
base.printingGuidelinesUrl !== undefined ||
base.materialWebsiteUrl !== undefined
text:
{
var result = ""
if (base.technicalDataSheetUrl !== undefined)
{
var tds_name = catalog.i18nc("@action:label", "Technical Data Sheet")
result += "<a href='%1'>%2</a>".arg(base.technicalDataSheetUrl).arg(tds_name)
}
if (base.safetyDataSheetUrl !== undefined)
{
if (result.length > 0)
{
result += "<br/>"
}
var sds_name = catalog.i18nc("@action:label", "Safety Data Sheet")
result += "<a href='%1'>%2</a>".arg(base.safetyDataSheetUrl).arg(sds_name)
}
if (base.printingGuidelinesUrl !== undefined)
{
if (result.length > 0)
{
result += "<br/>"
}
var pg_name = catalog.i18nc("@action:label", "Printing Guidelines")
result += "<a href='%1'>%2</a>".arg(base.printingGuidelinesUrl).arg(pg_name)
}
if (base.materialWebsiteUrl !== undefined)
{
if (result.length > 0)
{
result += "<br/>"
}
var pg_name = catalog.i18nc("@action:label", "Website")
result += "<a href='%1'>%2</a>".arg(base.materialWebsiteUrl).arg(pg_name)
}
return result
}
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
renderType: Text.NativeRendering
}
}

View file

@ -0,0 +1,43 @@
// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
Item
{
id: detailList
ScrollView
{
clip: true
anchors.fill: detailList
Column
{
anchors
{
right: parent.right
topMargin: UM.Theme.getSize("wide_margin").height
bottomMargin: UM.Theme.getSize("wide_margin").height
top: parent.top
}
height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
spacing: UM.Theme.getSize("default_margin").height
Repeater
{
model: toolbox.packagesModel
delegate: Loader
{
// FIXME: When using asynchronous loading, on Mac and Windows, the tile may fail to load complete,
// leaving an empty space below the title part. We turn it off for now to make it work on Mac and
// Windows.
// Can be related to this QT bug: https://bugreports.qt.io/browse/QTBUG-50992
asynchronous: false
source: "ToolboxDetailTile.qml"
}
}
}
}
}

View file

@ -0,0 +1,74 @@
// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
Item
{
id: tile
width: detailList.width - UM.Theme.getSize("wide_margin").width
height: normalData.height + 2 * UM.Theme.getSize("wide_margin").height
Column
{
id: normalData
anchors
{
top: parent.top
left: parent.left
right: controls.left
rightMargin: UM.Theme.getSize("wide_margin").width
}
Label
{
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
text: model.name
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
Label
{
width: parent.width
text: model.description
maximumLineCount: 25
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
ToolboxCompatibilityChart
{
width: parent.width
packageData: model
}
}
ToolboxDetailTileActions
{
id: controls
anchors.right: tile.right
anchors.top: tile.top
width: childrenRect.width
height: childrenRect.height
packageData: model
}
Rectangle
{
color: UM.Theme.getColor("lining")
width: tile.width
height: UM.Theme.getSize("default_lining").height
anchors.top: normalData.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height + UM.Theme.getSize("wide_margin").height //Normal margin for spacing after chart, wide margin between items.
}
}

View file

@ -0,0 +1,121 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
import Cura 1.1 as Cura
Column
{
property bool installed: toolbox.isInstalled(model.id)
property bool canUpdate: CuraApplication.getPackageManager().packagesWithUpdate.indexOf(model.id) != -1
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
property var packageData
width: UM.Theme.getSize("toolbox_action_button").width
spacing: UM.Theme.getSize("narrow_margin").height
Item
{
width: installButton.width
height: installButton.height
ToolboxProgressButton
{
id: installButton
active: toolbox.isDownloading && toolbox.activePackage == model
onReadyAction:
{
toolbox.activePackage = model
toolbox.startDownload(model.download_url)
}
onActiveAction: toolbox.cancelDownload()
// Don't allow installing while another download is running
enabled: installed || (!(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired)
opacity: enabled ? 1.0 : 0.5
visible: !updateButton.visible && !installed // Don't show when the update button is visible
}
Cura.SecondaryButton
{
id: installedButton
visible: installed
onClicked: toolbox.viewCategory = "installed"
text: catalog.i18nc("@action:button", "Installed")
fixedWidthMode: true
width: installButton.width
height: installButton.height
}
}
Label
{
wrapMode: Text.WordWrap
text: catalog.i18nc("@label:The string between <a href=> and </a> is the highlighted link", "<a href='%1'>Log in</a> is required to install or update")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
visible: loginRequired
width: installButton.width
renderType: Text.NativeRendering
MouseArea
{
anchors.fill: parent
onClicked: Cura.API.account.login()
}
}
Label
{
property var whereToBuyUrl:
{
var pg_name = "whereToBuy"
return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
}
renderType: Text.NativeRendering
text: catalog.i18nc("@label:The string between <a href=> and </a> is the highlighted link", "<a href='%1'>Buy material spools</a>")
linkColor: UM.Theme.getColor("text_link")
visible: whereToBuyUrl != undefined
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
MouseArea
{
anchors.fill: parent
onClicked: Qt.openUrlExternally(parent.whereToBuyUrl)
}
}
ToolboxProgressButton
{
id: updateButton
active: toolbox.isDownloading && toolbox.activePackage == model
readyLabel: catalog.i18nc("@action:button", "Update")
activeLabel: catalog.i18nc("@action:button", "Updating")
completeLabel: catalog.i18nc("@action:button", "Updated")
onReadyAction:
{
toolbox.activePackage = model
toolbox.update(model.id)
}
onActiveAction: toolbox.cancelDownload()
// Don't allow installing while another download is running
enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
opacity: enabled ? 1.0 : 0.5
visible: canUpdate
}
Connections
{
target: toolbox
onInstallChanged: installed = toolbox.isInstalled(model.id)
onFilterChanged:
{
installed = toolbox.isInstalled(model.id)
}
}
}

View file

@ -0,0 +1,45 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
Column
{
property var heading: ""
property var model
id: gridArea
height: childrenRect.height + 2 * padding
width: parent.width
spacing: UM.Theme.getSize("default_margin").height
padding: UM.Theme.getSize("wide_margin").height
Label
{
id: heading
text: gridArea.heading
width: parent.width
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("large")
renderType: Text.NativeRendering
}
Grid
{
id: grid
width: parent.width - 2 * parent.padding
columns: 2
columnSpacing: UM.Theme.getSize("default_margin").height
rowSpacing: UM.Theme.getSize("default_margin").width
Repeater
{
model: gridArea.model
delegate: Loader
{
asynchronous: true
width: Math.round((grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns)
height: UM.Theme.getSize("toolbox_thumbnail_small").height
source: "ToolboxDownloadsGridTile.qml"
}
}
}
}

View file

@ -0,0 +1,133 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import UM 1.1 as UM
import Cura 1.1 as Cura
Item
{
id: toolboxDownloadsGridTile
property int packageCount: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
height: childrenRect.height
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onEntered: thumbnail.border.color = UM.Theme.getColor("primary")
onExited: thumbnail.border.color = UM.Theme.getColor("lining")
onClicked:
{
base.selection = model
switch(toolbox.viewCategory)
{
case "material":
// If model has a type, it must be a package
if (model.type !== undefined)
{
toolbox.viewPage = "detail"
toolbox.filterModelByProp("packages", "id", model.id)
}
else
{
toolbox.viewPage = "author"
toolbox.setFilters("packages", {
"author_id": model.id,
"type": "material"
})
}
break
default:
toolbox.viewPage = "detail"
toolbox.filterModelByProp("packages", "id", model.id)
break
}
}
}
Rectangle
{
id: thumbnail
width: UM.Theme.getSize("toolbox_thumbnail_small").width
height: UM.Theme.getSize("toolbox_thumbnail_small").height
color: UM.Theme.getColor("main_background")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
Image
{
anchors.centerIn: parent
width: UM.Theme.getSize("toolbox_thumbnail_small").width - UM.Theme.getSize("wide_margin").width
height: UM.Theme.getSize("toolbox_thumbnail_small").height - UM.Theme.getSize("wide_margin").width
fillMode: Image.PreserveAspectFit
source: model.icon_url || "../../images/logobot.svg"
mipmap: true
}
UM.RecolorImage
{
width: (parent.width * 0.4) | 0
height: (parent.height * 0.4) | 0
anchors
{
bottom: parent.bottom
right: parent.right
}
sourceSize.height: height
visible: installedPackages != 0
color: (installedPackages >= packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
source: "../../images/installed_check.svg"
}
}
Item
{
anchors
{
left: thumbnail.right
leftMargin: Math.floor(UM.Theme.getSize("narrow_margin").width)
right: parent.right
top: parent.top
bottom: parent.bottom
}
Label
{
id: name
text: model.name
width: parent.width
elide: Text.ElideRight
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default_bold")
}
Label
{
id: info
text: model.description
elide: Text.ElideRight
width: parent.width
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
anchors.top: name.bottom
anchors.bottom: rating.top
verticalAlignment: Text.AlignVCenter
maximumLineCount: 2
}
SmallRatingWidget
{
id: rating
anchors
{
bottom: parent.bottom
left: parent.left
right: parent.right
}
}
}
}

View file

@ -0,0 +1,57 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
Rectangle
{
color: UM.Theme.getColor("secondary")
height: childrenRect.height
width: parent.width
Column
{
height: childrenRect.height + 2 * padding
spacing: UM.Theme.getSize("default_margin").width
width: parent.width
padding: UM.Theme.getSize("wide_margin").height
Label
{
id: heading
text: catalog.i18nc("@label", "Featured")
width: parent.width
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("large")
renderType: Text.NativeRendering
}
Grid
{
height: childrenRect.height
spacing: UM.Theme.getSize("wide_margin").width
columns: 3
anchors.horizontalCenter: parent.horizontalCenter
Repeater
{
model:
{
if (toolbox.viewCategory == "plugin")
{
return toolbox.pluginsShowcaseModel
}
if (toolbox.viewCategory == "material")
{
return toolbox.materialsShowcaseModel
}
}
delegate: Loader
{
asynchronous: true
source: "ToolboxDownloadsShowcaseTile.qml"
}
}
}
}
}

View file

@ -0,0 +1,119 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import UM 1.1 as UM
Rectangle
{
property int packageCount: toolbox.viewCategory == "material" ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1
property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
id: tileBase
width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width)
height: thumbnail.height + packageName.height + rating.height + UM.Theme.getSize("default_margin").width
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
color: UM.Theme.getColor("main_background")
Image
{
id: thumbnail
height: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
fillMode: Image.PreserveAspectFit
source: model.icon_url || "../../images/logobot.svg"
mipmap: true
anchors
{
top: parent.top
topMargin: UM.Theme.getSize("default_margin").height
horizontalCenter: parent.horizontalCenter
}
}
Label
{
id: packageName
text: model.name
anchors
{
horizontalCenter: parent.horizontalCenter
top: thumbnail.bottom
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
height: UM.Theme.getSize("toolbox_heading_label").height
width: parent.width - UM.Theme.getSize("default_margin").width
wrapMode: Text.WordWrap
elide: Text.ElideRight
font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("text")
}
UM.RecolorImage
{
width: (parent.width * 0.20) | 0
height: width
anchors
{
bottom: bottomBorder.top
right: parent.right
}
visible: installedPackages != 0
color: (installedPackages >= packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
source: "../../images/installed_check.svg"
}
SmallRatingWidget
{
id: rating
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("narrow_margin").height
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle
{
id: bottomBorder
color: UM.Theme.getColor("primary")
anchors.bottom: parent.bottom
width: parent.width
height: UM.Theme.getSize("toolbox_header_highlight").height
}
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onEntered: tileBase.border.color = UM.Theme.getColor("primary")
onExited: tileBase.border.color = UM.Theme.getColor("lining")
onClicked:
{
base.selection = model
switch(toolbox.viewCategory)
{
case "material":
// If model has a type, it must be a package
if (model.type !== undefined)
{
toolbox.viewPage = "detail"
toolbox.filterModelByProp("packages", "id", model.id)
}
else
{
toolbox.viewPage = "author"
toolbox.setFilters("packages", {
"author_id": model.id,
"type": "material"
})
}
break
default:
toolbox.viewPage = "detail"
toolbox.filterModelByProp("packages", "id", model.id)
break
}
}
}
}

View file

@ -0,0 +1,55 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
import Cura 1.0 as Cura
Item
{
id: footer
width: parent.width
anchors.bottom: parent.bottom
height: visible ? UM.Theme.getSize("toolbox_footer").height : 0
Label
{
text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.")
color: UM.Theme.getColor("text")
height: UM.Theme.getSize("toolbox_footer_button").height
verticalAlignment: Text.AlignVCenter
anchors
{
top: restartButton.top
left: parent.left
leftMargin: UM.Theme.getSize("wide_margin").width
right: restartButton.right
rightMargin: UM.Theme.getSize("default_margin").width
}
renderType: Text.NativeRendering
}
Cura.PrimaryButton
{
id: restartButton
anchors
{
top: parent.top
topMargin: UM.Theme.getSize("default_margin").height
right: parent.right
rightMargin: UM.Theme.getSize("wide_margin").width
}
height: UM.Theme.getSize("toolbox_footer_button").height
text: catalog.i18nc("@info:button", "Quit Cura")
onClicked: toolbox.restart()
}
ToolboxShadow
{
visible: footer.visible
anchors.bottom: footer.top
reversed: true
}
}

View file

@ -0,0 +1,91 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import UM 1.4 as UM
import Cura 1.0 as Cura
Item
{
id: header
width: parent.width
height: UM.Theme.getSize("toolbox_header").height
Row
{
id: bar
spacing: UM.Theme.getSize("default_margin").width
height: childrenRect.height
width: childrenRect.width
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
}
ToolboxTabButton
{
id: pluginsTabButton
text: catalog.i18nc("@title:tab", "Plugins")
active: toolbox.viewCategory == "plugin" && enabled
enabled: !toolbox.isDownloading && toolbox.viewPage != "loading" && toolbox.viewPage != "errored"
onClicked:
{
toolbox.filterModelByProp("packages", "type", "plugin")
toolbox.viewCategory = "plugin"
toolbox.viewPage = "overview"
}
}
ToolboxTabButton
{
id: materialsTabButton
text: catalog.i18nc("@title:tab", "Materials")
active: toolbox.viewCategory == "material" && enabled
enabled: !toolbox.isDownloading && toolbox.viewPage != "loading" && toolbox.viewPage != "errored"
onClicked:
{
toolbox.filterModelByProp("authors", "package_types", "material")
toolbox.viewCategory = "material"
toolbox.viewPage = "overview"
}
}
}
ToolboxTabButton
{
id: installedTabButton
text: catalog.i18nc("@title:tab", "Installed")
active: toolbox.viewCategory == "installed"
enabled: !toolbox.isDownloading
anchors
{
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
}
onClicked: toolbox.viewCategory = "installed"
width: UM.Theme.getSize("toolbox_header_tab").width + marketplaceNotificationIcon.width - UM.Theme.getSize("default_margin").width
}
Cura.NotificationIcon
{
id: marketplaceNotificationIcon
visible: CuraApplication.getPackageManager().packagesWithUpdate.length > 0
anchors.right: installedTabButton.right
anchors.verticalCenter: installedTabButton.verticalCenter
labelText:
{
const itemCount = CuraApplication.getPackageManager().packagesWithUpdate.length
return itemCount > 9 ? "9+" : itemCount
}
}
ToolboxShadow
{
anchors.top: bar.bottom
}
}

View file

@ -0,0 +1,120 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
Item
{
height: UM.Theme.getSize("toolbox_installed_tile").height
width: parent.width
property bool isEnabled: true
Rectangle
{
color: UM.Theme.getColor("lining")
width: parent.width
height: Math.floor(UM.Theme.getSize("default_lining").height)
anchors.bottom: parent.bottom
}
Row
{
id: tileRow
height: parent.height
width: parent.width
spacing: UM.Theme.getSize("default_margin").width
topPadding: UM.Theme.getSize("default_margin").height
CheckBox
{
id: disableButton
anchors.verticalCenter: pluginInfo.verticalCenter
checked: isEnabled
visible: model.type == "plugin"
width: visible ? UM.Theme.getSize("checkbox").width : 0
enabled: !toolbox.isDownloading
style: UM.Theme.styles.checkbox
onClicked: toolbox.isEnabled(model.id) ? toolbox.disable(model.id) : toolbox.enable(model.id)
}
Column
{
id: pluginInfo
topPadding: UM.Theme.getSize("narrow_margin").height
property var color: model.type === "plugin" && !isEnabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("text")
width: Math.floor(tileRow.width - (authorInfo.width + pluginActions.width + 2 * tileRow.spacing + ((disableButton.visible) ? disableButton.width + tileRow.spacing : 0)))
Label
{
text: model.name
width: parent.width
wrapMode: Text.WordWrap
font: UM.Theme.getFont("large_bold")
color: pluginInfo.color
renderType: Text.NativeRendering
}
Label
{
text: model.description
font: UM.Theme.getFont("default")
maximumLineCount: 3
elide: Text.ElideRight
width: parent.width
wrapMode: Text.WordWrap
color: pluginInfo.color
renderType: Text.NativeRendering
}
}
Column
{
id: authorInfo
width: Math.floor(UM.Theme.getSize("toolbox_action_button").width * 1.25)
Label
{
text:
{
if (model.author_email)
{
return "<a href=\"mailto:" + model.author_email + "?Subject=Cura: " + model.name + "\">" + model.author_name + "</a>"
}
else
{
return model.author_name
}
}
font: UM.Theme.getFont("medium")
width: parent.width
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin")
color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
linkColor: UM.Theme.getColor("text_link")
renderType: Text.NativeRendering
}
Label
{
text: model.version
font: UM.Theme.getFont("default")
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering
}
}
ToolboxInstalledTileActions
{
id: pluginActions
}
Connections
{
target: toolbox
onEnabledChanged: isEnabled = toolbox.isEnabled(model.id)
}
}
}

View file

@ -0,0 +1,90 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
import Cura 1.1 as Cura
Column
{
property bool canUpdate: CuraApplication.getPackageManager().packagesWithUpdate.indexOf(model.id) != -1
property bool canDowngrade: false
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
width: UM.Theme.getSize("toolbox_action_button").width
spacing: UM.Theme.getSize("narrow_margin").height
Label
{
visible: !model.is_installed
text: catalog.i18nc("@label", "Will install upon restarting")
color: UM.Theme.getColor("lining")
font: UM.Theme.getFont("default")
wrapMode: Text.WordWrap
width: parent.width
renderType: Text.NativeRendering
}
ToolboxProgressButton
{
id: updateButton
active: toolbox.isDownloading && toolbox.activePackage == model
readyLabel: catalog.i18nc("@action:button", "Update")
activeLabel: catalog.i18nc("@action:button", "Updating")
completeLabel: catalog.i18nc("@action:button", "Updated")
onReadyAction:
{
toolbox.activePackage = model
toolbox.update(model.id)
}
onActiveAction: toolbox.cancelDownload()
// Don't allow installing while another download is running
enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
opacity: enabled ? 1.0 : 0.5
visible: canUpdate
}
Label
{
wrapMode: Text.WordWrap
text: catalog.i18nc("@label:The string between <a href=> and </a> is the highlighted link", "<a href='%1'>Log in</a> is required to update")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
visible: loginRequired
width: updateButton.width
renderType: Text.NativeRendering
MouseArea
{
anchors.fill: parent
onClicked: Cura.API.account.login()
}
}
Cura.SecondaryButton
{
id: removeButton
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
visible: !model.is_bundled && model.is_installed
enabled: !toolbox.isDownloading
width: UM.Theme.getSize("toolbox_action_button").width
height: UM.Theme.getSize("toolbox_action_button").height
fixedWidthMode: true
onClicked: toolbox.checkPackageUsageAndUninstall(model.id)
Connections
{
target: toolbox
onMetadataChanged:
{
canDowngrade = toolbox.canDowngrade(model.id)
}
}
}
}

View file

@ -0,0 +1,60 @@
// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
import Cura 1.0 as Cura
Cura.PrimaryButton
{
id: button
property var active: false
property var complete: false
property var readyLabel: catalog.i18nc("@action:button", "Install")
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
property var completeLabel: catalog.i18nc("@action:button", "Installed")
signal readyAction() // Action when button is ready and clicked (likely install)
signal activeAction() // Action when button is active and clicked (likely cancel)
signal completeAction() // Action when button is complete and clicked (likely go to installed)
width: UM.Theme.getSize("toolbox_action_button").width
height: UM.Theme.getSize("toolbox_action_button").height
fixedWidthMode: true
text:
{
if (complete)
{
return completeLabel
}
else if (active)
{
return activeLabel
}
else
{
return readyLabel
}
}
onClicked:
{
if (complete)
{
completeAction()
}
else if (active)
{
activeAction()
}
else
{
readyAction()
}
}
busy: active
}

View file

@ -0,0 +1,24 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
Rectangle
{
property bool reversed: false
width: parent.width
height: 8
gradient: Gradient
{
GradientStop
{
position: reversed ? 1.0 : 0.0
color: reversed ? Qt.rgba(0,0,0,0.05) : Qt.rgba(0,0,0,0.2)
}
GradientStop
{
position: reversed ? 0.0 : 1.0
color: Qt.rgba(0,0,0,0)
}
}
}

View file

@ -0,0 +1,68 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
Button
{
id: control
property bool active: false
implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
background: Item
{
id: backgroundItem
Rectangle
{
id: highlight
visible: control.active
color: UM.Theme.getColor("primary")
anchors.bottom: parent.bottom
width: parent.width
height: UM.Theme.getSize("toolbox_header_highlight").height
}
}
contentItem: Label
{
id: label
text: control.text
color: UM.Theme.getColor("toolbox_header_button_text_inactive")
font: UM.Theme.getFont("medium")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
}
states:
[
State
{
name: "disabled"
when: !control.enabled
PropertyChanges
{
target: label
font: UM.Theme.getFont("default_italic")
}
},
State
{
name: "active"
when: control.active
PropertyChanges
{
target: label
font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("action_button_text")
}
}
]
}