1
0
Fork 0
mirror of synced 2024-05-18 11:32:50 +12:00

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
This commit is contained in:
loathingKernel 2023-04-04 14:46:02 +03:00
parent 7246078df3
commit f6396f488a
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
18 changed files with 441 additions and 424 deletions

View file

@ -25,12 +25,12 @@ 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("Games")) 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.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))
@ -40,11 +40,11 @@ class StoreTab(SideTabWidget):
self.api_core, self.api_core,
parent=self 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.info.back_button.clicked.connect(lambda: self.setCurrentIndex(self.previous_index))
self.wishlist = Wishlist(self.api_core, parent=self) 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.update_wishlist_signal.connect(self.update_wishlist)
self.wishlist.show_game_info.connect(self.show_game) self.wishlist.show_game_info.connect(self.show_game)

View file

@ -27,9 +27,12 @@ if __name__ == "__main__":
import rare.resources.stylesheets.RareStyle import rare.resources.stylesheets.RareStyle
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setApplicationName("Rare")
app.setOrganizationName("Rare")
set_style_sheet("RareStyle") set_style_sheet("RareStyle")
window = StoreWindow() window = StoreWindow()
window.setWindowTitle(f"{app.applicationName()} - Store")
window.resize(QSize(1280, 800)) window.resize(QSize(1280, 800))
window.show() window.show()
app.exec() app.exec()

View file

@ -33,7 +33,7 @@ class ShopGameInfo(QWidget, SideTabContents):
self.api_core = api_core self.api_core = api_core
self.installed = installed_titles self.installed = installed_titles
self.ui.open_store_button.clicked.connect(self.button_clicked) 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.image.setFixedSize(ImageSize.Normal)
self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop) self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
@ -139,7 +139,7 @@ class ShopGameInfo(QWidget, SideTabContents):
"VaultClosed", "VaultClosed",
"ProductLogo", "ProductLogo",
]: ]:
self.image.fetchPixmap(img["url"], self.id_str, self.title_str) self.image.fetchPixmap(img["url"])
break break
self.price.setText("") self.price.setText("")
self.discount_price.setText("") self.discount_price.setText("")
@ -207,7 +207,7 @@ class ShopGameInfo(QWidget, SideTabContents):
img_url = self.game.image_urls.product_logo img_url = self.game.image_urls.product_logo
else: else:
img_url = "" img_url = ""
self.image.fetchPixmap(img_url, self.game.id, self.game.title) self.image.fetchPixmap(img_url)
# self.image_stack.setCurrentIndex(0) # self.image_stack.setCurrentIndex(0)
try: try:

View file

@ -1,15 +1,13 @@
import logging import logging
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QFont, QMouseEvent from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QPushButton
from rare.components.tabs.store.shop_models import ImageUrlModel from rare.components.tabs.store.shop_models import ImageUrlModel
from rare.shared.image_manager import ImageSize 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.misc import qta_icon
from rare.utils.qt_requests import QtRequestManager
from .image_widget import ShopImageWidget from .image_widget import ShopImageWidget
logger = logging.getLogger("GameWidgets") logger = logging.getLogger("GameWidgets")
@ -18,11 +16,10 @@ logger = logging.getLogger("GameWidgets")
class GameWidget(ShopImageWidget): class GameWidget(ShopImageWidget):
show_info = pyqtSignal(dict) show_info = pyqtSignal(dict)
def __init__(self, path, json_info=None, parent=None): def __init__(self, manager: QtRequestManager, json_info=None, parent=None):
super(GameWidget, self).__init__(parent=parent) super(GameWidget, self).__init__(manager, parent=parent)
self.setFixedSize(ImageSize.Wide) self.setFixedSize(ImageSize.Wide)
self.ui.setupUi(self) self.ui.setupUi(self)
self.path = path
self.json_info = json_info self.json_info = json_info
if json_info: if json_info:
self.init_ui(json_info) self.init_ui(json_info)
@ -33,6 +30,13 @@ class GameWidget(ShopImageWidget):
return return
self.ui.title_label.setText(json_info.get("title")) 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"] price = json_info["price"]["totalPrice"]["fmtPrice"]["originalPrice"]
discount_price = json_info["price"]["totalPrice"]["fmtPrice"]["discountPrice"] discount_price = json_info["price"]["totalPrice"]["fmtPrice"]["discountPrice"]
self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}') self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}')
@ -51,7 +55,7 @@ class GameWidget(ShopImageWidget):
if img["type"] in ["DieselStoreFrontWide", "OfferImageWide", "VaultClosed", "ProductLogo",]: if img["type"] in ["DieselStoreFrontWide", "OfferImageWide", "VaultClosed", "ProductLogo",]:
if img["type"] == "VaultClosed" and json_info["title"] != "Mystery Game": if img["type"] == "VaultClosed" and json_info["title"] != "Mystery Game":
continue continue
self.fetchPixmap(img["url"], json_info["id"], json_info["title"]) self.fetchPixmap(img["url"])
break break
else: else:
logger.info(", ".join([img["type"] for img in json_info["keyImages"]])) 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) self.show_info.emit(self.json_info)
class WishlistWidget(QWidget, Ui_WishlistWidget): class WishlistWidget(ShopImageWidget):
open_game = pyqtSignal(dict) open_game = pyqtSignal(dict)
delete_from_wishlist = pyqtSignal(dict) delete_from_wishlist = pyqtSignal(dict)
def __init__(self, game: dict): def __init__(self, manager: QtRequestManager, game: dict, parent=None):
super(WishlistWidget, self).__init__() super(WishlistWidget, self).__init__(manager, parent=parent)
self.setupUi(self) self.setFixedSize(ImageSize.Wide)
self.ui.setupUi(self)
self.game = game self.game = game
self.title_label.setText(game.get("title"))
for attr in game["customAttributes"]: for attr in game["customAttributes"]:
if attr["key"] == "developerName": if attr["key"] == "developerName":
self.developer.setText(attr["value"]) developer = attr["value"]
break break
else: else:
self.developer.setText(game["seller"]["name"]) developer = game["seller"]["name"]
original_price = game["price"]["totalPrice"]["fmtPrice"]["originalPrice"] original_price = game["price"]["totalPrice"]["fmtPrice"]["originalPrice"]
discount_price = game["price"]["totalPrice"]["fmtPrice"]["discountPrice"] discount_price = game["price"]["totalPrice"]["fmtPrice"]["discountPrice"]
self.price.setText(original_price if original_price != "0" else self.tr("Free")) self.ui.title_label.setText(game.get("title"))
# if discount 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: if original_price != discount_price:
self.discount = True font = self.ui.price_label.font()
font = QFont()
font.setStrikeOut(True) font.setStrikeOut(True)
self.price.setFont(font) self.ui.price_label.setFont(font)
self.discount_price.setText(discount_price) self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}')
else: else:
self.discount = False self.ui.discount_label.setVisible(False)
self.discount_price.setVisible(False)
self.image = ImageLabel()
self.layout().insertWidget(0, self.image)
image_model = ImageUrlModel.from_json(game["keyImages"]) image_model = ImageUrlModel.from_json(game["keyImages"])
url = image_model.front_wide url = image_model.front_wide
if not url: if not url:
url = image_model.offer_image_wide 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.setIcon(icon("mdi.delete", color="white"))
self.delete_button.clicked.connect( self.delete_button.clicked.connect(
lambda: self.delete_from_wishlist.emit(self.game) 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 # left button
if e.button() == 1: if a0.button() == Qt.LeftButton:
a0.accept()
self.open_game.emit(self.game) self.open_game.emit(self.game)
# right # right
elif e.button() == 2: elif a0.button() == Qt.RightButton:
pass # self.showMenu(e) pass # self.showMenu(e)

View file

@ -1,10 +1,10 @@
from typing import Dict from PyQt5.QtCore import QEvent, QObject
from PyQt5.QtCore import QRect
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QPixmap, QPixmap,
QImage, QMovie, QImage,
QMovie,
QShowEvent,
) )
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QWidget, QWidget,
@ -24,19 +24,43 @@ class WaitingSpinner(QLabel):
super(WaitingSpinner, self).__init__(parent=parent) super(WaitingSpinner, self).__init__(parent=parent)
self.setObjectName(type(self).__name__) self.setObjectName(type(self).__name__)
self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) 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) self.setMovie(self.movie)
if self.parent() is not None:
self.parent().installEventFilter(self)
if autostart: if autostart:
self.movie.start() self.movie.start()
def setGeometry(self, a0: QRect) -> None: def __center_on_parent(self):
self.rect().moveCenter(self.parent().rect().center()) rect = self.rect()
super(WaitingSpinner, self).setGeometry(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): def start(self):
self.setVisible(True)
self.movie.start() self.movie.start()
def stop(self): def stop(self):
self.setVisible(False)
self.movie.stop() self.movie.stop()
@ -44,6 +68,7 @@ class IconWidget(object):
def __init__(self): def __init__(self):
self.mini_widget: QWidget = None self.mini_widget: QWidget = None
self.title_label: QLabel = None self.title_label: QLabel = None
self.developer_label: QLabel = None
self.price_label: QLabel = None self.price_label: QLabel = None
self.discount_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 = QLabel(parent=self.mini_widget)
self.title_label.setObjectName(f"{type(self).__name__}TitleLabel") self.title_label.setObjectName(f"{type(self).__name__}TitleLabel")
self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) 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.setAutoFillBackground(False)
self.title_label.setWordWrap(True) self.title_label.setWordWrap(True)
# information below title # 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 = QLabel(parent=self.mini_widget)
self.price_label.setObjectName(f"{type(self).__name__}TooltipLabel") 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.price_label.setAutoFillBackground(False)
self.discount_label = QLabel(parent=self.mini_widget) self.discount_label = QLabel(parent=self.mini_widget)
self.discount_label.setObjectName(f"{type(self).__name__}TooltipLabel") 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) self.discount_label.setAutoFillBackground(False)
# Create layouts # Create layouts
@ -88,7 +118,8 @@ class IconWidget(object):
# Layout the widgets # Layout the widgets
# (from inner to outer) # (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) row_layout.addWidget(self.discount_label)
mini_layout.addWidget(self.title_label) mini_layout.addWidget(self.title_label)
mini_layout.addLayout(row_layout) mini_layout.addLayout(row_layout)
@ -100,45 +131,29 @@ class IconWidget(object):
class ShopImageWidget(ImageWidget): class ShopImageWidget(ImageWidget):
__image_cache: Dict[str, Dict[str, QPixmap]] = {} def __init__(self, manager: QtRequestManager, parent=None):
def __init__(self, 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 = WaitingSpinner(parent=self)
self.spinner.setVisible(False) self.spinner.setVisible(False)
self.manager = QtRequestManager("bytes") self.manager = manager
self.app_id = ""
self.orientation = ""
def fetchPixmap(self, url, app_id: str, title: str = ""): def fetchPixmap(self, url):
self.setPixmap(QPixmap()) 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.setFixedSize(self._image_size.size)
self.spinner.setVisible(True)
self.spinner.start() self.spinner.start()
self.manager.get( self.manager.get(url, self.__on_image_ready, params={
url, self.__on_image_ready, payload={ "resize": 1,
"resize": 1, "w": self._image_size.size.width(), "h": self._image_size.size.height() "w": self._image_size.base.size.width(),
} "h": self._image_size.base.size.height(),
) })
def __on_image_ready(self, data): def __on_image_ready(self, data):
cover = QImage() cover = QImage()
cover.loadFromData(data) 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 = cover.convertToFormat(QImage.Format_ARGB32_Premultiplied)
cover = QPixmap(cover) cover = QPixmap(cover)
ShopImageWidget.__image_cache.update({self.app_id: {self.orientation: cover}}) self.setPixmap(cover)
super(ShopImageWidget, self).setPixmap(cover)
self.spinner.stop() self.spinner.stop()
self.spinner.setVisible(False)

View file

@ -2,36 +2,36 @@ from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QMouseEvent from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QFrame,
QWidget, QWidget,
QVBoxLayout,
QSizePolicy, QSizePolicy,
QLabel, QLabel, QScrollArea,
) )
from rare.shared.image_manager import ImageSize from rare.shared.image_manager import ImageSize
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 .image_widget import ShopImageWidget from .image_widget import ShopImageWidget
class SearchResults(QWidget): class SearchResults(QScrollArea, SideTabContents):
show_info = pyqtSignal(dict) show_info = pyqtSignal(dict)
def __init__(self, api_core, parent=None): def __init__(self, api_core, parent=None):
super(SearchResults, self).__init__(parent=parent) super(SearchResults, self).__init__(parent=parent)
self.implements_scrollarea = True
self.api_core = api_core self.api_core = api_core
self.results_frame = QFrame(self) self.results_container = QWidget(self)
self.results_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.results_frame.setFrameStyle(QFrame.StyledPanel) self.results_layout = FlowLayout(self.results_container)
self.results_layout = FlowLayout(self.results_frame) self.setWidget(self.results_container)
self.results_frame.setLayout(self.results_layout) self.setWidgetResizable(True)
self.main_layout = QVBoxLayout() # self.main_layout = QVBoxLayout(self)
self.main_layout.setContentsMargins(0, 0, 0, 0) # self.main_layout.setContentsMargins(0, 0, 0, 0)
self.main_layout.addWidget(self.results_frame) # self.main_layout.addWidget(self.results_scrollarea)
self.setLayout(self.main_layout)
self.setEnabled(False) self.setEnabled(False)
def load_results(self, text: str): def load_results(self, text: str):
@ -40,10 +40,10 @@ class SearchResults(QWidget):
self.api_core.search_game(text, self.show_results) self.api_core.search_game(text, self.show_results)
def show_results(self, results: dict): 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) self.results_layout.removeWidget(w)
w.deleteLater() 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) self.results_layout.removeWidget(w)
w.deleteLater() w.deleteLater()
@ -51,22 +51,23 @@ class SearchResults(QWidget):
self.results_layout.addWidget(QLabel(self.tr("No results found"))) self.results_layout.addWidget(QLabel(self.tr("No results found")))
else: else:
for res in results: 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) w.show_info.connect(self.show_info.emit)
self.results_layout.addWidget(w) self.results_layout.addWidget(w)
self.results_layout.update()
self.setEnabled(True) self.setEnabled(True)
class SearchResultItem(ShopImageWidget): class SearchResultItem(ShopImageWidget):
show_info = pyqtSignal(dict) show_info = pyqtSignal(dict)
def __init__(self, result: dict, parent=None): def __init__(self, manager: QtRequestManager, result: dict, parent=None):
super(SearchResultItem, self).__init__(parent=parent) super(SearchResultItem, self).__init__(manager, parent=parent)
self.setFixedSize(ImageSize.Normal) self.setFixedSize(ImageSize.Normal)
self.ui.setupUi(self) self.ui.setupUi(self)
for img in result["keyImages"]: for img in result["keyImages"]:
if img["type"] in ["DieselStoreFrontTall", "OfferImageTall", "Thumbnail", "ProductLogo"]: if img["type"] in ["DieselStoreFrontTall", "OfferImageTall", "Thumbnail", "ProductLogo"]:
self.fetchPixmap(img["url"], result["id"], result["title"]) self.fetchPixmap(img["url"])
break break
else: else:
print("No image found") print("No image found")

View file

@ -1,4 +1,3 @@
import urllib.parse
from logging import getLogger from logging import getLogger
from PyQt5.QtCore import pyqtSignal, QObject from PyQt5.QtCore import pyqtSignal, QObject
@ -10,31 +9,37 @@ from rare.components.tabs.store.constants import (
remove_from_wishlist_query, remove_from_wishlist_query,
) )
from rare.components.tabs.store.shop_models import BrowseModel from rare.components.tabs.store.shop_models import BrowseModel
from rare.utils.paths import cache_dir
from rare.utils.qt_requests import QtRequests from rare.utils.qt_requests import QtRequests
logger = getLogger("ShopAPICore") logger = getLogger("ShopAPICore")
graphql_url = "https://www.epicgames.com/graphql" graphql_url = "https://graphql.epicgames.com/graphql"
class ShopApiCore(QObject): class ShopApiCore(QObject):
update_wishlist = pyqtSignal() update_wishlist = pyqtSignal()
def __init__(self, auth_token, lc: str, cc: str): def __init__(self, token, language: str, country: str):
super(ShopApiCore, self).__init__() super(ShopApiCore, self).__init__()
self.token = auth_token self.token = token
self.language_code: str = lc self.language_code: str = language
self.country_code: str = cc self.country_code: str = country
self.locale = f"{self.language_code}-{self.country_code}" self.locale = f"{self.language_code}-{self.country_code}"
self.manager = QtRequests(parent=self) 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.browse_active = False
self.next_browse_request = tuple(()) self.next_browse_request = tuple(())
def get_free_games(self, handle_func: callable): 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}" url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions"
params = {
self.manager.get(url, lambda data: self._handle_free_games(data, handle_func)) "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): def _handle_free_games(self, data, handle_func):
try: try:
@ -50,14 +55,14 @@ class ShopApiCore(QObject):
handle_func(results) handle_func(results)
def get_wishlist(self, handle_func): def get_wishlist(self, handle_func):
self.auth_manager.post( self.authed_manager.post(
graphql_url, graphql_url,
lambda data: self._handle_wishlist(data, handle_func), lambda data: self._handle_wishlist(data, handle_func),
{ {
"query": wishlist_query, "query": wishlist_query,
"variables": { "variables": {
"country": self.country_code, "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( self.manager.post(graphql_url, lambda data: self._handle_search(data, handle_func), payload)
graphql_url, lambda data: self._handle_search(data, handle_func), payload,
)
def _handle_search(self, data, handle_func): def _handle_search(self, data, handle_func):
try: try:
@ -114,37 +117,11 @@ class ShopApiCore(QObject):
self.next_browse_request = (browse_model, handle_func) self.next_browse_request = (browse_model, handle_func)
return return
self.browse_active = True self.browse_active = True
url = "https://www.epicgames.com/graphql?operationName=searchStoreQuery&variables={}&extensions={}" payload = {
variables = urllib.parse.quote_plus(str( "query": search_query,
dict(browse_model.__dict__)) "variables": browse_model.__dict__
) }
extensions = urllib.parse.quote_plus(str( self.manager.post(graphql_url, lambda data: self._handle_browse_games(data, handle_func), payload)
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)
)
def _handle_browse_games(self, data, handle_func): def _handle_browse_games(self, data, handle_func):
self.browse_active = False self.browse_active = False
@ -188,11 +165,7 @@ class ShopApiCore(QObject):
}, },
"query": add_to_wishlist_query, "query": add_to_wishlist_query,
} }
self.auth_manager.post( self.authed_manager.post(graphql_url, lambda data: self._handle_add_to_wishlist(data, handle_func), payload)
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):
try: try:
@ -215,11 +188,8 @@ class ShopApiCore(QObject):
}, },
"query": remove_from_wishlist_query, "query": remove_from_wishlist_query,
} }
self.auth_manager.post( self.authed_manager.post(graphql_url, lambda data: self._handle_remove_from_wishlist(data, handle_func),
graphql_url, payload)
lambda data: self._handle_remove_from_wishlist(data, handle_func),
payload,
)
def _handle_remove_from_wishlist(self, data, handle_func): def _handle_remove_from_wishlist(self, data, handle_func):
try: try:

View file

@ -1,6 +1,7 @@
import datetime import datetime
from dataclasses import dataclass from dataclasses import dataclass
from typing import List, Dict from typing import List, Dict
import epicstore_api.queries as egs_query
class ImageUrlModel: class ImageUrlModel:
@ -158,22 +159,26 @@ class BrowseModel:
price: str = "" price: str = ""
onSale: bool = False onSale: bool = False
def __post_init__(self):
self.locale = f"{self.language_code}-{self.country_code}"
@property @property
def __dict__(self): def __dict__(self):
payload = { payload = {
"allowCountries": self.country_code,
"category": self.category,
"count": self.count, "count": self.count,
"country": self.country_code, "category": self.category,
"keywords": self.keywords, "allowCountries": self.country_code,
"locale": self.language_code, "namespace": "",
"priceRange": self.price,
"releaseDate": self.date,
"sortBy": "releaseDate", "sortBy": "releaseDate",
"sortDir": self.sortDir, "sortDir": self.sortDir,
"start": self.start, "start": self.start,
"keywords": self.keywords,
"tag": self.tag, "tag": self.tag,
"priceRange": self.price,
"releaseDate": self.date,
"withPrice": self.withPrice, "withPrice": self.withPrice,
"locale": self.locale,
"country": self.country_code,
} }
if self.price == "free": if self.price == "free":
payload["freeGame"] = True payload["freeGame"] = True
@ -187,5 +192,4 @@ class BrowseModel:
payload["effectiveDate"] = self.date payload["effectiveDate"] = self.date
else: else:
payload.pop("priceRange") payload.pop("priceRange")
return payload return payload

View file

@ -9,15 +9,17 @@ from PyQt5.QtWidgets import (
QLabel, QLabel,
QPushButton, QPushButton,
QHBoxLayout, QHBoxLayout,
QWidget, QSizePolicy, QWidget, QSizePolicy, QStackedLayout,
) )
from legendary.core import LegendaryCore from legendary.core import LegendaryCore
from rare.ui.components.tabs.store.store import Ui_ShopWidget 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.flow_layout import FlowLayout
from rare.widgets.side_tab import SideTabContents
from .constants import Constants from .constants import Constants
from .game_widgets import GameWidget from .game_widgets import GameWidget
from .image_widget import WaitingSpinner
from .shop_api_core import ShopApiCore from .shop_api_core import ShopApiCore
from .shop_models import BrowseModel from .shop_models import BrowseModel
@ -25,14 +27,16 @@ logger = logging.getLogger("Shop")
# noinspection PyAttributeOutsideInit,PyBroadException # noinspection PyAttributeOutsideInit,PyBroadException
class ShopWidget(QWidget, Ui_ShopWidget): class ShopWidget(QWidget, SideTabContents):
show_info = pyqtSignal(str) show_info = pyqtSignal(str)
show_game = pyqtSignal(dict) 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) super(ShopWidget, self).__init__(parent=parent)
self.setupUi(self) self.implements_scrollarea = True
self.path = path self.ui = Ui_ShopWidget()
self.ui.setupUi(self)
self.cache_dir = cache_dir
self.core = core self.core = core
self.api_core = shop_api self.api_core = shop_api
self.price = "" self.price = ""
@ -40,25 +44,39 @@ class ShopWidget(QWidget, Ui_ShopWidget):
self.types = [] self.types = []
self.update_games_allowed = True self.update_games_allowed = True
self.free_scrollarea.setDisabled(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.discount_widget.setLayout(FlowLayout(self.discount_widget)) self.discounts_layout = QStackedLayout(self.ui.discounts_group)
self.discount_stack.addWidget(WaitingSpinner(self.discount_stack)) self.discounts_spinner = WaitingSpinner(self.ui.discounts_group)
self.discount_stack.setCurrentIndex(1) 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.discounts_spinner.start()
self.game_stack.addWidget(WaitingSpinner(self.game_stack)) self.discounts_layout.setCurrentWidget(self.discounts_spinner)
self.game_stack.setCurrentIndex(1)
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( self.search_bar = ButtonLineEdit(
"fa.search", placeholder_text=self.tr("Search Games") "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) # 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) self.api_core.get_wishlist(self.add_wishlist_items)
def add_wishlist_items(self, wishlist): def add_wishlist_items(self, wishlist):
for i in range(self.discount_widget.layout().count()): for w in self.discounts_flow.findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly):
item = self.discount_widget.layout().itemAt(i) self.discounts_flow.layout().removeWidget(w)
if item: w.deleteLater()
item.widget().deleteLater()
if wishlist and wishlist[0] == "error": # if wishlist and wishlist[0] == "error":
self.discount_widget.layout().addWidget( # self.discounts_group.layout().addWidget(
QLabel(self.tr("Failed to get wishlist: {}").format(wishlist[1])) # QLabel(self.tr("Failed to get wishlist: {}").format(wishlist[1]))
) # )
btn = QPushButton(self.tr("Reload")) # btn = QPushButton(self.tr("Reload"))
self.discount_widget.layout().addWidget(btn) # self.discount_widget.layout().addWidget(btn)
btn.clicked.connect( # btn.clicked.connect(
lambda: self.api_core.get_wishlist(self.add_wishlist_items) # lambda: self.api_core.get_wishlist(self.add_wishlist_items)
) # )
self.discount_stack.setCurrentIndex(0) # self.discount_stack.setCurrentIndex(0)
return # return
discounts = 0 discounts = 0
for game in wishlist: for game in wishlist:
@ -108,48 +125,48 @@ class ShopWidget(QWidget, Ui_ShopWidget):
continue continue
try: try:
if game["offer"]["price"]["totalPrice"]["discount"] > 0: 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) w.show_info.connect(self.show_game)
self.discount_widget.layout().addWidget(w) self.discounts_flow.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.discounts_group.setVisible(discounts > 0) self.ui.discounts_group.setVisible(discounts > 0)
self.discount_stack.setCurrentIndex(0) self.discounts_layout.setCurrentWidget(self.discounts_flow)
# fix widget overlay # FIXME: FlowLayout doesn't update on adding widget
self.discount_widget.layout().update() self.discounts_flow.layout().update()
def add_free_games(self, free_games: list): def add_free_games(self, free_games: list):
for w in self.free_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly): for w in self.ui.free_container.layout().findChildren(QGroupBox, options=Qt.FindDirectChildrenOnly):
self.free_container.layout().removeWidget(w) self.ui.free_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.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.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.free_container.setEnabled(True) self.ui.free_container.setEnabled(True)
return 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 = QHBoxLayout(self.free_games_now)
# free_games_now_layout.setContentsMargins(0, 0, 0, 0) # 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_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 = QHBoxLayout(self.free_games_next)
# free_games_next_layout.setContentsMargins(0, 0, 0, 0) # 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_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() date = datetime.datetime.now()
free_games_now = [] free_games_now = []
@ -200,7 +217,7 @@ class ShopWidget(QWidget, Ui_ShopWidget):
# free games now # free games now
now_free = 0 now_free = 0
for free_game in free_games_now: 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) w.show_info.connect(self.show_game)
self.free_games_now.layout().addWidget(w) self.free_games_now.layout().addWidget(w)
self.free_game_widgets.append(w) self.free_game_widgets.append(w)
@ -212,64 +229,64 @@ class ShopWidget(QWidget, Ui_ShopWidget):
# free games next week # free games next week
for free_game in coming_free_games: 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": 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) self.free_games_next.layout().addWidget(w)
# 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.free_scrollarea.setMinimumHeight( self.ui.free_scrollarea.setMinimumHeight(
self.free_games_now.sizeHint().height() self.free_games_now.sizeHint().height()
+ self.free_container.layout().contentsMargins().top() + self.ui.free_container.layout().contentsMargins().top()
+ self.free_container.layout().contentsMargins().bottom() + self.ui.free_container.layout().contentsMargins().bottom()
+ self.free_scrollarea.horizontalScrollBar().sizeHint().height() + self.ui.free_scrollarea.horizontalScrollBar().sizeHint().height()
) )
self.free_scrollarea.setEnabled(True) self.ui.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.show_info.emit(self.search_bar.text())
def init_filter(self): def init_filter(self):
self.none_price.toggled.connect( self.ui.none_price.toggled.connect(
lambda: self.prepare_request("") if self.none_price.isChecked() else None 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") lambda: self.prepare_request("free")
if self.free_button.isChecked() if self.ui.free_button.isChecked()
else None else None
) )
self.under10.toggled.connect( self.ui.under10.toggled.connect(
lambda: self.prepare_request("<price>[0, 1000)") lambda: self.prepare_request("<price>[0, 1000)")
if self.under10.isChecked() if self.ui.under10.isChecked()
else None else None
) )
self.under20.toggled.connect( self.ui.under20.toggled.connect(
lambda: self.prepare_request("<price>[0, 2000)") lambda: self.prepare_request("<price>[0, 2000)")
if self.under20.isChecked() if self.ui.under20.isChecked()
else None else None
) )
self.under30.toggled.connect( self.ui.under30.toggled.connect(
lambda: self.prepare_request("<price>[0, 3000)") lambda: self.prepare_request("<price>[0, 3000)")
if self.under30.isChecked() if self.ui.under30.isChecked()
else None else None
) )
self.above.toggled.connect( self.ui.above.toggled.connect(
lambda: self.prepare_request("<price>[1499,]") lambda: self.prepare_request("<price>[1499,]")
if self.above.isChecked() if self.ui.above.isChecked()
else None 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("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() constants = Constants()
self.checkboxes = [] self.checkboxes = []
for groupbox, variables in [ for groupbox, variables in [
(self.genre_group, constants.categories), (self.ui.genre_group, constants.categories),
(self.platform_group, constants.platforms), (self.ui.platform_group, constants.platforms),
(self.others_group, constants.others), (self.ui.others_group, constants.others),
(self.type_group, constants.types), (self.ui.type_group, constants.types),
]: ]:
for text, tag in variables: for text, tag in variables:
@ -280,26 +297,26 @@ class ShopWidget(QWidget, Ui_ShopWidget):
) )
groupbox.layout().addWidget(checkbox) groupbox.layout().addWidget(checkbox)
self.checkboxes.append(checkbox) self.checkboxes.append(checkbox)
self.reset_button.clicked.connect(self.reset_filters) self.ui.reset_button.clicked.connect(self.reset_filters)
self.filter_scrollarea.setMinimumWidth( self.ui.filter_scrollarea.setMinimumWidth(
self.filter_container.sizeHint().width() self.ui.filter_container.sizeHint().width()
+ self.filter_container.layout().contentsMargins().left() + self.ui.filter_container.layout().contentsMargins().left()
+ self.filter_container.layout().contentsMargins().right() + self.ui.filter_container.layout().contentsMargins().right()
+ self.filter_scrollarea.verticalScrollBar().sizeHint().width() + self.ui.filter_scrollarea.verticalScrollBar().sizeHint().width()
) )
def reset_filters(self): def reset_filters(self):
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)
self.none_price.setChecked(True) self.ui.none_price.setChecked(True)
self.tags = [] self.tags = []
self.types = [] self.types = []
self.update_games_allowed = True self.update_games_allowed = True
self.prepare_request("") self.prepare_request("")
self.on_discount.setChecked(False) self.ui.on_discount.setChecked(False)
def prepare_request( def prepare_request(
self, self,
@ -323,22 +340,22 @@ class ShopWidget(QWidget, Ui_ShopWidget):
self.types.append(added_type) self.types.append(added_type)
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.on_discount.isChecked(): if (self.types or self.price) or self.tags or self.ui.on_discount.isChecked():
self.free_scrollarea.setVisible(False) self.ui.free_scrollarea.setVisible(False)
self.discounts_group.setVisible(False) self.ui.discounts_group.setVisible(False)
else: else:
self.free_scrollarea.setVisible(True) self.ui.free_scrollarea.setVisible(True)
if len(self.discounts_group.layout().children()) > 0: if len(self.ui.discounts_group.layout().children()) > 0:
self.discounts_group.setVisible(True) self.ui.discounts_group.setVisible(True)
self.game_stack.setCurrentIndex(1) self.games_layout.setCurrentWidget(self.games_spinner)
browse_model = BrowseModel( browse_model = BrowseModel(
language_code=self.core.language_code, language_code=self.core.language_code,
country_code=self.core.country_code, country_code=self.core.country_code,
count=20, count=20,
price=self.price, price=self.price,
onSale=self.on_discount.isChecked(), onSale=self.ui.on_discount.isChecked(),
) )
browse_model.tag = "|".join(self.tags) 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) self.api_core.browse_games(browse_model, self.show_games)
def show_games(self, data): def show_games(self, data):
for item in ( for w in self.games_flow.layout().findChildren(GameWidget, options=Qt.FindDirectChildrenOnly):
self.game_widget.layout().itemAt(i) self.games_flow.layout().removeWidget(w)
for i in range(self.game_widget.layout().count()) w.deleteLater()
):
item.widget().deleteLater()
if data: if data:
for game in data: for game in data:
w = GameWidget(self.path, game) w = GameWidget(self.api_core.cached_manager, game)
self.game_widget.layout().addWidget(w)
w.show_info.connect(self.show_game.emit) w.show_info.connect(self.show_game.emit)
self.games_flow.layout().addWidget(w)
else: else:
self.game_widget.layout().addWidget( self.games_flow.layout().addWidget(
QLabel(self.tr("Could not get games matching the filter")) QLabel(self.tr("Could not get games matching the filter"))
) )
self.game_stack.setCurrentIndex(0) self.games_layout.setCurrentWidget(self.games_flow)
# FIXME: FlowLayout doesn't update on adding widget
self.game_widget.layout().update() self.games_flow.layout().update()
class CheckBox(QCheckBox): class CheckBox(QCheckBox):

View file

@ -1,9 +1,10 @@
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import QMessageBox, QWidget 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.side_tab import SideTabContents
from rare.widgets.flow_layout import FlowLayout
from .shop_api_core import ShopApiCore from .shop_api_core import ShopApiCore
from .game_widgets import WishlistWidget from .game_widgets import WishlistWidget
@ -14,6 +15,7 @@ class Wishlist(QWidget, SideTabContents):
def __init__(self, api_core: ShopApiCore, parent=None): def __init__(self, api_core: ShopApiCore, parent=None):
super(Wishlist, self).__init__(parent=parent) super(Wishlist, self).__init__(parent=parent)
self.implements_scrollarea = True
self.api_core = api_core self.api_core = api_core
self.ui = Ui_Wishlist() self.ui = Ui_Wishlist()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -21,20 +23,19 @@ class Wishlist(QWidget, SideTabContents):
self.wishlist = [] self.wishlist = []
self.widgets = [] self.widgets = []
self.ui.sort_cb.currentIndexChanged.connect( self.list_layout = FlowLayout(self.ui.list_container)
lambda i: self.set_wishlist(self.wishlist, i)
) self.ui.sort_cb.currentIndexChanged.connect(self.sort_wishlist)
self.ui.filter_cb.currentIndexChanged.connect(self.set_filter) self.ui.filter_cb.currentIndexChanged.connect(self.set_filter)
self.ui.reload_button.clicked.connect(self.update_wishlist) self.ui.reload_button.clicked.connect(self.update_wishlist)
self.ui.reload_button.setIcon(icon("fa.refresh", color="white")) self.ui.reload_button.setIcon(icon("fa.refresh", color="white"))
self.ui.reverse.stateChanged.connect( 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): def update_wishlist(self):
self.setEnabled(False) self.setEnabled(False)
self.set_title.emit("Wishlist")
self.api_core.get_wishlist(self.set_wishlist) self.api_core.get_wishlist(self.set_wishlist)
def delete_from_wishlist(self, game): def delete_from_wishlist(self, game):
@ -66,6 +67,32 @@ class Wishlist(QWidget, SideTabContents):
else: else:
self.ui.no_games_label.setVisible(False) 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): def set_wishlist(self, wishlist=None, sort=0):
if wishlist and wishlist[0] == "error": if wishlist and wishlist[0] == "error":
return return
@ -76,45 +103,18 @@ class Wishlist(QWidget, SideTabContents):
for i in self.widgets: for i in self.widgets:
i.deleteLater() 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() self.widgets.clear()
if len(sorted_list) == 0: if len(wishlist) == 0:
self.ui.no_games_label.setVisible(True) self.ui.no_games_label.setVisible(True)
else: else:
self.ui.no_games_label.setVisible(False) self.ui.no_games_label.setVisible(False)
if self.ui.reverse.isChecked(): for game in wishlist:
sorted_list.reverse() w = WishlistWidget(self.api_core.cached_manager, game["offer"], self.ui.list_container)
for game in sorted_list:
w = WishlistWidget(game["offer"])
self.widgets.append(w)
self.ui.list_layout.addWidget(w)
w.open_game.connect(self.show_game_info.emit) w.open_game.connect(self.show_game_info.emit)
w.delete_from_wishlist.connect(self.delete_from_wishlist) 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) self.setEnabled(True)

View file

@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ShopInfo(object): class Ui_ShopInfo(object):
def setupUi(self, ShopInfo): def setupUi(self, ShopInfo):
ShopInfo.setObjectName("ShopInfo") ShopInfo.setObjectName("ShopInfo")
ShopInfo.resize(434, 250) ShopInfo.resize(747, 442)
ShopInfo.setWindowTitle("ShopGameInfo") ShopInfo.setWindowTitle("ShopGameInfo")
self.main_layout = QtWidgets.QHBoxLayout(ShopInfo) self.main_layout = QtWidgets.QHBoxLayout(ShopInfo)
self.main_layout.setObjectName("main_layout") self.main_layout.setObjectName("main_layout")

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>747</width>
<height>250</height> <height>442</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">

View file

@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ShopWidget(object): class Ui_ShopWidget(object):
def setupUi(self, ShopWidget): def setupUi(self, ShopWidget):
ShopWidget.setObjectName("ShopWidget") ShopWidget.setObjectName("ShopWidget")
ShopWidget.resize(750, 588) ShopWidget.resize(350, 382)
ShopWidget.setWindowTitle("Store") ShopWidget.setWindowTitle("Store")
self.shop_layout = QtWidgets.QHBoxLayout(ShopWidget) self.shop_layout = QtWidgets.QHBoxLayout(ShopWidget)
self.shop_layout.setObjectName("shop_layout") self.shop_layout.setObjectName("shop_layout")
@ -27,7 +27,7 @@ class Ui_ShopWidget(object):
self.games_scrollarea.setWidgetResizable(True) self.games_scrollarea.setWidgetResizable(True)
self.games_scrollarea.setObjectName("games_scrollarea") self.games_scrollarea.setObjectName("games_scrollarea")
self.games_container = QtWidgets.QWidget() 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.setObjectName("games_container")
self.games_container_layout = QtWidgets.QVBoxLayout(self.games_container) self.games_container_layout = QtWidgets.QVBoxLayout(self.games_container)
self.games_container_layout.setContentsMargins(0, 0, 3, 0) 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.setWidgetResizable(True)
self.free_scrollarea.setObjectName("free_scrollarea") self.free_scrollarea.setObjectName("free_scrollarea")
self.free_container = QtWidgets.QWidget() 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.setObjectName("free_container")
self.free_container_layout = QtWidgets.QHBoxLayout(self.free_container) self.free_container_layout = QtWidgets.QHBoxLayout(self.free_container)
self.free_container_layout.setContentsMargins(0, 0, 0, 3) 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.games_container_layout.addWidget(self.free_scrollarea)
self.discounts_group = QtWidgets.QGroupBox(self.games_container) self.discounts_group = QtWidgets.QGroupBox(self.games_container)
self.discounts_group.setObjectName("discounts_group") 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_container_layout.addWidget(self.discounts_group)
self.games_group = QtWidgets.QGroupBox(self.games_container) self.games_group = QtWidgets.QGroupBox(self.games_container)
self.games_group.setObjectName("games_group") 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_container_layout.addWidget(self.games_group)
self.games_scrollarea.setWidget(self.games_container) self.games_scrollarea.setWidget(self.games_container)
self.left_layout.addWidget(self.games_scrollarea) self.left_layout.addWidget(self.games_scrollarea)
@ -94,7 +83,12 @@ class Ui_ShopWidget(object):
self.filter_scrollarea.setWidgetResizable(True) self.filter_scrollarea.setWidgetResizable(True)
self.filter_scrollarea.setObjectName("filter_scrollarea") self.filter_scrollarea.setObjectName("filter_scrollarea")
self.filter_container = QtWidgets.QWidget() 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.setObjectName("filter_container")
self.filter_container_layout = QtWidgets.QVBoxLayout(self.filter_container) self.filter_container_layout = QtWidgets.QVBoxLayout(self.filter_container)
self.filter_container_layout.setContentsMargins(0, 0, 3, 0) self.filter_container_layout.setContentsMargins(0, 0, 3, 0)

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>750</width> <width>679</width>
<height>588</height> <height>329</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -35,8 +35,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>583</width> <width>515</width>
<height>574</height> <height>315</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="games_container_layout"> <layout class="QVBoxLayout" name="games_container_layout">
@ -77,10 +77,16 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>580</width> <width>16</width>
<height>83</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="free_container_layout"> <layout class="QHBoxLayout" name="free_container_layout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
@ -103,13 +109,6 @@
<property name="title"> <property name="title">
<string>Discounts from your wishlist</string> <string>Discounts from your wishlist</string>
</property> </property>
<layout class="QVBoxLayout" name="discounts_layout">
<item>
<widget class="QStackedWidget" name="discount_stack">
<widget class="QWidget" name="discount_widget"/>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@ -117,13 +116,6 @@
<property name="title"> <property name="title">
<string>Games</string> <string>Games</string>
</property> </property>
<layout class="QVBoxLayout" name="games_layout">
<item>
<widget class="QStackedWidget" name="game_stack">
<widget class="QWidget" name="game_widget"/>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -169,10 +161,16 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>145</width> <width>142</width>
<height>542</height> <height>390</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="filter_container_layout"> <layout class="QVBoxLayout" name="filter_container_layout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>

View file

@ -14,12 +14,12 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Wishlist(object): class Ui_Wishlist(object):
def setupUi(self, Wishlist): def setupUi(self, Wishlist):
Wishlist.setObjectName("Wishlist") Wishlist.setObjectName("Wishlist")
Wishlist.resize(527, 328) Wishlist.resize(423, 153)
Wishlist.setWindowTitle("Wishlist") Wishlist.setWindowTitle("Wishlist")
self.verticalLayout = QtWidgets.QVBoxLayout(Wishlist) self.verticalLayout = QtWidgets.QVBoxLayout(Wishlist)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout() self.tool_layout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.tool_layout.setObjectName("tool_layout")
self.sort_label = QtWidgets.QLabel(Wishlist) self.sort_label = QtWidgets.QLabel(Wishlist)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -27,29 +27,29 @@ class Ui_Wishlist(object):
sizePolicy.setHeightForWidth(self.sort_label.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.sort_label.sizePolicy().hasHeightForWidth())
self.sort_label.setSizePolicy(sizePolicy) self.sort_label.setSizePolicy(sizePolicy)
self.sort_label.setObjectName("sort_label") 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 = QtWidgets.QComboBox(Wishlist)
self.sort_cb.setObjectName("sort_cb") self.sort_cb.setObjectName("sort_cb")
self.sort_cb.addItem("") self.sort_cb.addItem("")
self.sort_cb.addItem("") self.sort_cb.addItem("")
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 = QtWidgets.QCheckBox(Wishlist)
self.reverse.setObjectName("reverse") self.reverse.setObjectName("reverse")
self.horizontalLayout.addWidget(self.reverse) self.tool_layout.addWidget(self.reverse)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) spacerItem = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem) self.tool_layout.addItem(spacerItem)
self.filter_label = QtWidgets.QLabel(Wishlist) self.filter_label = QtWidgets.QLabel(Wishlist)
self.filter_label.setObjectName("filter_label") 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 = QtWidgets.QComboBox(Wishlist)
self.filter_cb.setObjectName("filter_cb") self.filter_cb.setObjectName("filter_cb")
self.filter_cb.addItem("") self.filter_cb.addItem("")
self.filter_cb.addItem("") self.filter_cb.addItem("")
self.horizontalLayout.addWidget(self.filter_cb) self.tool_layout.addWidget(self.filter_cb)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) spacerItem1 = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1) self.tool_layout.addItem(spacerItem1)
self.reload_button = QtWidgets.QPushButton(Wishlist) self.reload_button = QtWidgets.QPushButton(Wishlist)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -58,16 +58,19 @@ class Ui_Wishlist(object):
self.reload_button.setSizePolicy(sizePolicy) self.reload_button.setSizePolicy(sizePolicy)
self.reload_button.setText("") self.reload_button.setText("")
self.reload_button.setObjectName("reload_button") self.reload_button.setObjectName("reload_button")
self.horizontalLayout.addWidget(self.reload_button) self.tool_layout.addWidget(self.reload_button)
self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout.addLayout(self.tool_layout)
self.list_layout = QtWidgets.QVBoxLayout()
self.list_layout.setObjectName("list_layout")
self.verticalLayout.addLayout(self.list_layout)
self.no_games_label = QtWidgets.QLabel(Wishlist) self.no_games_label = QtWidgets.QLabel(Wishlist)
self.no_games_label.setObjectName("no_games_label") self.no_games_label.setObjectName("no_games_label")
self.verticalLayout.addWidget(self.no_games_label) self.verticalLayout.addWidget(self.no_games_label)
spacerItem2 = QtWidgets.QSpacerItem(379, 218, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.list_scrollarea = QtWidgets.QScrollArea(Wishlist)
self.verticalLayout.addItem(spacerItem2) 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) self.retranslateUi(Wishlist)

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>527</width> <width>423</width>
<height>328</height> <height>153</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,7 +15,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="tool_layout">
<item> <item>
<widget class="QLabel" name="sort_label"> <widget class="QLabel" name="sort_label">
<property name="sizePolicy"> <property name="sizePolicy">
@ -61,14 +61,14 @@
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="tool_hspacer_1">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>0</width>
<height>20</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -95,14 +95,14 @@
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="tool_hspacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>0</width>
<height>20</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -122,9 +122,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QVBoxLayout" name="list_layout"/>
</item>
<item> <item>
<widget class="QLabel" name="no_games_label"> <widget class="QLabel" name="no_games_label">
<property name="text"> <property name="text">
@ -133,17 +130,21 @@
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="verticalSpacer"> <widget class="QScrollArea" name="list_scrollarea">
<property name="orientation"> <property name="widgetResizable">
<enum>Qt::Vertical</enum> <bool>true</bool>
</property> </property>
<property name="sizeHint" stdset="0"> <widget class="QWidget" name="list_container">
<size> <property name="geometry">
<width>379</width> <rect>
<height>218</height> <x>0</x>
</size> <y>0</y>
</property> <width>407</width>
</spacer> <height>83</height>
</rect>
</property>
</widget>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/wishlist_widget.ui' # 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 # 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. # 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): class Ui_WishlistWidget(object):
def setupUi(self, WishlistWidget): def setupUi(self, WishlistWidget):
WishlistWidget.setObjectName("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") WishlistWidget.setWindowTitle("WishlistWIdget")
self.horizontalLayout = QtWidgets.QHBoxLayout(WishlistWidget) self.main_layout = QtWidgets.QHBoxLayout(WishlistWidget)
self.horizontalLayout.setObjectName("horizontalLayout") self.main_layout.setContentsMargins(0, 0, 0, 0)
self.widget = QtWidgets.QWidget(WishlistWidget) self.main_layout.setObjectName("main_layout")
self.info_widget = QtWidgets.QWidget(WishlistWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.info_widget.sizePolicy().hasHeightForWidth())
self.widget.setSizePolicy(sizePolicy) self.info_widget.setSizePolicy(sizePolicy)
self.widget.setObjectName("widget") self.info_widget.setObjectName("info_widget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget) self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.info_widget)
self.verticalLayout_2.setObjectName("verticalLayout_2") 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 = QtGui.QFont()
font.setPointSize(16) font.setPointSize(16)
self.title_label.setFont(font) self.title_label.setFont(font)
@ -35,16 +41,16 @@ class Ui_WishlistWidget(object):
self.title_label.setWordWrap(True) self.title_label.setWordWrap(True)
self.title_label.setObjectName("title_label") self.title_label.setObjectName("title_label")
self.verticalLayout_2.addWidget(self.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 = QtGui.QFont()
font.setPointSize(12) font.setPointSize(12)
self.developer.setFont(font) self.developer.setFont(font)
self.developer.setText("TextLabel") self.developer.setText("TextLabel")
self.developer.setObjectName("developer") self.developer.setObjectName("developer")
self.verticalLayout_2.addWidget(self.developer) self.verticalLayout_2.addWidget(self.developer)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.price_layout = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.price_layout.setObjectName("price_layout")
self.discount_price = QtWidgets.QLabel(self.widget) self.discount_price = QtWidgets.QLabel(self.info_widget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -52,15 +58,13 @@ class Ui_WishlistWidget(object):
self.discount_price.setSizePolicy(sizePolicy) self.discount_price.setSizePolicy(sizePolicy)
self.discount_price.setText("TextLabel") self.discount_price.setText("TextLabel")
self.discount_price.setObjectName("discount_price") self.discount_price.setObjectName("discount_price")
self.horizontalLayout_2.addWidget(self.discount_price) self.price_layout.addWidget(self.discount_price)
self.price = QtWidgets.QLabel(self.widget) self.price = QtWidgets.QLabel(self.info_widget)
self.price.setText("TextLabel") self.price.setText("TextLabel")
self.price.setObjectName("price") self.price.setObjectName("price")
self.horizontalLayout_2.addWidget(self.price) self.price_layout.addWidget(self.price)
self.verticalLayout_2.addLayout(self.horizontalLayout_2) self.verticalLayout_2.addLayout(self.price_layout)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.main_layout.addWidget(self.info_widget, 0, QtCore.Qt.AlignTop)
self.verticalLayout_2.addItem(spacerItem)
self.horizontalLayout.addWidget(self.widget)
self.delete_button = QtWidgets.QPushButton(WishlistWidget) self.delete_button = QtWidgets.QPushButton(WishlistWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -69,7 +73,7 @@ class Ui_WishlistWidget(object):
self.delete_button.setSizePolicy(sizePolicy) self.delete_button.setSizePolicy(sizePolicy)
self.delete_button.setText("") self.delete_button.setText("")
self.delete_button.setObjectName("delete_button") self.delete_button.setObjectName("delete_button")
self.horizontalLayout.addWidget(self.delete_button) self.main_layout.addWidget(self.delete_button)
self.retranslateUi(WishlistWidget) self.retranslateUi(WishlistWidget)

View file

@ -6,16 +6,34 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>523</width> <width>202</width>
<height>172</height> <height>94</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string notr="true">WishlistWIdget</string> <string notr="true">WishlistWIdget</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="main_layout">
<item> <property name="leftMargin">
<widget class="QWidget" name="widget" native="true"> <number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignTop">
<widget class="QWidget" name="info_widget" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -51,7 +69,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="price_layout">
<item> <item>
<widget class="QLabel" name="discount_price"> <widget class="QLabel" name="discount_price">
<property name="sizePolicy"> <property name="sizePolicy">
@ -74,19 +92,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>