From 0d0b858a8ff046eb56393681078067fc3af91ec5 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Sun, 13 Jun 2021 14:33:17 +0200 Subject: [PATCH] Optimize search requests and option to cache images --- rare/components/tabs/settings/rare.py | 6 +- rare/components/tabs/shop/shop_models.py | 2 - rare/components/tabs/shop/shop_widget.py | 122 +++++++++++++---------- rare/ui/components/tabs/settings/rare.py | 21 ++-- rare/ui/components/tabs/settings/rare.ui | 43 +++++--- 5 files changed, 117 insertions(+), 77 deletions(-) diff --git a/rare/components/tabs/settings/rare.py b/rare/components/tabs/settings/rare.py index 2fafc3d9..bf9c511b 100644 --- a/rare/components/tabs/settings/rare.py +++ b/rare/components/tabs/settings/rare.py @@ -34,7 +34,8 @@ class RareSettings(QWidget, Ui_RareSettings): (self.confirm_start, "confirm_start", False), (self.auto_sync_cloud, "auto_sync_cloud", True), (self.notification, "notification", True), - (self.save_size, "save_size", False) + (self.save_size, "save_size", False), + (self.image_cache, "cache_images", True) ] self.settings = QSettings() @@ -99,6 +100,9 @@ class RareSettings(QWidget, Ui_RareSettings): self.save_size.stateChanged.connect( lambda: self.settings.setValue("save_size", self.save_size.isChecked()) ) + self.image_cache.stateChanged.connect( + lambda: self.settings.setValue("cache_images", self.image_cache.isChecked()) + ) if os.name == "posix": self.desktop_file = os.path.expanduser("~/Desktop/Rare.desktop") diff --git a/rare/components/tabs/shop/shop_models.py b/rare/components/tabs/shop/shop_models.py index 7e313b57..d029c27d 100644 --- a/rare/components/tabs/shop/shop_models.py +++ b/rare/components/tabs/shop/shop_models.py @@ -44,8 +44,6 @@ class ShopGame: @classmethod def from_json(cls, api_data: dict, search_data: dict): - print(api_data) - print(search_data) if isinstance(api_data, list): for product in api_data: if product["_title"] == "home": diff --git a/rare/components/tabs/shop/shop_widget.py b/rare/components/tabs/shop/shop_widget.py index 8bd37eb6..ed85b219 100644 --- a/rare/components/tabs/shop/shop_widget.py +++ b/rare/components/tabs/shop/shop_widget.py @@ -4,10 +4,9 @@ import logging import os from json import JSONDecodeError -import requests from PyQt5 import QtGui from PyQt5.QtCore import Qt, pyqtSignal, QUrl, QJsonDocument, QJsonParseError, \ - QStringListModel + QStringListModel, QSettings from PyQt5.QtGui import QPixmap from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QCompleter, QGroupBox, QHBoxLayout, QScrollArea @@ -16,12 +15,16 @@ from rare.ui.components.tabs.store.store import Ui_ShopWidget from rare.utils.extra_widgets import WaitingSpinner, ImageLabel, FlowLayout from rare.utils.utils import get_lang +logger = logging.getLogger("Shop") + # noinspection PyAttributeOutsideInit,PyBroadException class ShopWidget(QScrollArea, Ui_ShopWidget): show_info = pyqtSignal(list) show_game = pyqtSignal(dict) free_game_widgets = [] + active_search_request = False + next_search = "" def __init__(self): super(ShopWidget, self).__init__() @@ -137,19 +140,24 @@ class ShopWidget(QScrollArea, Ui_ShopWidget): self.free_game_request.deleteLater() def search_games(self, text, show_direct=False): - if text != "": - locale = get_lang() - payload = json.dumps({ - "query": query, - "variables": {"category": "games/edition/base|bundles/games|editors|software/edition/base", "count": 20, - "country": "DE", "keywords": text, "locale": locale, "sortDir": "DESC", - "allowCountries": locale.upper(), - "start": 0, "tag": "", "withMapping": False, "withPrice": True} - }).encode() - request = QNetworkRequest(QUrl("https://www.epicgames.com/graphql")) - request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") - self.search_request = self.manager.post(request, payload) - self.search_request.finished.connect(lambda: self.show_search_results(show_direct)) + if not self.active_search_request: + if text != "": + locale = get_lang() + payload = json.dumps({ + "query": query, + "variables": {"category": "games/edition/base|bundles/games|editors|software/edition/base", + "count": 20, + "country": locale.upper(), "keywords": text, "locale": locale, "sortDir": "DESC", + "allowCountries": locale.upper(), + "start": 0, "tag": "", "withMapping": False, "withPrice": True} + }).encode() + request = QNetworkRequest(QUrl("https://www.epicgames.com/graphql")) + request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") + self.search_request = self.manager.post(request, payload) + self.search_request.finished.connect(lambda: self.show_search_results(show_direct)) + + else: + self.next_search = text def show_search_results(self, show_direct=False): if self.search_request: @@ -158,27 +166,24 @@ class ShopWidget(QScrollArea, Ui_ShopWidget): json_data = QJsonDocument.fromJson(self.search_request.readAll().data(), error) if QJsonParseError.NoError == error.error: data = json.loads(json_data.toJson().data().decode())["data"]["Catalog"]["searchStore"]["elements"] + self.data = data + if show_direct: + self.show_search_result(True) + return + titles = [i.get("title") for i in data] + model = QStringListModel() + model.setStringList(titles) + self.completer.setModel(model) + # self.completer.popup() + if self.search_request: + self.search_request.deleteLater() else: logging.error(error.errorString()) - return # response = .decode(encoding="utf-8") # print(response) # results = json.loads(response) - else: - return - else: - return - self.data = data - if show_direct: - self.show_search_result(True) - return - titles = [i.get("title") for i in data] - model = QStringListModel() - model.setStringList(titles) - self.completer.setModel(model) - # self.completer.popup() - if self.search_request: - self.search_request.deleteLater() + + self.search_games(self.next_search) def show_search_result(self, show_direct=False): if not show_direct: @@ -198,6 +203,7 @@ class GameWidget(QWidget): def __init__(self, path, json_info=None): super(GameWidget, self).__init__() + self.manager = QNetworkAccessManager() if json_info: self.init_ui(json_info, path) self.path = path @@ -207,35 +213,34 @@ class GameWidget(QWidget): self.layout = QVBoxLayout() self.image = ImageLabel() self.json_info = json_info + self.slug = json_info["productSlug"] + self.width = 300 + self.title = json_info["title"] for img in json_info["keyImages"]: if img["type"] in ["DieselStoreFrontWide", "VaultClosed"]: - width = 300 - self.image.update_image(img["url"], json_info["title"], (width, int(width * 9 / 16))) + 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: print("No image found") - self.slug = json_info["productSlug"] - self.title = json_info["title"] - if not os.path.exists(p := os.path.join(self.path, f"{json_info['title']}.png")): + save = QSettings().value("cache_images", True, bool) + if os.path.exists(p := os.path.join(self.path, f"{json_info['title']}_wide.png")) and save: + self.image.setPixmap(QPixmap(p) + .scaled(self.width, int(self.width * 9 / 16), transformMode=Qt.SmoothTransformation)) + else: for img in json_info["keyImages"]: - if json_info["title"] != "Mystery Game": - if img["type"] == "DieselStoreFrontWide": - with open(p, "wb") as img_file: - content = requests.get(img["url"]).content - img_file.write(content) - break - else: - if img["type"] == "VaultClosed": - with open(p, "wb") as img_file: - content = requests.get(img["url"]).content - img_file.write(content) - break + if img["type"] in ["DieselStoreFrontWide", "VaultClosed"]: + if img["type"] == "VaultClosed" and self.title != "Mystery Game": + continue + self.image_request = self.manager.get(QNetworkRequest(QUrl(img["url"]))) + self.image_request.finished.connect(lambda: self.image_ready(save)) + break else: - print("No image found") - width = 300 - self.image.setPixmap(QPixmap(os.path.join(self.path, f"{json_info['title']}.png")) - .scaled(width, int(width * 9 / 16), transformMode=Qt.SmoothTransformation)) + # No image found + logger.error(f"No image found for {self.title}") + self.layout.addWidget(self.image) self.title_label = QLabel(json_info["title"]) @@ -243,6 +248,19 @@ class GameWidget(QWidget): self.layout.addWidget(self.title_label) self.setLayout(self.layout) + def image_ready(self, save: bool): + if self.image_request: + if self.image_request.error() == QNetworkReply.NoError: + data = self.image_request.readAll().data() + if save: + with open(os.path.join(self.path, f"{self.title}_wide.png"), "wb") as file: + file.write(data) + file.close() + pixmap = QPixmap() + pixmap.loadFromData(data) + self.image.setPixmap(pixmap.scaled(self.width, int(self.width * 9 / 16), + transformMode=Qt.SmoothTransformation)) + def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None: self.show_info.emit(self.json_info) diff --git a/rare/ui/components/tabs/settings/rare.py b/rare/ui/components/tabs/settings/rare.py index 6e948018..599ccbdb 100644 --- a/rare/ui/components/tabs/settings/rare.py +++ b/rare/ui/components/tabs/settings/rare.py @@ -14,6 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_RareSettings(object): def setupUi(self, RareSettings): RareSettings.setObjectName("RareSettings") + RareSettings.resize(544, 532) self.rare_layout = QtWidgets.QGridLayout(RareSettings) self.rare_layout.setObjectName("rare_layout") self.rpc_layout = QtWidgets.QVBoxLayout() @@ -34,26 +35,29 @@ class Ui_RareSettings(object): self.settings_group.setObjectName("settings_group") self.behavior_layout = QtWidgets.QGridLayout(self.settings_group) self.behavior_layout.setObjectName("behavior_layout") + self.notification = QtWidgets.QCheckBox(self.settings_group) + self.notification.setObjectName("notification") + self.behavior_layout.addWidget(self.notification, 4, 0, 1, 1) + self.auto_update = QtWidgets.QCheckBox(self.settings_group) + self.auto_update.setObjectName("auto_update") + self.behavior_layout.addWidget(self.auto_update, 1, 0, 1, 1) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.behavior_layout.addItem(spacerItem, 2, 1, 2, 1) self.save_size = QtWidgets.QCheckBox(self.settings_group) self.save_size.setObjectName("save_size") self.behavior_layout.addWidget(self.save_size, 5, 0, 1, 1) - self.notification = QtWidgets.QCheckBox(self.settings_group) - self.notification.setObjectName("notification") - self.behavior_layout.addWidget(self.notification, 4, 0, 1, 1) self.auto_sync_cloud = QtWidgets.QCheckBox(self.settings_group) self.auto_sync_cloud.setObjectName("auto_sync_cloud") self.behavior_layout.addWidget(self.auto_sync_cloud, 3, 0, 1, 1) self.confirm_start = QtWidgets.QCheckBox(self.settings_group) self.confirm_start.setObjectName("confirm_start") self.behavior_layout.addWidget(self.confirm_start, 2, 0, 1, 1) - self.auto_update = QtWidgets.QCheckBox(self.settings_group) - self.auto_update.setObjectName("auto_update") - self.behavior_layout.addWidget(self.auto_update, 1, 0, 1, 1) self.sys_tray = QtWidgets.QCheckBox(self.settings_group) self.sys_tray.setObjectName("sys_tray") self.behavior_layout.addWidget(self.sys_tray, 0, 0, 1, 1) + self.image_cache = QtWidgets.QCheckBox(self.settings_group) + self.image_cache.setObjectName("image_cache") + self.behavior_layout.addWidget(self.image_cache, 6, 0, 1, 1) self.rare_layout.addWidget(self.settings_group, 2, 0, 1, 1, QtCore.Qt.AlignTop) self.log_dir_group = QtWidgets.QGroupBox(RareSettings) self.log_dir_group.setObjectName("log_dir_group") @@ -128,12 +132,13 @@ class Ui_RareSettings(object): self.desktop_link.setText(_translate("RareSettings", "Create Desktop link")) self.startmenu_link.setText(_translate("RareSettings", "Create start menu link")) self.settings_group.setTitle(_translate("RareSettings", "Behavior")) - self.save_size.setText(_translate("RareSettings", "Restore window size on application startup")) self.notification.setText(_translate("RareSettings", "Show notification on download completion")) + self.auto_update.setText(_translate("RareSettings", "Update games on application startup")) + self.save_size.setText(_translate("RareSettings", "Restore window size on application startup")) self.auto_sync_cloud.setText(_translate("RareSettings", "Automatically sync with cloud")) self.confirm_start.setText(_translate("RareSettings", "Confirm game launch")) - self.auto_update.setText(_translate("RareSettings", "Update games on application startup")) self.sys_tray.setText(_translate("RareSettings", "Exit to System tray")) + self.image_cache.setText(_translate("RareSettings", "Cache images in store")) self.log_dir_group.setTitle(_translate("RareSettings", "Logs")) self.log_dir_open_button.setText(_translate("RareSettings", "Open Log directory")) self.log_dir_clean_button.setText(_translate("RareSettings", "Clean Log directory")) diff --git a/rare/ui/components/tabs/settings/rare.ui b/rare/ui/components/tabs/settings/rare.ui index 377f874c..6403c5bb 100644 --- a/rare/ui/components/tabs/settings/rare.ui +++ b/rare/ui/components/tabs/settings/rare.ui @@ -2,6 +2,14 @@ RareSettings + + + 0 + 0 + 544 + 532 + + RareSettings @@ -38,6 +46,20 @@ Behavior + + + + Show notification on download completion + + + + + + + Update games on application startup + + + @@ -58,13 +80,6 @@ - - - - Show notification on download completion - - - @@ -79,13 +94,6 @@ - - - - Update games on application startup - - - @@ -93,6 +101,13 @@ + + + + Cache images in store + + +