2021-06-04 10:01:54 +12:00
|
|
|
import logging
|
2024-02-13 05:29:39 +13:00
|
|
|
from typing import List, Dict
|
2021-06-04 09:23:55 +12:00
|
|
|
|
2023-09-24 06:24:28 +13:00
|
|
|
from PyQt5.QtCore import Qt, QUrl, pyqtSignal
|
2024-02-03 13:28:55 +13:00
|
|
|
from PyQt5.QtGui import QFont, QDesktopServices, QKeyEvent
|
2021-12-24 22:09:50 +13:00
|
|
|
from PyQt5.QtWidgets import (
|
|
|
|
QWidget,
|
|
|
|
QLabel,
|
|
|
|
QPushButton,
|
|
|
|
QGridLayout,
|
2023-01-30 12:56:29 +13:00
|
|
|
QSizePolicy,
|
2021-12-24 22:09:50 +13:00
|
|
|
)
|
2021-06-04 09:23:55 +12:00
|
|
|
|
2023-09-24 06:24:28 +13:00
|
|
|
from rare.components.tabs.store.api.debug import DebugDialog
|
2024-02-03 13:28:55 +13:00
|
|
|
from rare.components.tabs.store.api.models.diesel import DieselProduct, DieselProductDetail, DieselSystemDetail
|
2023-09-24 06:24:28 +13:00
|
|
|
from rare.components.tabs.store.api.models.response import CatalogOfferModel
|
2024-02-13 05:29:39 +13:00
|
|
|
from rare.components.tabs.store.store_api import StoreAPI
|
2023-09-24 06:24:28 +13:00
|
|
|
from rare.models.image import ImageSize
|
|
|
|
from rare.ui.components.tabs.store.details import Ui_DetailsWidget
|
2024-02-22 08:39:33 +13:00
|
|
|
from rare.utils.misc import qta_icon
|
2023-03-13 01:01:11 +13:00
|
|
|
from rare.widgets.elide_label import ElideLabel
|
2023-09-24 06:24:28 +13:00
|
|
|
from rare.widgets.side_tab import SideTabWidget, SideTabContents
|
|
|
|
from .image import LoadingImageWidget
|
2021-06-09 23:08:25 +12:00
|
|
|
|
2023-09-24 06:24:28 +13:00
|
|
|
logger = logging.getLogger("StoreDetails")
|
2021-06-04 09:23:55 +12:00
|
|
|
|
|
|
|
|
2023-09-24 06:24:28 +13:00
|
|
|
class DetailsWidget(QWidget, SideTabContents):
|
|
|
|
back_clicked: pyqtSignal = pyqtSignal()
|
2021-06-04 09:23:55 +12:00
|
|
|
|
2021-06-10 09:12:49 +12:00
|
|
|
# TODO Design
|
2024-02-13 05:29:39 +13:00
|
|
|
def __init__(self, installed: List, store_api: StoreAPI, parent=None):
|
2023-09-24 06:24:28 +13:00
|
|
|
super(DetailsWidget, self).__init__(parent=parent)
|
2024-02-03 13:28:55 +13:00
|
|
|
self.implements_scrollarea = True
|
|
|
|
|
2023-09-24 06:24:28 +13:00
|
|
|
self.ui = Ui_DetailsWidget()
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.setupUi(self)
|
2023-09-24 06:24:28 +13:00
|
|
|
self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
|
|
|
|
|
2024-02-13 05:29:39 +13:00
|
|
|
self.store_api = store_api
|
|
|
|
self.installed = installed
|
|
|
|
self.catalog_offer: CatalogOfferModel = None
|
2021-08-23 08:22:17 +12:00
|
|
|
|
2024-02-13 05:29:39 +13:00
|
|
|
self.image = LoadingImageWidget(store_api.cached_manager, self)
|
2023-12-15 01:08:08 +13:00
|
|
|
self.image.setFixedSize(ImageSize.Display)
|
2023-09-24 06:24:28 +13:00
|
|
|
self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
|
|
|
|
self.ui.left_layout.setAlignment(Qt.AlignTop)
|
|
|
|
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.wishlist_button.clicked.connect(self.add_to_wishlist)
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.store_button.clicked.connect(self.button_clicked)
|
2023-04-10 23:03:45 +12:00
|
|
|
self.ui.wishlist_button.setVisible(True)
|
2021-08-23 08:22:17 +12:00
|
|
|
self.in_wishlist = False
|
|
|
|
self.wishlist = []
|
|
|
|
|
2024-02-13 05:29:39 +13:00
|
|
|
self.requirements_tabs = SideTabWidget(parent=self.ui.requirements_frame)
|
2023-01-30 12:56:29 +13:00
|
|
|
self.requirements_tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.requirements_layout.addWidget(self.requirements_tabs)
|
2023-01-30 12:56:29 +13:00
|
|
|
|
2024-02-22 08:39:33 +13:00
|
|
|
self.ui.back_button.setIcon(qta_icon("fa.chevron-left"))
|
2023-09-24 06:24:28 +13:00
|
|
|
self.ui.back_button.clicked.connect(self.back_clicked)
|
|
|
|
|
|
|
|
self.setDisabled(False)
|
2023-01-30 12:56:29 +13:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
def handle_wishlist_update(self, wishlist: List[CatalogOfferModel]):
|
|
|
|
if wishlist and wishlist[0] == "error":
|
2021-11-02 08:17:36 +13:00
|
|
|
return
|
2023-04-10 23:03:45 +12:00
|
|
|
self.wishlist = [game.id for game in wishlist]
|
|
|
|
if self.id_str in self.wishlist:
|
2021-08-23 08:22:17 +12:00
|
|
|
self.in_wishlist = True
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.wishlist_button.setText(self.tr("Remove from Wishlist"))
|
2021-08-23 08:22:17 +12:00
|
|
|
else:
|
|
|
|
self.in_wishlist = False
|
2021-06-04 09:23:55 +12:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
def update_game(self, offer: CatalogOfferModel):
|
|
|
|
debug = DebugDialog(offer.__dict__, None)
|
|
|
|
debug.exec()
|
|
|
|
self.ui.title.setText(offer.title)
|
|
|
|
self.title_str = offer.title
|
|
|
|
self.id_str = offer.id
|
2024-02-13 05:29:39 +13:00
|
|
|
self.store_api.get_wishlist(self.handle_wishlist_update)
|
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
# lk: delete tabs in reverse order because indices are updated on deletion
|
2023-01-30 12:56:29 +13:00
|
|
|
while self.requirements_tabs.count():
|
|
|
|
self.requirements_tabs.widget(0).deleteLater()
|
|
|
|
self.requirements_tabs.removeTab(0)
|
|
|
|
self.requirements_tabs.clear()
|
2024-02-13 05:29:39 +13:00
|
|
|
|
|
|
|
slug = offer.productSlug
|
2021-09-13 07:19:51 +12:00
|
|
|
if not slug:
|
2024-02-13 05:29:39 +13:00
|
|
|
for mapping in offer.offerMappings:
|
2021-09-13 07:19:51 +12:00
|
|
|
if mapping["pageType"] == "productHome":
|
|
|
|
slug = mapping["pageSlug"]
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
logger.error("Could not get page information")
|
|
|
|
slug = ""
|
2021-06-09 10:00:00 +12:00
|
|
|
if "/home" in slug:
|
|
|
|
slug = slug.replace("/home", "")
|
|
|
|
self.slug = slug
|
2021-08-23 08:22:17 +12:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
if offer.namespace in self.installed:
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.store_button.setText(self.tr("Show Game on Epic Page"))
|
|
|
|
self.ui.status.setVisible(True)
|
2021-06-15 08:30:57 +12:00
|
|
|
else:
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.store_button.setText(self.tr("Buy Game in Epic Games Store"))
|
|
|
|
self.ui.status.setVisible(False)
|
2021-06-09 23:08:25 +12:00
|
|
|
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.original_price.setText(self.tr("Loading"))
|
2021-08-23 08:22:17 +12:00
|
|
|
# self.title.setText(self.tr("Loading"))
|
2023-01-30 12:56:29 +13:00
|
|
|
# self.image.setPixmap(QPixmap())
|
2021-06-09 23:25:57 +12:00
|
|
|
is_bundle = False
|
2023-04-10 23:03:45 +12:00
|
|
|
for i in offer.categories:
|
2021-06-09 23:25:57 +12:00
|
|
|
if "bundles" in i.get("path", ""):
|
|
|
|
is_bundle = True
|
2021-06-09 10:00:00 +12:00
|
|
|
|
|
|
|
# init API request
|
2021-09-13 07:19:51 +12:00
|
|
|
if slug:
|
2024-02-13 05:29:39 +13:00
|
|
|
self.store_api.get_game_config_cms(offer.productSlug, is_bundle, self.data_received)
|
2023-01-30 12:56:29 +13:00
|
|
|
# else:
|
|
|
|
# self.data_received({})
|
2024-02-13 05:29:39 +13:00
|
|
|
self.catalog_offer = offer
|
2021-08-23 08:22:17 +12:00
|
|
|
|
|
|
|
def add_to_wishlist(self):
|
|
|
|
if not self.in_wishlist:
|
2024-02-13 05:29:39 +13:00
|
|
|
self.store_api.add_to_wishlist(
|
|
|
|
self.catalog_offer.namespace,
|
|
|
|
self.catalog_offer.id,
|
2023-04-10 23:03:45 +12:00
|
|
|
lambda success: self.ui.wishlist_button.setText(self.tr("Remove from wishlist"))
|
|
|
|
if success
|
|
|
|
else self.ui.wishlist_button.setText("Something went wrong")
|
|
|
|
)
|
2021-08-23 08:22:17 +12:00
|
|
|
else:
|
2024-02-13 05:29:39 +13:00
|
|
|
self.store_api.remove_from_wishlist(
|
|
|
|
self.catalog_offer.namespace,
|
|
|
|
self.catalog_offer.id,
|
2023-04-10 23:03:45 +12:00
|
|
|
lambda success: self.ui.wishlist_button.setText(self.tr("Add to wishlist"))
|
2021-12-24 22:09:50 +13:00
|
|
|
if success
|
2023-04-10 23:03:45 +12:00
|
|
|
else self.ui.wishlist_button.setText("Something went wrong"),
|
2021-12-24 22:09:50 +13:00
|
|
|
)
|
2021-08-08 09:42:40 +12:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
def data_received(self, product: DieselProduct):
|
2021-09-13 07:19:51 +12:00
|
|
|
try:
|
2023-04-10 23:03:45 +12:00
|
|
|
if product.pages:
|
|
|
|
product_data: DieselProductDetail = product.pages[0].data
|
|
|
|
else:
|
|
|
|
product_data: DieselProductDetail = product.data
|
2021-09-13 07:19:51 +12:00
|
|
|
except Exception as e:
|
2023-01-30 12:56:29 +13:00
|
|
|
raise e
|
2021-09-13 07:19:51 +12:00
|
|
|
logger.error(str(e))
|
2021-12-04 13:52:55 +13:00
|
|
|
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.original_price.setFont(self.font())
|
2024-02-13 05:29:39 +13:00
|
|
|
price = self.catalog_offer.price.totalPrice.fmtPrice["originalPrice"]
|
|
|
|
discount_price = self.catalog_offer.price.totalPrice.fmtPrice["discountPrice"]
|
2023-04-10 23:03:45 +12:00
|
|
|
if price == "0" or price == 0:
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.original_price.setText(self.tr("Free"))
|
2021-08-26 06:41:10 +12:00
|
|
|
else:
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.original_price.setText(price)
|
2023-04-10 23:03:45 +12:00
|
|
|
if price != discount_price:
|
2024-02-13 05:29:39 +13:00
|
|
|
font = self.font()
|
2021-06-18 22:24:56 +12:00
|
|
|
font.setStrikeOut(True)
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.original_price.setFont(font)
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.discount_price.setText(
|
2023-04-10 23:03:45 +12:00
|
|
|
discount_price
|
|
|
|
if discount_price != "0"
|
2021-12-24 22:09:50 +13:00
|
|
|
else self.tr("Free")
|
|
|
|
)
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.discount_price.setVisible(True)
|
2021-06-11 00:13:28 +12:00
|
|
|
else:
|
2023-03-31 11:09:40 +13:00
|
|
|
self.ui.discount_price.setVisible(False)
|
2021-08-29 05:43:54 +12:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
requirements = product_data.requirements
|
|
|
|
if requirements and requirements.systems:
|
|
|
|
for system in requirements.systems:
|
2024-02-03 13:28:55 +13:00
|
|
|
req_widget = RequirementsWidget(system, self.requirements_tabs)
|
2024-02-13 05:29:39 +13:00
|
|
|
self.requirements_tabs.addTab(req_widget, system.systemType)
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.requirements_frame.setVisible(True)
|
2021-09-06 07:25:57 +12:00
|
|
|
else:
|
2023-04-10 23:03:45 +12:00
|
|
|
self.ui.requirements_frame.setVisible(False)
|
|
|
|
|
2024-02-13 05:29:39 +13:00
|
|
|
key_images = self.catalog_offer.keyImages
|
2023-04-10 23:03:45 +12:00
|
|
|
img_url = key_images.for_dimensions(self.image.size().width(), self.image.size().height())
|
|
|
|
self.image.fetchPixmap(img_url.url)
|
2021-06-11 00:13:28 +12:00
|
|
|
|
2023-01-30 12:56:29 +13:00
|
|
|
# self.image_stack.setCurrentIndex(0)
|
2023-04-10 23:03:45 +12:00
|
|
|
about = product_data.about
|
2023-09-24 06:24:28 +13:00
|
|
|
self.ui.description_label.setMarkdown(about.desciption)
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.developer.setText(about.developerAttribution)
|
2023-04-10 23:03:45 +12:00
|
|
|
# try:
|
|
|
|
# if isinstance(aboudeveloper, list):
|
|
|
|
# self.ui.dev.setText(", ".join(self.game.developer))
|
|
|
|
# else:
|
|
|
|
# self.ui.dev.setText(self.game.developer)
|
|
|
|
# except KeyError:
|
|
|
|
# pass
|
|
|
|
tags = product_data.unmapped["meta"].get("tags", [])
|
|
|
|
self.ui.tags.setText(", ".join(tags))
|
2021-08-23 08:22:17 +12:00
|
|
|
|
2021-09-06 07:25:57 +12:00
|
|
|
# clear Layout
|
2024-02-21 05:45:14 +13:00
|
|
|
for b in self.ui.social_links.findChildren(SocialButton, options=Qt.FindDirectChildrenOnly):
|
|
|
|
self.ui.social_links_layout.removeWidget(b)
|
2023-01-30 12:56:29 +13:00
|
|
|
b.deleteLater()
|
2021-09-13 09:28:54 +12:00
|
|
|
|
2024-02-13 05:29:39 +13:00
|
|
|
links = product_data.socialLinks
|
2021-09-06 07:25:57 +12:00
|
|
|
link_count = 0
|
2023-04-10 23:03:45 +12:00
|
|
|
for name, url in links.items():
|
|
|
|
if name == "_type":
|
|
|
|
continue
|
|
|
|
name = name.replace("link", "").lower()
|
|
|
|
if name == "homepage":
|
2024-02-22 08:39:33 +13:00
|
|
|
icn = qta_icon("mdi.web", "fa.search", scale_factor=1.5)
|
2021-09-06 07:25:57 +12:00
|
|
|
else:
|
|
|
|
try:
|
2024-02-22 08:39:33 +13:00
|
|
|
icn = qta_icon(f"mdi.{name}", f"fa.{name}", scale_factor=1.5)
|
2021-09-06 07:25:57 +12:00
|
|
|
except Exception as e:
|
|
|
|
logger.error(str(e))
|
|
|
|
continue
|
|
|
|
|
2024-02-21 05:45:14 +13:00
|
|
|
button = SocialButton(icn, url, parent=self.ui.social_links)
|
|
|
|
self.ui.social_links_layout.addWidget(button)
|
2021-09-06 07:25:57 +12:00
|
|
|
link_count += 1
|
|
|
|
|
2024-02-21 05:45:14 +13:00
|
|
|
self.ui.social_links.setEnabled(bool(link_count))
|
2023-01-30 12:56:29 +13:00
|
|
|
|
|
|
|
self.setEnabled(True)
|
2021-09-06 07:25:57 +12:00
|
|
|
|
2023-04-10 23:03:45 +12:00
|
|
|
# def add_wishlist_items(self, wishlist: List[CatalogGameModel]):
|
|
|
|
# wishlist = wishlist["data"]["Wishlist"]["wishlistItems"]["elements"]
|
|
|
|
# for game in wishlist:
|
|
|
|
# self.wishlist.append(game["offer"]["title"])
|
2021-06-04 09:23:55 +12:00
|
|
|
|
|
|
|
def button_clicked(self):
|
2024-02-13 05:29:39 +13:00
|
|
|
QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{self.store_api.language_code}/p/{self.slug}"))
|
2021-09-06 07:25:57 +12:00
|
|
|
|
2024-02-03 13:28:55 +13:00
|
|
|
def keyPressEvent(self, a0: QKeyEvent):
|
|
|
|
if a0.key() == Qt.Key_Escape:
|
|
|
|
self.back_clicked.emit()
|
|
|
|
|
2021-09-06 07:25:57 +12:00
|
|
|
|
|
|
|
class SocialButton(QPushButton):
|
2023-01-30 12:56:29 +13:00
|
|
|
def __init__(self, icn, url, parent=None):
|
|
|
|
super(SocialButton, self).__init__(icn, "", parent=parent)
|
2024-02-21 05:45:14 +13:00
|
|
|
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
2021-09-06 07:25:57 +12:00
|
|
|
self.url = url
|
2022-01-09 12:32:37 +13:00
|
|
|
self.clicked.connect(lambda: QDesktopServices.openUrl(QUrl(url)))
|
2021-09-06 07:25:57 +12:00
|
|
|
self.setToolTip(url)
|
2024-02-03 13:28:55 +13:00
|
|
|
|
|
|
|
|
|
|
|
class RequirementsWidget(QWidget, SideTabContents):
|
|
|
|
def __init__(self, system: DieselSystemDetail, parent=None):
|
|
|
|
super().__init__(parent=parent)
|
|
|
|
self.implements_scrollarea = True
|
|
|
|
|
|
|
|
bold_font = self.font()
|
|
|
|
bold_font.setBold(True)
|
|
|
|
|
|
|
|
req_layout = QGridLayout(self)
|
|
|
|
min_label = QLabel(self.tr("Minimum"), parent=self)
|
|
|
|
min_label.setFont(bold_font)
|
|
|
|
rec_label = QLabel(self.tr("Recommend"), parent=self)
|
|
|
|
rec_label.setFont(bold_font)
|
|
|
|
req_layout.addWidget(min_label, 0, 1)
|
|
|
|
req_layout.addWidget(rec_label, 0, 2)
|
|
|
|
req_layout.setColumnStretch(1, 2)
|
|
|
|
req_layout.setColumnStretch(2, 2)
|
|
|
|
for i, detail in enumerate(system.details):
|
|
|
|
req_layout.addWidget(QLabel(detail.title, parent=self), i + 1, 0)
|
|
|
|
min_label = ElideLabel(detail.minimum, parent=self)
|
|
|
|
req_layout.addWidget(min_label, i + 1, 1)
|
|
|
|
rec_label = ElideLabel(detail.recommended, parent=self)
|
|
|
|
req_layout.addWidget(rec_label, i + 1, 2)
|
|
|
|
req_layout.setAlignment(Qt.AlignTop)
|
|
|
|
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|