1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Store WIP

This commit is contained in:
loathingKernel 2023-09-23 20:24:28 +03:00
parent ecc036bd46
commit 14e842e886
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
16 changed files with 375 additions and 650 deletions

View file

@ -1,12 +1,11 @@
from legendary.core import LegendaryCore from legendary.core import LegendaryCore
from rare.shared import RareCore
from rare.utils.paths import cache_dir from rare.utils.paths import cache_dir
from rare.widgets.side_tab import SideTabWidget from rare.widgets.side_tab import SideTabWidget
from .api.models.response import CatalogOfferModel
from .game_info import ShopGameInfo from .game_info import ShopGameInfo
from .search_results import SearchResults from .search_results import SearchResults
from .shop_api_core import ShopApiCore from .shop_api_core import ShopApiCore
from .api.models.response import CatalogOfferModel
from .shop_widget import ShopWidget from .shop_widget import ShopWidget
from .wishlist import WishlistWidget, Wishlist from .wishlist import WishlistWidget, Wishlist
@ -28,11 +27,11 @@ class StoreTab(SideTabWidget):
self.shop = ShopWidget(cache_dir(), self.core, self.api_core, parent=self) self.shop = ShopWidget(cache_dir(), self.core, self.api_core, parent=self)
self.shop_index = self.addTab(self.shop, self.tr("Store")) self.shop_index = self.addTab(self.shop, self.tr("Store"))
self.shop.show_game.connect(self.show_game) self.shop.show_game.connect(self.show_game)
self.shop.show_info.connect(self.show_search) # self.shop.show_info.connect(self.show_search)
self.search = SearchResults(self.api_core, parent=self) # self.search = SearchResults(self.api_core, parent=self)
self.search_index = self.addTab(self.search, self.tr("Search"), self.tr("Results")) # self.search_index = self.addTab(self.search, self.tr("Search"), self.tr("Results"))
self.search.show_info.connect(self.show_game) # self.search.show_info.connect(self.show_game)
# self.search.back_button.clicked.connect(lambda: self.setCurrentIndex(self.shop_index)) # self.search.back_button.clicked.connect(lambda: self.setCurrentIndex(self.shop_index))
self.info = ShopGameInfo( self.info = ShopGameInfo(
@ -67,6 +66,6 @@ class StoreTab(SideTabWidget):
self.info.update_game(data) self.info.update_game(data)
self.setCurrentIndex(self.info_index) self.setCurrentIndex(self.info_index)
def show_search(self, text: str): # def show_search(self, text: str):
self.search.load_results(text) # self.search.load_results(text)
self.setCurrentIndex(self.search_index) # self.setCurrentIndex(self.search_index)

View file

@ -22,9 +22,9 @@ class StoreWindow(QDialog):
if __name__ == "__main__": if __name__ == "__main__":
from rare.utils.misc import set_style_sheet
import rare.resources.static_css import rare.resources.static_css
import rare.resources.stylesheets.RareStyle import rare.resources.stylesheets.RareStyle
from rare.utils.misc import set_style_sheet
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setApplicationName("Rare") app.setApplicationName("Rare")

View file

@ -1,7 +1,7 @@
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QTreeView, QDialog, QVBoxLayout from PyQt5.QtWidgets import QTreeView, QDialog, QVBoxLayout
from utils.json_formatter import QJsonModel from rare.utils.json_formatter import QJsonModel
class DebugView(QTreeView): class DebugView(QTreeView):

View file

@ -38,4 +38,39 @@ type LineOfferRes {
type GetPriceRes { type GetPriceRes {
totalPrice: TotalPrice totalPrice: TotalPrice
lineOffers: [LineOfferRes] lineOffers: [LineOfferRes]
}
type Image {
type: String
url: String
alt: String
}
type StorePageMapping {
cmsSlug: String
offerId: ID
prePurchaseOfferId: ID
}
type PageSandboxModel {
pageSlug: String
pageType: String
productId: ID
sandboxId: ID
createdDate: Date
updatedDate: Date
deletedDate: Date
mappings: [StorePageMapping]
}
type CatalogNamespace {
parent: ID
displayName: String
store: String
mappings: [PageSandboxModel]
}
type CatalogItem {
id: ID
namespace: ID
} }

View file

@ -6,11 +6,11 @@ from typing import List
@dataclass @dataclass
class SearchDateRange: class SearchDateRange:
start_date: datetime = datetime(year=1990, month=1, day=1, tzinfo=timezone.utc) start_date: datetime = datetime(year=1990, month=1, day=1, tzinfo=timezone.utc)
end_date: datetime = datetime.utcnow() end_date: datetime = datetime.utcnow().replace(tzinfo=timezone.utc)
def __str__(self): def __str__(self):
def fmt_date(date: datetime) -> str: def fmt_date(date: datetime) -> str:
# lk: The formatting accepted by the GraphQL API is either '%Y-%m-%dT%H:%M:%S.000Z' or '%Y-%m-%dT' # lk: The formatting accepted by the GraphQL API is either '%Y-%m-%dT%H:%M:%S.000Z' or '%Y-%m-%d'
return datetime.strftime(date, '%Y-%m-%dT%H:%M:%S.000Z') return datetime.strftime(date, '%Y-%m-%dT%H:%M:%S.000Z')
return f"[{fmt_date(self.start_date)},{fmt_date(self.end_date)}]" return f"[{fmt_date(self.start_date)},{fmt_date(self.end_date)}]"

View file

@ -1,8 +1,10 @@
import logging import logging
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime, timezone from datetime import datetime
from typing import List, Dict, Any, Type, Optional from typing import List, Dict, Any, Type, Optional
from .utils import parse_date
logger = logging.getLogger("StoreApiModels") logger = logging.getLogger("StoreApiModels")
# lk: Typing overloads for unimplemented types # lk: Typing overloads for unimplemented types
@ -13,171 +15,11 @@ CategoryModel = Dict
CustomAttributeModel = Dict CustomAttributeModel = Dict
ItemModel = Dict ItemModel = Dict
SellerModel = Dict SellerModel = Dict
OfferMappingModel = Dict PageSandboxModel = Dict
TagModel = Dict TagModel = Dict
PromotionsModel = Dict PromotionsModel = Dict
def parse_date(date: str):
return datetime.fromisoformat(date[:-1]).replace(tzinfo=timezone.utc)
@dataclass
class DieselSystemDetailItem:
p_type: Optional[str] = None
minimum: Optional[str] = None
recommended: Optional[str] = None
title: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetailItem"], src: Dict[str, Any]) -> "DieselSystemDetailItem":
d = src.copy()
tmp = cls(
p_type=d.pop("_type", ""),
minimum=d.pop("minimum", ""),
recommended=d.pop("recommended", ""),
title=d.pop("title", ""),
)
tmp.unmapped = d
return tmp
@dataclass
class DieselSystemDetail:
p_type: Optional[str] = None
details: Optional[List[DieselSystemDetailItem]] = None
system_type: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetail"], src: Dict[str, Any]) -> "DieselSystemDetail":
d = src.copy()
_details = d.pop("details", [])
details = [] if _details else None
for item in _details:
detail = DieselSystemDetailItem.from_dict(item)
details.append(detail)
tmp = cls(
p_type=d.pop("_type", ""),
details=details,
system_type=d.pop("systemType", ""),
)
tmp.unmapped = d
return tmp
@dataclass
class DieselSystemDetails:
p_type: Optional[str] = None
languages: Optional[List[str]] = None
rating: Optional[Dict] = None
systems: Optional[List[DieselSystemDetail]] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetails"], src: Dict[str, Any]) -> "DieselSystemDetails":
d = src.copy()
_systems = d.pop("systems", [])
systems = [] if _systems else None
for item in _systems:
system = DieselSystemDetail.from_dict(item)
systems.append(system)
tmp = cls(
p_type=d.pop("_type", ""),
languages=d.pop("languages", []),
rating=d.pop("rating", {}),
systems=systems,
)
tmp.unmapped = d
return tmp
@dataclass
class DieselProductAbout:
p_type: Optional[str] = None
desciption: Optional[str] = None
developer_attribution: Optional[str] = None
publisher_attribution: Optional[str] = None
short_description: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselProductAbout"], src: Dict[str, Any]) -> "DieselProductAbout":
d = src.copy()
tmp = cls(
p_type=d.pop("_type", ""),
desciption=d.pop("description", ""),
developer_attribution=d.pop("developerAttribution", ""),
publisher_attribution=d.pop("publisherAttribution", ""),
short_description=d.pop("shortDescription", ""),
)
tmp.unmapped = d
return tmp
@dataclass
class DieselProductDetail:
p_type: Optional[str] = None
about: Optional[DieselProductAbout] = None
requirements: Optional[DieselSystemDetails] = None
social_links: Optional[DieselSocialLinks] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselProductDetail"], src: Dict[str, Any]) -> "DieselProductDetail":
d = src.copy()
about = DieselProductAbout.from_dict(x) if (x := d.pop("about"), {}) else None
requirements = DieselSystemDetails.from_dict(x) if (x := d.pop("requirements", {})) else None
tmp = cls(
p_type=d.pop("_type", ""),
about=about,
requirements=requirements,
social_links=d.pop("socialLinks", {}),
)
tmp.unmapped = d
return tmp
@dataclass
class DieselProduct:
p_id: Optional[str] = None
p_images_: Optional[List[str]] = None
p_locale: Optional[str] = None
p_slug: Optional[str] = None
p_title: Optional[str] = None
p_url_pattern: Optional[str] = None
namespace: Optional[str] = None
pages: Optional[List["DieselProduct"]] = None
data: Optional[DieselProductDetail] = None
product_name: Optional[str] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselProduct"], src: Dict[str, Any]) -> "DieselProduct":
d = src.copy()
_pages = d.pop("pages", [])
pages = [] if _pages else None
for item in _pages:
page = DieselProduct.from_dict(item)
pages.append(page)
data = DieselProductDetail.from_dict(x) if (x := d.pop("data", {})) else None
tmp = cls(
p_id=d.pop("_id", ""),
p_images_=d.pop("_images_", []),
p_locale=d.pop("_locale", ""),
p_slug=d.pop("_slug", ""),
p_title=d.pop("_title", ""),
p_url_pattern=d.pop("_urlPattern", ""),
namespace=d.pop("namespace", ""),
pages=pages,
data=data,
product_name=d.pop("productName", ""),
)
tmp.unmapped = d
return tmp
@dataclass @dataclass
class ImageUrlModel: class ImageUrlModel:
type: Optional[str] = None type: Optional[str] = None
@ -271,14 +113,14 @@ LineOffersModel = Dict
@dataclass @dataclass
class PriceModel: class GetPriceResModel:
total_price: Optional[TotalPriceModel] = None total_price: Optional[TotalPriceModel] = None
fmt_price: Optional[FmtPriceModel] = None fmt_price: Optional[FmtPriceModel] = None
line_offers: Optional[LineOffersModel] = None line_offers: Optional[LineOffersModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict) unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod @classmethod
def from_dict(cls: Type["PriceModel"], src: Dict[str, Any]) -> "PriceModel": def from_dict(cls: Type["GetPriceResModel"], src: Dict[str, Any]) -> "GetPriceResModel":
d = src.copy() d = src.copy()
tmp = cls( tmp = cls(
total_price=d.pop("totalPrice", {}), total_price=d.pop("totalPrice", {}),
@ -302,9 +144,9 @@ class CatalogOfferModel:
items: Optional[List[ItemModel]] = None items: Optional[List[ItemModel]] = None
key_images: Optional[KeyImagesModel] = None key_images: Optional[KeyImagesModel] = None
namespace: Optional[str] = None namespace: Optional[str] = None
offer_mappings: Optional[List[OfferMappingModel]] = None offer_mappings: Optional[List[PageSandboxModel]] = None
offer_type: Optional[str] = None offer_type: Optional[str] = None
price: Optional[PriceModel] = None price: Optional[GetPriceResModel] = None
product_slug: Optional[str] = None product_slug: Optional[str] = None
promotions: Optional[PromotionsModel] = None promotions: Optional[PromotionsModel] = None
seller: Optional[SellerModel] = None seller: Optional[SellerModel] = None
@ -322,7 +164,7 @@ class CatalogOfferModel:
effective_date = parse_date(x) if (x := d.pop("effectiveDate", "")) else None effective_date = parse_date(x) if (x := d.pop("effectiveDate", "")) else None
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 = PriceModel.from_dict(x) if (x := d.pop("price", {})) else None price = GetPriceResModel.from_dict(x) if (x := d.pop("price", {})) 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", {}), catalog_ns=d.pop("catalogNs", {}),

View file

@ -1,5 +1,4 @@
import logging import logging
from pprint import pprint
from typing import List from typing import List
from PyQt5.QtCore import Qt, QUrl from PyQt5.QtCore import Qt, QUrl
@ -12,14 +11,14 @@ from PyQt5.QtWidgets import (
QSizePolicy, QSizePolicy,
) )
from rare.components.tabs.store.api.models.response import CatalogOfferModel, DieselProduct, DieselProductDetail from rare.models.image import ImageSize
from rare.shared import LegendaryCoreSingleton
from rare.shared.image_manager import ImageSize
from rare.ui.components.tabs.store.shop_game_info import Ui_ShopInfo from rare.ui.components.tabs.store.shop_game_info import Ui_ShopInfo
from rare.utils.misc import icon from rare.utils.misc import icon
from rare.widgets.side_tab import SideTabWidget, SideTabContents
from rare.widgets.elide_label import ElideLabel from rare.widgets.elide_label import ElideLabel
from rare.widgets.side_tab import SideTabWidget, SideTabContents
from .api.debug import DebugDialog from .api.debug import DebugDialog
from .api.models.diesel import DieselProduct, DieselProductDetail
from .api.models.response import CatalogOfferModel
from .image_widget import ShopImageWidget from .image_widget import ShopImageWidget
logger = logging.getLogger("ShopInfo") logger = logging.getLogger("ShopInfo")
@ -107,7 +106,7 @@ class ShopGameInfo(QWidget, SideTabContents):
# init API request # init API request
if slug: if slug:
self.api_core.get_game(offer.product_slug, is_bundle, self.data_received) self.api_core.get_game_config_cms(offer.product_slug, is_bundle, self.data_received)
# else: # else:
# self.data_received({}) # self.data_received({})
self.offer = offer self.offer = offer

View file

@ -3,10 +3,9 @@ import logging
from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QMouseEvent from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QPushButton from PyQt5.QtWidgets import QPushButton
from orjson import orjson
from rare.components.tabs.store.api.models.response import CatalogOfferModel from rare.components.tabs.store.api.models.response import CatalogOfferModel
from rare.shared.image_manager import ImageSize from rare.models.image import ImageSize
from rare.utils.misc import icon from rare.utils.misc import icon
from rare.utils.qt_requests import QtRequestManager from rare.utils.qt_requests import QtRequestManager
from .api.debug import DebugDialog from .api.debug import DebugDialog

View file

@ -1,10 +1,7 @@
from PyQt5.QtCore import QEvent, QObject
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QPixmap, QPixmap,
QImage, QImage,
QMovie,
QShowEvent,
) )
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QWidget, QWidget,
@ -17,51 +14,7 @@ from PyQt5.QtWidgets import (
from rare.utils.qt_requests import QtRequestManager from rare.utils.qt_requests import QtRequestManager
from rare.widgets.image_widget import ImageWidget from rare.widgets.image_widget import ImageWidget
from rare.widgets.loading_widget import LoadingWidget
class WaitingSpinner(QLabel):
def __init__(self, autostart=False, parent=None):
super(WaitingSpinner, self).__init__(parent=parent)
self.setObjectName(type(self).__name__)
self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.movie = QMovie(":/images/loader.gif", parent=self)
self.setFixedSize(128, 128)
self.setMovie(self.movie)
if self.parent() is not None:
self.parent().installEventFilter(self)
if autostart:
self.movie.start()
def __center_on_parent(self):
rect = self.rect()
rect.moveCenter(self.parent().contentsRect().center())
self.setGeometry(rect)
def event(self, e: QEvent) -> bool:
if e.type() == QEvent.ParentAboutToChange:
if self.parent() is not None:
self.parent().removeEventFilter(self)
if e.type() == QEvent.ParentChange:
if self.parent() is not None:
self.parent().installEventFilter(self)
return super().event(e)
def showEvent(self, a0: QShowEvent) -> None:
self.__center_on_parent()
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
if a0 is self.parent() and a1.type() == QEvent.Resize:
self.__center_on_parent()
return a0.event(a1)
return False
def start(self):
self.setVisible(True)
self.movie.start()
def stop(self):
self.setVisible(False)
self.movie.stop()
class IconWidget(object): class IconWidget(object):
@ -76,7 +29,7 @@ class IconWidget(object):
# on-hover popup # on-hover popup
self.mini_widget = QWidget(parent=widget) self.mini_widget = QWidget(parent=widget)
self.mini_widget.setObjectName(f"{type(self).__name__}MiniWidget") self.mini_widget.setObjectName(f"{type(self).__name__}MiniWidget")
self.mini_widget.setFixedHeight(widget.height() // 4) self.mini_widget.setFixedHeight(int(widget.height() // 3))
# game title # game title
self.title_label = QLabel(parent=self.mini_widget) self.title_label = QLabel(parent=self.mini_widget)
@ -134,7 +87,7 @@ class ShopImageWidget(ImageWidget):
def __init__(self, manager: QtRequestManager, parent=None): def __init__(self, manager: QtRequestManager, parent=None):
super(ShopImageWidget, self).__init__(parent=parent) super(ShopImageWidget, self).__init__(parent=parent)
self.ui = IconWidget() self.ui = IconWidget()
self.spinner = WaitingSpinner(parent=self) self.spinner = LoadingWidget(parent=self)
self.spinner.setVisible(False) self.spinner.setVisible(False)
self.manager = manager self.manager = manager

View file

@ -7,26 +7,24 @@ from PyQt5.QtWidgets import (
QLabel, QScrollArea, QLabel, QScrollArea,
) )
from rare.shared.image_manager import ImageSize from rare.models.image import ImageSize
from rare.utils.qt_requests import QtRequestManager from rare.utils.qt_requests import QtRequestManager
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 .image_widget import ShopImageWidget
from .api.debug import DebugDialog from .api.debug import DebugDialog
from .api.models.response import CatalogOfferModel from .api.models.response import CatalogOfferModel
from .image_widget import ShopImageWidget
class SearchResults(QScrollArea, SideTabContents): class SearchResultsWidget(QScrollArea):
show_info = pyqtSignal(CatalogOfferModel) show_info = pyqtSignal(CatalogOfferModel)
def __init__(self, api_core, parent=None): def __init__(self, api_core, parent=None):
super(SearchResults, self).__init__(parent=parent) super(SearchResultsWidget, self).__init__(parent=parent)
self.implements_scrollarea = True
self.api_core = api_core self.api_core = api_core
self.results_container = QWidget(self) self.results_container = QWidget(self)
self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.results_layout = FlowLayout(self.results_container) self.results_layout = FlowLayout(self.results_container)
self.setWidget(self.results_container) self.setWidget(self.results_container)
self.setWidgetResizable(True) self.setWidgetResizable(True)
@ -61,6 +59,12 @@ class SearchResults(QScrollArea, SideTabContents):
self.setEnabled(True) self.setEnabled(True)
class SearchResults(SearchResultsWidget, SideTabContents):
def __init__(self, api_core, parent=None):
super(SearchResults, self).__init__(api_core, parent=parent)
self.implements_scrollarea = True
class SearchResultItem(ShopImageWidget): class SearchResultItem(ShopImageWidget):
show_info = pyqtSignal(CatalogOfferModel) show_info = pyqtSignal(CatalogOfferModel)

View file

@ -14,8 +14,8 @@ from rare.components.tabs.store.constants import (
from rare.utils.paths import cache_dir from rare.utils.paths import cache_dir
from rare.utils.qt_requests import QtRequestManager from rare.utils.qt_requests import QtRequestManager
from .api.models.query import SearchStoreQuery from .api.models.query import SearchStoreQuery
from .api.models.diesel import DieselProduct
from .api.models.response import ( from .api.models.response import (
DieselProduct,
ResponseModel, ResponseModel,
CatalogOfferModel, CatalogOfferModel,
) )
@ -152,13 +152,13 @@ class ShopApiCore(QObject):
"query": search_query, "query": search_query,
"variables": browse_model.to_dict() "variables": browse_model.to_dict()
} }
debug = DebugDialog(payload["variables"], None) # debug = DebugDialog(payload["variables"], None)
debug.exec() # debug.exec()
self.manager.post(graphql_url, lambda data: self.__handle_browse_games(data, handle_func), payload) self.manager.post(graphql_url, lambda data: self.__handle_browse_games(data, handle_func), payload)
def __handle_browse_games(self, data, handle_func): def __handle_browse_games(self, data, handle_func):
debug = DebugDialog(data, None) # debug = DebugDialog(data, None)
debug.exec() # debug.exec()
self.browse_active = False self.browse_active = False
if data is None: if data is None:
data = {} data = {}
@ -181,15 +181,29 @@ class ShopApiCore(QObject):
self.browse_games(*self.next_browse_request) # pylint: disable=E1120 self.browse_games(*self.next_browse_request) # pylint: disable=E1120
self.next_browse_request = tuple(()) self.next_browse_request = tuple(())
def get_game(self, slug: str, is_bundle: bool, handle_func): def get_game_config_graphql(self, namespace: str, handle_func):
payload = {
"query": config_query,
"variables": {
"namespace": namespace
}
}
def __make_graphql_query(self):
pass
def __make_api_query(self):
pass
def get_game_config_cms(self, slug: str, is_bundle: bool, handle_func):
url = "https://store-content.ak.epicgames.com/api" url = "https://store-content.ak.epicgames.com/api"
url += f"/{self.locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}" url += f"/{self.locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}"
self.manager.get(url, lambda data: self.__handle_get_game(data, handle_func)) self.manager.get(url, lambda data: self.__handle_get_game(data, handle_func))
@staticmethod @staticmethod
def __handle_get_game(data, handle_func): def __handle_get_game(data, handle_func):
debug = DebugDialog(data, None) # debug = DebugDialog(data, None)
debug.exec() # debug.exec()
try: try:
product = DieselProduct.from_dict(data) product = DieselProduct.from_dict(data)
handle_func(product) handle_func(product)
@ -213,8 +227,8 @@ class ShopApiCore(QObject):
self.authed_manager.post(graphql_url, lambda data: self._handle_add_to_wishlist(data, handle_func), payload) self.authed_manager.post(graphql_url, lambda data: self._handle_add_to_wishlist(data, handle_func), payload)
def _handle_add_to_wishlist(self, data, handle_func): def _handle_add_to_wishlist(self, data, handle_func):
debug = DebugDialog(data, None) # debug = DebugDialog(data, None)
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.add_to_wishlist
@ -239,8 +253,8 @@ class ShopApiCore(QObject):
payload) payload)
def _handle_remove_from_wishlist(self, data, handle_func): def _handle_remove_from_wishlist(self, data, handle_func):
debug = DebugDialog(data, None) # debug = DebugDialog(data, None)
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.remove_from_wishlist

View file

@ -7,9 +7,8 @@ from PyQt5.QtWidgets import (
QGroupBox, QGroupBox,
QCheckBox, QCheckBox,
QLabel, QLabel,
QPushButton,
QHBoxLayout, QHBoxLayout,
QWidget, QSizePolicy, QStackedLayout, QWidget, QSizePolicy, QScrollArea, QVBoxLayout, QFrame, QSpacerItem,
) )
from legendary.core import LegendaryCore from legendary.core import LegendaryCore
@ -17,15 +16,16 @@ from rare.ui.components.tabs.store.store import Ui_ShopWidget
from rare.utils.extra_widgets import ButtonLineEdit from rare.utils.extra_widgets import ButtonLineEdit
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 .store_widgets import ShopGroupBox
from .api.models.query import SearchStoreQuery from .api.models.query import SearchStoreQuery
from .api.models.response import CatalogOfferModel, WishlistItemModel from .api.models.response import CatalogOfferModel, WishlistItemModel
from .api.models.utils import parse_date
from .constants import Constants from .constants import Constants
from .game_widgets import GameWidget from .game_widgets import GameWidget
from .image_widget import WaitingSpinner from .search_results import SearchResults
from .shop_api_core import ShopApiCore from .shop_api_core import ShopApiCore
from .api.models.utils import parse_date
logger = logging.getLogger("Shop") logger = logging.getLogger("Shop")
@ -47,39 +47,56 @@ class ShopWidget(QWidget, SideTabContents):
self.types = [] self.types = []
self.update_games_allowed = True self.update_games_allowed = True
self.ui.free_scrollarea.setDisabled(True)
self.free_game_widgets = [] 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.discounts_layout = QStackedLayout(self.ui.discounts_group) self.browse_scrollarea = QScrollArea(self)
self.discounts_spinner = WaitingSpinner(self.ui.discounts_group) self.browse_scrollarea.setWidgetResizable(True)
self.discounts_flow = QWidget(self.ui.discounts_group) self.browse_scrollarea.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.discounts_flow.setLayout(FlowLayout(self.discounts_flow)) self.browse_container = QWidget(self.browse_scrollarea)
self.discounts_flow.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) browse_contailer_layout = QVBoxLayout(self.browse_container)
self.discounts_layout.addWidget(self.discounts_spinner) browse_contailer_layout.setContentsMargins(0, 0, 3, 0)
self.discounts_layout.addWidget(self.discounts_flow) self.browse_container.setLayout(browse_contailer_layout)
self.browse_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.browse_scrollarea.setWidget(self.browse_container)
self.discounts_spinner.start() # self.free_scrollarea = QScrollArea(self.browse_container)
self.discounts_layout.setCurrentWidget(self.discounts_spinner) # self.free_scrollarea.setWidgetResizable(True)
# self.free_scrollarea.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
# self.free_container = QWidget(self.free_scrollarea)
# free_container_layout = QHBoxLayout(self.free_container)
# free_container_layout.setContentsMargins(0, 0, 0, 3)
# self.free_container.setLayout(free_container_layout)
# self.free_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
# self.free_scrollarea.setWidget(self.free_container)
#
# self.browse_container.layout().addWidget(self.free_scrollarea)
self.games_layout = QStackedLayout(self.ui.games_group) self.discounts_group = ShopGroupBox(self.tr("Discounts from your wishlist"), FlowLayout, self)
self.games_spinner = WaitingSpinner(self.ui.games_group) self.browse_container.layout().addWidget(self.discounts_group)
self.games_flow = QWidget(self.ui.games_group) self.discounts_group.loading(True)
self.games_flow.setLayout(FlowLayout(self.games_flow))
self.games_flow.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.games_layout.addWidget(self.games_spinner)
self.games_layout.addWidget(self.games_flow)
self.games_spinner.start() self.games_group = ShopGroupBox(self.tr("Games"), FlowLayout, self)
self.games_layout.setCurrentWidget(self.games_spinner) self.browse_container.layout().addWidget(self.games_group)
self.games_group.loading(True)
self.games_group.setVisible(False)
self.browse_container.layout().addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
self.search_scrollarea = SearchResults(self.api_core, self)
self.search_bar = ButtonLineEdit( self.search_bar = ButtonLineEdit(
"fa.search", placeholder_text=self.tr("Search Games") "fa.search", placeholder_text=self.tr("Search Games")
) )
self.ui.main_layout.addWidget(self.search_bar, 0, 0) self.ui.left_layout.addWidget(self.search_bar)
self.browse_stack = SlidingStackedWidget(self)
self.browse_stack.setDirection(Qt.Vertical)
self.browse_stack.addWidget(self.browse_scrollarea)
self.browse_stack.addWidget(self.search_scrollarea)
self.ui.left_layout.addWidget(self.browse_stack)
# self.search_bar.textChanged.connect(self.search_games) # self.search_bar.textChanged.connect(self.search_games)
@ -102,8 +119,8 @@ class ShopWidget(QWidget, SideTabContents):
self.api_core.get_wishlist(self.add_wishlist_items) self.api_core.get_wishlist(self.add_wishlist_items)
def add_wishlist_items(self, wishlist: List[WishlistItemModel]): def add_wishlist_items(self, wishlist: List[WishlistItemModel]):
for w in self.discounts_flow.findChildren(QWidget, options=Qt.FindDirectChildrenOnly): for w in self.discounts_group.findChildren(QWidget, options=Qt.FindDirectChildrenOnly):
self.discounts_flow.layout().removeWidget(w) self.discounts_group.layout().removeWidget(w)
w.deleteLater() w.deleteLater()
# if wishlist and wishlist[0] == "error": # if wishlist and wishlist[0] == "error":
@ -126,50 +143,46 @@ class ShopWidget(QWidget, SideTabContents):
if game.offer.price.total_price["discount"] > 0: if game.offer.price.total_price["discount"] > 0:
w = GameWidget(self.api_core.cached_manager, game.offer) w = GameWidget(self.api_core.cached_manager, game.offer)
w.show_info.connect(self.show_game) w.show_info.connect(self.show_game)
self.discounts_flow.layout().addWidget(w) self.discounts_group.layout().addWidget(w)
discounts += 1 discounts += 1
except Exception as e: except Exception as e:
logger.warning(f"{game} {e}") logger.warning(f"{game} {e}")
continue continue
self.ui.discounts_group.setVisible(discounts > 0) self.discounts_group.setVisible(discounts > 0)
self.discounts_layout.setCurrentWidget(self.discounts_flow) self.discounts_group.loading(False)
# FIXME: FlowLayout doesn't update on adding widget # FIXME: FlowLayout doesn't update on adding widget
self.discounts_flow.layout().update() self.discounts_group.layout().update()
def add_free_games(self, free_games: List[CatalogOfferModel]): def add_free_games(self, free_games: List[CatalogOfferModel]):
for w in self.ui.free_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly): for w in self.browse_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly):
self.ui.free_container.layout().removeWidget(w) self.browse_container.layout().removeWidget(w)
w.deleteLater() w.deleteLater()
if free_games and free_games[0] == "error": # if free_games and free_games[0] == "error":
self.ui.free_container.layout().addWidget( # self.ui.free_container.layout().addWidget(
QLabel(self.tr("Failed to fetch free games: {}").format(free_games[1])) # QLabel(self.tr("Failed to fetch free games: {}").format(free_games[1]))
) # )
btn = QPushButton(self.tr("Reload")) # btn = QPushButton(self.tr("Reload"))
self.ui.free_container.layout().addWidget(btn) # self.ui.free_container.layout().addWidget(btn)
btn.clicked.connect( # btn.clicked.connect(
lambda: self.api_core.get_free_games(self.add_free_games) # lambda: self.api_core.get_free_games(self.add_free_games)
) # )
self.ui.free_container.setEnabled(True) # self.ui.free_container.setEnabled(True)
return # return
self.free_games_now = QGroupBox(self.tr("Free now"), parent=self.ui.free_container) free_games_now = ShopGroupBox(self.tr("Free now"), layouting=QHBoxLayout, parent=self.browse_container)
free_games_now_layout = QHBoxLayout(self.free_games_now) free_games_now.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# free_games_now_layout.setContentsMargins(0, 0, 0, 0) # self.free_games_now.setLayout(free_games_now_layout)
self.free_games_now.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.browse_container.layout().insertWidget(0, free_games_now)
self.free_games_now.setLayout(free_games_now_layout)
self.ui.free_container.layout().addWidget(self.free_games_now)
self.free_games_next = QGroupBox(self.tr("Free next week"), parent=self.ui.free_container) free_games_next = ShopGroupBox(self.tr("Free next week"), layouting=QHBoxLayout, parent=self.browse_container)
free_games_next_layout = QHBoxLayout(self.free_games_next) free_games_next.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# free_games_next_layout.setContentsMargins(0, 0, 0, 0) # self.free_games_next.setLayout(free_games_next_layout)
self.free_games_next.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.browse_container.layout().insertWidget(1, free_games_next)
self.free_games_next.setLayout(free_games_next_layout)
self.ui.free_container.layout().addWidget(self.free_games_next)
date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc) date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
free_games_now = [] free_now_list = []
coming_free_games = [] free_next_list = []
for game in free_games: for game in free_games:
try: try:
if ( if (
@ -177,11 +190,11 @@ class ShopWidget(QWidget, SideTabContents):
and game.price.total_price["fmtPrice"]["originalPrice"] and game.price.total_price["fmtPrice"]["originalPrice"]
!= game.price.total_price["fmtPrice"]["discountPrice"] != game.price.total_price["fmtPrice"]["discountPrice"]
): ):
free_games_now.append(game) free_now_list.append(game)
continue continue
if game.title == "Mystery Game": if game.title == "Mystery Game":
coming_free_games.append(game) free_next_list.append(game)
continue continue
except KeyError as e: except KeyError as e:
logger.warning(str(e)) logger.warning(str(e))
@ -206,39 +219,43 @@ class ShopWidget(QWidget, SideTabContents):
continue continue
if start_date > date: if start_date > date:
coming_free_games.append(game) free_next_list.append(game)
# free games now # free games now
now_free = 0 now_free = 0
for free_game in free_games_now: for free_game in free_now_list:
w = GameWidget(self.api_core.cached_manager, free_game) w = GameWidget(self.api_core.cached_manager, free_game)
w.show_info.connect(self.show_game) w.show_info.connect(self.show_game)
self.free_games_now.layout().addWidget(w) free_games_now.layout().addWidget(w)
self.free_game_widgets.append(w) # self.free_game_widgets.append(w)
now_free += 1 now_free += 1
if now_free == 0: if now_free == 0:
self.free_games_now.layout().addWidget( free_games_now.layout().addWidget(
QLabel(self.tr("Could not find current free game")) QLabel(self.tr("Could not find current free game"))
) )
free_games_now.loading(False)
# free games next week # free games next week
for free_game in coming_free_games: for free_game in free_next_list:
w = GameWidget(self.api_core.cached_manager, free_game) w = GameWidget(self.api_core.cached_manager, free_game)
if free_game.title != "Mystery Game": if free_game.title != "Mystery Game":
w.show_info.connect(self.show_game) w.show_info.connect(self.show_game)
self.free_games_next.layout().addWidget(w) free_games_next.layout().addWidget(w)
free_games_next.loading(False)
# self.coming_free_games.setFixedWidth(int(40 + len(coming_free_games) * 300)) # self.coming_free_games.setFixedWidth(int(40 + len(coming_free_games) * 300))
self.ui.free_scrollarea.setMinimumHeight( # self.free_scrollarea.setMinimumHeight(
self.free_games_now.sizeHint().height() # free_games_now.sizeHint().height()
+ self.ui.free_container.layout().contentsMargins().top() # + self.free_container.layout().contentsMargins().top()
+ self.ui.free_container.layout().contentsMargins().bottom() # + self.free_container.layout().contentsMargins().bottom()
+ self.ui.free_scrollarea.horizontalScrollBar().sizeHint().height() # + self.free_scrollarea.horizontalScrollBar().sizeHint().height()
) # )
self.ui.free_scrollarea.setEnabled(True) # self.free_scrollarea.setEnabled(True)
def show_search_results(self): def show_search_results(self):
if self.search_bar.text(): if self.search_bar.text():
self.show_info.emit(self.search_bar.text()) self.browse_stack.slideInWidget(self.search_scrollarea)
self.search_scrollarea.load_results(self.search_bar.text())
# self.show_info.emit(self.search_bar.text())
def init_filter(self): def init_filter(self):
self.ui.none_price.toggled.connect( self.ui.none_price.toggled.connect(
@ -299,6 +316,7 @@ class ShopWidget(QWidget, SideTabContents):
) )
def reset_filters(self): def reset_filters(self):
self.browse_stack.slideInWidget(self.browse_scrollarea)
self.update_games_allowed = False self.update_games_allowed = False
for cb in self.checkboxes: for cb in self.checkboxes:
cb.setChecked(False) cb.setChecked(False)
@ -334,14 +352,14 @@ class ShopWidget(QWidget, SideTabContents):
if removed_type and removed_type in self.types: if removed_type and removed_type in self.types:
self.types.remove(removed_type) self.types.remove(removed_type)
if (self.types or self.price) or self.tags or self.ui.on_discount.isChecked(): if (self.types or self.price) or self.tags or self.ui.on_discount.isChecked():
self.ui.free_scrollarea.setVisible(False) # self.free_scrollarea.setVisible(False)
self.ui.discounts_group.setVisible(False) self.discounts_group.setVisible(False)
else: else:
self.ui.free_scrollarea.setVisible(True) # self.free_scrollarea.setVisible(True)
if len(self.ui.discounts_group.layout().children()) > 0: if len(self.discounts_group.layout().children()) > 0:
self.ui.discounts_group.setVisible(True) self.discounts_group.setVisible(True)
self.games_layout.setCurrentWidget(self.games_spinner) self.games_group.loading(True)
browse_model = SearchStoreQuery( browse_model = SearchStoreQuery(
language=self.core.language_code, language=self.core.language_code,
@ -357,22 +375,22 @@ class ShopWidget(QWidget, SideTabContents):
self.api_core.browse_games(browse_model, self.show_games) self.api_core.browse_games(browse_model, self.show_games)
def show_games(self, data): def show_games(self, data):
for w in self.games_flow.findChildren(QWidget, options=Qt.FindDirectChildrenOnly): for w in self.games_group.findChildren(QWidget, options=Qt.FindDirectChildrenOnly):
self.games_flow.layout().removeWidget(w) self.games_group.layout().removeWidget(w)
w.deleteLater() w.deleteLater()
if data: if data:
for game in data: for game in data:
w = GameWidget(self.api_core.cached_manager, game) w = GameWidget(self.api_core.cached_manager, game)
w.show_info.connect(self.show_game) w.show_info.connect(self.show_game)
self.games_flow.layout().addWidget(w) self.games_group.layout().addWidget(w)
else: else:
self.games_flow.layout().addWidget( self.games_group.layout().addWidget(
QLabel(self.tr("Could not get games matching the filter")) QLabel(self.tr("Could not get games matching the filter"))
) )
self.games_layout.setCurrentWidget(self.games_flow) self.games_group.loading(False)
# FIXME: FlowLayout doesn't update on adding widget # FIXME: FlowLayout doesn't update on adding widget
self.games_flow.layout().update() self.games_group.layout().update()
class CheckBox(QCheckBox): class CheckBox(QCheckBox):

View file

@ -5,11 +5,11 @@ from PyQt5.QtWidgets import QMessageBox, QWidget
from rare.ui.components.tabs.store.wishlist import Ui_Wishlist from rare.ui.components.tabs.store.wishlist import Ui_Wishlist
from rare.utils.misc import icon from rare.utils.misc import icon
from rare.widgets.side_tab import SideTabContents
from rare.widgets.flow_layout import FlowLayout from rare.widgets.flow_layout import FlowLayout
from .shop_api_core import ShopApiCore from rare.widgets.side_tab import SideTabContents
from .game_widgets import WishlistWidget
from .api.models.response import WishlistItemModel, CatalogOfferModel from .api.models.response import WishlistItemModel, CatalogOfferModel
from .game_widgets import WishlistWidget
from .shop_api_core import ShopApiCore
class Wishlist(QWidget, SideTabContents): class Wishlist(QWidget, SideTabContents):

View file

@ -16,8 +16,16 @@ class Ui_ShopWidget(object):
ShopWidget.setObjectName("ShopWidget") ShopWidget.setObjectName("ShopWidget")
ShopWidget.resize(788, 662) ShopWidget.resize(788, 662)
ShopWidget.setWindowTitle("Store") ShopWidget.setWindowTitle("Store")
self.main_layout = QtWidgets.QGridLayout(ShopWidget) self.main_layout = QtWidgets.QHBoxLayout(ShopWidget)
self.main_layout.setObjectName("main_layout") self.main_layout.setObjectName("main_layout")
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.main_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.reset_button = QtWidgets.QPushButton(ShopWidget)
self.reset_button.setObjectName("reset_button")
self.right_layout.addWidget(self.reset_button)
self.filter_scrollarea = QtWidgets.QScrollArea(ShopWidget) self.filter_scrollarea = QtWidgets.QScrollArea(ShopWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -89,59 +97,15 @@ class Ui_ShopWidget(object):
self.others_layout.setObjectName("others_layout") self.others_layout.setObjectName("others_layout")
self.filter_container_layout.addWidget(self.others_group) self.filter_container_layout.addWidget(self.others_group)
self.filter_scrollarea.setWidget(self.filter_container) self.filter_scrollarea.setWidget(self.filter_container)
self.main_layout.addWidget(self.filter_scrollarea, 1, 1, 1, 1) self.right_layout.addWidget(self.filter_scrollarea)
self.reset_button = QtWidgets.QPushButton(ShopWidget) self.main_layout.addLayout(self.right_layout)
self.reset_button.setObjectName("reset_button") self.main_layout.setStretch(0, 1)
self.main_layout.addWidget(self.reset_button, 0, 1, 1, 1)
self.games_scrollarea = QtWidgets.QScrollArea(ShopWidget)
self.games_scrollarea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.games_scrollarea.setFrameShadow(QtWidgets.QFrame.Plain)
self.games_scrollarea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.games_scrollarea.setWidgetResizable(True)
self.games_scrollarea.setObjectName("games_scrollarea")
self.games_container = QtWidgets.QWidget()
self.games_container.setGeometry(QtCore.QRect(0, 0, 628, 618))
self.games_container.setObjectName("games_container")
self.games_container_layout = QtWidgets.QVBoxLayout(self.games_container)
self.games_container_layout.setContentsMargins(0, 0, 3, 0)
self.games_container_layout.setObjectName("games_container_layout")
self.free_scrollarea = QtWidgets.QScrollArea(self.games_container)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.free_scrollarea.sizePolicy().hasHeightForWidth())
self.free_scrollarea.setSizePolicy(sizePolicy)
self.free_scrollarea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.free_scrollarea.setFrameShadow(QtWidgets.QFrame.Plain)
self.free_scrollarea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.free_scrollarea.setWidgetResizable(True)
self.free_scrollarea.setObjectName("free_scrollarea")
self.free_container = QtWidgets.QWidget()
self.free_container.setGeometry(QtCore.QRect(0, 0, 16, 16))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.free_container.sizePolicy().hasHeightForWidth())
self.free_container.setSizePolicy(sizePolicy)
self.free_container.setObjectName("free_container")
self.free_container_layout = QtWidgets.QHBoxLayout(self.free_container)
self.free_container_layout.setContentsMargins(0, 0, 0, 3)
self.free_container_layout.setObjectName("free_container_layout")
self.free_scrollarea.setWidget(self.free_container)
self.games_container_layout.addWidget(self.free_scrollarea)
self.discounts_group = QtWidgets.QGroupBox(self.games_container)
self.discounts_group.setObjectName("discounts_group")
self.games_container_layout.addWidget(self.discounts_group)
self.games_group = QtWidgets.QGroupBox(self.games_container)
self.games_group.setObjectName("games_group")
self.games_container_layout.addWidget(self.games_group)
self.games_scrollarea.setWidget(self.games_container)
self.main_layout.addWidget(self.games_scrollarea, 1, 0, 1, 1)
self.retranslateUi(ShopWidget) self.retranslateUi(ShopWidget)
def retranslateUi(self, ShopWidget): def retranslateUi(self, ShopWidget):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
self.reset_button.setText(_translate("ShopWidget", "Reset filters"))
self.price_group.setTitle(_translate("ShopWidget", "Price")) self.price_group.setTitle(_translate("ShopWidget", "Price"))
self.none_price.setText(_translate("ShopWidget", "None")) self.none_price.setText(_translate("ShopWidget", "None"))
self.free_button.setText(_translate("ShopWidget", "Free")) self.free_button.setText(_translate("ShopWidget", "Free"))
@ -154,9 +118,6 @@ class Ui_ShopWidget(object):
self.genre_group.setTitle(_translate("ShopWidget", "Genre")) self.genre_group.setTitle(_translate("ShopWidget", "Genre"))
self.type_group.setTitle(_translate("ShopWidget", "Type")) self.type_group.setTitle(_translate("ShopWidget", "Type"))
self.others_group.setTitle(_translate("ShopWidget", "Other tags")) self.others_group.setTitle(_translate("ShopWidget", "Other tags"))
self.reset_button.setText(_translate("ShopWidget", "Reset filters"))
self.discounts_group.setTitle(_translate("ShopWidget", "Discounts from your wishlist"))
self.games_group.setTitle(_translate("ShopWidget", "Games"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -13,267 +13,168 @@
<property name="windowTitle"> <property name="windowTitle">
<string notr="true">Store</string> <string notr="true">Store</string>
</property> </property>
<layout class="QGridLayout" name="main_layout"> <layout class="QHBoxLayout" name="main_layout" stretch="1,0">
<item row="1" column="1"> <item>
<widget class="QScrollArea" name="filter_scrollarea"> <layout class="QVBoxLayout" name="left_layout"/>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="filter_container">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>142</width>
<height>390</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="filter_container_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="price_group">
<property name="title">
<string>Price</string>
</property>
<layout class="QVBoxLayout" name="price_layout">
<item>
<widget class="QRadioButton" name="none_price">
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="free_button">
<property name="text">
<string>Free</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under10">
<property name="text">
<string>Under 10</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under20">
<property name="text">
<string>Under 20</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under30">
<property name="text">
<string>Under 30</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="above">
<property name="text">
<string>14.99 and above</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="on_discount">
<property name="text">
<string>Discount</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="platform_group">
<property name="title">
<string>Platform</string>
</property>
<layout class="QVBoxLayout" name="platfrom_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="genre_group">
<property name="title">
<string>Genre</string>
</property>
<layout class="QVBoxLayout" name="genre_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="type_group">
<property name="title">
<string>Type</string>
</property>
<layout class="QVBoxLayout" name="type_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="others_group">
<property name="title">
<string>Other tags</string>
</property>
<layout class="QVBoxLayout" name="others_layout"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item> </item>
<item row="0" column="1"> <item>
<widget class="QPushButton" name="reset_button"> <layout class="QVBoxLayout" name="right_layout">
<property name="text"> <item>
<string>Reset filters</string> <widget class="QPushButton" name="reset_button">
</property> <property name="text">
</widget> <string>Reset filters</string>
</item>
<item row="1" column="0">
<widget class="QScrollArea" name="games_scrollarea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="games_container">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>628</width>
<height>618</height>
</rect>
</property>
<layout class="QVBoxLayout" name="games_container_layout">
<property name="leftMargin">
<number>0</number>
</property> </property>
<property name="topMargin"> </widget>
<number>0</number> </item>
<item>
<widget class="QScrollArea" name="filter_scrollarea">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="rightMargin"> <property name="frameShape">
<number>3</number> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="bottomMargin"> <property name="frameShadow">
<number>0</number> <enum>QFrame::Plain</enum>
</property> </property>
<item> <property name="horizontalScrollBarPolicy">
<widget class="QScrollArea" name="free_scrollarea"> <enum>Qt::ScrollBarAlwaysOff</enum>
<property name="sizePolicy"> </property>
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <property name="sizeAdjustPolicy">
<horstretch>0</horstretch> <enum>QAbstractScrollArea::AdjustToContents</enum>
<verstretch>0</verstretch> </property>
</sizepolicy> <property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="filter_container">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>142</width>
<height>390</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="filter_container_layout">
<property name="leftMargin">
<number>0</number>
</property> </property>
<property name="frameShape"> <property name="topMargin">
<enum>QFrame::NoFrame</enum> <number>0</number>
</property> </property>
<property name="frameShadow"> <property name="rightMargin">
<enum>QFrame::Plain</enum> <number>3</number>
</property> </property>
<property name="verticalScrollBarPolicy"> <property name="bottomMargin">
<enum>Qt::ScrollBarAlwaysOff</enum> <number>0</number>
</property> </property>
<property name="widgetResizable"> <item>
<bool>true</bool> <widget class="QGroupBox" name="price_group">
</property> <property name="title">
<widget class="QWidget" name="free_container"> <string>Price</string>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>16</width>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="free_container_layout">
<property name="leftMargin">
<number>0</number>
</property> </property>
<property name="topMargin"> <layout class="QVBoxLayout" name="price_layout">
<number>0</number> <item>
<widget class="QRadioButton" name="none_price">
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="free_button">
<property name="text">
<string>Free</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under10">
<property name="text">
<string>Under 10</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under20">
<property name="text">
<string>Under 20</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under30">
<property name="text">
<string>Under 30</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="above">
<property name="text">
<string>14.99 and above</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="on_discount">
<property name="text">
<string>Discount</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="platform_group">
<property name="title">
<string>Platform</string>
</property> </property>
<property name="rightMargin"> <layout class="QVBoxLayout" name="platfrom_layout"/>
<number>0</number> </widget>
</item>
<item>
<widget class="QGroupBox" name="genre_group">
<property name="title">
<string>Genre</string>
</property> </property>
<property name="bottomMargin"> <layout class="QVBoxLayout" name="genre_layout"/>
<number>3</number> </widget>
</item>
<item>
<widget class="QGroupBox" name="type_group">
<property name="title">
<string>Type</string>
</property> </property>
</layout> <layout class="QVBoxLayout" name="type_layout"/>
</widget> </widget>
</widget> </item>
</item> <item>
<item> <widget class="QGroupBox" name="others_group">
<widget class="QGroupBox" name="discounts_group"> <property name="title">
<property name="title"> <string>Other tags</string>
<string>Discounts from your wishlist</string> </property>
</property> <layout class="QVBoxLayout" name="others_layout"/>
</widget> </widget>
</item> </item>
<item> </layout>
<widget class="QGroupBox" name="games_group"> </widget>
<property name="title"> </widget>
<string>Games</string> </item>
</property> </layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View file

@ -67,7 +67,7 @@ class QtRequestManager(QObject):
def __post(self, item: RequestQueueItem): def __post(self, item: RequestQueueItem):
request = self.__prepare_request(item) request = self.__prepare_request(item)
payload = orjson.dumps(item.payload) payload = orjson.dumps(item.payload) # pylint: disable=maybe-no-member
reply = self.manager.post(request, payload) reply = self.manager.post(request, payload)
reply.errorOccurred.connect(self.__on_error) reply.errorOccurred.connect(self.__on_error)
self.__active_requests[reply] = item self.__active_requests[reply] = item
@ -128,7 +128,7 @@ class QtRequestManager(QObject):
maintype, subtype = mimetype.split("/") maintype, subtype = mimetype.split("/")
bin_data = reply.readAll().data() bin_data = reply.readAll().data()
if mimetype == "application/json": if mimetype == "application/json":
data = orjson.loads(bin_data) data = orjson.loads(bin_data) # pylint: disable=maybe-no-member
elif maintype == "image": elif maintype == "image":
data = bin_data data = bin_data
else: else: