1
0
Fork 0
mirror of synced 2024-05-19 12:02:54 +12:00
This commit is contained in:
loathingKernel 2024-02-12 18:29:39 +02:00
parent 2a2458bacb
commit 9ec349e2d1
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
14 changed files with 270 additions and 283 deletions

View file

@ -28,21 +28,15 @@ class StoreTab(SideTabWidget):
self.landing = LandingPage(self.api, parent=self) self.landing = LandingPage(self.api, parent=self)
self.landing_index = self.addTab(self.landing, self.tr("Store")) self.landing_index = self.addTab(self.landing, self.tr("Store"))
self.search = SearchPage(self.core, self.api, parent=self) self.search = SearchPage(self.api, parent=self)
self.search_index = self.addTab(self.search, self.tr("Search")) self.search_index = self.addTab(self.search, self.tr("Search"))
self.wishlist = WishlistPage(self.api, parent=self) self.wishlist = WishlistPage(self.api, parent=self)
self.wishlist_index = self.addTab(self.wishlist, self.tr("Wishlist")) self.wishlist_index = self.addTab(self.wishlist, self.tr("Wishlist"))
self.api.update_wishlist.connect(self.update_wishlist)
self.previous_index = self.landing_index
def showEvent(self, a0: QShowEvent) -> None: def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous() or self.init: if a0.spontaneous() or self.init:
return super().showEvent(a0) return super().showEvent(a0)
# self.landing.load()
# self.wishlist.update_wishlist()
self.init = True self.init = True
return super().showEvent(a0) return super().showEvent(a0)
@ -51,6 +45,3 @@ class StoreTab(SideTabWidget):
return super().hideEvent(a0) return super().hideEvent(a0)
# TODO: Implement store unloading # TODO: Implement store unloading
return super().hideEvent(a0) return super().hideEvent(a0)
def update_wishlist(self):
self.landing.update_wishlist()

View file

@ -25,14 +25,14 @@ type DiscountSetting {
discountType: String discountType: String
} }
type AppliedRuled { type AppliedRules {
id: ID id: ID
endDate: Date endDate: Date
discountSetting: DiscountSetting discountSetting: DiscountSetting
} }
type LineOfferRes { type LineOfferRes {
appliedRules: [AppliedRuled] appliedRules: [AppliedRules]
} }
type GetPriceRes { type GetPriceRes {

View file

@ -33,7 +33,7 @@ class DieselSystemDetailItem:
class DieselSystemDetail: class DieselSystemDetail:
p_type: Optional[str] = None p_type: Optional[str] = None
details: Optional[List[DieselSystemDetailItem]] = None details: Optional[List[DieselSystemDetailItem]] = None
system_type: Optional[str] = None systemType: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
@ -47,7 +47,7 @@ class DieselSystemDetail:
tmp = cls( tmp = cls(
p_type=d.pop("_type", ""), p_type=d.pop("_type", ""),
details=details, details=details,
system_type=d.pop("systemType", ""), systemType=d.pop("systemType", ""),
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -107,7 +107,7 @@ class DieselProductDetail:
p_type: Optional[str] = None p_type: Optional[str] = None
about: Optional[DieselProductAbout] = None about: Optional[DieselProductAbout] = None
requirements: Optional[DieselSystemDetails] = None requirements: Optional[DieselSystemDetails] = None
social_links: Optional[DieselSocialLinks] = None socialLinks: Optional[DieselSocialLinks] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
@ -119,7 +119,7 @@ class DieselProductDetail:
p_type=d.pop("_type", ""), p_type=d.pop("_type", ""),
about=about, about=about,
requirements=requirements, requirements=requirements,
social_links=d.pop("socialLinks", {}), socialLinks=d.pop("socialLinks", {}),
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -136,7 +136,7 @@ class DieselProduct:
namespace: Optional[str] = None namespace: Optional[str] = None
pages: Optional[List["DieselProduct"]] = None pages: Optional[List["DieselProduct"]] = None
data: Optional[DieselProductDetail] = None data: Optional[DieselProductDetail] = None
product_name: Optional[str] = None productName: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
@ -158,7 +158,7 @@ class DieselProduct:
namespace=d.pop("namespace", ""), namespace=d.pop("namespace", ""),
pages=pages, pages=pages,
data=data, data=data,
product_name=d.pop("productName", ""), productName=d.pop("productName", ""),
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp

View file

@ -1,7 +1,7 @@
import logging import logging
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime from datetime import datetime
from typing import List, Dict, Any, Type, Optional from typing import List, Dict, Any, Type, Optional, Tuple
from .utils import parse_date from .utils import parse_date
@ -17,7 +17,6 @@ ItemModel = Dict
SellerModel = Dict SellerModel = Dict
PageSandboxModel = Dict PageSandboxModel = Dict
TagModel = Dict TagModel = Dict
PromotionsModel = Dict
@dataclass @dataclass
@ -39,16 +38,15 @@ class ImageUrlModel:
d = src.copy() d = src.copy()
type = d.pop("type", None) type = d.pop("type", None)
url = d.pop("url", None) url = d.pop("url", None)
tmp = cls( tmp = cls(type=type, url=url)
type=type,
url=url,
)
return tmp return tmp
@dataclass @dataclass
class KeyImagesModel: class KeyImagesModel:
key_images: Optional[List[ImageUrlModel]] = None key_images: Optional[List[ImageUrlModel]] = None
tall_types = ("DieselStoreFrontTall", "OfferImageTall", "Thumbnail", "ProductLogo", "DieselGameBoxLogo")
wide_types = ("DieselStoreFrontWide", "OfferImageWide", "VaultClosed", "ProductLogo")
def __getitem__(self, item): def __getitem__(self, item):
return self.key_images[item] return self.key_images[item]
@ -76,21 +74,13 @@ class KeyImagesModel:
return tmp return tmp
def available_tall(self) -> List[ImageUrlModel]: def available_tall(self) -> List[ImageUrlModel]:
tall_types = [ tall_images = filter(lambda img: img.type in KeyImagesModel.tall_types, self.key_images)
"DieselStoreFrontTall", tall_images = sorted(tall_images, key=lambda x: KeyImagesModel.tall_types.index(x.type))
"OfferImageTall",
"Thumbnail",
"ProductLogo",
"DieselGameBoxLogo",
]
tall_images = filter(lambda img: img.type in tall_types, self.key_images)
tall_images = sorted(tall_images, key=lambda x: tall_types.index(x.type))
return tall_images return tall_images
def available_wide(self) -> List[ImageUrlModel]: def available_wide(self) -> List[ImageUrlModel]:
wide_types = ["DieselStoreFrontWide", "OfferImageWide", "VaultClosed", "ProductLogo"] wide_images = filter(lambda img: img.type in KeyImagesModel.wide_types, self.key_images)
wide_images = filter(lambda img: img.type in wide_types, self.key_images) wide_images = sorted(wide_images, key=lambda x: KeyImagesModel.wide_types.index(x.type))
wide_images = sorted(wide_images, key=lambda x: wide_types.index(x.type))
return wide_images return wide_images
def for_dimensions(self, w: int, h: int) -> ImageUrlModel: def for_dimensions(self, w: int, h: int) -> ImageUrlModel:
@ -107,55 +97,133 @@ class KeyImagesModel:
return model return model
TotalPriceModel = Dict CurrencyModel = Dict
FmtPriceModel = Dict FormattedPriceModel = Dict
LineOffersModel = Dict LineOffersModel = Dict
@dataclass @dataclass
class GetPriceResModel: class TotalPriceModel:
total_price: Optional[TotalPriceModel] = None discountPrice: Optional[int] = None
fmt_price: Optional[FmtPriceModel] = None originalPrice: Optional[int] = None
line_offers: Optional[LineOffersModel] = None voucherDiscount: Optional[int] = None
discount: Optional[int] = None
currencyCode: Optional[str] = None
currencyInfo: Optional[CurrencyModel] = None
fmtPrice: Optional[FormattedPriceModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
def from_dict(cls: Type["GetPriceResModel"], src: Dict[str, Any]) -> "GetPriceResModel": def from_dict(cls: Type["TotalPriceModel"], src: Dict[str, Any]) -> "TotalPriceModel":
d = src.copy() d = src.copy()
tmp = cls( tmp = cls(
total_price=d.pop("totalPrice", {}), discountPrice=d.pop("discountPrice", None),
fmt_price=d.pop("fmtPrice", {}), originalPrice=d.pop("originalPrice", None),
line_offers=d.pop("lineOffers", {}), voucherDiscount=d.pop("voucherDiscount", None),
discount=d.pop("discount", None),
currencyCode=d.pop("currencyCode", None),
currencyInfo=d.pop("currrencyInfo", {}),
fmtPrice=d.pop("fmtPrice", {}),
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@dataclass
class GetPriceResModel:
totalPrice: Optional[TotalPriceModel] = None
lineOffers: Optional[LineOffersModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["GetPriceResModel"], src: Dict[str, Any]) -> "GetPriceResModel":
d = src.copy()
total_price = TotalPriceModel.from_dict(x) if (x := d.pop("totalPrice", {})) else None
tmp = cls(totalPrice=total_price, lineOffers=d.pop("lineOffers", {}))
tmp.unmapped = d
return tmp
DiscountSettingModel = Dict
@dataclass
class PromotionalOfferModel:
startDate: Optional[datetime] = None
endDate: Optional[datetime] = None
discountSetting: Optional[DiscountSettingModel] = None
@classmethod
def from_dict(cls: Type["PromotionalOfferModel"], src: Dict[str, Any]) -> "PromotionalOfferModel":
d = src.copy()
start_date = parse_date(x) if (x := d.pop("startDate", "")) else None
end_date = parse_date(x) if (x := d.pop("endDate", "")) else None
tmp = cls(startDate=start_date, endDate=end_date, discountSetting=d.pop("discountSetting", {}))
tmp.unmapped = d
return tmp
@dataclass
class PromotionalOffersModel:
promotionalOffers: Optional[Tuple[PromotionalOfferModel]] = None
@classmethod
def from_list(cls: Type["PromotionalOffersModel"], src: Dict[str, List]) -> "PromotionalOffersModel":
d = src.copy()
promotional_offers = (
tuple([PromotionalOfferModel.from_dict(y) for y in x]) if (x := d.pop("promotionalOffers", [])) else None
)
tmp = cls(promotionalOffers=promotional_offers)
tmp.unmapped = d
return tmp
@dataclass
class PromotionsModel:
promotionalOffers: Optional[Tuple[PromotionalOffersModel]] = None
upcomingPromotionalOffers: Optional[Tuple[PromotionalOffersModel]] = None
@classmethod
def from_dict(cls: Type["PromotionsModel"], src: Dict[str, Any]) -> "PromotionsModel":
d = src.copy()
promotional_offers = (
tuple([PromotionalOffersModel.from_list(y) for y in x]) if (x := d.pop("promotionalOffers", [])) else None
)
upcoming_promotional_offers = (
tuple([PromotionalOffersModel.from_list(y) for y in x])
if (x := d.pop("upcomingPromotionalOffers", []))
else None
)
tmp = cls(promotionalOffers=promotional_offers, upcomingPromotionalOffers=upcoming_promotional_offers)
tmp.unmapped = d
return tmp
@dataclass @dataclass
class CatalogOfferModel: class CatalogOfferModel:
catalog_ns: Optional[CatalogNamespaceModel] = None catalogNs: Optional[CatalogNamespaceModel] = None
categories: Optional[List[CategoryModel]] = None categories: Optional[List[CategoryModel]] = None
custom_attributes: Optional[List[CustomAttributeModel]] = None customAttributes: Optional[List[CustomAttributeModel]] = None
description: Optional[str] = None description: Optional[str] = None
effective_date: Optional[datetime] = None effectiveDate: Optional[datetime] = None
expiry_date: Optional[datetime] = None expiryDate: Optional[datetime] = None
id: Optional[str] = None id: Optional[str] = None
is_code_redemption_only: Optional[bool] = None isCodeRedemptionOnly: Optional[bool] = None
items: Optional[List[ItemModel]] = None items: Optional[List[ItemModel]] = None
key_images: Optional[KeyImagesModel] = None keyImages: Optional[KeyImagesModel] = None
namespace: Optional[str] = None namespace: Optional[str] = None
offer_mappings: Optional[List[PageSandboxModel]] = None offerMappings: Optional[List[PageSandboxModel]] = None
offer_type: Optional[str] = None offerType: Optional[str] = None
price: Optional[GetPriceResModel] = None price: Optional[GetPriceResModel] = None
product_slug: Optional[str] = None productSlug: Optional[str] = None
promotions: Optional[PromotionsModel] = None promotions: Optional[PromotionsModel] = None
seller: Optional[SellerModel] = None seller: Optional[SellerModel] = None
status: Optional[str] = None status: Optional[str] = None
tags: Optional[List[TagModel]] = None tags: Optional[List[TagModel]] = None
title: Optional[str] = None title: Optional[str] = None
url: Optional[str] = None url: Optional[str] = None
url_slug: Optional[str] = None urlSlug: Optional[str] = None
viewable_date: Optional[datetime] = None viewableDate: Optional[datetime] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
@ -165,31 +233,32 @@ class CatalogOfferModel:
expiry_date = parse_date(x) if (x := d.pop("expiryDate", "")) else None expiry_date = parse_date(x) if (x := d.pop("expiryDate", "")) else None
key_images = KeyImagesModel.from_list(d.pop("keyImages", [])) key_images = KeyImagesModel.from_list(d.pop("keyImages", []))
price = GetPriceResModel.from_dict(x) if (x := d.pop("price", {})) else None price = GetPriceResModel.from_dict(x) if (x := d.pop("price", {})) else None
promotions = PromotionsModel.from_dict(x) if (x := d.pop("promotions", {})) else None
viewable_date = parse_date(x) if (x := d.pop("viewableDate", "")) else None viewable_date = parse_date(x) if (x := d.pop("viewableDate", "")) else None
tmp = cls( tmp = cls(
catalog_ns=d.pop("catalogNs", {}), catalogNs=d.pop("catalogNs", {}),
categories=d.pop("categories", []), categories=d.pop("categories", []),
custom_attributes=d.pop("customAttributes", []), customAttributes=d.pop("customAttributes", []),
description=d.pop("description", ""), description=d.pop("description", ""),
effective_date=effective_date, effectiveDate=effective_date,
expiry_date=expiry_date, expiryDate=expiry_date,
id=d.pop("id", ""), id=d.pop("id", ""),
is_code_redemption_only=d.pop("isCodeRedemptionOnly", None), isCodeRedemptionOnly=d.pop("isCodeRedemptionOnly", None),
items=d.pop("items", []), items=d.pop("items", []),
key_images=key_images, keyImages=key_images,
namespace=d.pop("namespace", ""), namespace=d.pop("namespace", ""),
offer_mappings=d.pop("offerMappings", []), offerMappings=d.pop("offerMappings", []),
offer_type=d.pop("offerType", ""), offerType=d.pop("offerType", ""),
price=price, price=price,
product_slug=d.pop("productSlug", ""), productSlug=d.pop("productSlug", ""),
promotions=d.pop("promotions", {}), promotions=promotions,
seller=d.pop("seller", {}), seller=d.pop("seller", {}),
status=d.pop("status", ""), status=d.pop("status", ""),
tags=d.pop("tags", []), tags=d.pop("tags", []),
title=d.pop("title", ""), title=d.pop("title", ""),
url=d.pop("url", ""), url=d.pop("url", ""),
url_slug=d.pop("urlSlug", ""), urlSlug=d.pop("urlSlug", ""),
viewable_date=viewable_date, viewableDate=viewable_date,
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -200,8 +269,8 @@ class WishlistItemModel:
created: Optional[datetime] = None created: Optional[datetime] = None
id: Optional[str] = None id: Optional[str] = None
namespace: Optional[str] = None namespace: Optional[str] = None
is_first_time: Optional[bool] = None isFirstTime: Optional[bool] = None
offer_id: Optional[str] = None offerId: Optional[str] = None
order: Optional[Any] = None order: Optional[Any] = None
updated: Optional[datetime] = None updated: Optional[datetime] = None
offer: Optional[CatalogOfferModel] = None offer: Optional[CatalogOfferModel] = None
@ -217,8 +286,8 @@ class WishlistItemModel:
created=created, created=created,
id=d.pop("id", ""), id=d.pop("id", ""),
namespace=d.pop("namespace", ""), namespace=d.pop("namespace", ""),
is_first_time=d.pop("isFirstTime", None), isFirstTime=d.pop("isFirstTime", None),
offer_id=d.pop("offerId", ""), offerId=d.pop("offerId", ""),
order=d.pop("order", ""), order=d.pop("order", ""),
updated=updated, updated=updated,
offer=offer, offer=offer,
@ -238,10 +307,7 @@ class PagingModel:
d = src.copy() d = src.copy()
count = d.pop("count", None) count = d.pop("count", None)
total = d.pop("total", None) total = d.pop("total", None)
tmp = cls( tmp = cls(count=count, total=total)
count=count,
total=total,
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -261,26 +327,21 @@ class SearchStoreModel:
elem = CatalogOfferModel.from_dict(item) elem = CatalogOfferModel.from_dict(item)
elements.append(elem) elements.append(elem)
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
tmp = cls( tmp = cls(elements=elements, paging=paging)
elements=elements,
paging=paging,
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@dataclass @dataclass
class CatalogModel: class CatalogModel:
search_store: Optional[SearchStoreModel] = None searchStore: Optional[SearchStoreModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
def from_dict(cls: Type["CatalogModel"], src: Dict[str, Any]) -> "CatalogModel": def from_dict(cls: Type["CatalogModel"], src: Dict[str, Any]) -> "CatalogModel":
d = src.copy() d = src.copy()
search_store = SearchStoreModel.from_dict(x) if (x := d.pop("searchStore", {})) else None search_store = SearchStoreModel.from_dict(x) if (x := d.pop("searchStore", {})) else None
tmp = cls( tmp = cls(searchStore=search_store)
search_store=search_store,
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -300,10 +361,7 @@ class WishlistItemsModel:
elem = WishlistItemModel.from_dict(item) elem = WishlistItemModel.from_dict(item)
elements.append(elem) elements.append(elem)
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
tmp = cls( tmp = cls(elements=elements, paging=paging)
elements=elements,
paging=paging,
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@ -316,16 +374,14 @@ class RemoveFromWishlistModel:
@classmethod @classmethod
def from_dict(cls: Type["RemoveFromWishlistModel"], src: Dict[str, Any]) -> "RemoveFromWishlistModel": def from_dict(cls: Type["RemoveFromWishlistModel"], src: Dict[str, Any]) -> "RemoveFromWishlistModel":
d = src.copy() d = src.copy()
tmp = cls( tmp = cls(success=d.pop("success", None))
success=d.pop("success", None),
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@dataclass @dataclass
class AddToWishlistModel: class AddToWishlistModel:
wishlist_item: Optional[WishlistItemModel] = None wishlistItem: Optional[WishlistItemModel] = None
success: Optional[bool] = None success: Optional[bool] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@ -333,33 +389,26 @@ class AddToWishlistModel:
def from_dict(cls: Type["AddToWishlistModel"], src: Dict[str, Any]) -> "AddToWishlistModel": def from_dict(cls: Type["AddToWishlistModel"], src: Dict[str, Any]) -> "AddToWishlistModel":
d = src.copy() d = src.copy()
wishlist_item = WishlistItemModel.from_dict(x) if (x := d.pop("wishlistItem", {})) else None wishlist_item = WishlistItemModel.from_dict(x) if (x := d.pop("wishlistItem", {})) else None
tmp = cls( tmp = cls(wishlistItem=wishlist_item, success=d.pop("success", None))
wishlist_item=wishlist_item,
success=d.pop("success", None),
)
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp
@dataclass @dataclass
class WishlistModel: class WishlistModel:
wishlist_items: Optional[WishlistItemsModel] = None wishlistItems: Optional[WishlistItemsModel] = None
remove_from_wishlist: Optional[RemoveFromWishlistModel] = None removeFromWishlist: Optional[RemoveFromWishlistModel] = None
add_to_wishlist: Optional[AddToWishlistModel] = None addToWishlist: Optional[AddToWishlistModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
def from_dict(cls: Type["WishlistModel"], src: Dict[str, Any]) -> "WishlistModel": def from_dict(cls: Type["WishlistModel"], src: Dict[str, Any]) -> "WishlistModel":
d = src.copy() d = src.copy()
wishlist_items = WishlistItemsModel.from_dict(x) if (x := d.pop("wishlistItems", {})) else None wishlist_items = WishlistItemsModel.from_dict(x) if (x := d.pop("wishlistItems", {})) else None
remove_from_wishlist = ( remove_from_wishlist = RemoveFromWishlistModel.from_dict(x) if (x := d.pop("removeFromWishlist", {})) else None
RemoveFromWishlistModel.from_dict(x) if (x := d.pop("removeFromWishlist", {})) else None
)
add_to_wishlist = AddToWishlistModel.from_dict(x) if (x := d.pop("addToWishlist", {})) else None add_to_wishlist = AddToWishlistModel.from_dict(x) if (x := d.pop("addToWishlist", {})) else None
tmp = cls( tmp = cls(
wishlist_items=wishlist_items, wishlistItems=wishlist_items, removeFromWishlist=remove_from_wishlist, addToWishlist=add_to_wishlist
remove_from_wishlist=remove_from_wishlist,
add_to_wishlist=add_to_wishlist,
) )
tmp.unmapped = d tmp.unmapped = d
return tmp return tmp

View file

@ -2,4 +2,4 @@ from datetime import datetime, timezone
def parse_date(date: str): def parse_date(date: str):
return datetime.fromisoformat(date[:-1]).replace(tzinfo=timezone.utc) return datetime.fromisoformat(date[:-1]).replace(tzinfo=timezone.utc)

View file

@ -14,26 +14,25 @@ from PyQt5.QtWidgets import (
QFrame, QFrame,
) )
from rare.components.tabs.store.api.models.response import CatalogOfferModel, WishlistItemModel
from rare.widgets.flow_layout import FlowLayout from rare.widgets.flow_layout import FlowLayout
from rare.widgets.side_tab import SideTabContents from rare.widgets.side_tab import SideTabContents
from rare.widgets.sliding_stack import SlidingStackedWidget from rare.widgets.sliding_stack import SlidingStackedWidget
from rare.components.tabs.store.api.models.response import CatalogOfferModel, WishlistItemModel
from .api.models.utils import parse_date
from .store_api import StoreAPI from .store_api import StoreAPI
from .widgets.details import DetailsWidget from .widgets.details import DetailsWidget
from .widgets.items import StoreItemWidget
from .widgets.groups import StoreGroup from .widgets.groups import StoreGroup
from .widgets.items import StoreItemWidget
logger = logging.getLogger("StoreLanding") logger = logging.getLogger("StoreLanding")
class LandingPage(SlidingStackedWidget, SideTabContents): class LandingPage(SlidingStackedWidget, SideTabContents):
def __init__(self, api: StoreAPI, parent=None): def __init__(self, store_api: StoreAPI, parent=None):
super(LandingPage, self).__init__(parent=parent) super(LandingPage, self).__init__(parent=parent)
self.implements_scrollarea = True self.implements_scrollarea = True
self.landing_widget = LandingWidget(api, parent=self) self.landing_widget = LandingWidget(store_api, parent=self)
self.landing_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.landing_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.landing_widget.set_title.connect(self.set_title) self.landing_widget.set_title.connect(self.set_title)
self.landing_widget.show_details.connect(self.show_details) self.landing_widget.show_details.connect(self.show_details)
@ -43,7 +42,7 @@ class LandingPage(SlidingStackedWidget, SideTabContents):
self.landing_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain) self.landing_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.landing_scroll.setWidget(self.landing_widget) self.landing_scroll.setWidget(self.landing_widget)
self.details_widget = DetailsWidget([], api, parent=self) self.details_widget = DetailsWidget([], store_api, parent=self)
self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.details_widget.set_title.connect(self.set_title) self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main) self.details_widget.back_clicked.connect(self.show_main)
@ -83,7 +82,7 @@ class LandingWidget(QWidget, SideTabContents):
self.discounts_group = StoreGroup(self.tr("Wishlist discounts"), layout=FlowLayout, parent=self) self.discounts_group = StoreGroup(self.tr("Wishlist discounts"), layout=FlowLayout, parent=self)
self.discounts_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.discounts_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.games_group = StoreGroup(self.tr("Games"), FlowLayout, self) self.games_group = StoreGroup(self.tr("Free to play"), FlowLayout, self)
self.games_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.games_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.games_group.loading(False) self.games_group.loading(False)
self.games_group.setVisible(True) self.games_group.setVisible(True)
@ -97,8 +96,8 @@ class LandingWidget(QWidget, SideTabContents):
def showEvent(self, a0: QShowEvent) -> None: def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous(): if a0.spontaneous():
return super().showEvent(a0) return super().showEvent(a0)
self.api.get_free_games(self.__add_free) self.api.get_free(self.__update_free_games)
self.api.get_wishlist(self.__add_discounts) self.api.get_wishlist(self.__update_wishlist_discounts)
return super().showEvent(a0) return super().showEvent(a0)
def hideEvent(self, a0: QHideEvent) -> None: def hideEvent(self, a0: QHideEvent) -> None:
@ -107,28 +106,20 @@ class LandingWidget(QWidget, SideTabContents):
# TODO: Implement tab unloading # TODO: Implement tab unloading
return super().hideEvent(a0) return super().hideEvent(a0)
def __add_discounts(self, wishlist: List[WishlistItemModel]): def __update_wishlist_discounts(self, wishlist: List[WishlistItemModel]):
for w in self.discounts_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly): for w in self.discounts_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.discounts_group.layout().removeWidget(w) self.discounts_group.layout().removeWidget(w)
w.deleteLater() w.deleteLater()
discounts = 0 for item in wishlist:
for game in wishlist: if item.offer.price.totalPrice.discount > 0:
if not game: w = StoreItemWidget(self.api.cached_manager, item.offer)
continue w.show_details.connect(self.show_details)
try: self.discounts_group.layout().addWidget(w)
if game.offer.price.total_price["discount"] > 0: self.discounts_group.setVisible(bool(wishlist))
w = StoreItemWidget(self.api.cached_manager, game.offer)
w.show_details.connect(self.show_details)
self.discounts_group.layout().addWidget(w)
discounts += 1
except Exception as e:
logger.warning(f"{game} {e}")
continue
# self.discounts_group.setVisible(discounts > 0)
self.discounts_group.loading(False) self.discounts_group.loading(False)
def __add_free(self, free_games: List[CatalogOfferModel]): def __update_free_games(self, free_games: List[CatalogOfferModel]):
for w in self.free_games_now.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly): for w in self.free_games_now.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.free_games_now.layout().removeWidget(w) self.free_games_now.layout().removeWidget(w)
w.deleteLater() w.deleteLater()
@ -140,56 +131,38 @@ class LandingWidget(QWidget, SideTabContents):
date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc) date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
free_now = [] free_now = []
free_next = [] free_next = []
for game in free_games: for item in free_games:
try: try:
if ( if item.price.totalPrice.discountPrice == 0:
game.price.total_price["fmtPrice"]["discountPrice"] == "0" free_now.append(item)
and game.price.total_price["fmtPrice"]["originalPrice"]
!= game.price.total_price["fmtPrice"]["discountPrice"]
):
free_now.append(game)
continue continue
if item.title == "Mystery Game":
if game.title == "Mystery Game": free_next.append(item)
free_next.append(game)
continue continue
except KeyError as e: except KeyError as e:
logger.warning(str(e)) logger.warning(str(e))
try: if not item.promotions.promotionalOffers:
# parse datetime to check if game is next week or now start_date = item.promotions.upcomingPromotionalOffers[0].promotionalOffers[0].startDate
try: else:
start_date = parse_date( start_date = item.promotions.promotionalOffers[0].promotionalOffers[0].startDate
game.promotions["upcomingPromotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception:
try:
start_date = parse_date(
game.promotions["promotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception as e:
continue
except TypeError:
print("type error")
continue
if start_date > date: if start_date > date:
free_next.append(game) free_next.append(item)
# free games now # free games now
self.free_games_now.setVisible(bool(len(free_now))) self.free_games_now.setVisible(bool(free_now))
for game in free_now: for item in free_now:
w = StoreItemWidget(self.api.cached_manager, game) w = StoreItemWidget(self.api.cached_manager, item)
w.show_details.connect(self.show_details) w.show_details.connect(self.show_details)
self.free_games_now.layout().addWidget(w) self.free_games_now.layout().addWidget(w)
self.free_games_now.loading(False) self.free_games_now.loading(False)
# free games next week # free games next week
self.free_games_next.setVisible(bool(len(free_next))) self.free_games_next.setVisible(bool(free_next))
for game in free_next: for item in free_next:
w = StoreItemWidget(self.api.cached_manager, game) w = StoreItemWidget(self.api.cached_manager, item)
if game.title != "Mystery Game": if item.title != "Mystery Game":
w.show_details.connect(self.show_details) w.show_details.connect(self.show_details)
self.free_games_next.layout().addWidget(w) self.free_games_next.layout().addWidget(w)
self.free_games_next.loading(False) self.free_games_next.loading(False)

View file

@ -26,16 +26,16 @@ logger = logging.getLogger("Shop")
class SearchPage(SlidingStackedWidget, SideTabContents): class SearchPage(SlidingStackedWidget, SideTabContents):
def __init__(self, core, api: StoreAPI, parent=None): def __init__(self, store_api: StoreAPI, parent=None):
super(SearchPage, self).__init__(parent=parent) super(SearchPage, self).__init__(parent=parent)
self.implements_scrollarea = True self.implements_scrollarea = True
self.search_widget = SearchWidget(core, api, parent=self) self.search_widget = SearchWidget(store_api, parent=self)
self.search_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.search_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.search_widget.set_title.connect(self.set_title) self.search_widget.set_title.connect(self.set_title)
self.search_widget.show_details.connect(self.show_details) self.search_widget.show_details.connect(self.show_details)
self.details_widget = DetailsWidget([], api, parent=self) self.details_widget = DetailsWidget([], store_api, parent=self)
self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.details_widget.set_title.connect(self.set_title) self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main) self.details_widget.back_clicked.connect(self.show_main)
@ -58,27 +58,25 @@ class SearchPage(SlidingStackedWidget, SideTabContents):
class SearchWidget(QWidget, SideTabContents): class SearchWidget(QWidget, SideTabContents):
show_details = pyqtSignal(CatalogOfferModel) show_details = pyqtSignal(CatalogOfferModel)
def __init__(self, core: LegendaryCore, api: StoreAPI, parent=None): def __init__(self, store_api: StoreAPI, parent=None):
super(SearchWidget, self).__init__(parent=parent) super(SearchWidget, self).__init__(parent=parent)
self.implements_scrollarea = True self.implements_scrollarea = True
self.ui = Ui_SearchWidget() self.ui = Ui_SearchWidget()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.main_layout.setContentsMargins(0, 0, 3, 0) self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
self.core = core self.store_api = store_api
self.api_core = api
self.price = "" self.price = ""
self.tags = [] self.tags = []
self.types = [] self.types = []
self.update_games_allowed = True self.update_games_allowed = True
self.free_game_widgets = []
self.active_search_request = False self.active_search_request = False
self.next_search = "" self.next_search = ""
self.wishlist: List = [] self.wishlist: List = []
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Games")) self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Games"))
self.results_scrollarea = ResultsWidget(self.api_core, self) self.results_scrollarea = ResultsWidget(self.store_api, self)
self.results_scrollarea.show_details.connect(self.show_details) self.results_scrollarea.show_details.connect(self.show_details)
self.ui.left_layout.addWidget(self.search_bar) self.ui.left_layout.addWidget(self.search_bar)
@ -188,8 +186,8 @@ class SearchWidget(QWidget, SideTabContents):
self.games_group.loading(True) self.games_group.loading(True)
browse_model = SearchStoreQuery( browse_model = SearchStoreQuery(
language=self.core.language_code, language=self.store_api.language_code,
country=self.core.country_code, country=self.store_api.country_code,
count=20, count=20,
price_range=self.price, price_range=self.price,
on_sale=self.ui.on_discount.isChecked(), on_sale=self.ui.on_discount.isChecked(),
@ -198,7 +196,7 @@ class SearchWidget(QWidget, SideTabContents):
if self.types: if self.types:
browse_model.category = "|".join(self.types) browse_model.category = "|".join(self.types)
self.api_core.browse_games(browse_model, self.show_games) self.store_api.browse_games(browse_model, self.show_games)
class CheckBox(QCheckBox): class CheckBox(QCheckBox):

View file

@ -20,7 +20,7 @@ from .api.models.response import (
CatalogOfferModel, CatalogOfferModel,
) )
logger = getLogger("ShopAPICore") logger = getLogger("StoreAPI")
graphql_url = "https://graphql.epicgames.com/graphql" graphql_url = "https://graphql.epicgames.com/graphql"
@ -46,7 +46,7 @@ class StoreAPI(QObject):
self.browse_active = False self.browse_active = False
self.next_browse_request = tuple(()) self.next_browse_request = tuple(())
def get_free_games(self, handle_func: callable): def get_free(self, handle_func: callable):
url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions" url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions"
params = { params = {
"locale": self.locale, "locale": self.locale,
@ -59,7 +59,7 @@ class StoreAPI(QObject):
def __handle_free_games(data, handle_func): def __handle_free_games(data, handle_func):
try: try:
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
results: List[CatalogOfferModel] = response.data.catalog.search_store.elements results: List[CatalogOfferModel] = response.data.catalog.searchStore.elements
handle_func(results) handle_func(results)
except KeyError as e: except KeyError as e:
if DEBUG(): if DEBUG():
@ -94,7 +94,7 @@ class StoreAPI(QObject):
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
if response.errors: if response.errors:
logger.error(response.errors) logger.error(response.errors)
handle_func(response.data.wishlist.wishlist_items.elements) handle_func(response.data.wishlist.wishlistItems.elements)
except KeyError as e: except KeyError as e:
if DEBUG(): if DEBUG():
raise e raise e
@ -132,7 +132,7 @@ class StoreAPI(QObject):
def __handle_search(data, handler): def __handle_search(data, handler):
try: try:
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
handler(response.data.catalog.search_store.elements) handler(response.data.catalog.searchStore.elements)
except KeyError as e: except KeyError as e:
logger.error(str(e)) logger.error(str(e))
if DEBUG(): if DEBUG():
@ -167,7 +167,7 @@ class StoreAPI(QObject):
if not self.next_browse_request: if not self.next_browse_request:
try: try:
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
handle_func(response.data.catalog.search_store.elements) handle_func(response.data.catalog.searchStore.elements)
except KeyError as e: except KeyError as e:
if DEBUG(): if DEBUG():
raise e raise e
@ -233,7 +233,7 @@ class StoreAPI(QObject):
# debug.exec() # debug.exec()
try: try:
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
data = response.data.wishlist.add_to_wishlist data = response.data.wishlist.addToWishlist
handle_func(data.success) handle_func(data.success)
except Exception as e: except Exception as e:
if DEBUG(): if DEBUG():
@ -259,7 +259,7 @@ class StoreAPI(QObject):
# debug.exec() # debug.exec()
try: try:
response = ResponseModel.from_dict(data) response = ResponseModel.from_dict(data)
data = response.data.wishlist.remove_from_wishlist data = response.data.wishlist.removeFromWishlist
handle_func(data.success) handle_func(data.success)
except Exception as e: except Exception as e:
if DEBUG(): if DEBUG():

View file

@ -1,5 +1,5 @@
import logging import logging
from typing import List from typing import List, Dict
from PyQt5.QtCore import Qt, QUrl, pyqtSignal from PyQt5.QtCore import Qt, QUrl, pyqtSignal
from PyQt5.QtGui import QFont, QDesktopServices, QKeyEvent from PyQt5.QtGui import QFont, QDesktopServices, QKeyEvent
@ -14,6 +14,7 @@ from PyQt5.QtWidgets import (
from rare.components.tabs.store.api.debug import DebugDialog from rare.components.tabs.store.api.debug import DebugDialog
from rare.components.tabs.store.api.models.diesel import DieselProduct, DieselProductDetail, DieselSystemDetail from rare.components.tabs.store.api.models.diesel import DieselProduct, DieselProductDetail, DieselSystemDetail
from rare.components.tabs.store.api.models.response import CatalogOfferModel from rare.components.tabs.store.api.models.response import CatalogOfferModel
from rare.components.tabs.store.store_api import StoreAPI
from rare.models.image import ImageSize from rare.models.image import ImageSize
from rare.ui.components.tabs.store.details import Ui_DetailsWidget from rare.ui.components.tabs.store.details import Ui_DetailsWidget
from rare.utils.misc import icon from rare.utils.misc import icon
@ -28,7 +29,7 @@ class DetailsWidget(QWidget, SideTabContents):
back_clicked: pyqtSignal = pyqtSignal() back_clicked: pyqtSignal = pyqtSignal()
# TODO Design # TODO Design
def __init__(self, installed_titles: list, api_core, parent=None): def __init__(self, installed: List, store_api: StoreAPI, parent=None):
super(DetailsWidget, self).__init__(parent=parent) super(DetailsWidget, self).__init__(parent=parent)
self.implements_scrollarea = True self.implements_scrollarea = True
@ -36,13 +37,11 @@ class DetailsWidget(QWidget, SideTabContents):
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.main_layout.setContentsMargins(0, 0, 3, 0) self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
# self.core = LegendaryCoreSingleton() self.store_api = store_api
self.api_core = api_core self.installed = installed
self.installed = installed_titles self.catalog_offer: CatalogOfferModel = None
self.offer: CatalogOfferModel = None
self.data: dict = {}
self.image = LoadingImageWidget(api_core.cached_manager, self) self.image = LoadingImageWidget(store_api.cached_manager, self)
self.image.setFixedSize(ImageSize.Display) self.image.setFixedSize(ImageSize.Display)
self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop) self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
self.ui.left_layout.setAlignment(Qt.AlignTop) self.ui.left_layout.setAlignment(Qt.AlignTop)
@ -53,7 +52,7 @@ class DetailsWidget(QWidget, SideTabContents):
self.in_wishlist = False self.in_wishlist = False
self.wishlist = [] self.wishlist = []
self.requirements_tabs: SideTabWidget = SideTabWidget(parent=self.ui.requirements_frame) self.requirements_tabs = SideTabWidget(parent=self.ui.requirements_frame)
self.requirements_tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.requirements_tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.ui.requirements_layout.addWidget(self.requirements_tabs) self.ui.requirements_layout.addWidget(self.requirements_tabs)
@ -78,15 +77,17 @@ class DetailsWidget(QWidget, SideTabContents):
self.ui.title.setText(offer.title) self.ui.title.setText(offer.title)
self.title_str = offer.title self.title_str = offer.title
self.id_str = offer.id self.id_str = offer.id
self.api_core.get_wishlist(self.handle_wishlist_update) self.store_api.get_wishlist(self.handle_wishlist_update)
# lk: delete tabs in reverse order because indices are updated on deletion # lk: delete tabs in reverse order because indices are updated on deletion
while self.requirements_tabs.count(): while self.requirements_tabs.count():
self.requirements_tabs.widget(0).deleteLater() self.requirements_tabs.widget(0).deleteLater()
self.requirements_tabs.removeTab(0) self.requirements_tabs.removeTab(0)
self.requirements_tabs.clear() self.requirements_tabs.clear()
slug = offer.product_slug
slug = offer.productSlug
if not slug: if not slug:
for mapping in offer.offer_mappings: for mapping in offer.offerMappings:
if mapping["pageType"] == "productHome": if mapping["pageType"] == "productHome":
slug = mapping["pageSlug"] slug = mapping["pageSlug"]
break break
@ -114,24 +115,24 @@ class DetailsWidget(QWidget, SideTabContents):
# init API request # init API request
if slug: if slug:
self.api_core.get_game_config_cms(offer.product_slug, is_bundle, self.data_received) self.store_api.get_game_config_cms(offer.productSlug, is_bundle, self.data_received)
# else: # else:
# self.data_received({}) # self.data_received({})
self.offer = offer self.catalog_offer = offer
def add_to_wishlist(self): def add_to_wishlist(self):
if not self.in_wishlist: if not self.in_wishlist:
self.api_core.add_to_wishlist( self.store_api.add_to_wishlist(
self.offer.namespace, self.catalog_offer.namespace,
self.offer.id, self.catalog_offer.id,
lambda success: self.ui.wishlist_button.setText(self.tr("Remove from wishlist")) lambda success: self.ui.wishlist_button.setText(self.tr("Remove from wishlist"))
if success if success
else self.ui.wishlist_button.setText("Something went wrong") else self.ui.wishlist_button.setText("Something went wrong")
) )
else: else:
self.api_core.remove_from_wishlist( self.store_api.remove_from_wishlist(
self.offer.namespace, self.catalog_offer.namespace,
self.offer.id, self.catalog_offer.id,
lambda success: self.ui.wishlist_button.setText(self.tr("Add to wishlist")) lambda success: self.ui.wishlist_button.setText(self.tr("Add to wishlist"))
if success if success
else self.ui.wishlist_button.setText("Something went wrong"), else self.ui.wishlist_button.setText("Something went wrong"),
@ -146,34 +147,16 @@ class DetailsWidget(QWidget, SideTabContents):
except Exception as e: except Exception as e:
raise e raise e
logger.error(str(e)) logger.error(str(e))
self.price.setText("Error")
self.requirements_tabs.setEnabled(False)
for img in self.data.get("keyImages"):
if img["type"] in [
"DieselStoreFrontWide",
"OfferImageTall",
"VaultClosed",
"ProductLogo",
]:
self.image.fetchPixmap(img["url"])
break
self.price.setText("")
self.discount_price.setText("")
self.social_group.setEnabled(False)
self.tags.setText("")
self.dev.setText(self.data.get("seller", {}).get("name", ""))
return
# self.title.setText(self.game.title)
self.ui.price.setFont(QFont()) self.ui.price.setFont(self.font())
price = self.offer.price.total_price["fmtPrice"]["originalPrice"] price = self.catalog_offer.price.totalPrice.fmtPrice["originalPrice"]
discount_price = self.offer.price.total_price["fmtPrice"]["discountPrice"] discount_price = self.catalog_offer.price.totalPrice.fmtPrice["discountPrice"]
if price == "0" or price == 0: if price == "0" or price == 0:
self.ui.price.setText(self.tr("Free")) self.ui.price.setText(self.tr("Free"))
else: else:
self.ui.price.setText(price) self.ui.price.setText(price)
if price != discount_price: if price != discount_price:
font = QFont() font = self.font()
font.setStrikeOut(True) font.setStrikeOut(True)
self.ui.price.setFont(font) self.ui.price.setFont(font)
self.ui.discount_price.setText( self.ui.discount_price.setText(
@ -189,18 +172,11 @@ class DetailsWidget(QWidget, SideTabContents):
if requirements and requirements.systems: if requirements and requirements.systems:
for system in requirements.systems: for system in requirements.systems:
req_widget = RequirementsWidget(system, self.requirements_tabs) req_widget = RequirementsWidget(system, self.requirements_tabs)
self.requirements_tabs.addTab(req_widget, system.system_type) self.requirements_tabs.addTab(req_widget, system.systemType)
# self.req_group_box.layout().addWidget(req_tabs)
# self.req_group_box.layout().setAlignment(Qt.AlignTop)
# else:
# self.req_group_box.layout().addWidget(
# QLabel(self.tr("Could not get requirements"))
# )
self.ui.requirements_frame.setVisible(True)
else: else:
self.ui.requirements_frame.setVisible(False) self.ui.requirements_frame.setVisible(False)
key_images = self.offer.key_images key_images = self.catalog_offer.keyImages
img_url = key_images.for_dimensions(self.image.size().width(), self.image.size().height()) img_url = key_images.for_dimensions(self.image.size().width(), self.image.size().height())
self.image.fetchPixmap(img_url.url) self.image.fetchPixmap(img_url.url)
@ -223,7 +199,7 @@ class DetailsWidget(QWidget, SideTabContents):
self.ui.social_layout.removeWidget(b) self.ui.social_layout.removeWidget(b)
b.deleteLater() b.deleteLater()
links = product_data.social_links links = product_data.socialLinks
link_count = 0 link_count = 0
for name, url in links.items(): for name, url in links.items():
if name == "_type": if name == "_type":
@ -252,8 +228,7 @@ class DetailsWidget(QWidget, SideTabContents):
# self.wishlist.append(game["offer"]["title"]) # self.wishlist.append(game["offer"]["title"])
def button_clicked(self): def button_clicked(self):
return QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{self.store_api.language_code}/p/{self.slug}"))
QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{self.core.language_code}/p/{self.slug}"))
def keyPressEvent(self, a0: QKeyEvent): def keyPressEvent(self, a0: QKeyEvent):
if a0.key() == Qt.Key_Escape: if a0.key() == Qt.Key_Escape:

View file

@ -11,7 +11,7 @@ from rare.utils.misc import qta_icon
from rare.utils.qt_requests import QtRequests from rare.utils.qt_requests import QtRequests
from .image import LoadingImageWidget from .image import LoadingImageWidget
logger = logging.getLogger("GameWidgets") logger = logging.getLogger("StoreWidgets")
class ItemWidget(LoadingImageWidget): class ItemWidget(LoadingImageWidget):
@ -46,15 +46,15 @@ class StoreItemWidget(ItemWidget):
return return
self.ui.title_label.setText(game.title) self.ui.title_label.setText(game.title)
for attr in game.custom_attributes: for attr in game.customAttributes:
if attr["key"] == "developerName": if attr["key"] == "developerName":
developer = attr["value"] developer = attr["value"]
break break
else: else:
developer = game.seller["name"] developer = game.seller["name"]
self.ui.developer_label.setText(developer) self.ui.developer_label.setText(developer)
price = game.price.total_price["fmtPrice"]["originalPrice"] price = game.price.totalPrice.fmtPrice["originalPrice"]
discount_price = game.price.total_price["fmtPrice"]["discountPrice"] discount_price = game.price.totalPrice.fmtPrice["discountPrice"]
self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}') self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}')
if price != discount_price: if price != discount_price:
font = self.ui.price_label.font() font = self.ui.price_label.font()
@ -64,7 +64,7 @@ class StoreItemWidget(ItemWidget):
else: else:
self.ui.discount_label.setVisible(False) self.ui.discount_label.setVisible(False)
key_images = game.key_images key_images = game.keyImages
self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url) self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url)
# for img in json_info["keyImages"]: # for img in json_info["keyImages"]:
@ -83,13 +83,13 @@ class ResultsItemWidget(ItemWidget):
self.setFixedSize(ImageSize.Display) self.setFixedSize(ImageSize.Display)
self.ui.setupUi(self) self.ui.setupUi(self)
key_images = catalog_game.key_images key_images = catalog_game.keyImages
self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url) self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url)
self.ui.title_label.setText(catalog_game.title) self.ui.title_label.setText(catalog_game.title)
price = catalog_game.price.total_price["fmtPrice"]["originalPrice"] price = catalog_game.price.totalPrice.fmtPrice["originalPrice"]
discount_price = catalog_game.price.total_price["fmtPrice"]["discountPrice"] discount_price = catalog_game.price.totalPrice.fmtPrice["discountPrice"]
self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}') self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}')
if price != discount_price: if price != discount_price:
font = self.ui.price_label.font() font = self.ui.price_label.font()
@ -108,14 +108,14 @@ class WishlistItemWidget(ItemWidget):
super(WishlistItemWidget, self).__init__(manager, catalog_game, parent=parent) super(WishlistItemWidget, self).__init__(manager, catalog_game, parent=parent)
self.setFixedSize(ImageSize.DisplayWide) self.setFixedSize(ImageSize.DisplayWide)
self.ui.setupUi(self) self.ui.setupUi(self)
for attr in catalog_game.custom_attributes: for attr in catalog_game.customAttributes:
if attr["key"] == "developerName": if attr["key"] == "developerName":
developer = attr["value"] developer = attr["value"]
break break
else: else:
developer = catalog_game.seller["name"] developer = catalog_game.seller["name"]
original_price = catalog_game.price.total_price["fmtPrice"]["originalPrice"] original_price = catalog_game.price.totalPrice.fmtPrice["originalPrice"]
discount_price = catalog_game.price.total_price["fmtPrice"]["discountPrice"] discount_price = catalog_game.price.totalPrice.fmtPrice["discountPrice"]
self.ui.title_label.setText(catalog_game.title) self.ui.title_label.setText(catalog_game.title)
self.ui.developer_label.setText(developer) self.ui.developer_label.setText(developer)
@ -127,7 +127,7 @@ class WishlistItemWidget(ItemWidget):
self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}') self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}')
else: else:
self.ui.discount_label.setVisible(False) self.ui.discount_label.setVisible(False)
key_images = catalog_game.key_images key_images = catalog_game.keyImages
self.fetchPixmap( self.fetchPixmap(
key_images.for_dimensions(self.width(), self.height()).url key_images.for_dimensions(self.width(), self.height()).url
) )

View file

@ -116,13 +116,13 @@ class WishlistWidget(QWidget, SideTabContents):
func = lambda x: x.catalog_game.title func = lambda x: x.catalog_game.title
reverse = self.ui.reverse.isChecked() reverse = self.ui.reverse.isChecked()
elif sort == 1: elif sort == 1:
func = lambda x: x.catalog_game.price.total_price["fmtPrice"]["discountPrice"] func = lambda x: x.catalog_game.price.totalPrice["fmtPrice"]["discountPrice"]
reverse = self.ui.reverse.isChecked() reverse = self.ui.reverse.isChecked()
elif sort == 2: elif sort == 2:
func = lambda x: x.catalog_game.seller["name"] func = lambda x: x.catalog_game.seller["name"]
reverse = self.ui.reverse.isChecked() reverse = self.ui.reverse.isChecked()
elif sort == 3: elif sort == 3:
func = lambda x: 1 - (x.catalog_game.price.total_price["discountPrice"] / x.catalog_game.price.total_price["originalPrice"]) func = lambda x: 1 - (x.catalog_game.price.totalPrice["discountPrice"] / x.catalog_game.price.totalPrice["originalPrice"])
reverse = not self.ui.reverse.isChecked() reverse = not self.ui.reverse.isChecked()
else: else:
func = lambda x: x.catalog_game.title func = lambda x: x.catalog_game.title

View file

@ -18,6 +18,8 @@ class Ui_DetailsWidget(object):
DetailsWidget.setWindowTitle("DetailsWidget") DetailsWidget.setWindowTitle("DetailsWidget")
self.main_layout = QtWidgets.QHBoxLayout(DetailsWidget) self.main_layout = QtWidgets.QHBoxLayout(DetailsWidget)
self.main_layout.setObjectName("main_layout") self.main_layout.setObjectName("main_layout")
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.back_button = QtWidgets.QPushButton(DetailsWidget) self.back_button = QtWidgets.QPushButton(DetailsWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -28,9 +30,7 @@ class Ui_DetailsWidget(object):
self.back_button.setIconSize(QtCore.QSize(32, 32)) self.back_button.setIconSize(QtCore.QSize(32, 32))
self.back_button.setFlat(True) self.back_button.setFlat(True)
self.back_button.setObjectName("back_button") self.back_button.setObjectName("back_button")
self.main_layout.addWidget(self.back_button) self.left_layout.addWidget(self.back_button)
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.main_layout.addLayout(self.left_layout) self.main_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout() self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout") self.right_layout.setObjectName("right_layout")
@ -176,7 +176,7 @@ class Ui_DetailsWidget(object):
self.description_label.setObjectName("description_label") self.description_label.setObjectName("description_label")
self.right_layout.addWidget(self.description_label) self.right_layout.addWidget(self.description_label)
self.main_layout.addLayout(self.right_layout) self.main_layout.addLayout(self.right_layout)
self.main_layout.setStretch(2, 1) self.main_layout.setStretch(1, 1)
self.retranslateUi(DetailsWidget) self.retranslateUi(DetailsWidget)

View file

@ -13,31 +13,32 @@
<property name="windowTitle"> <property name="windowTitle">
<string notr="true">DetailsWidget</string> <string notr="true">DetailsWidget</string>
</property> </property>
<layout class="QHBoxLayout" name="main_layout" stretch="0,0,1"> <layout class="QHBoxLayout" name="main_layout" stretch="0,1">
<item> <item>
<widget class="QPushButton" name="back_button"> <layout class="QVBoxLayout" name="left_layout">
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Fixed" vsizetype="Expanding"> <widget class="QPushButton" name="back_button">
<horstretch>0</horstretch> <property name="sizePolicy">
<verstretch>0</verstretch> <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
</sizepolicy> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="text"> </sizepolicy>
<string notr="true"/> </property>
</property> <property name="text">
<property name="iconSize"> <string notr="true"/>
<size> </property>
<width>32</width> <property name="iconSize">
<height>32</height> <size>
</size> <width>32</width>
</property> <height>32</height>
<property name="flat"> </size>
<bool>true</bool> </property>
</property> <property name="flat">
</widget> <bool>true</bool>
</item> </property>
<item> </widget>
<layout class="QVBoxLayout" name="left_layout"/> </item>
</layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="right_layout"> <layout class="QVBoxLayout" name="right_layout">

View file

@ -5,7 +5,7 @@ from typing import Callable, Dict, TypeVar, List, Tuple
from typing import Union from typing import Union
import orjson import orjson
from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QUrlQuery, pyqtSlot from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QUrlQuery, pyqtSlot, QJsonDocument
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QNetworkDiskCache from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QNetworkDiskCache
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36" USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"