From f6396f488ae9e47c56b628b6bc99adf294be7bd6 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:46:02 +0300 Subject: [PATCH] Store: Exploratory changes to the store page Important changes: * Refactored QtRequests to accept parameters for `GET` operations * Infer response data type from content-type header * Support caching to disk, a manager with this set prefers the cache * Support multiple handlers for a single request (unused, possibly pointeless) * Subclass `ShopImageWidget` for all widgets used in the shop * Request a resized image instead of the original one * Fix the search and browse functions --- rare/components/tabs/store/__init__.py | 8 +- rare/components/tabs/store/__main__.py | 3 + rare/components/tabs/store/game_info.py | 6 +- rare/components/tabs/store/game_widgets.py | 66 +++--- rare/components/tabs/store/image_widget.py | 93 ++++---- rare/components/tabs/store/search_results.py | 39 ++-- rare/components/tabs/store/shop_api_core.py | 82 +++---- rare/components/tabs/store/shop_models.py | 20 +- rare/components/tabs/store/shop_widget.py | 211 ++++++++++-------- rare/components/tabs/store/wishlist.py | 78 +++---- .../components/tabs/store/shop_game_info.py | 2 +- .../components/tabs/store/shop_game_info.ui | 4 +- rare/ui/components/tabs/store/store.py | 34 ++- rare/ui/components/tabs/store/store.ui | 42 ++-- rare/ui/components/tabs/store/wishlist.py | 41 ++-- rare/ui/components/tabs/store/wishlist.ui | 45 ++-- .../components/tabs/store/wishlist_widget.py | 48 ++-- .../components/tabs/store/wishlist_widget.ui | 43 ++-- 18 files changed, 441 insertions(+), 424 deletions(-) diff --git a/rare/components/tabs/store/__init__.py b/rare/components/tabs/store/__init__.py index 3941be00..817e1acd 100644 --- a/rare/components/tabs/store/__init__.py +++ b/rare/components/tabs/store/__init__.py @@ -25,12 +25,12 @@ class StoreTab(SideTabWidget): ) self.shop = ShopWidget(cache_dir(), self.core, self.api_core, parent=self) - self.shop_index = self.addTab(self.shop, self.tr("Games")) + self.shop_index = self.addTab(self.shop, self.tr("Store")) self.shop.show_game.connect(self.show_game) self.shop.show_info.connect(self.show_search) self.search = SearchResults(self.api_core, parent=self) - self.search_index = self.addTab(self.search, self.tr("Search")) + self.search_index = self.addTab(self.search, self.tr("Search"), self.tr("Results")) self.search.show_info.connect(self.show_game) # self.search.back_button.clicked.connect(lambda: self.setCurrentIndex(self.shop_index)) @@ -40,11 +40,11 @@ class StoreTab(SideTabWidget): self.api_core, parent=self ) - self.info_index = self.addTab(self.info, self.tr("Information")) + self.info_index = self.addTab(self.info, self.tr("Information"), self.tr("Information")) # self.info.back_button.clicked.connect(lambda: self.setCurrentIndex(self.previous_index)) self.wishlist = Wishlist(self.api_core, parent=self) - self.wishlist_index = self.addTab(self.wishlist, self.tr("Wishlist")) + self.wishlist_index = self.addTab(self.wishlist, self.tr("Wishlist"), self.tr("Wishlist")) self.wishlist.update_wishlist_signal.connect(self.update_wishlist) self.wishlist.show_game_info.connect(self.show_game) diff --git a/rare/components/tabs/store/__main__.py b/rare/components/tabs/store/__main__.py index 1f62692c..29d9acfd 100644 --- a/rare/components/tabs/store/__main__.py +++ b/rare/components/tabs/store/__main__.py @@ -27,9 +27,12 @@ if __name__ == "__main__": import rare.resources.stylesheets.RareStyle app = QApplication(sys.argv) + app.setApplicationName("Rare") + app.setOrganizationName("Rare") set_style_sheet("RareStyle") window = StoreWindow() + window.setWindowTitle(f"{app.applicationName()} - Store") window.resize(QSize(1280, 800)) window.show() app.exec() \ No newline at end of file diff --git a/rare/components/tabs/store/game_info.py b/rare/components/tabs/store/game_info.py index b42dccdc..2d399b17 100644 --- a/rare/components/tabs/store/game_info.py +++ b/rare/components/tabs/store/game_info.py @@ -33,7 +33,7 @@ class ShopGameInfo(QWidget, SideTabContents): self.api_core = api_core self.installed = installed_titles self.ui.open_store_button.clicked.connect(self.button_clicked) - self.image = ShopImageWidget(self) + self.image = ShopImageWidget(api_core.cached_manager, self) self.image.setFixedSize(ImageSize.Normal) self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop) @@ -139,7 +139,7 @@ class ShopGameInfo(QWidget, SideTabContents): "VaultClosed", "ProductLogo", ]: - self.image.fetchPixmap(img["url"], self.id_str, self.title_str) + self.image.fetchPixmap(img["url"]) break self.price.setText("") self.discount_price.setText("") @@ -207,7 +207,7 @@ class ShopGameInfo(QWidget, SideTabContents): img_url = self.game.image_urls.product_logo else: img_url = "" - self.image.fetchPixmap(img_url, self.game.id, self.game.title) + self.image.fetchPixmap(img_url) # self.image_stack.setCurrentIndex(0) try: diff --git a/rare/components/tabs/store/game_widgets.py b/rare/components/tabs/store/game_widgets.py index 85e16c72..09ba8873 100644 --- a/rare/components/tabs/store/game_widgets.py +++ b/rare/components/tabs/store/game_widgets.py @@ -1,15 +1,13 @@ import logging -from PyQt5 import QtGui from PyQt5.QtCore import pyqtSignal, Qt -from PyQt5.QtGui import QFont, QMouseEvent -from PyQt5.QtWidgets import QWidget +from PyQt5.QtGui import QMouseEvent +from PyQt5.QtWidgets import QPushButton from rare.components.tabs.store.shop_models import ImageUrlModel from rare.shared.image_manager import ImageSize -from rare.ui.components.tabs.store.wishlist_widget import Ui_WishlistWidget -from rare.utils.extra_widgets import ImageLabel from rare.utils.misc import qta_icon +from rare.utils.qt_requests import QtRequestManager from .image_widget import ShopImageWidget logger = logging.getLogger("GameWidgets") @@ -18,11 +16,10 @@ logger = logging.getLogger("GameWidgets") class GameWidget(ShopImageWidget): show_info = pyqtSignal(dict) - def __init__(self, path, json_info=None, parent=None): - super(GameWidget, self).__init__(parent=parent) + def __init__(self, manager: QtRequestManager, json_info=None, parent=None): + super(GameWidget, self).__init__(manager, parent=parent) self.setFixedSize(ImageSize.Wide) self.ui.setupUi(self) - self.path = path self.json_info = json_info if json_info: self.init_ui(json_info) @@ -33,6 +30,13 @@ class GameWidget(ShopImageWidget): return self.ui.title_label.setText(json_info.get("title")) + for attr in json_info["customAttributes"]: + if attr["key"] == "developerName": + developer = attr["value"] + break + else: + developer = json_info["seller"]["name"] + self.ui.developer_label.setText(developer) price = json_info["price"]["totalPrice"]["fmtPrice"]["originalPrice"] discount_price = json_info["price"]["totalPrice"]["fmtPrice"]["discountPrice"] self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}') @@ -51,7 +55,7 @@ class GameWidget(ShopImageWidget): if img["type"] in ["DieselStoreFrontWide", "OfferImageWide", "VaultClosed", "ProductLogo",]: if img["type"] == "VaultClosed" and json_info["title"] != "Mystery Game": continue - self.fetchPixmap(img["url"], json_info["id"], json_info["title"]) + self.fetchPixmap(img["url"]) break else: logger.info(", ".join([img["type"] for img in json_info["keyImages"]])) @@ -62,52 +66,52 @@ class GameWidget(ShopImageWidget): self.show_info.emit(self.json_info) -class WishlistWidget(QWidget, Ui_WishlistWidget): +class WishlistWidget(ShopImageWidget): open_game = pyqtSignal(dict) delete_from_wishlist = pyqtSignal(dict) - def __init__(self, game: dict): - super(WishlistWidget, self).__init__() - self.setupUi(self) + def __init__(self, manager: QtRequestManager, game: dict, parent=None): + super(WishlistWidget, self).__init__(manager, parent=parent) + self.setFixedSize(ImageSize.Wide) + self.ui.setupUi(self) self.game = game - self.title_label.setText(game.get("title")) for attr in game["customAttributes"]: if attr["key"] == "developerName": - self.developer.setText(attr["value"]) + developer = attr["value"] break else: - self.developer.setText(game["seller"]["name"]) + developer = game["seller"]["name"] original_price = game["price"]["totalPrice"]["fmtPrice"]["originalPrice"] discount_price = game["price"]["totalPrice"]["fmtPrice"]["discountPrice"] - self.price.setText(original_price if original_price != "0" else self.tr("Free")) - # if discount + self.ui.title_label.setText(game.get("title")) + self.ui.developer_label.setText(developer) + self.ui.price_label.setText(f'{original_price if original_price != "0" else self.tr("Free")}') if original_price != discount_price: - self.discount = True - font = QFont() + font = self.ui.price_label.font() font.setStrikeOut(True) - self.price.setFont(font) - self.discount_price.setText(discount_price) + self.ui.price_label.setFont(font) + self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}') else: - self.discount = False - self.discount_price.setVisible(False) - - self.image = ImageLabel() - self.layout().insertWidget(0, self.image) + self.ui.discount_label.setVisible(False) image_model = ImageUrlModel.from_json(game["keyImages"]) url = image_model.front_wide if not url: url = image_model.offer_image_wide - self.image.update_image(url, game.get("title"), (240, 135)) + self.fetchPixmap(url) + + self.delete_button = QPushButton(self) self.delete_button.setIcon(icon("mdi.delete", color="white")) self.delete_button.clicked.connect( lambda: self.delete_from_wishlist.emit(self.game) ) + self.layout().insertWidget(0, self.delete_button, alignment=Qt.AlignRight) - def mousePressEvent(self, e: QtGui.QMouseEvent) -> None: + def mousePressEvent(self, a0: QMouseEvent) -> None: # left button - if e.button() == 1: + if a0.button() == Qt.LeftButton: + a0.accept() self.open_game.emit(self.game) # right - elif e.button() == 2: + elif a0.button() == Qt.RightButton: pass # self.showMenu(e) diff --git a/rare/components/tabs/store/image_widget.py b/rare/components/tabs/store/image_widget.py index a89621cf..ec925943 100644 --- a/rare/components/tabs/store/image_widget.py +++ b/rare/components/tabs/store/image_widget.py @@ -1,10 +1,10 @@ -from typing import Dict - -from PyQt5.QtCore import QRect +from PyQt5.QtCore import QEvent, QObject from PyQt5.QtCore import Qt from PyQt5.QtGui import ( QPixmap, - QImage, QMovie, + QImage, + QMovie, + QShowEvent, ) from PyQt5.QtWidgets import ( QWidget, @@ -24,19 +24,43 @@ class WaitingSpinner(QLabel): super(WaitingSpinner, self).__init__(parent=parent) self.setObjectName(type(self).__name__) self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) - self.movie = QMovie(":/images/loader.gif") + 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 setGeometry(self, a0: QRect) -> None: - self.rect().moveCenter(self.parent().rect().center()) - super(WaitingSpinner, self).setGeometry(self.rect()) + 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() @@ -44,6 +68,7 @@ class IconWidget(object): def __init__(self): self.mini_widget: QWidget = None self.title_label: QLabel = None + self.developer_label: QLabel = None self.price_label: QLabel = None self.discount_label: QLabel = None @@ -57,19 +82,24 @@ class IconWidget(object): self.title_label = QLabel(parent=self.mini_widget) self.title_label.setObjectName(f"{type(self).__name__}TitleLabel") self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - self.title_label.setAlignment(Qt.AlignVCenter) + self.title_label.setAlignment(Qt.AlignTop) self.title_label.setAutoFillBackground(False) self.title_label.setWordWrap(True) # information below title + self.developer_label = QLabel(parent=self.mini_widget) + self.developer_label.setObjectName(f"{type(self).__name__}TooltipLabel") + self.developer_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) + self.developer_label.setAutoFillBackground(False) + self.price_label = QLabel(parent=self.mini_widget) self.price_label.setObjectName(f"{type(self).__name__}TooltipLabel") - self.price_label.setAlignment(Qt.AlignRight) + self.price_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.price_label.setAutoFillBackground(False) self.discount_label = QLabel(parent=self.mini_widget) self.discount_label.setObjectName(f"{type(self).__name__}TooltipLabel") - self.discount_label.setAlignment(Qt.AlignRight) + self.discount_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.discount_label.setAutoFillBackground(False) # Create layouts @@ -88,7 +118,8 @@ class IconWidget(object): # Layout the widgets # (from inner to outer) - row_layout.addWidget(self.price_label, stretch=2) + row_layout.addWidget(self.developer_label, stretch=2) + row_layout.addWidget(self.price_label) row_layout.addWidget(self.discount_label) mini_layout.addWidget(self.title_label) mini_layout.addLayout(row_layout) @@ -100,45 +131,29 @@ class IconWidget(object): class ShopImageWidget(ImageWidget): - __image_cache: Dict[str, Dict[str, QPixmap]] = {} - - def __init__(self, parent=None): + def __init__(self, manager: QtRequestManager, parent=None): super(ShopImageWidget, self).__init__(parent=parent) self.ui = IconWidget() self.spinner = WaitingSpinner(parent=self) self.spinner.setVisible(False) - self.manager = QtRequestManager("bytes") - self.app_id = "" - self.orientation = "" + self.manager = manager - def fetchPixmap(self, url, app_id: str, title: str = ""): + def fetchPixmap(self, url): self.setPixmap(QPixmap()) - self.app_id = app_id - if self._image_size.size.width() > self._image_size.size.height(): - self.orientation = "wide" - else: - self.orientation = "tall" - - if ShopImageWidget.__image_cache.get(self.app_id, None) is not None: - if pixmap := ShopImageWidget.__image_cache[self.app_id].get(self.orientation, None): - self.setPixmap(pixmap) - return self.spinner.setFixedSize(self._image_size.size) - self.spinner.setVisible(True) self.spinner.start() - self.manager.get( - url, self.__on_image_ready, payload={ - "resize": 1, "w": self._image_size.size.width(), "h": self._image_size.size.height() - } - ) + self.manager.get(url, self.__on_image_ready, params={ + "resize": 1, + "w": self._image_size.base.size.width(), + "h": self._image_size.base.size.height(), + }) def __on_image_ready(self, data): cover = QImage() cover.loadFromData(data) - cover = cover.scaled(self._image_size.size, Qt.KeepAspectRatio, Qt.SmoothTransformation) + # cover = cover.scaled(self._image_size.size, Qt.KeepAspectRatio, Qt.SmoothTransformation) + cover.setDevicePixelRatio(self._image_size.base.pixel_ratio) cover = cover.convertToFormat(QImage.Format_ARGB32_Premultiplied) cover = QPixmap(cover) - ShopImageWidget.__image_cache.update({self.app_id: {self.orientation: cover}}) - super(ShopImageWidget, self).setPixmap(cover) + self.setPixmap(cover) self.spinner.stop() - self.spinner.setVisible(False) diff --git a/rare/components/tabs/store/search_results.py b/rare/components/tabs/store/search_results.py index 5e34e889..9860781e 100644 --- a/rare/components/tabs/store/search_results.py +++ b/rare/components/tabs/store/search_results.py @@ -2,36 +2,36 @@ from PyQt5.QtCore import Qt from PyQt5.QtCore import pyqtSignal from PyQt5.QtGui import QMouseEvent from PyQt5.QtWidgets import ( - QFrame, QWidget, - QVBoxLayout, QSizePolicy, - QLabel, + QLabel, QScrollArea, ) from rare.shared.image_manager import ImageSize +from rare.utils.qt_requests import QtRequestManager from rare.widgets.flow_layout import FlowLayout +from rare.widgets.side_tab import SideTabContents from .image_widget import ShopImageWidget -class SearchResults(QWidget): +class SearchResults(QScrollArea, SideTabContents): show_info = pyqtSignal(dict) def __init__(self, api_core, parent=None): super(SearchResults, self).__init__(parent=parent) + self.implements_scrollarea = True self.api_core = api_core - self.results_frame = QFrame(self) - self.results_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - self.results_frame.setFrameStyle(QFrame.StyledPanel) - self.results_layout = FlowLayout(self.results_frame) - self.results_frame.setLayout(self.results_layout) + self.results_container = QWidget(self) + self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.results_layout = FlowLayout(self.results_container) + self.setWidget(self.results_container) + self.setWidgetResizable(True) - self.main_layout = QVBoxLayout() - self.main_layout.setContentsMargins(0, 0, 0, 0) - self.main_layout.addWidget(self.results_frame) + # self.main_layout = QVBoxLayout(self) + # self.main_layout.setContentsMargins(0, 0, 0, 0) + # self.main_layout.addWidget(self.results_scrollarea) - self.setLayout(self.main_layout) self.setEnabled(False) def load_results(self, text: str): @@ -40,10 +40,10 @@ class SearchResults(QWidget): self.api_core.search_game(text, self.show_results) def show_results(self, results: dict): - for w in self.results_frame.findChildren(QLabel, options=Qt.FindDirectChildrenOnly): + for w in self.results_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly): self.results_layout.removeWidget(w) w.deleteLater() - for w in self.results_frame.findChildren(SearchResultItem, options=Qt.FindDirectChildrenOnly): + for w in self.results_container.findChildren(SearchResultItem, options=Qt.FindDirectChildrenOnly): self.results_layout.removeWidget(w) w.deleteLater() @@ -51,22 +51,23 @@ class SearchResults(QWidget): self.results_layout.addWidget(QLabel(self.tr("No results found"))) else: for res in results: - w = SearchResultItem(res, parent=self.results_frame) + w = SearchResultItem(self.api_core.cached_manager, res, parent=self.results_container) w.show_info.connect(self.show_info.emit) self.results_layout.addWidget(w) + self.results_layout.update() self.setEnabled(True) class SearchResultItem(ShopImageWidget): show_info = pyqtSignal(dict) - def __init__(self, result: dict, parent=None): - super(SearchResultItem, self).__init__(parent=parent) + def __init__(self, manager: QtRequestManager, result: dict, parent=None): + super(SearchResultItem, self).__init__(manager, parent=parent) self.setFixedSize(ImageSize.Normal) self.ui.setupUi(self) for img in result["keyImages"]: if img["type"] in ["DieselStoreFrontTall", "OfferImageTall", "Thumbnail", "ProductLogo"]: - self.fetchPixmap(img["url"], result["id"], result["title"]) + self.fetchPixmap(img["url"]) break else: print("No image found") diff --git a/rare/components/tabs/store/shop_api_core.py b/rare/components/tabs/store/shop_api_core.py index 906ef814..5d411b04 100644 --- a/rare/components/tabs/store/shop_api_core.py +++ b/rare/components/tabs/store/shop_api_core.py @@ -1,4 +1,3 @@ -import urllib.parse from logging import getLogger from PyQt5.QtCore import pyqtSignal, QObject @@ -10,31 +9,37 @@ from rare.components.tabs.store.constants import ( remove_from_wishlist_query, ) from rare.components.tabs.store.shop_models import BrowseModel +from rare.utils.paths import cache_dir from rare.utils.qt_requests import QtRequests logger = getLogger("ShopAPICore") -graphql_url = "https://www.epicgames.com/graphql" +graphql_url = "https://graphql.epicgames.com/graphql" class ShopApiCore(QObject): update_wishlist = pyqtSignal() - def __init__(self, auth_token, lc: str, cc: str): + def __init__(self, token, language: str, country: str): super(ShopApiCore, self).__init__() - self.token = auth_token - self.language_code: str = lc - self.country_code: str = cc + self.token = token + self.language_code: str = language + self.country_code: str = country self.locale = f"{self.language_code}-{self.country_code}" self.manager = QtRequests(parent=self) - self.auth_manager = QtRequests(token=auth_token, parent=self) + self.authed_manager = QtRequests(token=token, parent=self) + self.cached_manager = QtRequests(cache=str(cache_dir().joinpath("store")), parent=self) self.browse_active = False self.next_browse_request = tuple(()) def get_free_games(self, handle_func: callable): - url = f"https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale={self.language_code}&country={self.country_code}&allowCountries={self.country_code}" - - self.manager.get(url, lambda data: self._handle_free_games(data, handle_func)) + url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions" + params = { + "locale": self.locale, + "country": self.country_code, + "allowCountries": self.country_code, + } + self.manager.get(url, lambda data: self._handle_free_games(data, handle_func), params=params) def _handle_free_games(self, data, handle_func): try: @@ -50,14 +55,14 @@ class ShopApiCore(QObject): handle_func(results) def get_wishlist(self, handle_func): - self.auth_manager.post( + self.authed_manager.post( graphql_url, lambda data: self._handle_wishlist(data, handle_func), { "query": wishlist_query, "variables": { "country": self.country_code, - "locale": f"{self.language_code}-{self.country_code}", + "locale": self.locale, }, }, ) @@ -94,9 +99,7 @@ class ShopApiCore(QObject): }, } - self.manager.post( - graphql_url, lambda data: self._handle_search(data, handle_func), payload, - ) + self.manager.post(graphql_url, lambda data: self._handle_search(data, handle_func), payload) def _handle_search(self, data, handle_func): try: @@ -114,37 +117,11 @@ class ShopApiCore(QObject): self.next_browse_request = (browse_model, handle_func) return self.browse_active = True - url = "https://www.epicgames.com/graphql?operationName=searchStoreQuery&variables={}&extensions={}" - variables = urllib.parse.quote_plus(str( - dict(browse_model.__dict__)) - ) - extensions = urllib.parse.quote_plus(str( - dict( - persistedQuery=dict( - version=1, - sha256Hash="6e7c4dd0177150eb9a47d624be221929582df8648e7ec271c821838ff4ee148e" - ) - ) - ) - ) - - for old, new in [ - ("%26", "&"), - ("%27", "%22"), - ("+", ""), - ("%3A", ":"), - ("%2C", ","), - ("%5B", "["), - ("%5D", "]"), - ("True", "true"), - ]: - variables = variables.replace(old, new) - extensions = extensions.replace(old, new) - - url = url.format(variables, extensions) - self.auth_manager.get( - url, lambda data: self._handle_browse_games(data, handle_func) - ) + payload = { + "query": search_query, + "variables": browse_model.__dict__ + } + self.manager.post(graphql_url, lambda data: self._handle_browse_games(data, handle_func), payload) def _handle_browse_games(self, data, handle_func): self.browse_active = False @@ -188,11 +165,7 @@ class ShopApiCore(QObject): }, "query": add_to_wishlist_query, } - self.auth_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): try: @@ -215,11 +188,8 @@ class ShopApiCore(QObject): }, "query": remove_from_wishlist_query, } - self.auth_manager.post( - graphql_url, - lambda data: self._handle_remove_from_wishlist(data, handle_func), - payload, - ) + self.authed_manager.post(graphql_url, lambda data: self._handle_remove_from_wishlist(data, handle_func), + payload) def _handle_remove_from_wishlist(self, data, handle_func): try: diff --git a/rare/components/tabs/store/shop_models.py b/rare/components/tabs/store/shop_models.py index d6bb0054..f124c317 100644 --- a/rare/components/tabs/store/shop_models.py +++ b/rare/components/tabs/store/shop_models.py @@ -1,6 +1,7 @@ import datetime from dataclasses import dataclass from typing import List, Dict +import epicstore_api.queries as egs_query class ImageUrlModel: @@ -158,22 +159,26 @@ class BrowseModel: price: str = "" onSale: bool = False + def __post_init__(self): + self.locale = f"{self.language_code}-{self.country_code}" + @property def __dict__(self): payload = { - "allowCountries": self.country_code, - "category": self.category, "count": self.count, - "country": self.country_code, - "keywords": self.keywords, - "locale": self.language_code, - "priceRange": self.price, - "releaseDate": self.date, + "category": self.category, + "allowCountries": self.country_code, + "namespace": "", "sortBy": "releaseDate", "sortDir": self.sortDir, "start": self.start, + "keywords": self.keywords, "tag": self.tag, + "priceRange": self.price, + "releaseDate": self.date, "withPrice": self.withPrice, + "locale": self.locale, + "country": self.country_code, } if self.price == "free": payload["freeGame"] = True @@ -187,5 +192,4 @@ class BrowseModel: payload["effectiveDate"] = self.date else: payload.pop("priceRange") - return payload diff --git a/rare/components/tabs/store/shop_widget.py b/rare/components/tabs/store/shop_widget.py index 20b3903b..f8cf9a85 100644 --- a/rare/components/tabs/store/shop_widget.py +++ b/rare/components/tabs/store/shop_widget.py @@ -9,15 +9,17 @@ from PyQt5.QtWidgets import ( QLabel, QPushButton, QHBoxLayout, - QWidget, QSizePolicy, + QWidget, QSizePolicy, QStackedLayout, ) from legendary.core import LegendaryCore from rare.ui.components.tabs.store.store import Ui_ShopWidget -from rare.utils.extra_widgets import WaitingSpinner, ButtonLineEdit +from rare.utils.extra_widgets import ButtonLineEdit from rare.widgets.flow_layout import FlowLayout +from rare.widgets.side_tab import SideTabContents from .constants import Constants from .game_widgets import GameWidget +from .image_widget import WaitingSpinner from .shop_api_core import ShopApiCore from .shop_models import BrowseModel @@ -25,14 +27,16 @@ logger = logging.getLogger("Shop") # noinspection PyAttributeOutsideInit,PyBroadException -class ShopWidget(QWidget, Ui_ShopWidget): +class ShopWidget(QWidget, SideTabContents): show_info = pyqtSignal(str) show_game = pyqtSignal(dict) - def __init__(self, path, core: LegendaryCore, shop_api: ShopApiCore, parent=None): + def __init__(self, cache_dir, core: LegendaryCore, shop_api: ShopApiCore, parent=None): super(ShopWidget, self).__init__(parent=parent) - self.setupUi(self) - self.path = path + self.implements_scrollarea = True + self.ui = Ui_ShopWidget() + self.ui.setupUi(self) + self.cache_dir = cache_dir self.core = core self.api_core = shop_api self.price = "" @@ -40,25 +44,39 @@ class ShopWidget(QWidget, Ui_ShopWidget): self.types = [] self.update_games_allowed = True - self.free_scrollarea.setDisabled(True) + self.ui.free_scrollarea.setDisabled(True) self.free_game_widgets = [] self.active_search_request = False self.next_search = "" self.wishlist: List = [] - self.discount_widget.setLayout(FlowLayout(self.discount_widget)) - self.discount_stack.addWidget(WaitingSpinner(self.discount_stack)) - self.discount_stack.setCurrentIndex(1) + self.discounts_layout = QStackedLayout(self.ui.discounts_group) + self.discounts_spinner = WaitingSpinner(self.ui.discounts_group) + self.discounts_flow = QWidget(self.ui.discounts_group) + self.discounts_flow.setLayout(FlowLayout(self.discounts_flow)) + self.discounts_flow.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.discounts_layout.addWidget(self.discounts_spinner) + self.discounts_layout.addWidget(self.discounts_flow) - self.game_widget.setLayout(FlowLayout(self.game_widget)) - self.game_stack.addWidget(WaitingSpinner(self.game_stack)) - self.game_stack.setCurrentIndex(1) + self.discounts_spinner.start() + self.discounts_layout.setCurrentWidget(self.discounts_spinner) + + self.games_layout = QStackedLayout(self.ui.games_group) + self.games_spinner = WaitingSpinner(self.ui.games_group) + self.games_flow = QWidget(self.ui.games_group) + 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_layout.setCurrentWidget(self.games_spinner) self.search_bar = ButtonLineEdit( "fa.search", placeholder_text=self.tr("Search Games") ) - self.left_layout.insertWidget(0, self.search_bar) + self.ui.left_layout.insertWidget(0, self.search_bar) # self.search_bar.textChanged.connect(self.search_games) @@ -85,22 +103,21 @@ class ShopWidget(QWidget, Ui_ShopWidget): self.api_core.get_wishlist(self.add_wishlist_items) def add_wishlist_items(self, wishlist): - for i in range(self.discount_widget.layout().count()): - item = self.discount_widget.layout().itemAt(i) - if item: - item.widget().deleteLater() + for w in self.discounts_flow.findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly): + self.discounts_flow.layout().removeWidget(w) + w.deleteLater() - if wishlist and wishlist[0] == "error": - self.discount_widget.layout().addWidget( - QLabel(self.tr("Failed to get wishlist: {}").format(wishlist[1])) - ) - btn = QPushButton(self.tr("Reload")) - self.discount_widget.layout().addWidget(btn) - btn.clicked.connect( - lambda: self.api_core.get_wishlist(self.add_wishlist_items) - ) - self.discount_stack.setCurrentIndex(0) - return + # if wishlist and wishlist[0] == "error": + # self.discounts_group.layout().addWidget( + # QLabel(self.tr("Failed to get wishlist: {}").format(wishlist[1])) + # ) + # btn = QPushButton(self.tr("Reload")) + # self.discount_widget.layout().addWidget(btn) + # btn.clicked.connect( + # lambda: self.api_core.get_wishlist(self.add_wishlist_items) + # ) + # self.discount_stack.setCurrentIndex(0) + # return discounts = 0 for game in wishlist: @@ -108,48 +125,48 @@ class ShopWidget(QWidget, Ui_ShopWidget): continue try: if game["offer"]["price"]["totalPrice"]["discount"] > 0: - w = GameWidget(self.path, game["offer"]) + w = GameWidget(self.api_core.cached_manager, game["offer"]) w.show_info.connect(self.show_game) - self.discount_widget.layout().addWidget(w) + self.discounts_flow.layout().addWidget(w) discounts += 1 except Exception as e: logger.warning(f"{game} {e}") continue - self.discounts_group.setVisible(discounts > 0) - self.discount_stack.setCurrentIndex(0) - # fix widget overlay - self.discount_widget.layout().update() + self.ui.discounts_group.setVisible(discounts > 0) + self.discounts_layout.setCurrentWidget(self.discounts_flow) + # FIXME: FlowLayout doesn't update on adding widget + self.discounts_flow.layout().update() def add_free_games(self, free_games: list): - for w in self.free_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly): - self.free_container.layout().removeWidget(w) + for w in self.ui.free_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly): + self.ui.free_container.layout().removeWidget(w) w.deleteLater() if free_games and free_games[0] == "error": - self.free_container.layout().addWidget( + self.ui.free_container.layout().addWidget( QLabel(self.tr("Failed to fetch free games: {}").format(free_games[1])) ) btn = QPushButton(self.tr("Reload")) - self.free_container.layout().addWidget(btn) + self.ui.free_container.layout().addWidget(btn) btn.clicked.connect( lambda: self.api_core.get_free_games(self.add_free_games) ) - self.free_container.setEnabled(True) + self.ui.free_container.setEnabled(True) return - self.free_games_now = QGroupBox(self.tr("Free now"), parent=self.free_container) + self.free_games_now = QGroupBox(self.tr("Free now"), parent=self.ui.free_container) free_games_now_layout = QHBoxLayout(self.free_games_now) # free_games_now_layout.setContentsMargins(0, 0, 0, 0) - self.free_games_now.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.free_games_now.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.free_games_now.setLayout(free_games_now_layout) - self.free_container.layout().addWidget(self.free_games_now) + self.ui.free_container.layout().addWidget(self.free_games_now) - self.free_games_next = QGroupBox(self.tr("Free next week"), parent=self.free_container) + self.free_games_next = QGroupBox(self.tr("Free next week"), parent=self.ui.free_container) free_games_next_layout = QHBoxLayout(self.free_games_next) # free_games_next_layout.setContentsMargins(0, 0, 0, 0) - self.free_games_next.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.free_games_next.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.free_games_next.setLayout(free_games_next_layout) - self.free_container.layout().addWidget(self.free_games_next) + self.ui.free_container.layout().addWidget(self.free_games_next) date = datetime.datetime.now() free_games_now = [] @@ -200,7 +217,7 @@ class ShopWidget(QWidget, Ui_ShopWidget): # free games now now_free = 0 for free_game in free_games_now: - w = GameWidget(self.path, free_game) + w = GameWidget(self.api_core.cached_manager, free_game) w.show_info.connect(self.show_game) self.free_games_now.layout().addWidget(w) self.free_game_widgets.append(w) @@ -212,64 +229,64 @@ class ShopWidget(QWidget, Ui_ShopWidget): # free games next week for free_game in coming_free_games: - w = GameWidget(self.path, free_game) + w = GameWidget(self.api_core.cached_manager, free_game) if free_game["title"] != "Mystery Game": w.show_info.connect(self.show_game) self.free_games_next.layout().addWidget(w) # self.coming_free_games.setFixedWidth(int(40 + len(coming_free_games) * 300)) - self.free_scrollarea.setMinimumHeight( + self.ui.free_scrollarea.setMinimumHeight( self.free_games_now.sizeHint().height() - + self.free_container.layout().contentsMargins().top() - + self.free_container.layout().contentsMargins().bottom() - + self.free_scrollarea.horizontalScrollBar().sizeHint().height() + + self.ui.free_container.layout().contentsMargins().top() + + self.ui.free_container.layout().contentsMargins().bottom() + + self.ui.free_scrollarea.horizontalScrollBar().sizeHint().height() ) - self.free_scrollarea.setEnabled(True) + self.ui.free_scrollarea.setEnabled(True) def show_search_results(self): if self.search_bar.text(): self.show_info.emit(self.search_bar.text()) def init_filter(self): - self.none_price.toggled.connect( - lambda: self.prepare_request("") if self.none_price.isChecked() else None + self.ui.none_price.toggled.connect( + lambda: self.prepare_request("") if self.ui.none_price.isChecked() else None ) - self.free_button.toggled.connect( + self.ui.free_button.toggled.connect( lambda: self.prepare_request("free") - if self.free_button.isChecked() + if self.ui.free_button.isChecked() else None ) - self.under10.toggled.connect( + self.ui.under10.toggled.connect( lambda: self.prepare_request("[0, 1000)") - if self.under10.isChecked() + if self.ui.under10.isChecked() else None ) - self.under20.toggled.connect( + self.ui.under20.toggled.connect( lambda: self.prepare_request("[0, 2000)") - if self.under20.isChecked() + if self.ui.under20.isChecked() else None ) - self.under30.toggled.connect( + self.ui.under30.toggled.connect( lambda: self.prepare_request("[0, 3000)") - if self.under30.isChecked() + if self.ui.under30.isChecked() else None ) - self.above.toggled.connect( + self.ui.above.toggled.connect( lambda: self.prepare_request("[1499,]") - if self.above.isChecked() + if self.ui.above.isChecked() else None ) # self.on_discount.toggled.connect(lambda: self.prepare_request("sale") if self.on_discount.isChecked() else None) - self.on_discount.toggled.connect(lambda: self.prepare_request()) + self.ui.on_discount.toggled.connect(lambda: self.prepare_request()) constants = Constants() self.checkboxes = [] for groupbox, variables in [ - (self.genre_group, constants.categories), - (self.platform_group, constants.platforms), - (self.others_group, constants.others), - (self.type_group, constants.types), + (self.ui.genre_group, constants.categories), + (self.ui.platform_group, constants.platforms), + (self.ui.others_group, constants.others), + (self.ui.type_group, constants.types), ]: for text, tag in variables: @@ -280,26 +297,26 @@ class ShopWidget(QWidget, Ui_ShopWidget): ) groupbox.layout().addWidget(checkbox) self.checkboxes.append(checkbox) - self.reset_button.clicked.connect(self.reset_filters) - self.filter_scrollarea.setMinimumWidth( - self.filter_container.sizeHint().width() - + self.filter_container.layout().contentsMargins().left() - + self.filter_container.layout().contentsMargins().right() - + self.filter_scrollarea.verticalScrollBar().sizeHint().width() + self.ui.reset_button.clicked.connect(self.reset_filters) + self.ui.filter_scrollarea.setMinimumWidth( + self.ui.filter_container.sizeHint().width() + + self.ui.filter_container.layout().contentsMargins().left() + + self.ui.filter_container.layout().contentsMargins().right() + + self.ui.filter_scrollarea.verticalScrollBar().sizeHint().width() ) def reset_filters(self): self.update_games_allowed = False for cb in self.checkboxes: cb.setChecked(False) - self.none_price.setChecked(True) + self.ui.none_price.setChecked(True) self.tags = [] self.types = [] self.update_games_allowed = True self.prepare_request("") - self.on_discount.setChecked(False) + self.ui.on_discount.setChecked(False) def prepare_request( self, @@ -323,22 +340,22 @@ class ShopWidget(QWidget, Ui_ShopWidget): self.types.append(added_type) if removed_type and removed_type in self.types: self.types.remove(removed_type) - if (self.types or self.price) or self.tags or self.on_discount.isChecked(): - self.free_scrollarea.setVisible(False) - self.discounts_group.setVisible(False) + if (self.types or self.price) or self.tags or self.ui.on_discount.isChecked(): + self.ui.free_scrollarea.setVisible(False) + self.ui.discounts_group.setVisible(False) else: - self.free_scrollarea.setVisible(True) - if len(self.discounts_group.layout().children()) > 0: - self.discounts_group.setVisible(True) + self.ui.free_scrollarea.setVisible(True) + if len(self.ui.discounts_group.layout().children()) > 0: + self.ui.discounts_group.setVisible(True) - self.game_stack.setCurrentIndex(1) + self.games_layout.setCurrentWidget(self.games_spinner) browse_model = BrowseModel( language_code=self.core.language_code, country_code=self.core.country_code, count=20, price=self.price, - onSale=self.on_discount.isChecked(), + onSale=self.ui.on_discount.isChecked(), ) browse_model.tag = "|".join(self.tags) @@ -347,24 +364,22 @@ class ShopWidget(QWidget, Ui_ShopWidget): self.api_core.browse_games(browse_model, self.show_games) def show_games(self, data): - for item in ( - self.game_widget.layout().itemAt(i) - for i in range(self.game_widget.layout().count()) - ): - item.widget().deleteLater() + for w in self.games_flow.layout().findChildren(GameWidget, options=Qt.FindDirectChildrenOnly): + self.games_flow.layout().removeWidget(w) + w.deleteLater() + if data: for game in data: - w = GameWidget(self.path, game) - self.game_widget.layout().addWidget(w) + w = GameWidget(self.api_core.cached_manager, game) w.show_info.connect(self.show_game.emit) - + self.games_flow.layout().addWidget(w) else: - self.game_widget.layout().addWidget( + self.games_flow.layout().addWidget( QLabel(self.tr("Could not get games matching the filter")) ) - self.game_stack.setCurrentIndex(0) - - self.game_widget.layout().update() + self.games_layout.setCurrentWidget(self.games_flow) + # FIXME: FlowLayout doesn't update on adding widget + self.games_flow.layout().update() class CheckBox(QCheckBox): diff --git a/rare/components/tabs/store/wishlist.py b/rare/components/tabs/store/wishlist.py index 06a2d41d..0da63f44 100644 --- a/rare/components/tabs/store/wishlist.py +++ b/rare/components/tabs/store/wishlist.py @@ -1,9 +1,10 @@ -from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtWidgets import QMessageBox, QWidget from rare.ui.components.tabs.store.wishlist import Ui_Wishlist from rare.utils.misc import icon from rare.widgets.side_tab import SideTabContents +from rare.widgets.flow_layout import FlowLayout from .shop_api_core import ShopApiCore from .game_widgets import WishlistWidget @@ -14,6 +15,7 @@ class Wishlist(QWidget, SideTabContents): def __init__(self, api_core: ShopApiCore, parent=None): super(Wishlist, self).__init__(parent=parent) + self.implements_scrollarea = True self.api_core = api_core self.ui = Ui_Wishlist() self.ui.setupUi(self) @@ -21,20 +23,19 @@ class Wishlist(QWidget, SideTabContents): self.wishlist = [] self.widgets = [] - self.ui.sort_cb.currentIndexChanged.connect( - lambda i: self.set_wishlist(self.wishlist, i) - ) + self.list_layout = FlowLayout(self.ui.list_container) + + self.ui.sort_cb.currentIndexChanged.connect(self.sort_wishlist) self.ui.filter_cb.currentIndexChanged.connect(self.set_filter) self.ui.reload_button.clicked.connect(self.update_wishlist) self.ui.reload_button.setIcon(icon("fa.refresh", color="white")) self.ui.reverse.stateChanged.connect( - lambda: self.set_wishlist(sort=self.ui.sort_cb.currentIndex()) + lambda: self.sort_wishlist(sort=self.ui.sort_cb.currentIndex()) ) def update_wishlist(self): self.setEnabled(False) - self.set_title.emit("Wishlist") self.api_core.get_wishlist(self.set_wishlist) def delete_from_wishlist(self, game): @@ -66,6 +67,32 @@ class Wishlist(QWidget, SideTabContents): else: self.ui.no_games_label.setVisible(False) + def sort_wishlist(self, sort=0): + widgets = self.ui.list_container.findChildren(WishlistWidget, options=Qt.FindDirectChildrenOnly) + for w in widgets: + self.ui.list_container.layout().removeWidget(w) + + if sort == 0: + func = lambda x: x.game["title"] + reverse = self.ui.reverse.isChecked() + elif sort == 1: + func = lambda x: x.game["price"]["totalPrice"]["fmtPrice"]["discountPrice"] + reverse = self.ui.reverse.isChecked() + elif sort == 2: + func = lambda x: x.game["seller"]["name"] + reverse = self.ui.reverse.isChecked() + elif sort == 3: + func = lambda x: 1 - (x.game["price"]["totalPrice"]["discountPrice"] / x.game["price"]["totalPrice"]["originalPrice"]) + reverse = not self.ui.reverse.isChecked() + else: + func = lambda x: x.game["title"] + reverse = self.ui.reverse.isChecked() + + widgets = sorted(widgets, key=func, reverse=reverse) + for w in widgets: + self.ui.list_container.layout().addWidget(w) + + def set_wishlist(self, wishlist=None, sort=0): if wishlist and wishlist[0] == "error": return @@ -76,45 +103,18 @@ class Wishlist(QWidget, SideTabContents): for i in self.widgets: i.deleteLater() - if sort == 0: - sorted_list = sorted(self.wishlist, key=lambda x: x["offer"]["title"]) - elif sort == 1: - sorted_list = sorted( - self.wishlist, - key=lambda x: x["offer"]["price"]["totalPrice"]["fmtPrice"][ - "discountPrice" - ], - ) - elif sort == 2: - sorted_list = sorted( - self.wishlist, key=lambda x: x["offer"]["seller"]["name"] - ) - elif sort == 3: - sorted_list = sorted( - self.wishlist, - reverse=True, - key=lambda x: 1 - - ( - x["offer"]["price"]["totalPrice"]["discountPrice"] - / x["offer"]["price"]["totalPrice"]["originalPrice"] - ), - ) - else: - sorted_list = self.wishlist self.widgets.clear() - if len(sorted_list) == 0: + if len(wishlist) == 0: self.ui.no_games_label.setVisible(True) else: self.ui.no_games_label.setVisible(False) - if self.ui.reverse.isChecked(): - sorted_list.reverse() - - for game in sorted_list: - w = WishlistWidget(game["offer"]) - self.widgets.append(w) - self.ui.list_layout.addWidget(w) + for game in wishlist: + w = WishlistWidget(self.api_core.cached_manager, game["offer"], self.ui.list_container) w.open_game.connect(self.show_game_info.emit) w.delete_from_wishlist.connect(self.delete_from_wishlist) + self.widgets.append(w) + self.list_layout.addWidget(w) + self.list_layout.update() self.setEnabled(True) diff --git a/rare/ui/components/tabs/store/shop_game_info.py b/rare/ui/components/tabs/store/shop_game_info.py index 839506e1..f0c8b720 100644 --- a/rare/ui/components/tabs/store/shop_game_info.py +++ b/rare/ui/components/tabs/store/shop_game_info.py @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_ShopInfo(object): def setupUi(self, ShopInfo): ShopInfo.setObjectName("ShopInfo") - ShopInfo.resize(434, 250) + ShopInfo.resize(747, 442) ShopInfo.setWindowTitle("ShopGameInfo") self.main_layout = QtWidgets.QHBoxLayout(ShopInfo) self.main_layout.setObjectName("main_layout") diff --git a/rare/ui/components/tabs/store/shop_game_info.ui b/rare/ui/components/tabs/store/shop_game_info.ui index 382dcf92..802e6fd2 100644 --- a/rare/ui/components/tabs/store/shop_game_info.ui +++ b/rare/ui/components/tabs/store/shop_game_info.ui @@ -6,8 +6,8 @@ 0 0 - 434 - 250 + 747 + 442 diff --git a/rare/ui/components/tabs/store/store.py b/rare/ui/components/tabs/store/store.py index 3fe0fa68..90c13f3b 100644 --- a/rare/ui/components/tabs/store/store.py +++ b/rare/ui/components/tabs/store/store.py @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_ShopWidget(object): def setupUi(self, ShopWidget): ShopWidget.setObjectName("ShopWidget") - ShopWidget.resize(750, 588) + ShopWidget.resize(350, 382) ShopWidget.setWindowTitle("Store") self.shop_layout = QtWidgets.QHBoxLayout(ShopWidget) self.shop_layout.setObjectName("shop_layout") @@ -27,7 +27,7 @@ class Ui_ShopWidget(object): self.games_scrollarea.setWidgetResizable(True) self.games_scrollarea.setObjectName("games_scrollarea") self.games_container = QtWidgets.QWidget() - self.games_container.setGeometry(QtCore.QRect(0, 0, 583, 574)) + self.games_container.setGeometry(QtCore.QRect(0, 0, 186, 368)) self.games_container.setObjectName("games_container") self.games_container_layout = QtWidgets.QVBoxLayout(self.games_container) self.games_container_layout.setContentsMargins(0, 0, 3, 0) @@ -44,7 +44,12 @@ class Ui_ShopWidget(object): self.free_scrollarea.setWidgetResizable(True) self.free_scrollarea.setObjectName("free_scrollarea") self.free_container = QtWidgets.QWidget() - self.free_container.setGeometry(QtCore.QRect(0, 0, 580, 83)) + 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) @@ -53,25 +58,9 @@ class Ui_ShopWidget(object): self.games_container_layout.addWidget(self.free_scrollarea) self.discounts_group = QtWidgets.QGroupBox(self.games_container) self.discounts_group.setObjectName("discounts_group") - self.discounts_layout = QtWidgets.QVBoxLayout(self.discounts_group) - self.discounts_layout.setObjectName("discounts_layout") - self.discount_stack = QtWidgets.QStackedWidget(self.discounts_group) - self.discount_stack.setObjectName("discount_stack") - self.discount_widget = QtWidgets.QWidget() - self.discount_widget.setObjectName("discount_widget") - self.discount_stack.addWidget(self.discount_widget) - self.discounts_layout.addWidget(self.discount_stack) self.games_container_layout.addWidget(self.discounts_group) self.games_group = QtWidgets.QGroupBox(self.games_container) self.games_group.setObjectName("games_group") - self.games_layout = QtWidgets.QVBoxLayout(self.games_group) - self.games_layout.setObjectName("games_layout") - self.game_stack = QtWidgets.QStackedWidget(self.games_group) - self.game_stack.setObjectName("game_stack") - self.game_widget = QtWidgets.QWidget() - self.game_widget.setObjectName("game_widget") - self.game_stack.addWidget(self.game_widget) - self.games_layout.addWidget(self.game_stack) self.games_container_layout.addWidget(self.games_group) self.games_scrollarea.setWidget(self.games_container) self.left_layout.addWidget(self.games_scrollarea) @@ -94,7 +83,12 @@ class Ui_ShopWidget(object): self.filter_scrollarea.setWidgetResizable(True) self.filter_scrollarea.setObjectName("filter_scrollarea") self.filter_container = QtWidgets.QWidget() - self.filter_container.setGeometry(QtCore.QRect(0, 0, 145, 542)) + self.filter_container.setGeometry(QtCore.QRect(0, 0, 142, 390)) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filter_container.sizePolicy().hasHeightForWidth()) + self.filter_container.setSizePolicy(sizePolicy) self.filter_container.setObjectName("filter_container") self.filter_container_layout = QtWidgets.QVBoxLayout(self.filter_container) self.filter_container_layout.setContentsMargins(0, 0, 3, 0) diff --git a/rare/ui/components/tabs/store/store.ui b/rare/ui/components/tabs/store/store.ui index c5350030..90ccdfa8 100644 --- a/rare/ui/components/tabs/store/store.ui +++ b/rare/ui/components/tabs/store/store.ui @@ -6,8 +6,8 @@ 0 0 - 750 - 588 + 679 + 329 @@ -35,8 +35,8 @@ 0 0 - 583 - 574 + 515 + 315 @@ -77,10 +77,16 @@ 0 0 - 580 - 83 + 16 + 16 + + + 0 + 0 + + 0 @@ -103,13 +109,6 @@ Discounts from your wishlist - - - - - - - @@ -117,13 +116,6 @@ Games - - - - - - - @@ -169,10 +161,16 @@ 0 0 - 145 - 542 + 142 + 390 + + + 0 + 0 + + 0 diff --git a/rare/ui/components/tabs/store/wishlist.py b/rare/ui/components/tabs/store/wishlist.py index 4a0fb0a2..66c042f6 100644 --- a/rare/ui/components/tabs/store/wishlist.py +++ b/rare/ui/components/tabs/store/wishlist.py @@ -14,12 +14,12 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Wishlist(object): def setupUi(self, Wishlist): Wishlist.setObjectName("Wishlist") - Wishlist.resize(527, 328) + Wishlist.resize(423, 153) Wishlist.setWindowTitle("Wishlist") self.verticalLayout = QtWidgets.QVBoxLayout(Wishlist) self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") + self.tool_layout = QtWidgets.QHBoxLayout() + self.tool_layout.setObjectName("tool_layout") self.sort_label = QtWidgets.QLabel(Wishlist) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -27,29 +27,29 @@ class Ui_Wishlist(object): sizePolicy.setHeightForWidth(self.sort_label.sizePolicy().hasHeightForWidth()) self.sort_label.setSizePolicy(sizePolicy) self.sort_label.setObjectName("sort_label") - self.horizontalLayout.addWidget(self.sort_label) + self.tool_layout.addWidget(self.sort_label) self.sort_cb = QtWidgets.QComboBox(Wishlist) self.sort_cb.setObjectName("sort_cb") self.sort_cb.addItem("") self.sort_cb.addItem("") self.sort_cb.addItem("") self.sort_cb.addItem("") - self.horizontalLayout.addWidget(self.sort_cb) + self.tool_layout.addWidget(self.sort_cb) self.reverse = QtWidgets.QCheckBox(Wishlist) self.reverse.setObjectName("reverse") - self.horizontalLayout.addWidget(self.reverse) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem) + self.tool_layout.addWidget(self.reverse) + spacerItem = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.tool_layout.addItem(spacerItem) self.filter_label = QtWidgets.QLabel(Wishlist) self.filter_label.setObjectName("filter_label") - self.horizontalLayout.addWidget(self.filter_label) + self.tool_layout.addWidget(self.filter_label) self.filter_cb = QtWidgets.QComboBox(Wishlist) self.filter_cb.setObjectName("filter_cb") self.filter_cb.addItem("") self.filter_cb.addItem("") - self.horizontalLayout.addWidget(self.filter_cb) - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem1) + self.tool_layout.addWidget(self.filter_cb) + spacerItem1 = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.tool_layout.addItem(spacerItem1) self.reload_button = QtWidgets.QPushButton(Wishlist) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -58,16 +58,19 @@ class Ui_Wishlist(object): self.reload_button.setSizePolicy(sizePolicy) self.reload_button.setText("") self.reload_button.setObjectName("reload_button") - self.horizontalLayout.addWidget(self.reload_button) - self.verticalLayout.addLayout(self.horizontalLayout) - self.list_layout = QtWidgets.QVBoxLayout() - self.list_layout.setObjectName("list_layout") - self.verticalLayout.addLayout(self.list_layout) + self.tool_layout.addWidget(self.reload_button) + self.verticalLayout.addLayout(self.tool_layout) self.no_games_label = QtWidgets.QLabel(Wishlist) self.no_games_label.setObjectName("no_games_label") self.verticalLayout.addWidget(self.no_games_label) - spacerItem2 = QtWidgets.QSpacerItem(379, 218, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem2) + self.list_scrollarea = QtWidgets.QScrollArea(Wishlist) + self.list_scrollarea.setWidgetResizable(True) + self.list_scrollarea.setObjectName("list_scrollarea") + self.list_container = QtWidgets.QWidget() + self.list_container.setGeometry(QtCore.QRect(0, 0, 407, 83)) + self.list_container.setObjectName("list_container") + self.list_scrollarea.setWidget(self.list_container) + self.verticalLayout.addWidget(self.list_scrollarea) self.retranslateUi(Wishlist) diff --git a/rare/ui/components/tabs/store/wishlist.ui b/rare/ui/components/tabs/store/wishlist.ui index a9560ec0..b28a8ce0 100644 --- a/rare/ui/components/tabs/store/wishlist.ui +++ b/rare/ui/components/tabs/store/wishlist.ui @@ -6,8 +6,8 @@ 0 0 - 527 - 328 + 423 + 153 @@ -15,7 +15,7 @@ - + @@ -61,14 +61,14 @@ - + Qt::Horizontal - 40 - 20 + 0 + 0 @@ -95,14 +95,14 @@ - + Qt::Horizontal - 40 - 20 + 0 + 0 @@ -122,9 +122,6 @@ - - - @@ -133,17 +130,21 @@ - - - Qt::Vertical + + + true - - - 379 - 218 - - - + + + + 0 + 0 + 407 + 83 + + + + diff --git a/rare/ui/components/tabs/store/wishlist_widget.py b/rare/ui/components/tabs/store/wishlist_widget.py index 47119608..7ea93faf 100644 --- a/rare/ui/components/tabs/store/wishlist_widget.py +++ b/rare/ui/components/tabs/store/wishlist_widget.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'rare/ui/components/tabs/store/wishlist_widget.ui' # -# Created by: PyQt5 UI code generator 5.15.7 +# Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -14,20 +14,26 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_WishlistWidget(object): def setupUi(self, WishlistWidget): WishlistWidget.setObjectName("WishlistWidget") - WishlistWidget.resize(523, 172) + WishlistWidget.resize(202, 94) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(WishlistWidget.sizePolicy().hasHeightForWidth()) + WishlistWidget.setSizePolicy(sizePolicy) WishlistWidget.setWindowTitle("WishlistWIdget") - self.horizontalLayout = QtWidgets.QHBoxLayout(WishlistWidget) - self.horizontalLayout.setObjectName("horizontalLayout") - self.widget = QtWidgets.QWidget(WishlistWidget) + self.main_layout = QtWidgets.QHBoxLayout(WishlistWidget) + self.main_layout.setContentsMargins(0, 0, 0, 0) + self.main_layout.setObjectName("main_layout") + self.info_widget = QtWidgets.QWidget(WishlistWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth()) - self.widget.setSizePolicy(sizePolicy) - self.widget.setObjectName("widget") - self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget) + sizePolicy.setHeightForWidth(self.info_widget.sizePolicy().hasHeightForWidth()) + self.info_widget.setSizePolicy(sizePolicy) + self.info_widget.setObjectName("info_widget") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.info_widget) self.verticalLayout_2.setObjectName("verticalLayout_2") - self.title_label = QtWidgets.QLabel(self.widget) + self.title_label = QtWidgets.QLabel(self.info_widget) font = QtGui.QFont() font.setPointSize(16) self.title_label.setFont(font) @@ -35,16 +41,16 @@ class Ui_WishlistWidget(object): self.title_label.setWordWrap(True) self.title_label.setObjectName("title_label") self.verticalLayout_2.addWidget(self.title_label) - self.developer = QtWidgets.QLabel(self.widget) + self.developer = QtWidgets.QLabel(self.info_widget) font = QtGui.QFont() font.setPointSize(12) self.developer.setFont(font) self.developer.setText("TextLabel") self.developer.setObjectName("developer") self.verticalLayout_2.addWidget(self.developer) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.discount_price = QtWidgets.QLabel(self.widget) + self.price_layout = QtWidgets.QHBoxLayout() + self.price_layout.setObjectName("price_layout") + self.discount_price = QtWidgets.QLabel(self.info_widget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -52,15 +58,13 @@ class Ui_WishlistWidget(object): self.discount_price.setSizePolicy(sizePolicy) self.discount_price.setText("TextLabel") self.discount_price.setObjectName("discount_price") - self.horizontalLayout_2.addWidget(self.discount_price) - self.price = QtWidgets.QLabel(self.widget) + self.price_layout.addWidget(self.discount_price) + self.price = QtWidgets.QLabel(self.info_widget) self.price.setText("TextLabel") self.price.setObjectName("price") - self.horizontalLayout_2.addWidget(self.price) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout_2.addItem(spacerItem) - self.horizontalLayout.addWidget(self.widget) + self.price_layout.addWidget(self.price) + self.verticalLayout_2.addLayout(self.price_layout) + self.main_layout.addWidget(self.info_widget, 0, QtCore.Qt.AlignTop) self.delete_button = QtWidgets.QPushButton(WishlistWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) @@ -69,7 +73,7 @@ class Ui_WishlistWidget(object): self.delete_button.setSizePolicy(sizePolicy) self.delete_button.setText("") self.delete_button.setObjectName("delete_button") - self.horizontalLayout.addWidget(self.delete_button) + self.main_layout.addWidget(self.delete_button) self.retranslateUi(WishlistWidget) diff --git a/rare/ui/components/tabs/store/wishlist_widget.ui b/rare/ui/components/tabs/store/wishlist_widget.ui index 63dc3640..5acbac6f 100644 --- a/rare/ui/components/tabs/store/wishlist_widget.ui +++ b/rare/ui/components/tabs/store/wishlist_widget.ui @@ -6,16 +6,34 @@ 0 0 - 523 - 172 + 202 + 94 + + + 0 + 0 + + WishlistWIdget - - - + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 @@ -51,7 +69,7 @@ - + @@ -74,19 +92,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - -