1
0
Fork 0
mirror of synced 2024-06-29 11:40:37 +12:00
Rare/rare/components/tabs/shop/shop_widget.py
2021-12-22 19:16:33 +01:00

299 lines
12 KiB
Python

import datetime
import logging
import random
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QGroupBox, QScrollArea, QCheckBox, QLabel, QPushButton, QHBoxLayout
from legendary.core import LegendaryCore
from rare.ui.components.tabs.store.store import Ui_ShopWidget
from rare.utils.extra_widgets import WaitingSpinner, FlowLayout, ButtonLineEdit
from .constants import Constants
from .game_widgets import GameWidget
from .shop_api_core import ShopApiCore
from .shop_models import BrowseModel
logger = logging.getLogger("Shop")
# noinspection PyAttributeOutsideInit,PyBroadException
class ShopWidget(QScrollArea, Ui_ShopWidget):
show_info = pyqtSignal(str)
show_game = pyqtSignal(dict)
free_game_widgets = []
active_search_request = False
next_search = ""
wishlist: list = []
def __init__(self, path, core: LegendaryCore, shop_api: ShopApiCore):
super(ShopWidget, self).__init__()
self.setWidgetResizable(True)
self.setupUi(self)
self.path = path
self.core = core
self.api_core = shop_api
self.price = ""
self.tags = []
self.types = []
self.update_games_allowed = True
self.free_widget.setLayout(FlowLayout())
self.free_stack.addWidget(WaitingSpinner())
self.free_stack.setCurrentIndex(1)
self.discount_widget.setLayout(FlowLayout())
self.discount_stack.addWidget(WaitingSpinner())
self.discount_stack.setCurrentIndex(1)
self.game_widget.setLayout(FlowLayout())
self.game_stack.addWidget(WaitingSpinner())
self.game_stack.setCurrentIndex(1)
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Games"))
self.layout().insertWidget(0, self.search_bar)
# 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.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):
for i in range(self.discount_widget.layout().count()):
item = self.discount_widget.layout().itemAt(i)
if item:
item.widget().deleteLater()
if wishlist and wishlist[0] == "error":
self.discount_widget.layout().addWidget(QLabel(self.tr("Failed to get wishlist: ") + 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"]["totalPrice"]["discount"] > 0:
w = GameWidget(self.path, game["offer"])
w.show_info.connect(self.show_game.emit)
self.discount_widget.layout().addWidget(w)
discounts += 1
except Exception as e:
logger.warning(str(game) + str(e))
continue
self.discounts_gb.setVisible(discounts > 0)
self.discount_widget.update()
self.discount_stack.setCurrentIndex(0)
def add_free_games(self, free_games: list):
for i in range(self.free_widget.layout().count()):
item = self.free_widget.layout().itemAt(i)
if item:
item.widget().deleteLater()
if free_games and free_games[0] == "error":
self.free_widget.layout().addWidget(QLabel(self.tr("Failed to fetch free games: ") + free_games[1]))
btn = QPushButton(self.tr("Reload"))
self.free_widget.layout().addWidget(btn)
btn.clicked.connect(lambda: self.api_core.get_free_games(self.add_free_games))
self.free_stack.setCurrentIndex(0)
return
self.free_games_now = QGroupBox(self.tr("Now Free"))
self.free_games_now.setLayout(QHBoxLayout())
self.free_widget.layout().addWidget(self.free_games_now)
self.coming_free_games = QGroupBox(self.tr("Free Games next week"))
self.coming_free_games.setLayout(QHBoxLayout())
self.free_widget.layout().addWidget(self.coming_free_games)
date = datetime.datetime.now()
free_games_now = []
coming_free_games = []
for game in free_games:
try:
if game['price']['totalPrice']['fmtPrice']['discountPrice'] == "0" and \
game['price']['totalPrice']['fmtPrice']['originalPrice'] != \
game['price']['totalPrice']['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 = datetime.datetime.strptime(
game["promotions"]["upcomingPromotionalOffers"][0]["promotionalOffers"][0]["startDate"],
'%Y-%m-%dT%H:%M:%S.%fZ')
except Exception:
try:
start_date = datetime.datetime.strptime(
game["promotions"]["promotionalOffers"][0]["promotionalOffers"][0]["startDate"],
'%Y-%m-%dT%H:%M:%S.%fZ')
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.path, free_game)
w.show_info.connect(self.show_game.emit)
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.path, free_game)
if free_game["title"] != "Mystery Game":
w.show_info.connect(self.show_game.emit)
self.coming_free_games.layout().addWidget(w)
# self.coming_free_games.setFixedWidth(int(40 + len(coming_free_games) * 300))
self.free_stack.setCurrentIndex(0)
def show_search_results(self):
self.show_info.emit(self.search_bar.text())
def init_filter(self):
self.none_price.toggled.connect(lambda: self.prepare_request("") if self.none_price.isChecked() else None)
self.free_button.toggled.connect(lambda: self.prepare_request("free") if self.free_button.isChecked() else None)
self.under10.toggled.connect(
lambda: self.prepare_request("<price>[0, 1000)") if self.under10.isChecked() else None)
self.under20.toggled.connect(
lambda: self.prepare_request("<price>[0, 2000)") if self.under20.isChecked() else None)
self.under30.toggled.connect(
lambda: self.prepare_request("<price>[0, 3000)") if self.under30.isChecked() else None)
self.above.toggled.connect(lambda: self.prepare_request("<price>[1499,]") if self.above.isChecked() else None)
# self.on_discount.toggled.connect(lambda: self.prepare_request("sale") if self.on_discount.isChecked() else None)
self.on_discount.toggled.connect(lambda: self.prepare_request())
constants = Constants()
self.checkboxes = []
for groupbox, variables in [(self.genre_gb, constants.categories),
(self.platform_gb, constants.platforms),
(self.others_gb, constants.others),
(self.type_gb, 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.reset_button.clicked.connect(self.reset_filters)
def reset_filters(self):
self.update_games_allowed = False
for cb in self.checkboxes:
cb.setChecked(False)
self.none_price.setChecked(True)
self.tags = []
self.types = []
self.update_games_allowed = True
self.prepare_request("")
self.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.on_discount.isChecked():
self.free_game_group_box.setVisible(False)
self.discounts_gb.setVisible(False)
else:
self.free_game_group_box.setVisible(True)
if len(self.discounts_gb.layout().children()) > 0:
self.discounts_gb.setVisible(True)
self.game_stack.setCurrentIndex(1)
date = f"[{datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d')},]"
browse_model = BrowseModel(language_code=self.core.language_code, country_code=self.core.country_code,
date=date, count=20, price=self.price,
onSale=self.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 item in (self.game_widget.layout().itemAt(i) for i in range(self.game_widget.layout().count())):
item.widget().deleteLater()
if data:
for game in data:
w = GameWidget(self.path, game, 275)
self.game_widget.layout().addWidget(w)
w.show_info.connect(self.show_game.emit)
else:
self.game_widget.layout().addWidget(
QLabel(self.tr("Could not get games matching the filter")))
self.game_stack.setCurrentIndex(0)
self.game_widget.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)