1
0
Fork 0
mirror of synced 2024-05-04 20:52:58 +12:00

Store: Finalize store design

This commit is contained in:
loathingKernel 2023-09-23 20:24:28 +03:00
parent fda82b17cf
commit b4a26b5932
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
30 changed files with 1360 additions and 1327 deletions

View file

@ -1,14 +1,13 @@
from PyQt5.QtGui import QShowEvent, QHideEvent
from legendary.core import LegendaryCore
from rare.shared import RareCore
from rare.utils.paths import cache_dir
from rare.widgets.side_tab import SideTabWidget
from .game_info import ShopGameInfo
from .search_results import SearchResults
from .shop_api_core import ShopApiCore
from .api.models.response import CatalogOfferModel
from .shop_widget import ShopWidget
from .wishlist import WishlistWidget, Wishlist
from .landing import LandingWidget, LandingPage
from .search import SearchPage
from .store_api import StoreAPI
from .widgets.details import DetailsWidget
from .wishlist import WishlistPage
class StoreTab(SideTabWidget):
@ -19,45 +18,31 @@ class StoreTab(SideTabWidget):
self.core = core
# self.rcore = RareCore.instance()
self.api_core = ShopApiCore(
self.api = StoreAPI(
self.core.egs.session.headers["Authorization"],
self.core.language_code,
self.core.country_code,
[] # [i.asset_infos["Windows"].namespace for i in self.rcore.game_list if bool(i.asset_infos)]
)
self.shop = ShopWidget(cache_dir(), self.core, self.api_core, parent=self)
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.landing = LandingPage(self.api, parent=self)
self.landing_index = self.addTab(self.landing, self.tr("Store"))
self.search = SearchResults(self.api_core, parent=self)
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))
self.search = SearchPage(self.core, self.api, parent=self)
self.search_index = self.addTab(self.search, self.tr("Search"))
self.info = ShopGameInfo(
# [i.asset_infos["Windows"].namespace for i in self.rcore.game_list if bool(i.asset_infos)],
[],
self.api_core,
parent=self
)
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 = WishlistPage(self.api, parent=self)
self.wishlist_index = self.addTab(self.wishlist, self.tr("Wishlist"))
self.wishlist = Wishlist(self.api_core, parent=self)
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)
self.api.update_wishlist.connect(self.update_wishlist)
self.api_core.update_wishlist.connect(self.update_wishlist)
self.previous_index = self.shop_index
self.previous_index = self.landing_index
def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous() or self.init:
return super().showEvent(a0)
self.shop.load()
self.wishlist_widget.update_wishlist()
# self.landing.load()
# self.wishlist.update_wishlist()
self.init = True
return super().showEvent(a0)
@ -68,13 +53,4 @@ class StoreTab(SideTabWidget):
return super().hideEvent(a0)
def update_wishlist(self):
self.shop.update_wishlist()
def show_game(self, data: CatalogOfferModel):
self.previous_index = self.currentIndex()
self.info.update_game(data)
self.setCurrentIndex(self.info_index)
def show_search(self, text: str):
self.search.load_results(text)
self.setCurrentIndex(self.search_index)
self.landing.update_wishlist()

View file

@ -18,13 +18,13 @@ class StoreWindow(QDialog):
layout = QVBoxLayout(self)
layout.addWidget(self.store_tab)
self.store_tab.load()
self.store_tab.show()
if __name__ == "__main__":
from rare.utils.misc import set_style_sheet
import rare.resources.static_css
import rare.resources.stylesheets.RareStyle
from rare.utils.misc import set_style_sheet
app = QApplication(sys.argv)
app.setApplicationName("Rare")

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,212 @@
import datetime
import logging
from typing import List
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal
from PyQt5.QtGui import QShowEvent, QHideEvent
from PyQt5.QtWidgets import (
QHBoxLayout,
QWidget,
QSizePolicy,
QVBoxLayout,
QSpacerItem,
QScrollArea,
QFrame,
)
from rare.widgets.flow_layout import FlowLayout
from rare.widgets.side_tab import SideTabContents
from rare.widgets.sliding_stack import SlidingStackedWidget
from rare.components.tabs.store.api.models.response import CatalogOfferModel, WishlistItemModel
from .api.models.utils import parse_date
from .store_api import StoreAPI
from .widgets.details import DetailsWidget
from .widgets.items import StoreItemWidget
from .widgets.groups import StoreGroup
logger = logging.getLogger("StoreLanding")
class LandingPage(SlidingStackedWidget, SideTabContents):
def __init__(self, api: StoreAPI, parent=None):
super(LandingPage, self).__init__(parent=parent)
self.implements_scrollarea = True
self.landing_widget = LandingWidget(api, parent=self)
self.landing_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.landing_widget.set_title.connect(self.set_title)
self.landing_widget.show_details.connect(self.show_details)
self.landing_scroll = QScrollArea(self)
self.landing_scroll.setWidgetResizable(True)
self.landing_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.landing_scroll.setWidget(self.landing_widget)
self.details_widget = DetailsWidget([], api, parent=self)
self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
self.details_scroll = QScrollArea(self)
self.details_scroll.setWidgetResizable(True)
self.details_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.details_scroll.setWidget(self.details_widget)
self.setDirection(Qt.Horizontal)
self.addWidget(self.landing_scroll)
self.addWidget(self.details_scroll)
@pyqtSlot()
def show_main(self):
self.slideInWidget(self.landing_scroll)
@pyqtSlot(object)
def show_details(self, game: CatalogOfferModel):
self.details_widget.update_game(game)
self.slideInWidget(self.details_scroll)
class LandingWidget(QWidget, SideTabContents):
show_details = pyqtSignal(CatalogOfferModel)
def __init__(self, api: StoreAPI, parent=None):
super(LandingWidget, self).__init__(parent=parent)
self.api = api
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 3, 0)
self.setLayout(layout)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.free_games_now = StoreGroup(self.tr("Free now"), layout=QHBoxLayout, parent=self)
self.free_games_now.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.free_games_next = StoreGroup(self.tr("Free next week"), layout=QHBoxLayout, parent=self)
self.free_games_next.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.discounts_group = StoreGroup(self.tr("Wishlist discounts"), layout=FlowLayout, parent=self)
self.discounts_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.games_group = StoreGroup(self.tr("Games"), FlowLayout, self)
self.games_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.games_group.loading(False)
self.games_group.setVisible(True)
layout.addWidget(self.free_games_now, alignment=Qt.AlignTop)
layout.addWidget(self.free_games_next, alignment=Qt.AlignTop)
layout.addWidget(self.discounts_group, alignment=Qt.AlignTop)
layout.addWidget(self.games_group, alignment=Qt.AlignTop)
layout.addItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding))
def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous():
return super().showEvent(a0)
self.api.get_free_games(self.__add_free)
self.api.get_wishlist(self.__add_discounts)
return super().showEvent(a0)
def hideEvent(self, a0: QHideEvent) -> None:
if a0.spontaneous():
return super().hideEvent(a0)
# TODO: Implement tab unloading
return super().hideEvent(a0)
def __add_discounts(self, wishlist: List[WishlistItemModel]):
for w in self.discounts_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.discounts_group.layout().removeWidget(w)
w.deleteLater()
discounts = 0
for game in wishlist:
if not game:
continue
try:
if game.offer.price.total_price["discount"] > 0:
w = StoreItemWidget(self.api.cached_manager, game.offer)
w.show_details.connect(self.show_details)
self.discounts_group.layout().addWidget(w)
discounts += 1
except Exception as e:
logger.warning(f"{game} {e}")
continue
# self.discounts_group.setVisible(discounts > 0)
self.discounts_group.loading(False)
def __add_free(self, free_games: List[CatalogOfferModel]):
for w in self.free_games_now.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.free_games_now.layout().removeWidget(w)
w.deleteLater()
for w in self.free_games_next.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.free_games_next.layout().removeWidget(w)
w.deleteLater()
date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
free_now = []
free_next = []
for game in free_games:
try:
if (
game.price.total_price["fmtPrice"]["discountPrice"] == "0"
and game.price.total_price["fmtPrice"]["originalPrice"]
!= game.price.total_price["fmtPrice"]["discountPrice"]
):
free_now.append(game)
continue
if game.title == "Mystery Game":
free_next.append(game)
continue
except KeyError as e:
logger.warning(str(e))
try:
# parse datetime to check if game is next week or now
try:
start_date = parse_date(
game.promotions["upcomingPromotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception:
try:
start_date = parse_date(
game.promotions["promotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception as e:
continue
except TypeError:
print("type error")
continue
if start_date > date:
free_next.append(game)
# free games now
self.free_games_now.setVisible(bool(len(free_now)))
for game in free_now:
w = StoreItemWidget(self.api.cached_manager, game)
w.show_details.connect(self.show_details)
self.free_games_now.layout().addWidget(w)
self.free_games_now.loading(False)
# free games next week
self.free_games_next.setVisible(bool(len(free_next)))
for game in free_next:
w = StoreItemWidget(self.api.cached_manager, game)
if game.title != "Mystery Game":
w.show_details.connect(self.show_details)
self.free_games_next.layout().addWidget(w)
self.free_games_next.loading(False)
def show_games(self, data):
for w in self.games_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
self.games_group.layout().removeWidget(w)
w.deleteLater()
if data:
for game in data:
w = StoreItemWidget(self.api.cached_manager, game)
w.show_details.connect(self.show_details)
self.games_group.layout().addWidget(w)
self.games_group.loading(False)

View file

@ -0,0 +1,57 @@
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import (
QWidget,
QSizePolicy,
QLabel,
QScrollArea,
)
from rare.widgets.flow_layout import FlowLayout
from .api.models.response import CatalogOfferModel
from .widgets.items import ResultsItemWidget
class ResultsWidget(QScrollArea):
show_details = pyqtSignal(CatalogOfferModel)
def __init__(self, store_api, parent=None):
super(ResultsWidget, self).__init__(parent=parent)
self.implements_scrollarea = True
self.store_api = store_api
self.results_container = QWidget(self)
self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.results_layout = FlowLayout(self.results_container)
self.setWidget(self.results_container)
self.setWidgetResizable(True)
# self.main_layout = QVBoxLayout(self)
# self.main_layout.setContentsMargins(0, 0, 0, 0)
# self.main_layout.addWidget(self.results_scrollarea)
self.setEnabled(False)
def load_results(self, text: str):
self.setEnabled(False)
if text != "":
self.store_api.search_game(text, self.show_results)
def show_results(self, results: dict):
for w in self.results_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
for w in self.results_container.findChildren(ResultsItemWidget, options=Qt.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
if not results:
self.results_layout.addWidget(QLabel(self.tr("No results found")))
else:
for res in results:
w = ResultsItemWidget(self.store_api.cached_manager, res, parent=self.results_container)
w.show_details.connect(self.show_details.emit)
self.results_layout.addWidget(w)
self.results_layout.update()
self.setEnabled(True)

View file

@ -0,0 +1,223 @@
import logging
from typing import List
from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot
from PyQt5.QtWidgets import (
QCheckBox,
QWidget,
QSizePolicy,
QScrollArea,
QFrame,
)
from legendary.core import LegendaryCore
from rare.ui.components.tabs.store.search import Ui_SearchWidget
from rare.utils.extra_widgets import ButtonLineEdit
from rare.widgets.side_tab import SideTabContents
from rare.widgets.sliding_stack import SlidingStackedWidget
from .api.models.query import SearchStoreQuery
from .api.models.response import CatalogOfferModel
from .constants import Constants
from .results import ResultsWidget
from .store_api import StoreAPI
from .widgets.details import DetailsWidget
logger = logging.getLogger("Shop")
class SearchPage(SlidingStackedWidget, SideTabContents):
def __init__(self, core, api: StoreAPI, parent=None):
super(SearchPage, self).__init__(parent=parent)
self.implements_scrollarea = True
self.search_widget = SearchWidget(core, api, parent=self)
self.search_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.search_widget.set_title.connect(self.set_title)
self.search_widget.show_details.connect(self.show_details)
self.details_widget = DetailsWidget([], api, parent=self)
self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
self.details_scroll = QScrollArea(self)
self.details_scroll.setWidgetResizable(True)
self.details_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.details_scroll.setWidget(self.details_widget)
self.setDirection(Qt.Horizontal)
self.addWidget(self.search_widget)
self.addWidget(self.details_scroll)
@pyqtSlot()
def show_main(self):
self.slideInWidget(self.search_widget)
@pyqtSlot(object)
def show_details(self, game: CatalogOfferModel):
self.details_widget.update_game(game)
self.slideInWidget(self.details_scroll)
# noinspection PyAttributeOutsideInit,PyBroadException
class SearchWidget(QWidget, SideTabContents):
show_details = pyqtSignal(CatalogOfferModel)
def __init__(self, core: LegendaryCore, api: StoreAPI, parent=None):
super(SearchWidget, self).__init__(parent=parent)
self.implements_scrollarea = True
self.ui = Ui_SearchWidget()
self.ui.setupUi(self)
self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
self.core = core
self.api_core = api
self.price = ""
self.tags = []
self.types = []
self.update_games_allowed = True
self.free_game_widgets = []
self.active_search_request = False
self.next_search = ""
self.wishlist: List = []
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Games"))
self.results_scrollarea = ResultsWidget(self.api_core, self)
self.results_scrollarea.show_details.connect(self.show_details)
self.ui.left_layout.addWidget(self.search_bar)
self.ui.left_layout.addWidget(self.results_scrollarea)
self.search_bar.returnPressed.connect(self.show_search_results)
self.search_bar.buttonClicked.connect(self.show_search_results)
# self.init_filter()
def load(self):
# load browse games
self.prepare_request()
def show_search_results(self):
if text := self.search_bar.text():
self.results_scrollarea.load_results(text)
# self.show_info.emit(self.search_bar.text())
def init_filter(self):
self.ui.none_price.toggled.connect(
lambda: self.prepare_request("") if self.ui.none_price.isChecked() else None
)
self.ui.free_button.toggled.connect(
lambda: self.prepare_request("free") if self.ui.free_button.isChecked() else None
)
self.ui.under10.toggled.connect(
lambda: self.prepare_request("<price>[0, 1000)") if self.ui.under10.isChecked() else None
)
self.ui.under20.toggled.connect(
lambda: self.prepare_request("<price>[0, 2000)") if self.ui.under20.isChecked() else None
)
self.ui.under30.toggled.connect(
lambda: self.prepare_request("<price>[0, 3000)") if self.ui.under30.isChecked() else None
)
self.ui.above.toggled.connect(
lambda: self.prepare_request("<price>[1499,]") 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.ui.on_discount.toggled.connect(lambda: self.prepare_request())
constants = Constants()
self.checkboxes = []
for groupbox, variables in [
(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:
checkbox = CheckBox(text, tag)
checkbox.activated.connect(lambda x: self.prepare_request(added_tag=x))
checkbox.deactivated.connect(lambda x: self.prepare_request(removed_tag=x))
groupbox.layout().addWidget(checkbox)
self.checkboxes.append(checkbox)
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.ui.none_price.setChecked(True)
self.tags = []
self.types = []
self.update_games_allowed = True
self.ui.on_discount.setChecked(False)
def prepare_request(
self,
price: str = None,
added_tag: int = 0,
removed_tag: int = 0,
added_type: str = "",
removed_type: str = "",
):
if not self.update_games_allowed:
return
if price is not None:
self.price = price
if added_tag != 0:
self.tags.append(added_tag)
if removed_tag != 0 and removed_tag in self.tags:
self.tags.remove(removed_tag)
if added_type:
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.ui.on_discount.isChecked():
# self.free_scrollarea.setVisible(False)
self.discounts_group.setVisible(False)
else:
# self.free_scrollarea.setVisible(True)
if len(self.discounts_group.layout().children()) > 0:
self.discounts_group.setVisible(True)
self.games_group.loading(True)
browse_model = SearchStoreQuery(
language=self.core.language_code,
country=self.core.country_code,
count=20,
price_range=self.price,
on_sale=self.ui.on_discount.isChecked(),
)
browse_model.tag = "|".join(self.tags)
if self.types:
browse_model.category = "|".join(self.types)
self.api_core.browse_games(browse_model, self.show_games)
class CheckBox(QCheckBox):
activated = pyqtSignal(str)
deactivated = pyqtSignal(str)
def __init__(self, text, tag):
super(CheckBox, self).__init__(text)
self.tag = tag
self.toggled.connect(self.handle_toggle)
def handle_toggle(self):
if self.isChecked():
self.activated.emit(self.tag)
else:
self.deactivated.emit(self.tag)

View file

@ -1,98 +0,0 @@
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import (
QWidget,
QSizePolicy,
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
from .api.debug import DebugDialog
from .api.models.response import CatalogOfferModel
class SearchResults(QScrollArea, SideTabContents):
show_info = pyqtSignal(CatalogOfferModel)
def __init__(self, api_core, parent=None):
super(SearchResults, self).__init__(parent=parent)
self.implements_scrollarea = True
self.api_core = api_core
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)
# self.main_layout.setContentsMargins(0, 0, 0, 0)
# self.main_layout.addWidget(self.results_scrollarea)
self.setEnabled(False)
def load_results(self, text: str):
self.setEnabled(False)
if text != "":
self.api_core.search_game(text, self.show_results)
def show_results(self, results: dict):
for w in self.results_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
for w in self.results_container.findChildren(SearchResultItem, options=Qt.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
if not results:
self.results_layout.addWidget(QLabel(self.tr("No results found")))
else:
for res in results:
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(CatalogOfferModel)
def __init__(self, manager: QtRequestManager, catalog_game: CatalogOfferModel, parent=None):
super(SearchResultItem, self).__init__(manager, parent=parent)
self.setFixedSize(ImageSize.Normal)
self.ui.setupUi(self)
key_images = catalog_game.key_images
self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url)
self.ui.title_label.setText(catalog_game.title)
price = catalog_game.price.total_price["fmtPrice"]["originalPrice"]
discount_price = catalog_game.price.total_price["fmtPrice"]["discountPrice"]
self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}')
if price != discount_price:
font = self.ui.price_label.font()
font.setStrikeOut(True)
self.ui.price_label.setFont(font)
self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}')
else:
self.ui.discount_label.setVisible(False)
self.catalog_game = catalog_game
def mousePressEvent(self, a0: QMouseEvent) -> None:
if a0.button() == Qt.LeftButton:
a0.accept()
self.show_info.emit(self.catalog_game)
if a0.button() == Qt.RightButton:
a0.accept()
dialog = DebugDialog(self.catalog_game.__dict__, self)
dialog.show()

View file

@ -1,396 +0,0 @@
import datetime
import logging
from typing import List
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import (
QGroupBox,
QCheckBox,
QLabel,
QPushButton,
QHBoxLayout,
QWidget, QSizePolicy, QStackedLayout,
)
from legendary.core import LegendaryCore
from rare.ui.components.tabs.store.store import Ui_ShopWidget
from rare.utils.extra_widgets import ButtonLineEdit
from rare.widgets.flow_layout import FlowLayout
from rare.widgets.side_tab import SideTabContents
from .api.models.query import SearchStoreQuery
from .api.models.response import CatalogOfferModel, WishlistItemModel
from .constants import Constants
from .game_widgets import GameWidget
from .image_widget import WaitingSpinner
from .shop_api_core import ShopApiCore
from .api.models.utils import parse_date
logger = logging.getLogger("Shop")
# noinspection PyAttributeOutsideInit,PyBroadException
class ShopWidget(QWidget, SideTabContents):
show_info = pyqtSignal(str)
show_game = pyqtSignal(dict)
def __init__(self, cache_dir, core: LegendaryCore, shop_api: ShopApiCore, parent=None):
super(ShopWidget, self).__init__(parent=parent)
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 = ""
self.tags = []
self.types = []
self.update_games_allowed = True
self.ui.free_scrollarea.setDisabled(True)
self.free_game_widgets = []
self.active_search_request = False
self.next_search = ""
self.wishlist: List = []
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.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.ui.main_layout.addWidget(self.search_bar, 0, 0)
# self.search_bar.textChanged.connect(self.search_games)
self.search_bar.returnPressed.connect(self.show_search_results)
self.search_bar.buttonClicked.connect(self.show_search_results)
self.init_filter()
self.search_bar.setHidden(True)
self.filter_gb.setHidden(True)
self.filter_game_gb.setHidden(True)
# self.search_bar.textChanged.connect(self.load_completer)
def load(self):
# load free games
self.api_core.get_free_games(self.add_free_games)
# load wishlist
self.api_core.get_wishlist(self.add_wishlist_items)
# load browse games
self.prepare_request()
def update_wishlist(self):
self.api_core.get_wishlist(self.add_wishlist_items)
def add_wishlist_items(self, wishlist: List[WishlistItemModel]):
for w in self.discounts_flow.findChildren(QWidget, options=Qt.FindDirectChildrenOnly):
self.discounts_flow.layout().removeWidget(w)
w.deleteLater()
# 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:
if not game:
continue
try:
if game.offer.price.total_price["discount"] > 0:
w = GameWidget(self.api_core.cached_manager, game.offer)
w.show_info.connect(self.show_game)
self.discounts_flow.layout().addWidget(w)
discounts += 1
except Exception as e:
logger.warning(f"{game} {e}")
continue
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[CatalogOfferModel]):
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.ui.free_container.layout().addWidget(
QLabel(self.tr("Failed to fetch free games: {}").format(free_games[1]))
)
btn = QPushButton(self.tr("Reload"))
self.ui.free_container.layout().addWidget(btn)
btn.clicked.connect(
lambda: self.api_core.get_free_games(self.add_free_games)
)
self.ui.free_container.setEnabled(True)
return
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.Fixed, QSizePolicy.Fixed)
self.free_games_now.setLayout(free_games_now_layout)
self.ui.free_container.layout().addWidget(self.free_games_now)
self.free_games_next = QGroupBox(self.tr("Free next week"), parent=self.ui.free_container)
free_games_next_layout = QHBoxLayout(self.free_games_next)
# free_games_next_layout.setContentsMargins(0, 0, 0, 0)
self.free_games_next.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.free_games_next.setLayout(free_games_next_layout)
self.ui.free_container.layout().addWidget(self.free_games_next)
date = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
free_games_now = []
coming_free_games = []
for game in free_games:
try:
if (
game.price.total_price["fmtPrice"]["discountPrice"] == "0"
and game.price.total_price["fmtPrice"]["originalPrice"]
!= game.price.total_price["fmtPrice"]["discountPrice"]
):
free_games_now.append(game)
continue
if game.title == "Mystery Game":
coming_free_games.append(game)
continue
except KeyError as e:
logger.warning(str(e))
try:
# parse datetime to check if game is next week or now
try:
start_date = parse_date(
game.promotions["upcomingPromotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception:
try:
start_date = parse_date(
game.promotions["promotionalOffers"][0]["promotionalOffers"][0]["startDate"]
)
except Exception as e:
continue
except TypeError:
print("type error")
continue
if start_date > date:
coming_free_games.append(game)
# free games now
now_free = 0
for free_game in free_games_now:
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)
now_free += 1
if now_free == 0:
self.free_games_now.layout().addWidget(
QLabel(self.tr("Could not find current free game"))
)
# free games next week
for free_game in coming_free_games:
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.ui.free_scrollarea.setMinimumHeight(
self.free_games_now.sizeHint().height()
+ self.ui.free_container.layout().contentsMargins().top()
+ self.ui.free_container.layout().contentsMargins().bottom()
+ self.ui.free_scrollarea.horizontalScrollBar().sizeHint().height()
)
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.ui.none_price.toggled.connect(
lambda: self.prepare_request("") if self.ui.none_price.isChecked() else None
)
self.ui.free_button.toggled.connect(
lambda: self.prepare_request("free")
if self.ui.free_button.isChecked()
else None
)
self.ui.under10.toggled.connect(
lambda: self.prepare_request("<price>[0, 1000)")
if self.ui.under10.isChecked()
else None
)
self.ui.under20.toggled.connect(
lambda: self.prepare_request("<price>[0, 2000)")
if self.ui.under20.isChecked()
else None
)
self.ui.under30.toggled.connect(
lambda: self.prepare_request("<price>[0, 3000)")
if self.ui.under30.isChecked()
else None
)
self.ui.above.toggled.connect(
lambda: self.prepare_request("<price>[1499,]")
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.ui.on_discount.toggled.connect(lambda: self.prepare_request())
constants = Constants()
self.checkboxes = []
for groupbox, variables in [
(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:
checkbox = CheckBox(text, tag)
checkbox.activated.connect(lambda x: self.prepare_request(added_tag=x))
checkbox.deactivated.connect(
lambda x: self.prepare_request(removed_tag=x)
)
groupbox.layout().addWidget(checkbox)
self.checkboxes.append(checkbox)
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.ui.none_price.setChecked(True)
self.tags = []
self.types = []
self.update_games_allowed = True
self.prepare_request("")
self.ui.on_discount.setChecked(False)
def prepare_request(
self,
price: str = None,
added_tag: int = 0,
removed_tag: int = 0,
added_type: str = "",
removed_type: str = "",
):
if not self.update_games_allowed:
return
if price is not None:
self.price = price
if added_tag != 0:
self.tags.append(added_tag)
if removed_tag != 0 and removed_tag in self.tags:
self.tags.remove(removed_tag)
if added_type:
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.ui.on_discount.isChecked():
self.ui.free_scrollarea.setVisible(False)
self.ui.discounts_group.setVisible(False)
else:
self.ui.free_scrollarea.setVisible(True)
if len(self.ui.discounts_group.layout().children()) > 0:
self.ui.discounts_group.setVisible(True)
self.games_layout.setCurrentWidget(self.games_spinner)
browse_model = SearchStoreQuery(
language=self.core.language_code,
country=self.core.country_code,
count=20,
price_range=self.price,
on_sale=self.ui.on_discount.isChecked(),
)
browse_model.tag = "|".join(self.tags)
if self.types:
browse_model.category = "|".join(self.types)
self.api_core.browse_games(browse_model, self.show_games)
def show_games(self, data):
for w in self.games_flow.findChildren(QWidget, options=Qt.FindDirectChildrenOnly):
self.games_flow.layout().removeWidget(w)
w.deleteLater()
if data:
for game in data:
w = GameWidget(self.api_core.cached_manager, game)
w.show_info.connect(self.show_game)
self.games_flow.layout().addWidget(w)
else:
self.games_flow.layout().addWidget(
QLabel(self.tr("Could not get games matching the filter"))
)
self.games_layout.setCurrentWidget(self.games_flow)
# FIXME: FlowLayout doesn't update on adding widget
self.games_flow.layout().update()
class CheckBox(QCheckBox):
activated = pyqtSignal(str)
deactivated = pyqtSignal(str)
def __init__(self, text, tag):
super(CheckBox, self).__init__(text)
self.tag = tag
self.toggled.connect(self.handle_toggle)
def handle_toggle(self):
if self.isChecked():
self.activated.emit(self.tag)
else:
self.deactivated.emit(self.tag)

View file

@ -11,12 +11,11 @@ from rare.components.tabs.store.constants import (
wishlist_add_query,
wishlist_remove_query,
)
from rare.components.tabs.store.shop_models import BrowseModel
from rare.utils.paths import cache_dir
from rare.utils.qt_requests import QtRequests
from .api.models.query import SearchStoreQuery
from .api.models.diesel import DieselProduct
from .api.models.response import (
DieselProduct,
ResponseModel,
CatalogOfferModel,
)
@ -28,11 +27,11 @@ graphql_url = "https://graphql.epicgames.com/graphql"
DEBUG: Callable[[], bool] = lambda: "--debug" in QApplication.arguments()
class ShopApiCore(QObject):
class StoreAPI(QObject):
update_wishlist = pyqtSignal()
def __init__(self, token, language: str, country: str):
super(ShopApiCore, self).__init__()
def __init__(self, token, language: str, country: str, installed):
super(StoreAPI, self).__init__()
self.token = token
self.language_code: str = language
self.country_code: str = country
@ -42,6 +41,8 @@ class ShopApiCore(QObject):
self.authed_manager = QtRequests(token=token, parent=self)
self.cached_manager = QtRequests(cache=str(cache_dir().joinpath("store")), parent=self)
self.installed = installed
self.browse_active = False
self.next_browse_request = tuple(())
@ -153,13 +154,13 @@ class ShopApiCore(QObject):
"query": search_query,
"variables": browse_model.to_dict()
}
debug = DebugDialog(payload["variables"], None)
debug.exec()
# debug = DebugDialog(payload["variables"], None)
# debug.exec()
self.manager.post(graphql_url, lambda data: self.__handle_browse_games(data, handle_func), payload)
def __handle_browse_games(self, data, handle_func):
debug = DebugDialog(data, None)
debug.exec()
# debug = DebugDialog(data, None)
# debug.exec()
self.browse_active = False
if data is None:
data = {}
@ -182,15 +183,29 @@ class ShopApiCore(QObject):
self.browse_games(*self.next_browse_request) # pylint: disable=E1120
self.next_browse_request = tuple(())
def get_game(self, slug: str, is_bundle: bool, handle_func):
def get_game_config_graphql(self, namespace: str, handle_func):
payload = {
"query": config_query,
"variables": {
"namespace": namespace
}
}
def __make_graphql_query(self):
pass
def __make_api_query(self):
pass
def get_game_config_cms(self, slug: str, is_bundle: bool, handle_func):
url = "https://store-content.ak.epicgames.com/api"
url += f"/{self.locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}"
self.manager.get(url, lambda data: self.__handle_get_game(data, handle_func))
@staticmethod
def __handle_get_game(data, handle_func):
debug = DebugDialog(data, None)
debug.exec()
# debug = DebugDialog(data, None)
# debug.exec()
try:
product = DieselProduct.from_dict(data)
handle_func(product)
@ -214,8 +229,8 @@ class ShopApiCore(QObject):
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):
debug = DebugDialog(data, None)
debug.exec()
# debug = DebugDialog(data, None)
# debug.exec()
try:
response = ResponseModel.from_dict(data)
data = response.data.wishlist.add_to_wishlist
@ -240,8 +255,8 @@ class ShopApiCore(QObject):
payload)
def _handle_remove_from_wishlist(self, data, handle_func):
debug = DebugDialog(data, None)
debug.exec()
# debug = DebugDialog(data, None)
# debug.exec()
try:
response = ResponseModel.from_dict(data)
data = response.data.wishlist.remove_from_wishlist

View file

@ -1,8 +1,7 @@
import logging
from pprint import pprint
from typing import List
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtCore import Qt, QUrl, pyqtSignal
from PyQt5.QtGui import QFont, QDesktopServices, QFontMetrics
from PyQt5.QtWidgets import (
QWidget,
@ -12,38 +11,42 @@ from PyQt5.QtWidgets import (
QSizePolicy,
)
from rare.components.tabs.store.api.models.response import CatalogOfferModel, DieselProduct, DieselProductDetail
from rare.shared import LegendaryCoreSingleton
from rare.shared.image_manager import ImageSize
from rare.ui.components.tabs.store.shop_game_info import Ui_ShopInfo
from rare.components.tabs.store.api.debug import DebugDialog
from rare.components.tabs.store.api.models.diesel import DieselProduct, DieselProductDetail
from rare.components.tabs.store.api.models.response import CatalogOfferModel
from rare.models.image import ImageSize
from rare.ui.components.tabs.store.details import Ui_DetailsWidget
from rare.utils.misc import icon
from rare.widgets.side_tab import SideTabWidget, SideTabContents
from rare.widgets.elide_label import ElideLabel
from .api.debug import DebugDialog
from .image_widget import ShopImageWidget
from rare.widgets.side_tab import SideTabWidget, SideTabContents
from .image import LoadingImageWidget
logger = logging.getLogger("ShopInfo")
logger = logging.getLogger("StoreDetails")
class ShopGameInfo(QWidget, SideTabContents):
class DetailsWidget(QWidget, SideTabContents):
back_clicked: pyqtSignal = pyqtSignal()
# TODO Design
def __init__(self, installed_titles: list, api_core, parent=None):
super(ShopGameInfo, self).__init__(parent=parent)
self.ui = Ui_ShopInfo()
super(DetailsWidget, self).__init__(parent=parent)
self.ui = Ui_DetailsWidget()
self.ui.setupUi(self)
self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
# self.core = LegendaryCoreSingleton()
self.api_core = api_core
self.installed = installed_titles
self.ui.open_store_button.clicked.connect(self.button_clicked)
self.image = ShopImageWidget(api_core.cached_manager, self)
self.image.setFixedSize(ImageSize.Normal)
self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
self.offer: CatalogOfferModel = None
self.data: dict = {}
self.image = LoadingImageWidget(api_core.cached_manager, self)
self.image.setFixedSize(ImageSize.Normal)
self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
self.ui.left_layout.setAlignment(Qt.AlignTop)
self.ui.wishlist_button.clicked.connect(self.add_to_wishlist)
self.ui.open_store_button.clicked.connect(self.button_clicked)
self.ui.wishlist_button.setVisible(True)
self.in_wishlist = False
self.wishlist = []
@ -52,7 +55,9 @@ class ShopGameInfo(QWidget, SideTabContents):
self.requirements_tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.ui.requirements_layout.addWidget(self.requirements_tabs)
self.setDisabled(True)
self.ui.back_button.clicked.connect(self.back_clicked)
self.setDisabled(False)
def handle_wishlist_update(self, wishlist: List[CatalogOfferModel]):
if wishlist and wishlist[0] == "error":
@ -67,7 +72,6 @@ class ShopGameInfo(QWidget, SideTabContents):
def update_game(self, offer: CatalogOfferModel):
debug = DebugDialog(offer.__dict__, None)
debug.exec()
self.set_title.emit(offer.title)
self.ui.title.setText(offer.title)
self.title_str = offer.title
self.id_str = offer.id
@ -107,7 +111,7 @@ class ShopGameInfo(QWidget, SideTabContents):
# init API request
if slug:
self.api_core.get_game(offer.product_slug, is_bundle, self.data_received)
self.api_core.get_game_config_cms(offer.product_slug, is_bundle, self.data_received)
# else:
# self.data_received({})
self.offer = offer
@ -220,7 +224,7 @@ class ShopGameInfo(QWidget, SideTabContents):
# self.image_stack.setCurrentIndex(0)
about = product_data.about
self.ui.description_label.setText(about.desciption)
self.ui.description_label.setMarkdown(about.desciption)
self.ui.dev.setText(about.developer_attribution)
# try:
# if isinstance(aboudeveloper, list):

View file

@ -0,0 +1,18 @@
from PyQt5.QtWidgets import QGroupBox, QLayout
from rare.widgets.loading_widget import LoadingWidget
class StoreGroup(QGroupBox):
def __init__(self, title: str, layout: type[QLayout], parent=None):
super().__init__(parent=parent)
self.setTitle(title)
self.main_layout = layout(self)
self.loading_widget = LoadingWidget(autostart=True, parent=self)
def loading(self, state: bool) -> None:
if state:
self.loading_widget.start()
else:
self.loading_widget.stop()

View file

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

View file

@ -3,26 +3,40 @@ import logging
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QPushButton
from orjson import orjson
from rare.components.tabs.store.api.debug import DebugDialog
from rare.components.tabs.store.api.models.response import CatalogOfferModel
from rare.shared.image_manager import ImageSize
from rare.models.image import ImageSize
from rare.utils.misc import qta_icon
from rare.utils.qt_requests import QtRequestManager
from .api.debug import DebugDialog
from .image_widget import ShopImageWidget
from rare.utils.qt_requests import QtRequests
from .image import LoadingImageWidget
logger = logging.getLogger("GameWidgets")
class GameWidget(ShopImageWidget):
show_info = pyqtSignal(CatalogOfferModel)
class ItemWidget(LoadingImageWidget):
show_details = pyqtSignal(CatalogOfferModel)
def __init__(self, manager: QtRequestManager, catalog_game: CatalogOfferModel = None, parent=None):
super(GameWidget, self).__init__(manager, parent=parent)
def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel = None, parent=None):
super(ItemWidget, self).__init__(manager, parent=parent)
self.catalog_game = catalog_game
def mousePressEvent(self, a0: QMouseEvent) -> None:
if a0.button() == Qt.LeftButton:
a0.accept()
self.show_details.emit(self.catalog_game)
if a0.button() == Qt.RightButton:
a0.accept()
print(self.catalog_game.__dict__)
dialog = DebugDialog(self.catalog_game.__dict__, self)
dialog.show()
class StoreItemWidget(ItemWidget):
def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel = None, parent=None):
super(StoreItemWidget, self).__init__(manager, catalog_game, parent=parent)
self.setFixedSize(ImageSize.Wide)
self.ui.setupUi(self)
self.catalog_game = catalog_game
if catalog_game:
self.init_ui(catalog_game)
@ -62,26 +76,38 @@ class GameWidget(ShopImageWidget):
# else:
# logger.info(", ".join([img["type"] for img in json_info["keyImages"]]))
def mousePressEvent(self, a0: QMouseEvent) -> None:
if a0.button() == Qt.LeftButton:
a0.accept()
self.show_info.emit(self.catalog_game)
if a0.button() == Qt.RightButton:
a0.accept()
print(self.catalog_game.__dict__)
dialog = DebugDialog(self.catalog_game.__dict__, self)
dialog.show()
class ResultsItemWidget(ItemWidget):
def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel, parent=None):
super(ResultsItemWidget, self).__init__(manager, catalog_game, parent=parent)
self.setFixedSize(ImageSize.Normal)
self.ui.setupUi(self)
key_images = catalog_game.key_images
self.fetchPixmap(key_images.for_dimensions(self.width(), self.height()).url)
self.ui.title_label.setText(catalog_game.title)
price = catalog_game.price.total_price["fmtPrice"]["originalPrice"]
discount_price = catalog_game.price.total_price["fmtPrice"]["discountPrice"]
self.ui.price_label.setText(f'{price if price != "0" else self.tr("Free")}')
if price != discount_price:
font = self.ui.price_label.font()
font.setStrikeOut(True)
self.ui.price_label.setFont(font)
self.ui.discount_label.setText(f'{discount_price if discount_price != "0" else self.tr("Free")}')
else:
self.ui.discount_label.setVisible(False)
class WishlistWidget(ShopImageWidget):
open_game = pyqtSignal(CatalogOfferModel)
class WishlistItemWidget(ItemWidget):
show_details = pyqtSignal(CatalogOfferModel)
delete_from_wishlist = pyqtSignal(CatalogOfferModel)
def __init__(self, manager: QtRequestManager, catalog_game: CatalogOfferModel, parent=None):
super(WishlistWidget, self).__init__(manager, parent=parent)
def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel, parent=None):
super(WishlistItemWidget, self).__init__(manager, catalog_game, parent=parent)
self.setFixedSize(ImageSize.Wide)
self.ui.setupUi(self)
self.game = catalog_game
for attr in catalog_game.custom_attributes:
if attr["key"] == "developerName":
developer = attr["value"]
@ -109,17 +135,7 @@ class WishlistWidget(ShopImageWidget):
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)
lambda: self.delete_from_wishlist.emit(self.catalog_game)
)
self.layout().insertWidget(0, self.delete_button, alignment=Qt.AlignRight)
def mousePressEvent(self, a0: QMouseEvent) -> None:
# left button
if a0.button() == Qt.LeftButton:
a0.accept()
self.open_game.emit(self.game)
# right
if a0.button() == Qt.RightButton:
a0.accept()
dialog = DebugDialog(self.game.__dict__, self)
dialog.show()

View file

@ -1,27 +1,65 @@
from typing import List
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import QMessageBox, QWidget
from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot
from PyQt5.QtGui import QShowEvent
from PyQt5.QtWidgets import QMessageBox, QWidget, QScrollArea, QFrame, QSizePolicy
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
from rare.widgets.side_tab import SideTabContents
from rare.widgets.sliding_stack import SlidingStackedWidget
from .api.models.response import WishlistItemModel, CatalogOfferModel
from .store_api import StoreAPI
from .widgets.details import DetailsWidget
from .widgets.items import WishlistItemWidget
class Wishlist(QWidget, SideTabContents):
show_game_info = pyqtSignal(CatalogOfferModel)
class WishlistPage(SlidingStackedWidget, SideTabContents):
def __init__(self, api: StoreAPI, parent=None):
super(WishlistPage, self).__init__(parent=parent)
self.implements_scrollarea = True
self.wishlist_widget = WishlistWidget(api, parent=self)
self.wishlist_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.wishlist_widget.set_title.connect(self.set_title)
self.wishlist_widget.show_details.connect(self.show_details)
self.details_widget = DetailsWidget([], api, parent=self)
self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
self.details_scroll = QScrollArea(self)
self.details_scroll.setWidgetResizable(True)
self.details_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
self.details_scroll.setWidget(self.details_widget)
self.setDirection(Qt.Horizontal)
self.addWidget(self.wishlist_widget)
self.addWidget(self.details_scroll)
@pyqtSlot()
def show_main(self):
self.slideInWidget(self.wishlist_widget)
@pyqtSlot(object)
def show_details(self, game: CatalogOfferModel):
self.details_widget.update_game(game)
self.slideInWidget(self.details_scroll)
class WishlistWidget(QWidget, SideTabContents):
show_details = pyqtSignal(CatalogOfferModel)
update_wishlist_signal = pyqtSignal()
def __init__(self, api_core: ShopApiCore, parent=None):
super(Wishlist, self).__init__(parent=parent)
def __init__(self, api: StoreAPI, parent=None):
super(WishlistWidget, self).__init__(parent=parent)
self.implements_scrollarea = True
self.api_core = api_core
self.api = api
self.ui = Ui_Wishlist()
self.ui.setupUi(self)
self.ui.main_layout.setContentsMargins(0, 0, 3, 0)
self.setEnabled(False)
self.wishlist = []
self.widgets = []
@ -37,12 +75,16 @@ class Wishlist(QWidget, SideTabContents):
lambda: self.sort_wishlist(sort=self.ui.sort_cb.currentIndex())
)
def showEvent(self, a0: QShowEvent) -> None:
self.update_wishlist()
return super().showEvent(a0)
def update_wishlist(self):
self.setEnabled(False)
self.api_core.get_wishlist(self.set_wishlist)
self.api.get_wishlist(self.set_wishlist)
def delete_from_wishlist(self, game: CatalogOfferModel):
self.api_core.remove_from_wishlist(
self.api.remove_from_wishlist(
game.namespace,
game.id,
lambda success: self.update_wishlist()
@ -71,7 +113,7 @@ class Wishlist(QWidget, SideTabContents):
self.ui.no_games_label.setVisible(False)
def sort_wishlist(self, sort=0):
widgets = self.ui.list_container.findChildren(WishlistWidget, options=Qt.FindDirectChildrenOnly)
widgets = self.ui.list_container.findChildren(WishlistItemWidget, options=Qt.FindDirectChildrenOnly)
for w in widgets:
self.ui.list_container.layout().removeWidget(w)
@ -113,8 +155,8 @@ class Wishlist(QWidget, SideTabContents):
self.ui.no_games_label.setVisible(False)
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)
w = WishlistItemWidget(self.api.cached_manager, game.offer, self.ui.list_container)
w.show_details.connect(self.show_details)
w.delete_from_wishlist.connect(self.delete_from_wishlist)
self.widgets.append(w)
self.list_layout.addWidget(w)

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/shop_game_info.ui'
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/details.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# 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.
@ -11,24 +11,29 @@
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ShopInfo(object):
def setupUi(self, ShopInfo):
ShopInfo.setObjectName("ShopInfo")
ShopInfo.resize(443, 347)
ShopInfo.setWindowTitle("ShopGameInfo")
self.main_layout = QtWidgets.QHBoxLayout(ShopInfo)
class Ui_DetailsWidget(object):
def setupUi(self, DetailsWidget):
DetailsWidget.setObjectName("DetailsWidget")
DetailsWidget.resize(414, 343)
DetailsWidget.setWindowTitle("DetailsWidget")
self.main_layout = QtWidgets.QHBoxLayout(DetailsWidget)
self.main_layout.setObjectName("main_layout")
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.back_button = QtWidgets.QPushButton(DetailsWidget)
self.back_button.setText("")
self.back_button.setObjectName("back_button")
self.left_layout.addWidget(self.back_button)
self.main_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.info_layout = QtWidgets.QFormLayout()
self.info_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
self.info_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.info_layout.setContentsMargins(6, 6, 6, 6)
self.info_layout.setSpacing(12)
self.info_layout.setObjectName("info_layout")
self.title_label = QtWidgets.QLabel(ShopInfo)
self.title_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -36,12 +41,12 @@ class Ui_ShopInfo(object):
self.title_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.title_label.setObjectName("title_label")
self.info_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.title_label)
self.title = QtWidgets.QLabel(ShopInfo)
self.title = QtWidgets.QLabel(DetailsWidget)
self.title.setText("title")
self.title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.title.setObjectName("title")
self.info_layout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.title)
self.developer_label = QtWidgets.QLabel(ShopInfo)
self.developer_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -49,12 +54,12 @@ class Ui_ShopInfo(object):
self.developer_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.developer_label.setObjectName("developer_label")
self.info_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.developer_label)
self.dev = QtWidgets.QLabel(ShopInfo)
self.dev = QtWidgets.QLabel(DetailsWidget)
self.dev.setText("dev")
self.dev.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.dev.setObjectName("dev")
self.info_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.dev)
self.status_label = QtWidgets.QLabel(ShopInfo)
self.status_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -62,10 +67,10 @@ class Ui_ShopInfo(object):
self.status_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.status_label.setObjectName("status_label")
self.info_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.status_label)
self.owned_label = QtWidgets.QLabel(ShopInfo)
self.owned_label = QtWidgets.QLabel(DetailsWidget)
self.owned_label.setObjectName("owned_label")
self.info_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.owned_label)
self.price_label = QtWidgets.QLabel(ShopInfo)
self.price_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -73,7 +78,7 @@ class Ui_ShopInfo(object):
self.price_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.price_label.setObjectName("price_label")
self.info_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.price_label)
self.price_widget = QtWidgets.QWidget(ShopInfo)
self.price_widget = QtWidgets.QWidget(DetailsWidget)
self.price_widget.setObjectName("price_widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.price_widget)
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
@ -89,7 +94,7 @@ class Ui_ShopInfo(object):
self.discount_price.setObjectName("discount_price")
self.horizontalLayout.addWidget(self.discount_price)
self.info_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.price_widget)
self.tags_label = QtWidgets.QLabel(ShopInfo)
self.tags_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -97,11 +102,11 @@ class Ui_ShopInfo(object):
self.tags_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.tags_label.setObjectName("tags_label")
self.info_layout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.tags_label)
self.tags = QtWidgets.QLabel(ShopInfo)
self.tags = QtWidgets.QLabel(DetailsWidget)
self.tags.setText("tags")
self.tags.setObjectName("tags")
self.info_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.tags)
self.links_label = QtWidgets.QLabel(ShopInfo)
self.links_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -109,7 +114,7 @@ class Ui_ShopInfo(object):
self.links_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.links_label.setObjectName("links_label")
self.info_layout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.links_label)
self.social_group = QtWidgets.QWidget(ShopInfo)
self.social_group = QtWidgets.QWidget(DetailsWidget)
self.social_group.setMinimumSize(QtCore.QSize(250, 0))
self.social_group.setObjectName("social_group")
self.social_layout = QtWidgets.QHBoxLayout(self.social_group)
@ -117,7 +122,7 @@ class Ui_ShopInfo(object):
self.social_layout.setContentsMargins(0, 0, 0, 0)
self.social_layout.setObjectName("social_layout")
self.info_layout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.social_group)
self.actions_label = QtWidgets.QLabel(ShopInfo)
self.actions_label = QtWidgets.QLabel(DetailsWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
@ -125,7 +130,7 @@ class Ui_ShopInfo(object):
self.actions_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.actions_label.setObjectName("actions_label")
self.info_layout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.actions_label)
self.buttons_widget = QtWidgets.QWidget(ShopInfo)
self.buttons_widget = QtWidgets.QWidget(DetailsWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@ -146,7 +151,7 @@ class Ui_ShopInfo(object):
self.button_layout.addWidget(self.wishlist_button)
self.info_layout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.buttons_widget)
self.right_layout.addLayout(self.info_layout)
self.requirements_frame = QtWidgets.QFrame(ShopInfo)
self.requirements_frame = QtWidgets.QFrame(DetailsWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@ -159,55 +164,34 @@ class Ui_ShopInfo(object):
self.requirements_layout.setContentsMargins(0, 0, 0, 0)
self.requirements_layout.setObjectName("requirements_layout")
self.right_layout.addWidget(self.requirements_frame)
self.description_group = QtWidgets.QGroupBox(ShopInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.description_group.sizePolicy().hasHeightForWidth())
self.description_group.setSizePolicy(sizePolicy)
self.description_group.setFlat(False)
self.description_group.setObjectName("description_group")
self.description_layout = QtWidgets.QVBoxLayout(self.description_group)
self.description_layout.setObjectName("description_layout")
self.description_label = QtWidgets.QLabel(self.description_group)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.description_label.sizePolicy().hasHeightForWidth())
self.description_label.setSizePolicy(sizePolicy)
self.description_label.setText("error")
self.description_label.setTextFormat(QtCore.Qt.MarkdownText)
self.description_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.description_label.setWordWrap(True)
self.description_label = QtWidgets.QTextBrowser(DetailsWidget)
self.description_label.setOpenExternalLinks(True)
self.description_label.setObjectName("description_label")
self.description_layout.addWidget(self.description_label)
self.right_layout.addWidget(self.description_group)
self.right_layout.addWidget(self.description_label)
self.main_layout.addLayout(self.right_layout)
self.main_layout.setStretch(1, 1)
self.retranslateUi(ShopInfo)
self.retranslateUi(DetailsWidget)
def retranslateUi(self, ShopInfo):
def retranslateUi(self, DetailsWidget):
_translate = QtCore.QCoreApplication.translate
self.title_label.setText(_translate("ShopInfo", "Title"))
self.developer_label.setText(_translate("ShopInfo", "Developer"))
self.status_label.setText(_translate("ShopInfo", "Status"))
self.owned_label.setText(_translate("ShopInfo", "You already own this game"))
self.price_label.setText(_translate("ShopInfo", "Price"))
self.tags_label.setText(_translate("ShopInfo", "Tags"))
self.links_label.setText(_translate("ShopInfo", "Links"))
self.actions_label.setText(_translate("ShopInfo", "Actions"))
self.open_store_button.setText(_translate("ShopInfo", "Buy in Epic Games Store"))
self.wishlist_button.setText(_translate("ShopInfo", "Add to wishlist"))
self.description_group.setTitle(_translate("ShopInfo", "Description"))
self.title_label.setText(_translate("DetailsWidget", "Title"))
self.developer_label.setText(_translate("DetailsWidget", "Developer"))
self.status_label.setText(_translate("DetailsWidget", "Status"))
self.owned_label.setText(_translate("DetailsWidget", "You already own this game"))
self.price_label.setText(_translate("DetailsWidget", "Price"))
self.tags_label.setText(_translate("DetailsWidget", "Tags"))
self.links_label.setText(_translate("DetailsWidget", "Links"))
self.actions_label.setText(_translate("DetailsWidget", "Actions"))
self.open_store_button.setText(_translate("DetailsWidget", "Buy in Epic Games Store"))
self.wishlist_button.setText(_translate("DetailsWidget", "Add to wishlist"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ShopInfo = QtWidgets.QWidget()
ui = Ui_ShopInfo()
ui.setupUi(ShopInfo)
ShopInfo.show()
DetailsWidget = QtWidgets.QWidget()
ui = Ui_DetailsWidget()
ui.setupUi(DetailsWidget)
DetailsWidget.show()
sys.exit(app.exec_())

View file

@ -1,26 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ShopInfo</class>
<widget class="QWidget" name="ShopInfo">
<class>DetailsWidget</class>
<widget class="QWidget" name="DetailsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>443</width>
<height>347</height>
<width>414</width>
<height>343</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">ShopGameInfo</string>
<string notr="true">DetailsWidget</string>
</property>
<layout class="QHBoxLayout" name="main_layout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="left_layout"/>
<layout class="QVBoxLayout" name="left_layout">
<item>
<widget class="QPushButton" name="back_button">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item>
<layout class="QFormLayout" name="info_layout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@ -339,46 +350,10 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="description_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QTextBrowser" name="description_label">
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="title">
<string>Description</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="description_layout">
<item>
<widget class="QLabel" name="description_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">error</string>
</property>
<property name="textFormat">
<enum>Qt::MarkdownText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/store.ui'
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/landing.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# 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.
@ -11,14 +11,22 @@
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ShopWidget(object):
def setupUi(self, ShopWidget):
ShopWidget.setObjectName("ShopWidget")
ShopWidget.resize(788, 662)
ShopWidget.setWindowTitle("Store")
self.main_layout = QtWidgets.QGridLayout(ShopWidget)
class Ui_LandingWidget(object):
def setupUi(self, LandingWidget):
LandingWidget.setObjectName("LandingWidget")
LandingWidget.resize(788, 662)
LandingWidget.setWindowTitle("LandingWidget")
self.main_layout = QtWidgets.QHBoxLayout(LandingWidget)
self.main_layout.setObjectName("main_layout")
self.filter_scrollarea = QtWidgets.QScrollArea(ShopWidget)
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.main_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.reset_button = QtWidgets.QPushButton(LandingWidget)
self.reset_button.setObjectName("reset_button")
self.right_layout.addWidget(self.reset_button)
self.filter_scrollarea = QtWidgets.QScrollArea(LandingWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@ -89,81 +97,34 @@ class Ui_ShopWidget(object):
self.others_layout.setObjectName("others_layout")
self.filter_container_layout.addWidget(self.others_group)
self.filter_scrollarea.setWidget(self.filter_container)
self.main_layout.addWidget(self.filter_scrollarea, 1, 1, 1, 1)
self.reset_button = QtWidgets.QPushButton(ShopWidget)
self.reset_button.setObjectName("reset_button")
self.main_layout.addWidget(self.reset_button, 0, 1, 1, 1)
self.games_scrollarea = QtWidgets.QScrollArea(ShopWidget)
self.games_scrollarea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.games_scrollarea.setFrameShadow(QtWidgets.QFrame.Plain)
self.games_scrollarea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.games_scrollarea.setWidgetResizable(True)
self.games_scrollarea.setObjectName("games_scrollarea")
self.games_container = QtWidgets.QWidget()
self.games_container.setGeometry(QtCore.QRect(0, 0, 628, 618))
self.games_container.setObjectName("games_container")
self.games_container_layout = QtWidgets.QVBoxLayout(self.games_container)
self.games_container_layout.setContentsMargins(0, 0, 3, 0)
self.games_container_layout.setObjectName("games_container_layout")
self.free_scrollarea = QtWidgets.QScrollArea(self.games_container)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.free_scrollarea.sizePolicy().hasHeightForWidth())
self.free_scrollarea.setSizePolicy(sizePolicy)
self.free_scrollarea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.free_scrollarea.setFrameShadow(QtWidgets.QFrame.Plain)
self.free_scrollarea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.free_scrollarea.setWidgetResizable(True)
self.free_scrollarea.setObjectName("free_scrollarea")
self.free_container = QtWidgets.QWidget()
self.free_container.setGeometry(QtCore.QRect(0, 0, 16, 16))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.free_container.sizePolicy().hasHeightForWidth())
self.free_container.setSizePolicy(sizePolicy)
self.free_container.setObjectName("free_container")
self.free_container_layout = QtWidgets.QHBoxLayout(self.free_container)
self.free_container_layout.setContentsMargins(0, 0, 0, 3)
self.free_container_layout.setObjectName("free_container_layout")
self.free_scrollarea.setWidget(self.free_container)
self.games_container_layout.addWidget(self.free_scrollarea)
self.discounts_group = QtWidgets.QGroupBox(self.games_container)
self.discounts_group.setObjectName("discounts_group")
self.games_container_layout.addWidget(self.discounts_group)
self.games_group = QtWidgets.QGroupBox(self.games_container)
self.games_group.setObjectName("games_group")
self.games_container_layout.addWidget(self.games_group)
self.games_scrollarea.setWidget(self.games_container)
self.main_layout.addWidget(self.games_scrollarea, 1, 0, 1, 1)
self.right_layout.addWidget(self.filter_scrollarea)
self.main_layout.addLayout(self.right_layout)
self.main_layout.setStretch(0, 1)
self.retranslateUi(ShopWidget)
self.retranslateUi(LandingWidget)
def retranslateUi(self, ShopWidget):
def retranslateUi(self, LandingWidget):
_translate = QtCore.QCoreApplication.translate
self.price_group.setTitle(_translate("ShopWidget", "Price"))
self.none_price.setText(_translate("ShopWidget", "None"))
self.free_button.setText(_translate("ShopWidget", "Free"))
self.under10.setText(_translate("ShopWidget", "Under 10"))
self.under20.setText(_translate("ShopWidget", "Under 20"))
self.under30.setText(_translate("ShopWidget", "Under 30"))
self.above.setText(_translate("ShopWidget", "14.99 and above"))
self.on_discount.setText(_translate("ShopWidget", "Discount"))
self.platform_group.setTitle(_translate("ShopWidget", "Platform"))
self.genre_group.setTitle(_translate("ShopWidget", "Genre"))
self.type_group.setTitle(_translate("ShopWidget", "Type"))
self.others_group.setTitle(_translate("ShopWidget", "Other tags"))
self.reset_button.setText(_translate("ShopWidget", "Reset filters"))
self.discounts_group.setTitle(_translate("ShopWidget", "Discounts from your wishlist"))
self.games_group.setTitle(_translate("ShopWidget", "Games"))
self.reset_button.setText(_translate("LandingWidget", "Reset filters"))
self.price_group.setTitle(_translate("LandingWidget", "Price"))
self.none_price.setText(_translate("LandingWidget", "None"))
self.free_button.setText(_translate("LandingWidget", "Free"))
self.under10.setText(_translate("LandingWidget", "Under 10"))
self.under20.setText(_translate("LandingWidget", "Under 20"))
self.under30.setText(_translate("LandingWidget", "Under 30"))
self.above.setText(_translate("LandingWidget", "14.99 and above"))
self.on_discount.setText(_translate("LandingWidget", "Discount"))
self.platform_group.setTitle(_translate("LandingWidget", "Platform"))
self.genre_group.setTitle(_translate("LandingWidget", "Genre"))
self.type_group.setTitle(_translate("LandingWidget", "Type"))
self.others_group.setTitle(_translate("LandingWidget", "Other tags"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ShopWidget = QtWidgets.QWidget()
ui = Ui_ShopWidget()
ui.setupUi(ShopWidget)
ShopWidget.show()
LandingWidget = QtWidgets.QWidget()
ui = Ui_LandingWidget()
ui.setupUi(LandingWidget)
LandingWidget.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LandingWidget</class>
<widget class="QWidget" name="LandingWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>788</width>
<height>662</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">LandingWidget</string>
</property>
<layout class="QHBoxLayout" name="main_layout" stretch="1,0">
<item>
<layout class="QVBoxLayout" name="left_layout"/>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item>
<widget class="QPushButton" name="reset_button">
<property name="text">
<string>Reset filters</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="filter_scrollarea">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="filter_container">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>142</width>
<height>390</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="filter_container_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="price_group">
<property name="title">
<string>Price</string>
</property>
<layout class="QVBoxLayout" name="price_layout">
<item>
<widget class="QRadioButton" name="none_price">
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="free_button">
<property name="text">
<string>Free</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under10">
<property name="text">
<string>Under 10</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under20">
<property name="text">
<string>Under 20</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under30">
<property name="text">
<string>Under 30</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="above">
<property name="text">
<string>14.99 and above</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="on_discount">
<property name="text">
<string>Discount</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="platform_group">
<property name="title">
<string>Platform</string>
</property>
<layout class="QVBoxLayout" name="platfrom_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="genre_group">
<property name="title">
<string>Genre</string>
</property>
<layout class="QVBoxLayout" name="genre_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="type_group">
<property name="title">
<string>Type</string>
</property>
<layout class="QVBoxLayout" name="type_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="others_group">
<property name="title">
<string>Other tags</string>
</property>
<layout class="QVBoxLayout" name="others_layout"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/search.ui'
#
# Created by: PyQt5 UI code generator 5.15.10
#
# 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.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_SearchWidget(object):
def setupUi(self, SearchWidget):
SearchWidget.setObjectName("SearchWidget")
SearchWidget.resize(491, 382)
SearchWidget.setWindowTitle("SearchWidget")
self.main_layout = QtWidgets.QHBoxLayout(SearchWidget)
self.main_layout.setObjectName("main_layout")
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.main_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.reset_button = QtWidgets.QPushButton(SearchWidget)
self.reset_button.setObjectName("reset_button")
self.right_layout.addWidget(self.reset_button)
self.filter_scrollarea = QtWidgets.QScrollArea(SearchWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.filter_scrollarea.sizePolicy().hasHeightForWidth())
self.filter_scrollarea.setSizePolicy(sizePolicy)
self.filter_scrollarea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.filter_scrollarea.setFrameShadow(QtWidgets.QFrame.Plain)
self.filter_scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.filter_scrollarea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.filter_scrollarea.setWidgetResizable(True)
self.filter_scrollarea.setObjectName("filter_scrollarea")
self.filter_container = QtWidgets.QWidget()
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)
self.filter_container_layout.setObjectName("filter_container_layout")
self.price_group = QtWidgets.QGroupBox(self.filter_container)
self.price_group.setObjectName("price_group")
self.price_layout = QtWidgets.QVBoxLayout(self.price_group)
self.price_layout.setObjectName("price_layout")
self.none_price = QtWidgets.QRadioButton(self.price_group)
self.none_price.setChecked(True)
self.none_price.setObjectName("none_price")
self.price_layout.addWidget(self.none_price)
self.free_button = QtWidgets.QRadioButton(self.price_group)
self.free_button.setObjectName("free_button")
self.price_layout.addWidget(self.free_button)
self.under10 = QtWidgets.QRadioButton(self.price_group)
self.under10.setObjectName("under10")
self.price_layout.addWidget(self.under10)
self.under20 = QtWidgets.QRadioButton(self.price_group)
self.under20.setObjectName("under20")
self.price_layout.addWidget(self.under20)
self.under30 = QtWidgets.QRadioButton(self.price_group)
self.under30.setObjectName("under30")
self.price_layout.addWidget(self.under30)
self.above = QtWidgets.QRadioButton(self.price_group)
self.above.setObjectName("above")
self.price_layout.addWidget(self.above)
self.on_discount = QtWidgets.QCheckBox(self.price_group)
self.on_discount.setObjectName("on_discount")
self.price_layout.addWidget(self.on_discount)
self.filter_container_layout.addWidget(self.price_group)
self.platform_group = QtWidgets.QGroupBox(self.filter_container)
self.platform_group.setObjectName("platform_group")
self.platfrom_layout = QtWidgets.QVBoxLayout(self.platform_group)
self.platfrom_layout.setObjectName("platfrom_layout")
self.filter_container_layout.addWidget(self.platform_group)
self.genre_group = QtWidgets.QGroupBox(self.filter_container)
self.genre_group.setObjectName("genre_group")
self.genre_layout = QtWidgets.QVBoxLayout(self.genre_group)
self.genre_layout.setObjectName("genre_layout")
self.filter_container_layout.addWidget(self.genre_group)
self.type_group = QtWidgets.QGroupBox(self.filter_container)
self.type_group.setObjectName("type_group")
self.type_layout = QtWidgets.QVBoxLayout(self.type_group)
self.type_layout.setObjectName("type_layout")
self.filter_container_layout.addWidget(self.type_group)
self.others_group = QtWidgets.QGroupBox(self.filter_container)
self.others_group.setObjectName("others_group")
self.others_layout = QtWidgets.QVBoxLayout(self.others_group)
self.others_layout.setObjectName("others_layout")
self.filter_container_layout.addWidget(self.others_group)
self.filter_scrollarea.setWidget(self.filter_container)
self.right_layout.addWidget(self.filter_scrollarea)
self.main_layout.addLayout(self.right_layout)
self.main_layout.setStretch(0, 1)
self.retranslateUi(SearchWidget)
def retranslateUi(self, SearchWidget):
_translate = QtCore.QCoreApplication.translate
self.reset_button.setText(_translate("SearchWidget", "Reset filters"))
self.price_group.setTitle(_translate("SearchWidget", "Price"))
self.none_price.setText(_translate("SearchWidget", "None"))
self.free_button.setText(_translate("SearchWidget", "Free"))
self.under10.setText(_translate("SearchWidget", "Under 10"))
self.under20.setText(_translate("SearchWidget", "Under 20"))
self.under30.setText(_translate("SearchWidget", "Under 30"))
self.above.setText(_translate("SearchWidget", "14.99 and above"))
self.on_discount.setText(_translate("SearchWidget", "Discount"))
self.platform_group.setTitle(_translate("SearchWidget", "Platform"))
self.genre_group.setTitle(_translate("SearchWidget", "Genre"))
self.type_group.setTitle(_translate("SearchWidget", "Type"))
self.others_group.setTitle(_translate("SearchWidget", "Other tags"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
SearchWidget = QtWidgets.QWidget()
ui = Ui_SearchWidget()
ui.setupUi(SearchWidget)
SearchWidget.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SearchWidget</class>
<widget class="QWidget" name="SearchWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>382</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">SearchWidget</string>
</property>
<layout class="QHBoxLayout" name="main_layout" stretch="1,0">
<item>
<layout class="QVBoxLayout" name="left_layout"/>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item>
<widget class="QPushButton" name="reset_button">
<property name="text">
<string>Reset filters</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="filter_scrollarea">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="filter_container">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>142</width>
<height>390</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="filter_container_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="price_group">
<property name="title">
<string>Price</string>
</property>
<layout class="QVBoxLayout" name="price_layout">
<item>
<widget class="QRadioButton" name="none_price">
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="free_button">
<property name="text">
<string>Free</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under10">
<property name="text">
<string>Under 10</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under20">
<property name="text">
<string>Under 20</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="under30">
<property name="text">
<string>Under 30</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="above">
<property name="text">
<string>14.99 and above</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="on_discount">
<property name="text">
<string>Discount</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="platform_group">
<property name="title">
<string>Platform</string>
</property>
<layout class="QVBoxLayout" name="platfrom_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="genre_group">
<property name="title">
<string>Genre</string>
</property>
<layout class="QVBoxLayout" name="genre_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="type_group">
<property name="title">
<string>Type</string>
</property>
<layout class="QVBoxLayout" name="type_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="others_group">
<property name="title">
<string>Other tags</string>
</property>
<layout class="QVBoxLayout" name="others_layout"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

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

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# 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/widgets/wishlist_widget.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# 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.

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'rare/ui/components/tabs/store/wishlist.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# 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.
@ -16,8 +16,8 @@ class Ui_Wishlist(object):
Wishlist.setObjectName("Wishlist")
Wishlist.resize(423, 153)
Wishlist.setWindowTitle("Wishlist")
self.verticalLayout = QtWidgets.QVBoxLayout(Wishlist)
self.verticalLayout.setObjectName("verticalLayout")
self.main_layout = QtWidgets.QVBoxLayout(Wishlist)
self.main_layout.setObjectName("main_layout")
self.tool_layout = QtWidgets.QHBoxLayout()
self.tool_layout.setObjectName("tool_layout")
self.sort_label = QtWidgets.QLabel(Wishlist)
@ -59,10 +59,10 @@ class Ui_Wishlist(object):
self.reload_button.setText("")
self.reload_button.setObjectName("reload_button")
self.tool_layout.addWidget(self.reload_button)
self.verticalLayout.addLayout(self.tool_layout)
self.main_layout.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)
self.main_layout.addWidget(self.no_games_label)
self.list_scrollarea = QtWidgets.QScrollArea(Wishlist)
self.list_scrollarea.setWidgetResizable(True)
self.list_scrollarea.setObjectName("list_scrollarea")
@ -70,7 +70,7 @@ class Ui_Wishlist(object):
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.main_layout.addWidget(self.list_scrollarea)
self.retranslateUi(Wishlist)

View file

@ -13,7 +13,7 @@
<property name="windowTitle">
<string notr="true">Wishlist</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="main_layout">
<item>
<layout class="QHBoxLayout" name="tool_layout">
<item>