Merge pull request #99 from Dummerle/dev
Add a shop page to browse games, search games, and see information about them
This commit is contained in:
commit
7b0bed5eca
|
@ -144,3 +144,39 @@ class VerifyResult(Enum):
|
|||
HASH_MISMATCH = 1
|
||||
FILE_MISSING = 2
|
||||
OTHER_ERROR = 3
|
||||
|
||||
|
||||
x = {'title': 'Frostpunk',
|
||||
'id': 'b43c1e1e0ca14b6784b323c59c751136', 'namespace': 'd5241c76f178492ea1540fce45616757',
|
||||
'description': 'Frostpunk', 'effectiveDate': '2099-01-01T00:00:00.000Z', 'offerType': 'OTHERS', 'expiryDate': None,
|
||||
'status': 'ACTIVE', 'isCodeRedemptionOnly': True, 'keyImages': [{'type': 'VaultClosed',
|
||||
'url': 'https://cdn1.epicgames.com/d5241c76f178492ea1540fce45616757/offer/EpicVault_Clean_OPEN_V10_LightsON-1920x1080-75e6d0636a6083944570a1c6f94ead4f.png'},
|
||||
{'type': 'DieselStoreFrontWide',
|
||||
'url': 'https://cdn1.epicgames.com/salesEvent/salesEvent/EGS_Frostpunk_wide_2560x1440-ef2f4d458120af0839dde35b1a022828'},
|
||||
{'type': 'DieselStoreFrontTall',
|
||||
'url': 'https://cdn1.epicgames.com/salesEvent/salesEvent/EGS_Frostpunk_Tall_1200x1600-c71dc27cfe505c6c662c49011b36a0c5'}],
|
||||
'seller': {'id': 'o-ufmrk5furrrxgsp5tdngefzt5rxdcn', 'name': 'Epic Dev Test Account'}, 'productSlug': 'frostpunk',
|
||||
'urlSlug': 'free-games-06', 'url': None,
|
||||
'items': [{'id': '8341d7c7e4534db7848cc428aa4cbe5a', 'namespace': 'd5241c76f178492ea1540fce45616757'}],
|
||||
'customAttributes': [{'key': 'com.epicgames.app.freegames.vault.close', 'value': '[]'},
|
||||
{'key': 'com.epicgames.app.blacklist', 'value': '[]'},
|
||||
{'key': 'com.epicgames.app.freegames.vault.slug',
|
||||
'value': 'news/the-epic-mega-sale-returns-for-2021'},
|
||||
{'key': 'publisherName', 'value': '11 bit studios'}, {'key': 'dupe', 'value': '[]'},
|
||||
{'key': 'com.epicgames.app.freegames.vault.open', 'value': '[]'},
|
||||
{'key': 'developerName', 'value': '11 bit studios'},
|
||||
{'key': 'com.epicgames.app.productSlug', 'value': 'frostpunk'}],
|
||||
'categories': [{'path': 'freegames/vaulted'}, {'path': 'freegames'}, {'path': 'games'}, {'path': 'applications'}],
|
||||
'tags': [], 'price': {'totalPrice': {'discountPrice': 0, 'originalPrice': 0, 'voucherDiscount': 0, 'discount': 0,
|
||||
'currencyCode': 'USD', 'currencyInfo': {'decimals': 2},
|
||||
'fmtPrice': {'originalPrice': '0', 'discountPrice': '0',
|
||||
'intermediatePrice': '0'}},
|
||||
'lineOffers': [{'appliedRules': []}]}, 'promotions': {'promotionalOffers': [],
|
||||
'upcomingPromotionalOffers': [{
|
||||
'promotionalOffers': [
|
||||
{
|
||||
'startDate': '2021-06-03T15:00:00.000Z',
|
||||
'endDate': '2021-06-10T15:00:00.000Z',
|
||||
'discountSetting': {
|
||||
'discountType': 'PERCENTAGE',
|
||||
'discountPercentage': 0}}]}]}}
|
||||
|
|
|
@ -12,6 +12,7 @@ elif os.name == "nt":
|
|||
cache_dir = os.path.expandvars("%APPDATA%/rare/cache")
|
||||
else:
|
||||
cache_dir = os.path.expanduser("~/.cache/rare/")
|
||||
|
||||
if not os.path.exists(cache_dir):
|
||||
os.makedirs(cache_dir)
|
||||
|
||||
|
@ -26,3 +27,4 @@ if not os.path.exists(data_dir):
|
|||
os.makedirs(data_dir)
|
||||
|
||||
image_dir = os.path.join(data_dir, "images")
|
||||
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
import os
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from rare import __version__
|
||||
from rare import __version__, data_dir
|
||||
from rare.utils import singleton, utils
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# CLI Options
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-V", "--version", action="store_true", help="Shows version and exits")
|
||||
parser.add_argument("-S", "--silent", action="store_true",
|
||||
help="Launch Rare in background. Open it from System Tray Icon")
|
||||
parser.add_argument("--debug", action="store_true", help="Launch in debug mode")
|
||||
parser.add_argument("--offline", action="store_true", help="Launch Rare in offline mode")
|
||||
|
||||
parser.add_argument("--desktop-shortcut", action="store_true", dest="desktop_shortcut",
|
||||
|
@ -37,12 +40,12 @@ def main():
|
|||
print(__version__)
|
||||
return
|
||||
try:
|
||||
# this object only allows one instance pre machine
|
||||
# this object only allows one instance per machine
|
||||
me = singleton.SingleInstance()
|
||||
except singleton.SingleInstanceException:
|
||||
print("Rare is already running")
|
||||
|
||||
with open(os.path.expanduser("~/.cache/rare/lockfile"), "w") as file:
|
||||
with open(os.path.join(data_dir, "lockfile"), "w") as file:
|
||||
if args.subparser == "launch":
|
||||
file.write("launch " + args.app_name)
|
||||
else:
|
||||
|
@ -53,6 +56,7 @@ def main():
|
|||
if args.subparser == "launch":
|
||||
args.silent = True
|
||||
|
||||
|
||||
# fix error in cx_freeze
|
||||
|
||||
from rare.app import start
|
||||
|
|
18
rare/app.py
18
rare/app.py
|
@ -10,22 +10,24 @@ from PyQt5.QtGui import QIcon, QPalette
|
|||
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QStyleFactory
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare import languages_path, resources_path
|
||||
from rare import languages_path, resources_path, cache_dir
|
||||
from rare.components.dialogs.launch_dialog import LaunchDialog
|
||||
from rare.components.main_window import MainWindow
|
||||
from rare.components.tray_icon import TrayIcon
|
||||
from rare.utils.utils import get_lang, load_color_scheme
|
||||
|
||||
start_time = time.strftime('%y-%m-%d--%H-%M') # year-month-day-hour-minute
|
||||
file_name = os.path.expanduser(f"~/.cache/rare/logs/Rare_{start_time}.log")
|
||||
file_name = os.path.join(cache_dir, f"logs/Rare_{start_time}.log")
|
||||
if not os.path.exists(os.path.dirname(file_name)):
|
||||
os.makedirs(os.path.dirname(file_name))
|
||||
|
||||
logging.basicConfig(
|
||||
format='[%(name)s] %(levelname)s: %(message)s',
|
||||
level=logging.INFO,
|
||||
filename=file_name,
|
||||
)
|
||||
if "--debug" in sys.argv:
|
||||
logging.basicConfig(format='[%(name)s] %(levelname)s: %(message)s', level=logging.INFO)
|
||||
else:
|
||||
logging.basicConfig(
|
||||
format='[%(name)s] %(levelname)s: %(message)s',
|
||||
level=logging.INFO,
|
||||
filename=file_name,
|
||||
)
|
||||
logger = logging.getLogger("Rare")
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from requests.exceptions import ConnectionError
|
|||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare import image_dir
|
||||
|
||||
from rare.components.dialogs.login import LoginDialog
|
||||
from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog
|
||||
from rare.utils.utils import download_images
|
||||
|
@ -26,6 +27,7 @@ class ImageThread(QThread):
|
|||
self.download_progess.emit(100)
|
||||
|
||||
|
||||
|
||||
class LaunchDialog(QDialog, Ui_LaunchDialog):
|
||||
quit_app = pyqtSignal(int)
|
||||
start_app = pyqtSignal(bool)
|
||||
|
@ -66,6 +68,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
|
|||
if not os.path.exists(image_dir):
|
||||
os.makedirs(image_dir)
|
||||
|
||||
|
||||
if not self.offline:
|
||||
self.image_info.setText(self.tr("Downloading Images"))
|
||||
self.image_thread = ImageThread(self.core, self)
|
||||
|
|
|
@ -6,6 +6,7 @@ from PyQt5.QtGui import QCloseEvent
|
|||
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QApplication
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare import data_dir
|
||||
from rare.components.tab_widget import TabWidget
|
||||
from rare.utils.rpc import DiscordRPC
|
||||
|
||||
|
@ -59,7 +60,7 @@ class MainWindow(QMainWindow):
|
|||
self.timer.start(1000)
|
||||
|
||||
def timer_finished(self):
|
||||
file_path = os.path.expanduser("~/.cache/rare/lockfile")
|
||||
file_path = os.path.join(data_dir, "lockfile")
|
||||
if os.path.exists(file_path):
|
||||
file = open(file_path, "r")
|
||||
action = file.read()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import webbrowser
|
||||
|
||||
from PyQt5.QtCore import QSize, pyqtSignal
|
||||
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut
|
||||
from qtawesome import icon
|
||||
|
@ -13,6 +11,7 @@ from rare.components.tabs.cloud_saves import SyncSaves
|
|||
from rare.components.tabs.downloads import DownloadTab
|
||||
from rare.components.tabs.games import GameTab
|
||||
from rare.components.tabs.settings import SettingsTab
|
||||
from rare.components.tabs.shop import Shop
|
||||
from rare.utils import legendary_utils
|
||||
from rare.utils.models import InstallQueueItemModel, InstallOptionsModel
|
||||
|
||||
|
@ -23,32 +22,26 @@ class TabWidget(QTabWidget):
|
|||
|
||||
def __init__(self, core: LegendaryCore, parent, offline):
|
||||
super(TabWidget, self).__init__(parent=parent)
|
||||
disabled_tab = 3 if not offline else 1
|
||||
disabled_tab = 4 if not offline else 1
|
||||
self.core = core
|
||||
self.setTabBar(TabBar(disabled_tab))
|
||||
|
||||
# Generate Tabs
|
||||
self.games_tab = GameTab(core, self, offline)
|
||||
self.addTab(self.games_tab, self.tr("Games"))
|
||||
|
||||
if not offline:
|
||||
updates = self.games_tab.default_widget.game_list.updates
|
||||
self.downloadTab = DownloadTab(core, updates, self)
|
||||
self.addTab(self.downloadTab, "Downloads" + (" (" + str(len(updates)) + ")" if len(updates) != 0 else ""))
|
||||
|
||||
self.cloud_saves = SyncSaves(core, self)
|
||||
self.addTab(self.cloud_saves, "Cloud Saves")
|
||||
|
||||
self.store = Shop(self.core)
|
||||
self.addTab(self.store, self.tr("Store (Beta)"))
|
||||
self.settings = SettingsTab(core, self)
|
||||
|
||||
# Space Tab
|
||||
self.addTab(QWidget(), "")
|
||||
self.setTabEnabled(disabled_tab, False)
|
||||
# Buttons
|
||||
store_button = TabButtonWidget(core, 'fa.shopping-cart', 'Epic Games Store')
|
||||
store_button.pressed.connect(lambda: webbrowser.open("https://www.epicgames.com/store"))
|
||||
self.tabBar().setTabButton(disabled_tab, self.tabBar().RightSide, store_button)
|
||||
|
||||
# Button
|
||||
self.account = QWidget()
|
||||
self.addTab(self.account, "")
|
||||
self.setTabEnabled(disabled_tab + 1, False)
|
||||
|
@ -105,7 +98,7 @@ class TabWidget(QTabWidget):
|
|||
self.games_tab.default_widget.game_list.game_exited.connect(self.game_finished)
|
||||
|
||||
# Open game list on click on Games tab button
|
||||
self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None)
|
||||
self.tabBarClicked.connect(self.mouse_clicked)
|
||||
self.setIconSize(QSize(25, 25))
|
||||
|
||||
# shortcuts
|
||||
|
@ -117,8 +110,15 @@ class TabWidget(QTabWidget):
|
|||
self.downloadTab.dl_status.connect(
|
||||
self.games_tab.default_widget.game_list.installing_widget.image_widget.set_status)
|
||||
|
||||
def mouse_clicked(self, tab_num):
|
||||
if tab_num == 0:
|
||||
self.games_tab.layout.setCurrentIndex(0)
|
||||
if tab_num == 3:
|
||||
self.store.load()
|
||||
|
||||
# TODO; maybe pass InstallOptionsModel only, not split arguments
|
||||
def install_game(self, options: InstallOptionsModel, update=False, silent=False):
|
||||
|
||||
install_dialog = InstallDialog(self.core,
|
||||
InstallQueueItemModel(options=options),
|
||||
update=update, silent=silent, parent=self)
|
||||
|
@ -165,8 +165,7 @@ class TabWidget(QTabWidget):
|
|||
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
|
||||
self.downloadTab.update_text.setVisible(len(self.downloadTab.update_widgets) == 0)
|
||||
|
||||
# Update gamelist and set text of Downlaods to "Downloads"
|
||||
|
||||
# Update gamelist and set text of Downloads to "Downloads"
|
||||
def dl_finished(self, update_list):
|
||||
if update_list[0]:
|
||||
self.games_tab.default_widget.game_list.update_list(update_list[1])
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import os
|
||||
import platform
|
||||
|
||||
|
@ -8,6 +9,7 @@ from qtawesome import icon
|
|||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from custom_legendary.models.game import Game, InstalledGame
|
||||
from rare import data_dir
|
||||
from rare.components.tabs.games.game_info.dlcs import DlcTab
|
||||
from rare.components.tabs.games.game_info.game_settings import GameSettings
|
||||
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
||||
|
@ -71,6 +73,18 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
self.setupUi(self)
|
||||
self.core = core
|
||||
|
||||
|
||||
self.ratings = {"platinum": self.tr("Platinum"),
|
||||
"gold": self.tr("Gold"),
|
||||
"silver": self.tr("Silver"),
|
||||
"bronze": self.tr("Bronze"),
|
||||
"fail": self.tr("Could not get grade"),
|
||||
"pending": self.tr("Not enough reports")}
|
||||
if os.path.exists(p := os.path.join(data_dir, "game_list.json")):
|
||||
self.grade_table = json.load(open(p))
|
||||
else:
|
||||
self.grade_table = {}
|
||||
|
||||
if platform.system() == "Windows":
|
||||
self.lbl_grade.setVisible(False)
|
||||
self.grade.setVisible(False)
|
||||
|
|
|
@ -6,6 +6,7 @@ from PyQt5.QtWidgets import QGroupBox, QHBoxLayout, QVBoxLayout, QScrollArea, QL
|
|||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from custom_legendary.models.game import Game
|
||||
from rare import data_dir
|
||||
from rare.utils.utils import download_image
|
||||
|
||||
|
||||
|
@ -82,7 +83,7 @@ class DLCWidget(QGroupBox):
|
|||
super(DLCWidget, self).__init__()
|
||||
self.main_layout = QHBoxLayout()
|
||||
self.dlc = dlc
|
||||
IMAGE_DIR = QSettings().value("img_dir", os.path.expanduser("~/.cache/rare/images"))
|
||||
IMAGE_DIR = QSettings().value("img_dir", os.path.join(data_dir, "images"))
|
||||
if installed:
|
||||
|
||||
if os.path.exists(os.path.join(IMAGE_DIR, dlc.app_name, "FinalArt.png")):
|
||||
|
|
|
@ -9,6 +9,7 @@ from qtawesome import icon
|
|||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from custom_legendary.models.game import Game
|
||||
from rare import data_dir
|
||||
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
||||
from rare.utils.extra_widgets import SideTabBar
|
||||
from rare.utils.json_formatter import QJsonModel
|
||||
|
@ -71,6 +72,7 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
|
|||
self.steam_worker.rating_signal.connect(self.grade.setText)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
|
||||
self.lbl_grade.setVisible(False)
|
||||
self.grade.setVisible(False)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer
|
|||
from PyQt5.QtWidgets import QScrollArea, QWidget, QLabel, QVBoxLayout, QStackedWidget
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare import data_dir
|
||||
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
|
||||
from rare.components.tabs.games.game_widgets.installed_icon_widget import GameWidgetInstalled
|
||||
from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget
|
||||
|
|
|
@ -8,7 +8,7 @@ from PyQt5.QtWidgets import QGroupBox, QMessageBox, QAction
|
|||
from custom_legendary.core import LegendaryCore
|
||||
from custom_legendary.models.game import InstalledGame
|
||||
from rare.components.dialogs.uninstall_dialog import UninstallDialog
|
||||
from rare.components.extra.Console import ConsoleWindow
|
||||
from rare.components.extra.console import ConsoleWindow
|
||||
from rare.utils import legendary_utils
|
||||
from rare.utils.utils import create_desktop_link
|
||||
|
||||
|
@ -150,8 +150,10 @@ class BaseInstalledWidget(QGroupBox):
|
|||
def stderr(self):
|
||||
stderr = bytes(self.proc.readAllStandardError()).decode("utf-8", errors="ignore")
|
||||
print(stderr)
|
||||
logger.error(stderr)
|
||||
# QMessageBox.warning(self, "Warning", stderr + "\nSee ~/.cache/rare/logs/")
|
||||
|
||||
|
||||
def finished(self, exit_code):
|
||||
logger.info("Game exited with exit code: " + str(exit_code))
|
||||
self.finish_signal.emit(self.game.app_name)
|
||||
|
|
|
@ -8,6 +8,7 @@ from logging import getLogger
|
|||
from PyQt5.QtCore import QSettings, Qt
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
from rare import cache_dir, data_dir
|
||||
from rare.components.tabs.settings.rpc_settings import RPCSettings
|
||||
from rare.ui.components.tabs.settings.rare import Ui_RareSettings
|
||||
from rare.utils import utils
|
||||
|
@ -35,13 +36,19 @@ class RareSettings(QWidget, Ui_RareSettings):
|
|||
(self.auto_sync_cloud, "auto_sync_cloud", True),
|
||||
(self.notification, "notification", True),
|
||||
(self.save_size, "save_size", False),
|
||||
(self.log_games, "show_console", False)
|
||||
(self.log_games, "show_console", False),
|
||||
# (self.image_cache, "cache_images", True)
|
||||
]
|
||||
|
||||
self.settings = QSettings()
|
||||
self.img_dir_path = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images/"), type=str)
|
||||
self.img_dir_path = self.settings.value("img_dir", os.path.join(data_dir, "images"), type=str)
|
||||
language = self.settings.value("language", get_lang(), type=str)
|
||||
self.logdir = os.path.expanduser("~/.cache/rare/logs")
|
||||
self.logdir = os.path.join(cache_dir, "logs")
|
||||
|
||||
|
||||
# Select Image directory
|
||||
# self.img_dir = PathEdit(self.img_dir_path, file_type=QFileDialog.DirectoryOnly, save_func=self.save_path)
|
||||
# self.img_dir_layout.addWidget(self.img_dir)
|
||||
|
||||
# Select lang
|
||||
self.lang_select.addItems([i[1] for i in languages])
|
||||
|
@ -85,6 +92,7 @@ class RareSettings(QWidget, Ui_RareSettings):
|
|||
)
|
||||
|
||||
if platform.system() == "Linux":
|
||||
|
||||
self.desktop_file = os.path.expanduser("~/Desktop/Rare.desktop")
|
||||
self.start_menu_link = os.path.expanduser("~/.local/share/applications/Rare.desktop")
|
||||
elif platform.system() == "Windows":
|
||||
|
@ -105,7 +113,7 @@ class RareSettings(QWidget, Ui_RareSettings):
|
|||
self.log_dir_open_button.clicked.connect(self.open_dir)
|
||||
self.log_dir_clean_button.clicked.connect(self.clean_logdir)
|
||||
|
||||
logdir = os.path.expanduser("~/.cache/rare/logs")
|
||||
logdir = os.path.join(cache_dir, "logs")
|
||||
# get size of logdir
|
||||
size = 0
|
||||
for i in os.listdir(logdir):
|
||||
|
@ -116,8 +124,8 @@ class RareSettings(QWidget, Ui_RareSettings):
|
|||
# self.log_dir_size_label.setVisible(False)
|
||||
|
||||
def clean_logdir(self):
|
||||
for i in os.listdir(os.path.expanduser("~/.cache/rare/logs")):
|
||||
os.remove(os.path.expanduser("~/.cache/rare/logs/") + i)
|
||||
for i in os.listdir(os.path.join(cache_dir, "logs")):
|
||||
os.remove(os.path.join(cache_dir, "logs/") + i)
|
||||
self.log_dir_size_label.setText("0KB")
|
||||
|
||||
def create_start_menu_link(self):
|
||||
|
|
61
rare/components/tabs/shop/__init__.py
Normal file
61
rare/components/tabs/shop/__init__.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
from PyQt5.QtWidgets import QStackedWidget, QTabWidget
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare import cache_dir
|
||||
from rare.components.tabs.shop.game_info import ShopGameInfo
|
||||
from rare.components.tabs.shop.search_results import SearchResults
|
||||
from rare.components.tabs.shop.shop_api_core import ShopApiCore
|
||||
from rare.components.tabs.shop.shop_widget import ShopWidget
|
||||
from rare.components.tabs.shop.wishlist import WishlistWidget, Wishlist
|
||||
|
||||
|
||||
class Shop(QStackedWidget):
|
||||
init = False
|
||||
|
||||
def __init__(self, core: LegendaryCore):
|
||||
super(Shop, self).__init__()
|
||||
self.core = core
|
||||
self.api_core = ShopApiCore(self.core.egs.session.headers["Authorization"])
|
||||
|
||||
self.shop = ShopWidget(cache_dir, core, self.api_core)
|
||||
self.wishlist_widget = Wishlist(self.api_core)
|
||||
|
||||
self.store_tabs = QTabWidget()
|
||||
self.store_tabs.addTab(self.shop, self.tr("Games"))
|
||||
self.store_tabs.addTab(self.wishlist_widget, self.tr("Wishlist"))
|
||||
# self.store_tabs.addTab(self.browse_games, self.tr("Browse"))
|
||||
|
||||
self.addWidget(self.store_tabs)
|
||||
|
||||
self.search_results = SearchResults(self.api_core)
|
||||
self.addWidget(self.search_results)
|
||||
self.search_results.show_info.connect(self.show_game_info)
|
||||
|
||||
self.info = ShopGameInfo([i.asset_info.namespace for i in self.core.get_game_list(True)], self.api_core)
|
||||
self.addWidget(self.info)
|
||||
self.info.back_button.clicked.connect(lambda: self.setCurrentIndex(0))
|
||||
|
||||
self.search_results.back_button.clicked.connect(lambda: self.setCurrentIndex(0))
|
||||
self.shop.show_info.connect(self.show_search_results)
|
||||
|
||||
self.wishlist_widget.show_game_info.connect(self.show_game_info)
|
||||
self.shop.show_game.connect(self.show_game_info)
|
||||
self.api_core.update_wishlist.connect(self.update_wishlist)
|
||||
self.wishlist_widget.update_wishlist_signal.connect(self.update_wishlist)
|
||||
|
||||
def update_wishlist(self):
|
||||
self.shop.update_wishlist()
|
||||
|
||||
def load(self):
|
||||
if not self.init:
|
||||
self.init = True
|
||||
self.shop.load()
|
||||
self.wishlist_widget.update_wishlist()
|
||||
|
||||
def show_game_info(self, data):
|
||||
self.info.update_game(data)
|
||||
self.setCurrentIndex(2)
|
||||
|
||||
def show_search_results(self, text: str):
|
||||
self.search_results.load_results(text)
|
||||
self.setCurrentIndex(1)
|
110
rare/components/tabs/shop/constants.py
Normal file
110
rare/components/tabs/shop/constants.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
from PyQt5.QtCore import QObject
|
||||
|
||||
|
||||
# Class to use QObject.tr()
|
||||
class Constants(QObject):
|
||||
def __init__(self):
|
||||
super(Constants, self).__init__()
|
||||
self.categories = sorted([
|
||||
(self.tr("Action"), "1216"),
|
||||
(self.tr("Adventure"), "1117"),
|
||||
(self.tr("Puzzle"), "1298"),
|
||||
(self.tr("Open world"), "1307"),
|
||||
(self.tr("Racing"), "1212"),
|
||||
(self.tr("RPG"), "1367"),
|
||||
(self.tr("Shooter"), "1210"),
|
||||
(self.tr("Strategy"), "1115"),
|
||||
(self.tr("Survival"), "1080"),
|
||||
(self.tr("First Person"), "1294"),
|
||||
(self.tr("Indie"), "1263"),
|
||||
(self.tr("Simulation"), "1393"),
|
||||
(self.tr("Sport"), "1283")
|
||||
], key=lambda x: x[0])
|
||||
|
||||
self.platforms = [
|
||||
("MacOS", "9548"),
|
||||
("Windows", "9547"),
|
||||
]
|
||||
self.others = [
|
||||
(self.tr("Single player"), "1370"),
|
||||
(self.tr("Multiplayer"), "1203"),
|
||||
(self.tr("Controller"), "9549"),
|
||||
(self.tr("Co-op"), "1264"),
|
||||
]
|
||||
|
||||
self.types = [
|
||||
(self.tr("Editor"), "editors"),
|
||||
(self.tr("Game"), "games/edition/base"),
|
||||
(self.tr("Bundle"), "bundles/games"),
|
||||
(self.tr("Add-on"), "addons"),
|
||||
(self.tr("Apps"), "software/edition/base")
|
||||
]
|
||||
|
||||
|
||||
game_query = "query searchStoreQuery($allowCountries: String, $category: String, $count: Int, $country: String!, " \
|
||||
"$keywords: String, $locale: String, $namespace: String, $withMapping: Boolean = false, $itemNs: String, " \
|
||||
"$sortBy: String, $sortDir: String, $start: Int, $tag: String, $releaseDate: String, $withPrice: Boolean " \
|
||||
"= false, $withPromotions: Boolean = false, $priceRange: String, $freeGame: Boolean, $onSale: Boolean, " \
|
||||
"$effectiveDate: String) {\n Catalog {\n searchStore(\n allowCountries: $allowCountries\n " \
|
||||
"category: $category\n count: $count\n country: $country\n keywords: $keywords\n " \
|
||||
"locale: $locale\n namespace: $namespace\n itemNs: $itemNs\n sortBy: $sortBy\n " \
|
||||
"sortDir: $sortDir\n releaseDate: $releaseDate\n start: $start\n tag: $tag\n " \
|
||||
"priceRange: $priceRange\n freeGame: $freeGame\n onSale: $onSale\n effectiveDate: " \
|
||||
"$effectiveDate\n ) {\n elements {\n title\n id\n namespace\n " \
|
||||
"description\n effectiveDate\n keyImages {\n type\n url\n }\n " \
|
||||
" currentPrice\n seller {\n id\n name\n }\n productSlug\n " \
|
||||
" urlSlug\n url\n tags {\n id\n }\n items {\n id\n " \
|
||||
" namespace\n }\n customAttributes {\n key\n value\n }\n " \
|
||||
"categories {\n path\n }\n catalogNs @include(if: $withMapping) {\n " \
|
||||
"mappings(pageType: \"productHome\") {\n pageSlug\n pageType\n }\n " \
|
||||
"}\n offerMappings @include(if: $withMapping) {\n pageSlug\n pageType\n " \
|
||||
"}\n price(country: $country) @include(if: $withPrice) {\n totalPrice {\n " \
|
||||
"discountPrice\n originalPrice\n voucherDiscount\n discount\n " \
|
||||
" currencyCode\n currencyInfo {\n decimals\n }\n fmtPrice(" \
|
||||
"locale: $locale) {\n originalPrice\n discountPrice\n " \
|
||||
"intermediatePrice\n }\n }\n lineOffers {\n appliedRules {\n " \
|
||||
" id\n endDate\n discountSetting {\n discountType\n " \
|
||||
" }\n }\n }\n }\n promotions(category: $category) @include(if: " \
|
||||
"$withPromotions) {\n promotionalOffers {\n promotionalOffers {\n " \
|
||||
"startDate\n endDate\n discountSetting {\n discountType\n " \
|
||||
" discountPercentage\n }\n }\n }\n " \
|
||||
"upcomingPromotionalOffers {\n promotionalOffers {\n startDate\n " \
|
||||
"endDate\n discountSetting {\n discountType\n " \
|
||||
"discountPercentage\n }\n }\n }\n }\n }\n paging {\n " \
|
||||
" count\n total\n }\n }\n }\n}\n "
|
||||
|
||||
search_query = "query searchStoreQuery($allowCountries: String, $category: String, $count: Int, $country: String!, " \
|
||||
"$keywords: String, $locale: String, $namespace: String, $withMapping: Boolean = false, $itemNs: String, " \
|
||||
"$sortBy: String, $sortDir: String, $start: Int, $tag: String, $releaseDate: String, $withPrice: Boolean = " \
|
||||
"false, $withPromotions: Boolean = false, $priceRange: String, $freeGame: Boolean, $onSale: Boolean, " \
|
||||
"$effectiveDate: String) {\n Catalog {\n searchStore(\n allowCountries: $allowCountries\n " \
|
||||
"category: $category\n count: $count\n country: $country\n keywords: $keywords\n locale: " \
|
||||
"$locale\n namespace: $namespace\n itemNs: $itemNs\n sortBy: $sortBy\n sortDir: " \
|
||||
"$sortDir\n releaseDate: $releaseDate\n start: $start\n tag: $tag\n priceRange: " \
|
||||
"$priceRange\n freeGame: $freeGame\n onSale: $onSale\n effectiveDate: $effectiveDate\n ) {" \
|
||||
"\n elements {\n title\n id\n namespace\n description\n " \
|
||||
"effectiveDate\n keyImages {\n type\n url\n }\n currentPrice\n " \
|
||||
"seller {\n id\n name\n }\n productSlug\n urlSlug\n url\n " \
|
||||
" tags {\n id\n }\n items {\n id\n namespace\n }\n " \
|
||||
"customAttributes {\n key\n value\n }\n categories {\n path\n " \
|
||||
"}\n catalogNs @include(if: $withMapping) {\n mappings(pageType: \"productHome\") {\n " \
|
||||
" pageSlug\n pageType\n }\n }\n offerMappings @include(if: $withMapping) " \
|
||||
"{\n pageSlug\n pageType\n }\n price(country: $country) @include(if: " \
|
||||
"$withPrice) {\n totalPrice {\n discountPrice\n originalPrice\n " \
|
||||
"voucherDiscount\n discount\n currencyCode\n currencyInfo {\n " \
|
||||
"decimals\n }\n fmtPrice(locale: $locale) {\n originalPrice\n " \
|
||||
"discountPrice\n intermediatePrice\n }\n }\n lineOffers {\n " \
|
||||
" appliedRules {\n id\n endDate\n discountSetting {\n " \
|
||||
"discountType\n }\n }\n }\n }\n promotions(category: " \
|
||||
"$category) @include(if: $withPromotions) {\n promotionalOffers {\n promotionalOffers {\n " \
|
||||
" startDate\n endDate\n discountSetting {\n " \
|
||||
"discountType\n discountPercentage\n }\n }\n }\n " \
|
||||
"upcomingPromotionalOffers {\n promotionalOffers {\n startDate\n " \
|
||||
"endDate\n discountSetting {\n discountType\n discountPercentage\n " \
|
||||
" }\n }\n }\n }\n }\n paging {\n count\n " \
|
||||
"total\n }\n }\n }\n}\n "
|
||||
|
||||
wishlist_query = "\n query wishlistQuery($country:String!, $locale:String) {\n Wishlist {\n wishlistItems {\n elements {\n id\n order\n created\n offerId\n updated\n namespace\n \n offer {\n productSlug\n urlSlug\n title\n id\n namespace\n offerType\n expiryDate\n status\n isCodeRedemptionOnly\n description\n effectiveDate\n keyImages {\n type\n url\n }\n seller {\n id\n name\n }\n productSlug\n urlSlug\n items {\n id\n namespace\n }\n customAttributes {\n key\n value\n }\n catalogNs {\n mappings(pageType: \"productHome\") {\n pageSlug\n pageType\n }\n }\n offerMappings {\n pageSlug\n pageType\n }\n categories {\n path\n }\n price(country: $country) {\n totalPrice {\n discountPrice\n originalPrice\n voucherDiscount\n discount\n fmtPrice(locale: $locale) {\n originalPrice\n discountPrice\n intermediatePrice\n }\n currencyCode\n currencyInfo {\n decimals\n symbol\n }\n }\n lineOffers {\n appliedRules {\n id\n endDate\n }\n }\n }\n }\n\n }\n }\n }\n }\n"
|
||||
add_to_wishlist_query = "\n mutation removeFromWishlistMutation($namespace: String!, $offerId: String!, $operation: RemoveOperation!) {\n Wishlist {\n removeFromWishlist(namespace: $namespace, offerId: $offerId, operation: $operation) {\n success\n }\n }\n }\n"
|
||||
remove_from_wishlist_query = "\n mutation removeFromWishlistMutation($namespace: String!, $offerId: String!, $operation: RemoveOperation!) {\n Wishlist {\n removeFromWishlist(namespace: $namespace, offerId: $offerId, operation: $operation) {\n success\n }\n }\n }\n"
|
||||
coupon_query = "\n query getCoupons($currencyCountry: String!, $identityId: String!, $locale: String) {\n CodeRedemption {\n coupons(currencyCountry: $currencyCountry, identityId: $identityId, includeSalesEventInfo: true) {\n code\n codeStatus\n codeType\n consumptionMetadata {\n amountDisplay {\n amount\n currency\n placement\n symbol\n }\n minSalesPriceDisplay {\n amount\n currency\n placement\n symbol\n }\n }\n endDate\n namespace\n salesEvent(locale: $locale) {\n eventName\n eventSlug\n voucherImages {\n type\n url\n }\n voucherLink\n }\n startDate\n }\n }\n }\n"
|
189
rare/components/tabs/shop/game_info.py
Normal file
189
rare/components/tabs/shop/game_info.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
import logging
|
||||
import webbrowser
|
||||
|
||||
from PyQt5.QtGui import QPixmap, QFont
|
||||
from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QHBoxLayout
|
||||
from qtawesome import icon
|
||||
|
||||
from rare.components.tabs.shop.shop_models import ShopGame
|
||||
from rare.ui.components.tabs.store.shop_game_info import Ui_shop_info
|
||||
from rare.utils.extra_widgets import WaitingSpinner, ImageLabel
|
||||
from rare.utils.utils import get_lang
|
||||
|
||||
logger = logging.getLogger("ShopInfo")
|
||||
|
||||
|
||||
class ShopGameInfo(QWidget, Ui_shop_info):
|
||||
game: ShopGame
|
||||
data: dict
|
||||
|
||||
# TODO Design
|
||||
def __init__(self, installed_titles: list, api_core):
|
||||
super(ShopGameInfo, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.api_core = api_core
|
||||
self.installed = installed_titles
|
||||
self.open_store_button.clicked.connect(self.button_clicked)
|
||||
self.image = ImageLabel()
|
||||
self.image_stack.addWidget(self.image)
|
||||
self.image_stack.addWidget(WaitingSpinner())
|
||||
|
||||
self.locale = get_lang()
|
||||
self.wishlist_button.clicked.connect(self.add_to_wishlist)
|
||||
self.in_wishlist = False
|
||||
self.wishlist = []
|
||||
|
||||
def handle_wishlist_update(self, data):
|
||||
self.wishlist = [i["offer"]["title"] for i in data]
|
||||
if self.title_str in self.wishlist:
|
||||
self.in_wishlist = True
|
||||
self.wishlist_button.setVisible(True)
|
||||
self.wishlist_button.setText(self.tr("Remove from Wishlist"))
|
||||
else:
|
||||
self.in_wishlist = False
|
||||
self.wishlist_button.setVisible(False)
|
||||
|
||||
def update_game(self, data: dict):
|
||||
self.image_stack.setCurrentIndex(1)
|
||||
self.title.setText(data["title"])
|
||||
self.title_str = data["title"]
|
||||
self.api_core.get_wishlist(self.handle_wishlist_update)
|
||||
for i in reversed(range(self.req_group_box.layout().count())):
|
||||
self.req_group_box.layout().itemAt(i).widget().setParent(None)
|
||||
slug = data["productSlug"]
|
||||
if "/home" in slug:
|
||||
slug = slug.replace("/home", "")
|
||||
self.slug = slug
|
||||
|
||||
if data["namespace"] in self.installed:
|
||||
self.open_store_button.setText(self.tr("Show Game on Epic Page"))
|
||||
self.owned_label.setVisible(True)
|
||||
else:
|
||||
self.open_store_button.setText(self.tr("Buy Game in Epic Games Store"))
|
||||
self.owned_label.setVisible(False)
|
||||
|
||||
self.dev.setText(self.tr("Loading"))
|
||||
self.price.setText(self.tr("Loading"))
|
||||
# self.title.setText(self.tr("Loading"))
|
||||
self.image.setPixmap(QPixmap())
|
||||
self.data = data
|
||||
is_bundle = False
|
||||
for i in data["categories"]:
|
||||
if "bundles" in i.get("path", ""):
|
||||
is_bundle = True
|
||||
|
||||
# init API request
|
||||
self.api_core.get_game(slug, is_bundle, self.data_received)
|
||||
|
||||
def add_to_wishlist(self):
|
||||
if not self.in_wishlist:
|
||||
return
|
||||
# self.api_core.add_to_wishlist(self.game.namespace, self.game.offer_id,
|
||||
# lambda success: self.wishlist_button.setText(self.tr("Remove from wishlist"))
|
||||
# if success else self.wishlist_button.setText("Something goes wrong"))
|
||||
else:
|
||||
self.api_core.remove_from_wishlist(self.game.namespace, self.game.offer_id,
|
||||
lambda success: self.wishlist_button.setVisible(False)
|
||||
if success else self.wishlist_button.setText("Something goes wrong"))
|
||||
|
||||
def data_received(self, game):
|
||||
self.game = ShopGame.from_json(game, self.data)
|
||||
self.title.setText(self.game.title)
|
||||
self.price.setFont(QFont())
|
||||
if self.game.price == "0" or self.game.price == 0:
|
||||
self.price.setText(self.tr("Free"))
|
||||
else:
|
||||
self.price.setText(self.game.price)
|
||||
if self.game.price != self.game.discount_price:
|
||||
font = QFont()
|
||||
font.setStrikeOut(True)
|
||||
self.price.setFont(font)
|
||||
self.discount_price.setText(
|
||||
self.game.discount_price if self.game.discount_price != "0" else self.tr("Free"))
|
||||
self.discount_price.setVisible(True)
|
||||
else:
|
||||
self.discount_price.setVisible(False)
|
||||
|
||||
bold_font = QFont()
|
||||
bold_font.setBold(True)
|
||||
min_label = QLabel(self.tr("Minimum"))
|
||||
min_label.setFont(bold_font)
|
||||
rec_label = QLabel(self.tr("Recommend"))
|
||||
rec_label.setFont(bold_font)
|
||||
|
||||
if self.game.reqs:
|
||||
self.req_group_box.layout().addWidget(min_label, 0, 1)
|
||||
self.req_group_box.layout().addWidget(rec_label, 0, 2)
|
||||
for i, (key, value) in enumerate(self.game.reqs.get("Windows", {}).items()):
|
||||
self.req_group_box.layout().addWidget(QLabel(key), i + 1, 0)
|
||||
min_label = QLabel(value[0])
|
||||
min_label.setWordWrap(True)
|
||||
self.req_group_box.layout().addWidget(min_label, i + 1, 1)
|
||||
rec_label = QLabel(value[1])
|
||||
rec_label.setWordWrap(True)
|
||||
self.req_group_box.layout().addWidget(rec_label, i + 1, 2)
|
||||
else:
|
||||
self.req_group_box.layout().addWidget(QLabel(self.tr("Could not get requirements")))
|
||||
|
||||
if self.game.image_urls.front_tall:
|
||||
img = self.game.image_urls.front_tall
|
||||
elif self.game.image_urls.offer_image_tall:
|
||||
img = self.game.image_urls.offer_image_tall
|
||||
else:
|
||||
img = ""
|
||||
|
||||
self.image.update_image(img, self.game.title, (240, 320))
|
||||
|
||||
self.image_stack.setCurrentIndex(0)
|
||||
try:
|
||||
if isinstance(self.game.developer, list):
|
||||
self.dev.setText(", ".join(self.game.developer))
|
||||
else:
|
||||
self.dev.setText(self.game.developer)
|
||||
except KeyError:
|
||||
pass
|
||||
self.tags.setText(", ".join(self.game.tags))
|
||||
|
||||
# clear Layout
|
||||
QWidget().setLayout(self.social_link_gb.layout())
|
||||
self.social_link_gb.setLayout(QHBoxLayout())
|
||||
|
||||
self.social_link_gb.layout().addStretch(1)
|
||||
link_count = 0
|
||||
for name, url in self.game.links:
|
||||
|
||||
if name.lower() == "homepage":
|
||||
icn = icon("mdi.web", scale_factor=1.5)
|
||||
else:
|
||||
try:
|
||||
icn = icon("mdi." + name.lower(), scale_factor=1.5)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
continue
|
||||
|
||||
button = SocialButton(icn, url)
|
||||
self.social_link_gb.layout().addWidget(button)
|
||||
link_count += 1
|
||||
self.social_link_gb.layout().addStretch(1)
|
||||
|
||||
if link_count == 0:
|
||||
self.social_link_gb.setVisible(False)
|
||||
else:
|
||||
self.social_link_gb.setVisible(True)
|
||||
self.social_link_gb.layout().addStretch(1)
|
||||
|
||||
def add_wishlist_items(self, wishlist):
|
||||
wishlist = wishlist["data"]["Wishlist"]["wishlistItems"]["elements"]
|
||||
for game in wishlist:
|
||||
self.wishlist.append(game["offer"]["title"])
|
||||
|
||||
def button_clicked(self):
|
||||
webbrowser.open("https://www.epicgames.com/store/de/p/" + self.slug)
|
||||
|
||||
|
||||
class SocialButton(QPushButton):
|
||||
def __init__(self, icn, url):
|
||||
super(SocialButton, self).__init__(icn, "")
|
||||
self.url = url
|
||||
self.clicked.connect(lambda: webbrowser.open(url))
|
||||
self.setToolTip(url)
|
121
rare/components/tabs/shop/game_widgets.py
Normal file
121
rare/components/tabs/shop/game_widgets.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
import logging
|
||||
|
||||
from PyQt5 import QtGui
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout
|
||||
from qtawesome import icon
|
||||
|
||||
from rare.components.tabs.shop.shop_models import ImageUrlModel
|
||||
from rare.ui.components.tabs.store.wishlist_widget import Ui_WishlistWidget
|
||||
from rare.utils.extra_widgets import ImageLabel
|
||||
|
||||
logger = logging.getLogger("GameWidgets")
|
||||
|
||||
|
||||
class GameWidget(QWidget):
|
||||
show_info = pyqtSignal(dict)
|
||||
|
||||
def __init__(self, path, json_info=None, width=300):
|
||||
super(GameWidget, self).__init__()
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.width = width
|
||||
self.path = path
|
||||
if json_info:
|
||||
self.init_ui(json_info)
|
||||
|
||||
def init_ui(self, json_info):
|
||||
self.layout = QVBoxLayout()
|
||||
self.image = ImageLabel()
|
||||
self.layout.addWidget(self.image)
|
||||
mini_layout = QHBoxLayout()
|
||||
self.layout.addLayout(mini_layout)
|
||||
|
||||
self.title_label = QLabel(json_info.get("title"))
|
||||
self.title_label.setWordWrap(True)
|
||||
mini_layout.addWidget(self.title_label)
|
||||
mini_layout.addStretch(1)
|
||||
|
||||
price = json_info['price']['totalPrice']['fmtPrice']['originalPrice']
|
||||
discount_price = json_info['price']['totalPrice']['fmtPrice']['discountPrice']
|
||||
price_label = QLabel(price)
|
||||
if price != discount_price:
|
||||
font = QFont()
|
||||
font.setStrikeOut(True)
|
||||
price_label.setFont(font)
|
||||
mini_layout.addWidget(QLabel(discount_price if discount_price != "0" else self.tr("Free")))
|
||||
mini_layout.addWidget(price_label)
|
||||
else:
|
||||
mini_layout.addWidget(price_label)
|
||||
|
||||
for c in r'<>?":|\/*':
|
||||
json_info["title"] = json_info["title"].replace(c, "")
|
||||
|
||||
self.json_info = json_info
|
||||
self.slug = json_info["productSlug"]
|
||||
|
||||
self.title = json_info["title"]
|
||||
for img in json_info["keyImages"]:
|
||||
if img["type"] in ["DieselStoreFrontWide", "OfferImageWide", "VaultClosed"]:
|
||||
if img["type"] == "VaultClosed" and self.title != "Mystery Game":
|
||||
continue
|
||||
self.image.update_image(img["url"], json_info["title"], (self.width, int(self.width * 9 / 16)))
|
||||
break
|
||||
else:
|
||||
logger.info(", ".join([img["type"] for img in json_info["keyImages"]]))
|
||||
# print(json_info["keyImages"])
|
||||
|
||||
self.setLayout(self.layout)
|
||||
|
||||
def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
|
||||
self.show_info.emit(self.json_info)
|
||||
|
||||
|
||||
class WishlistWidget(QWidget, Ui_WishlistWidget):
|
||||
open_game = pyqtSignal(dict)
|
||||
delete_from_wishlist = pyqtSignal(dict)
|
||||
|
||||
def __init__(self, game: dict):
|
||||
super(WishlistWidget, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.game = game
|
||||
self.title_label.setText(game.get("title"))
|
||||
for attr in game["customAttributes"]:
|
||||
if attr["key"] == "developerName":
|
||||
self.developer.setText(attr["value"])
|
||||
break
|
||||
else:
|
||||
self.developer.setText(game["seller"]["name"])
|
||||
original_price = game['price']['totalPrice']['fmtPrice']['originalPrice']
|
||||
discount_price = game['price']['totalPrice']['fmtPrice']['discountPrice']
|
||||
|
||||
self.price.setText(original_price if original_price != "0" else self.tr("Free"))
|
||||
# if discount
|
||||
if original_price != discount_price:
|
||||
self.discount = True
|
||||
font = QFont()
|
||||
font.setStrikeOut(True)
|
||||
self.price.setFont(font)
|
||||
self.discount_price.setText(discount_price)
|
||||
else:
|
||||
self.discount = False
|
||||
self.discount_price.setVisible(False)
|
||||
|
||||
self.image = ImageLabel()
|
||||
self.layout().insertWidget(0, self.image)
|
||||
image_model = ImageUrlModel.from_json(game["keyImages"])
|
||||
url = image_model.front_wide
|
||||
if not url:
|
||||
url = image_model.offer_image_wide
|
||||
self.image.update_image(url, game.get("title"), (240, 135))
|
||||
self.delete_button.setIcon(icon("mdi.delete", color="white"))
|
||||
self.delete_button.clicked.connect(lambda: self.delete_from_wishlist.emit(self.game))
|
||||
|
||||
def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
|
||||
# left button
|
||||
if e.button() == 1:
|
||||
self.open_game.emit(self.game)
|
||||
# right
|
||||
elif e.button() == 2:
|
||||
pass # self.showMenu(e)
|
102
rare/components/tabs/shop/search_results.py
Normal file
102
rare/components/tabs/shop/search_results.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
from PyQt5 import QtGui
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QScrollArea, QGroupBox, QPushButton, \
|
||||
QStackedWidget
|
||||
|
||||
from rare.utils.extra_widgets import ImageLabel, FlowLayout, WaitingSpinner
|
||||
|
||||
|
||||
class SearchResults(QStackedWidget):
|
||||
show_info = pyqtSignal(dict)
|
||||
|
||||
def __init__(self, api_core):
|
||||
super(SearchResults, self).__init__()
|
||||
self.search_result_widget = QWidget()
|
||||
self.api_core = api_core
|
||||
self.addWidget(self.search_result_widget)
|
||||
self.main_layout = QVBoxLayout()
|
||||
self.back_button = QPushButton(self.tr("Back"))
|
||||
self.main_layout.addWidget(self.back_button)
|
||||
self.main_layout.addWidget(self.back_button)
|
||||
self.result_area = QScrollArea()
|
||||
self.widget = QWidget()
|
||||
self.result_area.setWidgetResizable(True)
|
||||
self.main_layout.addWidget(self.result_area)
|
||||
self.result_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
|
||||
self.result_area.setWidget(self.widget)
|
||||
self.layout = FlowLayout()
|
||||
self.widget.setLayout(self.layout)
|
||||
|
||||
self.search_result_widget.setLayout(self.main_layout)
|
||||
|
||||
self.addWidget(WaitingSpinner())
|
||||
self.setCurrentIndex(1)
|
||||
|
||||
def load_results(self, text: str):
|
||||
self.setCurrentIndex(1)
|
||||
if text != "":
|
||||
self.api_core.search_game(text, self.show_results)
|
||||
|
||||
def show_results(self, results: dict):
|
||||
QVBoxLayout().addWidget(self.widget)
|
||||
self.widget = QWidget()
|
||||
self.layout = FlowLayout()
|
||||
if not results:
|
||||
self.layout.addWidget(QLabel(self.tr("No results found")))
|
||||
else:
|
||||
for res in results:
|
||||
w = _SearchResultItem(res)
|
||||
w.show_info.connect(self.show_info.emit)
|
||||
self.layout.addWidget(w)
|
||||
self.widget.setLayout(self.layout)
|
||||
self.result_area.setWidget(self.widget)
|
||||
self.setCurrentIndex(0)
|
||||
|
||||
|
||||
class _SearchResultItem(QGroupBox):
|
||||
res: dict
|
||||
show_info = pyqtSignal(dict)
|
||||
|
||||
def __init__(self, result: dict):
|
||||
super(_SearchResultItem, self).__init__()
|
||||
self.layout = QVBoxLayout()
|
||||
self.image = ImageLabel()
|
||||
for img in result["keyImages"]:
|
||||
if img["type"] == "DieselStoreFrontTall":
|
||||
width = 240
|
||||
self.image.update_image(img["url"], result["title"], (width, 360))
|
||||
break
|
||||
else:
|
||||
print("No image found")
|
||||
self.layout.addWidget(self.image)
|
||||
|
||||
self.res = result
|
||||
self.title = QLabel(self.res["title"])
|
||||
title_font = QFont()
|
||||
title_font.setPixelSize(15)
|
||||
self.title.setFont(title_font)
|
||||
self.title.setWordWrap(True)
|
||||
self.layout.addWidget(self.title)
|
||||
price = result['price']['totalPrice']['fmtPrice']['originalPrice']
|
||||
discount_price = result['price']['totalPrice']['fmtPrice']['discountPrice']
|
||||
price_layout = QHBoxLayout()
|
||||
price_label = QLabel(price if price != "0" else self.tr("Free"))
|
||||
price_layout.addWidget(price_label)
|
||||
|
||||
if price != discount_price:
|
||||
font = QFont()
|
||||
font.setStrikeOut(True)
|
||||
price_label.setFont(font)
|
||||
price_layout.addWidget(QLabel(discount_price))
|
||||
# self.discount_price = QLabel(f"{self.tr('Discount price: ')}{discount_price}")
|
||||
self.layout.addLayout(price_layout)
|
||||
|
||||
self.setLayout(self.layout)
|
||||
|
||||
self.setFixedWidth(260)
|
||||
|
||||
def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
|
||||
if a0.button() == 1:
|
||||
self.show_info.emit(self.res)
|
137
rare/components/tabs/shop/shop_api_core.py
Normal file
137
rare/components/tabs/shop/shop_api_core.py
Normal file
|
@ -0,0 +1,137 @@
|
|||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
from rare.components.tabs.shop.constants import wishlist_query, search_query, game_query, add_to_wishlist_query, \
|
||||
remove_from_wishlist_query
|
||||
from rare.components.tabs.shop.shop_models import BrowseModel
|
||||
from rare.utils.qt_requests import QtRequestManager
|
||||
from rare.utils.utils import get_lang
|
||||
|
||||
logger = getLogger("ShopAPICore")
|
||||
graphql_url = "https://www.epicgames.com/graphql"
|
||||
|
||||
|
||||
class ShopApiCore(QObject):
|
||||
update_wishlist = pyqtSignal()
|
||||
|
||||
def __init__(self, auth_token):
|
||||
super(ShopApiCore, self).__init__()
|
||||
self.token = auth_token
|
||||
self.manager = QtRequestManager()
|
||||
self.auth_manager = QtRequestManager(authorization_token=auth_token)
|
||||
self.locale = get_lang()
|
||||
|
||||
self.browse_active = False
|
||||
self.next_browse_request = tuple(())
|
||||
|
||||
def get_free_games(self, handle_func: callable):
|
||||
url = "https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions"
|
||||
|
||||
self.manager.get(url, lambda data: self._handle_free_games(data, handle_func))
|
||||
|
||||
def _handle_free_games(self, data, handle_func):
|
||||
try:
|
||||
handle_func(data["data"]["Catalog"]["searchStore"]["elements"])
|
||||
except KeyError as e:
|
||||
logger.error(str(e))
|
||||
|
||||
def get_wishlist(self, handle_func):
|
||||
self.auth_manager.post(graphql_url, {
|
||||
"query": wishlist_query,
|
||||
"variables": {
|
||||
"country": self.locale.upper(),
|
||||
"locale": self.locale
|
||||
}
|
||||
}, lambda data: self._handle_wishlist(data, handle_func))
|
||||
|
||||
def _handle_wishlist(self, data, handle_func):
|
||||
handle_func(data["data"]["Wishlist"]["wishlistItems"]["elements"])
|
||||
|
||||
def search_game(self, name, handle_func):
|
||||
payload = {
|
||||
"query": search_query,
|
||||
"variables": {"category": "games/edition/base|bundles/games|editors|software/edition/base", "count": 1,
|
||||
"country": "DE", "keywords": name, "locale": self.locale, "sortDir": "DESC",
|
||||
"allowCountries": self.locale.upper(),
|
||||
"start": 0, "tag": "", "withMapping": False, "withPrice": True}
|
||||
}
|
||||
|
||||
self.manager.post(graphql_url, payload, lambda data: self._handle_search(data, handle_func))
|
||||
|
||||
def _handle_search(self, data, handle_func):
|
||||
handle_func(data["data"]["Catalog"]["searchStore"]["elements"])
|
||||
|
||||
def browse_games(self, browse_model: BrowseModel, handle_func):
|
||||
if self.browse_active:
|
||||
self.next_browse_request = (browse_model, handle_func)
|
||||
return
|
||||
self.browse_active = True
|
||||
payload = {
|
||||
"variables": browse_model.__dict__,
|
||||
"query": game_query
|
||||
}
|
||||
|
||||
self.auth_manager.post(graphql_url, payload, lambda data: self._handle_browse_games(data, handle_func))
|
||||
|
||||
def _handle_browse_games(self, data, handle_func):
|
||||
self.browse_active = False
|
||||
if not self.next_browse_request:
|
||||
handle_func(data["data"]["Catalog"]["searchStore"]["elements"])
|
||||
else:
|
||||
self.browse_games(*self.next_browse_request)
|
||||
self.next_browse_request = tuple(())
|
||||
|
||||
def get_game(self, slug: str, is_bundle: bool, handle_func):
|
||||
url = f"https://store-content.ak.epicgames.com/api/{self.locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}"
|
||||
self.manager.get(url, lambda data: self._handle_get_game(data, handle_func))
|
||||
|
||||
def _handle_get_game(self, data, handle_func):
|
||||
handle_func(data)
|
||||
|
||||
def add_to_wishlist(self, namespace, offer_id, handle_func: callable):
|
||||
payload = {
|
||||
"variables": {
|
||||
"offerId": offer_id,
|
||||
"namespace": namespace,
|
||||
"country": self.locale.upper(),
|
||||
"locale": self.locale
|
||||
},
|
||||
"query": add_to_wishlist_query
|
||||
}
|
||||
self.auth_manager.post(graphql_url, payload, lambda data: self._handle_add_to_wishlist(data, handle_func))
|
||||
|
||||
def _handle_add_to_wishlist(self, data, handle_func):
|
||||
try:
|
||||
data = data["data"]["Wishlist"]["addToWishlist"]
|
||||
if data["success"]:
|
||||
handle_func(True)
|
||||
else:
|
||||
handle_func(False)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
handle_func(False)
|
||||
self.update_wishlist.emit()
|
||||
|
||||
def remove_from_wishlist(self, namespace, offer_id, handle_func: callable):
|
||||
payload = {
|
||||
"variables": {
|
||||
"offerId": offer_id,
|
||||
"namespace": namespace,
|
||||
"operation": "REMOVE"
|
||||
},
|
||||
"query": remove_from_wishlist_query
|
||||
}
|
||||
self.auth_manager.post(graphql_url, payload, lambda data: self._handle_remove_from_wishlist(data, handle_func))
|
||||
|
||||
def _handle_remove_from_wishlist(self, data, handle_func):
|
||||
try:
|
||||
data = data["data"]["Wishlist"]["removeFromWishlist"]
|
||||
if data["success"]:
|
||||
handle_func(True)
|
||||
else:
|
||||
handle_func(False)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
handle_func(False)
|
||||
self.update_wishlist.emit()
|
144
rare/components/tabs/shop/shop_models.py
Normal file
144
rare/components/tabs/shop/shop_models.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
import datetime
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
|
||||
from rare.utils.utils import get_lang
|
||||
|
||||
|
||||
class ImageUrlModel:
|
||||
def __init__(self, front_tall: str = "", offer_image_tall: str = "",
|
||||
thumbnail: str = "", front_wide: str = "", offer_image_wide: str = ""):
|
||||
self.front_tall = front_tall
|
||||
self.offer_image_tall = offer_image_tall
|
||||
self.thumbnail = thumbnail
|
||||
self.front_wide = front_wide
|
||||
self.offer_image_wide = offer_image_wide
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json_data: list):
|
||||
tmp = cls()
|
||||
for item in json_data:
|
||||
if item["type"] == "Thumbnail":
|
||||
tmp.thumbnail = item["url"]
|
||||
elif item["type"] == "DieselStoreFrontTall":
|
||||
tmp.front_tall = item["url"]
|
||||
elif item["type"] == "DieselStoreFrontWide":
|
||||
tmp.front_wide = item["url"]
|
||||
elif item["type"] == "OfferImageTall":
|
||||
tmp.offer_image_tall = item["url"]
|
||||
elif item["type"] == "OfferImageWide":
|
||||
tmp.offer_image_wide = item["url"]
|
||||
return tmp
|
||||
|
||||
|
||||
class ShopGame:
|
||||
# TODO: Copyrights etc
|
||||
def __init__(self, title: str = "", image_urls: ImageUrlModel = None, social_links: dict = None,
|
||||
langs: list = None, reqs: dict = None, publisher: str = "", developer: str = "",
|
||||
original_price: str = "", discount_price: str = "", tags: list = None, namespace: str = "",
|
||||
offer_id: str = ""):
|
||||
self.title = title
|
||||
self.image_urls = image_urls
|
||||
self.links = []
|
||||
if social_links:
|
||||
for item in social_links:
|
||||
if item.startswith("link"):
|
||||
self.links.append(tuple((item.replace("link", ""), social_links[item])))
|
||||
else:
|
||||
self.links = []
|
||||
self.languages = langs
|
||||
self.reqs = reqs
|
||||
self.publisher = publisher
|
||||
self.developer = developer
|
||||
self.price = original_price
|
||||
self.discount_price = discount_price
|
||||
self.tags = tags
|
||||
self.namespace = namespace
|
||||
self.offer_id = offer_id
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, api_data: dict, search_data: dict):
|
||||
if isinstance(api_data, list):
|
||||
for product in api_data:
|
||||
if product["_title"] == "home":
|
||||
api_data = product
|
||||
break
|
||||
if "pages" in api_data.keys():
|
||||
for page in api_data["pages"]:
|
||||
if page["_slug"] == "home":
|
||||
api_data = page
|
||||
break
|
||||
tmp = cls()
|
||||
tmp.title = search_data.get("title", "Fail")
|
||||
tmp.image_urls = ImageUrlModel.from_json(search_data["keyImages"])
|
||||
links = api_data["data"]["socialLinks"]
|
||||
tmp.links = []
|
||||
for item in links:
|
||||
if item.startswith("link"):
|
||||
tmp.links.append(tuple((item.replace("link", ""), links[item])))
|
||||
tmp.available_voice_langs = api_data["data"]["requirements"].get("languages", "Failed")
|
||||
tmp.reqs = {}
|
||||
for i, system in enumerate(api_data["data"]["requirements"].get("systems", [])):
|
||||
try:
|
||||
tmp.reqs[system["systemType"]] = {}
|
||||
except KeyError:
|
||||
continue
|
||||
for req in system["details"]:
|
||||
try:
|
||||
tmp.reqs[system["systemType"]][req["title"]] = (req["minimum"], req["recommended"])
|
||||
except KeyError:
|
||||
pass
|
||||
tmp.publisher = api_data["data"]["meta"].get("publisher", "")
|
||||
tmp.developer = api_data["data"]["meta"].get("developer", "")
|
||||
if not tmp.developer:
|
||||
for i in search_data["customAttributes"]:
|
||||
if i["key"] == "developerName":
|
||||
tmp.developer = i["value"]
|
||||
tmp.price = search_data['price']['totalPrice']['fmtPrice']['originalPrice']
|
||||
tmp.discount_price = search_data['price']['totalPrice']['fmtPrice']['discountPrice']
|
||||
tmp.tags = [i.replace("_", " ").capitalize() for i in api_data["data"]["meta"].get("tags", [])]
|
||||
tmp.namespace = search_data["namespace"]
|
||||
tmp.offer_id = search_data["id"]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
@dataclass
|
||||
class BrowseModel:
|
||||
category: str = "games/edition/base|bundles/games|editors|software/edition/base"
|
||||
count: int = 30
|
||||
locale: str = get_lang()
|
||||
keywords: str = ""
|
||||
sortDir: str = "DESC"
|
||||
start: int = 0
|
||||
tag: str = ""
|
||||
withMapping: bool = True
|
||||
withPrice: bool = True
|
||||
date: str = f"[,{datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%dT%X')}.{str(random.randint(0, 999)).zfill(3)}Z]"
|
||||
price: str = ""
|
||||
onSale: bool = False
|
||||
|
||||
@property
|
||||
def __dict__(self):
|
||||
payload = {"category": self.category,
|
||||
"count": self.count,
|
||||
"country": self.locale.upper(),
|
||||
"keywords": self.keywords,
|
||||
"locale": self.locale,
|
||||
"sortDir": self.sortDir,
|
||||
"allowCountries": self.locale.upper(),
|
||||
"start": self.start,
|
||||
"tag": self.tag,
|
||||
"withMapping": self.withMapping,
|
||||
"withPrice": self.withPrice,
|
||||
"releaseDate": self.date,
|
||||
"effectiveDate": self.date,
|
||||
}
|
||||
|
||||
if self.price == "free":
|
||||
payload["freeGame"] = True
|
||||
elif self.price.startswith("<price>"):
|
||||
payload["priceRange"] = self.price.replace("<price>", "")
|
||||
if self.onSale:
|
||||
payload["onSale"] = True
|
||||
return payload
|
275
rare/components/tabs/shop/shop_widget.py
Normal file
275
rare/components/tabs/shop/shop_widget.py
Normal file
|
@ -0,0 +1,275 @@
|
|||
import datetime
|
||||
import logging
|
||||
import random
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QWidget, QGroupBox, QScrollArea, QCheckBox, QVBoxLayout, QLabel
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare.components.tabs.shop import ShopApiCore
|
||||
from rare.components.tabs.shop.constants import Constants
|
||||
from rare.components.tabs.shop.game_widgets import GameWidget
|
||||
from rare.components.tabs.shop.shop_models import BrowseModel
|
||||
from rare.ui.components.tabs.store.store import Ui_ShopWidget
|
||||
from rare.utils.extra_widgets import WaitingSpinner, FlowLayout, ButtonLineEdit
|
||||
from rare.utils.utils import get_lang
|
||||
|
||||
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.locale = get_lang()
|
||||
self.update_games_allowed = True
|
||||
self.free_widget.setLayout(FlowLayout())
|
||||
self.free_games_now = QGroupBox(self.tr("Now Free"))
|
||||
self.free_games_now.setLayout(FlowLayout())
|
||||
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(FlowLayout())
|
||||
self.free_widget.layout().addWidget(self.coming_free_games)
|
||||
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)
|
||||
self.prepare_request()
|
||||
|
||||
def update_wishlist(self):
|
||||
self.api_core.get_wishlist(self.add_wishlist_items)
|
||||
|
||||
def add_wishlist_items(self, wishlist):
|
||||
QWidget().setLayout(self.discount_widget.layout())
|
||||
|
||||
self.discount_widget.setLayout(FlowLayout())
|
||||
discounts = 0
|
||||
for game in wishlist:
|
||||
if not game:
|
||||
continue
|
||||
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
|
||||
self.discounts_gb.setVisible(discounts > 0)
|
||||
self.discount_stack.setCurrentIndex(0)
|
||||
|
||||
def add_free_games(self, free_games):
|
||||
date = datetime.datetime.now()
|
||||
free_games_now = []
|
||||
coming_free_games = []
|
||||
for game in free_games:
|
||||
if game["title"] == "Mystery Game":
|
||||
coming_free_games.append(game)
|
||||
continue
|
||||
try:
|
||||
# parse datetime to check if game is next week or now
|
||||
try:
|
||||
end_date = datetime.datetime.strptime(
|
||||
game["promotions"]["upcomingPromotionalOffers"][0]["promotionalOffers"][0]["endDate"],
|
||||
'%Y-%m-%dT%H:%M:%S.%fZ')
|
||||
except Exception:
|
||||
try:
|
||||
end_date = datetime.datetime.strptime(
|
||||
game["promotions"]["promotionalOffers"][0]["promotionalOffers"][0]["endDate"],
|
||||
'%Y-%m-%dT%H:%M:%S.%fZ')
|
||||
except Exception:
|
||||
continue
|
||||
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:
|
||||
print(e)
|
||||
logger.warning(str(e))
|
||||
continue
|
||||
|
||||
except TypeError:
|
||||
print("type error")
|
||||
continue
|
||||
if start_date < date < end_date:
|
||||
free_games_now.append(game)
|
||||
elif start_date > date:
|
||||
coming_free_games.append(game)
|
||||
# free games now
|
||||
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)
|
||||
|
||||
# self.free_games_now.layout().addStretch(1)
|
||||
|
||||
# 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("")
|
||||
|
||||
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)
|
||||
|
||||
locale = get_lang()
|
||||
self.game_stack.setCurrentIndex(1)
|
||||
date = f"[,{datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%dT%X')}.{str(random.randint(0, 999)).zfill(3)}Z]"
|
||||
|
||||
browse_model = BrowseModel(locale=locale, 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):
|
||||
QWidget().setLayout(self.game_widget.layout())
|
||||
if data:
|
||||
self.game_widget.setLayout(FlowLayout())
|
||||
|
||||
for game in data:
|
||||
price = game['price']['totalPrice']['fmtPrice']['originalPrice']
|
||||
discount_price = game['price']['totalPrice']['fmtPrice']['discountPrice']
|
||||
|
||||
if price != discount_price:
|
||||
w = GameWidget(self.path, game, 275)
|
||||
else:
|
||||
w = GameWidget(self.path, game, 275)
|
||||
self.game_widget.layout().addWidget(w)
|
||||
w.show_info.connect(self.show_game.emit)
|
||||
|
||||
else:
|
||||
self.game_widget.setLayout(QVBoxLayout())
|
||||
self.game_widget.layout().addWidget(
|
||||
QLabel(self.tr("Could not get games matching the filter")))
|
||||
self.game_widget.layout().addStretch(1)
|
||||
self.game_stack.setCurrentIndex(0)
|
||||
|
||||
|
||||
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)
|
88
rare/components/tabs/shop/wishlist.py
Normal file
88
rare/components/tabs/shop/wishlist.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QStackedWidget, QMessageBox
|
||||
from qtawesome import icon
|
||||
|
||||
from rare.components.tabs.shop import ShopApiCore
|
||||
from rare.components.tabs.shop.game_widgets import WishlistWidget
|
||||
from rare.ui.components.tabs.store.wishlist import Ui_Wishlist
|
||||
from rare.utils.extra_widgets import WaitingSpinner
|
||||
|
||||
|
||||
class Wishlist(QStackedWidget, Ui_Wishlist):
|
||||
show_game_info = pyqtSignal(dict)
|
||||
update_wishlist_signal = pyqtSignal()
|
||||
|
||||
def __init__(self, api_core: ShopApiCore):
|
||||
super(Wishlist, self).__init__()
|
||||
self.api_core = api_core
|
||||
self.setupUi(self)
|
||||
self.addWidget(WaitingSpinner())
|
||||
self.setCurrentIndex(1)
|
||||
self.wishlist = []
|
||||
self.widgets = []
|
||||
|
||||
self.sort_cb.currentIndexChanged.connect(lambda i: self.set_wishlist(self.wishlist, i))
|
||||
self.filter_cb.currentIndexChanged.connect(self.set_filter)
|
||||
self.reload_button.clicked.connect(self.update_wishlist)
|
||||
self.reload_button.setIcon(icon("fa.refresh", color="white"))
|
||||
|
||||
def update_wishlist(self):
|
||||
self.setCurrentIndex(1)
|
||||
self.api_core.get_wishlist(self.set_wishlist)
|
||||
|
||||
def delete_from_wishlist(self, game):
|
||||
self.api_core.remove_from_wishlist(game["namespace"], game["id"],
|
||||
lambda success: self.update_wishlist() if success else
|
||||
QMessageBox.warning(self, "Error",
|
||||
self.tr("Could not remove game from wishlist")))
|
||||
self.update_wishlist_signal.emit()
|
||||
|
||||
def set_filter(self, i):
|
||||
count = 0
|
||||
for w in self.widgets:
|
||||
if i == 1 and not w.discount:
|
||||
w.setVisible(False)
|
||||
else:
|
||||
w.setVisible(True)
|
||||
count += 1
|
||||
|
||||
if i == 0:
|
||||
w.setVisible(True)
|
||||
|
||||
if count == 0:
|
||||
self.no_games_label.setVisible(True)
|
||||
else:
|
||||
self.no_games_label.setVisible(False)
|
||||
|
||||
def set_wishlist(self, wishlist, sort=0):
|
||||
self.wishlist = wishlist
|
||||
|
||||
for i in self.widgets:
|
||||
i.setParent(None)
|
||||
|
||||
if sort == 0:
|
||||
sorted_list = sorted(wishlist, key=lambda x: x["offer"]["title"])
|
||||
elif sort == 1:
|
||||
sorted_list = sorted(wishlist, key=lambda x: x["offer"]['price']['totalPrice']['fmtPrice']['discountPrice'])
|
||||
elif sort == 2:
|
||||
sorted_list = sorted(wishlist, key=lambda x: x["offer"]["seller"]["name"])
|
||||
elif sort == 3:
|
||||
sorted_list = sorted(wishlist, reverse=True, key=lambda x: 1 - (
|
||||
x["offer"]["price"]["totalPrice"]["discountPrice"] / x["offer"]["price"]["totalPrice"][
|
||||
"originalPrice"]))
|
||||
else:
|
||||
sorted_list = wishlist
|
||||
self.widgets.clear()
|
||||
|
||||
if len(sorted_list) == 0:
|
||||
self.no_games_label.setVisible(True)
|
||||
else:
|
||||
self.no_games_label.setVisible(False)
|
||||
|
||||
for game in sorted_list:
|
||||
w = WishlistWidget(game["offer"])
|
||||
self.widgets.append(w)
|
||||
self.list_layout.addWidget(w)
|
||||
w.open_game.connect(self.show_game_info.emit)
|
||||
w.delete_from_wishlist.connect(self.delete_from_wishlist)
|
||||
self.setCurrentIndex(0)
|
|
@ -255,8 +255,8 @@
|
|||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
0
rare/ui/components/tabs/store/__init__.py
Normal file
0
rare/ui/components/tabs/store/__init__.py
Normal file
136
rare/ui/components/tabs/store/browse_games.py
Normal file
136
rare/ui/components/tabs/store/browse_games.py
Normal file
|
@ -0,0 +1,136 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'browse_games.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
#
|
||||
# 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, QtWidgets
|
||||
|
||||
|
||||
class Ui_browse_games(object):
|
||||
def setupUi(self, browse_games):
|
||||
browse_games.setObjectName("browse_games")
|
||||
browse_games.resize(706, 541)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(browse_games)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.stack = QtWidgets.QStackedWidget(browse_games)
|
||||
self.stack.setObjectName("stack")
|
||||
self.games_page = QtWidgets.QWidget()
|
||||
self.games_page.setObjectName("games_page")
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.games_page)
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.games = QtWidgets.QScrollArea(self.games_page)
|
||||
self.games.setWidgetResizable(True)
|
||||
self.games.setObjectName("games")
|
||||
self.scrollAreaWidgetContents = QtWidgets.QWidget()
|
||||
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 462, 503))
|
||||
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
|
||||
self.games.setWidget(self.scrollAreaWidgetContents)
|
||||
self.verticalLayout_5.addWidget(self.games)
|
||||
self.stack.addWidget(self.games_page)
|
||||
self.error = QtWidgets.QWidget()
|
||||
self.error.setObjectName("error")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.error)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.error_label = QtWidgets.QLabel(self.error)
|
||||
self.error_label.setObjectName("error_label")
|
||||
self.verticalLayout_6.addWidget(self.error_label)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_6.addItem(spacerItem)
|
||||
self.stack.addWidget(self.error)
|
||||
self.horizontalLayout_2.addWidget(self.stack)
|
||||
self.filter_scroll = QtWidgets.QScrollArea(browse_games)
|
||||
self.filter_scroll.setMaximumSize(QtCore.QSize(200, 16777215))
|
||||
self.filter_scroll.setWidgetResizable(True)
|
||||
self.filter_scroll.setObjectName("filter_scroll")
|
||||
self.scroll_widget = QtWidgets.QWidget()
|
||||
self.scroll_widget.setGeometry(QtCore.QRect(0, 0, 198, 521))
|
||||
self.scroll_widget.setObjectName("scroll_widget")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.scroll_widget)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.price_gb = QtWidgets.QGroupBox(self.scroll_widget)
|
||||
self.price_gb.setObjectName("price_gb")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.price_gb)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.clear_price = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.clear_price.setChecked(True)
|
||||
self.clear_price.setObjectName("clear_price")
|
||||
self.verticalLayout_2.addWidget(self.clear_price)
|
||||
self.free_button = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.free_button.setObjectName("free_button")
|
||||
self.verticalLayout_2.addWidget(self.free_button)
|
||||
self.under10 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under10.setObjectName("under10")
|
||||
self.verticalLayout_2.addWidget(self.under10)
|
||||
self.under20 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under20.setObjectName("under20")
|
||||
self.verticalLayout_2.addWidget(self.under20)
|
||||
self.under30 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under30.setObjectName("under30")
|
||||
self.verticalLayout_2.addWidget(self.under30)
|
||||
self.above = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.above.setObjectName("above")
|
||||
self.verticalLayout_2.addWidget(self.above)
|
||||
self.on_discount = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.on_discount.setObjectName("on_discount")
|
||||
self.verticalLayout_2.addWidget(self.on_discount)
|
||||
self.verticalLayout_3.addWidget(self.price_gb)
|
||||
self.genre_gb = QtWidgets.QGroupBox(self.scroll_widget)
|
||||
self.genre_gb.setObjectName("genre_gb")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.genre_gb)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.verticalLayout_3.addWidget(self.genre_gb)
|
||||
self.type_gb = QtWidgets.QGroupBox(self.scroll_widget)
|
||||
self.type_gb.setObjectName("type_gb")
|
||||
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.type_gb)
|
||||
self.verticalLayout_8.setObjectName("verticalLayout_8")
|
||||
self.verticalLayout_3.addWidget(self.type_gb)
|
||||
self.platform_gb = QtWidgets.QGroupBox(self.scroll_widget)
|
||||
self.platform_gb.setObjectName("platform_gb")
|
||||
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.platform_gb)
|
||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||
self.verticalLayout_3.addWidget(self.platform_gb)
|
||||
self.others_gb = QtWidgets.QGroupBox(self.scroll_widget)
|
||||
self.others_gb.setObjectName("others_gb")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.others_gb)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.verticalLayout_3.addWidget(self.others_gb)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_3.addItem(spacerItem1)
|
||||
self.filter_scroll.setWidget(self.scroll_widget)
|
||||
self.horizontalLayout_2.addWidget(self.filter_scroll)
|
||||
|
||||
self.retranslateUi(browse_games)
|
||||
self.stack.setCurrentIndex(0)
|
||||
QtCore.QMetaObject.connectSlotsByName(browse_games)
|
||||
|
||||
def retranslateUi(self, browse_games):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
browse_games.setWindowTitle(_translate("browse_games", "Form"))
|
||||
self.error_label.setText(_translate("browse_games", "An error occured"))
|
||||
self.price_gb.setTitle(_translate("browse_games", "Price"))
|
||||
self.clear_price.setText(_translate("browse_games", "Clear price filter"))
|
||||
self.free_button.setText(_translate("browse_games", "Free"))
|
||||
self.under10.setText(_translate("browse_games", "Under 10"))
|
||||
self.under20.setText(_translate("browse_games", "Under 20"))
|
||||
self.under30.setText(_translate("browse_games", "Under 30"))
|
||||
self.above.setText(_translate("browse_games", "14.99 and above"))
|
||||
self.on_discount.setText(_translate("browse_games", "Discount"))
|
||||
self.genre_gb.setTitle(_translate("browse_games", "Genre"))
|
||||
self.type_gb.setTitle(_translate("browse_games", "Type"))
|
||||
self.platform_gb.setTitle(_translate("browse_games", "Platform"))
|
||||
self.others_gb.setTitle(_translate("browse_games", "Other Tags"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
browse_games = QtWidgets.QWidget()
|
||||
ui = Ui_browse_games()
|
||||
ui.setupUi(browse_games)
|
||||
browse_games.show()
|
||||
sys.exit(app.exec_())
|
204
rare/ui/components/tabs/store/browse_games.ui
Normal file
204
rare/ui/components/tabs/store/browse_games.ui
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>browse_games</class>
|
||||
<widget class="QWidget" name="browse_games">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>706</width>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="games_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="games">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>462</width>
|
||||
<height>503</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="error">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="error_label">
|
||||
<property name="text">
|
||||
<string>An error occured</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="filter_scroll">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scroll_widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>198</width>
|
||||
<height>521</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="price_gb">
|
||||
<property name="title">
|
||||
<string>Price</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="clear_price">
|
||||
<property name="text">
|
||||
<string>Clear price filter</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="QRadioButton" name="on_discount">
|
||||
<property name="text">
|
||||
<string>Discount</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="genre_gb">
|
||||
<property name="title">
|
||||
<string>Genre</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="type_gb">
|
||||
<property name="title">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="platform_gb">
|
||||
<property name="title">
|
||||
<string>Platform</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="others_gb">
|
||||
<property name="title">
|
||||
<string>Other Tags</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
124
rare/ui/components/tabs/store/shop_game_info.py
Normal file
124
rare/ui/components/tabs/store/shop_game_info.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'shop_game_info.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
#
|
||||
# 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_shop_info(object):
|
||||
def setupUi(self, shop_info):
|
||||
shop_info.setObjectName("shop_info")
|
||||
shop_info.resize(702, 468)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(shop_info)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.back_button = QtWidgets.QPushButton(shop_info)
|
||||
self.back_button.setObjectName("back_button")
|
||||
self.verticalLayout.addWidget(self.back_button)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.image_stack = QtWidgets.QStackedWidget(shop_info)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.image_stack.sizePolicy().hasHeightForWidth())
|
||||
self.image_stack.setSizePolicy(sizePolicy)
|
||||
self.image_stack.setObjectName("image_stack")
|
||||
self.horizontalLayout.addWidget(self.image_stack)
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.title = QtWidgets.QLabel(shop_info)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(18)
|
||||
self.title.setFont(font)
|
||||
self.title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||
self.title.setObjectName("title")
|
||||
self.verticalLayout_2.addWidget(self.title)
|
||||
self.dev = QtWidgets.QLabel(shop_info)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.dev.setFont(font)
|
||||
self.dev.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||
self.dev.setObjectName("dev")
|
||||
self.verticalLayout_2.addWidget(self.dev)
|
||||
self.owned_label = QtWidgets.QLabel(shop_info)
|
||||
self.owned_label.setObjectName("owned_label")
|
||||
self.verticalLayout_2.addWidget(self.owned_label)
|
||||
self.price = QtWidgets.QLabel(shop_info)
|
||||
self.price.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||
self.price.setObjectName("price")
|
||||
self.verticalLayout_2.addWidget(self.price)
|
||||
self.discount_price = QtWidgets.QLabel(shop_info)
|
||||
self.discount_price.setObjectName("discount_price")
|
||||
self.verticalLayout_2.addWidget(self.discount_price)
|
||||
self.tags = QtWidgets.QLabel(shop_info)
|
||||
self.tags.setObjectName("tags")
|
||||
self.verticalLayout_2.addWidget(self.tags)
|
||||
self.open_store_button = QtWidgets.QPushButton(shop_info)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.open_store_button.sizePolicy().hasHeightForWidth())
|
||||
self.open_store_button.setSizePolicy(sizePolicy)
|
||||
self.open_store_button.setObjectName("open_store_button")
|
||||
self.verticalLayout_2.addWidget(self.open_store_button)
|
||||
self.wishlist_button = QtWidgets.QPushButton(shop_info)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.wishlist_button.sizePolicy().hasHeightForWidth())
|
||||
self.wishlist_button.setSizePolicy(sizePolicy)
|
||||
self.wishlist_button.setObjectName("wishlist_button")
|
||||
self.verticalLayout_2.addWidget(self.wishlist_button)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_2)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem1)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.req_group_box = QtWidgets.QGroupBox(shop_info)
|
||||
self.req_group_box.setObjectName("req_group_box")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.req_group_box)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.verticalLayout.addWidget(self.req_group_box)
|
||||
self.social_link_gb = QtWidgets.QGroupBox(shop_info)
|
||||
self.social_link_gb.setObjectName("social_link_gb")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.social_link_gb)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.verticalLayout.addWidget(self.social_link_gb)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem2)
|
||||
|
||||
self.retranslateUi(shop_info)
|
||||
self.image_stack.setCurrentIndex(-1)
|
||||
QtCore.QMetaObject.connectSlotsByName(shop_info)
|
||||
|
||||
def retranslateUi(self, shop_info):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
shop_info.setWindowTitle(_translate("shop_info", "Form"))
|
||||
self.back_button.setText(_translate("shop_info", "Back"))
|
||||
self.title.setText(_translate("shop_info", "Error"))
|
||||
self.dev.setText(_translate("shop_info", "TextLabel"))
|
||||
self.owned_label.setText(_translate("shop_info", "You already own this game"))
|
||||
self.price.setText(_translate("shop_info", "TextLabel"))
|
||||
self.discount_price.setText(_translate("shop_info", "TextLabel"))
|
||||
self.tags.setText(_translate("shop_info", "TextLabel"))
|
||||
self.open_store_button.setText(_translate("shop_info", "Buy Game in Epic Games Store"))
|
||||
self.wishlist_button.setText(_translate("shop_info", "Add to wishlist"))
|
||||
self.req_group_box.setTitle(_translate("shop_info", "Requirements"))
|
||||
self.social_link_gb.setTitle(_translate("shop_info", "Social Links"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
shop_info = QtWidgets.QWidget()
|
||||
ui = Ui_shop_info()
|
||||
ui.setupUi(shop_info)
|
||||
shop_info.show()
|
||||
sys.exit(app.exec_())
|
191
rare/ui/components/tabs/store/shop_game_info.ui
Normal file
191
rare/ui/components/tabs/store/shop_game_info.ui
Normal file
|
@ -0,0 +1,191 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>shop_info</class>
|
||||
<widget class="QWidget" name="shop_info">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>468</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="back_button">
|
||||
<property name="text">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="image_stack">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="title">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Error</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dev">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="owned_label">
|
||||
<property name="text">
|
||||
<string>You already own this game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="price">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="discount_price">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="tags">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="open_store_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Buy Game in Epic Games Store</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="wishlist_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add to wishlist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="req_group_box">
|
||||
<property name="title">
|
||||
<string>Requirements</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="social_link_gb">
|
||||
<property name="title">
|
||||
<string>Social Links</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
180
rare/ui/components/tabs/store/store.py
Normal file
180
rare/ui/components/tabs/store/store.py
Normal file
|
@ -0,0 +1,180 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'store.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
#
|
||||
# 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, QtWidgets
|
||||
|
||||
|
||||
class Ui_ShopWidget(object):
|
||||
def setupUi(self, ShopWidget):
|
||||
ShopWidget.setObjectName("ShopWidget")
|
||||
ShopWidget.resize(850, 572)
|
||||
self.verticalLayout_7 = QtWidgets.QVBoxLayout(ShopWidget)
|
||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.scrollArea = QtWidgets.QScrollArea(ShopWidget)
|
||||
self.scrollArea.setWidgetResizable(True)
|
||||
self.scrollArea.setObjectName("scrollArea")
|
||||
self.scrollAreaWidgetContents = QtWidgets.QWidget()
|
||||
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 828, 550))
|
||||
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.widget = QtWidgets.QWidget(self.scrollAreaWidgetContents)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.free_game_group_box = QtWidgets.QGroupBox(self.widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.free_game_group_box.sizePolicy().hasHeightForWidth())
|
||||
self.free_game_group_box.setSizePolicy(sizePolicy)
|
||||
self.free_game_group_box.setObjectName("free_game_group_box")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.free_game_group_box)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.free_stack = QtWidgets.QStackedWidget(self.free_game_group_box)
|
||||
self.free_stack.setObjectName("free_stack")
|
||||
self.free_widget = QtWidgets.QWidget()
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.free_widget.sizePolicy().hasHeightForWidth())
|
||||
self.free_widget.setSizePolicy(sizePolicy)
|
||||
self.free_widget.setObjectName("free_widget")
|
||||
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.free_widget)
|
||||
self.verticalLayout_8.setObjectName("verticalLayout_8")
|
||||
self.free_stack.addWidget(self.free_widget)
|
||||
self.verticalLayout_3.addWidget(self.free_stack)
|
||||
self.verticalLayout.addWidget(self.free_game_group_box)
|
||||
self.discounts_gb = QtWidgets.QGroupBox(self.widget)
|
||||
self.discounts_gb.setObjectName("discounts_gb")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.discounts_gb)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.discount_stack = QtWidgets.QStackedWidget(self.discounts_gb)
|
||||
self.discount_stack.setObjectName("discount_stack")
|
||||
self.discount_widget = QtWidgets.QWidget()
|
||||
self.discount_widget.setObjectName("discount_widget")
|
||||
self.discount_stack.addWidget(self.discount_widget)
|
||||
self.verticalLayout_6.addWidget(self.discount_stack)
|
||||
self.verticalLayout.addWidget(self.discounts_gb)
|
||||
self.filter_game_gb = QtWidgets.QGroupBox(self.widget)
|
||||
self.filter_game_gb.setObjectName("filter_game_gb")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.filter_game_gb)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.game_stack = QtWidgets.QStackedWidget(self.filter_game_gb)
|
||||
self.game_stack.setObjectName("game_stack")
|
||||
self.game_widget = QtWidgets.QWidget()
|
||||
self.game_widget.setObjectName("game_widget")
|
||||
self.game_stack.addWidget(self.game_widget)
|
||||
self.verticalLayout_4.addWidget(self.game_stack)
|
||||
self.verticalLayout.addWidget(self.filter_game_gb)
|
||||
self.horizontalLayout.addWidget(self.widget)
|
||||
self.filter_gb = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.filter_gb.sizePolicy().hasHeightForWidth())
|
||||
self.filter_gb.setSizePolicy(sizePolicy)
|
||||
self.filter_gb.setMinimumSize(QtCore.QSize(150, 0))
|
||||
self.filter_gb.setMaximumSize(QtCore.QSize(16777215, 16777215))
|
||||
self.filter_gb.setObjectName("filter_gb")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.filter_gb)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.reset_button = QtWidgets.QPushButton(self.filter_gb)
|
||||
self.reset_button.setObjectName("reset_button")
|
||||
self.verticalLayout_2.addWidget(self.reset_button)
|
||||
self.price_gb = QtWidgets.QGroupBox(self.filter_gb)
|
||||
self.price_gb.setObjectName("price_gb")
|
||||
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.price_gb)
|
||||
self.verticalLayout_9.setObjectName("verticalLayout_9")
|
||||
self.none_price = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.none_price.setChecked(True)
|
||||
self.none_price.setObjectName("none_price")
|
||||
self.verticalLayout_9.addWidget(self.none_price)
|
||||
self.free_button = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.free_button.setObjectName("free_button")
|
||||
self.verticalLayout_9.addWidget(self.free_button)
|
||||
self.under10 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under10.setObjectName("under10")
|
||||
self.verticalLayout_9.addWidget(self.under10)
|
||||
self.under20 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under20.setObjectName("under20")
|
||||
self.verticalLayout_9.addWidget(self.under20)
|
||||
self.under30 = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.under30.setObjectName("under30")
|
||||
self.verticalLayout_9.addWidget(self.under30)
|
||||
self.above = QtWidgets.QRadioButton(self.price_gb)
|
||||
self.above.setObjectName("above")
|
||||
self.verticalLayout_9.addWidget(self.above)
|
||||
self.on_discount = QtWidgets.QCheckBox(self.price_gb)
|
||||
self.on_discount.setObjectName("on_discount")
|
||||
self.verticalLayout_9.addWidget(self.on_discount)
|
||||
self.verticalLayout_2.addWidget(self.price_gb)
|
||||
self.platform_gb = QtWidgets.QGroupBox(self.filter_gb)
|
||||
self.platform_gb.setObjectName("platform_gb")
|
||||
self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.platform_gb)
|
||||
self.verticalLayout_13.setObjectName("verticalLayout_13")
|
||||
self.verticalLayout_2.addWidget(self.platform_gb)
|
||||
self.genre_gb = QtWidgets.QGroupBox(self.filter_gb)
|
||||
self.genre_gb.setObjectName("genre_gb")
|
||||
self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.genre_gb)
|
||||
self.verticalLayout_12.setObjectName("verticalLayout_12")
|
||||
self.verticalLayout_2.addWidget(self.genre_gb)
|
||||
self.type_gb = QtWidgets.QGroupBox(self.filter_gb)
|
||||
self.type_gb.setObjectName("type_gb")
|
||||
self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.type_gb)
|
||||
self.verticalLayout_11.setObjectName("verticalLayout_11")
|
||||
self.verticalLayout_2.addWidget(self.type_gb)
|
||||
self.others_gb = QtWidgets.QGroupBox(self.filter_gb)
|
||||
self.others_gb.setObjectName("others_gb")
|
||||
self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.others_gb)
|
||||
self.verticalLayout_10.setObjectName("verticalLayout_10")
|
||||
self.verticalLayout_2.addWidget(self.others_gb)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem)
|
||||
self.horizontalLayout.addWidget(self.filter_gb)
|
||||
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
|
||||
self.horizontalLayout_2.addWidget(self.scrollArea)
|
||||
self.verticalLayout_7.addLayout(self.horizontalLayout_2)
|
||||
|
||||
self.retranslateUi(ShopWidget)
|
||||
QtCore.QMetaObject.connectSlotsByName(ShopWidget)
|
||||
|
||||
def retranslateUi(self, ShopWidget):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ShopWidget.setWindowTitle(_translate("ShopWidget", "Form"))
|
||||
self.free_game_group_box.setTitle(_translate("ShopWidget", "Free Games"))
|
||||
self.discounts_gb.setTitle(_translate("ShopWidget", "Discounts from your wishlist"))
|
||||
self.filter_game_gb.setTitle(_translate("ShopWidget", "Games"))
|
||||
self.filter_gb.setTitle(_translate("ShopWidget", "Filter"))
|
||||
self.reset_button.setText(_translate("ShopWidget", "Reset"))
|
||||
self.price_gb.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_gb.setTitle(_translate("ShopWidget", "Platform"))
|
||||
self.genre_gb.setTitle(_translate("ShopWidget", "Genre"))
|
||||
self.type_gb.setTitle(_translate("ShopWidget", "Type"))
|
||||
self.others_gb.setTitle(_translate("ShopWidget", "Other Tags"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
ShopWidget = QtWidgets.QWidget()
|
||||
ui = Ui_ShopWidget()
|
||||
ui.setupUi(ShopWidget)
|
||||
ShopWidget.show()
|
||||
sys.exit(app.exec_())
|
248
rare/ui/components/tabs/store/store.ui
Normal file
248
rare/ui/components/tabs/store/store.ui
Normal file
|
@ -0,0 +1,248 @@
|
|||
<?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>850</width>
|
||||
<height>572</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>828</width>
|
||||
<height>550</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="free_game_group_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Free Games</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="free_stack">
|
||||
<widget class="QWidget" name="free_widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred"
|
||||
vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout"
|
||||
name="verticalLayout_8"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="discounts_gb">
|
||||
<property name="title">
|
||||
<string>Discounts from your wishlist</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="discount_stack">
|
||||
<widget class="QWidget" name="discount_widget"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filter_game_gb">
|
||||
<property name="title">
|
||||
<string>Games</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="game_stack">
|
||||
<widget class="QWidget" name="game_widget"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filter_gb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="reset_button">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="price_gb">
|
||||
<property name="title">
|
||||
<string>Price</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<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_gb">
|
||||
<property name="title">
|
||||
<string>Platform</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="genre_gb">
|
||||
<property name="title">
|
||||
<string>Genre</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="type_gb">
|
||||
<property name="title">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="others_gb">
|
||||
<property name="title">
|
||||
<string>Other Tags</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
112
rare/ui/components/tabs/store/wishlist.py
Normal file
112
rare/ui/components/tabs/store/wishlist.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'wishlist.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
#
|
||||
# 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_Wishlist(object):
|
||||
def setupUi(self, Wishlist):
|
||||
Wishlist.setObjectName("Wishlist")
|
||||
Wishlist.resize(736, 398)
|
||||
self.page = QtWidgets.QWidget()
|
||||
self.page.setObjectName("page")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.page)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.scroll_area = QtWidgets.QScrollArea(self.page)
|
||||
self.scroll_area.setWidgetResizable(True)
|
||||
self.scroll_area.setObjectName("scroll_area")
|
||||
self.scroll_widget = QtWidgets.QWidget()
|
||||
self.scroll_widget.setGeometry(QtCore.QRect(0, 0, 716, 378))
|
||||
self.scroll_widget.setObjectName("scroll_widget")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.scroll_widget)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.title_label = QtWidgets.QLabel(self.scroll_widget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(15)
|
||||
self.title_label.setFont(font)
|
||||
self.title_label.setObjectName("title_label")
|
||||
self.verticalLayout_2.addWidget(self.title_label)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.sort_label = QtWidgets.QLabel(self.scroll_widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.sort_label.sizePolicy().hasHeightForWidth())
|
||||
self.sort_label.setSizePolicy(sizePolicy)
|
||||
self.sort_label.setObjectName("sort_label")
|
||||
self.horizontalLayout.addWidget(self.sort_label)
|
||||
self.sort_cb = QtWidgets.QComboBox(self.scroll_widget)
|
||||
self.sort_cb.setObjectName("sort_cb")
|
||||
self.sort_cb.addItem("")
|
||||
self.sort_cb.addItem("")
|
||||
self.sort_cb.addItem("")
|
||||
self.sort_cb.addItem("")
|
||||
self.horizontalLayout.addWidget(self.sort_cb)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.filter_label = QtWidgets.QLabel(self.scroll_widget)
|
||||
self.filter_label.setObjectName("filter_label")
|
||||
self.horizontalLayout.addWidget(self.filter_label)
|
||||
self.filter_cb = QtWidgets.QComboBox(self.scroll_widget)
|
||||
self.filter_cb.setObjectName("filter_cb")
|
||||
self.filter_cb.addItem("")
|
||||
self.filter_cb.addItem("")
|
||||
self.horizontalLayout.addWidget(self.filter_cb)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem1)
|
||||
self.reload_button = QtWidgets.QPushButton(self.scroll_widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.reload_button.sizePolicy().hasHeightForWidth())
|
||||
self.reload_button.setSizePolicy(sizePolicy)
|
||||
self.reload_button.setText("")
|
||||
self.reload_button.setObjectName("reload_button")
|
||||
self.horizontalLayout.addWidget(self.reload_button)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
self.list_layout = QtWidgets.QVBoxLayout()
|
||||
self.list_layout.setObjectName("list_layout")
|
||||
self.verticalLayout_2.addLayout(self.list_layout)
|
||||
self.no_games_label = QtWidgets.QLabel(self.scroll_widget)
|
||||
self.no_games_label.setObjectName("no_games_label")
|
||||
self.verticalLayout_2.addWidget(self.no_games_label)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(379, 218, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem2)
|
||||
self.scroll_area.setWidget(self.scroll_widget)
|
||||
self.verticalLayout.addWidget(self.scroll_area)
|
||||
Wishlist.addWidget(self.page)
|
||||
|
||||
self.retranslateUi(Wishlist)
|
||||
QtCore.QMetaObject.connectSlotsByName(Wishlist)
|
||||
|
||||
def retranslateUi(self, Wishlist):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Wishlist.setWindowTitle(_translate("Wishlist", "StackedWidget"))
|
||||
self.title_label.setText(_translate("Wishlist", "Wishlist"))
|
||||
self.sort_label.setText(_translate("Wishlist", "Sort by"))
|
||||
self.sort_cb.setItemText(0, _translate("Wishlist", "Name"))
|
||||
self.sort_cb.setItemText(1, _translate("Wishlist", "Price"))
|
||||
self.sort_cb.setItemText(2, _translate("Wishlist", "Developer"))
|
||||
self.sort_cb.setItemText(3, _translate("Wishlist", "Discount"))
|
||||
self.filter_label.setText(_translate("Wishlist", "Filter:"))
|
||||
self.filter_cb.setItemText(0, _translate("Wishlist", "None"))
|
||||
self.filter_cb.setItemText(1, _translate("Wishlist", "Discount"))
|
||||
self.no_games_label.setText(_translate("Wishlist", "No games matching your filter"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
Wishlist = QtWidgets.QStackedWidget()
|
||||
ui = Ui_Wishlist()
|
||||
ui.setupUi(Wishlist)
|
||||
Wishlist.show()
|
||||
sys.exit(app.exec_())
|
178
rare/ui/components/tabs/store/wishlist.ui
Normal file
178
rare/ui/components/tabs/store/wishlist.ui
Normal file
|
@ -0,0 +1,178 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Wishlist</class>
|
||||
<widget class="QStackedWidget" name="Wishlist">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>736</width>
|
||||
<height>398</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>StackedWidget</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scroll_area">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scroll_widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>716</width>
|
||||
<height>378</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="title_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Wishlist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="sort_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort by</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="sort_cb">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Price</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Developer</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Discount</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="filter_label">
|
||||
<property name="text">
|
||||
<string>Filter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="filter_cb">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Discount</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reload_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="list_layout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="no_games_label">
|
||||
<property name="text">
|
||||
<string>No games matching your filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>379</width>
|
||||
<height>218</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
89
rare/ui/components/tabs/store/wishlist_widget.py
Normal file
89
rare/ui/components/tabs/store/wishlist_widget.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'wishlist_widget.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
#
|
||||
# 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_WishlistWidget(object):
|
||||
def setupUi(self, WishlistWidget):
|
||||
WishlistWidget.setObjectName("WishlistWidget")
|
||||
WishlistWidget.resize(523, 172)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(WishlistWidget)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.widget = QtWidgets.QWidget(WishlistWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
|
||||
self.widget.setSizePolicy(sizePolicy)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.title_label = QtWidgets.QLabel(self.widget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(16)
|
||||
self.title_label.setFont(font)
|
||||
self.title_label.setWordWrap(True)
|
||||
self.title_label.setObjectName("title_label")
|
||||
self.verticalLayout_2.addWidget(self.title_label)
|
||||
self.developer = QtWidgets.QLabel(self.widget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.developer.setFont(font)
|
||||
self.developer.setObjectName("developer")
|
||||
self.verticalLayout_2.addWidget(self.developer)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.discount_price = QtWidgets.QLabel(self.widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.discount_price.sizePolicy().hasHeightForWidth())
|
||||
self.discount_price.setSizePolicy(sizePolicy)
|
||||
self.discount_price.setObjectName("discount_price")
|
||||
self.horizontalLayout_2.addWidget(self.discount_price)
|
||||
self.price = QtWidgets.QLabel(self.widget)
|
||||
self.price.setObjectName("price")
|
||||
self.horizontalLayout_2.addWidget(self.price)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem)
|
||||
self.horizontalLayout.addWidget(self.widget)
|
||||
self.delete_button = QtWidgets.QPushButton(WishlistWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.delete_button.sizePolicy().hasHeightForWidth())
|
||||
self.delete_button.setSizePolicy(sizePolicy)
|
||||
self.delete_button.setText("")
|
||||
self.delete_button.setObjectName("delete_button")
|
||||
self.horizontalLayout.addWidget(self.delete_button)
|
||||
|
||||
self.retranslateUi(WishlistWidget)
|
||||
QtCore.QMetaObject.connectSlotsByName(WishlistWidget)
|
||||
|
||||
def retranslateUi(self, WishlistWidget):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
WishlistWidget.setWindowTitle(_translate("WishlistWidget", "Form"))
|
||||
self.title_label.setText(_translate("WishlistWidget", "TextLabel"))
|
||||
self.developer.setText(_translate("WishlistWidget", "TextLabel"))
|
||||
self.discount_price.setText(_translate("WishlistWidget", "TextLabel"))
|
||||
self.price.setText(_translate("WishlistWidget", "TextLabel"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
WishlistWidget = QtWidgets.QWidget()
|
||||
ui = Ui_WishlistWidget()
|
||||
ui.setupUi(WishlistWidget)
|
||||
WishlistWidget.show()
|
||||
sys.exit(app.exec_())
|
110
rare/ui/components/tabs/store/wishlist_widget.ui
Normal file
110
rare/ui/components/tabs/store/wishlist_widget.ui
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WishlistWidget</class>
|
||||
<widget class="QWidget" name="WishlistWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>523</width>
|
||||
<height>172</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="title_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="developer">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="discount_price">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="price">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="delete_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,13 +1,20 @@
|
|||
import io
|
||||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal
|
||||
from PyQt5.QtGui import QMovie
|
||||
import PIL
|
||||
from PIL import Image
|
||||
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal, QSettings
|
||||
from PyQt5.QtGui import QMovie, QPixmap
|
||||
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, QHBoxLayout, QWidget, QPushButton, \
|
||||
QStyleOptionTab, QStylePainter, QTabBar
|
||||
QStyleOptionTab, QStylePainter, QTabBar, QLineEdit, QToolButton
|
||||
from qtawesome import icon
|
||||
|
||||
from rare import resources_path
|
||||
from rare import resources_path, cache_dir
|
||||
from rare.ui.utils.pathedit import Ui_PathEdit
|
||||
from rare.utils.qt_requests import QtRequestManager
|
||||
|
||||
logger = getLogger("ExtraWidgets")
|
||||
|
||||
|
||||
class FlowLayout(QLayout):
|
||||
|
@ -252,3 +259,82 @@ class SelectViewWidget(QWidget):
|
|||
self.list_view.setIcon(icon("fa5s.list", color="orange"))
|
||||
self.icon_view = True
|
||||
self.toggled.emit()
|
||||
|
||||
|
||||
class ImageLabel(QLabel):
|
||||
|
||||
def __init__(self):
|
||||
super(ImageLabel, self).__init__()
|
||||
self.path = cache_dir
|
||||
self.manager = QtRequestManager("bytes")
|
||||
|
||||
def update_image(self, url, name, size: tuple = (240, 320)):
|
||||
self.setFixedSize(*size)
|
||||
self.img_size = size
|
||||
self.name = name
|
||||
for c in r'<>?":|\/* ':
|
||||
self.name = self.name.replace(c, "")
|
||||
if self.img_size[0] > self.img_size[1]:
|
||||
name_extension = "wide"
|
||||
else:
|
||||
name_extension = "tall"
|
||||
self.name = f"{self.name}_{name_extension}.png"
|
||||
if not os.path.exists(os.path.join(self.path, self.name)):
|
||||
self.manager.get(url, self.image_ready)
|
||||
# self.request.finished.connect(self.image_ready)
|
||||
else:
|
||||
self.show_image()
|
||||
|
||||
def image_ready(self, data):
|
||||
try:
|
||||
self.setPixmap(QPixmap())
|
||||
except RuntimeError:
|
||||
return
|
||||
try:
|
||||
image: Image.Image = Image.open(io.BytesIO(data))
|
||||
except PIL.UnidentifiedImageError:
|
||||
print(self.name)
|
||||
return
|
||||
image = image.resize((self.img_size[0], self.img_size[1]))
|
||||
|
||||
if QSettings().value("cache_images", False, bool):
|
||||
image.save(os.path.join(self.path, self.name), format="png")
|
||||
byte_array = io.BytesIO()
|
||||
image.save(byte_array, format="PNG")
|
||||
# pixmap = QPixmap.fromImage(ImageQt(image))
|
||||
pixmap = QPixmap()
|
||||
pixmap.loadFromData(byte_array.getvalue())
|
||||
# pixmap = QPixmap.fromImage(ImageQt.ImageQt(image))
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
def show_image(self):
|
||||
self.image = QPixmap(os.path.join(self.path, self.name)).scaled(*self.img_size,
|
||||
transformMode=Qt.SmoothTransformation)
|
||||
self.setPixmap(self.image)
|
||||
|
||||
|
||||
class ButtonLineEdit(QLineEdit):
|
||||
buttonClicked = pyqtSignal()
|
||||
|
||||
def __init__(self, icon_name, placeholder_text: str, parent=None):
|
||||
super(ButtonLineEdit, self).__init__(parent)
|
||||
|
||||
self.button = QToolButton(self)
|
||||
self.button.setIcon(icon(icon_name, color="white"))
|
||||
self.button.setStyleSheet('border: 0px; padding: 0px;')
|
||||
self.button.setCursor(Qt.ArrowCursor)
|
||||
self.button.clicked.connect(self.buttonClicked.emit)
|
||||
self.setPlaceholderText(placeholder_text)
|
||||
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
|
||||
buttonSize = self.button.sizeHint()
|
||||
|
||||
self.setStyleSheet('QLineEdit {padding-right: %dpx; }' % (buttonSize.width() + frameWidth + 1))
|
||||
self.setMinimumSize(max(self.minimumSizeHint().width(), buttonSize.width() + frameWidth * 2 + 2),
|
||||
max(self.minimumSizeHint().height(), buttonSize.height() + frameWidth * 2 + 2))
|
||||
|
||||
def resizeEvent(self, event):
|
||||
buttonSize = self.button.sizeHint()
|
||||
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
|
||||
self.button.move(self.rect().right() - frameWidth - buttonSize.width(),
|
||||
(self.rect().bottom() - buttonSize.height() + 1) / 2)
|
||||
super(ButtonLineEdit, self).resizeEvent(event)
|
||||
|
|
92
rare/utils/qt_requests.py
Normal file
92
rare/utils/qt_requests.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
import json
|
||||
from dataclasses import dataclass
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QJsonParseError, QJsonDocument
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
|
||||
logger = getLogger("QtRequests")
|
||||
|
||||
|
||||
class QtRequestManager(QObject):
|
||||
data_ready = pyqtSignal(object)
|
||||
request = None
|
||||
request_active = None
|
||||
|
||||
def __init__(self, type: str = "json", authorization_token: str = None):
|
||||
super(QtRequestManager, self).__init__()
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.type = type
|
||||
self.authorization_token = authorization_token
|
||||
self.request_queue = []
|
||||
|
||||
def post(self, url: str, payload: dict, handle_func):
|
||||
if not self.request_active:
|
||||
request = QNetworkRequest(QUrl(url))
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
|
||||
self.request_active = RequestQueueItem(handle_func=handle_func)
|
||||
payload = json.dumps(payload).encode("utf-8")
|
||||
|
||||
request.setHeader(QNetworkRequest.UserAgentHeader,
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36")
|
||||
|
||||
if self.authorization_token is not None:
|
||||
request.setRawHeader(b"Authorization", self.authorization_token.encode())
|
||||
|
||||
self.request = self.manager.post(request, payload)
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
|
||||
else:
|
||||
self.request_queue.append(
|
||||
RequestQueueItem(method="post", url=url, payload=payload, handle_func=handle_func))
|
||||
|
||||
def get(self, url: str, handle_func: callable):
|
||||
if not self.request_active:
|
||||
request = QNetworkRequest(QUrl(url))
|
||||
request.setHeader(QNetworkRequest.UserAgentHeader,
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36")
|
||||
|
||||
self.request_active = RequestQueueItem(handle_func=handle_func)
|
||||
self.request = self.manager.get(request)
|
||||
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
else:
|
||||
self.request_queue.append(RequestQueueItem(method="get", url=url, handle_func=handle_func))
|
||||
|
||||
def prepare_data(self):
|
||||
# self.request_active = False
|
||||
data = {} if self.type == "json" else b""
|
||||
if self.request:
|
||||
try:
|
||||
if self.request.error() == QNetworkReply.NoError:
|
||||
if self.type == "json":
|
||||
error = QJsonParseError()
|
||||
json_data = QJsonDocument.fromJson(self.request.readAll().data(), error)
|
||||
if QJsonParseError.NoError == error.error:
|
||||
data = json.loads(json_data.toJson().data().decode())
|
||||
|
||||
else:
|
||||
logger.error(error.errorString())
|
||||
else:
|
||||
data = self.request.readAll().data()
|
||||
|
||||
except RuntimeError as e:
|
||||
logger.error(str(e))
|
||||
self.request_active.handle_func(data)
|
||||
self.request.deleteLater()
|
||||
self.request_active = None
|
||||
|
||||
if self.request_queue:
|
||||
if self.request_queue[0].method == "post":
|
||||
self.post(self.request_queue[0].url, self.request_queue[0].payload, self.request_queue[0].handle_func)
|
||||
else:
|
||||
self.get(self.request_queue[0].url, self.request_queue[0].handle_func)
|
||||
self.request_queue.pop(0)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RequestQueueItem:
|
||||
method: str = None
|
||||
url: str = None
|
||||
handle_func: callable = None
|
||||
payload: dict = None
|
|
@ -9,6 +9,8 @@ from PyQt5.QtCore import QThread, pyqtSignal
|
|||
from custom_legendary.core import LegendaryCore
|
||||
from rare import cache_dir, data_dir
|
||||
|
||||
from rare import data_dir, cache_dir
|
||||
|
||||
replace_chars = ",;.:-_ "
|
||||
|
||||
file = os.path.join(cache_dir, "game_list.json")
|
||||
|
@ -77,6 +79,7 @@ def get_grade(steam_code):
|
|||
|
||||
def load_json() -> dict:
|
||||
if not os.path.exists(file):
|
||||
|
||||
response = requests.get(url)
|
||||
steam_ids = json.loads(response.text)["applist"]["apps"]
|
||||
ids = {}
|
||||
|
@ -108,6 +111,7 @@ def get_steam_id(title: str):
|
|||
ids = json.loads(open(file, "r").read())
|
||||
if title in ids.keys():
|
||||
steam_name = [title]
|
||||
|
||||
else:
|
||||
steam_name = difflib.get_close_matches(title, ids.keys(), n=1)
|
||||
if steam_name:
|
||||
|
|
|
@ -26,6 +26,7 @@ logger = getLogger("Utils")
|
|||
settings = QSettings("Rare", "Rare")
|
||||
|
||||
|
||||
|
||||
def download_images(signal: pyqtSignal, core: LegendaryCore):
|
||||
if not os.path.isdir(image_dir):
|
||||
os.makedirs(image_dir)
|
||||
|
@ -288,6 +289,7 @@ def create_rare_desktop_link(type_of_link):
|
|||
def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop") -> bool:
|
||||
igame = core.get_installed_game(app_name)
|
||||
|
||||
|
||||
if os.path.exists(p := os.path.join(image_dir, igame.app_name, 'Thumbnail.png')):
|
||||
icon = p
|
||||
elif os.path.exists(p := os.path.join(image_dir, igame.app_name, "DieselGameBoxLogo.png")):
|
||||
|
@ -295,6 +297,7 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop") -
|
|||
else:
|
||||
icon = os.path.join(os.path.join(image_dir, igame.app_name, "DieselGameBoxTall.png"))
|
||||
icon = icon.replace(".png", "")
|
||||
|
||||
# Linux
|
||||
if platform.system() == "Linux":
|
||||
if type_of_link == "desktop":
|
||||
|
@ -387,6 +390,7 @@ def get_uninstalled_pixmap(app_name: str) -> QPixmap:
|
|||
return pixmap
|
||||
|
||||
|
||||
|
||||
def optimal_text_background(image: list) -> Tuple[int, int, int]:
|
||||
"""
|
||||
Finds an optimal background color for text on the image by calculating the
|
||||
|
@ -419,3 +423,4 @@ def text_color_for_background(background: Tuple[int, int, int]) -> Tuple[int,
|
|||
return 255, 255, 255
|
||||
else:
|
||||
return 0, 0, 0
|
||||
|
||||
|
|
Loading…
Reference in a new issue