1
0
Fork 0
mirror of synced 2024-09-28 15:31:14 +12:00

Add basic store

This commit is contained in:
Dummerle 2021-06-03 23:23:55 +02:00
parent 7b44b91b72
commit b31080a5ae
14 changed files with 704 additions and 13 deletions

View file

@ -144,3 +144,39 @@ class VerifyResult(Enum):
HASH_MISMATCH = 1 HASH_MISMATCH = 1
FILE_MISSING = 2 FILE_MISSING = 2
OTHER_ERROR = 3 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}}]}]}}

View file

@ -13,6 +13,7 @@ from rare.components.tabs.cloud_saves import SyncSaves
from rare.components.tabs.downloads import DownloadTab from rare.components.tabs.downloads import DownloadTab
from rare.components.tabs.games import GameTab from rare.components.tabs.games import GameTab
from rare.components.tabs.settings import SettingsTab from rare.components.tabs.settings import SettingsTab
from rare.components.tabs.shop import Shop
from rare.utils import legendary_utils from rare.utils import legendary_utils
from rare.utils.models import InstallQueueItemModel, InstallOptionsModel from rare.utils.models import InstallQueueItemModel, InstallOptionsModel
@ -22,7 +23,7 @@ class TabWidget(QTabWidget):
def __init__(self, core: LegendaryCore, parent, offline): def __init__(self, core: LegendaryCore, parent, offline):
super(TabWidget, self).__init__(parent=parent) 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.core = core
self.setTabBar(TabBar(disabled_tab)) self.setTabBar(TabBar(disabled_tab))
@ -38,6 +39,9 @@ class TabWidget(QTabWidget):
self.cloud_saves = SyncSaves(core, self) self.cloud_saves = SyncSaves(core, self)
self.addTab(self.cloud_saves, "Cloud Saves") self.addTab(self.cloud_saves, "Cloud Saves")
self.store = Shop()
self.addTab(self.store, self.tr("Store"))
self.settings = SettingsTab(core, self) self.settings = SettingsTab(core, self)
# Space Tab # Space Tab
@ -92,9 +96,15 @@ class TabWidget(QTabWidget):
self.games_tab.default_widget.game_list.game_exited.connect(self.game_finished) self.games_tab.default_widget.game_list.game_exited.connect(self.game_finished)
# Open game list on click on Games tab button # 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)) self.setIconSize(QSize(25, 25))
def mouse_clicked(self, tab_num):
if tab_num == 0:
self.games_tab.layout.setCurrentIndex(0)
if tab_num == 3:
self.store.load()
def install_game(self, app_name, disable_path=False): def install_game(self, app_name, disable_path=False):
install_dialog = InstallDialog(self.core, install_dialog = InstallDialog(self.core,
InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)), InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)),

View file

@ -8,7 +8,6 @@ from qtawesome import icon
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import InstalledGame from custom_legendary.models.game import InstalledGame
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
from rare.utils.extra_widgets import ClickableLabel
logger = getLogger("GameWidgetInstalled") logger = getLogger("GameWidgetInstalled")
@ -36,7 +35,7 @@ class GameWidgetInstalled(BaseInstalledWidget):
if self.pixmap: if self.pixmap:
w = 200 w = 200
self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation) self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation)
self.image = ClickableLabel() self.image = QLabel()
self.image.setObjectName("game_widget") self.image.setObjectName("game_widget")
self.image.setPixmap(self.pixmap) self.image.setPixmap(self.pixmap)
self.layout.addWidget(self.image) self.layout.addWidget(self.image)

View file

@ -5,7 +5,6 @@ from PyQt5.QtWidgets import QVBoxLayout, QLabel
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import Game from custom_legendary.models.game import Game
from rare.components.tabs.games.game_widgets.base_uninstalled_widget import BaseUninstalledWidget from rare.components.tabs.games.game_widgets.base_uninstalled_widget import BaseUninstalledWidget
from rare.utils.extra_widgets import ClickableLabel
logger = getLogger("Uninstalled") logger = getLogger("Uninstalled")
@ -19,7 +18,7 @@ class IconWidgetUninstalled(BaseUninstalledWidget):
if self.pixmap: if self.pixmap:
w = 200 w = 200
self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3)) self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3))
self.image = ClickableLabel() self.image = QLabel()
self.image.setPixmap(self.pixmap) self.image.setPixmap(self.pixmap)
self.layout.addWidget(self.image) self.layout.addWidget(self.image)

View file

@ -0,0 +1,28 @@
from PyQt5.QtWidgets import QStackedWidget, QWidget, QVBoxLayout, QLabel
from rare.components.tabs.shop.shop_info import ShopGameInfo
from rare.components.tabs.shop.shop_widget import ShopWidget
class Shop(QStackedWidget):
init = False
def __init__(self):
super(Shop, self).__init__()
self.shop = ShopWidget()
self.addWidget(self.shop)
self.info = ShopGameInfo()
self.addWidget(self.info)
self.shop.show_info.connect(self.show_info)
def load(self):
if not self.init:
self.init = True
self.shop.load()
def show_info(self, slug):
self.info.update_game(slug)
self.setCurrentIndex(1)

View file

@ -0,0 +1,35 @@
import os
import webbrowser
from PyQt5.QtCore import QLocale, Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtNetwork import QNetworkAccessManager
from PyQt5.QtWidgets import QWidget
from rare.ui.components.tabs.store.shop_game_info import Ui_shop_info
from rare.utils import api_utils
class ShopGameInfo(QWidget, Ui_shop_info):
slug = ""
def __init__(self):
super(ShopGameInfo, self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.button_clicked)
self.manager = QNetworkAccessManager()
def update_game(self, slug: str):
locale = QLocale.system().name().split("_")[0]
game = api_utils.get_product(slug, locale)
self.slug = slug
self.title.setText(game[0]["productName"])
self.image.setPixmap(
QPixmap(os.path.expanduser(f"~/.cache/rare/cache/{game[0]['productName']}.png")).scaled(180,
int(180 * 9 / 16),
transformMode=Qt.SmoothTransformation))
self.dev.setText(game[0]["data"]["meta"]["developer"][0])
def button_clicked(self):
webbrowser.open("https://www.epicgames.com/store/de/p/" + self.slug)

View file

@ -0,0 +1,209 @@
import datetime
import json
import logging
import os
from json import JSONDecodeError
import requests
from PyQt5 import QtGui
from PyQt5.QtCore import Qt, pyqtSignal, QUrl, QByteArray, QJsonDocument, QJsonParseError, QObjectCleanupHandler, \
QStringListModel
from PyQt5.QtGui import QPixmap
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout, QCompleter
from rare.ui.components.tabs.store.store import Ui_ShopWidget
from rare.utils.extra_widgets import WaitingSpinner
from rare.utils.utils import get_lang
class ShopWidget(QWidget, Ui_ShopWidget):
show_info = pyqtSignal(str)
free_game_widgets = []
def __init__(self):
super(ShopWidget, self).__init__()
self.setupUi(self)
self.search_results.setVisible(False)
self.manager = QNetworkAccessManager()
self.free_games_stack.addWidget(WaitingSpinner())
self.free_games_stack.setCurrentIndex(1)
self.search.textChanged.connect(self.search_games)
self.completer = QCompleter()
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.search.setCompleter(self.completer)
self.search.returnPressed.connect(self.show_game)
self.data = []
def load(self):
if not os.path.exists(p := os.path.expanduser(f"~/.cache/rare/cache/")):
os.makedirs(p)
url = "https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions"
self.free_game_request = self.manager.get(QNetworkRequest(QUrl(url)))
self.free_game_request.readyRead.connect(self.add_free_games)
self.free_game_request.finished.connect(self.free_game_request.deleteLater if self.free_game_request else None)
# free_games = api_utils.get_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:
print(self.free_game_request.readAll().data().decode())
return
else:
return
else:
return
free_games = free_games["data"]["Catalog"]["searchStore"]["elements"]
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
end_date = datetime.datetime.strptime(
game["promotions"].get("promotionalOffers", game["promotions"].get("upcomingPromotionalOffers"))[0]["promotionalOffers"][0]["endDate"],
'%Y-%m-%dT%H:%M:%S.%fZ')
start_date = datetime.datetime.strptime(
game["promotions"].get("promotionalOffers", game["promotions"].get("upcomingPromotionalOffers"))[0][
"promotionalOffers"][0]["startDate"],
'%Y-%m-%dT%H:%M:%S.%fZ')
except IndexError:
print("index error")
continue
except KeyError:
print("keyerror")
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)
for free_game in free_games_now:
w = GameWidget(free_game)
w.show_info.connect(self.show_info)
self.free_game_now.layout().addWidget(w)
self.free_game_widgets.append(w)
self.free_game_group_box_2.setMinimumHeight(200)
for free_game in coming_free_games:
w = GameWidget(free_game)
if free_game["title"] != "Mystery Game":
w.show_info.connect(self.show_info)
self.comming_free_game.layout().addWidget(w)
self.free_game_widgets.append(w)
self.free_games_stack.setCurrentIndex(0)
def search_games(self, text):
if text == "":
self.search_results.setVisible(False)
else:
locale = get_lang()
payload = QByteArray()
payload.append(
"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")
payload = json.dumps({
"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",
"variables": {"category": "games/edition/base|bundles/games|editors|software/edition/base", "count": 10,
"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 = self.manager.post(QNetworkRequest(QUrl("https://www.epicgames.com/graphql")), payload)
self.search_request.readyRead.connect(self.show_search_results)
self.search_request.finished.connect(
self.search_request.deleteLater if self.search_request else None)
def show_search_results(self):
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"]
else:
logging.error(error.errorString())
self.search_results.setVisible(False)
return
#response = .decode(encoding="utf-8")
#print(response)
#results = json.loads(response)
else:
return
else:
return
self.data = data
titles = [i.get("title") for i in data]
model = QStringListModel()
model.setStringList(titles)
self.completer.setModel(model)
self.completer.popup()
# self.search_results.setLayout(layout)
# self.search_results.setVisible(True)
def show_game(self):
if self.data:
slug = self.data[0].get("productSlug")
self.show_info.emit(slug)
class SearchResultItem(QWidget):
def __init__(self, json_info):
super(SearchResultItem, self).__init__()
self.layout = QHBoxLayout()
self.title = QLabel(json_info.get("title", "undefined"))
self.layout.addWidget(self.title)
self.slug = json_info.get("productSlug", "undefined")
self.setLayout(self.layout)
class GameWidget(QWidget):
show_info = pyqtSignal(str)
def __init__(self, json_info):
super(GameWidget, self).__init__()
self.layout = QVBoxLayout()
self.image = QLabel()
self.slug = json_info["productSlug"]
if not os.path.exists(path := os.path.expanduser(f"~/.cache/rare/cache/{json_info['title']}.png")):
for img in json_info["keyImages"]:
if json_info["title"] != "Mystery Game":
if img["type"] == "DieselStoreFrontWide":
with open(path, "wb") as img_file:
content = requests.get(img["url"]).content
img_file.write(content)
break
else:
if img["type"] == "VaultClosed":
with open(path, "wb") as img_file:
content = requests.get(img["url"]).content
img_file.write(content)
break
else:
print("No image found")
width = 300
self.image.setPixmap(QPixmap(os.path.expanduser(f"~/.cache/rare/cache/{json_info['title']}.png"))
.scaled(width, int(width * 9 / 16), transformMode=Qt.SmoothTransformation))
self.layout.addWidget(self.image)
self.title = QLabel(json_info["title"])
self.layout.addWidget(self.title)
self.setLayout(self.layout)
def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
self.show_info.emit(self.slug)

View file

@ -0,0 +1,61 @@
# -*- 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.gridLayout = QtWidgets.QGridLayout(shop_info)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(shop_info)
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 3, 1, 1, 1)
self.price = QtWidgets.QLabel(shop_info)
self.price.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.price.setObjectName("price")
self.gridLayout.addWidget(self.price, 1, 1, 1, 1)
self.title = QtWidgets.QLabel(shop_info)
self.title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.title.setObjectName("title")
self.gridLayout.addWidget(self.title, 0, 1, 1, 1)
self.image = QtWidgets.QLabel(shop_info)
self.image.setObjectName("image")
self.gridLayout.addWidget(self.image, 0, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 4, 1, 1, 1)
self.dev = QtWidgets.QLabel(shop_info)
self.dev.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.dev.setObjectName("dev")
self.gridLayout.addWidget(self.dev, 2, 1, 1, 1)
self.retranslateUi(shop_info)
QtCore.QMetaObject.connectSlotsByName(shop_info)
def retranslateUi(self, shop_info):
_translate = QtCore.QCoreApplication.translate
shop_info.setWindowTitle(_translate("shop_info", "Form"))
self.pushButton.setText(_translate("shop_info", "Buy Game in Epic Games Store"))
self.price.setText(_translate("shop_info", "TextLabel"))
self.title.setText(_translate("shop_info", "Error"))
self.image.setText(_translate("shop_info", "TextLabel"))
self.dev.setText(_translate("shop_info", "TextLabel"))
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_())

View file

@ -0,0 +1,78 @@
<?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="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Buy Game in Epic Games Store</string>
</property>
</widget>
</item>
<item row="1" column="1">
<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 row="0" column="1">
<widget class="QLabel" name="title">
<property name="text">
<string>Error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="image">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="dev">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,80 @@
# -*- 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, QtGui, QtWidgets
class Ui_ShopWidget(object):
def setupUi(self, ShopWidget):
ShopWidget.setObjectName("ShopWidget")
ShopWidget.resize(697, 362)
self.verticalLayout = QtWidgets.QVBoxLayout(ShopWidget)
self.verticalLayout.setObjectName("verticalLayout")
self.search = QtWidgets.QLineEdit(ShopWidget)
self.search.setObjectName("search")
self.verticalLayout.addWidget(self.search)
self.search_results = QtWidgets.QGroupBox(ShopWidget)
self.search_results.setFlat(False)
self.search_results.setObjectName("search_results")
self.verticalLayout.addWidget(self.search_results)
self.free_game_group_box_2 = QtWidgets.QGroupBox(ShopWidget)
self.free_game_group_box_2.setObjectName("free_game_group_box_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.free_game_group_box_2)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.free_games_stack = QtWidgets.QStackedWidget(self.free_game_group_box_2)
self.free_games_stack.setObjectName("free_games_stack")
self.free_games_page = QtWidgets.QWidget()
self.free_games_page.setObjectName("free_games_page")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.free_games_page)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.free_game_now = QtWidgets.QGroupBox(self.free_games_page)
self.free_game_now.setObjectName("free_game_now")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.free_game_now)
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_3.addWidget(self.free_game_now)
self.comming_free_game = QtWidgets.QGroupBox(self.free_games_page)
self.comming_free_game.setObjectName("comming_free_game")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.comming_free_game)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout_3.addWidget(self.comming_free_game)
self.free_games_stack.addWidget(self.free_games_page)
self.verticalLayout_2.addWidget(self.free_games_stack)
self.verticalLayout.addWidget(self.free_game_group_box_2)
self.games_groupbox_2 = QtWidgets.QGroupBox(ShopWidget)
self.games_groupbox_2.setObjectName("games_groupbox_2")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.games_groupbox_2)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.verticalLayout.addWidget(self.games_groupbox_2)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.retranslateUi(ShopWidget)
self.free_games_stack.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(ShopWidget)
def retranslateUi(self, ShopWidget):
_translate = QtCore.QCoreApplication.translate
ShopWidget.setWindowTitle(_translate("ShopWidget", "Form"))
self.search.setPlaceholderText(_translate("ShopWidget", "Search Games"))
self.search_results.setTitle(_translate("ShopWidget", "Search results"))
self.free_game_group_box_2.setTitle(_translate("ShopWidget", "Free Games"))
self.free_game_now.setTitle(_translate("ShopWidget", "Free Game"))
self.comming_free_game.setTitle(_translate("ShopWidget", "Comming Free Game"))
self.games_groupbox_2.setTitle(_translate("ShopWidget", "Other nice games"))
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_())

View file

@ -0,0 +1,95 @@
<?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>697</width>
<height>362</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="search">
<property name="placeholderText">
<string>Search Games</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="search_results">
<property name="title">
<string>Search results</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="free_game_group_box_2">
<property name="title">
<string>Free Games</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QStackedWidget" name="free_games_stack">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="free_games_page">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QGroupBox" name="free_game_now">
<property name="title">
<string>Free Game</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="comming_free_game">
<property name="title">
<string>Comming Free Game</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="games_groupbox_2">
<property name="title">
<string>Other nice games</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7"/>
</widget>
</item>
<item>
<spacer name="spacer">
<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>

View file

@ -114,13 +114,6 @@ class FlowLayout(QLayout):
return parent.spacing() return parent.spacing()
class ClickableLabel(QLabel):
clicked = pyqtSignal()
def __init__(self):
super(ClickableLabel, self).__init__()
class PathEdit(QWidget, Ui_PathEdit): class PathEdit(QWidget, Ui_PathEdit):
def __init__(self, def __init__(self,
text: str = "", text: str = "",

View file

@ -34,3 +34,51 @@ class InstallQueueItemModel:
def __bool__(self): def __bool__(self):
return (self.status_q is not None) and (self.download is not None) and (self.options is not None) return (self.status_q is not None) and (self.download is not None) and (self.options is not None)
class ShopGame:
# TODO: Copyrights etc
def __init__(self, title: str = "", image_urls: dict = None, social_links: dict = None,
langs: list = None, reqs: list = None, publisher: str = "", developer: 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 # {"Betriebssystem":win7, processor:i9 9900k, ram...}; Note: name from language
self.publisher = publisher
self.developer = developer
@classmethod
def from_json(cls, data: dict):
if isinstance(data, list):
for product in data:
if product["_title"] == "home":
data = product
break
tmp = cls()
tmp.title = data.get("productName", "undefined")
tmp.img_urls = {
"DieselImage": data["data"]["about"]["image"]["src"],
"banner": data["data"]["hero"]["backgroundImageUrl"]
}
links = 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 = data["data"]["requirements"]["languages"]
tmp.reqs = {}
for system in data["data"]["requirements"]["systems"]:
tmp.reqs[system] = {}
for i in system:
tmp.reqs[i[system]["title"]] = tuple((i[system]["minimum"], i[system]["recommend"]))
tmp.publisher = data["data"]["meta"].get("publisher", "undefined")
tmp.developer = data["data"]["meta"].get("developer", "undefined")
return tmp

20
test.py Normal file
View file

@ -0,0 +1,20 @@
import sys
from PyQt5.QtCore import Qt, QStringListModel
from PyQt5.QtWidgets import QApplication, QCompleter, QLineEdit
def get_data(model):
model.setStringList(["completion", "data", "goes", "here"])
if __name__ == "__main__":
app = QApplication(sys.argv)
edit = QLineEdit()
completer = QCompleter()
edit.setCompleter(completer)
model = QStringListModel()
completer.setModel(model)
get_data(model)
edit.show()
sys.exit(app.exec_())