Some optimizations
This commit is contained in:
parent
2233c7f338
commit
983e80a4c6
|
@ -41,7 +41,7 @@ class Shop(QStackedWidget):
|
|||
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_info)
|
||||
self.shop.show_info.connect(self.show_search_results)
|
||||
self.shop.show_game.connect(self.show_game_info)
|
||||
self.browse_games.show_game.connect(self.show_game_info)
|
||||
|
||||
|
@ -55,6 +55,6 @@ class Shop(QStackedWidget):
|
|||
self.info.update_game(data)
|
||||
self.setCurrentIndex(2)
|
||||
|
||||
def show_info(self, data):
|
||||
self.search_results.show_results(data)
|
||||
def show_search_results(self, text: str):
|
||||
self.search_results.load_results(text)
|
||||
self.setCurrentIndex(1)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import random
|
||||
|
||||
from PyQt5.QtCore import QUrl, pyqtSignal, QJsonParseError, QJsonDocument
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QWidget, QCheckBox, QVBoxLayout, QLabel
|
||||
|
||||
from rare.components.tabs.shop.constants import game_query, Constants
|
||||
from rare.components.tabs.shop.game_widgets import GameWidget
|
||||
from rare.ui.components.tabs.store.browse_games import Ui_browse_games
|
||||
from rare.utils.extra_widgets import FlowLayout, WaitingSpinner
|
||||
from rare.utils.utils import get_lang
|
||||
from rare.utils.utils import get_lang, QtRequestManager
|
||||
|
||||
logger = logging.getLogger("BrowseGames")
|
||||
|
||||
|
@ -22,8 +20,6 @@ class BrowseGames(QWidget, Ui_browse_games):
|
|||
price = ""
|
||||
tags = []
|
||||
types = []
|
||||
request_active = False
|
||||
next_request = False
|
||||
|
||||
def __init__(self, path):
|
||||
super(BrowseGames, self).__init__()
|
||||
|
@ -32,7 +28,8 @@ class BrowseGames(QWidget, Ui_browse_games):
|
|||
self.games_widget = QWidget()
|
||||
self.games_widget.setLayout(FlowLayout())
|
||||
self.games.setWidget(self.games_widget)
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.manager = QtRequestManager("json")
|
||||
self.manager.data_ready.connect(self.show_games)
|
||||
|
||||
self.stack.addWidget(WaitingSpinner())
|
||||
|
||||
|
@ -85,10 +82,6 @@ class BrowseGames(QWidget, Ui_browse_games):
|
|||
if removed_type and removed_type in self.types:
|
||||
self.types.remove(removed_type)
|
||||
|
||||
if self.request_active:
|
||||
self.next_request = True
|
||||
return
|
||||
|
||||
locale = get_lang()
|
||||
self.stack.setCurrentIndex(2)
|
||||
date = f"[,{datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%dT%X')}.{str(random.randint(0, 999)).zfill(3)}Z]"
|
||||
|
@ -112,57 +105,26 @@ class BrowseGames(QWidget, Ui_browse_games):
|
|||
if self.types:
|
||||
payload["variables"]["category"] = "|".join(self.types)
|
||||
|
||||
request = QNetworkRequest(QUrl("https://www.epicgames.com/graphql"))
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
|
||||
self.request_active = True
|
||||
self.game_request = self.manager.post(request, json.dumps(payload).encode("utf-8"))
|
||||
self.game_request.finished.connect(self.show_games)
|
||||
self.manager.post("https://www.epicgames.com/graphql", payload)
|
||||
|
||||
def show_games(self):
|
||||
if self.game_request:
|
||||
if self.game_request.error() == QNetworkReply.NoError:
|
||||
error = QJsonParseError()
|
||||
json_data = QJsonDocument.fromJson(self.game_request.readAll().data(), error)
|
||||
def show_games(self, data):
|
||||
data = data["data"]["Catalog"]["searchStore"]["elements"]
|
||||
QWidget().setLayout(self.games_widget.layout())
|
||||
|
||||
if error.error == error.NoError:
|
||||
try:
|
||||
games = json.loads(json_data.toJson().data().decode())["data"]["Catalog"]["searchStore"][
|
||||
"elements"]
|
||||
except TypeError as e:
|
||||
logger.error("Type Error: " + str(e))
|
||||
self.stack.setCurrentIndex(1)
|
||||
else:
|
||||
QWidget().setLayout(self.games_widget.layout())
|
||||
if games:
|
||||
self.games_widget.setLayout(FlowLayout())
|
||||
if data:
|
||||
self.games_widget.setLayout(FlowLayout())
|
||||
|
||||
for game in games:
|
||||
w = GameWidget(self.path, game, 275)
|
||||
self.games_widget.layout().addWidget(w)
|
||||
w.show_info.connect(self.show_game.emit)
|
||||
for game in data:
|
||||
w = GameWidget(self.path, game, 275)
|
||||
self.games_widget.layout().addWidget(w)
|
||||
w.show_info.connect(self.show_game.emit)
|
||||
|
||||
else:
|
||||
self.games_widget.setLayout(QVBoxLayout())
|
||||
self.games_widget.layout().addWidget(
|
||||
QLabel(self.tr("Could not get games matching the filter")))
|
||||
self.games_widget.layout().addStretch(1)
|
||||
self.stack.setCurrentIndex(0)
|
||||
self.request_active = False
|
||||
if self.next_request:
|
||||
self.prepare_request()
|
||||
self.next_request = ()
|
||||
|
||||
return
|
||||
|
||||
else:
|
||||
logger.error(error.errorString())
|
||||
else:
|
||||
logger.error(self.game_request.errorString())
|
||||
if self.next_request:
|
||||
self.prepare_request()
|
||||
self.next_request = False
|
||||
else:
|
||||
self.stack.setCurrentIndex(1)
|
||||
self.games_widget.setLayout(QVBoxLayout())
|
||||
self.games_widget.layout().addWidget(
|
||||
QLabel(self.tr("Could not get games matching the filter")))
|
||||
self.games_widget.layout().addStretch(1)
|
||||
self.stack.setCurrentIndex(0)
|
||||
|
||||
|
||||
class CheckBox(QCheckBox):
|
||||
|
|
|
@ -72,3 +72,34 @@ game_query = "query searchStoreQuery($allowCountries: String, $category: String,
|
|||
"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 "
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import json
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtGui
|
||||
from PyQt5.QtCore import pyqtSignal, QUrl, QJsonParseError, QJsonDocument
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel
|
||||
|
||||
from rare.components.tabs.shop.constants import search_query
|
||||
from rare.utils.extra_widgets import ImageLabel
|
||||
from rare.utils.utils import get_lang
|
||||
from rare.utils.utils import get_lang, QtRequestManager
|
||||
|
||||
logger = logging.getLogger("GameWidgets")
|
||||
|
||||
|
@ -19,12 +19,11 @@ class GameWidget(QWidget):
|
|||
super(GameWidget, self).__init__()
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.width = width
|
||||
self.path = path
|
||||
if json_info:
|
||||
self.init_ui(json_info, path)
|
||||
self.path = path
|
||||
self.init_ui(json_info)
|
||||
|
||||
def init_ui(self, json_info, path):
|
||||
self.path = path
|
||||
def init_ui(self, json_info):
|
||||
self.layout = QVBoxLayout()
|
||||
self.image = ImageLabel()
|
||||
self.layout.addWidget(self.image)
|
||||
|
@ -58,69 +57,21 @@ class GameWidget(QWidget):
|
|||
@classmethod
|
||||
def from_request(cls, name, path):
|
||||
c = cls(path)
|
||||
c.manager = QNetworkAccessManager()
|
||||
c.request = c.manager.get(QNetworkRequest())
|
||||
|
||||
c.manager = QtRequestManager("json")
|
||||
c.manager.data_ready.connect(c.handle_response)
|
||||
locale = get_lang()
|
||||
payload = json.dumps({
|
||||
"query": query,
|
||||
payload = {
|
||||
"query": search_query,
|
||||
"variables": {"category": "games/edition/base|bundles/games|editors|software/edition/base", "count": 1,
|
||||
"country": "DE", "keywords": name, "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")
|
||||
c.search_request = c.manager.post(request, payload)
|
||||
c.search_request.finished.connect(lambda: c.handle_response(path))
|
||||
}
|
||||
c.manager.post("https://www.epicgames.com/graphql", payload)
|
||||
c.search_request.da.connect(lambda: c.handle_response(path))
|
||||
return c
|
||||
|
||||
def handle_response(self, path):
|
||||
if self.search_request:
|
||||
if self.search_request.error() == QNetworkReply.NoError:
|
||||
error = QJsonParseError()
|
||||
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"][0]
|
||||
self.init_ui(data, path)
|
||||
else:
|
||||
logging.error(error.errorString())
|
||||
return
|
||||
def handle_response(self, data):
|
||||
|
||||
else:
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
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 "
|
||||
data = data["data"]["Catalog"]["searchStore"]["elements"][0]
|
||||
self.init_ui(data)
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
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
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QScrollArea, QGroupBox, QPushButton, \
|
||||
QStackedWidget
|
||||
|
||||
from rare.utils.extra_widgets import ImageLabel, FlowLayout
|
||||
from rare.components.tabs.shop.constants import search_query
|
||||
from rare.utils.extra_widgets import ImageLabel, FlowLayout, WaitingSpinner
|
||||
from rare.utils.utils import QtRequestManager, get_lang
|
||||
|
||||
|
||||
class SearchResults(QWidget):
|
||||
class SearchResults(QStackedWidget):
|
||||
show_info = pyqtSignal(dict)
|
||||
|
||||
def __init__(self):
|
||||
super(SearchResults, self).__init__()
|
||||
self.search_result_widget = QWidget()
|
||||
self.addWidget(self.search_result_widget)
|
||||
self.main_layout = QVBoxLayout()
|
||||
self.back_button = QPushButton(self.tr("Back"))
|
||||
self.main_layout.addWidget(self.back_button)
|
||||
|
@ -25,9 +30,30 @@ class SearchResults(QWidget):
|
|||
self.layout = FlowLayout()
|
||||
self.widget.setLayout(self.layout)
|
||||
|
||||
self.setLayout(self.main_layout)
|
||||
self.search_manager = QtRequestManager("json")
|
||||
self.search_manager.data_ready.connect(self.show_results)
|
||||
|
||||
def show_results(self, results: list):
|
||||
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 != "":
|
||||
locale = get_lang()
|
||||
payload = {
|
||||
"query": search_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}
|
||||
}
|
||||
self.search_manager.post("https://www.epicgames.com/graphql", payload)
|
||||
|
||||
def show_results(self, results: dict):
|
||||
results = results["data"]["Catalog"]["searchStore"]["elements"]
|
||||
QVBoxLayout().addWidget(self.widget)
|
||||
self.widget = QWidget()
|
||||
self.layout = FlowLayout()
|
||||
|
@ -40,6 +66,7 @@ class SearchResults(QWidget):
|
|||
self.layout.addWidget(w)
|
||||
self.widget.setLayout(self.layout)
|
||||
self.result_area.setWidget(self.widget)
|
||||
self.setCurrentIndex(0)
|
||||
|
||||
|
||||
class _SearchResultItem(QGroupBox):
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
import json
|
||||
import logging
|
||||
import webbrowser
|
||||
|
||||
from PyQt5.QtCore import QUrl, QJsonDocument, QJsonParseError
|
||||
from PyQt5.QtGui import QPixmap, QFont
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from PyQt5.QtWidgets import QWidget, QLabel
|
||||
|
||||
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
|
||||
from rare.utils.utils import get_lang, QtRequestManager
|
||||
|
||||
logger = logging.getLogger("ShopInfo")
|
||||
|
||||
|
@ -28,7 +25,8 @@ class ShopGameInfo(QWidget, Ui_shop_info):
|
|||
self.image = ImageLabel()
|
||||
self.image_stack.addWidget(self.image)
|
||||
self.image_stack.addWidget(WaitingSpinner())
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.manager = QtRequestManager("json")
|
||||
self.manager.data_ready.connect(self.data_received)
|
||||
|
||||
def update_game(self, data: dict):
|
||||
self.image_stack.setCurrentIndex(1)
|
||||
|
@ -60,25 +58,9 @@ class ShopGameInfo(QWidget, Ui_shop_info):
|
|||
locale = get_lang()
|
||||
url = f"https://store-content.ak.epicgames.com/api/{locale}/content/{'products' if not is_bundle else 'bundles'}/{slug}"
|
||||
# game = api_utils.get_product(slug, locale)
|
||||
self.request = self.manager.get(QNetworkRequest(QUrl(url)))
|
||||
self.request.finished.connect(self.data_received)
|
||||
self.manager.get(url)
|
||||
|
||||
def data_received(self):
|
||||
if self.request:
|
||||
if self.request.error() == QNetworkReply.NoError:
|
||||
error = QJsonParseError()
|
||||
json_data = QJsonDocument.fromJson(self.request.readAll().data(), error)
|
||||
|
||||
if error.error == error.NoError:
|
||||
game = json.loads(json_data.toJson().data().decode())
|
||||
else:
|
||||
logging.info(self.slug, error.errorString())
|
||||
return
|
||||
else:
|
||||
logger.error("Data failed")
|
||||
return
|
||||
else:
|
||||
return
|
||||
def data_received(self, game):
|
||||
self.game = ShopGame.from_json(game, self.data)
|
||||
self.title.setText(self.game.title)
|
||||
self.price.setFont(QFont())
|
||||
|
@ -133,7 +115,6 @@ class ShopGameInfo(QWidget, Ui_shop_info):
|
|||
pass
|
||||
self.tags.setText(", ".join(self.game.tags))
|
||||
# self.price.setText(self.game.price)
|
||||
self.request.deleteLater()
|
||||
|
||||
def button_clicked(self):
|
||||
webbrowser.open("https://www.epicgames.com/store/de/p/" + self.slug)
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
import datetime
|
||||
import json
|
||||
import logging
|
||||
from json import JSONDecodeError
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, QUrl, QJsonDocument, QJsonParseError, \
|
||||
QStringListModel
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, QStringListModel
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
from PyQt5.QtWidgets import QWidget, QCompleter, QGroupBox, QHBoxLayout, QScrollArea
|
||||
|
||||
from rare.components.tabs.shop.constants import search_query
|
||||
from rare.components.tabs.shop.game_widgets import GameWidget
|
||||
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
|
||||
from rare.utils.utils import QtRequestManager, get_lang
|
||||
|
||||
logger = logging.getLogger("Shop")
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit,PyBroadException
|
||||
class ShopWidget(QScrollArea, Ui_ShopWidget):
|
||||
show_info = pyqtSignal(list)
|
||||
show_info = pyqtSignal(str)
|
||||
show_game = pyqtSignal(dict)
|
||||
free_game_widgets = []
|
||||
active_search_request = False
|
||||
|
@ -49,31 +47,40 @@ class ShopWidget(QScrollArea, Ui_ShopWidget):
|
|||
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Games"))
|
||||
self.scrollAreaWidgetContents.layout().insertWidget(0, self.search_bar)
|
||||
|
||||
self.search_bar.textChanged.connect(self.search_games)
|
||||
# self.search_bar.textChanged.connect(self.search_games)
|
||||
|
||||
self.search_bar.setCompleter(self.completer)
|
||||
self.search_bar.returnPressed.connect(self.show_search_result)
|
||||
self.search_bar.buttonClicked.connect(self.show_search_result)
|
||||
self.search_bar.returnPressed.connect(self.show_search_results)
|
||||
self.search_bar.buttonClicked.connect(self.show_search_results)
|
||||
|
||||
self.games_groupbox.setLayout(FlowLayout())
|
||||
self.games_groupbox.setVisible(False)
|
||||
|
||||
self.search_request_manager = QtRequestManager("json")
|
||||
self.search_request_manager.data_ready.connect(self.set_completer)
|
||||
|
||||
self.search_bar.textChanged.connect(self.load_completer)
|
||||
|
||||
def load_completer(self, text):
|
||||
if text != "":
|
||||
locale = get_lang()
|
||||
payload = {
|
||||
"query": search_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}
|
||||
}
|
||||
self.search_request_manager.post("https://www.epicgames.com/graphql", payload)
|
||||
|
||||
def load(self):
|
||||
url = "https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions"
|
||||
self.free_game_request = self.manager.get(QNetworkRequest(QUrl(url)))
|
||||
self.free_game_request.finished.connect(self.add_free_games)
|
||||
self.free_game_request_manager = QtRequestManager("json")
|
||||
self.free_game_request_manager.get(url)
|
||||
self.free_game_request_manager.data_ready.connect(self.add_free_games)
|
||||
|
||||
def add_free_games(self):
|
||||
if self.free_game_request:
|
||||
if self.free_game_request.error() == QNetworkReply.NoError:
|
||||
try:
|
||||
free_games = json.loads(self.free_game_request.readAll().data().decode())
|
||||
except JSONDecodeError:
|
||||
return
|
||||
else:
|
||||
return
|
||||
else:
|
||||
return
|
||||
def add_free_games(self, free_games):
|
||||
free_games = free_games["data"]["Catalog"]["searchStore"]["elements"]
|
||||
date = datetime.datetime.now()
|
||||
free_games_now = []
|
||||
|
@ -132,100 +139,13 @@ class ShopWidget(QScrollArea, Ui_ShopWidget):
|
|||
self.coming_free_games.layout().addStretch(1)
|
||||
# self.coming_free_games.setFixedWidth(int(40 + len(coming_free_games) * 300))
|
||||
self.free_games_stack.setCurrentIndex(1)
|
||||
self.free_game_request.deleteLater()
|
||||
|
||||
def search_games(self, text, show_direct=False):
|
||||
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))
|
||||
self.active_search_request = True
|
||||
def set_completer(self, search_data):
|
||||
search_data = search_data["data"]["Catalog"]["searchStore"]["elements"]
|
||||
titles = [i.get("title") for i in search_data]
|
||||
model = QStringListModel()
|
||||
model.setStringList(titles)
|
||||
self.completer.setModel(model)
|
||||
|
||||
else:
|
||||
self.next_search = text
|
||||
|
||||
def show_search_results(self, show_direct=False):
|
||||
self.active_search_request = False
|
||||
if self.search_request:
|
||||
try:
|
||||
if self.search_request.error() == QNetworkReply.NoError:
|
||||
error = QJsonParseError()
|
||||
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)
|
||||
else:
|
||||
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())
|
||||
# response = .decode(encoding="utf-8")
|
||||
# print(response)
|
||||
# results = json.loads(response)
|
||||
except RuntimeError:
|
||||
return
|
||||
if self.next_search:
|
||||
self.search_games(self.next_search)
|
||||
self.next_search = ""
|
||||
|
||||
def show_search_result(self, show_direct=False):
|
||||
if not show_direct:
|
||||
self.show_info.emit(self.data)
|
||||
else:
|
||||
try:
|
||||
result = self.data[0]
|
||||
except IndexError:
|
||||
print("error")
|
||||
return
|
||||
self.show_game.emit(result)
|
||||
|
||||
|
||||
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 "
|
||||
def show_search_results(self):
|
||||
self.show_info.emit(self.search_bar.text())
|
||||
|
|
|
@ -3,15 +3,15 @@ import os
|
|||
from logging import getLogger
|
||||
|
||||
from PIL import Image
|
||||
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal, QUrl, QSettings
|
||||
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal, QSettings
|
||||
from PyQt5.QtGui import QMovie, QPixmap
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, QHBoxLayout, QWidget, QPushButton, \
|
||||
QStyleOptionTab, QStylePainter, QTabBar, QLineEdit, QToolButton
|
||||
from qtawesome import icon
|
||||
|
||||
from rare import style_path
|
||||
from rare.ui.utils.pathedit import Ui_PathEdit
|
||||
from rare.utils.utils import QtRequestManager
|
||||
|
||||
logger = getLogger("ExtraWidgets")
|
||||
|
||||
|
@ -266,7 +266,8 @@ class ImageLabel(QLabel):
|
|||
if p := os.environ.get("XDG_CACHE_HOME"):
|
||||
path = os.path.join(p, "rare", "cache")
|
||||
self.path = path
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.manager = QtRequestManager("bytes")
|
||||
self.manager.data_ready.connect(self.image_ready)
|
||||
|
||||
def update_image(self, url, name, size: tuple = (240, 320)):
|
||||
self.setFixedSize(*size)
|
||||
|
@ -280,32 +281,26 @@ class ImageLabel(QLabel):
|
|||
name_extension = "tall"
|
||||
self.name = f"{self.name}_{name_extension}.png"
|
||||
if not os.path.exists(os.path.join(self.path, self.name)):
|
||||
self.request = self.manager.get(QNetworkRequest(QUrl(url)))
|
||||
self.request.finished.connect(self.image_ready)
|
||||
self.manager.get(url)
|
||||
# self.request.finished.connect(self.image_ready)
|
||||
else:
|
||||
self.show_image()
|
||||
|
||||
def image_ready(self):
|
||||
def image_ready(self, data):
|
||||
self.setPixmap(QPixmap())
|
||||
if self.request:
|
||||
if self.request.error() == QNetworkReply.NoError:
|
||||
data = self.request.readAll().data()
|
||||
image: Image.Image = Image.open(io.BytesIO(data))
|
||||
image = image.resize((self.img_size[0], self.img_size[1]))
|
||||
|
||||
if QSettings().value("cache_images", True, 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)
|
||||
else:
|
||||
logger.error(self.request.errorString())
|
||||
else:
|
||||
return
|
||||
image: Image.Image = Image.open(io.BytesIO(data))
|
||||
image = image.resize((self.img_size[0], self.img_size[1]))
|
||||
|
||||
if QSettings().value("cache_images", True, 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,
|
||||
|
|
|
@ -6,8 +6,9 @@ from logging import getLogger
|
|||
|
||||
import requests
|
||||
from PIL import Image, UnidentifiedImageError
|
||||
from PyQt5.QtCore import pyqtSignal, QLocale, QSettings
|
||||
from PyQt5.QtCore import pyqtSignal, QLocale, QSettings, QObject, QUrl, QJsonParseError, QJsonDocument
|
||||
from PyQt5.QtGui import QPalette, QColor
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
|
||||
# Windows
|
||||
if os.name == "nt":
|
||||
|
@ -336,3 +337,85 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
|
|||
shortcut.IconLocation = os.path.join(icon + ".ico")
|
||||
|
||||
shortcut.save()
|
||||
|
||||
|
||||
class QtRequestManager(QObject):
|
||||
data_ready = pyqtSignal(object)
|
||||
request = None
|
||||
request_active = False
|
||||
|
||||
def __init__(self, type: str = "json", queue=False):
|
||||
super(QtRequestManager, self).__init__()
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.type = type
|
||||
self.queue = queue
|
||||
if self.queue:
|
||||
self.next_request = []
|
||||
else:
|
||||
self.next_request = ["", tuple(())]
|
||||
|
||||
def post(self, url: str, payload: dict):
|
||||
if not self.request_active:
|
||||
request = QNetworkRequest(QUrl(url))
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
|
||||
|
||||
payload = json.dumps(payload).encode("utf-8")
|
||||
|
||||
self.request = self.manager.post(request, payload)
|
||||
self.request_active = True
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
|
||||
else:
|
||||
if self.queue:
|
||||
self.next_request.append(["post", (url, payload)])
|
||||
else:
|
||||
self.next_request = ["post", (url, payload)]
|
||||
|
||||
def get(self, url: str):
|
||||
if not self.request_active:
|
||||
self.request_active = True
|
||||
self.request = self.manager.get(QNetworkRequest(QUrl(url)))
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
else:
|
||||
if self.queue:
|
||||
self.next_request.append(["get", (url,)])
|
||||
else:
|
||||
self.next_request = ["get", (url,)]
|
||||
|
||||
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.data_ready.emit(data)
|
||||
self.request.deleteLater()
|
||||
|
||||
if self.queue:
|
||||
if self.next_request:
|
||||
if self.next_request[0][0] == "post":
|
||||
self.post(*self.next_request[0][1])
|
||||
else:
|
||||
self.get(self.next_request[0][1][0])
|
||||
self.next_request.pop(0)
|
||||
else:
|
||||
if method := self.next_request[0]:
|
||||
if method == "post":
|
||||
self.post(*self.next_request[1])
|
||||
self.next_request = ["", ()]
|
||||
else:
|
||||
self.get(self.next_request[1][0])
|
||||
self.next_request = ["", ()]
|
||||
|
|
Loading…
Reference in a new issue