mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-22 22:23:57 -06:00
Adds rough first version of rating stars
It's not fully polished just yet CURA-6013
This commit is contained in:
parent
ab8a2a9b2b
commit
f4220da550
8 changed files with 180 additions and 17 deletions
|
@ -44,7 +44,7 @@ class Account(QObject):
|
|||
OAUTH_SERVER_URL= self._oauth_root,
|
||||
CALLBACK_PORT=self._callback_port,
|
||||
CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
|
||||
CLIENT_ID="um---------------ultimaker_cura_drive_plugin",
|
||||
CLIENT_ID="um----------------------------ultimaker_cura",
|
||||
CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write",
|
||||
AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
|
||||
AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
|
||||
|
|
101
plugins/Toolbox/resources/qml/RatingWidget.qml
Normal file
101
plugins/Toolbox/resources/qml/RatingWidget.qml
Normal file
|
@ -0,0 +1,101 @@
|
|||
import QtQuick 2.2
|
||||
import QtQuick.Controls 2.0
|
||||
import UM 1.0 as UM
|
||||
|
||||
Item
|
||||
{
|
||||
id: ratingWidget
|
||||
|
||||
property real rating: 0
|
||||
property int indexHovered: -1
|
||||
property string packageId: ""
|
||||
property int numRatings: 0
|
||||
property int userRating: 0
|
||||
width: contentRow.width
|
||||
height: contentRow.height
|
||||
MouseArea
|
||||
{
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: ratingWidget.enabled
|
||||
acceptedButtons: Qt.NoButton
|
||||
onExited:
|
||||
{
|
||||
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)
|
||||
{
|
||||
indexHovered = index
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
// Unfilled stars should always have the default color. Only filled stars should change on hover
|
||||
color:
|
||||
{
|
||||
if(!enabled)
|
||||
{
|
||||
return "#5a5a5a"
|
||||
}
|
||||
if((ratingWidget.indexHovered >= 0 || ratingWidget.userRating > 0) && isStarFilled)
|
||||
{
|
||||
return UM.Theme.getColor("primary")
|
||||
}
|
||||
return "#5a5a5a"
|
||||
}
|
||||
}
|
||||
onClicked:
|
||||
{
|
||||
if(userRating == 0)
|
||||
{
|
||||
//User didn't vote yet, locally fake it
|
||||
numRatings += 1
|
||||
}
|
||||
userRating = index + 1 // Fake local data
|
||||
toolbox.ratePackage(ratingWidget.packageId, index + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: "(" + numRatings + ")"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,6 +84,16 @@ Item
|
|||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
|
||||
RatingWidget
|
||||
{
|
||||
visible: model.type == "plugin"
|
||||
packageId: model.id
|
||||
rating: model.average_rating != undefined ? model.average_rating : 0
|
||||
numRatings: model.num_ratings != undefined ? model.num_ratings : 0
|
||||
userRating: model.user_rating
|
||||
enabled: installedPackages != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea
|
||||
|
|
|
@ -41,6 +41,9 @@ class PackagesModel(ListModel):
|
|||
self.addRoleName(Qt.UserRole + 20, "links")
|
||||
self.addRoleName(Qt.UserRole + 21, "website")
|
||||
self.addRoleName(Qt.UserRole + 22, "login_required")
|
||||
self.addRoleName(Qt.UserRole + 23, "average_rating")
|
||||
self.addRoleName(Qt.UserRole + 24, "num_ratings")
|
||||
self.addRoleName(Qt.UserRole + 25, "user_rating")
|
||||
|
||||
# List of filters for queries. The result is the union of the each list of results.
|
||||
self._filter = {} # type: Dict[str, str]
|
||||
|
@ -101,7 +104,10 @@ class PackagesModel(ListModel):
|
|||
"tags": package["tags"] if "tags" in package else [],
|
||||
"links": links_dict,
|
||||
"website": package["website"] if "website" in package else None,
|
||||
"login_required": "login-required" in package.get("tags", [])
|
||||
"login_required": "login-required" in package.get("tags", []),
|
||||
"average_rating": package.get("rating", {}).get("average", 0),
|
||||
"num_ratings": package.get("rating", {}).get("count", 0),
|
||||
"user_rating": package.get("rating", {}).get("user", 0)
|
||||
})
|
||||
|
||||
# Filter on all the key-word arguments.
|
||||
|
|
|
@ -22,7 +22,8 @@ from cura.CuraApplication import CuraApplication
|
|||
|
||||
from .AuthorsModel import AuthorsModel
|
||||
from .PackagesModel import PackagesModel
|
||||
|
||||
from cura.CuraVersion import CuraVersion
|
||||
from cura.API import CuraAPI
|
||||
if TYPE_CHECKING:
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
|
||||
|
@ -50,17 +51,10 @@ class Toolbox(QObject, Extension):
|
|||
self._download_progress = 0 # type: float
|
||||
self._is_downloading = False # type: bool
|
||||
self._network_manager = None # type: Optional[QNetworkAccessManager]
|
||||
self._request_header = [
|
||||
b"User-Agent",
|
||||
str.encode(
|
||||
"%s/%s (%s %s)" % (
|
||||
self._application.getApplicationName(),
|
||||
self._application.getVersion(),
|
||||
platform.system(),
|
||||
platform.machine(),
|
||||
)
|
||||
)
|
||||
]
|
||||
self._request_headers = [] # type: List[Tuple(bytes, bytes)]
|
||||
self._updateRequestHeader()
|
||||
|
||||
|
||||
self._request_urls = {} # type: Dict[str, QUrl]
|
||||
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
|
||||
self._old_plugin_ids = set() # type: Set[str]
|
||||
|
@ -115,6 +109,7 @@ class Toolbox(QObject, Extension):
|
|||
self._restart_dialog_message = "" # type: str
|
||||
|
||||
self._application.initializationFinished.connect(self._onAppInitialized)
|
||||
self._application.getCuraAPI().account.loginStateChanged.connect(self._updateRequestHeader)
|
||||
|
||||
# Signals:
|
||||
# --------------------------------------------------------------------------
|
||||
|
@ -134,12 +129,38 @@ class Toolbox(QObject, Extension):
|
|||
showLicenseDialog = pyqtSignal()
|
||||
uninstallVariablesChanged = pyqtSignal()
|
||||
|
||||
def _updateRequestHeader(self):
|
||||
self._request_headers = [
|
||||
(b"User-Agent",
|
||||
str.encode(
|
||||
"%s/%s (%s %s)" % (
|
||||
self._application.getApplicationName(),
|
||||
self._application.getVersion(),
|
||||
platform.system(),
|
||||
platform.machine(),
|
||||
)
|
||||
))
|
||||
]
|
||||
access_token = self._application.getCuraAPI().account.accessToken
|
||||
if access_token:
|
||||
self._request_headers.append((b"Authorization", "Bearer {}".format(access_token).encode()))
|
||||
|
||||
def _resetUninstallVariables(self) -> None:
|
||||
self._package_id_to_uninstall = None # type: Optional[str]
|
||||
self._package_name_to_uninstall = ""
|
||||
self._package_used_materials = [] # type: List[Tuple[GlobalStack, str, str]]
|
||||
self._package_used_qualities = [] # type: List[Tuple[GlobalStack, str, str]]
|
||||
|
||||
@pyqtSlot(str, int)
|
||||
def ratePackage(self, package_id: str, rating: int) -> None:
|
||||
url = QUrl("{base_url}/packages/{package_id}/ratings".format(base_url=self._api_url, package_id = package_id))
|
||||
|
||||
self._rate_request = QNetworkRequest(url)
|
||||
for header_name, header_value in self._request_headers:
|
||||
cast(QNetworkRequest, self._rate_request).setRawHeader(header_name, header_value)
|
||||
data = "{\"data\": {\"cura_version\": \"%s\", \"rating\": %i}}" % (Version(CuraVersion), rating)
|
||||
self._rate_reply = cast(QNetworkAccessManager, self._network_manager).put(self._rate_request, data.encode())
|
||||
|
||||
@pyqtSlot(result = str)
|
||||
def getLicenseDialogPluginName(self) -> str:
|
||||
return self._license_dialog_plugin_name
|
||||
|
@ -563,7 +584,8 @@ class Toolbox(QObject, Extension):
|
|||
def _makeRequestByType(self, request_type: str) -> None:
|
||||
Logger.log("i", "Requesting %s metadata from server.", request_type)
|
||||
request = QNetworkRequest(self._request_urls[request_type])
|
||||
request.setRawHeader(*self._request_header)
|
||||
for header_name, header_value in self._request_headers:
|
||||
request.setRawHeader(header_name, header_value)
|
||||
if self._network_manager:
|
||||
self._network_manager.get(request)
|
||||
|
||||
|
@ -578,7 +600,8 @@ class Toolbox(QObject, Extension):
|
|||
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
|
||||
# Patch for Qt 5.9+
|
||||
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
|
||||
cast(QNetworkRequest, self._download_request).setRawHeader(*self._request_header)
|
||||
for header_name, header_value in self._request_headers:
|
||||
cast(QNetworkRequest, self._download_request).setRawHeader(header_name, header_value)
|
||||
self._download_reply = cast(QNetworkAccessManager, self._network_manager).get(self._download_request)
|
||||
self.setDownloadProgress(0)
|
||||
self.setIsDownloading(True)
|
||||
|
@ -660,7 +683,7 @@ class Toolbox(QObject, Extension):
|
|||
else:
|
||||
self.setViewPage("errored")
|
||||
self.resetDownload()
|
||||
else:
|
||||
elif reply.operation() == QNetworkAccessManager.PutOperation:
|
||||
# Ignore any operation that is not a get operation
|
||||
pass
|
||||
|
||||
|
|
11
resources/themes/cura-light/icons/star_empty.svg
Normal file
11
resources/themes/cura-light/icons/star_empty.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14px" height="13px" viewBox="0 0 14 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.2 (67145) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Star Copy 8</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Toolbox-VIP-material" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Marketplace-hover-" transform="translate(-140.000000, -457.000000)" stroke="#666666">
|
||||
<path d="M150.450431,468.749111 L149.791458,464.907 L152.582915,462.186001 L148.725216,461.625444 L147,458.129776 L145.274784,461.625444 L141.417085,462.186001 L144.208542,464.907 L143.549569,468.749111 L147,466.935112 L150.450431,468.749111 Z" id="Star-Copy-8"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 844 B |
11
resources/themes/cura-light/icons/star_filled.svg
Normal file
11
resources/themes/cura-light/icons/star_filled.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14px" height="13px" viewBox="0 0 14 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.2 (67145) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Star Copy 7</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Toolbox-VIP-material" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Marketplace-hover-" transform="translate(-127.000000, -457.000000)" fill="#666666" stroke="#666666">
|
||||
<path d="M137.450431,468.749111 L136.791458,464.907 L139.582915,462.186001 L135.725216,461.625444 L134,458.129776 L132.274784,461.625444 L128.417085,462.186001 L131.208542,464.907 L130.549569,468.749111 L134,466.935112 L137.450431,468.749111 Z" id="Star-Copy-7"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 859 B |
|
@ -394,6 +394,7 @@
|
|||
"section": [0.0, 2.2],
|
||||
"section_icon": [1.6, 1.6],
|
||||
"section_icon_column": [2.8, 0.0],
|
||||
"rating_star": [1.0, 1.0],
|
||||
|
||||
"setting": [25.0, 1.8],
|
||||
"setting_control": [10.0, 2.0],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue