1
0
Fork 0
mirror of synced 2024-06-21 12:00:25 +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
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}}]}]}}

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.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
@ -22,7 +23,7 @@ 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))
@ -38,6 +39,9 @@ class TabWidget(QTabWidget):
self.cloud_saves = SyncSaves(core, self)
self.addTab(self.cloud_saves, "Cloud Saves")
self.store = Shop()
self.addTab(self.store, self.tr("Store"))
self.settings = SettingsTab(core, self)
# Space Tab
@ -92,9 +96,15 @@ 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))
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):
install_dialog = InstallDialog(self.core,
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.models.game import InstalledGame
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
from rare.utils.extra_widgets import ClickableLabel
logger = getLogger("GameWidgetInstalled")
@ -36,7 +35,7 @@ class GameWidgetInstalled(BaseInstalledWidget):
if self.pixmap:
w = 200
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.setPixmap(self.pixmap)
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.models.game import Game
from rare.components.tabs.games.game_widgets.base_uninstalled_widget import BaseUninstalledWidget
from rare.utils.extra_widgets import ClickableLabel
logger = getLogger("Uninstalled")
@ -19,7 +18,7 @@ class IconWidgetUninstalled(BaseUninstalledWidget):
if self.pixmap:
w = 200
self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3))
self.image = ClickableLabel()
self.image = QLabel()
self.image.setPixmap(self.pixmap)
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()
class ClickableLabel(QLabel):
clicked = pyqtSignal()
def __init__(self):
super(ClickableLabel, self).__init__()
class PathEdit(QWidget, Ui_PathEdit):
def __init__(self,
text: str = "",

View file

@ -34,3 +34,51 @@ class InstallQueueItemModel:
def __bool__(self):
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_())