diff --git a/rare/components/tabs/shop/shop_info.py b/rare/components/tabs/shop/shop_info.py index fbe970bc..ff73cbc5 100644 --- a/rare/components/tabs/shop/shop_info.py +++ b/rare/components/tabs/shop/shop_info.py @@ -2,20 +2,22 @@ import json import logging import webbrowser -from PyQt5.QtCore import QLocale, QUrl, QJsonDocument, QJsonParseError +from PyQt5.QtCore import QLocale, QUrl, QJsonDocument, QJsonParseError, Qt from PyQt5.QtGui import QPixmap from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply from PyQt5.QtWidgets import QWidget +from rare.components.tabs.shop.shop_models import ShopGame from rare.ui.components.tabs.store.shop_game_info import Ui_shop_info -from rare.utils import models + +logger = logging.getLogger("ShopInfo") class ShopGameInfo(QWidget, Ui_shop_info): - game: models.ShopGame + game: ShopGame data: dict - # TODO GANZ VIEL + # TODO Design; More information(requirements, more images); bundles (eg EA triple) def __init__(self): super(ShopGameInfo, self).__init__() self.setupUi(self) @@ -28,7 +30,7 @@ class ShopGameInfo(QWidget, Ui_shop_info): slug = slug.replace("/home", "") self.slug = slug self.title.setText(data["title"]) - self.price.setText(data['price']['totalPrice']['fmtPrice']['originalPrice']) + self.dev.setText(self.tr("Loading")) self.image.setPixmap(QPixmap()) self.data = data @@ -39,7 +41,6 @@ class ShopGameInfo(QWidget, Ui_shop_info): # game = api_utils.get_product(slug, locale) self.request = self.manager.get(QNetworkRequest(QUrl(url))) self.request.finished.connect(self.data_received) - # self.request.finished.connect(self.request.deleteLater if self.request else None) def data_received(self): logging.info(f"Data of game {self.data['title']} received") @@ -57,16 +58,16 @@ class ShopGameInfo(QWidget, Ui_shop_info): return else: return - self.game = models.ShopGame.from_json(game, self.data) + self.game = ShopGame.from_json(game, self.data) # print(game) self.title.setText(self.game.title) - """ - if not os.path.exists(path := os.path.expanduser(f"~/.cache/rare/cache/{self.game.title}.png")): - url = game["pages"][0]["_images_"][0] - open(os.path.expanduser(path), "wb").write(requests.get(url).content) - width = 360 - self.image.setPixmap(QPixmap(path).scaled(width, int(width * 9 / 16), transformMode=Qt.SmoothTransformation)) - """ + + self.price.setText(self.game.price) + self.discount_price.setText(self.game.discount_price) + + self.image_request = self.manager.get(QNetworkRequest(QUrl(self.game.image_urls.offer_image_tall))) + self.image_request.finished.connect(self.image_loaded) + try: self.dev.setText(",".join(self.game.developer)) except KeyError: @@ -76,5 +77,14 @@ class ShopGameInfo(QWidget, Ui_shop_info): self.request.deleteLater() + def image_loaded(self): + if self.image_request and self.image_request.error() == QNetworkReply.NoError: + data = self.image_request.readAll().data() + pixmap = QPixmap() + pixmap.loadFromData(data) + self.image.setPixmap(pixmap.scaled(240, 320, transformMode=Qt.SmoothTransformation)) + else: + logger.error("Load image failed") + def button_clicked(self): webbrowser.open("https://www.epicgames.com/store/de/p/" + self.slug) diff --git a/rare/components/tabs/shop/shop_models.py b/rare/components/tabs/shop/shop_models.py new file mode 100644 index 00000000..37a25b98 --- /dev/null +++ b/rare/components/tabs/shop/shop_models.py @@ -0,0 +1,75 @@ + + +class _ImageUrlModel: + def __init__(self, front_tall: str = "", offer_image_tall: str = "", + thumbnail: str = "", front_wide: str = ""): + self.front_tall = front_tall + self.offer_image_tall = offer_image_tall + self.thumbnail = thumbnail + self.front_wide = front_wide + + @classmethod + def from_json(cls, json_data: list): + tmp = cls() + for item in json_data: + if item["type"] == "Thumbnail": + tmp.thumbnail = item["url"] + elif item["type"] == "DieselStoreFrontTall": + tmp.front_tall = item["url"] + elif item["type"] == "DieselStoreFrontWide": + tmp.front_wide = item["url"] + elif item["type"] == "OfferImageTall": + tmp.offer_image_tall = item["url"] + return tmp + + +class ShopGame: + # TODO: Copyrights etc + def __init__(self, title: str = "", image_urls: _ImageUrlModel = None, social_links: dict = None, + langs: list = None, reqs: list = None, publisher: str = "", developer: str = "", + original_price: str = "", discount_price: str=""): + self.title = title + self.image_urls = image_urls + self.links = [] + if social_links: + for item in social_links: + if item.startswith("link"): + self.links.append(tuple((item.replace("link", ""), social_links[item]))) + else: + self.links = [] + self.languages = langs + self.reqs = reqs # {"Betriebssystem":win7, processor:i9 9900k, ram...}; Note: name from language + self.publisher = publisher + self.developer = developer + self.price = original_price + self.discount_price = discount_price + + @classmethod + def from_json(cls, api_data: dict, search_data: dict): + if isinstance(api_data, list): + for product in api_data: + if product["_title"] == "home": + api_data = product + break + + tmp = cls() + tmp.title = api_data.get("productName", "undefined") + tmp.image_urls = _ImageUrlModel.from_json(search_data["keyImages"]) + links = api_data["pages"][0]["data"]["socialLinks"] + tmp.links = [] + for item in links: + if item.startswith("link"): + tmp.links.append(tuple((item.replace("link", ""), links[item]))) + tmp.available_voice_langs = api_data["pages"][0]["data"]["requirements"]["languages"] + tmp.reqs = [] + for i, system in enumerate(api_data["pages"][0]["data"]["requirements"]["systems"]): + tmp.reqs.append({"name": system["systemType"], "value": []}) + for req in system["details"]: + tmp.reqs[i]["value"].append(tuple((req["minimum"], req["recommended"]))) + + tmp.publisher = api_data["pages"][0]["data"]["meta"].get("publisher", "undefined") + tmp.developer = api_data["pages"][0]["data"]["meta"].get("developer", "undefined") + tmp.price = search_data['price']['totalPrice']['fmtPrice']['originalPrice'] + tmp.discount_price = search_data['price']['totalPrice']['fmtPrice']['discountPrice'] + + return tmp diff --git a/rare/ui/components/tabs/store/shop_game_info.py b/rare/ui/components/tabs/store/shop_game_info.py index 5ae1d466..5fa9bcba 100644 --- a/rare/ui/components/tabs/store/shop_game_info.py +++ b/rare/ui/components/tabs/store/shop_game_info.py @@ -39,6 +39,9 @@ class Ui_shop_info(object): self.price.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse) self.price.setObjectName("price") self.verticalLayout_2.addWidget(self.price) + self.discount_price = QtWidgets.QLabel(shop_info) + self.discount_price.setObjectName("discount_price") + self.verticalLayout_2.addWidget(self.discount_price) self.horizontalLayout.addLayout(self.verticalLayout_2) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) @@ -60,6 +63,7 @@ class Ui_shop_info(object): self.title.setText(_translate("shop_info", "Error")) self.dev.setText(_translate("shop_info", "TextLabel")) self.price.setText(_translate("shop_info", "TextLabel")) + self.discount_price.setText(_translate("shop_info", "TextLabel")) self.open_store_button.setText(_translate("shop_info", "Buy Game in Epic Games Store")) diff --git a/rare/ui/components/tabs/store/shop_game_info.ui b/rare/ui/components/tabs/store/shop_game_info.ui index 960a1f87..5ca98cc4 100644 --- a/rare/ui/components/tabs/store/shop_game_info.ui +++ b/rare/ui/components/tabs/store/shop_game_info.ui @@ -62,6 +62,13 @@ + + + + TextLabel + + + diff --git a/rare/utils/models.py b/rare/utils/models.py index 416c90d5..44400ddc 100644 --- a/rare/utils/models.py +++ b/rare/utils/models.py @@ -34,62 +34,3 @@ class InstallQueueItemModel: def __bool__(self): return (self.status_q is not None) and (self.download is not None) and (self.options is not None) - - -class ShopGame: - # TODO: Copyrights etc - def __init__(self, title: str = "", image_urls: dict = None, social_links: dict = None, - langs: list = None, reqs: list = None, publisher: str = "", developer: str = "", - price: str = ""): - self.title = title - self.image_urls = image_urls - self.links = [] - if social_links: - for item in social_links: - if item.startswith("link"): - self.links.append(tuple((item.replace("link", ""), social_links[item]))) - else: - self.links = [] - self.languages = langs - self.reqs = reqs # {"Betriebssystem":win7, processor:i9 9900k, ram...}; Note: name from language - self.publisher = publisher - self.developer = developer - self.price = price - - @classmethod - def from_json(cls, api_data: dict, search_data: dict): - print(api_data) - if isinstance(api_data, list): - for product in api_data: - if product["_title"] == "home": - api_data = product - print("home") - break - - tmp = cls() - tmp.title = api_data.get("productName", "undefined") - """tmp.img_urls = { - "DieselImage": data["pages"][0]["data"]["about"]["image"]["src"], - "banner": data["pages"][0]["data"]["hero"]["backgroundImageUrl"] - }""" - links = api_data["pages"][0]["data"]["socialLinks"] - tmp.links = [] - for item in links: - if item.startswith("link"): - tmp.links.append(tuple((item.replace("link", ""), links[item]))) - tmp.available_voice_langs = api_data["pages"][0]["data"]["requirements"]["languages"] - tmp.reqs = [] - for i, system in enumerate(api_data["pages"][0]["data"]["requirements"]["systems"]): - tmp.reqs.append({"name": system["systemType"], "value": []}) - for req in system["details"]: - tmp.reqs[i]["value"].append(tuple((req["minimum"], req["recommended"]))) - - tmp.publisher = api_data["pages"][0]["data"]["meta"].get("publisher", "undefined") - tmp.developer = api_data["pages"][0]["data"]["meta"].get("developer", "undefined") - tmp.price = { - "normal": search_data["price"]["totalPrice"]["originalPrice"] - } - if price := search_data["price"]["totalPrice"].get("discountPrice"): - tmp.price["discount"] = price - - return tmp