From df35b8cec19fddd000d627c17be6ee23235a5719 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Tue, 18 Jun 2024 23:42:30 +0300
Subject: [PATCH 01/43] LegendarySettings: Refactor path_save and add slot
decorators
---
rare/components/tabs/settings/legendary.py | 58 ++++++++++++----------
1 file changed, 32 insertions(+), 26 deletions(-)
diff --git a/rare/components/tabs/settings/legendary.py b/rare/components/tabs/settings/legendary.py
index 3d2d49c9a..b82413e9f 100644
--- a/rare/components/tabs/settings/legendary.py
+++ b/rare/components/tabs/settings/legendary.py
@@ -3,7 +3,7 @@
from logging import getLogger
from typing import Tuple, Set
-from PyQt5.QtCore import QObject, pyqtSignal, QThreadPool, QSettings
+from PyQt5.QtCore import QObject, pyqtSignal, QThreadPool, QSettings, pyqtSlot
from PyQt5.QtGui import QShowEvent, QHideEvent
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
@@ -65,31 +65,32 @@ def __init__(self, parent=None):
self.ui.install_dir_layout.addWidget(self.install_dir)
# Max Workers
- max_workers = self.core.lgd.config["Legendary"].getint(
- "max_workers", fallback=0
+ self.ui.max_worker_spin.setValue(
+ self.core.lgd.config["Legendary"].getint("max_workers", fallback=0)
)
- self.ui.max_worker_spin.setValue(max_workers)
self.ui.max_worker_spin.valueChanged.connect(self.max_worker_save)
+
# Max memory
- max_memory = self.core.lgd.config["Legendary"].getint("max_memory", fallback=0)
- self.ui.max_memory_spin.setValue(max_memory)
+ self.ui.max_memory_spin.setValue(
+ self.core.lgd.config["Legendary"].getint("max_memory", fallback=0)
+ )
self.ui.max_memory_spin.valueChanged.connect(self.max_memory_save)
+
# Preferred CDN
- preferred_cdn = self.core.lgd.config["Legendary"].get(
- "preferred_cdn", fallback=""
+ self.ui.preferred_cdn_line.setText(
+ self.core.lgd.config["Legendary"].get("preferred_cdn", fallback="")
)
- self.ui.preferred_cdn_line.setText(preferred_cdn)
self.ui.preferred_cdn_line.textChanged.connect(self.preferred_cdn_save)
+
# Disable HTTPS
- disable_https = self.core.lgd.config["Legendary"].getboolean(
- "disable_https", fallback=False
+ self.ui.disable_https_check.setChecked(
+ self.core.lgd.config["Legendary"].getboolean("disable_https", fallback=False)
)
- self.ui.disable_https_check.setChecked(disable_https)
self.ui.disable_https_check.stateChanged.connect(self.disable_https_save)
- # Cleanup
- self.ui.clean_button.clicked.connect(lambda: self.cleanup(False))
- self.ui.clean_keep_manifests_button.clicked.connect(lambda: self.cleanup(True))
+ # Clean metadata
+ self.ui.clean_button.clicked.connect(lambda: self.clean_metadata(keep_manifests=False))
+ self.ui.clean_keep_manifests_button.clicked.connect(lambda: self.clean_metadata(keep_manifests=True))
self.locale_edit = IndicatorLineEdit(
f"{self.core.language_code}-{self.core.country_code}",
@@ -170,48 +171,53 @@ def locale_save_cb(self, text: str):
if text:
self.core.egs.language_code, self.core.egs.country_code = text.split("-")
self.core.lgd.config.set("Legendary", "locale", text)
- elif self.core.lgd.config.has_option("Legendary", "locale"):
+ else:
self.core.lgd.config.remove_option("Legendary", "locale")
+ @pyqtSlot(str)
def __mac_path_save(self, text: str) -> None:
self.__path_save(text, "mac_install_dir")
+ @pyqtSlot(str)
def __win_path_save(self, text: str) -> None:
self.__path_save(text, "install_dir")
if pf.system() != "Darwin":
self.__mac_path_save(text)
- def __path_save(self, text: str, option: str = "Windows"):
- self.core.lgd.config["Legendary"][option] = text
- if not text and option in self.core.lgd.config["Legendary"].keys():
- self.core.lgd.config["Legendary"].pop(option)
+ def __path_save(self, text: str, option: str):
+ if text:
+ self.core.lgd.config.set("Legendary", option, text)
else:
- logger.debug("Set %s option in config to %s", option, text)
+ self.core.lgd.config.remove_option("Legendary", option)
- def max_worker_save(self, workers: str):
- if workers := int(workers):
+ @pyqtSlot(int)
+ def max_worker_save(self, workers: int):
+ if workers:
self.core.lgd.config.set("Legendary", "max_workers", str(workers))
else:
self.core.lgd.config.remove_option("Legendary", "max_workers")
- def max_memory_save(self, memory: str):
- if memory := int(memory):
+ @pyqtSlot(int)
+ def max_memory_save(self, memory: int):
+ if memory:
self.core.lgd.config.set("Legendary", "max_memory", str(memory))
else:
self.core.lgd.config.remove_option("Legendary", "max_memory")
+ @pyqtSlot(str)
def preferred_cdn_save(self, cdn: str):
if cdn:
self.core.lgd.config.set("Legendary", "preferred_cdn", cdn.strip())
else:
self.core.lgd.config.remove_option("Legendary", "preferred_cdn")
+ @pyqtSlot(int)
def disable_https_save(self, checked: int):
self.core.lgd.config.set(
"Legendary", "disable_https", str(bool(checked)).lower()
)
- def cleanup(self, keep_manifests: bool):
+ def clean_metadata(self, keep_manifests: bool):
before = self.core.lgd.get_dir_size()
logger.debug("Removing app metadata...")
app_names = {g.app_name for g in self.core.get_assets(update_assets=False)}
From a5dd0e73fba1b05975d9db8b30bb442e1289968a Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 19 Jun 2024 02:21:12 +0300
Subject: [PATCH 02/43] SteamCompat: check if library folders actually exist
before searching them
---
rare/utils/compat/steam.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/rare/utils/compat/steam.py b/rare/utils/compat/steam.py
index a7553d8ae..f8efa522f 100644
--- a/rare/utils/compat/steam.py
+++ b/rare/utils/compat/steam.py
@@ -27,6 +27,7 @@ def find_libraries(steam_path: str) -> Set[str]:
libraryfolders = vdf.load(f)["libraryfolders"]
# libraries = [os.path.join(folder["path"], "steamapps") for key, folder in libraryfolders.items()]
libraries = {os.path.join(folder["path"], "steamapps") for key, folder in libraryfolders.items()}
+ libraries = set(filter(lambda x: os.path.isdir(x), libraries))
return libraries
From f28935c5ca0b41712639f2b32dae4d905be4caff Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 19 Jun 2024 02:22:40 +0300
Subject: [PATCH 03/43] RareGame: fix small lockup when querying for protondb
grade
---
rare/models/game.py | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/rare/models/game.py b/rare/models/game.py
index 59d6120d1..035efdba0 100644
--- a/rare/models/game.py
+++ b/rare/models/game.py
@@ -441,15 +441,9 @@ def steam_grade(self) -> str:
return "na"
if self.metadata.steam_grade != "pending":
elapsed_time = abs(datetime.now(UTC) - self.metadata.steam_date)
-
if elapsed_time.days > 3:
logger.info("Refreshing ProtonDB grade for %s", self.app_title)
-
- def set_steam_grade():
- appid, rating = get_rating(self.core, self.app_name)
- self.set_steam_grade(appid, rating)
-
- worker = QRunnable.create(set_steam_grade)
+ worker = QRunnable.create(self.set_steam_grade)
QThreadPool.globalInstance().start(worker)
self.metadata.steam_grade = "pending"
return self.metadata.steam_grade
@@ -464,7 +458,8 @@ def set_steam_appid(self, appid: int):
set_envvar(self.app_name, "STEAM_COMPAT_APP_ID", str(appid))
self.metadata.steam_appid = appid
- def set_steam_grade(self, appid: int, grade: str) -> None:
+ def set_steam_grade(self) -> None:
+ appid, grade = get_rating(self.core, self.app_name)
if appid and self.steam_appid is None:
self.set_steam_appid(appid)
self.metadata.steam_grade = grade
From cdb131fd192bfa586de42c5d7227a5c0907ad792 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 19 Jun 2024 14:54:15 +0300
Subject: [PATCH 04/43] WishlistItemsModel: Return an empty Tuple instead of
None in case there aren't any items.
Fixes: https://github.com/RareDevs/Rare/discussions/413#discussioncomment-9816019
---
.../tabs/store/api/models/response.py | 20 ++++++-------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/rare/components/tabs/store/api/models/response.py b/rare/components/tabs/store/api/models/response.py
index c8dfb5a0b..e9509f2f8 100644
--- a/rare/components/tabs/store/api/models/response.py
+++ b/rare/components/tabs/store/api/models/response.py
@@ -314,7 +314,7 @@ def from_dict(cls: Type["PagingModel"], src: Dict[str, Any]) -> "PagingModel":
@dataclass
class SearchStoreModel:
- elements: Optional[List[CatalogOfferModel]] = None
+ elements: Optional[Tuple[CatalogOfferModel, ...]] = None
paging: Optional[PagingModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@@ -322,13 +322,9 @@ class SearchStoreModel:
def from_dict(cls: Type["SearchStoreModel"], src: Dict[str, Any]) -> "SearchStoreModel":
d = src.copy()
_elements = d.pop("elements", [])
- elements = [] if _elements else None
- for item in _elements:
- elem = CatalogOfferModel.from_dict(item)
- elements.append(elem)
+ elements = tuple(map(CatalogOfferModel.from_dict, _elements))
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
- tmp = cls(elements=elements, paging=paging)
- tmp.unmapped = d
+ tmp = cls(elements=elements, paging=paging, unmapped=d)
return tmp
@@ -348,7 +344,7 @@ def from_dict(cls: Type["CatalogModel"], src: Dict[str, Any]) -> "CatalogModel":
@dataclass
class WishlistItemsModel:
- elements: Optional[List[WishlistItemModel]] = None
+ elements: Optional[Tuple[WishlistItemModel, ...]] = None
paging: Optional[PagingModel] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@@ -356,13 +352,9 @@ class WishlistItemsModel:
def from_dict(cls: Type["WishlistItemsModel"], src: Dict[str, Any]) -> "WishlistItemsModel":
d = src.copy()
_elements = d.pop("elements", [])
- elements = [] if _elements else None
- for item in _elements:
- elem = WishlistItemModel.from_dict(item)
- elements.append(elem)
+ elements = tuple(map(WishlistItemModel.from_dict, _elements))
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
- tmp = cls(elements=elements, paging=paging)
- tmp.unmapped = d
+ tmp = cls(elements=elements, paging=paging, unmapped=d)
return tmp
From 8ff37040ac01ef211250473e96336a1bb23b12c1 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 19 Jun 2024 18:44:33 +0300
Subject: [PATCH 05/43] StoreApiModels: Clean code by removing optional and
one-lining some things.
---
.../tabs/store/api/models/response.py | 300 ++++++++----------
1 file changed, 137 insertions(+), 163 deletions(-)
diff --git a/rare/components/tabs/store/api/models/response.py b/rare/components/tabs/store/api/models/response.py
index e9509f2f8..fe789f52d 100644
--- a/rare/components/tabs/store/api/models/response.py
+++ b/rare/components/tabs/store/api/models/response.py
@@ -1,7 +1,7 @@
import logging
from dataclasses import dataclass, field
from datetime import datetime
-from typing import List, Dict, Any, Type, Optional, Tuple
+from typing import List, Dict, Any, Type, Tuple
from .utils import parse_date
@@ -21,10 +21,10 @@
@dataclass
class ImageUrlModel:
- type: Optional[str] = None
- url: Optional[str] = None
+ type: str = None
+ url: str = None
- def to_dict(self) -> Dict[str, Any]:
+ def as_dict(self) -> Dict[str, Any]:
tmp: Dict[str, Any] = {}
tmp.update({})
if self.type is not None:
@@ -36,17 +36,28 @@ def to_dict(self) -> Dict[str, Any]:
@classmethod
def from_dict(cls: Type["ImageUrlModel"], src: Dict[str, Any]) -> "ImageUrlModel":
d = src.copy()
- type = d.pop("type", None)
- url = d.pop("url", None)
- tmp = cls(type=type, url=url)
- return tmp
+ return cls(type=d.pop("type", ""), url=d.pop("url", ""))
@dataclass
class KeyImagesModel:
- key_images: Optional[List[ImageUrlModel]] = None
- tall_types = ("DieselGameBoxTall", "DieselStoreFrontTall", "OfferImageTall", "DieselGameBoxLogo", "Thumbnail", "ProductLogo")
- wide_types = ("DieselGameBoxwide", "DieselStoreFrontWide", "OfferImageWide", "DieselGameBox", "VaultClosed", "ProductLogo")
+ key_images: Tuple[ImageUrlModel, ...] = None
+ tall_types = (
+ "DieselGameBoxTall",
+ "DieselStoreFrontTall",
+ "OfferImageTall",
+ "DieselGameBoxLogo",
+ "Thumbnail",
+ "ProductLogo",
+ )
+ wide_types = (
+ "DieselGameBoxwide",
+ "DieselStoreFrontWide",
+ "OfferImageWide",
+ "DieselGameBox",
+ "VaultClosed",
+ "ProductLogo",
+ )
def __getitem__(self, item):
return self.key_images[item]
@@ -54,24 +65,11 @@ def __getitem__(self, item):
def __bool__(self):
return bool(self.key_images)
- def to_list(self) -> List[Dict[str, Any]]:
- items: Optional[List[Dict[str, Any]]] = None
- if self.key_images is not None:
- items = []
- for image_url in self.key_images:
- item = image_url.to_dict()
- items.append(item)
- return items
-
@classmethod
def from_list(cls: Type["KeyImagesModel"], src: List[Dict]):
d = src.copy()
- key_images = []
- for item in d:
- image_url = ImageUrlModel.from_dict(item)
- key_images.append(image_url)
- tmp = cls(key_images)
- return tmp
+ key_images = tuple(map(ImageUrlModel.from_dict, d))
+ return cls(key_images=key_images)
def available_tall(self) -> List[ImageUrlModel]:
tall_images = filter(lambda img: img.type in KeyImagesModel.tall_types, self.key_images)
@@ -92,7 +90,7 @@ def for_dimensions(self, w: int, h: int) -> ImageUrlModel:
_ = model.url
except Exception as e:
logger.error(e)
- logger.error(self.to_list())
+ logger.error(tuple(map(lambda x: x.as_dict(), self.key_images)))
else:
return model
@@ -104,44 +102,41 @@ def for_dimensions(self, w: int, h: int) -> ImageUrlModel:
@dataclass
class TotalPriceModel:
- discountPrice: Optional[int] = None
- originalPrice: Optional[int] = None
- voucherDiscount: Optional[int] = None
- discount: Optional[int] = None
- currencyCode: Optional[str] = None
- currencyInfo: Optional[CurrencyModel] = None
- fmtPrice: Optional[FormattedPriceModel] = None
+ discountPrice: int = None
+ originalPrice: int = None
+ voucherDiscount: int = None
+ discount: int = None
+ currencyCode: str = None
+ currencyInfo: CurrencyModel = None
+ fmtPrice: FormattedPriceModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["TotalPriceModel"], src: Dict[str, Any]) -> "TotalPriceModel":
d = src.copy()
- tmp = cls(
- discountPrice=d.pop("discountPrice", None),
- originalPrice=d.pop("originalPrice", None),
- voucherDiscount=d.pop("voucherDiscount", None),
- discount=d.pop("discount", None),
- currencyCode=d.pop("currencyCode", None),
+ return cls(
+ discountPrice=d.pop("discountPrice", 0),
+ originalPrice=d.pop("originalPrice", 0),
+ voucherDiscount=d.pop("voucherDiscount", 0),
+ discount=d.pop("discount", 0),
+ currencyCode=d.pop("currencyCode", ""),
currencyInfo=d.pop("currrencyInfo", {}),
fmtPrice=d.pop("fmtPrice", {}),
+ unmapped=d,
)
- tmp.unmapped = d
- return tmp
@dataclass
class GetPriceResModel:
- totalPrice: Optional[TotalPriceModel] = None
- lineOffers: Optional[LineOffersModel] = None
+ totalPrice: TotalPriceModel = None
+ lineOffers: LineOffersModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["GetPriceResModel"], src: Dict[str, Any]) -> "GetPriceResModel":
d = src.copy()
total_price = TotalPriceModel.from_dict(x) if (x := d.pop("totalPrice", {})) else None
- tmp = cls(totalPrice=total_price, lineOffers=d.pop("lineOffers", {}))
- tmp.unmapped = d
- return tmp
+ return cls(totalPrice=total_price, lineOffers=d.pop("lineOffers", {}), unmapped=d)
DiscountSettingModel = Dict
@@ -149,81 +144,79 @@ def from_dict(cls: Type["GetPriceResModel"], src: Dict[str, Any]) -> "GetPriceRe
@dataclass
class PromotionalOfferModel:
- startDate: Optional[datetime] = None
- endDate: Optional[datetime] = None
- discountSetting: Optional[DiscountSettingModel] = None
+ startDate: datetime = None
+ endDate: datetime = None
+ discountSetting: DiscountSettingModel = None
+ unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["PromotionalOfferModel"], src: Dict[str, Any]) -> "PromotionalOfferModel":
d = src.copy()
start_date = parse_date(x) if (x := d.pop("startDate", "")) else None
end_date = parse_date(x) if (x := d.pop("endDate", "")) else None
- tmp = cls(startDate=start_date, endDate=end_date, discountSetting=d.pop("discountSetting", {}))
- tmp.unmapped = d
- return tmp
+ return cls(
+ startDate=start_date,
+ endDate=end_date,
+ discountSetting=d.pop("discountSetting", {}),
+ unmapped=d,
+ )
@dataclass
class PromotionalOffersModel:
- promotionalOffers: Optional[Tuple[PromotionalOfferModel]] = None
+ promotionalOffers: Tuple[PromotionalOfferModel, ...] = None
+ unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_list(cls: Type["PromotionalOffersModel"], src: Dict[str, List]) -> "PromotionalOffersModel":
d = src.copy()
- promotional_offers = (
- tuple([PromotionalOfferModel.from_dict(y) for y in x]) if (x := d.pop("promotionalOffers", [])) else None
- )
- tmp = cls(promotionalOffers=promotional_offers)
- tmp.unmapped = d
- return tmp
+ promotional_offers = tuple(map(PromotionalOfferModel.from_dict, d.pop("promotionalOffers", [])))
+ return cls(promotionalOffers=promotional_offers, unmapped=d)
@dataclass
class PromotionsModel:
- promotionalOffers: Optional[Tuple[PromotionalOffersModel]] = None
- upcomingPromotionalOffers: Optional[Tuple[PromotionalOffersModel]] = None
+ promotionalOffers: Tuple[PromotionalOffersModel, ...] = None
+ upcomingPromotionalOffers: Tuple[PromotionalOffersModel, ...] = None
+ unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["PromotionsModel"], src: Dict[str, Any]) -> "PromotionsModel":
d = src.copy()
- promotional_offers = (
- tuple([PromotionalOffersModel.from_list(y) for y in x]) if (x := d.pop("promotionalOffers", [])) else None
+ promotional_offers = tuple(map(PromotionalOffersModel.from_list, d.pop("promotionalOffers", [])))
+ upcoming_promotional_offers = tuple(
+ map(PromotionalOffersModel.from_list, d.pop("upcomingPromotionalOffers", []))
)
- upcoming_promotional_offers = (
- tuple([PromotionalOffersModel.from_list(y) for y in x])
- if (x := d.pop("upcomingPromotionalOffers", []))
- else None
+ return cls(
+ promotionalOffers=promotional_offers, upcomingPromotionalOffers=upcoming_promotional_offers, unmapped=d
)
- tmp = cls(promotionalOffers=promotional_offers, upcomingPromotionalOffers=upcoming_promotional_offers)
- tmp.unmapped = d
- return tmp
@dataclass
class CatalogOfferModel:
- catalogNs: Optional[CatalogNamespaceModel] = None
- categories: Optional[List[CategoryModel]] = None
- customAttributes: Optional[List[CustomAttributeModel]] = None
- description: Optional[str] = None
- effectiveDate: Optional[datetime] = None
- expiryDate: Optional[datetime] = None
- id: Optional[str] = None
- isCodeRedemptionOnly: Optional[bool] = None
- items: Optional[List[ItemModel]] = None
- keyImages: Optional[KeyImagesModel] = None
- namespace: Optional[str] = None
- offerMappings: Optional[List[PageSandboxModel]] = None
- offerType: Optional[str] = None
- price: Optional[GetPriceResModel] = None
- productSlug: Optional[str] = None
- promotions: Optional[PromotionsModel] = None
- seller: Optional[SellerModel] = None
- status: Optional[str] = None
- tags: Optional[List[TagModel]] = None
- title: Optional[str] = None
- url: Optional[str] = None
- urlSlug: Optional[str] = None
- viewableDate: Optional[datetime] = None
+ catalogNs: CatalogNamespaceModel = None
+ categories: List[CategoryModel] = None
+ customAttributes: List[CustomAttributeModel] = None
+ description: str = None
+ effectiveDate: datetime = None
+ expiryDate: datetime = None
+ id: str = None
+ isCodeRedemptionOnly: bool = None
+ items: List[ItemModel] = None
+ keyImages: KeyImagesModel = None
+ namespace: str = None
+ offerMappings: List[PageSandboxModel] = None
+ offerType: str = None
+ price: GetPriceResModel = None
+ productSlug: str = None
+ promotions: PromotionsModel = None
+ seller: SellerModel = None
+ status: str = None
+ tags: List[TagModel] = None
+ title: str = None
+ url: str = None
+ urlSlug: str = None
+ viewableDate: datetime = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -235,7 +228,7 @@ def from_dict(cls: Type["CatalogOfferModel"], src: Dict[str, Any]) -> "CatalogOf
price = GetPriceResModel.from_dict(x) if (x := d.pop("price", {})) else None
promotions = PromotionsModel.from_dict(x) if (x := d.pop("promotions", {})) else None
viewable_date = parse_date(x) if (x := d.pop("viewableDate", "")) else None
- tmp = cls(
+ return cls(
catalogNs=d.pop("catalogNs", {}),
categories=d.pop("categories", []),
customAttributes=d.pop("customAttributes", []),
@@ -243,7 +236,7 @@ def from_dict(cls: Type["CatalogOfferModel"], src: Dict[str, Any]) -> "CatalogOf
effectiveDate=effective_date,
expiryDate=expiry_date,
id=d.pop("id", ""),
- isCodeRedemptionOnly=d.pop("isCodeRedemptionOnly", None),
+ isCodeRedemptionOnly=d.pop("isCodeRedemptionOnly", False),
items=d.pop("items", []),
keyImages=key_images,
namespace=d.pop("namespace", ""),
@@ -259,21 +252,20 @@ def from_dict(cls: Type["CatalogOfferModel"], src: Dict[str, Any]) -> "CatalogOf
url=d.pop("url", ""),
urlSlug=d.pop("urlSlug", ""),
viewableDate=viewable_date,
+ unmapped=d,
)
- tmp.unmapped = d
- return tmp
@dataclass
class WishlistItemModel:
- created: Optional[datetime] = None
- id: Optional[str] = None
- namespace: Optional[str] = None
- isFirstTime: Optional[bool] = None
- offerId: Optional[str] = None
- order: Optional[Any] = None
- updated: Optional[datetime] = None
- offer: Optional[CatalogOfferModel] = None
+ created: datetime = None
+ id: str = None
+ namespace: str = None
+ isFirstTime: bool = None
+ offerId: str = None
+ order: Any = None
+ updated: datetime = None
+ offer: CatalogOfferModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -282,40 +274,37 @@ def from_dict(cls: Type["WishlistItemModel"], src: Dict[str, Any]) -> "WishlistI
created = parse_date(x) if (x := d.pop("created", "")) else None
offer = CatalogOfferModel.from_dict(x) if (x := d.pop("offer", {})) else None
updated = parse_date(x) if (x := d.pop("updated", "")) else None
- tmp = cls(
+ return cls(
created=created,
id=d.pop("id", ""),
namespace=d.pop("namespace", ""),
- isFirstTime=d.pop("isFirstTime", None),
+ isFirstTime=d.pop("isFirstTime", False),
offerId=d.pop("offerId", ""),
order=d.pop("order", ""),
updated=updated,
offer=offer,
+ unmapped=d,
)
- tmp.unmapped = d
- return tmp
@dataclass
class PagingModel:
- count: Optional[int] = None
- total: Optional[int] = None
+ count: int = None
+ total: int = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["PagingModel"], src: Dict[str, Any]) -> "PagingModel":
d = src.copy()
- count = d.pop("count", None)
- total = d.pop("total", None)
- tmp = cls(count=count, total=total)
- tmp.unmapped = d
- return tmp
+ count = d.pop("count", 0)
+ total = d.pop("total", 0)
+ return cls(count=count, total=total, unmapped=d)
@dataclass
class SearchStoreModel:
- elements: Optional[Tuple[CatalogOfferModel, ...]] = None
- paging: Optional[PagingModel] = None
+ elements: Tuple[CatalogOfferModel, ...] = None
+ paging: PagingModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -324,28 +313,25 @@ def from_dict(cls: Type["SearchStoreModel"], src: Dict[str, Any]) -> "SearchStor
_elements = d.pop("elements", [])
elements = tuple(map(CatalogOfferModel.from_dict, _elements))
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
- tmp = cls(elements=elements, paging=paging, unmapped=d)
- return tmp
+ return cls(elements=elements, paging=paging, unmapped=d)
@dataclass
class CatalogModel:
- searchStore: Optional[SearchStoreModel] = None
+ searchStore: SearchStoreModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["CatalogModel"], src: Dict[str, Any]) -> "CatalogModel":
d = src.copy()
search_store = SearchStoreModel.from_dict(x) if (x := d.pop("searchStore", {})) else None
- tmp = cls(searchStore=search_store)
- tmp.unmapped = d
- return tmp
+ return cls(searchStore=search_store, unmapped=d)
@dataclass
class WishlistItemsModel:
- elements: Optional[Tuple[WishlistItemModel, ...]] = None
- paging: Optional[PagingModel] = None
+ elements: Tuple[WishlistItemModel, ...] = None
+ paging: PagingModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -354,43 +340,38 @@ def from_dict(cls: Type["WishlistItemsModel"], src: Dict[str, Any]) -> "Wishlist
_elements = d.pop("elements", [])
elements = tuple(map(WishlistItemModel.from_dict, _elements))
paging = PagingModel.from_dict(x) if (x := d.pop("paging", {})) else None
- tmp = cls(elements=elements, paging=paging, unmapped=d)
- return tmp
+ return cls(elements=elements, paging=paging, unmapped=d)
@dataclass
class RemoveFromWishlistModel:
- success: Optional[bool] = None
+ success: bool = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["RemoveFromWishlistModel"], src: Dict[str, Any]) -> "RemoveFromWishlistModel":
d = src.copy()
- tmp = cls(success=d.pop("success", None))
- tmp.unmapped = d
- return tmp
+ return cls(success=d.pop("success", False), unmapped=d)
@dataclass
class AddToWishlistModel:
- wishlistItem: Optional[WishlistItemModel] = None
- success: Optional[bool] = None
+ wishlistItem: WishlistItemModel = None
+ success: bool = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["AddToWishlistModel"], src: Dict[str, Any]) -> "AddToWishlistModel":
d = src.copy()
wishlist_item = WishlistItemModel.from_dict(x) if (x := d.pop("wishlistItem", {})) else None
- tmp = cls(wishlistItem=wishlist_item, success=d.pop("success", None))
- tmp.unmapped = d
- return tmp
+ return cls(wishlistItem=wishlist_item, success=d.pop("success", False), unmapped=d)
@dataclass
class WishlistModel:
- wishlistItems: Optional[WishlistItemsModel] = None
- removeFromWishlist: Optional[RemoveFromWishlistModel] = None
- addToWishlist: Optional[AddToWishlistModel] = None
+ wishlistItems: WishlistItemsModel = None
+ removeFromWishlist: RemoveFromWishlistModel = None
+ addToWishlist: AddToWishlistModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -399,11 +380,12 @@ def from_dict(cls: Type["WishlistModel"], src: Dict[str, Any]) -> "WishlistModel
wishlist_items = WishlistItemsModel.from_dict(x) if (x := d.pop("wishlistItems", {})) else None
remove_from_wishlist = RemoveFromWishlistModel.from_dict(x) if (x := d.pop("removeFromWishlist", {})) else None
add_to_wishlist = AddToWishlistModel.from_dict(x) if (x := d.pop("addToWishlist", {})) else None
- tmp = cls(
- wishlistItems=wishlist_items, removeFromWishlist=remove_from_wishlist, addToWishlist=add_to_wishlist
+ return cls(
+ wishlistItems=wishlist_items,
+ removeFromWishlist=remove_from_wishlist,
+ addToWishlist=add_to_wishlist,
+ unmapped=d,
)
- tmp.unmapped = d
- return tmp
ProductModel = Dict
@@ -411,9 +393,9 @@ def from_dict(cls: Type["WishlistModel"], src: Dict[str, Any]) -> "WishlistModel
@dataclass
class DataModel:
- product: Optional[ProductModel] = None
- catalog: Optional[CatalogModel] = None
- wishlist: Optional[WishlistModel] = None
+ product: ProductModel = None
+ catalog: CatalogModel = None
+ wishlist: WishlistModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -421,9 +403,7 @@ def from_dict(cls: Type["DataModel"], src: Dict[str, Any]) -> "DataModel":
d = src.copy()
catalog = CatalogModel.from_dict(x) if (x := d.pop("Catalog", {})) else None
wishlist = WishlistModel.from_dict(x) if (x := d.pop("Wishlist", {})) else None
- tmp = cls(product=d.pop("Product", {}), catalog=catalog, wishlist=wishlist)
- tmp.unmapped = d
- return tmp
+ return cls(product=d.pop("Product", {}), catalog=catalog, wishlist=wishlist, unmapped=d)
@dataclass
@@ -433,9 +413,7 @@ class ErrorModel:
@classmethod
def from_dict(cls: Type["ErrorModel"], src: Dict[str, Any]) -> "ErrorModel":
d = src.copy()
- tmp = cls()
- tmp.unmapped = d
- return tmp
+ return cls(unmapped=d)
@dataclass
@@ -445,16 +423,14 @@ class ExtensionsModel:
@classmethod
def from_dict(cls: Type["ExtensionsModel"], src: Dict[str, Any]) -> "ExtensionsModel":
d = src.copy()
- tmp = cls()
- tmp.unmapped = d
- return tmp
+ return cls(unmapped=d)
@dataclass
class ResponseModel:
- data: Optional[DataModel] = None
- errors: Optional[List[ErrorModel]] = None
- extensions: Optional[ExtensionsModel] = None
+ data: DataModel = None
+ errors: List[ErrorModel] = None
+ extensions: ExtensionsModel = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -467,6 +443,4 @@ def from_dict(cls: Type["ResponseModel"], src: Dict[str, Any]) -> "ResponseModel
error = ErrorModel.from_dict(item)
errors.append(error)
extensions = ExtensionsModel.from_dict(x) if (x := d.pop("extensions", {})) else None
- tmp = cls(data=data, errors=errors, extensions=extensions)
- tmp.unmapped = d
- return tmp
+ return cls(data=data, errors=errors, extensions=extensions, unmapped=d)
From 26a81ce1f21788c91d65c2ab35e8b795165b248a Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Thu, 20 Jun 2024 15:28:26 +0300
Subject: [PATCH 06/43] Refactor: Use fully qualified Qt enumeration names
---
rare/commands/launcher/__init__.py | 4 +-
rare/commands/launcher/cloud_sync_dialog.py | 4 +-
rare/commands/launcher/console_dialog.py | 14 ++---
rare/components/__init__.py | 6 +-
rare/components/dialogs/install_dialog.py | 4 +-
rare/components/dialogs/launch_dialog.py | 14 ++---
rare/components/dialogs/login/__init__.py | 20 +++----
.../components/dialogs/login/browser_login.py | 10 ++--
rare/components/dialogs/login/import_login.py | 5 +-
rare/components/dialogs/move_dialog.py | 4 +-
rare/components/dialogs/uninstall_dialog.py | 2 +-
rare/components/main_window.py | 35 ++++++-----
rare/components/tabs/__init__.py | 8 +--
rare/components/tabs/downloads/__init__.py | 6 +-
rare/components/tabs/downloads/download.py | 14 ++---
rare/components/tabs/downloads/groups.py | 6 +-
rare/components/tabs/downloads/widgets.py | 2 +-
rare/components/tabs/games/__init__.py | 2 +-
.../tabs/games/game_info/__init__.py | 4 +-
.../tabs/games/game_info/cloud_saves.py | 11 ++--
.../tabs/games/game_info/details.py | 2 +-
rare/components/tabs/games/game_info/dlcs.py | 8 +--
.../tabs/games/game_info/settings.py | 10 ++--
.../tabs/games/game_widgets/__init__.py | 4 +-
.../tabs/games/game_widgets/game_widget.py | 14 ++---
.../tabs/games/game_widgets/icon_widget.py | 22 +++----
.../tabs/games/game_widgets/library_widget.py | 14 ++---
.../games/game_widgets/list_game_widget.py | 16 ++---
.../tabs/games/game_widgets/list_widget.py | 42 +++++++-------
rare/components/tabs/games/head_bar.py | 28 ++++-----
.../tabs/games/integrations/__init__.py | 5 +-
.../tabs/games/integrations/egl_sync_group.py | 30 +++++-----
.../tabs/games/integrations/eos_group.py | 24 ++++----
.../tabs/games/integrations/import_group.py | 32 +++++-----
.../tabs/games/integrations/ubisoft_group.py | 8 +--
rare/components/tabs/settings/legendary.py | 6 +-
rare/components/tabs/settings/rare.py | 16 ++---
.../tabs/settings/widgets/env_vars.py | 8 +--
.../tabs/settings/widgets/env_vars_model.py | 58 +++++++++----------
rare/components/tabs/settings/widgets/game.py | 2 +-
.../tabs/settings/widgets/launch.py | 8 +--
.../tabs/settings/widgets/overlay.py | 8 +--
.../tabs/settings/widgets/proton.py | 10 ++--
rare/components/tabs/settings/widgets/wine.py | 10 ++--
.../tabs/settings/widgets/wrappers.py | 42 +++++++-------
rare/components/tabs/store/api/debug.py | 2 +-
rare/components/tabs/store/landing.py | 54 ++++++++---------
rare/components/tabs/store/results.py | 6 +-
rare/components/tabs/store/search.py | 6 +-
rare/components/tabs/store/store_api.py | 4 +-
rare/components/tabs/store/widgets/details.py | 16 ++---
rare/components/tabs/store/widgets/image.py | 16 ++---
rare/components/tabs/store/widgets/items.py | 6 +-
rare/components/tabs/store/wishlist.py | 16 ++---
rare/components/tray_icon.py | 4 +-
rare/models/image.py | 6 +-
rare/shared/image_manager.py | 43 +++++++++-----
rare/utils/json_formatter.py | 14 ++---
rare/utils/misc.py | 22 +++----
rare/utils/paths.py | 22 +++----
rare/utils/qt_requests.py | 14 +++--
rare/widgets/button_edit.py | 4 +-
rare/widgets/collapsible_widget.py | 14 ++---
rare/widgets/dialogs.py | 28 ++++-----
rare/widgets/elide_label.py | 2 +-
rare/widgets/flow_layout.py | 14 ++---
rare/widgets/image_widget.py | 16 ++---
rare/widgets/indicator_edit.py | 24 ++++----
rare/widgets/library_layout.py | 12 ++--
rare/widgets/loading_widget.py | 8 +--
rare/widgets/rare_app.py | 10 ++--
rare/widgets/selective_widget.py | 2 +-
rare/widgets/side_tab.py | 18 +++---
rare/widgets/sliding_stack.py | 16 ++---
74 files changed, 525 insertions(+), 496 deletions(-)
diff --git a/rare/commands/launcher/__init__.py b/rare/commands/launcher/__init__.py
index 06bcb2981..0380653fc 100644
--- a/rare/commands/launcher/__init__.py
+++ b/rare/commands/launcher/__init__.py
@@ -428,8 +428,8 @@ def stop(self):
def launch(args: Namespace) -> int:
args = InitArgs.from_argparse(args)
- QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
- QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
+ QApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling, True)
+ QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps, True)
app = RareLauncher(args)
app.setQuitOnLastWindowClosed(True)
diff --git a/rare/commands/launcher/cloud_sync_dialog.py b/rare/commands/launcher/cloud_sync_dialog.py
index 1a861039a..daa28f2b5 100644
--- a/rare/commands/launcher/cloud_sync_dialog.py
+++ b/rare/commands/launcher/cloud_sync_dialog.py
@@ -73,11 +73,11 @@ def __init__(self, igame: InstalledGame, dt_local: datetime, dt_remote: datetime
def __on_upload(self):
self.status = CloudSyncDialogResult.UPLOAD
- self.done(QDialog.Accepted)
+ self.done(QDialog.DialogCode.Accepted)
def __on_download(self):
self.status = CloudSyncDialogResult.DOWNLOAD
- self.done(QDialog.Accepted)
+ self.done(QDialog.DialogCode.Accepted)
def done_handler(self):
self.result_ready.emit(self.status)
diff --git a/rare/commands/launcher/console_dialog.py b/rare/commands/launcher/console_dialog.py
index a952bc5ef..efca16582 100644
--- a/rare/commands/launcher/console_dialog.py
+++ b/rare/commands/launcher/console_dialog.py
@@ -25,7 +25,7 @@ class ConsoleDialog(QDialog):
def __init__(self, app_title: str, parent=None):
super(ConsoleDialog, self).__init__(parent=parent)
- self.setAttribute(Qt.WA_DeleteOnClose, True)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
self.setWindowTitle(
dialog_title(game_title(self.tr("Console"), app_title))
)
@@ -49,7 +49,7 @@ def __init__(self, app_title: str, parent=None):
button_layout.addWidget(self.clear_button)
self.clear_button.clicked.connect(self.console_edit.clear)
- button_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed))
+ button_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
self.terminate_button = QPushButton(self.tr("Terminate"))
# self.terminate_button.setVisible(platform.system() == "Windows")
@@ -151,7 +151,7 @@ class ConsoleEnv(QDialog):
def __init__(self, app_title: str, parent=None):
super(ConsoleEnv, self).__init__(parent=parent)
- self.setAttribute(Qt.WA_DeleteOnClose, False)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
self.ui = Ui_ConsoleEnv()
self.ui.setupUi(self)
self.setWindowTitle(
@@ -166,7 +166,7 @@ def setTable(self, env: QProcessEnvironment):
self.ui.table.setItem(idx, 0, QTableWidgetItem(env.keys()[idx]))
self.ui.table.setItem(idx, 1, QTableWidgetItem(env.value(env.keys()[idx])))
- self.ui.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
+ self.ui.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
class ConsoleEdit(QPlainTextEdit):
@@ -175,14 +175,14 @@ def __init__(self, parent=None):
super(ConsoleEdit, self).__init__(parent=parent)
self.setReadOnly(True)
font = QFont("Monospace")
- font.setStyleHint(QFont.Monospace)
+ font.setStyleHint(QFont.StyleHint.Monospace)
self.setFont(font)
def scroll_to_last_line(self):
cursor = self.textCursor()
- cursor.movePosition(QTextCursor.End)
+ cursor.movePosition(QTextCursor.MoveOperation.End)
cursor.movePosition(
- QTextCursor.Up if cursor.atBlockStart() else QTextCursor.StartOfLine
+ QTextCursor.MoveOperation.Up if cursor.atBlockStart() else QTextCursor.MoveOperation.StartOfLine
)
self.setTextCursor(cursor)
diff --git a/rare/components/__init__.py b/rare/components/__init__.py
index d9286841d..d13dbec7f 100644
--- a/rare/components/__init__.py
+++ b/rare/components/__init__.py
@@ -87,7 +87,7 @@ def launch_app(self):
@pyqtSlot()
def __on_start_app(self):
self.relogin_timer = QTimer(self)
- self.relogin_timer.setTimerType(Qt.VeryCoarseTimer)
+ self.relogin_timer.setTimerType(Qt.TimerType.VeryCoarseTimer)
self.relogin_timer.timeout.connect(self.relogin)
self.poke_timer()
@@ -122,8 +122,8 @@ def __on_exit_app(self, exit_code=0):
def start(args) -> int:
while True:
- QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
- QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
+ QApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling, True)
+ QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps, True)
app = Rare(args)
exit_code = app.exec()
del app
diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py
index 9042f2ce5..1e67d759c 100644
--- a/rare/components/dialogs/install_dialog.py
+++ b/rare/components/dialogs/install_dialog.py
@@ -108,14 +108,14 @@ def __init__(self, rgame: RareGame, options: InstallOptionsModel, parent=None):
self.install_dir_edit = PathEdit(
path=base_path,
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
edit_func=self.install_dir_edit_callback,
save_func=self.install_dir_save_callback,
parent=self,
)
self.ui.main_layout.setWidget(
self.ui.main_layout.getWidgetPosition(self.ui.install_dir_label)[0],
- QFormLayout.FieldRole,
+ QFormLayout.ItemRole.FieldRole,
self.install_dir_edit,
)
diff --git a/rare/components/dialogs/launch_dialog.py b/rare/components/dialogs/launch_dialog.py
index 2de1f85d2..e0b627377 100644
--- a/rare/components/dialogs/launch_dialog.py
+++ b/rare/components/dialogs/launch_dialog.py
@@ -20,13 +20,13 @@ class LaunchDialog(BaseDialog):
def __init__(self, parent=None):
super(LaunchDialog, self).__init__(parent=parent)
self.setWindowFlags(
- Qt.Window
- | Qt.Dialog
- | Qt.CustomizeWindowHint
- | Qt.WindowSystemMenuHint
- | Qt.WindowTitleHint
- | Qt.WindowMinimizeButtonHint
- | Qt.MSWindowsFixedSizeDialogHint
+ Qt.WindowType.Window
+ | Qt.WindowType.Dialog
+ | Qt.WindowType.CustomizeWindowHint
+ | Qt.WindowType.WindowSystemMenuHint
+ | Qt.WindowType.WindowTitleHint
+ | Qt.WindowType.WindowMinimizeButtonHint
+ | Qt.WindowType.MSWindowsFixedSizeDialogHint
)
self.ui = Ui_LaunchDialog()
diff --git a/rare/components/dialogs/login/__init__.py b/rare/components/dialogs/login/__init__.py
index 32a2ee5e2..df8c08d33 100644
--- a/rare/components/dialogs/login/__init__.py
+++ b/rare/components/dialogs/login/__init__.py
@@ -19,7 +19,7 @@
class LandingPage(QFrame):
def __init__(self, parent=None):
super(LandingPage, self).__init__(parent=parent)
- self.setFrameStyle(self.StyledPanel)
+ self.setFrameStyle(QFrame.Shape.StyledPanel)
self.ui = Ui_LandingPage()
self.ui.setupUi(self)
@@ -29,14 +29,14 @@ class LoginDialog(BaseDialog):
def __init__(self, core: LegendaryCore, parent=None):
super(LoginDialog, self).__init__(parent=parent)
self.setWindowFlags(
- Qt.Window
- | Qt.Dialog
- | Qt.CustomizeWindowHint
- | Qt.WindowSystemMenuHint
- | Qt.WindowTitleHint
- | Qt.WindowMinimizeButtonHint
- | Qt.WindowCloseButtonHint
- | Qt.MSWindowsFixedSizeDialogHint
+ Qt.WindowType.Window
+ | Qt.WindowType.Dialog
+ | Qt.WindowType.CustomizeWindowHint
+ | Qt.WindowType.WindowSystemMenuHint
+ | Qt.WindowType.WindowTitleHint
+ | Qt.WindowType.WindowMinimizeButtonHint
+ | Qt.WindowType.WindowCloseButtonHint
+ | Qt.WindowType.MSWindowsFixedSizeDialogHint
)
self.ui = Ui_LoginDialog()
@@ -108,7 +108,7 @@ def __init__(self, core: LegendaryCore, parent=None):
self.ui.back_button.setAutoDefault(False)
self.ui.next_button.setAutoDefault(True)
- self.ui.main_layout.setSizeConstraint(QLayout.SetFixedSize)
+ self.ui.main_layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
def back_clicked(self):
self.ui.back_button.setEnabled(False)
diff --git a/rare/components/dialogs/login/browser_login.py b/rare/components/dialogs/login/browser_login.py
index df15855f0..6e173c87d 100644
--- a/rare/components/dialogs/login/browser_login.py
+++ b/rare/components/dialogs/login/browser_login.py
@@ -4,7 +4,7 @@
from PyQt5.QtCore import pyqtSignal, QUrl, QProcess, pyqtSlot
from PyQt5.QtGui import QDesktopServices
-from PyQt5.QtWidgets import QFrame, qApp, QFormLayout, QLineEdit
+from PyQt5.QtWidgets import QFrame, QApplication, QFormLayout, QLineEdit
from legendary.utils import webview_login
from rare.lgndr.core import LegendaryCore
@@ -22,7 +22,7 @@ class BrowserLogin(QFrame):
def __init__(self, core: LegendaryCore, parent=None):
super(BrowserLogin, self).__init__(parent=parent)
- self.setFrameStyle(self.StyledPanel)
+ self.setFrameStyle(QFrame.Shape.StyledPanel)
self.ui = Ui_BrowserLogin()
self.ui.setupUi(self)
@@ -32,13 +32,13 @@ def __init__(self, core: LegendaryCore, parent=None):
self.sid_edit = IndicatorLineEdit(
placeholder=self.tr("Insert authorizationCode here"), edit_func=self.text_changed, parent=self
)
- self.sid_edit.line_edit.setEchoMode(QLineEdit.Password)
+ self.sid_edit.line_edit.setEchoMode(QLineEdit.EchoMode.Password)
self.ui.link_text.setText(self.login_url)
self.ui.copy_button.setIcon(qta_icon("mdi.content-copy", "fa.copy"))
self.ui.copy_button.clicked.connect(self.copy_link)
self.ui.form_layout.setWidget(
self.ui.form_layout.getWidgetPosition(self.ui.sid_label)[0],
- QFormLayout.FieldRole, self.sid_edit
+ QFormLayout.ItemRole.FieldRole, self.sid_edit
)
self.ui.open_button.clicked.connect(self.open_browser)
@@ -46,7 +46,7 @@ def __init__(self, core: LegendaryCore, parent=None):
@pyqtSlot()
def copy_link(self):
- clipboard = qApp.clipboard()
+ clipboard = QApplication.instance().clipboard()
clipboard.setText(self.login_url)
self.ui.status_label.setText(self.tr("Copied to clipboard"))
diff --git a/rare/components/dialogs/login/import_login.py b/rare/components/dialogs/login/import_login.py
index b02905c48..da901679a 100644
--- a/rare/components/dialogs/login/import_login.py
+++ b/rare/components/dialogs/login/import_login.py
@@ -26,7 +26,7 @@ class ImportLogin(QFrame):
def __init__(self, core: LegendaryCore, parent=None):
super(ImportLogin, self).__init__(parent=parent)
- self.setFrameStyle(self.StyledPanel)
+ self.setFrameStyle(QFrame.Shape.StyledPanel)
self.ui = Ui_ImportLogin()
self.ui.setupUi(self)
@@ -70,7 +70,8 @@ def get_wine_prefixes(self):
def prefix_path(self):
prefix_dialog = QFileDialog(self, self.tr("Choose path"), os.path.expanduser("~/"))
- prefix_dialog.setFileMode(QFileDialog.DirectoryOnly)
+ prefix_dialog.setFileMode(QFileDialog.FileMode.Directory)
+ prefix_dialog.setOption(QFileDialog.Option.ShowDirsOnly)
if prefix_dialog.exec_():
names = prefix_dialog.selectedFiles()
self.ui.prefix_combo.setCurrentText(names[0])
diff --git a/rare/components/dialogs/move_dialog.py b/rare/components/dialogs/move_dialog.py
index 38ea2a149..26cc08ece 100644
--- a/rare/components/dialogs/move_dialog.py
+++ b/rare/components/dialogs/move_dialog.py
@@ -40,7 +40,7 @@ def __init__(self, rgame: RareGame, parent=None):
self.core = RareCore.instance().core()
self.rgame: Optional[RareGame] = None
- self.path_edit = PathEdit("", QFileDialog.Directory, edit_func=self.path_edit_callback)
+ self.path_edit = PathEdit("", QFileDialog.FileMode.Directory, edit_func=self.path_edit_callback)
self.path_edit.extend_reasons({
MovePathEditReasons.DST_MISSING: self.tr("You need to provide the destination directory."),
MovePathEditReasons.NO_WRITE_PERM: self.tr("No write permission on destination."),
@@ -68,7 +68,7 @@ def __init__(self, rgame: RareGame, parent=None):
bottom_layout.addWidget(self.avail_space, stretch=1)
layout = QVBoxLayout()
- layout.setSizeConstraint(QLayout.SetFixedSize)
+ layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
layout.addWidget(self.path_edit)
layout.addWidget(self.warn_label)
layout.addLayout(bottom_layout)
diff --git a/rare/components/dialogs/uninstall_dialog.py b/rare/components/dialogs/uninstall_dialog.py
index b9ba5606d..f88f31585 100644
--- a/rare/components/dialogs/uninstall_dialog.py
+++ b/rare/components/dialogs/uninstall_dialog.py
@@ -53,7 +53,7 @@ def __init__(self, rgame: RareGame, options: UninstallOptionsModel, parent=None)
@pyqtSlot(int)
def __on_keep_files_changed(self, state: int):
- self.keep_folder.setCheckState(state if state else Qt.Checked)
+ self.keep_folder.setCheckState(state if state else Qt.CheckState.Checked)
self.keep_folder.setEnabled(not state)
def done_handler(self) -> None:
diff --git a/rare/components/main_window.py b/rare/components/main_window.py
index 5e38faf87..4f46b97ec 100644
--- a/rare/components/main_window.py
+++ b/rare/components/main_window.py
@@ -14,6 +14,7 @@
QLabel,
QWidget,
QHBoxLayout,
+ QSystemTrayIcon,
)
from rare.models.options import options
@@ -36,7 +37,7 @@ def __init__(self, parent=None):
self.__accept_close = False
self._window_launched = False
super(MainWindow, self).__init__(parent=parent)
- self.setAttribute(Qt.WA_DeleteOnClose, True)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
self.rcore = RareCore.instance()
self.core = RareCore.instance().core()
self.signals = RareCore.instance().signals()
@@ -60,7 +61,7 @@ def __init__(self, parent=None):
self.active_container = QWidget(self.status_bar)
active_layout = QHBoxLayout(self.active_container)
active_layout.setContentsMargins(0, 0, 0, 0)
- active_layout.setSizeConstraint(QHBoxLayout.SetFixedSize)
+ active_layout.setSizeConstraint(QHBoxLayout.SizeConstraint.SetFixedSize)
self.status_bar.addWidget(self.active_container, stretch=0)
self.queued_label = QLabel(self.tr("Queued:"), self.status_bar)
@@ -69,17 +70,17 @@ def __init__(self, parent=None):
self.status_bar.addPermanentWidget(self.queued_label)
self.queued_scroll = QScrollArea(self.status_bar)
- self.queued_scroll.setFrameStyle(QScrollArea.NoFrame)
+ self.queued_scroll.setFrameStyle(QScrollArea.Shape.NoFrame)
self.queued_scroll.setWidgetResizable(True)
- self.queued_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- self.queued_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ self.queued_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+ self.queued_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.queued_scroll.setFixedHeight(self.queued_label.sizeHint().height())
self.status_bar.addPermanentWidget(self.queued_scroll, stretch=1)
self.queued_container = QWidget(self.queued_scroll)
queued_layout = QHBoxLayout(self.queued_container)
queued_layout.setContentsMargins(0, 0, 0, 0)
- queued_layout.setSizeConstraint(QHBoxLayout.SetFixedSize)
+ queued_layout.setSizeConstraint(QHBoxLayout.SizeConstraint.SetFixedSize)
self.active_label.setVisible(False)
self.active_container.setVisible(False)
@@ -115,12 +116,14 @@ def __init__(self, parent=None):
self.tray_icon: TrayIcon = TrayIcon(self)
self.tray_icon.exit_app.connect(self.__on_exit_app)
self.tray_icon.show_app.connect(self.show)
- self.tray_icon.activated.connect(lambda r: self.toggle() if r == self.tray_icon.DoubleClick else None)
+ self.tray_icon.activated.connect(
+ lambda r: self.toggle() if r == QSystemTrayIcon.ActivationReason.DoubleClick else None
+ )
# enable kinetic scrolling
for scroll_area in self.findChildren(QScrollArea):
if not scroll_area.property("no_kinetic_scroll"):
- QScroller.grabGesture(scroll_area.viewport(), QScroller.LeftMouseButtonGesture)
+ QScroller.grabGesture(scroll_area.viewport(), QScroller.ScrollerGestureType.LeftMouseButtonGesture)
# fix scrolling
for combo_box in scroll_area.findChildren(QComboBox):
@@ -169,10 +172,10 @@ def update_statusbar(self):
self.active_container.setVisible(False)
self.queued_label.setVisible(False)
self.queued_scroll.setVisible(False)
- for label in self.active_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly):
+ for label in self.active_container.findChildren(QLabel, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.active_container.layout().removeWidget(label)
label.deleteLater()
- for label in self.queued_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly):
+ for label in self.queued_container.findChildren(QLabel, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.queued_container.layout().removeWidget(label)
label.deleteLater()
for info in self.rcore.queue_info():
@@ -230,10 +233,10 @@ def closeEvent(self, e: QCloseEvent) -> None:
"Rare cannot exit until they are completed.\n\n"
"Do you want to clear the queue?"
),
- buttons=(QMessageBox.Yes | QMessageBox.No),
- defaultButton=QMessageBox.No,
+ buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
+ defaultButton=QMessageBox.StandardButton.No,
)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
self.rcore.queue_threadpool.clear()
for qw in self.rcore.queued_workers():
self.rcore.dequeue_worker(qw)
@@ -249,10 +252,10 @@ def closeEvent(self, e: QCloseEvent) -> None:
"Quitting Rare now will stop the download.\n\n"
"Are you sure you want to quit?"
),
- buttons=(QMessageBox.Yes | QMessageBox.No),
- defaultButton=QMessageBox.No,
+ buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
+ defaultButton=QMessageBox.StandardButton.No,
)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
self.tab_widget.downloads_tab.stop_download(omit_queue=True)
else:
e.ignore()
diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py
index 769bc82d9..e621bd6d6 100644
--- a/rare/components/tabs/__init__.py
+++ b/rare/components/tabs/__init__.py
@@ -60,7 +60,7 @@ def __init__(self, parent):
account_menu.addAction(account_action)
account_button.setMenu(account_menu)
self.tab_bar.setTabButton(
- button_index, MainTabBar.RightSide, account_button
+ button_index, MainTabBar.ButtonPosition.RightSide, account_button
)
self.settings_tab = SettingsTab(self)
@@ -107,11 +107,11 @@ def __on_exit_app(self, exit_code: int):
self,
self.tr("Logout"),
self.tr("Do you really want to logout {}?").format(self.core.lgd.userdata.get("display_name")),
- buttons=(QMessageBox.Yes | QMessageBox.No),
- defaultButton=QMessageBox.No,
+ buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
+ defaultButton=QMessageBox.StandardButton.No,
)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
self.core.lgd.invalidate_userdata()
else:
return
diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py
index e43cac466..c6dc7febf 100644
--- a/rare/components/tabs/downloads/__init__.py
+++ b/rare/components/tabs/downloads/__init__.py
@@ -55,12 +55,12 @@ def __init__(self, parent=None):
self.queue_scrollarea = QScrollArea(self)
self.queue_scrollarea.setWidgetResizable(True)
- self.queue_scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- self.queue_scrollarea.setFrameStyle(QScrollArea.Plain | QScrollArea.NoFrame)
+ self.queue_scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+ self.queue_scrollarea.setFrameStyle(QScrollArea.Shadow.Plain | QScrollArea.Shape.NoFrame)
layout.addWidget(self.queue_scrollarea)
queue_contents = QWidget(self.queue_scrollarea)
- queue_contents.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ queue_contents.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.queue_scrollarea.setWidget(queue_contents)
self.queue_scrollarea.widget().setAutoFillBackground(False)
self.queue_scrollarea.viewport().setAutoFillBackground(False)
diff --git a/rare/components/tabs/downloads/download.py b/rare/components/tabs/downloads/download.py
index 840457c1e..9ca05ed91 100644
--- a/rare/components/tabs/downloads/download.py
+++ b/rare/components/tabs/downloads/download.py
@@ -31,17 +31,17 @@ def prepare_pixmap(self, pixmap: QPixmap) -> QPixmap:
device: QImage = QImage(
pixmap.size().width() * 1,
int(self.sizeHint().height() * pixmap.devicePixelRatioF()) + 1,
- QImage.Format_ARGB32_Premultiplied,
+ QImage.Format.Format_ARGB32_Premultiplied,
)
painter = QPainter(device)
brush = QBrush(pixmap)
painter.fillRect(device.rect(), brush)
# the gradient could be cached and reused as it is expensive
gradient = QLinearGradient(0, 0, device.width(), 0)
- gradient.setColorAt(0.02, Qt.transparent)
- gradient.setColorAt(0.5, Qt.black)
- gradient.setColorAt(0.98, Qt.transparent)
- painter.setCompositionMode(QPainter.CompositionMode_DestinationIn)
+ gradient.setColorAt(0.02, Qt.GlobalColor.transparent)
+ gradient.setColorAt(0.5, Qt.GlobalColor.black)
+ gradient.setColorAt(0.98, Qt.GlobalColor.transparent)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_DestinationIn)
painter.fillRect(device.rect(), gradient)
painter.end()
ret = QPixmap.fromImage(device)
@@ -59,11 +59,11 @@ def setPixmap(self, pixmap: QPixmap) -> None:
def paint_image_empty(self, painter: QPainter, a0: QPaintEvent) -> None:
# when pixmap object is not available yet, show a gray rectangle
painter.setOpacity(0.5 * self._opacity)
- painter.fillRect(a0.rect(), self.palette().color(QPalette.Window))
+ painter.fillRect(a0.rect(), self.palette().color(QPalette.ColorRole.Window))
def paint_image_cover(self, painter: QPainter, a0: QPaintEvent) -> None:
painter.setOpacity(self._opacity)
- color = self.palette().color(QPalette.Window).darker(75)
+ color = self.palette().color(QPalette.ColorRole.Window).darker(75)
painter.fillRect(self.rect(), color)
brush = QBrush(self._pixmap)
brush.setTransform(self._transform)
diff --git a/rare/components/tabs/downloads/groups.py b/rare/components/tabs/downloads/groups.py
index cd0869dbb..f80e5e0ab 100644
--- a/rare/components/tabs/downloads/groups.py
+++ b/rare/components/tabs/downloads/groups.py
@@ -29,7 +29,7 @@ def __init__(self, parent=None):
self.setObjectName(type(self).__name__)
self.setTitle(self.tr("Updates"))
self.__text = QLabel(self.tr("No updates available"))
- self.__text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.__text.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
# lk: For findChildren to work, the update's layout has to be in a widget
self.__container = QWidget(self)
@@ -45,7 +45,7 @@ def __find_widget(self, app_name: str) -> Optional[UpdateWidget]:
return self.__container.findChild(UpdateWidget, name=widget_object_name(UpdateWidget, app_name))
def count(self) -> int:
- return len(self.__container.findChildren(UpdateWidget, options=Qt.FindDirectChildrenOnly))
+ return len(self.__container.findChildren(UpdateWidget, options=Qt.FindChildOption.FindDirectChildrenOnly))
def contains(self, app_name: str) -> bool:
return self.__find_widget(app_name) is not None
@@ -92,7 +92,7 @@ def __init__(self, parent=None):
self.setObjectName(type(self).__name__)
self.setTitle(self.tr("Queue"))
self.__text = QLabel(self.tr("No downloads in queue"), self)
- self.__text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.__text.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
# lk: For findChildren to work, the queue's layout has to be in a widget
self.__container = QWidget(self)
diff --git a/rare/components/tabs/downloads/widgets.py b/rare/components/tabs/downloads/widgets.py
index fc239909b..7ca833386 100644
--- a/rare/components/tabs/downloads/widgets.py
+++ b/rare/components/tabs/downloads/widgets.py
@@ -37,7 +37,7 @@ def __init__(
self.image.setFixedSize(ImageSize.LibraryIcon)
self.ui.image_layout.addWidget(self.image)
- self.ui.queue_info_layout.setAlignment(Qt.AlignTop)
+ self.ui.queue_info_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
if game and igame:
self.update_information(game, igame, analysis, old_igame)
diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py
index 9aa32231e..80c36781d 100644
--- a/rare/components/tabs/games/__init__.py
+++ b/rare/components/tabs/games/__init__.py
@@ -54,7 +54,7 @@ def __init__(self, parent=None):
self.view_scroll = QScrollArea(self.games_page)
self.view_scroll.setWidgetResizable(True)
- self.view_scroll.setFrameShape(QFrame.StyledPanel)
+ self.view_scroll.setFrameShape(QFrame.Shape.StyledPanel)
self.view_scroll.horizontalScrollBar().setDisabled(True)
library_view = LibraryView(self.settings.value(*options.library_view))
diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py
index 5a6a802d3..c31502ab6 100644
--- a/rare/components/tabs/games/game_info/__init__.py
+++ b/rare/components/tabs/games/game_info/__init__.py
@@ -68,7 +68,7 @@ def update_game(self, rgame: RareGame):
self.setCurrentIndex(self.details_index)
def keyPressEvent(self, a0: QKeyEvent):
- if a0.key() == Qt.Key_Escape:
+ if a0.key() == Qt.Key.Key_Escape:
self.back_clicked.emit()
@@ -78,7 +78,7 @@ def __init__(self, parent=None):
self.implements_scrollarea = True
self.setColumnWidth(0, 300)
self.setWordWrap(True)
- self.setEditTriggers(QTreeView.NoEditTriggers)
+ self.setEditTriggers(QTreeView.EditTrigger.NoEditTriggers)
self.model = QJsonModel()
self.setModel(self.model)
self.rgame: Optional[RareGame] = None
diff --git a/rare/components/tabs/games/game_info/cloud_saves.py b/rare/components/tabs/games/game_info/cloud_saves.py
index c87769fb9..3946e06f9 100644
--- a/rare/components/tabs/games/game_info/cloud_saves.py
+++ b/rare/components/tabs/games/game_info/cloud_saves.py
@@ -62,19 +62,19 @@ def __init__(self, parent=None):
self.cloud_save_path_edit = PathEdit(
"",
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
placeholder=self.tr('Use "Calculate path" or "Browse" ...'),
edit_func=self.edit_save_path,
save_func=self.save_save_path,
)
self.cloud_ui.main_layout.setWidget(
self.cloud_ui.main_layout.getWidgetPosition(self.cloud_ui.path_label)[0],
- QFormLayout.FieldRole,
+ QFormLayout.ItemRole.FieldRole,
self.cloud_save_path_edit
)
self.compute_save_path_button = QPushButton(qta_icon("fa.magic"), self.tr("Calculate path"))
- self.compute_save_path_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
+ self.compute_save_path_button.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
self.compute_save_path_button.clicked.connect(self.compute_save_path)
self.cloud_ui.main_layout.addRow(None, self.compute_save_path_button)
@@ -88,9 +88,10 @@ def __init__(self, parent=None):
layout.addWidget(self.sync_widget)
layout.addWidget(self.cloud_widget)
layout.addWidget(self.info_label)
- layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding))
+ layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Expanding))
- def edit_save_path(self, text: str) -> Tuple[bool, str, int]:
+ @staticmethod
+ def edit_save_path(text: str) -> Tuple[bool, str, int]:
if platform.system() != "Windows":
if os.path.exists(text):
return True, text, IndicatorReasonsCommon.VALID
diff --git a/rare/components/tabs/games/game_info/details.py b/rare/components/tabs/games/game_info/details.py
index 60a50042f..cf61153ed 100644
--- a/rare/components/tabs/games/game_info/details.py
+++ b/rare/components/tabs/games/game_info/details.py
@@ -59,7 +59,7 @@ def __init__(self, parent=None):
self.image = ImageWidget(self)
self.image.setFixedSize(ImageSize.DisplayTall)
- self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
+ self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignmentFlag.AlignTop)
self.ui.install_button.clicked.connect(self.__on_install)
self.ui.import_button.clicked.connect(self.__on_import)
diff --git a/rare/components/tabs/games/game_info/dlcs.py b/rare/components/tabs/games/game_info/dlcs.py
index 80edd1667..83c599712 100644
--- a/rare/components/tabs/games/game_info/dlcs.py
+++ b/rare/components/tabs/games/game_info/dlcs.py
@@ -111,23 +111,23 @@ def __init__(self, parent=None):
self.rgame: Optional[RareGame] = None
def list_installed(self) -> List[InstalledGameDlcWidget]:
- return self.ui.installed_dlc_container.findChildren(InstalledGameDlcWidget, options=Qt.FindDirectChildrenOnly)
+ return self.ui.installed_dlc_container.findChildren(InstalledGameDlcWidget, options=Qt.FindChildOption.FindDirectChildrenOnly)
def list_available(self) -> List[AvailableGameDlcWidget]:
- return self.ui.available_dlc_container.findChildren(AvailableGameDlcWidget, options=Qt.FindDirectChildrenOnly)
+ return self.ui.available_dlc_container.findChildren(AvailableGameDlcWidget, options=Qt.FindChildOption.FindDirectChildrenOnly)
def get_installed(self, app_name: str) -> Optional[InstalledGameDlcWidget]:
return self.ui.installed_dlc_container.findChild(
InstalledGameDlcWidget,
name=widget_object_name(InstalledGameDlcWidget, app_name),
- options=Qt.FindDirectChildrenOnly
+ options=Qt.FindChildOption.FindDirectChildrenOnly
)
def get_available(self, app_name: str) -> Optional[AvailableGameDlcWidget]:
return self.ui.available_dlc_container.findChild(
AvailableGameDlcWidget,
name=widget_object_name(AvailableGameDlcWidget, app_name),
- options=Qt.FindDirectChildrenOnly
+ options=Qt.FindChildOption.FindDirectChildrenOnly
)
def update_installed_page(self):
diff --git a/rare/components/tabs/games/game_info/settings.py b/rare/components/tabs/games/game_info/settings.py
index c693b5f26..932a7af02 100644
--- a/rare/components/tabs/games/game_info/settings.py
+++ b/rare/components/tabs/games/game_info/settings.py
@@ -55,7 +55,7 @@ def __init__(self, parent=None):
self.offline_combo.currentIndexChanged.connect(self.__offline_changed)
self.override_exe_edit = PathEdit(
- file_mode=QFileDialog.ExistingFile,
+ file_mode=QFileDialog.FileMode.ExistingFile,
name_filters=["*.exe", "*.app"],
placeholder=self.tr("Relative path to the replacement executable"),
edit_func=self.__override_exe_edit_callback,
@@ -77,10 +77,10 @@ def showEvent(self, a0: QShowEvent):
return super().showEvent(a0)
skip_update = config.get_option(self.app_name, "skip_update_check", fallback=None)
- self.skip_update_combo.setCurrentIndex(self.offline_combo.findData(skip_update, Qt.UserRole))
+ self.skip_update_combo.setCurrentIndex(self.offline_combo.findData(skip_update, Qt.ItemDataRole.UserRole))
offline = config.get_option(self.app_name, "offline", fallback=None)
- self.offline_combo.setCurrentIndex(self.offline_combo.findData(offline, Qt.UserRole))
+ self.offline_combo.setCurrentIndex(self.offline_combo.findData(offline, Qt.ItemDataRole.UserRole))
if self.igame:
self.offline_combo.setEnabled(self.igame.can_run_offline)
@@ -99,7 +99,7 @@ def showEvent(self, a0: QShowEvent):
@pyqtSlot(int)
def __skip_update_changed(self, index):
- data = self.skip_update_combo.itemData(index, Qt.UserRole)
+ data = self.skip_update_combo.itemData(index, Qt.ItemDataRole.UserRole)
config.save_option(self.app_name, "skip_update_check", data)
def __override_exe_edit_callback(self, path: str) -> Tuple[bool, str, int]:
@@ -125,7 +125,7 @@ def __override_exe_save_callback(self, path: str):
@pyqtSlot(int)
def __offline_changed(self, index):
- data = self.skip_update_combo.itemData(index, Qt.UserRole)
+ data = self.skip_update_combo.itemData(index, Qt.ItemDataRole.UserRole)
config.save_option(self.app_name, "offline", data)
def __launch_params_changed(self, value) -> None:
diff --git a/rare/components/tabs/games/game_widgets/__init__.py b/rare/components/tabs/games/game_widgets/__init__.py
index 6c3950f9c..904fc6535 100644
--- a/rare/components/tabs/games/game_widgets/__init__.py
+++ b/rare/components/tabs/games/game_widgets/__init__.py
@@ -92,7 +92,7 @@ def __init__(self, rcore: RareCore, parent=None):
view_layout = LibraryLayout(self)
view_layout.setSpacing(9)
view_layout.setContentsMargins(0, 13, 0, 13)
- view_layout.setAlignment(Qt.AlignTop)
+ view_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.setLayout(view_layout)
def add_widget(self, rgame: RareGame) -> IconGameWidget:
@@ -137,7 +137,7 @@ def __init__(self, rcore, parent=None):
super().__init__(rcore, parent=parent)
view_layout = QVBoxLayout(self)
view_layout.setContentsMargins(3, 3, 9, 3)
- view_layout.setAlignment(Qt.AlignTop)
+ view_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.setLayout(view_layout)
def add_widget(self, rgame: RareGame) -> ListGameWidget:
diff --git a/rare/components/tabs/games/game_widgets/game_widget.py b/rare/components/tabs/games/game_widgets/game_widget.py
index aa2fa0c16..8c5d7e097 100644
--- a/rare/components/tabs/games/game_widgets/game_widget.py
+++ b/rare/components/tabs/games/game_widgets/game_widget.py
@@ -35,7 +35,7 @@ def __init__(self, rgame: RareGame, parent=None):
self.rgame: RareGame = rgame
- self.setContextMenuPolicy(Qt.ActionsContextMenu)
+ self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
self.launch_action = QAction(self.tr("Launch"), self)
self.launch_action.triggered.connect(self._launch)
@@ -104,7 +104,7 @@ def __init__(self, rgame: RareGame, parent=None):
def paintEvent(self, a0: QPaintEvent) -> None:
if not self.visibleRegion().isNull() and not self.rgame.has_pixmap:
- self.startTimer(random.randrange(42, 2361, 129), Qt.CoarseTimer)
+ self.startTimer(random.randrange(42, 2361, 129), Qt.TimerType.CoarseTimer)
# self.startTimer(random.randrange(42, 2361, 363), Qt.VeryCoarseTimer)
# self.rgame.load_pixmap()
super().paintEvent(a0)
@@ -183,7 +183,7 @@ def update_actions(self):
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
if a0 is self.ui.launch_btn:
- if a1.type() == QEvent.Enter:
+ if a1.type() == QEvent.Type.Enter:
if not self.rgame.can_launch:
self.ui.tooltip_label.setText(self.hover_strings["not_can_launch"])
elif self.rgame.is_origin:
@@ -195,18 +195,18 @@ def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
elif self.rgame.can_launch:
self.ui.tooltip_label.setText(self.hover_strings["can_launch"])
return True
- if a1.type() == QEvent.Leave:
+ if a1.type() == QEvent.Type.Leave:
self.ui.tooltip_label.setText(self.hover_strings["info"])
# return True
if a0 is self.ui.install_btn:
- if a1.type() == QEvent.Enter:
+ if a1.type() == QEvent.Type.Enter:
self.ui.tooltip_label.setText(self.hover_strings["install"])
return True
- if a1.type() == QEvent.Leave:
+ if a1.type() == QEvent.Type.Leave:
self.ui.tooltip_label.setText(self.hover_strings["info"])
# return True
if a0 is self:
- if a1.type() == QEvent.Enter:
+ if a1.type() == QEvent.Type.Enter:
self.ui.tooltip_label.setText(self.hover_strings["info"])
return super(GameWidget, self).eventFilter(a0, a1)
diff --git a/rare/components/tabs/games/game_widgets/icon_widget.py b/rare/components/tabs/games/game_widgets/icon_widget.py
index 2f3ddd352..9daaa4324 100644
--- a/rare/components/tabs/games/game_widgets/icon_widget.py
+++ b/rare/components/tabs/games/game_widgets/icon_widget.py
@@ -46,8 +46,8 @@ def setupUi(self, widget: QWidget):
# game title
self.title_label = QLabel(parent=self.mini_widget)
self.title_label.setObjectName(f"{type(self).__name__}TitleLabel")
- self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
- self.title_label.setAlignment(Qt.AlignVCenter)
+ self.title_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
+ self.title_label.setAlignment(Qt.AlignmentFlag.AlignVCenter)
self.title_label.setAutoFillBackground(False)
self.title_label.setWordWrap(True)
@@ -73,8 +73,8 @@ def setupUi(self, widget: QWidget):
# When the button gets clicked on, it receives keyboard focus. Disabling the button
# afterwards leads to `focusNextChild` getting called. This makes the scrollarea
# trying to ensure that `nextChild` is visible, essentially scrolling to a random widget
- self.launch_btn.setFocusPolicy(Qt.NoFocus)
- self.install_btn.setFocusPolicy(Qt.NoFocus)
+ self.launch_btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
+ self.install_btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
# Create layouts
# layout on top of the image, holds the status label, a spacer item and the mini widget
@@ -88,7 +88,7 @@ def setupUi(self, widget: QWidget):
# layout for the top row, holds the title and the launch button
row_layout = QHBoxLayout()
row_layout.setSpacing(0)
- row_layout.setAlignment(Qt.AlignTop)
+ row_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
# Layout the widgets
# (from inner to outer)
@@ -100,11 +100,11 @@ def setupUi(self, widget: QWidget):
self.mini_widget.setLayout(mini_layout)
image_layout.addWidget(self.status_label)
- image_layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
+ image_layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding))
image_layout.addWidget(self.mini_widget)
widget.setLayout(image_layout)
- widget.setContextMenuPolicy(Qt.ActionsContextMenu)
+ widget.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
widget.leaveEvent(None)
self.translateUi(widget)
@@ -117,13 +117,13 @@ def enterAnimation(self, widget: QWidget):
self._animation.setDuration(250)
self._animation.setStartValue(0)
self._animation.setEndValue(1)
- self._animation.setEasingCurve(QEasingCurve.InSine)
- self._animation.start(QPropertyAnimation.DeleteWhenStopped)
+ self._animation.setEasingCurve(QEasingCurve.Type.InSine)
+ self._animation.start(QPropertyAnimation.DeletionPolicy.DeleteWhenStopped)
def leaveAnimation(self, widget: QWidget):
self._animation = QPropertyAnimation(self.mini_effect, b"opacity")
self._animation.setDuration(150)
self._animation.setStartValue(1)
self._animation.setEndValue(0)
- self._animation.setEasingCurve(QEasingCurve.OutSine)
- self._animation.start(QPropertyAnimation.DeleteWhenStopped)
+ self._animation.setEasingCurve(QEasingCurve.Type.OutSine)
+ self._animation.start(QPropertyAnimation.DeletionPolicy.DeleteWhenStopped)
diff --git a/rare/components/tabs/games/game_widgets/library_widget.py b/rare/components/tabs/games/game_widgets/library_widget.py
index acb331bb2..e812886be 100644
--- a/rare/components/tabs/games/game_widgets/library_widget.py
+++ b/rare/components/tabs/games/game_widgets/library_widget.py
@@ -13,8 +13,8 @@ def __init__(self, parent=None):
if self.parent() is not None:
self.parent().installEventFilter(self)
self.setObjectName(type(self).__name__)
- self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
- self.setFrameStyle(QLabel.StyledPanel)
+ self.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
+ self.setFrameStyle(QLabel.Shape.StyledPanel)
def __center_on_parent(self):
fm = QFontMetrics(self.font())
@@ -23,10 +23,10 @@ def __center_on_parent(self):
self.setGeometry(rect)
def event(self, e: QEvent) -> bool:
- if e.type() == QEvent.ParentAboutToChange:
+ if e.type() == QEvent.Type.ParentAboutToChange:
if self.parent() is not None:
self.parent().removeEventFilter(self)
- if e.type() == QEvent.ParentChange:
+ if e.type() == QEvent.Type.ParentChange:
if self.parent() is not None:
self.parent().installEventFilter(self)
return super().event(e)
@@ -38,7 +38,7 @@ def showEvent(self, a0: QShowEvent) -> None:
super().showEvent(a0)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
- if a0 is self.parent() and a1.type() == QEvent.Resize:
+ if a0 is self.parent() and a1.type() == QEvent.Type.Resize:
self.__center_on_parent()
return a0.event(a1)
return False
@@ -92,8 +92,8 @@ def progressPixmap(self, color: QPixmap, gray: QPixmap, progress: int) -> QPixma
device = QPixmap(color.size())
painter = QPainter(device)
- painter.setRenderHint(QPainter.SmoothPixmapTransform, self._smooth_transform)
- painter.setCompositionMode(QPainter.CompositionMode_Source)
+ painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, self._smooth_transform)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source)
# lk: Vertical loading
# prog_h = (device.height() * progress // 100)
# brush = QBrush(gray)
diff --git a/rare/components/tabs/games/game_widgets/list_game_widget.py b/rare/components/tabs/games/game_widgets/list_game_widget.py
index dd165c087..d9e066d5b 100644
--- a/rare/components/tabs/games/game_widgets/list_game_widget.py
+++ b/rare/components/tabs/games/game_widgets/list_game_widget.py
@@ -84,17 +84,17 @@ def prepare_pixmap(self, pixmap: QPixmap) -> QPixmap:
device: QImage = QImage(
pixmap.size().width() * 1,
int(self.sizeHint().height() * pixmap.devicePixelRatioF()) + 1,
- QImage.Format_ARGB32_Premultiplied
+ QImage.Format.Format_ARGB32_Premultiplied
)
painter = QPainter(device)
brush = QBrush(pixmap)
painter.fillRect(device.rect(), brush)
# the gradient could be cached and reused as it is expensive
gradient = QLinearGradient(0, 0, device.width(), 0)
- gradient.setColorAt(0.02, Qt.transparent)
- gradient.setColorAt(0.5, Qt.black)
- gradient.setColorAt(0.98, Qt.transparent)
- painter.setCompositionMode(QPainter.CompositionMode_DestinationIn)
+ gradient.setColorAt(0.02, Qt.GlobalColor.transparent)
+ gradient.setColorAt(0.5, Qt.GlobalColor.black)
+ gradient.setColorAt(0.98, Qt.GlobalColor.transparent)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_DestinationIn)
painter.fillRect(device.rect(), gradient)
painter.end()
ret = QPixmap.fromImage(device)
@@ -111,7 +111,7 @@ def setPixmap(self, pixmap: QPixmap) -> None:
def paint_image_cover(self, painter: QPainter, a0: QPaintEvent) -> None:
painter.setOpacity(self._opacity)
- color = self.palette().color(QPalette.Window).darker(75)
+ color = self.palette().color(QPalette.ColorRole.Window).darker(75)
painter.fillRect(self.rect(), color)
brush = QBrush(self._pixmap)
brush.setTransform(self._transform)
@@ -129,8 +129,8 @@ def progressPixmap(self, color: QPixmap, gray: QPixmap, progress: int) -> QPixma
int(self.sizeHint().height() * color.devicePixelRatioF()) + 1,
)
painter = QPainter(device)
- painter.setRenderHint(QPainter.SmoothPixmapTransform, self._smooth_transform)
- painter.setCompositionMode(QPainter.CompositionMode_Source)
+ painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, self._smooth_transform)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source)
prog_h = (device.height() * progress // 100)
brush = QBrush(gray)
painter.fillRect(device.rect().adjusted(0, 0, 0, -prog_h), brush)
diff --git a/rare/components/tabs/games/game_widgets/list_widget.py b/rare/components/tabs/games/game_widgets/list_widget.py
index 045a851fa..7fe6308de 100644
--- a/rare/components/tabs/games/game_widgets/list_widget.py
+++ b/rare/components/tabs/games/game_widgets/list_widget.py
@@ -32,30 +32,30 @@ def setupUi(self, widget: QWidget):
self.status_label = QLabel(parent=widget)
self.status_label.setObjectName(f"{type(self).__name__}StatusLabel")
- self.status_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
+ self.status_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
self.tooltip_label = QLabel(parent=widget)
self.tooltip_label.setObjectName(f"{type(self).__name__}TooltipLabel")
- self.tooltip_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
+ self.tooltip_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
self.install_btn = QPushButton(parent=widget)
self.install_btn.setObjectName(f"{type(self).__name__}Button")
self.install_btn.setIcon(qta_icon("ri.install-line"))
- self.install_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.install_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.install_btn.setFixedWidth(120)
self.launch_btn = QPushButton(parent=widget)
self.launch_btn.setObjectName(f"{type(self).__name__}Button")
self.launch_btn.setIcon(qta_icon("ei.play-alt"))
- self.launch_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.launch_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.launch_btn.setFixedWidth(120)
# lk: do not focus on button
# When the button gets clicked on, it receives keyboard focus. Disabling the button
# afterwards leads to `focusNextChild` getting called. This makes the scrollarea
# trying to ensure that `nextChild` is visible, essentially scrolling to a random widget
- self.launch_btn.setFocusPolicy(Qt.NoFocus)
- self.install_btn.setFocusPolicy(Qt.NoFocus)
+ self.launch_btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
+ self.install_btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
self.developer_label = ElideLabel(parent=widget)
self.developer_label.setObjectName(f"{type(self).__name__}InfoLabel")
@@ -67,15 +67,15 @@ def setupUi(self, widget: QWidget):
self.size_label = ElideLabel(parent=widget)
self.size_label.setObjectName(f"{type(self).__name__}InfoLabel")
- self.size_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+ self.size_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.size_label.setFixedWidth(60)
# Create layouts
left_layout = QVBoxLayout()
- left_layout.setAlignment(Qt.AlignLeft)
+ left_layout.setAlignment(Qt.AlignmentFlag.AlignLeft)
bottom_layout = QHBoxLayout()
- bottom_layout.setAlignment(Qt.AlignRight)
+ bottom_layout.setAlignment(Qt.AlignmentFlag.AlignRight)
layout = QHBoxLayout()
layout.setSpacing(0)
@@ -85,25 +85,25 @@ def setupUi(self, widget: QWidget):
# (from inner to outer)
left_layout.addWidget(self.title_label, stretch=1)
- bottom_layout.addWidget(self.developer_label, stretch=0, alignment=Qt.AlignLeft)
- bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))
- bottom_layout.addWidget(self.version_label, stretch=0, alignment=Qt.AlignLeft)
- bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))
- bottom_layout.addWidget(self.size_label, stretch=0, alignment=Qt.AlignLeft)
- bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))
- bottom_layout.addWidget(self.status_label, stretch=0, alignment=Qt.AlignLeft)
- bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))
- bottom_layout.addWidget(self.tooltip_label, stretch=0, alignment=Qt.AlignRight)
+ bottom_layout.addWidget(self.developer_label, stretch=0, alignment=Qt.AlignmentFlag.AlignLeft)
+ bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum))
+ bottom_layout.addWidget(self.version_label, stretch=0, alignment=Qt.AlignmentFlag.AlignLeft)
+ bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum))
+ bottom_layout.addWidget(self.size_label, stretch=0, alignment=Qt.AlignmentFlag.AlignLeft)
+ bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum))
+ bottom_layout.addWidget(self.status_label, stretch=0, alignment=Qt.AlignmentFlag.AlignLeft)
+ bottom_layout.addItem(QSpacerItem(20, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum))
+ bottom_layout.addWidget(self.tooltip_label, stretch=0, alignment=Qt.AlignmentFlag.AlignRight)
left_layout.addLayout(bottom_layout)
layout.addLayout(left_layout)
- layout.addWidget(self.install_btn, stretch=0, alignment=Qt.AlignRight)
- layout.addWidget(self.launch_btn, stretch=0, alignment=Qt.AlignRight)
+ layout.addWidget(self.install_btn, stretch=0, alignment=Qt.AlignmentFlag.AlignRight)
+ layout.addWidget(self.launch_btn, stretch=0, alignment=Qt.AlignmentFlag.AlignRight)
widget.setLayout(layout)
- widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
widget.setFixedHeight(widget.sizeHint().height())
widget.leaveEvent(None)
diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py
index 6c69122f9..b2ca6d195 100644
--- a/rare/components/tabs/games/head_bar.py
+++ b/rare/components/tabs/games/head_bar.py
@@ -6,12 +6,12 @@
QHBoxLayout,
QWidget,
QPushButton,
-)
-from PyQt5.QtWidgets import (
QLabel,
QComboBox,
QMenu,
- QAction, QSpacerItem, QSizePolicy,
+ QAction,
+ QSpacerItem,
+ QSizePolicy,
)
from rare.models.options import options, LibraryFilter, LibraryOrder
@@ -54,7 +54,7 @@ def __init__(self, parent=None):
try:
_filter = LibraryFilter(self.settings.value(*options.library_filter))
- if (index := self.filter.findData(_filter, Qt.UserRole)) < 0:
+ if (index := self.filter.findData(_filter, Qt.ItemDataRole.UserRole)) < 0:
raise ValueError(f"Filter '{_filter}' is not available")
else:
self.filter.setCurrentIndex(index)
@@ -62,7 +62,7 @@ def __init__(self, parent=None):
self.logger.error("Error while loading library: %s", e)
self.settings.setValue(options.library_filter.key, options.library_filter.default)
_filter = LibraryFilter(options.library_filter.default)
- self.filter.setCurrentIndex(self.filter.findData(_filter, Qt.UserRole))
+ self.filter.setCurrentIndex(self.filter.findData(_filter, Qt.ItemDataRole.UserRole))
self.filter.currentIndexChanged.connect(self.__filter_changed)
self.order = QComboBox(parent=self)
@@ -77,7 +77,7 @@ def __init__(self, parent=None):
try:
_order = LibraryOrder(self.settings.value(*options.library_order))
- if (index := self.order.findData(_order, Qt.UserRole)) < 0:
+ if (index := self.order.findData(_order, Qt.ItemDataRole.UserRole)) < 0:
raise ValueError(f"Order '{_order}' is not available")
else:
self.order.setCurrentIndex(index)
@@ -85,7 +85,7 @@ def __init__(self, parent=None):
self.logger.error("Error while loading library: %s", e)
self.settings.setValue(options.library_order.key, options.library_order.default)
_order = LibraryOrder(options.library_order.default)
- self.order.setCurrentIndex(self.order.findData(_order, Qt.UserRole))
+ self.order.setCurrentIndex(self.order.findData(_order, Qt.ItemDataRole.UserRole))
self.order.currentIndexChanged.connect(self.__order_changed)
integrations_menu = QMenu(parent=self)
@@ -111,7 +111,7 @@ def __init__(self, parent=None):
integrations.setMenu(integrations_menu)
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search"))
- self.search_bar.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
+ self.search_bar.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Preferred)
self.search_bar.setObjectName("SearchBar")
self.search_bar.setMinimumWidth(250)
@@ -139,13 +139,13 @@ def __init__(self, parent=None):
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.filter)
layout.addWidget(self.order)
- layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed))
+ layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
layout.addWidget(self.search_bar)
layout.addWidget(self.installed_icon)
layout.addWidget(self.installed_label)
layout.addWidget(self.available_icon)
layout.addWidget(self.available_label)
- layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed))
+ layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
layout.addWidget(integrations)
layout.addWidget(self.refresh_list)
@@ -158,20 +158,20 @@ def __refresh_clicked(self):
self.rcore.fetch()
def current_filter(self) -> LibraryFilter:
- return self.filter.currentData(Qt.UserRole)
+ return self.filter.currentData(Qt.ItemDataRole.UserRole)
@pyqtSlot(int)
def __filter_changed(self, index: int):
- data = self.filter.itemData(index, Qt.UserRole)
+ data = self.filter.itemData(index, Qt.ItemDataRole.UserRole)
self.filterChanged.emit(data)
self.settings.setValue(options.library_filter.key, int(data))
def current_order(self) -> LibraryOrder:
- return self.order.currentData(Qt.UserRole)
+ return self.order.currentData(Qt.ItemDataRole.UserRole)
@pyqtSlot(int)
def __order_changed(self, index: int):
- data = self.order.itemData(index, Qt.UserRole)
+ data = self.order.itemData(index, Qt.ItemDataRole.UserRole)
self.orderChanged.emit(data)
self.settings.setValue(options.library_order.key, int(data))
diff --git a/rare/components/tabs/games/integrations/__init__.py b/rare/components/tabs/games/integrations/__init__.py
index 0e9eb6bb2..def0b3363 100644
--- a/rare/components/tabs/games/integrations/__init__.py
+++ b/rare/components/tabs/games/integrations/__init__.py
@@ -62,7 +62,8 @@ def __init__(self, widget: Optional[QWidget], info: str, parent=None):
if widget is not None:
self.__layout.addWidget(widget)
self.__layout.addWidget(self.info)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
- def addWidget(self, widget: QWidget, stretch: int = 0, alignment: Qt.AlignmentFlag = Qt.Alignment()):
+ def addWidget(self, widget: QWidget, stretch: int = 0, alignment: Qt.AlignmentFlag = None):
+ alignment = alignment if alignment is not None else Qt.AlignmentFlag(0)
self.__layout.insertWidget(self.layout().count() - 1, widget, stretch, alignment)
diff --git a/rare/components/tabs/games/integrations/egl_sync_group.py b/rare/components/tabs/games/integrations/egl_sync_group.py
index f2478bfeb..71ac5a37d 100644
--- a/rare/components/tabs/games/integrations/egl_sync_group.py
+++ b/rare/components/tabs/games/integrations/egl_sync_group.py
@@ -35,20 +35,20 @@ def __init__(self, parent=None):
placeholder=self.tr(
"Path to the Wine prefix where EGL is installed, or the Manifests folder"
),
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
edit_func=self.egl_path_edit_edit_cb,
save_func=self.egl_path_edit_save_cb,
parent=self,
)
self.ui.egl_sync_layout.setWidget(
self.ui.egl_sync_layout.getWidgetPosition(self.ui.egl_path_edit_label)[0],
- QFormLayout.FieldRole, self.egl_path_edit
+ QFormLayout.ItemRole.FieldRole, self.egl_path_edit
)
self.egl_path_info = ElideLabel(parent=self)
self.ui.egl_sync_layout.setWidget(
self.ui.egl_sync_layout.getWidgetPosition(self.ui.egl_path_info_label)[0],
- QFormLayout.FieldRole, self.egl_path_info
+ QFormLayout.ItemRole.FieldRole, self.egl_path_info
)
if platform.system() == "Windows":
@@ -145,21 +145,21 @@ def egl_path_edit_save_cb(self, path):
def egl_path_changed(self, path):
if self.egl_path_edit.is_valid:
self.ui.egl_sync_check.setEnabled(bool(path))
- self.ui.egl_sync_check.setCheckState(Qt.Unchecked)
+ self.ui.egl_sync_check.setCheckState(Qt.CheckState.Unchecked)
# self.egl_watcher.removePaths([p for p in self.egl_watcher.directories()])
# self.egl_watcher.addPaths([path])
self.update_lists()
def egl_sync_changed(self, state):
- if state == Qt.Unchecked:
+ if state == Qt.CheckState.Unchecked:
self.import_list.setEnabled(bool(self.import_list.items))
self.export_list.setEnabled(bool(self.export_list.items))
self.core.lgd.config.remove_option("Legendary", "egl_sync")
else:
self.core.lgd.config.set("Legendary", "egl_sync", str(True))
# lk: do import/export here since automatic sync was selected
- self.import_list.mark(Qt.Checked)
- self.export_list.mark(Qt.Checked)
+ self.import_list.mark(Qt.CheckState.Checked)
+ self.export_list.mark(Qt.CheckState.Checked)
sync_worker = EGLSyncWorker(self.import_list, self.export_list)
QThreadPool.globalInstance().start(sync_worker)
self.import_list.setEnabled(False)
@@ -191,13 +191,13 @@ class EGLSyncListItem(QListWidgetItem):
def __init__(self, game: Union[EGLManifest,InstalledGame], parent=None):
super(EGLSyncListItem, self).__init__(parent=parent)
self.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
- self.setCheckState(Qt.Unchecked)
+ self.setCheckState(Qt.CheckState.Unchecked)
self.core = RareCore.instance().core()
self.game = game
self.setText(self.app_title)
def is_checked(self) -> bool:
- return self.checkState() == Qt.Checked
+ return self.checkState() == Qt.CheckState.Checked
@abstractmethod
def action(self) -> Union[str, bool]:
@@ -254,19 +254,19 @@ def __init__(self, parent=None):
super(EGLSyncListGroup, self).__init__(parent=parent)
self.ui = Ui_EGLSyncListGroup()
self.ui.setupUi(self)
- self.ui.list.setFrameShape(QFrame.NoFrame)
+ self.ui.list.setFrameShape(QFrame.Shape.NoFrame)
self.rcore = RareCore.instance()
self.core = RareCore.instance().core()
self.ui.list.itemDoubleClicked.connect(
- lambda item: item.setCheckState(Qt.Unchecked)
- if item.checkState() != Qt.Unchecked
- else item.setCheckState(Qt.Checked)
+ lambda item: item.setCheckState(Qt.CheckState.Unchecked)
+ if item.checkState() != Qt.CheckState.Unchecked
+ else item.setCheckState(Qt.CheckState.Checked)
)
self.ui.list.itemChanged.connect(self.has_selected)
- self.ui.select_all_button.clicked.connect(lambda: self.mark(Qt.Checked))
- self.ui.select_none_button.clicked.connect(lambda: self.mark(Qt.Unchecked))
+ self.ui.select_all_button.clicked.connect(lambda: self.mark(Qt.CheckState.Checked))
+ self.ui.select_none_button.clicked.connect(lambda: self.mark(Qt.CheckState.Unchecked))
self.ui.action_button.clicked.connect(self.action)
diff --git a/rare/components/tabs/games/integrations/eos_group.py b/rare/components/tabs/games/integrations/eos_group.py
index fae747be6..b4c1cb247 100644
--- a/rare/components/tabs/games/integrations/eos_group.py
+++ b/rare/components/tabs/games/integrations/eos_group.py
@@ -46,11 +46,11 @@ def run(self) -> None:
class EosPrefixWidget(QFrame):
def __init__(self, overlay: RareEosOverlay, prefix: Optional[str], parent=None):
super(EosPrefixWidget, self).__init__(parent=parent)
- self.setFrameShape(QFrame.StyledPanel)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.indicator = QLabel(parent=self)
- self.indicator.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
+ self.indicator.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Preferred)
self.prefix_label = ElideLabel(
prefix.replace(os.path.expanduser("~"), "~") if prefix is not None else overlay.app_title,
@@ -86,7 +86,7 @@ def __init__(self, overlay: RareEosOverlay, prefix: Optional[str], parent=None):
@pyqtSlot(int)
def path_changed(self, index: int) -> None:
- path = self.path_select.itemData(index, Qt.UserRole)
+ path = self.path_select.itemData(index, Qt.ItemDataRole.UserRole)
active_path = os.path.normpath(p) if (p := self.overlay.active_path(self.prefix)) else ""
if self.overlay.is_enabled(self.prefix) and (path == active_path):
self.button.setText(self.tr("Disable overlay"))
@@ -115,18 +115,18 @@ def update_state(self) -> None:
install_path = os.path.normpath(p) if (p := self.overlay.install_path) else ""
self.path_select.addItem("Auto-detect", "")
- self.path_select.setItemData(0, "Auto-detect", Qt.ToolTipRole)
+ self.path_select.setItemData(0, "Auto-detect", Qt.ItemDataRole.ToolTipRole)
for path in self.overlay.available_paths(self.prefix):
path = os.path.normpath(path)
self.path_select.addItem("Legendary-managed" if path == install_path else "EGL-managed", path)
- self.path_select.setItemData(self.path_select.findData(path), path, Qt.ToolTipRole)
+ self.path_select.setItemData(self.path_select.findData(path), path, Qt.ItemDataRole.ToolTipRole)
self.path_select.setCurrentIndex(self.path_select.findData(active_path))
self.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE)
@pyqtSlot()
def action(self) -> None:
- path = self.path_select.currentData(Qt.UserRole)
+ path = self.path_select.currentData(Qt.ItemDataRole.UserRole)
active_path = os.path.normpath(p) if (p := self.overlay.active_path(self.prefix)) else ""
install_path = os.path.normpath(p) if (p := self.overlay.install_path) else ""
if self.overlay.is_enabled(self.prefix) and (path == active_path):
@@ -168,8 +168,8 @@ def __init__(self, parent=None):
self.ui.install_button.setObjectName("InstallButton")
self.ui.uninstall_button.setObjectName("UninstallButton")
- self.ui.install_page_layout.setAlignment(Qt.AlignTop)
- self.ui.info_page_layout.setAlignment(Qt.AlignTop)
+ self.ui.install_page_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
+ self.ui.info_page_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.ui.install_button.setIcon(qta_icon("ri.install-line"))
self.ui.uninstall_button.setIcon(qta_icon("ri.uninstall-line"))
@@ -177,8 +177,8 @@ def __init__(self, parent=None):
self.installed_path_label = ElideLabel(parent=self)
self.installed_version_label = ElideLabel(parent=self)
- self.ui.info_label_layout.setWidget(0, QFormLayout.FieldRole, self.installed_version_label)
- self.ui.info_label_layout.setWidget(1, QFormLayout.FieldRole, self.installed_path_label)
+ self.ui.info_label_layout.setWidget(0, QFormLayout.ItemRole.FieldRole, self.installed_version_label)
+ self.ui.info_label_layout.setWidget(1, QFormLayout.ItemRole.FieldRole, self.installed_path_label)
self.rcore = RareCore.instance()
self.core = self.rcore.core()
@@ -219,7 +219,7 @@ def update_state(self):
self.ui.uninstall_button.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE)
def update_prefixes(self):
- for widget in self.findChildren(EosPrefixWidget, options=Qt.FindDirectChildrenOnly):
+ for widget in self.findChildren(EosPrefixWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
widget.deleteLater()
if platform.system() != "Windows":
diff --git a/rare/components/tabs/games/integrations/import_group.py b/rare/components/tabs/games/integrations/import_group.py
index 20237f7a0..8650b615d 100644
--- a/rare/components/tabs/games/integrations/import_group.py
+++ b/rare/components/tabs/games/integrations/import_group.py
@@ -163,15 +163,15 @@ def __init__(self, app_names: Set[Tuple[str, str]], parent=None):
self.setPopup(treeview)
treeview.setRootIsDecorated(False)
treeview.header().hide()
- treeview.header().setSectionResizeMode(0, QHeaderView.Stretch)
- treeview.header().setSectionResizeMode(1, QHeaderView.Stretch)
+ treeview.header().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
+ treeview.header().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
# listview = QListView()
# self.setPopup(listview)
# # listview.setModelColumn(1)
- self.setFilterMode(Qt.MatchContains)
- self.setCaseSensitivity(Qt.CaseInsensitive)
+ self.setFilterMode(Qt.MatchFlag.MatchContains)
+ self.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
# self.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
def __activated_idx(self, idx):
@@ -201,14 +201,14 @@ def __init__(self, parent=None):
self.path_edit = PathEdit(
self.core.get_default_install_dir(self.core.default_platform),
- QFileDialog.DirectoryOnly,
+ QFileDialog.FileMode.Directory,
edit_func=self.path_edit_callback,
parent=self,
)
self.path_edit.textChanged.connect(self.path_changed)
self.ui.import_layout.setWidget(
self.ui.import_layout.getWidgetPosition(self.ui.path_edit_label)[0],
- QFormLayout.FieldRole, self.path_edit
+ QFormLayout.ItemRole.FieldRole, self.path_edit
)
self.app_name_edit = IndicatorLineEdit(
@@ -220,7 +220,7 @@ def __init__(self, parent=None):
self.app_name_edit.textChanged.connect(self.app_name_changed)
self.ui.import_layout.setWidget(
self.ui.import_layout.getWidgetPosition(self.ui.app_name_label)[0],
- QFormLayout.FieldRole, self.app_name_edit
+ QFormLayout.ItemRole.FieldRole, self.app_name_edit
)
self.ui.import_folder_check.stateChanged.connect(self.import_folder_changed)
@@ -234,11 +234,11 @@ def __init__(self, parent=None):
)
self.button_info_stack = QStackedWidget(self)
- self.button_info_stack.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.button_info_stack.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.button_info_stack.setFixedHeight(self.ui.import_button.sizeHint().height())
self.info_label = ElideLabel(text="", parent=self.button_info_stack)
self.info_label.setFixedHeight(False)
- self.info_label.setAlignment(Qt.AlignVCenter)
+ self.info_label.setAlignment(Qt.AlignmentFlag.AlignVCenter)
self.info_progress = QProgressBar(self.button_info_stack)
self.button_info_stack.addWidget(self.info_label)
self.button_info_stack.addWidget(self.info_progress)
@@ -274,8 +274,8 @@ def path_edit_callback(self, path) -> Tuple[bool, str, int]:
@pyqtSlot(str)
def path_changed(self, path: str):
self.info_label.setText("")
- self.ui.import_folder_check.setCheckState(Qt.Unchecked)
- self.ui.import_force_check.setCheckState(Qt.Unchecked)
+ self.ui.import_folder_check.setCheckState(Qt.CheckState.Unchecked)
+ self.ui.import_force_check.setCheckState(Qt.CheckState.Unchecked)
if self.path_edit.is_valid:
self.app_name_edit.setText(find_app_name(path, self.core))
else:
@@ -298,8 +298,8 @@ def app_name_save_callback(self, text) -> None:
@pyqtSlot(str)
def app_name_changed(self, app_name: str):
self.info_label.setText("")
- self.ui.import_dlcs_check.setCheckState(Qt.Unchecked)
- self.ui.import_force_check.setCheckState(Qt.Unchecked)
+ self.ui.import_dlcs_check.setCheckState(Qt.CheckState.Unchecked)
+ self.ui.import_force_check.setCheckState(Qt.CheckState.Unchecked)
self.ui.import_dlcs_check.setEnabled(
self.app_name_edit.is_valid and bool(self.core.get_dlc_for_game(app_name))
)
@@ -318,8 +318,8 @@ def import_folder_changed(self, state: Qt.CheckState):
" will be imported."
) if state else ""
)
- self.ui.import_dlcs_check.setCheckState(Qt.Unchecked)
- self.ui.import_force_check.setCheckState(Qt.Unchecked)
+ self.ui.import_dlcs_check.setCheckState(Qt.CheckState.Unchecked)
+ self.ui.import_force_check.setCheckState(Qt.CheckState.Unchecked)
self.ui.import_dlcs_check.setEnabled(
state
or (self.app_name_edit.is_valid and bool(self.core.get_dlc_for_game(self.app_name_edit.text())))
@@ -400,7 +400,7 @@ def __on_import_result(self, result: List[ImportedGame]):
buttons=QMessageBox.StandardButton.Close,
parent=self,
)
- messagebox.setWindowModality(Qt.NonModal)
+ messagebox.setWindowModality(Qt.WindowModality.NonModal)
details: List = []
for res in success:
details.append(
diff --git a/rare/components/tabs/games/integrations/ubisoft_group.py b/rare/components/tabs/games/integrations/ubisoft_group.py
index 5de288cf7..24a44a648 100644
--- a/rare/components/tabs/games/integrations/ubisoft_group.py
+++ b/rare/components/tabs/games/integrations/ubisoft_group.py
@@ -96,8 +96,8 @@ def run_real(self) -> None:
class UbiLinkWidget(QFrame):
def __init__(self, game: Game, ubi_account_id, activated: bool = False, parent=None):
super(UbiLinkWidget, self).__init__(parent=parent)
- self.setFrameShape(QFrame.StyledPanel)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.args = RareCore.instance().args()
self.game = game
@@ -105,7 +105,7 @@ def __init__(self, game: Game, ubi_account_id, activated: bool = False, parent=N
self.ok_indicator = QLabel(parent=self)
self.ok_indicator.setPixmap(qta_icon("fa.circle-o", color="grey").pixmap(20, 20))
- self.ok_indicator.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
+ self.ok_indicator.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Preferred)
self.title_label = ElideLabel(game.app_title, parent=self)
@@ -188,7 +188,7 @@ def showEvent(self, a0: QShowEvent) -> None:
if self.worker is not None:
return
- for widget in self.findChildren(UbiLinkWidget, options=Qt.FindDirectChildrenOnly):
+ for widget in self.findChildren(UbiLinkWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
widget.deleteLater()
self.loading_widget.start()
diff --git a/rare/components/tabs/settings/legendary.py b/rare/components/tabs/settings/legendary.py
index b82413e9f..fb7a61f1c 100644
--- a/rare/components/tabs/settings/legendary.py
+++ b/rare/components/tabs/settings/legendary.py
@@ -50,7 +50,7 @@ def __init__(self, parent=None):
self.mac_install_dir = PathEdit(
self.core.get_default_install_dir("Mac"),
placeholder=self.tr("Default installation folder for macOS games"),
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
save_func=self.__mac_path_save,
)
self.ui.install_dir_layout.addWidget(self.mac_install_dir)
@@ -59,7 +59,7 @@ def __init__(self, parent=None):
self.install_dir = PathEdit(
self.core.get_default_install_dir(),
placeholder=self.tr("Default installation folder for Windows games"),
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
save_func=self.__win_path_save,
)
self.ui.install_dir_layout.addWidget(self.install_dir)
@@ -96,7 +96,7 @@ def __init__(self, parent=None):
f"{self.core.language_code}-{self.core.country_code}",
edit_func=self.locale_edit_cb,
save_func=self.locale_save_cb,
- horiz_policy=QSizePolicy.Minimum,
+ horiz_policy=QSizePolicy.Policy.Minimum,
parent=self,
)
self.ui.locale_layout.addWidget(self.locale_edit)
diff --git a/rare/components/tabs/settings/rare.py b/rare/components/tabs/settings/rare.py
index 52efa5966..f1ffe2e36 100644
--- a/rare/components/tabs/settings/rare.py
+++ b/rare/components/tabs/settings/rare.py
@@ -36,7 +36,7 @@ def __init__(self, parent=None):
for lang_code, title in get_translations():
self.ui.lang_select.addItem(title, lang_code)
language = self.settings.value(*options.language)
- if (index := self.ui.lang_select.findData(language, Qt.UserRole)) > 0:
+ if (index := self.ui.lang_select.findData(language, Qt.ItemDataRole.UserRole)) > 0:
self.ui.lang_select.setCurrentIndex(index)
else:
self.ui.lang_select.setCurrentIndex(0)
@@ -46,7 +46,7 @@ def __init__(self, parent=None):
for item in get_color_schemes():
self.ui.color_select.addItem(item, item)
color = self.settings.value(*options.color_scheme)
- if (index := self.ui.color_select.findData(color, Qt.UserRole)) > 0:
+ if (index := self.ui.color_select.findData(color, Qt.ItemDataRole.UserRole)) > 0:
self.ui.color_select.setCurrentIndex(index)
self.ui.color_select.setDisabled(False)
self.ui.style_select.setDisabled(True)
@@ -58,7 +58,7 @@ def __init__(self, parent=None):
for item in get_style_sheets():
self.ui.style_select.addItem(item, item)
style = self.settings.value(*options.style_sheet)
- if (index := self.ui.style_select.findData(style, Qt.UserRole)) > 0:
+ if (index := self.ui.style_select.findData(style, Qt.ItemDataRole.UserRole)) > 0:
self.ui.style_select.setCurrentIndex(index)
self.ui.style_select.setDisabled(False)
self.ui.color_select.setDisabled(True)
@@ -76,7 +76,7 @@ def __init__(self, parent=None):
self.ui.view_combo.currentIndexChanged.connect(self.on_view_combo_changed)
self.discord_rpc_settings = DiscordRPCSettings(self)
- self.ui.right_layout.insertWidget(1, self.discord_rpc_settings, alignment=Qt.AlignTop)
+ self.ui.right_layout.insertWidget(1, self.discord_rpc_settings, alignment=Qt.AlignmentFlag.AlignTop)
self.ui.sys_tray.setChecked(self.settings.value(*options.sys_tray))
self.ui.sys_tray.stateChanged.connect(
@@ -197,7 +197,7 @@ def create_desktop_link(self):
@pyqtSlot(int)
def on_color_select_changed(self, index: int):
- scheme = self.ui.color_select.itemData(index, Qt.UserRole)
+ scheme = self.ui.color_select.itemData(index, Qt.ItemDataRole.UserRole)
if scheme:
self.ui.style_select.setCurrentIndex(0)
self.ui.style_select.setDisabled(True)
@@ -208,7 +208,7 @@ def on_color_select_changed(self, index: int):
@pyqtSlot(int)
def on_style_select_changed(self, index: int):
- style = self.ui.style_select.itemData(index, Qt.UserRole)
+ style = self.ui.style_select.itemData(index, Qt.ItemDataRole.UserRole)
if style:
self.ui.color_select.setCurrentIndex(0)
self.ui.color_select.setDisabled(True)
@@ -219,7 +219,7 @@ def on_style_select_changed(self, index: int):
@pyqtSlot(int)
def on_view_combo_changed(self, index: int):
- view = LibraryView(self.ui.view_combo.itemData(index, Qt.UserRole))
+ view = LibraryView(self.ui.view_combo.itemData(index, Qt.ItemDataRole.UserRole))
self.settings.setValue(options.library_view.key, int(view))
@pyqtSlot()
@@ -233,7 +233,7 @@ def save_window_size(self):
@pyqtSlot(int)
def on_lang_changed(self, index: int):
- lang_code = self.ui.lang_select.itemData(index, Qt.UserRole)
+ lang_code = self.ui.lang_select.itemData(index, Qt.ItemDataRole.UserRole)
if lang_code == locale.getlocale()[0]:
self.settings.remove(options.language.key)
else:
diff --git a/rare/components/tabs/settings/widgets/env_vars.py b/rare/components/tabs/settings/widgets/env_vars.py
index 1b55fb564..d87010f12 100644
--- a/rare/components/tabs/settings/widgets/env_vars.py
+++ b/rare/components/tabs/settings/widgets/env_vars.py
@@ -29,7 +29,7 @@ def __init__(self, parent):
self.table_view.verticalHeader().sectionPressed.disconnect()
self.table_view.horizontalHeader().sectionPressed.disconnect()
self.table_view.verticalHeader().sectionClicked.connect(self.table_model.removeRow)
- self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
+ self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
self.table_view.horizontalHeader().setStretchLastSection(True)
self.table_view.setCornerButtonEnabled(False)
@@ -53,7 +53,7 @@ def showEvent(self, a0: QShowEvent):
return super().showEvent(a0)
def keyPressEvent(self, a0):
- if a0.key() in {Qt.Key_Delete, Qt.Key_Backspace}:
+ if a0.key() in {Qt.Key.Key_Delete, Qt.Key.Key_Backspace}:
indexes = self.table_view.selectedIndexes()
if not len(indexes):
return
@@ -61,8 +61,8 @@ def keyPressEvent(self, a0):
if idx.column() == 0:
self.table_view.model().removeRow(idx.row())
elif idx.column() == 1:
- self.table_view.model().setData(idx, "", Qt.EditRole)
- elif a0.key() == Qt.Key_Escape:
+ self.table_view.model().setData(idx, "", Qt.ItemDataRole.EditRole)
+ elif a0.key() == Qt.Key.Key_Escape:
a0.ignore()
def reset_model(self):
diff --git a/rare/components/tabs/settings/widgets/env_vars_model.py b/rare/components/tabs/settings/widgets/env_vars_model.py
index 8acb8cf4e..9769c9ae3 100644
--- a/rare/components/tabs/settings/widgets/env_vars_model.py
+++ b/rare/components/tabs/settings/widgets/env_vars_model.py
@@ -98,8 +98,8 @@ def __is_key_valid(self, value: str):
return False
return value == match.group(0)
- def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any:
- if role in {Qt.DisplayRole, Qt.EditRole}:
+ def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> Any:
+ if role in {Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole}:
if index.row() == self.__data_length():
return ""
if index.column() == 0:
@@ -107,22 +107,22 @@ def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any:
else:
return self.__value(index)
- if role == Qt.TextAlignmentRole:
+ if role == Qt.ItemDataRole.TextAlignmentRole:
if index.column() == 0:
- return Qt.AlignVCenter + Qt.AlignRight
+ return Qt.AlignmentFlag.AlignVCenter + Qt.AlignmentFlag.AlignRight
else:
- return Qt.AlignVCenter + Qt.AlignLeft
+ return Qt.AlignmentFlag.AlignVCenter + Qt.AlignmentFlag.AlignLeft
- if role == Qt.FontRole:
+ if role == Qt.ItemDataRole.FontRole:
font = QFont("Monospace")
- font.setStyleHint(QFont.Monospace)
+ font.setStyleHint(QFont.StyleHint.Monospace)
if index.row() < self.__data_length() and not self.__is_local(index):
- font.setWeight(QFont.Bold)
+ font.setWeight(QFont.Weight.Bold)
else:
- font.setWeight(QFont.Normal)
+ font.setWeight(QFont.Weight.Normal)
return font
- if role == Qt.ToolTipRole:
+ if role == Qt.ItemDataRole.ToolTipRole:
if index.row() == self.__data_length():
if index.column() == 1:
return self.tr("Disabled, please set the variable name first.")
@@ -131,12 +131,12 @@ def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any:
if self.__key(index) in self.__readonly:
return self.tr("Readonly, please edit this via setting the appropriate setting.")
- def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.DisplayRole) -> Any:
- if role == Qt.DisplayRole:
- if orientation == Qt.Horizontal:
+ def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.ItemDataRole.DisplayRole) -> Any:
+ if role == Qt.ItemDataRole.DisplayRole:
+ if orientation == Qt.Orientation.Horizontal:
return self.__title(section)
- if role == Qt.DecorationRole:
- if orientation == Qt.Vertical:
+ if role == Qt.ItemDataRole.DecorationRole:
+ if orientation == Qt.Orientation.Vertical:
if section < self.__data_length():
if self.__is_readonly(section) or not self.__is_local(section):
return qta_icon("mdi.lock", "ei.lock")
@@ -145,23 +145,23 @@ def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.D
if self.__is_local(section):
return qta_icon("mdi.delete", "ei.remove-sign")
return qta_icon("mdi.plus", "ei.plus-sign")
- if role == Qt.TextAlignmentRole:
- return Qt.AlignVCenter + Qt.AlignHCenter
+ if role == Qt.ItemDataRole.TextAlignmentRole:
+ return Qt.AlignmentFlag.AlignVCenter + Qt.AlignmentFlag.AlignHCenter
return None
def flags(self, index: QModelIndex):
# Disable the value cell on rows without a name
if index.row() == self.__data_length():
if index.column() == 1:
- return super().flags(index) ^ Qt.ItemIsEnabled
+ return super().flags(index) ^ Qt.ItemFlag.ItemIsEnabled
else:
- return Qt.ItemIsEditable | super().flags(index)
+ return Qt.ItemFlag.ItemIsEditable | super().flags(index)
# Disable readonly variables
if self.__is_readonly(index):
- return super().flags(index) ^ Qt.ItemIsEnabled
+ return super().flags(index) ^ Qt.ItemFlag.ItemIsEnabled
- return Qt.ItemIsEditable | super().flags(index)
+ return Qt.ItemFlag.ItemIsEditable | super().flags(index)
def rowCount(self, parent: QModelIndex = None) -> int:
parent = parent if parent else QModelIndex()
@@ -172,8 +172,8 @@ def columnCount(self, parent: QModelIndex = None) -> int:
parent = parent if parent else QModelIndex()
return 2
- def setData(self, index: QModelIndex, value: Any, role: int = Qt.DisplayRole) -> bool:
- if role != Qt.EditRole:
+ def setData(self, index: QModelIndex, value: Any, role: int = Qt.ItemDataRole.DisplayRole) -> bool:
+ if role != Qt.ItemDataRole.EditRole:
return False
if index.column() == 0:
@@ -190,7 +190,7 @@ def setData(self, index: QModelIndex, value: Any, role: int = Qt.DisplayRole) ->
self.__data_map[value] = ""
self.core.lgd.save_config()
self.dataChanged.emit(index, index, [])
- self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row())
+ self.headerDataChanged.emit(Qt.Orientation.Vertical, index.row(), index.row())
# if we are on the last row, add a new last row to the table when setting the variable name
else:
# if we are not in the last row, we have to update an existing variable name
@@ -214,8 +214,8 @@ def setData(self, index: QModelIndex, value: Any, role: int = Qt.DisplayRole) ->
self.endInsertRows()
self.dataChanged.emit(index, self.index(index.row(), 1), [])
self.dataChanged.emit(self.index(self.__data_length() - 1, 0), self.index(self.__data_length() - 1, 1), [])
- self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row())
- self.headerDataChanged.emit(Qt.Vertical, self.__data_length() - 1, self.__data_length() - 1)
+ self.headerDataChanged.emit(Qt.Orientation.Vertical, index.row(), index.row())
+ self.headerDataChanged.emit(Qt.Orientation.Vertical, self.__data_length() - 1, self.__data_length() - 1)
else:
# lk: the check for key existance before assigning a value is ommitted
@@ -228,7 +228,7 @@ def setData(self, index: QModelIndex, value: Any, role: int = Qt.DisplayRole) ->
self.__data_map[self.__key(index)] = value
self.core.lgd.save_config()
self.dataChanged.emit(self.index(index.row(), 0), index, [])
- self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row())
+ self.headerDataChanged.emit(Qt.Orientation.Vertical, index.row(), index.row())
return True
def removeRow(self, row: int, parent: QModelIndex = None) -> bool:
@@ -246,7 +246,7 @@ def removeRow(self, row: int, parent: QModelIndex = None) -> bool:
del self.__data_map[self.__key(row)]
self.core.lgd.save_config()
self.dataChanged.emit(self.index(row, 0), self.index(row, 1), [])
- self.headerDataChanged.emit(Qt.Vertical, row, row)
+ self.headerDataChanged.emit(Qt.Orientation.Vertical, row, row)
else:
self.beginRemoveRows(QModelIndex(), row, row)
del self.__data_map[self.__key(row)]
@@ -273,7 +273,7 @@ def __init__(self):
self.table.verticalHeader().sectionPressed.disconnect()
self.table.horizontalHeader().sectionPressed.disconnect()
self.table.verticalHeader().sectionClicked.connect(self.model.removeRow)
- self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
+ self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
self.table.horizontalHeader().setStretchLastSection(True)
self.table.setCornerButtonEnabled(False)
diff --git a/rare/components/tabs/settings/widgets/game.py b/rare/components/tabs/settings/widgets/game.py
index 851c65da0..ca77017dd 100644
--- a/rare/components/tabs/settings/widgets/game.py
+++ b/rare/components/tabs/settings/widgets/game.py
@@ -72,7 +72,7 @@ def __init__(
self.main_layout.addWidget(self.mangohud)
self.main_layout.addWidget(self.env_vars)
- self.main_layout.setAlignment(Qt.AlignTop)
+ self.main_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
def hideEvent(self, a0: QHideEvent):
if a0.spontaneous():
diff --git a/rare/components/tabs/settings/widgets/launch.py b/rare/components/tabs/settings/widgets/launch.py
index aef477592..0c69fb2b5 100644
--- a/rare/components/tabs/settings/widgets/launch.py
+++ b/rare/components/tabs/settings/widgets/launch.py
@@ -29,7 +29,7 @@ def __init__(
self.prelaunch_edit = PathEdit(
path="",
placeholder=self.tr("Path to script or program to run before the game launches"),
- file_mode=QFileDialog.ExistingFile,
+ file_mode=QFileDialog.FileMode.ExistingFile,
edit_func=self.__prelaunch_edit_callback,
save_func=self.__prelaunch_save_callback,
)
@@ -47,9 +47,9 @@ def __init__(
prelaunch_layout.addWidget(self.prelaunch_check)
self.main_layout = QFormLayout(self)
- self.main_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
- self.main_layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
- self.main_layout.setFormAlignment(Qt.AlignLeading | Qt.AlignTop)
+ self.main_layout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
+ self.main_layout.setLabelAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self.main_layout.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignTop)
self.main_layout.addRow(self.tr("Wrappers"), self.wrappers_widget)
self.main_layout.addRow(self.tr("Prelaunch"), prelaunch_layout)
diff --git a/rare/components/tabs/settings/widgets/overlay.py b/rare/components/tabs/settings/widgets/overlay.py
index 47fbd7be1..6bfe300ae 100644
--- a/rare/components/tabs/settings/widgets/overlay.py
+++ b/rare/components/tabs/settings/widgets/overlay.py
@@ -45,11 +45,11 @@ def setDefault(self):
self.setCurrentIndex(0)
def getValue(self) -> Optional[str]:
- return f"{self.option}={self.currentData(Qt.UserRole)}" if self.currentIndex() > 0 else None
+ return f"{self.option}={self.currentData(Qt.ItemDataRole.UserRole)}" if self.currentIndex() > 0 else None
def setValue(self, options: Dict[str, str]):
if (value := options.get(self.option, None)) is not None:
- self.setCurrentIndex(self.findData(value, Qt.UserRole))
+ self.setCurrentIndex(self.findData(value, Qt.ItemDataRole.UserRole))
options.pop(self.option)
else:
self.setDefault()
@@ -166,7 +166,7 @@ def update_settings_override(self, state: ActivationStates):
raise NotImplementedError
def update_settings(self):
- current_state = self.ui.show_overlay_combo.currentData(Qt.UserRole)
+ current_state = self.ui.show_overlay_combo.currentData(Qt.ItemDataRole.UserRole)
self.ui.options_group.setEnabled(current_state == ActivationStates.CUSTOM)
if current_state == ActivationStates.GLOBAL:
@@ -191,7 +191,7 @@ def update_settings(self):
self.update_settings_override(current_state)
def setCurrentState(self, state: ActivationStates):
- self.ui.show_overlay_combo.setCurrentIndex(self.ui.show_overlay_combo.findData(state, Qt.UserRole))
+ self.ui.show_overlay_combo.setCurrentIndex(self.ui.show_overlay_combo.findData(state, Qt.ItemDataRole.UserRole))
self.ui.options_group.setEnabled(state == ActivationStates.CUSTOM)
def showEvent(self, a0: QShowEvent):
diff --git a/rare/components/tabs/settings/widgets/proton.py b/rare/components/tabs/settings/widgets/proton.py
index d6c2f9f2f..98d4fd2fd 100644
--- a/rare/components/tabs/settings/widgets/proton.py
+++ b/rare/components/tabs/settings/widgets/proton.py
@@ -31,7 +31,7 @@ def __init__(self, parent=None):
self.tool_combo.currentIndexChanged.connect(self.__on_proton_changed)
self.tool_prefix = PathEdit(
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
edit_func=self.proton_prefix_edit,
save_func=self.proton_prefix_save,
placeholder=self.tr("Please select path for proton prefix"),
@@ -41,9 +41,9 @@ def __init__(self, parent=None):
layout = QFormLayout(self)
layout.addRow(self.tr("Proton tool"), self.tool_combo)
layout.addRow(self.tr("Compat data"), self.tool_prefix)
- layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
- layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
- layout.setFormAlignment(Qt.AlignLeading | Qt.AlignTop)
+ layout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
+ layout.setLabelAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ layout.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignTop)
self.app_name: str = "default"
self.core = RareCore.instance().core()
@@ -72,7 +72,7 @@ def showEvent(self, a0: QShowEvent) -> None:
self.tool_combo.setCurrentIndex(index)
self.tool_combo.blockSignals(False)
- enabled = bool(self.tool_combo.currentData(Qt.UserRole))
+ enabled = bool(self.tool_combo.currentData(Qt.ItemDataRole.UserRole))
self.tool_prefix.blockSignals(True)
self.tool_prefix.setText(config.get_proton_compatdata(self.app_name, fallback=""))
self.tool_prefix.setEnabled(enabled)
diff --git a/rare/components/tabs/settings/widgets/wine.py b/rare/components/tabs/settings/widgets/wine.py
index bc120d570..db5a78ae3 100644
--- a/rare/components/tabs/settings/widgets/wine.py
+++ b/rare/components/tabs/settings/widgets/wine.py
@@ -29,7 +29,7 @@ def __init__(self, parent=None):
# Wine prefix
self.wine_prefix = PathEdit(
path="",
- file_mode=QFileDialog.DirectoryOnly,
+ file_mode=QFileDialog.FileMode.Directory,
edit_func=lambda path: (os.path.isdir(path) or not path, path, IndicatorReasonsCommon.DIR_NOT_EXISTS),
save_func=self.save_prefix,
)
@@ -37,7 +37,7 @@ def __init__(self, parent=None):
# Wine executable
self.wine_exec = PathEdit(
path="",
- file_mode=QFileDialog.ExistingFile,
+ file_mode=QFileDialog.FileMode.ExistingFile,
name_filters=["wine", "wine64"],
edit_func=lambda text: (os.path.exists(text) or not text, text, IndicatorReasonsCommon.DIR_NOT_EXISTS),
save_func=self.save_exec,
@@ -46,9 +46,9 @@ def __init__(self, parent=None):
layout = QFormLayout(self)
layout.addRow(self.tr("Executable"), self.wine_exec)
layout.addRow(self.tr("Prefix"), self.wine_prefix)
- layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
- layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
- layout.setFormAlignment(Qt.AlignLeading | Qt.AlignTop)
+ layout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
+ layout.setLabelAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ layout.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignTop)
def showEvent(self, a0: QShowEvent):
if a0.spontaneous():
diff --git a/rare/components/tabs/settings/widgets/wrappers.py b/rare/components/tabs/settings/widgets/wrappers.py
index a4f70eb10..b16a6f592 100644
--- a/rare/components/tabs/settings/widgets/wrappers.py
+++ b/rare/components/tabs/settings/widgets/wrappers.py
@@ -99,7 +99,7 @@ def setup(self, wrappers: Iterable[Wrapper]):
@pyqtSlot(int)
def __on_index_changed(self, index: int):
- command = self.combo_box.itemData(index, Qt.UserRole)
+ command = self.combo_box.itemData(index, Qt.ItemDataRole.UserRole)
self.line_edit.setText(command)
@@ -111,8 +111,8 @@ class WrapperWidget(QFrame):
def __init__(self, wrapper: Wrapper, parent=None):
super(WrapperWidget, self).__init__(parent=parent)
- self.setFrameShape(QFrame.StyledPanel)
- self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
self.setToolTip(wrapper.as_str)
text_lbl = QLabel(wrapper.name, parent=self)
@@ -175,23 +175,23 @@ def __on_edit_result(self, accepted: bool, command: str):
self.deleteLater()
def mouseMoveEvent(self, a0: QMouseEvent) -> None:
- if a0.buttons() == Qt.LeftButton:
+ if a0.buttons() == Qt.MouseButton.LeftButton:
a0.accept()
if self.wrapper.is_compat_tool:
return
drag = QDrag(self)
mime = QMimeData()
drag.setMimeData(mime)
- drag.exec_(Qt.MoveAction)
+ drag.exec_(Qt.DropAction.MoveAction)
class WrapperSettingsScroll(QScrollArea):
def __init__(self, parent=None):
super(WrapperSettingsScroll, self).__init__(parent=parent)
- self.setFrameShape(QFrame.StyledPanel)
- self.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
- self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ self.setSizeAdjustPolicy(QScrollArea.SizeAdjustPolicy.AdjustToContents)
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+ self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
self.setWidgetResizable(True)
self.setProperty("no_kinetic_scroll", True)
@@ -204,7 +204,7 @@ def setWidget(self, w):
w.installEventFilter(self)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
- if a0 is self.widget() and a1.type() == QEvent.Resize:
+ if a0 is self.widget() and a1.type() == QEvent.Type.Resize:
self.__resize(a0)
return a0.event(a1)
return False
@@ -231,8 +231,8 @@ def __init__(self, parent=None):
super(WrapperSettings, self).__init__(parent=parent)
self.wrapper_label = QLabel(self.tr("No wrappers defined"), self)
- self.wrapper_label.setFrameStyle(QLabel.StyledPanel | QLabel.Plain)
- self.wrapper_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.wrapper_label.setFrameStyle(QLabel.Shape.StyledPanel | QLabel.Shadow.Plain)
+ self.wrapper_label.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.add_button = QPushButton(self.tr("Add wrapper"), self)
self.add_button.clicked.connect(self.__on_add)
@@ -250,10 +250,10 @@ def __init__(self, parent=None):
main_layout = QHBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
- main_layout.addWidget(self.wrapper_scroll, alignment=Qt.AlignTop)
- main_layout.addWidget(self.add_button, alignment=Qt.AlignTop)
+ main_layout.addWidget(self.wrapper_scroll, alignment=Qt.AlignmentFlag.AlignTop)
+ main_layout.addWidget(self.add_button, alignment=Qt.AlignmentFlag.AlignTop)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.app_name: str = "default"
self.core = RareCore.instance().core()
@@ -332,10 +332,10 @@ def add_user_wrapper(self, wrapper: Wrapper, position: int = -1):
self,
self.tr("Warning"),
self.tr("Wrapper {0} is not in $PATH. Add it anyway?").format(wrapper.executable),
- QMessageBox.Yes | QMessageBox.No,
- QMessageBox.No,
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.No,
)
- if ans == QMessageBox.No:
+ if ans == QMessageBox.StandardButton.No:
return
self.add_wrapper(wrapper, position)
@@ -359,7 +359,7 @@ def __update_wrapper(self, old: Wrapper, new: Wrapper):
@pyqtSlot()
def update_state(self):
- for w in self.wrapper_container.findChildren(WrapperWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.wrapper_container.findChildren(WrapperWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
w.deleteLater()
wrappers = self.wrappers.get_game_wrapper_list(self.app_name)
if not wrappers:
@@ -382,8 +382,8 @@ def __init__(self, label: QLabel, parent=None):
main_layout.addWidget(label)
main_layout.addLayout(self.__layout)
main_layout.setContentsMargins(0, 0, 0, 0)
- main_layout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
- main_layout.setSizeConstraint(QHBoxLayout.SetFixedSize)
+ main_layout.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
+ main_layout.setSizeConstraint(QHBoxLayout.SizeConstraint.SetFixedSize)
# lk: set object names for the stylesheet
self.setObjectName(type(self).__name__)
diff --git a/rare/components/tabs/store/api/debug.py b/rare/components/tabs/store/api/debug.py
index 24a20016a..470dba99d 100644
--- a/rare/components/tabs/store/api/debug.py
+++ b/rare/components/tabs/store/api/debug.py
@@ -11,7 +11,7 @@ def __init__(self, data, parent=None):
self.setWordWrap(True)
self.model = QJsonModel(self)
self.setModel(self.model)
- self.setContextMenuPolicy(Qt.ActionsContextMenu)
+ self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
try:
self.model.load(data)
except Exception as e:
diff --git a/rare/components/tabs/store/landing.py b/rare/components/tabs/store/landing.py
index 75957af3f..7f2f48ee8 100644
--- a/rare/components/tabs/store/landing.py
+++ b/rare/components/tabs/store/landing.py
@@ -33,23 +33,23 @@ def __init__(self, store_api: StoreAPI, parent=None):
self.implements_scrollarea = True
self.landing_widget = LandingWidget(store_api, parent=self)
- self.landing_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.landing_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.landing_widget.set_title.connect(self.set_title)
self.landing_widget.show_details.connect(self.show_details)
self.landing_scroll = QScrollArea(self)
self.landing_scroll.setWidgetResizable(True)
- self.landing_scroll.setFrameStyle(QFrame.NoFrame | QFrame.Plain)
+ self.landing_scroll.setFrameStyle(QFrame.Shape.NoFrame | QFrame.Shadow.Plain)
self.landing_scroll.setWidget(self.landing_widget)
self.landing_scroll.widget().setAutoFillBackground(False)
self.landing_scroll.viewport().setAutoFillBackground(False)
self.details_widget = StoreDetailsWidget([], store_api, parent=self)
- self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.details_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
- self.setDirection(Qt.Horizontal)
+ self.setDirection(Qt.Orientation.Horizontal)
self.addWidget(self.landing_scroll)
self.addWidget(self.details_widget)
@@ -73,7 +73,7 @@ def setWidget(self, w):
w.installEventFilter(self)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
- if a0 is self.widget() and a1.type() == QEvent.Resize:
+ if a0 is self.widget() and a1.type() == QEvent.Type.Resize:
self.__resize(a0)
return a0.event(a1)
return False
@@ -105,21 +105,21 @@ def __init__(self, api: StoreAPI, parent=None):
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 3, 0)
self.setLayout(layout)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.free_games_now = StoreGroup(self.tr("Free now"), layout=QHBoxLayout, parent=self)
- self.free_games_now.main_layout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
- self.free_games_now.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.free_games_now.main_layout.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
+ self.free_games_now.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.free_games_next = StoreGroup(self.tr("Free next week"), layout=QHBoxLayout, parent=self)
- self.free_games_next.main_layout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
- self.free_games_next.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.free_games_next.main_layout.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
+ self.free_games_next.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.discounts_group = StoreGroup(self.tr("Wishlist discounts"), layout=FlowLayout, parent=self)
- self.discounts_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.discounts_group.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.games_group = StoreGroup(self.tr("Free to play"), FlowLayout, self)
- self.games_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.games_group.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.games_group.loading(False)
self.games_group.setVisible(False)
@@ -129,25 +129,25 @@ def __init__(self, api: StoreAPI, parent=None):
free_container_layout = QHBoxLayout(free_container)
free_scroll.setWidgetResizable(True)
- free_scroll.setFrameShape(QScrollArea.NoFrame)
- free_scroll.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
- free_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ free_scroll.setFrameShape(QScrollArea.Shape.NoFrame)
+ free_scroll.setSizeAdjustPolicy(QScrollArea.SizeAdjustPolicy.AdjustToContents)
+ free_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
free_container_layout.setContentsMargins(0, 0, 0, 0)
- free_container_layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
- free_container_layout.setSizeConstraint(QHBoxLayout.SetFixedSize)
+ free_container_layout.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
+ free_container_layout.setSizeConstraint(QHBoxLayout.SizeConstraint.SetFixedSize)
free_container_layout.addWidget(self.free_games_now)
free_container_layout.addWidget(self.free_games_next)
free_scroll.widget().setAutoFillBackground(False)
free_scroll.viewport().setAutoFillBackground(False)
- # layout.addWidget(self.free_games_now, alignment=Qt.AlignTop)
- # layout.addWidget(self.free_games_next, alignment=Qt.AlignTop)
- layout.addWidget(free_scroll, alignment=Qt.AlignTop)
- layout.addWidget(self.discounts_group, alignment=Qt.AlignTop)
- layout.addWidget(self.games_group, alignment=Qt.AlignTop)
- layout.addItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding))
+ # layout.addWidget(self.free_games_now, alignment=Qt.AlignmentFlag.AlignTop)
+ # layout.addWidget(self.free_games_next, alignment=Qt.AlignmentFlag.AlignTop)
+ layout.addWidget(free_scroll, alignment=Qt.AlignmentFlag.AlignTop)
+ layout.addWidget(self.discounts_group, alignment=Qt.AlignmentFlag.AlignTop)
+ layout.addWidget(self.games_group, alignment=Qt.AlignmentFlag.AlignTop)
+ layout.addItem(QSpacerItem(0, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Expanding))
def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous():
@@ -163,7 +163,7 @@ def hideEvent(self, a0: QHideEvent) -> None:
return super().hideEvent(a0)
def __update_wishlist_discounts(self, wishlist: List[WishlistItemModel]):
- for w in self.discounts_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.discounts_group.findChildren(StoreItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.discounts_group.layout().removeWidget(w)
w.deleteLater()
@@ -176,11 +176,11 @@ def __update_wishlist_discounts(self, wishlist: List[WishlistItemModel]):
self.discounts_group.loading(False)
def __update_free_games(self, free_games: List[CatalogOfferModel]):
- for w in self.free_games_now.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.free_games_now.findChildren(StoreItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.free_games_now.layout().removeWidget(w)
w.deleteLater()
- for w in self.free_games_next.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.free_games_next.findChildren(StoreItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.free_games_next.layout().removeWidget(w)
w.deleteLater()
@@ -228,7 +228,7 @@ def show_games(self, data):
if not data:
return
- for w in self.games_group.findChildren(StoreItemWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.games_group.findChildren(StoreItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.games_group.layout().removeWidget(w)
w.deleteLater()
diff --git a/rare/components/tabs/store/results.py b/rare/components/tabs/store/results.py
index 6ae530882..1a9ba5fce 100644
--- a/rare/components/tabs/store/results.py
+++ b/rare/components/tabs/store/results.py
@@ -20,7 +20,7 @@ def __init__(self, store_api, parent=None):
self.store_api = store_api
self.results_container = QWidget(self)
- self.results_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.results_container.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.results_layout = FlowLayout(self.results_container)
self.setWidget(self.results_container)
self.setWidgetResizable(True)
@@ -37,10 +37,10 @@ def load_results(self, text: str):
self.store_api.search_game(text, self.show_results)
def show_results(self, results: dict):
- for w in self.results_container.findChildren(QLabel, options=Qt.FindDirectChildrenOnly):
+ for w in self.results_container.findChildren(QLabel, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
- for w in self.results_container.findChildren(ResultsItemWidget, options=Qt.FindDirectChildrenOnly):
+ for w in self.results_container.findChildren(ResultsItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.results_layout.removeWidget(w)
w.deleteLater()
diff --git a/rare/components/tabs/store/search.py b/rare/components/tabs/store/search.py
index 599dc94c7..3a993d855 100644
--- a/rare/components/tabs/store/search.py
+++ b/rare/components/tabs/store/search.py
@@ -31,16 +31,16 @@ def __init__(self, store_api: StoreAPI, parent=None):
self.implements_scrollarea = True
self.search_widget = SearchWidget(store_api, parent=self)
- self.search_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.search_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.search_widget.set_title.connect(self.set_title)
self.search_widget.show_details.connect(self.show_details)
self.details_widget = StoreDetailsWidget([], store_api, parent=self)
- self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.details_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
- self.setDirection(Qt.Horizontal)
+ self.setDirection(Qt.Orientation.Horizontal)
self.addWidget(self.search_widget)
self.addWidget(self.details_widget)
diff --git a/rare/components/tabs/store/store_api.py b/rare/components/tabs/store/store_api.py
index 112be2e89..cd0c15a82 100644
--- a/rare/components/tabs/store/store_api.py
+++ b/rare/components/tabs/store/store_api.py
@@ -1,5 +1,5 @@
from logging import getLogger
-from typing import List, Callable
+from typing import List, Callable, Tuple
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QApplication
@@ -58,7 +58,7 @@ def get_free(self, handle_func: callable):
def __handle_free_games(data, handle_func):
try:
response = ResponseModel.from_dict(data)
- results: List[CatalogOfferModel] = response.data.catalog.searchStore.elements
+ results: Tuple[CatalogOfferModel, ...] = response.data.catalog.searchStore.elements
handle_func(results)
except KeyError as e:
if DEBUG():
diff --git a/rare/components/tabs/store/widgets/details.py b/rare/components/tabs/store/widgets/details.py
index 45da0c219..5c0a69071 100644
--- a/rare/components/tabs/store/widgets/details.py
+++ b/rare/components/tabs/store/widgets/details.py
@@ -42,8 +42,8 @@ def __init__(self, installed: List, store_api: StoreAPI, parent=None):
self.image = LoadingImageWidget(store_api.cached_manager, self)
self.image.setFixedSize(ImageSize.DisplayTall)
- self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignTop)
- self.ui.left_layout.setAlignment(Qt.AlignTop)
+ self.ui.left_layout.insertWidget(0, self.image, alignment=Qt.AlignmentFlag.AlignTop)
+ self.ui.left_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.ui.wishlist_button.clicked.connect(self.add_to_wishlist)
self.ui.store_button.clicked.connect(self.button_clicked)
@@ -52,7 +52,7 @@ def __init__(self, installed: List, store_api: StoreAPI, parent=None):
self.wishlist = []
self.requirements_tabs = SideTabWidget(parent=self.ui.requirements_frame)
- self.requirements_tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.requirements_tabs.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.ui.requirements_layout.addWidget(self.requirements_tabs)
self.ui.back_button.setIcon(qta_icon("fa.chevron-left"))
@@ -195,7 +195,7 @@ def data_received(self, product: DieselProduct):
self.ui.tags.setText(", ".join(tags))
# clear Layout
- for b in self.ui.social_links.findChildren(SocialButton, options=Qt.FindDirectChildrenOnly):
+ for b in self.ui.social_links.findChildren(SocialButton, options=Qt.FindChildOption.FindDirectChildrenOnly):
self.ui.social_links_layout.removeWidget(b)
b.deleteLater()
@@ -231,14 +231,14 @@ def button_clicked(self):
QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{self.store_api.language_code}/p/{self.slug}"))
def keyPressEvent(self, a0: QKeyEvent):
- if a0.key() == Qt.Key_Escape:
+ if a0.key() == Qt.Key.Key_Escape:
self.back_clicked.emit()
class SocialButton(QPushButton):
def __init__(self, icn, url, parent=None):
super(SocialButton, self).__init__(icn, "", parent=parent)
- self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.url = url
self.clicked.connect(lambda: QDesktopServices.openUrl(QUrl(url)))
self.setToolTip(url)
@@ -267,5 +267,5 @@ def __init__(self, system: DieselSystemDetail, parent=None):
req_layout.addWidget(min_label, i + 1, 1)
rec_label = ElideLabel(detail.recommended, parent=self)
req_layout.addWidget(rec_label, i + 1, 2)
- req_layout.setAlignment(Qt.AlignTop)
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ req_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
diff --git a/rare/components/tabs/store/widgets/image.py b/rare/components/tabs/store/widgets/image.py
index 22bd01407..0719a09cd 100644
--- a/rare/components/tabs/store/widgets/image.py
+++ b/rare/components/tabs/store/widgets/image.py
@@ -34,25 +34,25 @@ def setupUi(self, widget: QWidget):
# game title
self.title_label = QLabel(parent=self.mini_widget)
self.title_label.setObjectName(f"{type(self).__name__}TitleLabel")
- self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
- self.title_label.setAlignment(Qt.AlignTop)
+ self.title_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
+ self.title_label.setAlignment(Qt.AlignmentFlag.AlignTop)
self.title_label.setAutoFillBackground(False)
self.title_label.setWordWrap(True)
# information below title
self.developer_label = QLabel(parent=self.mini_widget)
self.developer_label.setObjectName(f"{type(self).__name__}TooltipLabel")
- self.developer_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
+ self.developer_label.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
self.developer_label.setAutoFillBackground(False)
self.price_label = QLabel(parent=self.mini_widget)
self.price_label.setObjectName(f"{type(self).__name__}TooltipLabel")
- self.price_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
+ self.price_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
self.price_label.setAutoFillBackground(False)
self.discount_label = QLabel(parent=self.mini_widget)
self.discount_label.setObjectName(f"{type(self).__name__}TooltipLabel")
- self.discount_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
+ self.discount_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
self.discount_label.setAutoFillBackground(False)
# Create layouts
@@ -67,7 +67,7 @@ def setupUi(self, widget: QWidget):
# layout for the top row, holds the title and the launch button
row_layout = QHBoxLayout()
row_layout.setSpacing(6)
- row_layout.setAlignment(Qt.AlignBottom)
+ row_layout.setAlignment(Qt.AlignmentFlag.AlignBottom)
# Layout the widgets
# (from inner to outer)
@@ -78,7 +78,7 @@ def setupUi(self, widget: QWidget):
mini_layout.addLayout(row_layout)
self.mini_widget.setLayout(mini_layout)
- image_layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
+ image_layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding))
image_layout.addWidget(self.mini_widget)
widget.setLayout(image_layout)
@@ -106,7 +106,7 @@ def __on_image_ready(self, data):
cover.loadFromData(data)
# cover = cover.scaled(self._image_size.size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
cover.setDevicePixelRatio(self._image_size.base.pixel_ratio)
- cover = cover.convertToFormat(QImage.Format_ARGB32_Premultiplied)
+ cover = cover.convertToFormat(QImage.Format.Format_ARGB32_Premultiplied)
cover = QPixmap(cover)
self.setPixmap(cover)
self.spinner.stop()
diff --git a/rare/components/tabs/store/widgets/items.py b/rare/components/tabs/store/widgets/items.py
index 726d8d96c..46def2817 100644
--- a/rare/components/tabs/store/widgets/items.py
+++ b/rare/components/tabs/store/widgets/items.py
@@ -21,10 +21,10 @@ def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel = None,
self.catalog_game = catalog_game
def mousePressEvent(self, a0: QMouseEvent) -> None:
- if a0.button() == Qt.LeftButton:
+ if a0.button() == Qt.MouseButton.LeftButton:
a0.accept()
self.show_details.emit(self.catalog_game)
- if a0.button() == Qt.RightButton:
+ if a0.button() == Qt.MouseButton.RightButton:
a0.accept()
@@ -132,5 +132,5 @@ def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel, parent=
self.delete_button.clicked.connect(
lambda: self.delete_from_wishlist.emit(self.catalog_game)
)
- self.layout().insertWidget(0, self.delete_button, alignment=Qt.AlignRight)
+ self.layout().insertWidget(0, self.delete_button, alignment=Qt.AlignmentFlag.AlignRight)
diff --git a/rare/components/tabs/store/wishlist.py b/rare/components/tabs/store/wishlist.py
index e3f059755..14899b42f 100644
--- a/rare/components/tabs/store/wishlist.py
+++ b/rare/components/tabs/store/wishlist.py
@@ -22,16 +22,16 @@ def __init__(self, api: StoreAPI, parent=None):
self.implements_scrollarea = True
self.wishlist_widget = WishlistWidget(api, parent=self)
- self.wishlist_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.wishlist_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.wishlist_widget.set_title.connect(self.set_title)
self.wishlist_widget.show_details.connect(self.show_details)
self.details_widget = StoreDetailsWidget([], api, parent=self)
- self.details_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.details_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.details_widget.set_title.connect(self.set_title)
self.details_widget.back_clicked.connect(self.show_main)
- self.setDirection(Qt.Horizontal)
+ self.setDirection(Qt.Orientation.Horizontal)
self.addWidget(self.wishlist_widget)
self.addWidget(self.details_widget)
@@ -121,8 +121,8 @@ def delete_from_wishlist(self, game: CatalogOfferModel):
@pyqtSlot(int)
def filter_wishlist(self, index: int = int(WishlistFilter.NONE)):
- list_filter = self.ui.filter_combo.itemData(index, Qt.UserRole)
- widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindDirectChildrenOnly)
+ list_filter = self.ui.filter_combo.itemData(index, Qt.ItemDataRole.UserRole)
+ widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly)
for w in widgets:
if list_filter == WishlistFilter.NONE:
w.setVisible(True)
@@ -135,8 +135,8 @@ def filter_wishlist(self, index: int = int(WishlistFilter.NONE)):
@pyqtSlot(int)
def order_wishlist(self, index: int = int(WishlistOrder.NAME)):
- list_order = self.ui.order_combo.itemData(index, Qt.UserRole)
- widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindDirectChildrenOnly)
+ list_order = self.ui.order_combo.itemData(index, Qt.ItemDataRole.UserRole)
+ widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly)
for w in widgets:
self.wishlist_layout.removeWidget(w)
@@ -167,7 +167,7 @@ def set_wishlist(self, wishlist: List[WishlistItemModel] = None):
if wishlist and wishlist[0] == "error":
return
- widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindDirectChildrenOnly)
+ widgets = self.ui.container.findChildren(WishlistItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly)
for w in widgets:
self.wishlist_layout.removeWidget(w)
w.deleteLater()
diff --git a/rare/components/tray_icon.py b/rare/components/tray_icon.py
index b3adb6097..4ad91e2ed 100644
--- a/rare/components/tray_icon.py
+++ b/rare/components/tray_icon.py
@@ -63,7 +63,9 @@ def last_played(self) -> List:
@pyqtSlot(str, str)
def notify(self, title: str, body: str):
if self.settings.value(*options.notification):
- self.showMessage(f"{title} - {QApplication.applicationName()}", body, QSystemTrayIcon.Information, 4000)
+ self.showMessage(
+ f"{title} - {QApplication.applicationName()}", body, QSystemTrayIcon.MessageIcon.Information, 4000
+ )
@pyqtSlot()
def update_actions(self):
diff --git a/rare/models/image.py b/rare/models/image.py
index 703de5d86..e7d5918d6 100644
--- a/rare/models/image.py
+++ b/rare/models/image.py
@@ -19,13 +19,13 @@ def __init__(self, divisor: float, pixel_ratio: float, orientation: ImageType =
self.__pixel_ratio = pixel_ratio
if orientation == ImageType.Tall:
self.__img_factor = 67
- self.__size = QSize(self.__img_factor * 3, self.__img_factor * 4) * pixel_ratio / divisor
+ self.__size = QSize(self.__img_factor * 3, self.__img_factor * 4) * (pixel_ratio / divisor)
if orientation == ImageType.Wide:
self.__img_factor = 34
- self.__size = QSize(self.__img_factor * 16, self.__img_factor * 9) * pixel_ratio / divisor
+ self.__size = QSize(self.__img_factor * 16, self.__img_factor * 9) * (pixel_ratio / divisor)
if orientation == ImageType.Icon:
self.__img_factor = 128
- self.__size = QSize(self.__img_factor * 1, self.__img_factor * 1) * pixel_ratio / divisor
+ self.__size = QSize(self.__img_factor * 1, self.__img_factor * 1) * (pixel_ratio / divisor)
self.__orientation = orientation
# lk: for prettier images set this to true
# self.__smooth_transform: bool = True
diff --git a/rare/shared/image_manager.py b/rare/shared/image_manager.py
index 225276b10..2de8c1e58 100644
--- a/rare/shared/image_manager.py
+++ b/rare/shared/image_manager.py
@@ -266,19 +266,19 @@ def __generate_icon_overlay(rect: QRect) -> QPainterPath:
@staticmethod
def __convert_icon(cover: QImage) -> QImage:
icon_size = QSize(128, 128)
- icon = QImage(icon_size, QImage.Format_ARGB32_Premultiplied)
+ icon = QImage(icon_size, QImage.Format.Format_ARGB32_Premultiplied)
painter = QPainter(icon)
- painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
- painter.setRenderHint(QPainter.Antialiasing, True)
- painter.setCompositionMode(QPainter.CompositionMode_Source)
- painter.fillRect(icon.rect(), Qt.transparent)
+ painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, True)
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source)
+ painter.fillRect(icon.rect(), Qt.GlobalColor.transparent)
overlay = ImageManager.__generate_icon_overlay(icon.rect())
brush = QBrush(cover)
scale = max(icon.width() / cover.width(), icon.height() / cover.height())
transform = QTransform().scale(scale, scale)
brush.setTransform(transform)
painter.fillPath(overlay, brush)
- pen = QPen(Qt.black, 2)
+ pen = QPen(Qt.GlobalColor.black, 2)
painter.setPen(pen)
painter.drawPath(overlay)
painter.end()
@@ -304,7 +304,7 @@ def find_image_data(image_types: Tuple):
def convert_image(image_data, logo_data, preset: ImageSize.Preset) -> QImage:
image = QImage()
image.loadFromData(image_data)
- image.convertToFormat(QImage.Format_ARGB32_Premultiplied)
+ image.convertToFormat(QImage.Format.Format_ARGB32_Premultiplied)
# lk: Images are not always at the correct aspect ratio, so crop them to size
wr, hr = preset.aspect_ratio
factor = min(image.width() // wr, image.height() // hr)
@@ -315,14 +315,23 @@ def convert_image(image_data, logo_data, preset: ImageSize.Preset) -> QImage:
if logo_data is not None:
logo = QImage()
logo.loadFromData(logo_data)
- logo.convertToFormat(QImage.Format_ARGB32_Premultiplied)
+ logo.convertToFormat(QImage.Format.Format_ARGB32_Premultiplied)
if logo.width() > image.width():
- logo = logo.scaled(image.width(), image.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ logo = logo.scaled(
+ image.width(),
+ image.height(),
+ Qt.AspectRatioMode.KeepAspectRatio,
+ Qt.TransformationMode.SmoothTransformation
+ )
painter = QPainter(image)
painter.drawImage((image.width() - logo.width()) // 2, image.height() - logo.height(), logo)
painter.end()
- return image.scaled(preset.size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ return image.scaled(
+ preset.size,
+ Qt.AspectRatioMode.KeepAspectRatio,
+ Qt.TransformationMode.SmoothTransformation
+ )
tall = convert_image(tall_data, logo_data, ImageSize.Tall)
wide = convert_image(wide_data, logo_data, ImageSize.Wide)
@@ -334,13 +343,13 @@ def save_image(image: QImage, color_path: Path, gray_path: Path):
# this is not required if we ever want to re-apply the alpha channel
# image = image.convertToFormat(QImage.Format_Indexed8)
# add the alpha channel back to the cover
- image = image.convertToFormat(QImage.Format_ARGB32_Premultiplied)
+ image = image.convertToFormat(QImage.Format.Format_ARGB32_Premultiplied)
image.save(color_path.as_posix(), format="PNG")
# quick way to convert to grayscale, but keep the alpha channel
- alpha = image.convertToFormat(QImage.Format_Alpha8)
- image = image.convertToFormat(QImage.Format_Grayscale8)
+ alpha = image.convertToFormat(QImage.Format.Format_Alpha8)
+ image = image.convertToFormat(QImage.Format.Format_Grayscale8)
# add the alpha channel back to the grayscale cover
- image = image.convertToFormat(QImage.Format_ARGB32_Premultiplied)
+ image = image.convertToFormat(QImage.Format.Format_ARGB32_Premultiplied)
image.setAlphaChannel(alpha)
image.save(gray_path.as_posix(), format="PNG")
@@ -433,7 +442,11 @@ def __get_cover(
ret.setDevicePixelRatio(preset.pixel_ratio)
# lk: Scaling happens at painting. It might be inefficient so leave this here as an alternative
# lk: If this is uncommented, the transformation in ImageWidget should be adjusted also
- ret = ret.scaled(device.size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ ret = ret.scaled(
+ device.size,
+ Qt.AspectRatioMode.KeepAspectRatio,
+ Qt.TransformationMode.SmoothTransformation
+ )
ret.setDevicePixelRatio(device.pixel_ratio)
return ret
diff --git a/rare/utils/json_formatter.py b/rare/utils/json_formatter.py
index 67da0c1ee..00df5d757 100644
--- a/rare/utils/json_formatter.py
+++ b/rare/utils/json_formatter.py
@@ -170,34 +170,34 @@ def data(self, index, role):
item = index.internalPointer()
- if role == QtCore.Qt.DisplayRole:
+ if role == QtCore.Qt.ItemDataRole.DisplayRole:
if index.column() == 0:
return item.key
if index.column() == 1:
return item.value
- elif role == QtCore.Qt.EditRole:
+ elif role == QtCore.Qt.ItemDataRole.EditRole:
if index.column() == 1:
return item.value
def setData(self, index, value, role):
- if role == QtCore.Qt.EditRole:
+ if role == QtCore.Qt.ItemDataRole.EditRole:
if index.column() == 1:
item = index.internalPointer()
item.value = str(value)
- self.dataChanged.emit(index, index, [QtCore.Qt.EditRole])
+ self.dataChanged.emit(index, index, [QtCore.Qt.ItemDataRole.EditRole])
return True
return False
def headerData(self, section, orientation, role):
- if role != QtCore.Qt.DisplayRole:
+ if role != QtCore.Qt.ItemDataRole.DisplayRole:
return None
- if orientation == QtCore.Qt.Horizontal:
+ if orientation == QtCore.Qt.Orientation.Horizontal:
return self._headers[section]
def index(self, row, column, parent=QtCore.QModelIndex()):
@@ -245,7 +245,7 @@ def flags(self, index):
flags = super(QJsonModel, self).flags(index)
if index.column() == 1:
- return QtCore.Qt.ItemIsEditable | flags
+ return QtCore.Qt.ItemFlag.ItemIsEditable | flags
else:
return flags
diff --git a/rare/utils/misc.py b/rare/utils/misc.py
index b630db5cf..7eeafd831 100644
--- a/rare/utils/misc.py
+++ b/rare/utils/misc.py
@@ -12,7 +12,7 @@
Qt, QLocale,
)
from PyQt5.QtGui import QPalette, QColor, QFontMetrics
-from PyQt5.QtWidgets import qApp, QStyleFactory, QLabel
+from PyQt5.QtWidgets import QApplication, QStyleFactory, QLabel
from PyQt5.sip import wrappertype
from rare.utils.paths import resources_path
@@ -59,7 +59,7 @@ class ExitCodes(IntEnum):
def load_color_scheme(path: str) -> QPalette:
palette = QPalette()
- scheme = QSettings(path, QSettings.IniFormat)
+ scheme = QSettings(path, QSettings.Format.IniFormat)
try:
scheme.beginGroup("ColorScheme")
for g in color_group_map:
@@ -71,7 +71,7 @@ def load_color_scheme(path: str) -> QPalette:
if color is not None:
palette.setColor(group, role, QColor(color))
else:
- palette.setColor(group, role, palette.color(QPalette.Active, role))
+ palette.setColor(group, role, palette.color(QPalette.ColorGroup.Active, role))
scheme.endGroup()
scheme.endGroup()
except:
@@ -81,7 +81,7 @@ def load_color_scheme(path: str) -> QPalette:
def get_static_style() -> str:
file = QFile(":/static_css/stylesheet.qss")
- file.open(QFile.ReadOnly)
+ file.open(QFile.OpenModeFlag.ReadOnly)
static = file.readAll().data().decode("utf-8")
file.close()
return static
@@ -89,6 +89,7 @@ def get_static_style() -> str:
def set_color_pallete(color_scheme: str) -> None:
static = get_static_style()
+ qApp: QApplication = QApplication.instance()
if not color_scheme:
qApp.setStyle(QStyleFactory.create(qApp.property("rareDefaultQtStyle")))
@@ -101,8 +102,8 @@ def set_color_pallete(color_scheme: str) -> None:
if custom_palette is not None:
qApp.setPalette(custom_palette)
qApp.setStyleSheet(static)
- icon_color_normal = qApp.palette().color(QPalette.Foreground).name()
- icon_color_disabled = qApp.palette().color(QPalette.Foreground).name()
+ icon_color_normal = qApp.palette().color(QPalette.ColorRole.WindowText).name()
+ icon_color_disabled = qApp.palette().color(QPalette.ColorRole.WindowText).name()
qtawesome.set_defaults(color=icon_color_normal, color_disabled=icon_color_disabled)
@@ -112,6 +113,7 @@ def get_color_schemes() -> Iterable[str]:
def set_style_sheet(style_sheet: str) -> None:
static = get_static_style()
+ qApp: QApplication = QApplication.instance()
if not style_sheet:
qApp.setStyle(QStyleFactory.create(qApp.property("rareDefaultQtStyle")))
@@ -120,13 +122,13 @@ def set_style_sheet(style_sheet: str) -> None:
qApp.setStyle(QStyleFactory.create("Fusion"))
file = QFile(f":/stylesheets/{style_sheet}/stylesheet.qss")
- file.open(QFile.ReadOnly)
+ file.open(QFile.OpenModeFlag.ReadOnly)
stylesheet = file.readAll().data().decode("utf-8")
file.close()
qApp.setStyleSheet(stylesheet + static)
- icon_color_normal = qApp.palette().color(QPalette.Text).name()
- icon_color_disabled = qApp.palette().color(QPalette.Text).name()
+ icon_color_normal = qApp.palette().color(QPalette.ColorRole.Text).name()
+ icon_color_disabled = qApp.palette().color(QPalette.ColorRole.Text).name()
qtawesome.set_defaults(color="#eee", color_disabled="#eee")
@@ -187,7 +189,7 @@ def widget_object_name(widget: Union[QObject, wrappertype, Type], suffix: str) -
def elide_text(label: QLabel, text: str) -> str:
metrics = QFontMetrics(label.font())
- return metrics.elidedText(text, Qt.ElideRight, label.sizeHint().width())
+ return metrics.elidedText(text, Qt.TextElideMode.ElideRight, label.sizeHint().width())
def style_hyperlink(link: str, title: str) -> str:
diff --git a/rare/utils/paths.py b/rare/utils/paths.py
index 9a9b255d4..7a0bc5ff8 100644
--- a/rare/utils/paths.py
+++ b/rare/utils/paths.py
@@ -20,10 +20,10 @@
# lk: delete old Rare directories
for old_dir in [
- Path(QStandardPaths.writableLocation(QStandardPaths.CacheLocation), "rare").joinpath("tmp"),
- Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation), "rare").joinpath("images"),
- Path(QStandardPaths.writableLocation(QStandardPaths.CacheLocation), "rare"),
- Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation), "rare"),
+ Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.CacheLocation), "rare").joinpath("tmp"),
+ Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation), "rare").joinpath("images"),
+ Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.CacheLocation), "rare"),
+ Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation), "rare"),
]:
if old_dir.exists():
# lk: case-sensitive matching on Winblows
@@ -34,21 +34,21 @@
# lk: TempLocation doesn't depend on OrganizationName or ApplicationName
# lk: so it is fine to use it before initializing the QApplication
def lock_file() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.TempLocation), "Rare.lock")
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.TempLocation), "Rare.lock")
def config_dir() -> Path:
# FIXME: This returns ~/.config/Rare/Rare/ for some reason while the settings are in ~/.config/Rare/Rare.conf
# Take the parent for now, but this should be investigated
- return Path(QStandardPaths.writableLocation(QStandardPaths.AppConfigLocation)).parent
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppConfigLocation)).parent
def data_dir() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation))
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation))
def cache_dir() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.CacheLocation))
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.CacheLocation))
def image_dir() -> Path:
@@ -87,15 +87,15 @@ def create_dirs() -> None:
def home_dir() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.HomeLocation))
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.HomeLocation))
def desktop_dir() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.DesktopLocation))
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.DesktopLocation))
def applications_dir() -> Path:
- return Path(QStandardPaths.writableLocation(QStandardPaths.ApplicationsLocation))
+ return Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.ApplicationsLocation))
def proton_compat_dir(app_name: str) -> Path:
diff --git a/rare/utils/qt_requests.py b/rare/utils/qt_requests.py
index 02a9c5a24..9f1c36420 100644
--- a/rare/utils/qt_requests.py
+++ b/rare/utils/qt_requests.py
@@ -55,11 +55,15 @@ def __prepare_query(url, params) -> QUrl:
def __prepare_request(self, item: RequestQueueItem) -> QNetworkRequest:
request = QNetworkRequest(item.url)
- request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json; charset=UTF-8")
- request.setHeader(QNetworkRequest.UserAgentHeader, USER_AGENT)
- request.setAttribute(QNetworkRequest.RedirectPolicyAttribute, QNetworkRequest.NoLessSafeRedirectPolicy)
+ request.setHeader(QNetworkRequest.KnownHeaders.ContentTypeHeader, "application/json; charset=UTF-8")
+ request.setHeader(QNetworkRequest.KnownHeaders.UserAgentHeader, USER_AGENT)
+ request.setAttribute(
+ QNetworkRequest.Attribute.RedirectPolicyAttribute, QNetworkRequest.RedirectPolicy.NoLessSafeRedirectPolicy
+ )
if self.cache is not None:
- request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferCache)
+ request.setAttribute(
+ QNetworkRequest.Attribute.CacheLoadControlAttribute, QNetworkRequest.CacheLoadControl.PreferCache
+ )
if self.token is not None:
request.setRawHeader(b"Authorization", self.token.encode())
return request
@@ -106,7 +110,7 @@ def __on_finished(self, reply: QNetworkReply):
if reply.error():
self.log.error(reply.errorString())
else:
- mimetype, charset = self.__parse_content_type(reply.header(QNetworkRequest.ContentTypeHeader))
+ mimetype, charset = self.__parse_content_type(reply.header(QNetworkRequest.KnownHeaders.ContentTypeHeader))
maintype, subtype = mimetype.split("/")
bin_data = reply.readAll().data()
if mimetype == "application/json":
diff --git a/rare/widgets/button_edit.py b/rare/widgets/button_edit.py
index c332d8a3a..580dbb35c 100644
--- a/rare/widgets/button_edit.py
+++ b/rare/widgets/button_edit.py
@@ -14,7 +14,7 @@ def __init__(self, icon_name, placeholder_text: str, parent=None):
self.button = QPushButton(self)
self.button.setObjectName(f"{type(self).__name__}Button")
self.button.setIcon(qta_icon(icon_name))
- self.button.setCursor(Qt.ArrowCursor)
+ self.button.setCursor(Qt.CursorShape.ArrowCursor)
self.button.clicked.connect(self.buttonClicked.emit)
self.setPlaceholderText(placeholder_text)
@@ -33,7 +33,7 @@ def __init__(self, icon_name, placeholder_text: str, parent=None):
# )
def resizeEvent(self, event):
- frame_width = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
+ frame_width = self.style().pixelMetric(QStyle.PixelMetric.PM_DefaultFrameWidth)
button_size = self.button.sizeHint()
self.button.move(
self.rect().right() - frame_width - button_size.width(),
diff --git a/rare/widgets/collapsible_widget.py b/rare/widgets/collapsible_widget.py
index 553d8c348..60d8d49af 100644
--- a/rare/widgets/collapsible_widget.py
+++ b/rare/widgets/collapsible_widget.py
@@ -57,7 +57,7 @@ def sizeHint(self) -> QSize:
pass
def animationStart(self, checked):
- direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward
+ direction = QAbstractAnimation.Direction.Forward if checked else QAbstractAnimation.Direction.Backward
self.toggle_animation.setDirection(direction)
self.toggle_animation.start()
@@ -75,7 +75,7 @@ def setWidget(self, widget: QWidget):
self.content_area = widget
self.content_area.setParent(self)
- self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.content_area.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
# start out collapsed
if not is_checked:
@@ -104,10 +104,10 @@ class CollapsibleFrame(QFrame, CollapsibleBase):
def __init__(self, animation_duration: int = 200, parent=None):
super(CollapsibleFrame, self).__init__(parent=parent)
self.setup(animation_duration)
- self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
+ self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Sunken)
self.toggle_button = QToolButton(self)
- self.toggle_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
+ self.toggle_button.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
self.toggle_button.setIcon(qta_icon("fa.arrow-right"))
self.toggle_button.setCheckable(True)
self.toggle_button.setChecked(False)
@@ -116,13 +116,13 @@ def __init__(self, animation_duration: int = 200, parent=None):
font = self.title_label.font()
font.setBold(True)
self.title_label.setFont(font)
- self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.title_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
# don't waste space
self.main_layout = QGridLayout(self)
self.main_layout.setVerticalSpacing(0)
self.main_layout.setContentsMargins(0, 0, 0, 0)
- self.main_layout.addWidget(self.toggle_button, 0, 0, 1, 1, Qt.AlignLeft)
+ self.main_layout.addWidget(self.toggle_button, 0, 0, 1, 1, Qt.AlignmentFlag.AlignLeft)
self.main_layout.addWidget(self.title_label, 0, 1, 1, 1)
self.main_layout.setColumnStretch(1, 1)
self.main_layout.setRowStretch(0, 0)
@@ -239,7 +239,7 @@ def replace_func_group(state):
dialog.layout().addWidget(replace_button)
dialog.layout().addWidget(collapsible_frame)
dialog.layout().addWidget(collapsible_group)
- dialog.layout().setSizeConstraint(QVBoxLayout.SetFixedSize)
+ dialog.layout().setSizeConstraint(QVBoxLayout.SizeConstraint.SetFixedSize)
dialog.show()
sys.exit(app.exec_())
diff --git a/rare/widgets/dialogs.py b/rare/widgets/dialogs.py
index 836b3b55e..b101d4859 100644
--- a/rare/widgets/dialogs.py
+++ b/rare/widgets/dialogs.py
@@ -29,9 +29,9 @@ class BaseDialog(QDialog):
def __init__(self, parent=None):
super(BaseDialog, self).__init__(parent=parent)
- self.setAttribute(Qt.WA_DeleteOnClose, True)
- self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
- self.setWindowModality(Qt.WindowModal)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
+ self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.CustomizeWindowHint | Qt.WindowType.WindowTitleHint)
+ self.setWindowModality(Qt.WindowModality.WindowModal)
def setWindowTitle(self, a0):
super().setWindowTitle(dialog_title(a0))
@@ -52,10 +52,10 @@ def exec_(self):
# from QDialog if required, not this one.
# `super(BaseDialog, self).keyPressEvent(a0)`
def keyPressEvent(self, a0: QKeyEvent) -> None:
- if a0.matches(QKeySequence.Cancel):
+ if a0.matches(QKeySequence.StandardKey.Cancel):
a0.ignore()
return
- if a0.key() == Qt.Key_Enter or a0.key() == Qt.Key_Return:
+ if a0.key() == Qt.Key.Key_Enter or a0.key() == Qt.Key.Key_Return:
a0.ignore()
return
super().keyPressEvent(a0)
@@ -98,12 +98,12 @@ def __init__(self, parent=None):
# lk: dirty way to set a minimum width with fixed size constraint
spacer = QSpacerItem(
480, self.main_layout.spacing(),
- QSizePolicy.Expanding, QSizePolicy.Fixed
+ QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
self.main_layout.addItem(spacer)
self.main_layout.addLayout(self.button_layout)
- self.main_layout.setSizeConstraint(QLayout.SetFixedSize)
- self.main_layout.setAlignment(Qt.AlignVCenter)
+ self.main_layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
+ self.main_layout.setAlignment(Qt.AlignmentFlag.AlignVCenter)
def close(self):
raise RuntimeError(f"Don't use `close()` with {type(self).__name__}")
@@ -118,7 +118,7 @@ def setCentralWidget(self, widget: QWidget):
self.main_layout.indexOf(self.subtitle_label) + 1,
widget
)
- widget.layout().setAlignment(Qt.AlignTop)
+ widget.layout().setAlignment(Qt.AlignmentFlag.AlignTop)
def setCentralLayout(self, layout: QLayout):
layout.setContentsMargins(0, 0, 0, 0)
@@ -126,7 +126,7 @@ def setCentralLayout(self, layout: QLayout):
self.main_layout.indexOf(self.subtitle_label) + 1,
layout
)
- layout.setAlignment(Qt.AlignTop)
+ layout.setAlignment(Qt.AlignmentFlag.AlignTop)
@abstractmethod
def accept_handler(self):
@@ -223,10 +223,10 @@ def __init__(self, parent=None):
self.accept_button = QPushButton("accept", self)
self.reject_button = QPushButton("reject", self)
self.action_button = QPushButton("action", self)
- self.button_box = QDialogButtonBox(Qt.Horizontal, self)
- self.button_box.addButton(self.accept_button, QDialogButtonBox.AcceptRole)
- self.button_box.addButton(self.reject_button, QDialogButtonBox.RejectRole)
- self.button_box.addButton(self.action_button, QDialogButtonBox.ActionRole)
+ self.button_box = QDialogButtonBox(Qt.Orientation.Horizontal, self)
+ self.button_box.addButton(self.accept_button, QDialogButtonBox.ButtonRole.AcceptRole)
+ self.button_box.addButton(self.reject_button, QDialogButtonBox.ButtonRole.RejectRole)
+ self.button_box.addButton(self.action_button, QDialogButtonBox.ButtonRole.ActionRole)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
diff --git a/rare/widgets/elide_label.py b/rare/widgets/elide_label.py
index 7c8c95fdd..545200668 100644
--- a/rare/widgets/elide_label.py
+++ b/rare/widgets/elide_label.py
@@ -22,7 +22,7 @@ def setText(self, a0: str) -> None:
def __setElideText(self, a0: str):
elided_text = self.__fm.elidedText(
- a0, Qt.ElideRight,
+ a0, Qt.TextElideMode.ElideRight,
self.width() - (self.contentsMargins().left() + self.contentsMargins().right())
)
if not self.__tooltip:
diff --git a/rare/widgets/flow_layout.py b/rare/widgets/flow_layout.py
index c13b67b5c..f9c90224c 100644
--- a/rare/widgets/flow_layout.py
+++ b/rare/widgets/flow_layout.py
@@ -55,7 +55,7 @@ def horizontalSpacing(self):
if self._hspacing >= 0:
return self._hspacing
else:
- return self.smartSpacing(QStyle.PM_LayoutHorizontalSpacing)
+ return self.smartSpacing(QStyle.PixelMetric.PM_LayoutHorizontalSpacing)
def setVerticalSpacing(self, a0: int) -> None:
self._vspacing = a0
@@ -65,7 +65,7 @@ def verticalSpacing(self):
if self._vspacing >= 0:
return self._vspacing
else:
- return self.smartSpacing(QStyle.PM_LayoutVerticalSpacing)
+ return self.smartSpacing(QStyle.PixelMetric.PM_LayoutVerticalSpacing)
def count(self) -> int:
return len(self._items)
@@ -82,9 +82,9 @@ def takeAt(self, index: int) -> Optional[QLayoutItem]:
return item
return None
- def expandingDirections(self) -> Qt.Orientations:
- return Qt.Orientations(Qt.Orientation(0))
- # return Qt.Horizontal | Qt.Vertical
+ def expandingDirections(self) -> Qt.Orientation:
+ return Qt.Orientation(Qt.Orientation(0))
+ # return Qt.Orientation.Horizontal | Qt.Orientation.Vertical
def hasHeightForWidth(self) -> bool:
return True
@@ -125,12 +125,12 @@ def doLayout(self, rect, testonly):
hspace = self.horizontalSpacing()
if hspace == -1:
hspace = widget.style().layoutSpacing(
- QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal
+ QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal
)
vspace = self.verticalSpacing()
if vspace == -1:
vspace = widget.style().layoutSpacing(
- QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical
+ QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Vertical
)
nextX = x + item.sizeHint().width() + hspace
if nextX - hspace > effective.right() and lineheight > 0:
diff --git a/rare/widgets/image_widget.py b/rare/widgets/image_widget.py
index c453490c1..70af5018b 100644
--- a/rare/widgets/image_widget.py
+++ b/rare/widgets/image_widget.py
@@ -98,8 +98,8 @@ def _generate_squared_overlay(self) -> OverlayPath:
)
)
gradient = QLinearGradient(0, 0, 0, self.height())
- gradient.setColorAt(0.0, Qt.black)
- gradient.setColorAt(1.0, Qt.transparent)
+ gradient.setColorAt(0.0, Qt.GlobalColor.black)
+ gradient.setColorAt(1.0, Qt.GlobalColor.transparent)
self._squared_overlay = path.subtracted(inner_path), gradient
return self._squared_overlay
@@ -122,7 +122,7 @@ def _generate_rounded_overlay(self) -> OverlayPath:
def paint_image_empty(self, painter: QPainter, a0: QPaintEvent) -> None:
# when pixmap object is not available yet, show a gray rectangle
painter.setOpacity(0.5 * self._opacity)
- painter.fillRect(a0.rect(), Qt.darkGray)
+ painter.fillRect(a0.rect(), Qt.GlobalColor.darkGray)
def paint_image_cover(self, painter: QPainter, a0: QPaintEvent) -> None:
painter.setOpacity(self._opacity)
@@ -132,14 +132,14 @@ def paint_image_cover(self, painter: QPainter, a0: QPaintEvent) -> None:
painter.fillRect(a0.rect(), brush)
def paint_overlay_rounded(self, painter: QPainter, a0: QPaintEvent) -> None:
- painter.setRenderHint(QPainter.Antialiasing, True)
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
painter.setOpacity(1.0)
- painter.setCompositionMode(QPainter.CompositionMode_Source)
+ painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source)
overlay, _ = self._generate_rounded_overlay()
- painter.fillPath(overlay, self.palette().color(QPalette.Window))
+ painter.fillPath(overlay, self.palette().color(QPalette.ColorRole.Window))
def paint_overlay_squared(self, painter: QPainter, a0: QPaintEvent) -> None:
- painter.setRenderHint(QPainter.Antialiasing, False)
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing, False)
painter.setOpacity(self._opacity)
painter.fillPath(*self._generate_squared_overlay())
@@ -148,7 +148,7 @@ def paintEvent(self, a0: QPaintEvent) -> None:
if not painter.paintEngine().isActive():
return
# helps with better image quality
- painter.setRenderHint(QPainter.SmoothPixmapTransform, self._smooth_transform)
+ painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, self._smooth_transform)
self.paint_image(painter, a0)
self.paint_overlay(painter, a0)
painter.end()
diff --git a/rare/widgets/indicator_edit.py b/rare/widgets/indicator_edit.py
index 2f0a5e19f..ae731cac6 100644
--- a/rare/widgets/indicator_edit.py
+++ b/rare/widgets/indicator_edit.py
@@ -124,7 +124,7 @@ def __init__(
completer: QCompleter = None,
edit_func: Callable[[str], Tuple[bool, str, int]] = None,
save_func: Callable[[str], None] = None,
- horiz_policy: QSizePolicy.Policy = QSizePolicy.Expanding,
+ horiz_policy: QSizePolicy.Policy = QSizePolicy.Policy.Expanding,
parent=None,
):
super(IndicatorLineEdit, self).__init__(parent=parent)
@@ -137,14 +137,14 @@ def __init__(
self.line_edit.setObjectName(f"{type(self).__name__}Edit")
self.line_edit.setPlaceholderText(placeholder if placeholder else self.tr("Use global/default settings"))
self.line_edit.setToolTip(placeholder if placeholder else "")
- self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Fixed)
+ self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Policy.Fixed)
# Add completer
self.setCompleter(completer)
layout.addWidget(self.line_edit)
if edit_func is not None:
self.indicator_label = QLabel(self)
self.indicator_label.setPixmap(qta_icon("ei.info-circle", color="gray").pixmap(16, 16))
- self.indicator_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.indicator_label.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
layout.addWidget(self.indicator_label)
self.__reasons = IndicatorReasonsStrings(self)
@@ -266,13 +266,13 @@ class PathEdit(IndicatorLineEdit):
def __init__(
self,
path: str = "",
- file_mode: QFileDialog.FileMode = QFileDialog.AnyFile,
- file_filter: QDir.Filters = 0,
+ file_mode: QFileDialog.FileMode = QFileDialog.FileMode.AnyFile,
+ file_filter: QDir.Filter = 0,
name_filters: List[str] = None,
placeholder: str = "",
edit_func: Callable[[str], Tuple[bool, str, int]] = None,
save_func: Callable[[str], None] = None,
- horiz_policy: QSizePolicy.Policy = QSizePolicy.Expanding,
+ horiz_policy: QSizePolicy.Policy = QSizePolicy.Policy.Expanding,
parent=None,
):
self.__root_path = path if path else os.path.expanduser("~/")
@@ -280,9 +280,9 @@ def __init__(
self.__completer_model = QFileSystemModel(self.__completer)
try:
self.__completer_model.setOptions(
- QFileSystemModel.DontWatchForChanges
- | QFileSystemModel.DontResolveSymlinks
- | QFileSystemModel.DontUseCustomDirectoryIcons
+ QFileSystemModel.Option.DontWatchForChanges
+ | QFileSystemModel.Option.DontResolveSymlinks
+ | QFileSystemModel.Option.DontUseCustomDirectoryIcons
)
except AttributeError as e: # Error on Ubuntu
logger.warning(e)
@@ -327,11 +327,11 @@ def __set_path(self):
if not dlg_path or not os.path.isabs(dlg_path):
dlg_path = self.__root_path
dlg = QFileDialog(self, self.tr("Choose path"), dlg_path)
- dlg.setOption(QFileDialog.DontUseCustomDirectoryIcons)
+ dlg.setOption(QFileDialog.Option.DontUseCustomDirectoryIcons)
dlg.setIconProvider(PathEditIconProvider())
dlg.setFileMode(self.__file_mode)
- if self.__file_mode == QFileDialog.Directory:
- dlg.setOption(QFileDialog.ShowDirsOnly, True)
+ if self.__file_mode == QFileDialog.FileMode.Directory:
+ dlg.setOption(QFileDialog.Option.ShowDirsOnly, True)
if self.__file_filter:
dlg.setFilter(self.__file_filter)
if self.__name_filter:
diff --git a/rare/widgets/library_layout.py b/rare/widgets/library_layout.py
index 721e1ad37..8282c8d52 100644
--- a/rare/widgets/library_layout.py
+++ b/rare/widgets/library_layout.py
@@ -10,9 +10,9 @@ class LibraryLayout(FlowLayout):
def __init__(self, parent=None):
super(LibraryLayout, self).__init__(parent)
- def expandingDirections(self) -> Qt.Orientations:
- return Qt.Orientations(Qt.Orientation(0))
- # return Qt.Horizontal | Qt.Vertical
+ def expandingDirections(self) -> Qt.Orientation:
+ return Qt.Orientation(Qt.Orientation(0))
+ # return Qt.Orientation.Horizontal | Qt.Orientation.Vertical
def setGeometry(self, a0: QRect) -> None:
super(FlowLayout, self).setGeometry(a0)
@@ -75,11 +75,13 @@ def doLayout(self, rect, testonly):
hspace = self.horizontalSpacing()
if hspace == -1:
hspace = widget.style().layoutSpacing(
- QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal
+ QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal
)
vspace = self.verticalSpacing()
if vspace == -1:
- vspace = widget.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
+ vspace = widget.style().layoutSpacing(
+ QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Vertical
+ )
# lk: get the remaining space after subtracting the space required for each widget and its static padding
# lk: also reserve space for the leading static padding
diff --git a/rare/widgets/loading_widget.py b/rare/widgets/loading_widget.py
index 196d940d8..0103e5cf3 100644
--- a/rare/widgets/loading_widget.py
+++ b/rare/widgets/loading_widget.py
@@ -7,7 +7,7 @@ class LoadingWidget(QLabel):
def __init__(self, autostart=False, parent=None):
super(LoadingWidget, self).__init__(parent=parent)
self.setObjectName(type(self).__name__)
- self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+ self.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.movie = QMovie(":/images/loader.webp", parent=self)
# The animation's exact size is 94x94
self.setFixedSize(96, 96)
@@ -22,10 +22,10 @@ def __center_on_parent(self):
self.setGeometry(rect)
def event(self, e: QEvent) -> bool:
- if e.type() == QEvent.ParentAboutToChange:
+ if e.type() == QEvent.Type.ParentAboutToChange:
if self.parent() is not None:
self.parent().removeEventFilter(self)
- if e.type() == QEvent.ParentChange:
+ if e.type() == QEvent.Type.ParentChange:
if self.parent() is not None:
self.parent().installEventFilter(self)
return super().event(e)
@@ -40,7 +40,7 @@ def showEvent(self, a0: QShowEvent) -> None:
super().showEvent(a0)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
- if a0 is self.parent() and a1.type() == QEvent.Resize:
+ if a0 is self.parent() and a1.type() == QEvent.Type.Resize:
self.__center_on_parent()
return a0.event(a1)
return False
diff --git a/rare/widgets/rare_app.py b/rare/widgets/rare_app.py
index 238335bfd..e123d5360 100644
--- a/rare/widgets/rare_app.py
+++ b/rare/widgets/rare_app.py
@@ -51,10 +51,10 @@ def _on_exception(self, exc_type, exc_value, exc_tb):
self.logger.fatal(message)
action = QMessageBox.warning(
None, exc_type.__name__, message,
- buttons=QMessageBox.Ignore | QMessageBox.Abort,
- defaultButton=QMessageBox.Abort
+ buttons=QMessageBox.StandardButton.Ignore | QMessageBox.StandardButton.Abort,
+ defaultButton=QMessageBox.StandardButton.Abort
)
- if action == QMessageBox.Abort:
+ if action == QMessageBox.StandardButton.Abort:
QApplication.instance().quit()
@@ -64,7 +64,7 @@ def __init__(self, args: Namespace, log_file: str):
self.logger = logging.getLogger(type(self).__name__)
self._hook = RareAppException(self)
self.setQuitOnLastWindowClosed(False)
- self.setAttribute(Qt.AA_DontUseNativeDialogs, True)
+ self.setAttribute(Qt.ApplicationAttribute.AA_DontUseNativeDialogs, True)
self.setDesktopFileName("rare")
self.setApplicationName("Rare")
@@ -146,7 +146,7 @@ def load_translator(self, lang: str):
locale = QLocale(lang)
self.logger.info("Using locale: %s", locale.name())
translations = {
- "qtbase": QLibraryInfo.location(QLibraryInfo.TranslationsPath),
+ "qtbase": QLibraryInfo.location(QLibraryInfo.LibraryPath.TranslationsPath),
"rare": os.path.join(paths.resources_path, "languages"),
}
for filename, path in translations.items():
diff --git a/rare/widgets/selective_widget.py b/rare/widgets/selective_widget.py
index 527697cc5..c2c0e2ebe 100644
--- a/rare/widgets/selective_widget.py
+++ b/rare/widgets/selective_widget.py
@@ -51,7 +51,7 @@ def __init__(self, rgame: RareGame, platform: str, parent=None):
def install_tags(self):
install_tags = [""]
- for cb in self.findChildren(TagCheckBox, options=Qt.FindDirectChildrenOnly):
+ for cb in self.findChildren(TagCheckBox, options=Qt.FindChildOption.FindDirectChildrenOnly):
if data := cb.isChecked():
# noinspection PyTypeChecker
install_tags.extend(data)
diff --git a/rare/widgets/side_tab.py b/rare/widgets/side_tab.py
index 54dcadcea..ce73d5c98 100644
--- a/rare/widgets/side_tab.py
+++ b/rare/widgets/side_tab.py
@@ -47,7 +47,7 @@ def paintEvent(self, event):
for i in range(self.count()):
self.initStyleOption(opt, i)
- painter.drawControl(QStyle.CE_TabBarTabShape, opt)
+ painter.drawControl(QStyle.ControlElement.CE_TabBarTabShape, opt)
painter.save()
s = opt.rect.size()
@@ -60,7 +60,7 @@ def paintEvent(self, event):
painter.translate(c)
painter.rotate(90)
painter.translate(-c)
- painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
+ painter.drawControl(QStyle.ControlElement.CE_TabBarTabLabel, opt)
painter.restore()
@@ -90,7 +90,7 @@ def __init__(self, widget: Union[QWidget, SideTabContentsProtocol], title: str =
self.setTitle(title)
if widget.layout():
- widget.layout().setAlignment(Qt.AlignTop)
+ widget.layout().setAlignment(Qt.AlignmentFlag.AlignTop)
widget.layout().setContentsMargins(0, 0, 3, 0)
if hasattr(widget, "set_title"):
widget.set_title.connect(self.setTitle)
@@ -100,14 +100,14 @@ def __init__(self, widget: Union[QWidget, SideTabContentsProtocol], title: str =
if not hasattr(widget, "implements_scrollarea") or not widget.implements_scrollarea:
scrollarea = QScrollArea(self)
- scrollarea.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
- scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- scrollarea.setFrameStyle(QScrollArea.NoFrame)
+ scrollarea.setSizeAdjustPolicy(QScrollArea.SizeAdjustPolicy.AdjustToContents)
+ scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+ scrollarea.setFrameStyle(QScrollArea.Shape.NoFrame)
scrollarea.setMinimumWidth(
widget.sizeHint().width() + scrollarea.verticalScrollBar().sizeHint().width()
)
scrollarea.setWidgetResizable(True)
- widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
scrollarea.setWidget(widget)
scrollarea.widget().setAutoFillBackground(False)
scrollarea.viewport().setAutoFillBackground(False)
@@ -115,7 +115,7 @@ def __init__(self, widget: Union[QWidget, SideTabContentsProtocol], title: str =
else:
layout.addWidget(widget)
- layout.setAlignment(Qt.AlignTop)
+ layout.setAlignment(Qt.AlignmentFlag.AlignTop)
def setTitle(self, text: str) -> None:
self.title.setText(f"
{text}
")
@@ -129,7 +129,7 @@ def __init__(self, show_back: bool = False, padding: int = -1, parent=None):
super(SideTabWidget, self).__init__(parent=parent)
self.setTabBar(SideTabBar(padding=padding, parent=self))
self.setDocumentMode(True)
- self.setTabPosition(QTabWidget.West)
+ self.setTabPosition(QTabWidget.TabPosition.West)
if show_back:
super(SideTabWidget, self).addTab(
QWidget(self), qta_icon("mdi.keyboard-backspace", "ei.backward"), self.tr("Back")
diff --git a/rare/widgets/sliding_stack.py b/rare/widgets/sliding_stack.py
index 00654f4e4..ccc9f0ca4 100644
--- a/rare/widgets/sliding_stack.py
+++ b/rare/widgets/sliding_stack.py
@@ -19,9 +19,9 @@ class SlidingStackedWidget(QStackedWidget):
def __init__(self, parent=None):
super(SlidingStackedWidget, self).__init__(parent)
- self.m_direction = Qt.Horizontal
+ self.m_direction = Qt.Orientation.Horizontal
self.m_speed = 500
- self.m_animationtype = QEasingCurve.OutBack
+ self.m_animationtype = QEasingCurve.Type.OutBack
self.m_now = 0
self.m_next = 0
self.m_wrap = False
@@ -75,7 +75,7 @@ def slideInWidget(self, newwidget):
offsetx, offsety = self.frameRect().width(), self.frameRect().height()
self.widget(_next).setGeometry(self.frameRect())
- if not self.m_direction == Qt.Horizontal:
+ if not self.m_direction == Qt.Orientation.Horizontal:
if _now < _next:
offsetx, offsety = 0, -offsety
else:
@@ -111,7 +111,7 @@ def slideInWidget(self, newwidget):
self.m_next = _next
self.m_now = _now
self.m_active = True
- animgroup.start(QAbstractAnimation.DeleteWhenStopped)
+ animgroup.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
@pyqtSlot()
def animationDoneSlot(self):
@@ -121,18 +121,18 @@ def animationDoneSlot(self):
self.m_active = False
def event(self, e: QEvent):
- if e.type() == QEvent.Gesture:
+ if e.type() == QEvent.Type.Gesture:
return self.gestureEvent(QGestureEvent(e))
return super(SlidingStackedWidget, self).event(e)
def gestureEvent(self, e: QGestureEvent):
- if swipe := e.gesture(Qt.SwipeGesture):
+ if swipe := e.gesture(Qt.GestureType.SwipeGesture):
self.swipeTriggered(swipe)
return True
def swipeTriggered(self, g: QSwipeGesture):
- if g.state() == Qt.GestureFinished:
- if g.horizontalDirection() == QSwipeGesture.Left:
+ if g.state() == Qt.GestureState.GestureFinished:
+ if g.horizontalDirection() == QSwipeGesture.SwipeDirection.Left:
self.slideInPrev()
else:
self.slideInNext()
From f525f1bb3e88bd173f4d254dac0d499552aa4578 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Thu, 20 Jun 2024 22:01:32 +0300
Subject: [PATCH 07/43] Refactor: compatibility with pyside6
---
rare/models/base_game.py | 3 ++-
rare/shared/image_manager.py | 2 +-
rare/shared/rare_core.py | 21 ++++++++++++---------
rare/utils/misc.py | 15 +++++++++++----
rare/widgets/library_layout.py | 8 +++++++-
5 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/rare/models/base_game.py b/rare/models/base_game.py
index 8b65295f2..faff4ec72 100644
--- a/rare/models/base_game.py
+++ b/rare/models/base_game.py
@@ -37,7 +37,7 @@ class State(IntEnum):
UNINSTALLING = 5
SYNCING = 6
- class Signals:
+ class Signals(QObject):
class Progress(QObject):
start = pyqtSignal()
update = pyqtSignal(int)
@@ -81,6 +81,7 @@ def __init__(self, legendary_core: LegendaryCore, game: Game):
self._state = RareGameBase.State.IDLE
def __del__(self):
+ self.signals.deleteLater()
del self.signals
@property
diff --git a/rare/shared/image_manager.py b/rare/shared/image_manager.py
index 2de8c1e58..332a3e742 100644
--- a/rare/shared/image_manager.py
+++ b/rare/shared/image_manager.py
@@ -67,7 +67,7 @@ def __init__(self, signals: GlobalSignals, core: LegendaryCore):
self.__img_types: Tuple = self.__img_tall_types + self.__img_wide_types + self.__img_logo_types
self.__dl_retries = 1
self.__worker_app_names: Set[str] = set()
- super(QObject, self).__init__()
+ super(ImageManager, self).__init__()
self.signals = signals
self.core = core
diff --git a/rare/shared/rare_core.py b/rare/shared/rare_core.py
index 4d674bc49..672389eba 100644
--- a/rare/shared/rare_core.py
+++ b/rare/shared/rare_core.py
@@ -350,15 +350,18 @@ def __on_fetch_result(self, result: Tuple, result_type: int):
logger.info("Acquired data from %s worker", FetchWorker.Result(result_type).name)
- if all([self.__fetched_games_dlcs, self.__fetched_entitlements]):
- logger.debug("Fetch time %s seconds", time.perf_counter() - self.__start_time)
- self.__wrappers.import_wrappers(
- self.__core, self.__settings, [rgame.app_name for rgame in self.games]
- )
- load_steam_shortcuts()
- self.progress.emit(100, self.tr("Launching Rare"))
- self.completed.emit()
- QTimer.singleShot(100, self.__post_init)
+ # Return early if there are still things to fetch
+ if not all({self.__fetched_games_dlcs, self.__fetched_entitlements}):
+ return
+
+ logger.debug("Fetch time %s seconds", time.perf_counter() - self.__start_time)
+ self.__wrappers.import_wrappers(
+ self.__core, self.__settings, [rgame.app_name for rgame in self.games]
+ )
+ load_steam_shortcuts()
+ self.progress.emit(100, self.tr("Launching Rare"))
+ self.completed.emit()
+ QTimer.singleShot(100, self.__post_init)
def fetch(self):
self.__start_time = time.perf_counter()
diff --git a/rare/utils/misc.py b/rare/utils/misc.py
index 7eeafd831..776034440 100644
--- a/rare/utils/misc.py
+++ b/rare/utils/misc.py
@@ -8,8 +8,9 @@
QObject,
QSettings,
QFile,
- QDir,
- Qt, QLocale,
+ Qt,
+ QLocale,
+ QDirIterator,
)
from PyQt5.QtGui import QPalette, QColor, QFontMetrics
from PyQt5.QtWidgets import QApplication, QStyleFactory, QLabel
@@ -108,7 +109,10 @@ def set_color_pallete(color_scheme: str) -> None:
def get_color_schemes() -> Iterable[str]:
- yield from QDir(":/schemes")
+ it = QDirIterator(":/schemes/")
+ while it.hasNext():
+ it.next()
+ yield it.fileName()
def set_style_sheet(style_sheet: str) -> None:
@@ -133,7 +137,10 @@ def set_style_sheet(style_sheet: str) -> None:
def get_style_sheets() -> Iterable[str]:
- yield from QDir(":/stylesheets/")
+ it = QDirIterator(":/stylesheets/")
+ while it.hasNext():
+ it.next()
+ yield it.fileName()
def get_translations() -> Tuple[Tuple[str, str], ...]:
diff --git a/rare/widgets/library_layout.py b/rare/widgets/library_layout.py
index 8282c8d52..4f18d708a 100644
--- a/rare/widgets/library_layout.py
+++ b/rare/widgets/library_layout.py
@@ -124,4 +124,10 @@ def doLayout(self, rect, testonly):
def sort(self, key: Callable, reverse=False) -> None:
self._items.sort(key=key, reverse=reverse)
- self.setGeometry(self.parent().contentsRect().adjusted(*self.parent().getContentsMargins()))
+ margins = (
+ self.parent().contentsMargins().left(),
+ self.parent().contentsMargins().top(),
+ self.parent().contentsMargins().right(),
+ self.parent().contentsMargins().bottom(),
+ )
+ self.setGeometry(self.parent().contentsRect().adjusted(*margins))
From df0a7b11cdadfa0734d013eff268bd5ab096d688 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Thu, 20 Jun 2024 22:35:17 +0300
Subject: [PATCH 08/43] Refactor: move ResultsWidget into the same file as
SearchPage
---
rare/components/tabs/store/results.py | 56 ---------------------
rare/components/tabs/store/search.py | 55 ++++++++++++++++++--
rare/components/tabs/store/widgets/items.py | 6 +--
3 files changed, 53 insertions(+), 64 deletions(-)
delete mode 100644 rare/components/tabs/store/results.py
diff --git a/rare/components/tabs/store/results.py b/rare/components/tabs/store/results.py
deleted file mode 100644
index 1a9ba5fce..000000000
--- a/rare/components/tabs/store/results.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from PyQt5.QtCore import Qt
-from PyQt5.QtCore import pyqtSignal
-from PyQt5.QtWidgets import (
- QWidget,
- QSizePolicy,
- QLabel,
- QScrollArea,
-)
-
-from rare.widgets.flow_layout import FlowLayout
-from .api.models.response import CatalogOfferModel
-from .widgets.items import ResultsItemWidget
-
-
-class ResultsWidget(QScrollArea):
- show_details = pyqtSignal(CatalogOfferModel)
-
- def __init__(self, store_api, parent=None):
- super(ResultsWidget, self).__init__(parent=parent)
- self.store_api = store_api
-
- self.results_container = QWidget(self)
- self.results_container.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
- self.results_layout = FlowLayout(self.results_container)
- self.setWidget(self.results_container)
- self.setWidgetResizable(True)
-
- # self.main_layout = QVBoxLayout(self)
- # self.main_layout.setContentsMargins(0, 0, 0, 0)
- # self.main_layout.addWidget(self.results_scrollarea)
-
- self.setEnabled(False)
-
- def load_results(self, text: str):
- self.setEnabled(False)
- if text != "":
- self.store_api.search_game(text, self.show_results)
-
- def show_results(self, results: dict):
- for w in self.results_container.findChildren(QLabel, options=Qt.FindChildOption.FindDirectChildrenOnly):
- self.results_layout.removeWidget(w)
- w.deleteLater()
- for w in self.results_container.findChildren(ResultsItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
- self.results_layout.removeWidget(w)
- w.deleteLater()
-
- if not results:
- self.results_layout.addWidget(QLabel(self.tr("No results found")))
- else:
- for res in results:
- w = ResultsItemWidget(self.store_api.cached_manager, res, parent=self.results_container)
- w.show_details.connect(self.show_details.emit)
- self.results_layout.addWidget(w)
- self.results_layout.update()
- self.setEnabled(True)
-
diff --git a/rare/components/tabs/store/search.py b/rare/components/tabs/store/search.py
index 3a993d855..2b0ff3704 100644
--- a/rare/components/tabs/store/search.py
+++ b/rare/components/tabs/store/search.py
@@ -1,26 +1,26 @@
import logging
from typing import List
-from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot
+from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
QCheckBox,
QWidget,
QSizePolicy,
QScrollArea,
- QFrame,
+ QLabel,
)
-from legendary.core import LegendaryCore
from rare.ui.components.tabs.store.search import Ui_SearchWidget
from rare.widgets.button_edit import ButtonLineEdit
+from rare.widgets.flow_layout import FlowLayout
from rare.widgets.side_tab import SideTabContents
from rare.widgets.sliding_stack import SlidingStackedWidget
from .api.models.query import SearchStoreQuery
from .api.models.response import CatalogOfferModel
from .constants import Constants
-from .results import ResultsWidget
from .store_api import StoreAPI
from .widgets.details import StoreDetailsWidget
+from .widgets.items import SearchItemWidget
logger = logging.getLogger("Shop")
@@ -118,7 +118,9 @@ def init_filter(self):
self.ui.above.toggled.connect(
lambda: self.prepare_request("[1499,]") if self.ui.above.isChecked() else None
)
- # self.on_discount.toggled.connect(lambda: self.prepare_request("sale") if self.on_discount.isChecked() else None)
+ # self.on_discount.toggled.connect(
+ # lambda: self.prepare_request("sale") if self.on_discount.isChecked() else None
+ # )
self.ui.on_discount.toggled.connect(lambda: self.prepare_request())
constants = Constants()
@@ -217,3 +219,46 @@ def handle_toggle(self):
self.activated.emit(self.tag)
else:
self.deactivated.emit(self.tag)
+
+
+class ResultsWidget(QScrollArea):
+ show_details = pyqtSignal(CatalogOfferModel)
+
+ def __init__(self, store_api, parent=None):
+ super(ResultsWidget, self).__init__(parent=parent)
+ self.store_api = store_api
+
+ self.results_container = QWidget(self)
+ self.results_container.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
+ self.results_layout = FlowLayout(self.results_container)
+ self.setWidget(self.results_container)
+ self.setWidgetResizable(True)
+
+ # self.main_layout = QVBoxLayout(self)
+ # self.main_layout.setContentsMargins(0, 0, 0, 0)
+ # self.main_layout.addWidget(self.results_scrollarea)
+
+ self.setEnabled(False)
+
+ def load_results(self, text: str):
+ self.setEnabled(False)
+ if text != "":
+ self.store_api.search_game(text, self.show_results)
+
+ def show_results(self, results: dict):
+ for w in self.results_container.findChildren(QLabel, options=Qt.FindChildOption.FindDirectChildrenOnly):
+ self.results_layout.removeWidget(w)
+ w.deleteLater()
+ for w in self.results_container.findChildren(SearchItemWidget, options=Qt.FindChildOption.FindDirectChildrenOnly):
+ self.results_layout.removeWidget(w)
+ w.deleteLater()
+
+ if not results:
+ self.results_layout.addWidget(QLabel(self.tr("No results found")))
+ else:
+ for res in results:
+ w = SearchItemWidget(self.store_api.cached_manager, res, parent=self.results_container)
+ w.show_details.connect(self.show_details.emit)
+ self.results_layout.addWidget(w)
+ self.results_layout.update()
+ self.setEnabled(True)
diff --git a/rare/components/tabs/store/widgets/items.py b/rare/components/tabs/store/widgets/items.py
index 46def2817..61fef4902 100644
--- a/rare/components/tabs/store/widgets/items.py
+++ b/rare/components/tabs/store/widgets/items.py
@@ -73,10 +73,10 @@ def init_ui(self, game: CatalogOfferModel):
# logger.info(", ".join([img["type"] for img in json_info["keyImages"]]))
-class ResultsItemWidget(ItemWidget):
+class SearchItemWidget(ItemWidget):
def __init__(self, manager: QtRequests, catalog_game: CatalogOfferModel, parent=None):
- super(ResultsItemWidget, self).__init__(manager, catalog_game, parent=parent)
- self.setFixedSize(ImageSize.DisplayTall)
+ super(SearchItemWidget, self).__init__(manager, catalog_game, parent=parent)
+ self.setFixedSize(ImageSize.LibraryTall)
self.ui.setupUi(self)
key_images = catalog_game.keyImages
From e63c13d52db45901ba247b4e676680c0dafa98ba Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Fri, 21 Jun 2024 12:39:47 +0300
Subject: [PATCH 09/43] RareGame: Do not try to resolve entitlements if they
weren't fetched
`entitlements` might be an empty list, so check if it is truthy instead of `None`
---
rare/models/game.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rare/models/game.py b/rare/models/game.py
index 035efdba0..17fedec98 100644
--- a/rare/models/game.py
+++ b/rare/models/game.py
@@ -468,7 +468,7 @@ def set_steam_grade(self) -> None:
self.signals.widget.update.emit()
def grant_date(self, force=False) -> datetime:
- if (entitlements := self.core.lgd.entitlements) is None:
+ if not (entitlements := self.core.lgd.entitlements):
return self.metadata.grant_date
if self.metadata.grant_date == datetime.min.replace(tzinfo=UTC) or force:
logger.debug("Grant date for %s not found in metadata, resolving", self.app_name)
From db61a98a9531f295cc80922108d23577edaab9e9 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:22:00 +0300
Subject: [PATCH 10/43] misc: update nuitka qt5 scripts
---
misc/nuitka_build.bat | 4 ++--
misc/nuitka_build.sh | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/misc/nuitka_build.bat b/misc/nuitka_build.bat
index db6932c2b..9062a612a 100644
--- a/misc/nuitka_build.bat
+++ b/misc/nuitka_build.bat
@@ -21,8 +21,8 @@ python -m nuitka ^
--prefer-source-code ^
--include-package=pypresence ^
--include-package-data=qtawesome ^
---include-data-dir=rare\resources\images=rare\resources\images ^
---include-data-files=rare\resources\languages=rare\resources\languages="*.qm" ^
+--include-data-dir=rare\resources\images\=rare\resources\images\ ^
+--include-data-files=rare\resources\languages\=rare\resources\languages\="rare_*.qm" ^
--windows-icon-from-ico=rare\resources\images\Rare.ico ^
--windows-company-name=Rare ^
--windows-product-name=Rare ^
diff --git a/misc/nuitka_build.sh b/misc/nuitka_build.sh
index 840ee503f..f20d79cf6 100755
--- a/misc/nuitka_build.sh
+++ b/misc/nuitka_build.sh
@@ -21,8 +21,8 @@ python -m nuitka \
--prefer-source-code \
--include-package=pypresence \
--include-package-data=qtawesome \
---include-data-dir=rare/resources/images=rare/resources/images \
---include-data-files=rare/resources/languages=rare/resources/languages="*.qm" \
+--include-data-dir=rare/resources/images/=rare/resources/images/ \
+--include-data-files=rare/resources/languages/=rare/resources/languages/="rare_*.qm" \
--windows-icon-from-ico=rare/resources/images/Rare.ico \
--windows-company-name=Rare \
--windows-product-name=Rare \
From b2bdc8bd4301cdd84dc4e5b86fb86005d2b37c83 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:35:15 +0300
Subject: [PATCH 11/43] RareApp; Remove old code
---
rare/widgets/rare_app.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/rare/widgets/rare_app.py b/rare/widgets/rare_app.py
index e123d5360..bf20df02b 100644
--- a/rare/widgets/rare_app.py
+++ b/rare/widgets/rare_app.py
@@ -116,10 +116,6 @@ def __init__(self, args: Namespace, log_file: str):
self.settings = QSettings(self)
- # # Translator
- # self.translator = QTranslator(self)
- # self.qt_translator = QTranslator(self)
-
# Style
# lk: this is a bit silly but serves well until we have a class
# lk: store the default qt style name from the system on startup as a property for later reference
From c0023cd23891da9d15208019dcd4db17c8e1b736 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:46:24 +0300
Subject: [PATCH 12/43] RareSettings: reword message
---
rare/ui/components/tabs/settings/rare.ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rare/ui/components/tabs/settings/rare.ui b/rare/ui/components/tabs/settings/rare.ui
index 1c47b7c83..09b08a2db 100644
--- a/rare/ui/components/tabs/settings/rare.ui
+++ b/rare/ui/components/tabs/settings/rare.ui
@@ -122,7 +122,7 @@
-
- Exit to system tray
+ Close to system tray
From 04aafb153f2286481ea04ddab0e8ac42389af452 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:49:58 +0300
Subject: [PATCH 13/43] RareGame: Properly parent QObjects and remote delete
methods
PySide6 complains that the signals have already been deleted
---
rare/commands/launcher/__init__.py | 2 +-
rare/models/base_game.py | 37 +++++++++++-------------------
rare/models/game.py | 8 +++----
rare/shared/rare_core.py | 4 ++--
4 files changed, 20 insertions(+), 31 deletions(-)
diff --git a/rare/commands/launcher/__init__.py b/rare/commands/launcher/__init__.py
index 0380653fc..fe30bbe4f 100644
--- a/rare/commands/launcher/__init__.py
+++ b/rare/commands/launcher/__init__.py
@@ -148,7 +148,7 @@ def __init__(self, args: InitArgs):
if not game:
self.logger.error(f"Game {args.app_name} not found. Exiting")
return
- self.rgame = RareGameSlim(self.core, game)
+ self.rgame = RareGameSlim(self.core, game, self)
language = self.settings.value(*options.language)
self.load_translator(language)
diff --git a/rare/models/base_game.py b/rare/models/base_game.py
index faff4ec72..f457c2742 100644
--- a/rare/models/base_game.py
+++ b/rare/models/base_game.py
@@ -58,32 +58,21 @@ class Game(QObject):
launched = pyqtSignal(str)
finished = pyqtSignal(str)
- def __init__(self):
- super(RareGameBase.Signals, self).__init__()
- self.progress = RareGameBase.Signals.Progress()
- self.widget = RareGameBase.Signals.Widget()
- self.download = RareGameBase.Signals.Download()
- self.game = RareGameBase.Signals.Game()
-
- def __del__(self):
- self.progress.deleteLater()
- self.widget.deleteLater()
- self.download.deleteLater()
- self.game.deleteLater()
-
- __slots__ = "igame"
-
- def __init__(self, legendary_core: LegendaryCore, game: Game):
- super(RareGameBase, self).__init__()
- self.signals = RareGameBase.Signals()
+ def __init__(self, parent=None):
+ super(RareGameBase.Signals, self).__init__(parent=parent)
+ self.progress = RareGameBase.Signals.Progress(self)
+ self.widget = RareGameBase.Signals.Widget(self)
+ self.download = RareGameBase.Signals.Download(self)
+ self.game = RareGameBase.Signals.Game(self)
+
+ def __init__(self, legendary_core: LegendaryCore, game: Game, parent=None):
+ super(RareGameBase, self).__init__(parent=parent)
+ self.signals = RareGameBase.Signals(self)
self.core = legendary_core
self.game: Game = game
+ self.igame: InstalledGame = None
self._state = RareGameBase.State.IDLE
- def __del__(self):
- self.signals.deleteLater()
- del self.signals
-
@property
def state(self) -> 'RareGameBase.State':
return self._state
@@ -207,8 +196,8 @@ def install_path(self) -> Optional[str]:
class RareGameSlim(RareGameBase):
- def __init__(self, legendary_core: LegendaryCore, game: Game):
- super(RareGameSlim, self).__init__(legendary_core, game)
+ def __init__(self, legendary_core: LegendaryCore, game: Game, parent=None):
+ super(RareGameSlim, self).__init__(legendary_core, game, parent=parent)
# None if origin or not installed
self.igame: Optional[InstalledGame] = self.core.get_installed_game(game.app_name)
self.saves: List[RareSaveGame] = []
diff --git a/rare/models/game.py b/rare/models/game.py
index 17fedec98..c5c08ab7d 100644
--- a/rare/models/game.py
+++ b/rare/models/game.py
@@ -75,8 +75,8 @@ def __dict__(self):
def __bool__(self):
return self.queued or self.queue_pos is not None or self.last_played is not None
- def __init__(self, legendary_core: LegendaryCore, image_manager: ImageManager, game: Game):
- super(RareGame, self).__init__(legendary_core, game)
+ def __init__(self, legendary_core: LegendaryCore, image_manager: ImageManager, game: Game, parent=None):
+ super(RareGame, self).__init__(legendary_core, game, parent=parent)
self.__origin_install_path: Optional[str] = None
self.__origin_install_size: Optional[int] = None
@@ -583,8 +583,8 @@ def launch(
class RareEosOverlay(RareGameBase):
- def __init__(self, legendary_core: LegendaryCore, game: Game):
- super(RareEosOverlay, self).__init__(legendary_core, game)
+ def __init__(self, legendary_core: LegendaryCore, game: Game, parent=None):
+ super(RareEosOverlay, self).__init__(legendary_core, game, parent=parent)
self.igame: Optional[InstalledGame] = self.core.lgd.get_overlay_install_info()
@property
diff --git a/rare/shared/rare_core.py b/rare/shared/rare_core.py
index 672389eba..f0f2fa22f 100644
--- a/rare/shared/rare_core.py
+++ b/rare/shared/rare_core.py
@@ -72,7 +72,7 @@ def __init__(self, args: Namespace):
self.queue_threadpool.setMaxThreadCount(2)
self.__library: Dict[str, RareGame] = {}
- self.__eos_overlay = RareEosOverlay(self.__core, EOSOverlayApp)
+ self.__eos_overlay = RareEosOverlay(self.__core, EOSOverlayApp, self)
self.__eos_overlay.signals.game.install.connect(self.__signals.game.install)
self.__eos_overlay.signals.game.uninstall.connect(self.__signals.game.uninstall)
@@ -307,7 +307,7 @@ def __create_or_update_rgame(self, game: Game) -> RareGame:
logger.info(f"Updating Game for {rgame.app_name}")
rgame.update_rgame()
else:
- rgame = RareGame(self.__core, self.__image_manager, game)
+ rgame = RareGame(self.__core, self.__image_manager, game, self)
self.__add_game(rgame)
return rgame
From 556f47c2c7dae304127d5d3cc7cd9ff712bafc27 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:51:31 +0300
Subject: [PATCH 14/43] Stylesheets: remove some TabButtonWidget styling
---
rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss | 1 -
rare/resources/stylesheets/RareStyle/stylesheet.qss | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
index abc7d8054..8e3b63f80 100644
--- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
+++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
@@ -695,7 +695,6 @@ QTabBar#MainTabBar::tab:top:selected {
}
QPushButton#TabButtonWidget,
QToolButton#TabButtonWidget {
- padding: 0px;
border-color: rgb( 51, 54, 59);
}
QPushButton#TabButtonWidget:disabled,
diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss
index 39c97c9ee..80a898dba 100644
--- a/rare/resources/stylesheets/RareStyle/stylesheet.qss
+++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss
@@ -693,9 +693,9 @@ QTabBar#MainTabBar::tab:top:selected {
border-color: rgb( 72, 61, 139);
border-bottom-color: rgb( 32, 34, 37);
}
+
QPushButton#TabButtonWidget,
QToolButton#TabButtonWidget {
- padding: 0px;
border-color: rgb( 51, 54, 59);
}
QPushButton#TabButtonWidget:disabled,
From d9cab4196b20a407da2abf8521ee33c42a130e72 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:52:34 +0300
Subject: [PATCH 15/43] TrayIcon: use custom action instead of weird hackiness
---
rare/components/tray_icon.py | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/rare/components/tray_icon.py b/rare/components/tray_icon.py
index 4ad91e2ed..1451a5407 100644
--- a/rare/components/tray_icon.py
+++ b/rare/components/tray_icon.py
@@ -73,11 +73,7 @@ def update_actions(self):
action.deleteLater()
self.game_actions.clear()
for rgame in self.last_played():
- a = QAction(rgame.app_title)
- a.setProperty("app_name", rgame.app_name)
- a.triggered.connect(
- lambda: self.rcore.get_game(self.sender().property("app_name")).launch()
- )
+ a = TrayAction(self.rcore, rgame.app_title, rgame.app_name)
self.menu.insertAction(self.separator, a)
self.game_actions.append(a)
@@ -86,3 +82,14 @@ def remove_button(self, app_name: str):
if action := next((i for i in self.game_actions if i.property("app_name") == app_name), None):
self.game_actions.remove(action)
action.deleteLater()
+
+
+class TrayAction(QAction):
+ def __init__(self, rcore: RareCore, text: str, app_name: str):
+ super(TrayAction, self).__init__(text=text)
+ self.rcore = rcore
+ self.app_name = app_name
+ self.triggered.connect(self.__on_triggered)
+
+ def __on_triggered(self):
+ self.rcore.get_game(self.app_name).launch()
From 4ba35f72555370c86f883d48f0cc7b277434b2ac Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:56:35 +0300
Subject: [PATCH 16/43] GameWidget: remove use of `__slots__` as forward
declaration
This pattern caused PySide6 to derp hard. Use abstract methods instead.
---
.../tabs/games/game_widgets/game_widget.py | 24 ++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/rare/components/tabs/games/game_widgets/game_widget.py b/rare/components/tabs/games/game_widgets/game_widget.py
index 8c5d7e097..ae8435fbc 100644
--- a/rare/components/tabs/games/game_widgets/game_widget.py
+++ b/rare/components/tabs/games/game_widgets/game_widget.py
@@ -1,5 +1,6 @@
import platform
import random
+from abc import abstractmethod
from logging import getLogger
from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot, QObject, QEvent
@@ -97,10 +98,27 @@ def __init__(self, rgame: RareGame, parent=None):
"not_can_launch": self.tr("Can't launch"),
}
+ self._ui = None
+
# lk: abstract class for typing, the `self.ui` attribute should be used
# lk: by the Ui class in the children. It must contain at least the same
# lk: attributes as `GameWidgetUi` class
- __slots__ = "ui", "update_pixmap", "start_progress"
+
+ @property
+ def ui(self):
+ return self._ui
+
+ @ui.setter
+ def ui(self, arg):
+ self._ui = arg
+
+ @abstractmethod
+ def update_pixmap(self):
+ pass
+
+ @abstractmethod
+ def start_progress(self):
+ pass
def paintEvent(self, a0: QPaintEvent) -> None:
if not self.visibleRegion().isNull() and not self.rgame.has_pixmap:
@@ -212,10 +230,10 @@ def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
def mousePressEvent(self, e: QMouseEvent) -> None:
# left button
- if e.button() == 1:
+ if e.button() == Qt.MouseButton.LeftButton:
self.show_info.emit(self.rgame)
# right
- elif e.button() == 2:
+ elif e.button() == Qt.MouseButton.RightButton:
super(GameWidget, self).mousePressEvent(e)
@pyqtSlot()
From d21311f2c7648e1d6006366bccf265ca296bf6d8 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 16:04:35 +0300
Subject: [PATCH 17/43] ImportGroup: replace game title with app_name after if
a match is found
The hacky way used in AppNameCompleter doesn't work in PySide6, so search
for the app_name based on the completed game's title.
---
.../tabs/games/integrations/import_group.py | 35 ++++++-------------
rare/widgets/indicator_edit.py | 6 ++--
2 files changed, 14 insertions(+), 27 deletions(-)
diff --git a/rare/components/tabs/games/integrations/import_group.py b/rare/components/tabs/games/integrations/import_group.py
index 8650b615d..7dede9c93 100644
--- a/rare/components/tabs/games/integrations/import_group.py
+++ b/rare/components/tabs/games/integrations/import_group.py
@@ -4,9 +4,9 @@
from enum import IntEnum
from logging import getLogger
from pathlib import Path
-from typing import List, Tuple, Optional, Set
+from typing import List, Tuple, Optional, Set, Dict
-from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal, QRunnable, QObject, QThreadPool, pyqtSlot
+from PyQt5.QtCore import Qt, pyqtSignal, QRunnable, QObject, QThreadPool, pyqtSlot
from PyQt5.QtGui import QStandardItemModel, QShowEvent
from PyQt5.QtWidgets import (
QFileDialog,
@@ -145,14 +145,11 @@ def __import_game(self, path: Path, app_name: str, platform: str):
class AppNameCompleter(QCompleter):
- activated = pyqtSignal(str)
def __init__(self, app_names: Set[Tuple[str, str]], parent=None):
super(AppNameCompleter, self).__init__(parent)
- # pylint: disable=E1136
- super(AppNameCompleter, self).activated[QModelIndex].connect(self.__activated_idx)
- model = QStandardItemModel(len(app_names), 2)
+ model = QStandardItemModel(len(app_names), 2, self)
for idx, game in enumerate(app_names):
app_name, app_title = game
model.setData(model.index(idx, 0), app_title)
@@ -166,24 +163,10 @@ def __init__(self, app_names: Set[Tuple[str, str]], parent=None):
treeview.header().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
treeview.header().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
- # listview = QListView()
- # self.setPopup(listview)
- # # listview.setModelColumn(1)
-
self.setFilterMode(Qt.MatchFlag.MatchContains)
self.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
# self.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
- def __activated_idx(self, idx):
- # lk: don't even look at this in a funny way, it will die of shame
- # lk: Note to self, the completer and popup models are different.
- # lk: Getting the index from the popup and trying to use it in the completer will return invalid results
- if isinstance(idx, QModelIndex):
- self.activated.emit(self.popup().model().data(self.popup().model().index(idx.row(), 1)))
- # TODO: implement conversion from app_name to app_title (signal loop here)
- # if isinstance(idx_str, str):
- # self.activated.emit(idx_str)
-
class ImportGroup(QGroupBox):
def __init__(self, parent=None):
@@ -196,7 +179,7 @@ def __init__(self, parent=None):
self.worker: Optional[ImportWorker] = None
self.threadpool = QThreadPool.globalInstance()
- self.__app_names: Set[str] = set()
+ self.__app_names: Dict[str, str] = dict()
self.__install_dirs: Set[str] = set()
self.path_edit = PathEdit(
@@ -247,7 +230,7 @@ def __init__(self, parent=None):
def showEvent(self, a0: QShowEvent) -> None:
if a0.spontaneous():
return super().showEvent(a0)
- self.__app_names = {rgame.app_name for rgame in self.rcore.games}
+ self.__app_names = {rgame.app_title: rgame.app_name for rgame in self.rcore.games}
self.__install_dirs = {rgame.folder_name for rgame in self.rcore.games if not rgame.is_dlc}
self.app_name_edit.setCompleter(
AppNameCompleter(app_names={(rgame.app_name, rgame.app_title) for rgame in self.rcore.games})
@@ -284,10 +267,12 @@ def path_changed(self, path: str):
def app_name_edit_callback(self, text) -> Tuple[bool, str, int]:
if not text:
return False, text, IndicatorReasonsCommon.UNDEFINED
- if text in self.__app_names:
+ if text in self.__app_names.keys():
+ return True, self.__app_names[text], IndicatorReasonsCommon.VALID
+ if text in self.__app_names.values():
return True, text, IndicatorReasonsCommon.VALID
else:
- return False, text, IndicatorReasonsCommon.NOT_INSTALLED
+ return False, text, IndicatorReasonsCommon.GAME_NOT_EXISTS
def app_name_save_callback(self, text) -> None:
rgame = self.rcore.get_game(text)
@@ -391,7 +376,7 @@ def __on_import_result(self, result: List[ImportedGame]):
errored = [r for r in result if r.result == ImportResult.ERROR]
# pylint: disable=E1101
messagebox = QMessageBox(
- QMessageBox.Information,
+ QMessageBox.Icon.Information,
self.tr("Import summary"),
self.tr(
"Tried to import {} folders.\n\n"
diff --git a/rare/widgets/indicator_edit.py b/rare/widgets/indicator_edit.py
index ae731cac6..e197fe326 100644
--- a/rare/widgets/indicator_edit.py
+++ b/rare/widgets/indicator_edit.py
@@ -42,7 +42,8 @@ class IndicatorReasonsCommon(IntEnum):
DIR_NOT_EMPTY = 5
DIR_NOT_EXISTS = 6
FILE_NOT_EXISTS = 7
- NOT_INSTALLED = 8
+ GAME_NOT_INSTALLED = 8
+ GAME_NOT_EXISTS = 9
class IndicatorReasons(IntEnum):
@@ -74,7 +75,8 @@ def __init__(self, parent=None):
IndicatorReasonsCommon.DIR_NOT_EMPTY: self.tr("Directory is not empty"),
IndicatorReasonsCommon.DIR_NOT_EXISTS: self.tr("Directory does not exist"),
IndicatorReasonsCommon.FILE_NOT_EXISTS: self.tr("File does not exist"),
- IndicatorReasonsCommon.NOT_INSTALLED: self.tr("Game is not installed or does not exist"),
+ IndicatorReasonsCommon.GAME_NOT_INSTALLED: self.tr("Game is not installed"),
+ IndicatorReasonsCommon.GAME_NOT_EXISTS: self.tr("Game does not exist"),
}
def __getitem__(self, item: int) -> str:
From fd6b586d1c6b00ae560dfd2e7eae5863823f1076 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 16:06:47 +0300
Subject: [PATCH 18/43] MainTabBar: remove account widget tab and manually set
widget position
In PySide6 setting the button as the button in the tab causes a crash,
so work around that.
---
rare/components/tabs/__init__.py | 29 +++++++++++++----------------
rare/components/tabs/tab_widgets.py | 27 ++++++++++++++++++++++++++-
2 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py
index e621bd6d6..741a0117f 100644
--- a/rare/components/tabs/__init__.py
+++ b/rare/components/tabs/__init__.py
@@ -1,4 +1,4 @@
-from PyQt5.QtCore import QSize, pyqtSignal, pyqtSlot
+from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut, QMessageBox
from rare.shared import RareCore, LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
@@ -29,28 +29,33 @@ def __init__(self, parent):
# Generate Tabs
self.games_tab = GamesLibrary(self)
- self.games_index = self.addTab(self.games_tab, self.tr("Games"))
+ self.games_index = self.addTab(self.games_tab, qta_icon("mdi.gamepad-circle"), self.tr("Games"))
# Downloads Tab after Games Tab to use populated RareCore games list
self.downloads_tab = DownloadsTab(self)
- self.downloads_index = self.addTab(self.downloads_tab, "")
+ self.downloads_index = self.addTab(self.downloads_tab, qta_icon("mdi.download-circle"), "")
self.downloads_tab.update_title.connect(self.__on_downloads_update_title)
self.downloads_tab.update_queues_count()
self.setTabEnabled(self.downloads_index, not self.args.offline)
if not self.args.offline:
self.store_tab = StoreTab(self.core, parent=self)
- self.store_index = self.addTab(self.store_tab, self.tr("Store (Beta)"))
+ self.store_index = self.addTab(self.store_tab, qta_icon("mdi.storefront"), self.tr("Store (Beta)"))
self.setTabEnabled(self.store_index, not self.args.offline)
# Space Tab
space_index = self.addTab(QWidget(self), "")
self.setTabEnabled(space_index, False)
self.tab_bar.expanded = space_index
- # Button
- button_index = self.addTab(QWidget(self), "")
- self.setTabEnabled(button_index, False)
+ # Settings Tab
+ self.settings_tab = SettingsTab(self)
+ self.settings_index = self.addTab(self.settings_tab, qta_icon("fa.gear"), "")
+ self.settings_tab.about.update_available_ready.connect(
+ lambda: self.tab_bar.setTabText(self.settings_index, "(!)")
+ )
+
+ # Account Button
self.account_widget = AccountWidget(self)
self.account_widget.exit_app.connect(self.__on_exit_app)
account_action = QWidgetAction(self)
@@ -59,15 +64,7 @@ def __init__(self, parent):
account_menu = QMenu(account_button)
account_menu.addAction(account_action)
account_button.setMenu(account_menu)
- self.tab_bar.setTabButton(
- button_index, MainTabBar.ButtonPosition.RightSide, account_button
- )
-
- self.settings_tab = SettingsTab(self)
- self.settings_index = self.addTab(self.settings_tab, qta_icon("fa.gear"), "")
- self.settings_tab.about.update_available_ready.connect(
- lambda: self.tab_bar.setTabText(self.settings_index, "(!)")
- )
+ self.tab_bar.setButton(account_button)
# Open game list on click on Games tab button
self.tabBarClicked.connect(self.mouse_clicked)
diff --git a/rare/components/tabs/tab_widgets.py b/rare/components/tabs/tab_widgets.py
index dfa01d8cf..4c0bc5076 100644
--- a/rare/components/tabs/tab_widgets.py
+++ b/rare/components/tabs/tab_widgets.py
@@ -1,4 +1,5 @@
-from PyQt5.QtGui import QIcon
+from PyQt5.QtCore import QEvent, QPoint
+from PyQt5.QtGui import QIcon, QResizeEvent
from PyQt5.QtWidgets import QTabBar, QSizePolicy, QPushButton
@@ -10,7 +11,9 @@ def __init__(self, parent=None):
font.setPointSize(font.pointSize() + 1)
font.setBold(True)
self.setFont(font)
+
self.expanded = -1
+ self.button: TabButtonWidget = None
def tabSizeHint(self, index):
size = super(MainTabBar, self).tabSizeHint(index)
@@ -21,6 +24,27 @@ def tabSizeHint(self, index):
size.setWidth(max(size.width(), size.width() + offset))
return size
+ def __center_button(self):
+ self.button.move(QPoint(
+ self.tabRect(self.expanded).right() - self.button.width() - self.style().PixelMetric.PM_DefaultFrameWidth,
+ self.tabRect(self.expanded).bottom() - self.button.height()
+ ))
+
+ def resizeEvent(self, e: QResizeEvent):
+ super().resizeEvent(e)
+ self.__center_button()
+
+ def event(self, e):
+ if e.type() == QEvent.Type.StyleChange:
+ self.__center_button()
+ return super().event(e)
+
+ def setButton(self, widget: QPushButton):
+ widget.setParent(self)
+ widget.setFixedHeight(self.style().PixelMetric.PM_TabBarTabVSpace)
+ widget.setFixedWidth(widget.minimumSizeHint().width())
+ self.button = widget
+
class TabButtonWidget(QPushButton):
def __init__(self, icon: QIcon, tooltip: str = "", parent=None):
@@ -28,3 +52,4 @@ def __init__(self, icon: QIcon, tooltip: str = "", parent=None):
self.setObjectName(type(self).__name__)
self.setIcon(icon)
self.setToolTip(tooltip)
+ self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
From 03a1e07b46a691f8e45592d0c7b36bc76490ef27 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 17:09:37 +0300
Subject: [PATCH 19/43] Rare: regenerate resources
---
.../stylesheets/ChildOfMetropolis/__init__.py | 452 +++++++++---------
.../stylesheets/RareStyle/__init__.py | 372 +++++++-------
rare/ui/components/tabs/settings/rare.py | 2 +-
3 files changed, 413 insertions(+), 413 deletions(-)
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
index 73407d654..be09c944b 100644
--- a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
+++ b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
@@ -2,7 +2,7 @@
# Resource object code
#
-# Created by: The Resource Compiler for PyQt5 (Qt v5.15.11)
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
#
# WARNING! All changes made in this file will be lost!
@@ -45,208 +45,208 @@
\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\
\x22\x23\x45\x37\x42\x44\x35\x34\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\
\x67\x3e\
-\x00\x00\x0c\x7c\
+\x00\x00\x0c\x79\
\x00\
-\x00\x45\x4b\x78\x9c\xcd\x1c\x5d\x73\xda\xb8\xf6\x9d\x5f\xa1\x1b\
-\xa6\x33\x4d\x2e\x34\x80\x4d\x48\x9c\xe9\x43\x08\xcd\xee\x9d\xd9\
-\xce\x6e\x37\x99\xbb\x0f\x9d\x3e\x18\x50\xc0\x53\x63\x53\xdb\x34\
-\xed\xee\xe4\xbf\xdf\xa3\x2f\x5b\x92\x25\x19\x13\xda\xb9\x74\x9a\
-\x80\x74\xa4\xf3\xa1\xf3\x6d\x91\xf3\xb3\xce\xc7\x07\xfc\xad\xf8\
-\xd4\x49\xd2\x6c\x13\xc6\x01\x82\x57\x17\xd3\x17\xea\x7a\x17\xde\
-\x95\x77\x47\x86\x50\xbf\x8f\x36\x61\x94\xa0\xc7\x34\x29\xd0\x22\
-\x8d\xd3\xac\xb3\x8c\xf2\x70\x1e\xe3\x25\xac\xe9\xfa\x9e\x3f\xf1\
-\x97\xa8\x3b\xb9\x98\x4c\x26\x97\x62\x85\x80\x90\x57\xa1\xda\x2b\
-\x5b\xcd\xc3\xd7\xe8\x62\xd2\x43\x68\x32\x24\x3f\xe0\xdd\x78\xfc\
-\xea\x14\xbd\x7d\x8b\xba\xb3\x9b\xd9\x6c\xf6\x6e\xcf\x55\x23\xb1\
-\xea\xe6\xf2\xe6\xe6\x66\xda\xf9\x38\x0d\x17\x9f\x57\x59\xba\x4b\
-\x96\x2a\x83\xa3\xc1\x68\x34\x1a\xa3\xee\xed\xe8\xd6\xbf\x1d\x2b\
-\x0c\xce\xcb\x25\x9c\x60\xbc\x8c\x0a\xc2\x05\x61\xd3\x83\x97\xef\
-\x0b\xaa\xc4\x3a\x7d\x09\xb0\x9b\xa1\x0c\x87\x8b\x22\xfa\x8a\xcf\
-\xc5\x7a\xf4\x14\x2d\x57\xb8\xc8\xd1\x6b\x22\xf0\x77\x30\x9a\xf7\
-\xd0\x1f\x59\xba\xca\x70\x9e\x4f\xc3\x2c\x47\xb8\x58\x9c\x76\xd6\
-\xe9\x57\x9c\x51\x2a\x81\x4c\x78\x79\x1e\xea\x4e\x47\x33\xcf\x81\
-\xee\x69\x8d\x13\x44\xd7\x45\xc9\x0a\x91\xdf\x25\xf6\x0a\xe9\x74\
-\x57\x14\x69\x02\x28\x7f\xc5\xe1\x12\x67\xf9\x69\x27\xc7\x31\x06\
-\xa0\x34\x09\x00\xd3\xa3\x0f\xff\xe0\xfc\x86\xb3\x9b\x89\x9b\x31\
-\xb6\x4c\xe6\xa8\x13\xc6\x05\xce\x92\xb0\xc0\x64\xa7\xcb\x51\x38\
-\x02\xdd\x99\xde\x4e\xdf\x4d\xef\x9c\x3b\x89\x65\x84\xea\x2c\x7d\
-\xca\x11\x88\xff\xb7\x28\x2f\xce\x1f\x32\x8c\xcf\x1f\x08\x8a\xff\
-\x46\x18\xc6\xc3\x64\x49\x17\xdc\x2f\xb2\x34\x8e\x89\xac\x3a\x70\
-\xb6\x69\x06\x7c\xa8\xe7\xea\x5f\x7a\xcb\xcb\x39\xea\x8e\x6f\x67\
-\xde\x5d\x85\x9c\x42\x4a\x88\x37\x69\x5e\x94\xc4\xdb\x54\x6b\x32\
-\x02\xad\xba\x00\xd5\x1a\x7a\x57\x92\x6a\xb1\xb3\x50\xb4\xc2\x22\
-\x3c\x1d\x6b\x5b\x45\x88\x56\xeb\x18\xfe\x17\x20\xd4\xf1\xc8\xbf\
-\x08\x07\x8d\x7c\x2d\xb3\x74\xbb\x4c\x9f\x12\x81\xa1\x87\x42\x34\
-\x8f\x0a\x44\xb7\x01\xc8\x62\x1d\x26\x62\x15\x93\x43\x86\xe1\x3c\
-\xb7\x61\x16\x12\x3d\xd8\xc3\xa2\xa5\xc5\xa5\x71\x9b\xb4\xc0\x5b\
-\x78\x8f\xfe\x10\x0c\xd1\x9b\x81\x25\x5a\x09\x5e\x65\xe1\x32\xc2\
-\xe0\x1b\x2a\xfd\xc8\x51\x5a\xd2\x0f\x84\x7f\xc6\x08\x14\x81\xa9\
-\xc0\x1f\xe9\x76\xb7\x25\x47\x7f\xbf\xc5\x8b\x28\x8c\x3f\x75\xa2\
-\x24\x2f\xc2\x38\xee\x4b\x3a\x80\xba\x83\x09\x48\xea\xee\xea\x66\
-\x42\x25\x05\x68\x39\x54\x09\x2d\x99\x18\x40\x8f\x01\x7a\x3a\x9d\
-\xcc\xa6\x16\x68\x49\x28\x00\x3d\x02\xe8\xc9\x6c\xec\x5d\x0e\x54\
-\xe8\x5d\x52\xa7\xa5\x3b\x19\x10\x4a\xee\xa6\x83\xcb\x31\x83\x2e\
-\xa1\x24\xf8\x8a\x9a\xee\x98\xc0\x4f\xef\x2e\xfd\x0b\xdf\x0e\x5f\
-\xd1\x03\x6e\x0c\xe0\x2f\x07\xe3\x4b\xdf\xd3\xe1\xcf\xce\x3b\x9d\
-\x33\xf4\x0f\xd5\x6e\x2a\xef\x40\xb8\xf3\x6b\x3a\xc6\x8e\xa2\x2f\
-\xa6\x98\x62\xf1\xa9\xf2\x2c\xca\x69\xe6\x27\xaf\x3b\xcf\x9d\xb3\
-\x40\xe0\xef\xc1\xfb\xd2\x0a\x4a\x65\x50\x31\x32\xe5\x31\x62\x54\
-\xa6\x5c\x18\x3b\x1f\x7e\x0b\xe7\x38\xee\xf1\xdf\x3a\x2a\xbe\x2d\
-\x68\x4c\xb1\x0e\xd0\x60\xfb\xcd\xb6\x65\x91\x85\x49\x0e\xaa\x0e\
-\xea\xc6\x40\xb6\xe1\x72\x09\xae\x47\x5a\x54\x7a\xc4\xbe\x81\x22\
-\x66\xdd\x8c\xa2\xf7\x38\xd9\x11\x82\xc0\x59\x11\x0f\x25\xbd\x0d\
-\x82\xa8\xc0\x1b\x18\x20\x3e\x8c\xcf\x89\xb7\xd5\x9c\x70\x6d\xf2\
-\xfb\x72\x96\x39\x68\x36\x94\x33\x7a\x64\x38\xc4\xde\xde\xa6\x59\
-\x82\x33\xe6\xd5\x65\xb8\xbb\x2c\xdc\xe0\x8f\x8f\xe4\xe7\xfd\x3a\
-\xdc\xe2\xb7\x27\x17\x27\x9f\x60\xfc\x17\xe0\x66\x3b\x4d\xbf\x51\
-\x5a\x13\x4c\xdc\x0e\xd9\x95\x7b\x20\xf2\x36\xda\x88\xd1\x19\x18\
-\xb1\xf4\x56\x9a\x79\x48\xd3\x98\x6d\x72\x9b\x6e\xe6\xa9\xfa\xb6\
-\x54\x07\x69\x0c\x7d\xb8\x99\xe7\x20\xfa\x45\xf1\x1f\xe0\x8e\xf3\
-\x7c\xbf\x8d\x12\xb6\x74\x96\xee\x00\xbe\xfa\x2c\xb9\x41\x02\x27\
-\xfc\xbd\xf1\xac\x87\xe5\x59\xb3\xe1\xbc\xf8\x4e\xfc\x71\x9e\xc6\
-\xd1\x52\x99\x20\x4e\x66\x97\x07\x68\x24\x16\x94\x27\x4f\x47\xc8\
-\x81\xbe\x4c\xe6\x2f\x10\xe8\xcf\x96\x9d\xae\xcd\x16\xf3\x63\x09\
-\x4e\x4b\xab\x38\x82\x18\x5a\x33\x78\x03\x99\x0e\x99\xda\xe5\x6b\
-\x76\x2e\x9c\xdd\x4d\x94\xf4\xd7\x98\x85\x4f\xef\xcd\x60\x80\xf9\
-\xd1\x9f\x9f\x29\x53\xc3\x37\xde\x00\x6f\xae\x11\xb8\x4b\xd3\xec\
-\x25\xe8\x07\x99\x7b\xe6\x9a\x7f\x10\x86\xa1\x0b\xc3\xb8\xc4\x60\
-\x32\xdd\xc1\xc9\x27\xbb\x9b\x7b\xb6\x18\xbb\xba\x42\x28\xbf\xcf\
-\x97\x94\xca\xf5\x4f\xd3\xd9\x4b\xc0\x35\xa7\x5b\x5f\xc5\x52\x6e\
-\x75\xd5\xbf\xca\xf8\x40\x83\x9c\x7d\x31\x4b\xaa\x58\x7c\xa1\x6e\
-\x30\x60\x4a\x47\xa2\x8c\xc3\x1c\xf8\x86\x7b\x2a\x28\x6c\x4d\x12\
-\xa4\x3e\xc9\x90\x7a\xca\x27\xc9\xf8\x60\x78\xb7\xed\xcf\xe9\x41\
-\x33\x20\x98\xe7\x9f\x05\xba\xdd\x7c\x01\xf5\x0c\x68\x5f\x3f\xcd\
-\xa2\x55\x04\xf9\x33\x93\xf5\xf5\x51\x9d\x14\x1f\x2f\x80\xc6\x18\
-\x3f\x16\x25\xc0\x40\x03\x98\xa7\x40\xdb\xc6\x00\xa3\x72\xac\xc4\
-\x6d\x03\xeb\xea\x7c\x29\x03\x6d\x59\x25\x0c\x4b\x1c\xde\x2f\xbc\
-\x2b\xb1\x58\xa5\xb3\x2e\xe4\x6d\x9a\x47\xac\x4c\x01\x59\xa0\x8c\
-\x18\x4e\x73\x0e\xc3\xa6\xa8\x50\xb4\x79\x62\x82\x22\x91\x16\x89\
-\x31\x35\xc0\xc3\x35\xa2\x9d\x6f\x65\x39\xf1\x9e\x1a\xc9\x31\x08\
-\x6d\xf2\xc5\xe1\x47\x9b\x70\x05\x7a\xb4\xcb\xe2\xd7\x27\xc1\x39\
-\xd5\xaa\x7c\x8d\x21\x67\x3e\xbf\x5d\x47\xf1\xf2\xf7\xc7\xf7\x18\
-\x84\xb7\x05\x35\xcb\xcf\xcb\x5d\xdf\xe4\x5f\x57\x27\xa7\x1c\x73\
-\x13\x53\x32\x4a\x22\xb3\xe1\x05\xfa\x37\x1a\x9d\x81\x42\x2b\x2a\
-\x8e\xde\x52\x27\x26\x62\x2a\xc0\x78\xf4\x53\x46\xd3\x7a\x96\xf0\
-\x0b\xf1\x96\x28\xf7\x3b\x64\x82\x55\x8c\xa3\xb0\x80\xf2\x05\x57\
-\xb3\x90\x63\x92\x60\x2c\xfc\xaa\x6a\x0c\x82\xf6\xf6\xb2\xca\xd3\
-\xac\xe8\xef\xb6\x8a\xa4\x9c\x2e\xa0\x22\x9c\xe1\xb6\xd0\x2e\x4f\
-\x9a\x49\x27\x86\xfe\x42\xba\xd5\x33\x56\x02\x26\x27\xbc\x9e\xf3\
-\x16\x10\xa9\xfb\x21\x18\x02\x70\xb0\x80\x33\x23\x6e\xec\x59\x59\
-\x1a\x04\x8b\xf5\x2e\xf9\x6c\xdd\xc1\x92\x81\xf3\xcf\xa3\x57\xec\
-\xe3\x26\xcc\xa8\xab\x74\x64\xe8\x4a\x32\x61\xc9\x5f\x94\x70\xa6\
-\xd0\x33\x74\x6c\xcc\x9a\x11\x94\xb1\x72\xdf\x00\x22\x52\x11\x2d\
-\xc2\x58\xd3\xf7\x21\x0f\x94\x15\xe0\x1a\xdc\xfc\xdf\x70\xdc\x25\
-\x68\x19\xbd\xeb\xb0\x01\x90\xd3\x8f\x21\x11\x2a\xb7\xef\x29\xd3\
-\xa0\x39\xae\xe9\x72\x75\x85\xd3\xb2\xbe\x46\x14\x13\x50\x80\x92\
-\x34\xc1\xd7\x0a\x99\x06\x91\xd7\x5c\xb0\x93\x85\x06\x73\xbd\xb6\
-\x85\x45\x76\xe6\xfa\xf6\x35\x11\x34\x1b\x55\x4b\x0c\x06\x29\xba\
-\x70\x48\x21\xa5\x3d\x13\xfb\xa1\x20\x81\xa8\x25\x86\x75\x98\x2c\
-\x4b\xff\x7f\x60\x52\xb1\x67\x79\x2f\x67\xfb\xb6\x74\x44\x49\x77\
-\x07\xf2\x28\x27\xca\x1b\xd4\x8b\x29\xa3\xcf\x78\x36\x96\x5b\x75\
-\x41\xd6\x3d\x0d\x13\x14\x8d\xea\xf5\xd1\x8c\xdb\xa4\x03\x85\xa6\
-\x70\x56\x04\xa0\xd3\xf5\x41\xa6\x89\x6e\x04\x15\x0f\xc1\x63\x94\
-\xe5\x85\x28\x15\x64\xba\xf7\x21\xd0\xb4\x9a\x12\x25\x16\x4b\x9d\
-\x07\xb9\xd1\x50\xd6\xab\x6c\x65\xba\x2b\xa8\x8e\xa2\x01\xe3\x64\
-\x95\x45\x4b\x32\x50\xf3\x8b\x54\x31\xd7\xe9\x53\x7f\x89\x21\x36\
-\xd1\x66\x60\x5f\x64\xe0\xe5\x6a\x57\x9a\x5d\x6b\xae\x38\x5a\x3a\
-\x64\xba\xec\x15\x9a\x52\xf6\xca\x5b\x57\x8c\x22\xa5\xba\xe4\x2c\
-\xab\x83\x55\xb1\x2e\x46\x2d\xea\xe7\xe8\xd6\xb0\x01\x55\xf0\xaa\
-\x62\x41\x5c\x7f\x80\x3c\x84\x1d\x10\x48\x64\x43\xf2\x9c\x28\x87\
-\x18\x5f\x84\x8b\x35\xc9\x80\x8a\x94\x66\x2a\xb2\x19\x40\xa4\x3f\
-\x3f\x93\x48\xfc\xb8\xd8\x65\x44\x56\xb7\x69\xbc\xdb\x24\xb4\xce\
-\x33\x61\x56\x15\xa6\xb6\xfa\xcf\xf4\xc9\xba\x54\xd6\x16\xc0\xae\
-\x71\xcc\xea\xb1\x1a\xdf\xd5\xb0\xda\x94\x52\xcb\xb7\x56\xae\xa5\
-\xaa\xec\x74\x12\xa4\x0a\x4f\xa3\x42\x9e\xd1\x08\x11\x53\x07\xd1\
-\x22\xa7\x17\x55\xc3\xa0\x67\xa8\xed\xdd\x55\x71\xb5\x56\xaa\x8e\
-\xa4\x4d\xda\x55\xcb\xd2\x6e\xa5\xf8\xab\xad\xc4\x90\xd9\xdb\xec\
-\x59\x54\x37\x71\xfb\x43\xda\x6a\xd2\x08\x57\xe4\x0b\x7d\x98\x5b\
-\xd6\x85\xb0\x2c\x45\x18\x01\x58\xd6\xae\x1f\x25\x4b\x70\x88\x45\
-\xaa\x89\x45\x9b\x6c\x8c\xee\x65\x6a\x6b\x09\xc1\x9c\x22\x36\xcf\
-\xa8\xed\xeb\x95\x38\x17\x04\xcb\xaf\xa8\x55\x29\x5d\xd5\xdb\x35\
-\x5e\x7c\x66\x6f\xff\x04\xc9\xa4\x0d\x0a\xa5\xe7\x5f\x62\x27\x50\
-\x74\x89\x65\xb1\xa9\x3a\x2a\xed\xaf\x4e\x48\x26\x26\xcb\xad\x32\
-\x2f\x79\x54\x32\x2d\x4d\x8e\xae\x7a\xb6\xad\xae\xb8\x5a\xfb\xff\
-\x57\x4c\x2b\xf9\xbf\x31\xcb\x37\x50\x6b\x4b\x70\x0c\xa0\xb2\xaf\
-\x30\x70\x28\x4f\x9b\x59\x95\x21\x0c\x3c\x2b\xbe\xa8\xce\xbc\x32\
-\x6d\x90\xc2\x9e\xfd\x9c\x67\x1b\x75\xe6\x32\x6d\xfc\xaa\xf5\x39\
-\x1f\x57\x87\x15\x27\x65\x39\x98\x05\xa1\xc3\x7a\x2e\xd5\xac\x49\
-\xe8\xd5\xac\x49\xe6\xd2\xac\x49\xe4\x7c\xda\x41\x31\x19\x6f\xd5\
-\x06\xf8\xb2\x03\x97\x52\xf5\x00\x8c\xfc\xc2\x3b\x0c\xce\x10\x72\
-\x77\x48\xc0\x2c\x5c\xeb\x30\x26\xde\x75\x18\x93\x04\x6a\x30\x26\
-\x39\x28\x40\x47\x94\xc6\x3a\x8c\x1f\xfb\x35\x91\x58\xac\xcb\x79\
-\x18\xe3\x57\xed\xb1\x2f\xa2\x6c\x11\x37\x9d\x05\xc7\xda\xe4\x1c\
-\x0c\x60\x0e\x6d\x6c\x72\x05\x26\x30\x87\x7e\xea\xae\xa1\xbd\x42\
-\x96\x0f\xad\xdb\x68\x66\x93\x4c\xac\xc0\x8d\xba\xda\x24\x1f\x3b\
-\x70\xa3\xf6\xbe\x44\x56\x92\xba\x9a\x04\xe6\xd6\xdb\x97\x20\x66\
-\x9a\x6a\xc0\x59\x9d\x12\xdf\x95\x5c\xe4\xea\x3f\xf1\xc0\x38\x4f\
-\xe3\x65\xf5\xcc\x4b\xa9\xcd\xdf\x8c\xc9\x33\x2f\x18\xfe\xfd\xf1\
-\x31\xc7\x85\xa8\x89\xc8\xac\xd6\xf6\x3c\x34\xeb\xd4\x1b\x80\xbc\
-\xe2\x79\x33\x02\xc4\xb2\x7a\x7d\xa4\xf2\x21\x7c\xbd\x3d\x29\xb2\
-\x1d\x2e\x9f\x8f\x29\xb5\x3e\xa5\xb7\x7c\xcc\xd7\xc4\x6e\x2d\xdc\
-\xf3\x55\x41\x50\x84\xf3\x9e\xac\xda\x45\x54\x94\x3d\x9c\x86\xe7\
-\x46\xd6\x66\x38\xed\x1d\xd9\x7a\xe1\x47\x90\x68\xed\x09\x93\xaf\
-\xad\xe4\x4d\x75\x9a\x48\x5b\x81\x4c\x35\x58\xbd\x37\x0b\x39\xbe\
-\x9a\x15\x06\xe8\x0b\xe9\x48\xc0\x59\xf0\xab\x40\xaf\x29\x00\x79\
-\x7d\x1b\x92\x24\xbc\x87\xbe\xc3\xef\x41\xaf\x1a\x1e\x05\x08\x0d\
-\x61\x18\x7e\x0f\xab\xe1\x9c\x1d\xa4\x20\x40\x9f\x18\x8a\xbc\xf3\
-\x94\x11\x22\x44\xe6\x2c\x9b\xe4\x63\x95\xdd\x80\x76\xbe\x2f\x7a\
-\x14\x26\x95\x82\x9d\x0f\xf7\xd1\xdf\xf8\x97\x2c\xda\xaa\x36\x5c\
-\x75\x74\xf9\xd1\xfa\x7a\x8a\xea\x8b\xc6\x06\x38\xa8\xbf\xe8\xdd\
-\xa9\x20\xd8\x86\x09\xd1\xbc\x67\x65\x10\x18\xe9\xcf\x69\x4f\x9d\
-\x8d\x57\xfd\xf5\x2f\x5b\xf0\x06\x38\x2b\xbe\xf7\x97\x59\xf8\x34\
-\x0d\x73\xd6\x36\x2a\xc1\xe8\x5a\xc5\x74\xac\x8f\x00\xda\xb6\x27\
-\xed\x37\x73\xfc\xaa\xf5\x21\x48\x08\xe0\x38\x7b\xea\x08\x7f\xb6\
-\xa2\xa4\xe2\xa2\x77\x52\x2b\x45\x45\x37\x67\x64\xde\x5a\x6e\x81\
-\x68\x08\xf6\xee\x82\xd4\x9f\x3d\xd6\xdb\x63\xdc\x99\x51\x93\xb2\
-\x54\x84\x1a\x65\x2a\x62\xe9\x69\x91\x67\x78\x62\xac\x3f\x6b\xac\
-\x5b\xb3\xbb\x67\xd2\x60\x96\x03\x66\x95\xfd\xa1\x6a\x96\x03\x66\
-\x95\x46\xb3\x64\x94\xb8\xcc\xf2\xd9\x71\xaa\xc6\xc7\x7b\x2e\xc6\
-\x0d\x07\xa2\x31\xae\x88\xa6\x25\xe3\x23\x23\xdf\x83\x63\xb0\x5d\
-\xea\x60\xad\x73\x70\xfc\x33\x69\x76\x95\xc6\x33\x79\x11\x7d\xfb\
-\x8b\xae\x35\x75\x64\xbe\x45\x83\xd0\xa4\x15\x8e\x3e\xb6\xda\xb9\
-\x30\x48\xa5\x35\x6a\x49\x5f\x0f\xc2\x4b\xf8\x35\x87\x1e\x8b\xaa\
-\x9b\xe9\x36\x6f\x61\xf2\x22\x0e\x79\x37\xc4\xc0\x46\x3f\xe4\x72\
-\x7e\x9a\x7c\xdb\xa3\xb2\x09\x5a\xc3\x43\x3c\xb6\xe6\xf9\x59\xf3\
-\x50\x8d\x2c\x54\x0d\x6b\x71\x45\x3c\x1e\x32\xc5\x15\x1a\x8b\x4c\
-\x81\x85\x05\xa3\x76\x71\xc5\xa9\x35\x6d\x45\x4b\xd3\x47\x05\x33\
-\x0d\x5b\x16\x07\xab\x5c\xa7\x31\xc8\x59\x09\x67\x87\x45\x96\xfe\
-\xd0\x99\xf0\x1d\xc5\xc5\xca\x87\xaa\x50\x6e\x61\x5b\x65\xcb\xc0\
-\xb7\xe9\x9a\x51\x3b\xb6\xcd\x69\xee\x31\xe3\x4a\xa5\x83\x6d\x1d\
-\xf7\x01\x47\xd2\xda\x75\x1b\x0c\xe1\x87\x89\xae\x35\x71\x54\x74\
-\xad\xbd\xbb\x3d\xb7\xd3\xd9\xb3\xf9\x77\x26\x94\xd6\x88\xdd\x89\
-\xe7\x1e\x78\x29\xbf\x66\x27\x6b\x36\x05\x23\xdd\xe6\x0d\x8c\x2e\
-\xc4\x25\xef\xf6\xde\x7e\xef\xa4\x5a\x95\x6f\x7b\x44\x56\x41\xd3\
-\x52\xae\x08\x8b\x9d\x74\xf3\xea\xc8\x25\xd2\x4f\x4f\x79\xbd\xa3\
-\xba\x26\x56\x5b\x3f\x44\xdb\xa3\x48\xc7\x68\x7e\xcd\x17\xc5\xd2\
-\x6d\xb8\x88\x8a\xef\xe0\x42\x06\x03\x46\xd4\x34\x8c\xe3\x34\x4d\
-\x2a\xba\x8c\x5f\x9d\x71\x5f\x6d\xf8\xe9\xac\x00\xe1\xe7\x67\xe8\
-\x3d\xf9\xf2\x22\x29\xd1\x49\x79\x4f\xb0\x90\xab\x08\xe4\xc9\x3f\
-\xd3\xf8\x2e\x99\x57\x0a\xfe\x1f\xa3\x90\x8e\xea\xb2\x6d\xef\x47\
-\x14\x34\x66\xcd\x3b\xb0\xc8\x24\xa3\xfc\x42\xbf\x2e\x17\xb7\x03\
-\xd8\x93\xe1\x9a\x4b\x93\x11\xd4\x5a\x28\xbc\x4b\x51\x26\x1c\xea\
-\x8d\x13\x47\x7d\x7b\x80\xf8\x4b\xa5\x21\xf7\x73\xc7\x54\x71\xf8\
-\x9d\x14\x03\x95\x34\xb7\xa7\x77\x5c\x7a\x56\x10\x9e\xf1\x5a\x2f\
-\x3a\xe9\xdd\x21\x36\x6a\x76\xc8\x46\xfc\x71\xb8\x07\x7a\x02\x64\
-\xbc\xaf\xa3\xa3\xe7\xc3\x2a\x7e\xa3\x81\x58\x0a\x71\xbb\xc7\x75\
-\xb3\xf1\xc2\x92\x54\x8e\xd2\xd5\xf5\x88\x2e\xc1\x42\xdf\xb1\xd6\
-\x9e\x72\x3d\x42\x9f\x6c\xba\xba\xcb\x31\x65\xab\xf9\x6b\x34\x86\
-\xb4\x6e\xec\xc3\xff\xab\xd3\x06\x94\xe6\xcb\x2f\x56\x28\x23\xfb\
-\x14\xa5\x0f\x28\x7d\x0f\xfe\x4f\x4e\x85\x37\xbb\x8f\x96\xd8\xe5\
-\xcd\xc8\xfc\x4f\xf0\x66\xf6\x82\xa6\x75\x23\xdb\xfb\x01\x75\x4d\
-\xcd\x99\x55\x62\x39\xcc\x99\x35\xa4\x77\xf2\xfe\x75\x5f\x46\xc9\
-\xd3\x5d\x99\x28\x8b\x3d\xdd\xe1\x68\x5b\xb1\xa4\x4f\xf3\x38\x3a\
-\x0c\x33\x61\xdb\xdd\x48\x5d\xab\xe9\xa0\xc5\xdd\x18\xb1\xab\xfe\
-\xc6\x8c\xbc\xee\x6e\x04\x87\xe6\xef\xe5\x38\x1c\x8e\x8e\xc0\xfc\
-\x1d\x5a\xdb\x51\xed\x7f\xf1\x52\x4f\x4d\x89\x79\x81\x9e\x2e\xd6\
-\x35\xe3\x12\xf7\x26\xbb\x6c\xde\x7a\xf9\x7e\xec\xb8\x6a\x5f\xdd\
-\x93\x23\x88\xfe\xca\xc2\xed\x16\x93\x3f\x1a\x50\x90\xaf\xf9\xe7\
-\x0a\x3a\xc9\xb5\x70\x38\xe6\x32\x0c\x37\xd5\x4c\x00\x7b\x7a\x35\
-\xf3\xcd\x3d\xd3\x86\x16\x87\xe6\x82\xb4\xd4\x0a\xd5\xed\xbe\xea\
-\x5b\x8a\x62\x9f\x7b\x2e\x0a\x36\x73\xd0\x37\x88\x4c\x5f\x67\x30\
-\x6f\x2f\x1d\xa1\x6b\x1b\x62\x97\xf4\xdb\xd5\xfa\x2e\x74\xf0\x87\
-\x5f\x13\x14\x04\x5d\x5d\x5d\x19\x4f\x70\x7f\x71\xd8\x99\xd8\x23\
-\x0e\xc9\x7f\x4c\xe4\xd4\x86\x8d\x42\x7a\xe4\x6f\x43\x78\x3e\xf9\
-\xc1\x62\x16\xa8\xf3\xff\x00\x3a\x14\xdc\x50\
+\x00\x45\x3a\x78\x9c\xcd\x1c\xdb\x6e\xdb\x38\xf6\xdd\x5f\xc1\x8d\
+\x51\xa0\xc9\xda\xf5\x45\x72\xec\x28\xe8\x43\x1c\x37\x33\x0b\x4c\
+\x31\xd3\x49\xb0\xf3\x50\xf4\x41\xb6\x18\x5b\xa8\x2c\xb9\x92\xdc\
+\xb4\x33\xc8\xbf\xef\x21\x29\x4a\x24\x45\x52\x96\xe3\x16\xeb\xa2\
+\x89\x4d\x1e\xf2\x5c\x78\xee\xa2\x33\xb8\xe8\x7c\x7c\xc0\xdf\xf2\
+\x4f\x9d\x38\x49\xb7\x7e\xe4\x21\x78\x75\x31\x7d\xa1\xae\x73\xe9\
+\x5c\x39\x77\x64\x08\xf5\xfb\x68\xeb\x87\x31\x7a\x4c\xe2\x1c\xad\
+\x92\x28\x49\x3b\x41\x98\xf9\xcb\x08\x07\xb0\xa6\xeb\x3a\xee\xd4\
+\x0d\x50\x77\x7a\x39\x9d\x4e\x67\x7c\x05\x87\x10\x57\xa1\xda\x2b\
+\x5d\x2f\xfd\xd7\xe8\x72\xda\x43\x68\x3a\x22\x3f\xe0\xdd\x64\xf2\
+\xea\x1c\xbd\x7d\x8b\xba\x8b\x9b\xc5\x62\xf1\xee\xc0\x55\x63\xbe\
+\xea\x66\x76\x73\x73\x33\xef\x7c\x9c\xfb\xab\xcf\xeb\x34\xd9\xc7\
+\x81\xcc\xe0\x78\x38\x1e\x8f\x27\xa8\x7b\x3b\xbe\x75\x6f\x27\x12\
+\x83\xcb\x72\x49\x41\x30\x0e\xc2\x9c\x70\x41\xd8\x74\xe0\xe5\xba\
+\x9c\x2a\xbe\x4e\x5d\x02\xec\xa6\x28\xc5\xfe\x2a\x0f\xbf\xe2\x01\
+\x5f\x8f\x9e\xc2\x60\x8d\xf3\x0c\xbd\x26\x02\x7f\x07\xa3\x59\x0f\
+\xfd\x91\x26\xeb\x14\x67\xd9\xdc\x4f\x33\x84\xf3\xd5\x79\x67\x93\
+\x7c\xc5\x29\xa5\x12\xc8\x84\x97\xe3\xa0\xee\x7c\xbc\x70\x2c\xe8\
+\x9e\x36\x38\x46\x74\x5d\x18\xaf\x11\xf9\x5d\x62\xaf\x90\xce\xf7\
+\x79\x9e\xc4\x80\xf2\x57\xec\x07\x38\xcd\xce\x3b\x19\x8e\x30\x00\
+\x25\xb1\x07\x98\x1e\x5d\xf8\x07\xe7\x37\x5a\xdc\x4c\xed\x8c\xb1\
+\x65\x22\x47\x1d\x3f\xca\x71\x1a\xfb\x39\x26\x3b\xcd\xc6\xfe\x18\
+\x74\x67\x7e\x3b\x7f\x37\xbf\xb3\xee\xc4\x97\x11\xaa\xd3\xe4\x29\
+\x43\x20\xfe\xdf\xc2\x2c\x1f\x3c\xa4\x18\x0f\x1e\x08\x8a\xff\x86\
+\x18\xc6\xfd\x38\xa0\x0b\xee\x57\x69\x12\x45\x44\x56\x1d\x38\xdb\
+\x24\x05\x3e\xe4\x73\x75\x67\x4e\x30\x5b\xa2\xee\xe4\x76\xe1\xdc\
+\x55\xc8\x29\xa4\x80\x78\x9b\x64\x79\x49\xbc\x49\xb5\xa6\x63\xd0\
+\xaa\x4b\x50\xad\x91\x73\x25\xa8\x16\x3b\x0b\x49\x2b\x0c\xc2\x53\
+\xb1\xb6\x55\x84\x70\xbd\x89\xe0\x7f\x0e\x42\x9d\x8c\xdd\x4b\x7f\
+\xd8\xc8\x57\x90\x26\xbb\x20\x79\x8a\x39\x86\x1e\xf2\xd1\x32\xcc\
+\x11\xdd\x06\x20\xf3\x8d\x1f\xf3\x55\x4c\x0e\x29\x86\xf3\xdc\xf9\
+\xa9\x4f\xf4\xe0\x00\x8b\x16\x16\x97\xc6\xad\xd3\x02\x67\xe5\x3c\
+\xba\x23\x30\x44\x67\x01\x96\x68\x24\x78\x9d\xfa\x41\x88\xc1\x37\
+\x54\xfa\x91\xa1\xa4\xa4\x1f\x08\xff\x8c\x11\x28\x02\x53\x81\x3f\
+\x92\xdd\x7e\x47\x8e\xfe\x7e\x87\x57\xa1\x1f\x7d\xea\x84\x71\x96\
+\xfb\x51\xd4\x17\x74\x00\x75\x87\x53\x90\xd4\xdd\xd5\xcd\x94\x4a\
+\x0a\xd0\x16\x50\x25\xb4\x60\x62\x00\x3d\x01\xe8\xf9\x7c\xba\x98\
+\x1b\xa0\x05\xa1\x00\xf4\x18\xa0\xa7\x8b\x89\x33\x1b\xca\xd0\xfb\
+\xb8\x4e\x4b\x77\x3a\x24\x94\xdc\xcd\x87\xb3\x09\x83\x2e\xa1\x04\
+\xf8\x8a\x9a\xee\x84\xc0\xcf\xef\x66\xee\xa5\x6b\x86\xaf\xe8\x01\
+\x37\x06\xf0\xb3\xe1\x64\xe6\x3a\x2a\xfc\xc5\xa0\xd3\xe9\x5c\xa0\
+\x7f\xa8\x7a\x53\x81\x7b\xdc\x9f\x5f\xd3\x31\x76\x16\x7d\x3e\xc5\
+\x34\xab\x98\x2a\x0f\xa3\x9c\x66\x8e\xf2\xba\xf3\xdc\xb9\xf0\x38\
+\x01\x3d\x78\x5f\x9a\x41\xa9\x0d\x32\x46\xa6\x3d\x5a\x8c\xd2\x94\
+\x0d\x63\xe7\xc3\x6f\xfe\x12\x47\xbd\xe2\xb7\x8a\xaa\xd8\x16\x54\
+\x26\xdf\x78\x68\xb8\xfb\x66\xda\x32\x4f\xfd\x38\x03\x5d\x07\x7d\
+\x63\x20\x3b\x3f\x08\xc0\xf7\x08\x8b\x4a\x97\xd8\xd7\x50\xc4\xcc\
+\x9b\x51\xf4\x1e\xc7\x7b\x42\x10\x78\x2b\xe2\xa2\x84\xb7\x9e\x17\
+\xe6\x78\x0b\x03\xc4\x89\x15\x73\xfc\x6d\x35\xc7\x7d\x9b\xf8\xbe\
+\x9c\x65\x1e\x9a\x0d\x65\x8c\x1e\x11\x0e\xb1\xb7\xb7\x49\x1a\xe3\
+\x94\xb9\x75\x11\xee\x2e\xf5\xb7\xf8\xe3\x23\xf9\x79\xbf\xf1\x77\
+\xf8\xed\xd9\xe5\xd9\x27\x18\xff\x05\xb8\xd9\xcd\x93\x6f\x94\xd6\
+\x18\x13\xbf\x43\x76\x2d\x5c\x10\x79\x1b\x6e\xf9\xe8\x02\xac\x58\
+\x78\x2b\xcc\x3c\x24\x49\xc4\x36\xb9\x4d\xb6\xcb\x44\x7e\x5b\xaa\
+\x83\x30\x86\x3e\xdc\x2c\x33\x10\xfd\x2a\xff\x0f\x70\x57\xf0\x7c\
+\xbf\x0b\x63\xb6\x74\x91\xec\x01\xbe\xfa\x2c\xf8\x41\x02\xc7\x1d\
+\xbe\xf6\xac\x47\xe5\x59\xb3\xe1\x2c\xff\x4e\x1c\x72\x96\x44\x61\
+\x20\x4d\x10\x2f\xb3\xcf\x3c\x34\xe6\x0b\xca\x93\xa7\x23\xe4\x40\
+\x5f\x26\xf3\x17\x08\xf4\x67\xcb\x4e\xd5\x66\x83\xf9\xb1\x0c\xa7\
+\xa5\x55\x9c\x40\x0c\xad\x19\xbc\x81\x54\x87\x4c\xed\xb3\x0d\x3b\
+\x97\x82\xdd\x6d\x18\xf7\x37\x98\xc5\x4f\xe7\xcd\x70\x88\x8b\xa3\
+\x1f\x5c\x48\x53\xa3\x37\xce\x10\x6f\xaf\x11\xf8\x4b\xdd\xec\x0c\
+\xf4\x83\xcc\x3d\x17\x9a\x7f\x14\x86\x91\x0d\xc3\xa4\xc4\xa0\x33\
+\xdd\xe1\xd9\x27\xb3\x9b\x7b\x36\x18\xbb\xbc\x82\x2b\xbf\x5b\x2c\
+\x29\x95\xeb\x9f\xa6\xb3\x17\x80\x6b\x4e\xb7\xbe\x8a\xe5\xdc\xf2\
+\xaa\x7f\x95\xf1\x81\x46\x39\xf3\x62\x96\x55\xb1\xf8\x42\xdd\xa0\
+\xc7\x94\x8e\x44\x19\x8b\x39\x14\x1b\x1e\xa8\xa0\xb0\x35\xc9\x90\
+\xfa\x24\x45\xea\x49\x9f\x04\xe3\x83\xe1\xfd\xae\xbf\xa4\x07\xcd\
+\x80\x60\xbe\xf8\xcc\xd1\xed\x97\x2b\x28\x68\x40\xfb\xfa\x49\x1a\
+\xae\x43\x48\xa0\x99\xac\xaf\x4f\xea\xa4\x8a\xf1\x1c\x68\x8c\xf0\
+\x63\x5e\x02\x0c\x15\x80\x65\x02\xb4\x6d\x35\x30\x32\xc7\x52\xdc\
+\xd6\xb0\x2e\xcf\x97\x32\x50\x96\x55\xc2\x30\xc4\xe1\xc3\xc2\xbb\
+\x14\x8b\x65\x3a\xeb\x42\xde\x25\x59\xc8\xea\x14\x90\x05\x4a\x89\
+\xe1\x34\xe7\x30\x6c\x8a\x0a\x45\x99\x27\x26\xc8\x33\x69\x9e\x19\
+\x53\x03\x3c\x5e\x23\xda\xf9\x56\x96\x14\x1f\xa8\x91\x05\x06\xae\
+\x4d\x2e\x3f\xfc\x70\xeb\xaf\x41\x8f\xf6\x69\xf4\xfa\xcc\x1b\x50\
+\xad\xca\x36\x18\x92\xe6\xc1\xed\x26\x8c\x82\xdf\x1f\xdf\x63\x10\
+\xde\x0e\xd4\x2c\x1b\x94\xbb\xbe\xc9\xbe\xae\xcf\xce\x0b\xcc\x4d\
+\x4c\x89\x28\x89\xcc\x46\x97\xe8\xdf\x68\x7c\x01\x0a\x2d\xa9\x38\
+\x7a\x4b\x9d\x18\x8f\xa9\x00\xe3\xd0\x4f\x29\xcd\xeb\x59\xc6\xcf\
+\xc5\x5b\xa2\x3c\xec\x90\x09\x56\x3e\x8e\xfc\x1c\xea\x17\x5c\xcd\
+\x42\x8e\x49\x82\x31\xf7\xab\xb2\x31\x70\xda\xdb\xcb\x2a\x4b\xd2\
+\xbc\xbf\xdf\x49\x92\xb2\xba\x80\x8a\x70\x86\xdb\x40\xbb\x38\xa9\
+\x27\x9d\x18\xfa\x0b\xe9\x96\xcf\x58\x0a\x98\x05\xe1\xf5\x9c\x37\
+\x87\x48\xdd\xf7\xc1\x10\x80\x83\x15\x9c\x19\x71\x63\xcf\xd2\x52\
+\xcf\x5b\x6d\xf6\xf1\x67\xe3\x0e\x86\x0c\xbc\xf8\x3c\x7e\xc5\x3e\
+\x6e\xfd\x94\xba\x4a\x4b\x86\x2e\x25\x13\x86\xfc\x45\x0a\x67\x12\
+\x3d\x23\xcb\xc6\xac\x1b\x41\x19\x2b\xf7\xf5\x20\x22\xe5\xe1\xca\
+\x8f\x14\x7d\x1f\x15\x81\xb2\x02\xdc\x80\x9b\xff\x1b\x8e\xbb\x04\
+\x2d\xa3\x77\x1d\xd6\x03\x72\xfa\x11\x24\x42\xe5\xf6\x3d\x69\x1a\
+\x34\xc7\x36\x5d\xae\xae\x70\x1a\xd6\xd7\x88\x62\x02\xf2\x50\x9c\
+\xc4\xf8\x5a\x22\x53\x23\xf2\x9a\x0b\xb6\xb2\xd0\x60\xae\xd7\xa6\
+\xb0\xc8\xce\x5c\xdd\xbe\x26\x82\x66\xa3\x6a\x89\x41\x23\x45\x1b\
+\x0e\x21\xa4\xb4\x67\xe2\x30\x14\x24\x10\xb5\xc4\xb0\xf1\xe3\xa0\
+\xf4\xff\x47\x26\x15\x07\x96\xf7\x62\xb6\x6f\x4a\x47\xa4\x74\x77\
+\x28\x8e\x16\x44\x39\xc3\x7a\x31\xa5\xf5\x19\xcf\xda\x72\xab\x2e\
+\xc8\xba\xa7\x61\x82\xa2\x51\xbd\x3e\x9a\x16\x36\x69\x41\xa1\x28\
+\x9c\x11\x01\xe8\x74\x7d\x90\x69\xa2\x1d\x41\xc5\x83\xf7\x18\xa6\
+\x59\xce\x4b\x05\x91\xee\x43\x08\xd4\xad\xa6\x44\xf1\xc5\x42\xe7\
+\x41\x6c\x34\x94\xf5\x2a\x5b\x99\xec\x73\xaa\xa3\x68\xc8\x38\x59\
+\xa7\x61\x40\x06\x6a\x7e\x91\x2a\xe6\x26\x79\xea\x07\x18\x62\x13\
+\xed\x06\xf6\x79\x06\x5e\xae\xb6\xa5\xd9\xb5\xe6\x8a\xa5\xa5\x43\
+\xa6\xcb\x66\xa1\x2e\x65\xaf\xbc\x75\xc5\x28\x92\xaa\xcb\x82\x65\
+\x79\xb0\x2a\xd6\xf9\xa8\x41\xfd\x2c\xdd\x1a\x36\x20\x0b\x5e\x56\
+\x2c\x88\xeb\x0f\x90\x87\xb0\x03\x02\x89\x6c\x49\x9e\x13\x66\x10\
+\xe3\x73\x7f\xb5\x21\x19\x50\x9e\xd0\x4c\x45\x34\x03\x88\xf4\x83\
+\x0b\x81\xc4\x8f\xab\x7d\x4a\x64\x75\x9b\x44\xfb\x6d\x4c\xeb\x3c\
+\x1d\x66\x59\x61\x6a\xab\xff\x4c\x9e\x8c\x4b\x45\x6d\x01\xec\x0a\
+\xc7\xac\x1e\xab\xf1\x5d\x0d\xcb\x4d\x29\xb9\x7c\x6b\xe5\x5a\xaa\
+\xca\x4e\x25\x41\xa8\xf0\x14\x2a\xc4\x19\x85\x10\x3e\x75\x14\x2d\
+\x62\x7a\x51\x35\x0c\x7a\x9a\xda\xde\x5e\x15\x57\x6b\x85\xea\x48\
+\xd8\xa4\x5d\xb5\x2c\xec\x56\x8a\xbf\xda\x8a\x0f\xe9\xbd\xcd\x81\
+\x45\x75\x13\xb7\x3f\xa4\xad\x26\x8c\x14\x8a\x7c\xa9\x0e\x17\x96\
+\x75\xc9\x2d\x4b\x12\x86\x07\x96\xb5\xef\x87\x71\x00\x0e\x31\x4f\
+\x14\xb1\x28\x93\x8d\xd1\xbd\x4c\x6d\x0d\x21\xb8\xa0\x88\xcd\x33\
+\x6a\xfb\x6a\x25\x5e\x08\x82\xe5\x57\xd4\xaa\xa4\xae\xea\xed\x06\
+\xaf\x3e\xb3\xb7\x7f\x82\x64\x92\x06\x85\x52\xf3\x2f\xbe\x13\x28\
+\xba\xc0\x32\xdf\x54\x1e\x15\xf6\x97\x27\x04\x13\x13\xe5\x56\x99\
+\x97\x38\x2a\x98\x96\x22\x47\x5b\x3d\xdb\x56\x57\x6c\xad\xfd\xff\
+\x2b\xa6\xa5\xfc\x5f\x9b\xe5\x6b\xa8\x35\x25\x38\x1a\x50\xd1\x57\
+\x68\x38\x14\xa7\xf5\xac\x8a\x10\x1a\x9e\x25\x5f\x54\x67\x5e\x9a\
+\xd6\x48\xe1\xc0\x7e\xce\xb3\x89\x3a\x7d\x99\x36\x79\xd5\xfa\x9c\
+\x4f\xab\xc3\x92\x93\x32\x1c\xcc\x8a\xd0\x61\x3c\x97\x6a\x56\x27\
+\xf4\x6a\x56\x27\x73\x61\x56\x27\xf2\x62\xda\x42\x31\x19\x6f\xd5\
+\x06\xf8\xb2\x07\x97\x52\xf5\x00\xb4\xfc\xc2\x3b\x0c\xce\x10\x72\
+\x77\x48\xc0\x0c\x5c\xab\x30\x3a\xde\x55\x18\x9d\x04\x6a\x30\x3a\
+\x39\x48\x40\x27\x94\xc6\xc6\x8f\x1e\xfb\x35\x91\x18\xac\xcb\x7a\
+\x18\x93\x57\xed\xb1\xaf\xc2\x74\x15\x35\x9d\x45\x81\xb5\xc9\x39\
+\x68\xc0\x2c\xda\xd8\xe4\x0a\x74\x60\x16\xfd\x54\x5d\x43\x7b\x85\
+\x2c\x9f\x5a\xb7\xd1\xcc\x26\x99\x18\x81\x1b\x75\xb5\x49\x3e\x66\
+\xe0\x46\xed\x7d\x89\xac\x04\x75\xd5\x09\xcc\xae\xb7\x2f\x41\xcc\
+\x34\x55\x83\xb3\x3a\xa5\x62\x57\x72\x93\xab\xff\x54\x04\xc6\x65\
+\x12\x05\xd5\x33\x2f\xa9\x36\x7f\x33\x21\xcf\xbc\x60\xf8\xf7\xc7\
+\xc7\x0c\xe7\xbc\x26\x22\xb3\x4a\xdb\xf3\xd8\xac\x53\x6d\x00\x16\
+\x15\xcf\x9b\x31\x20\x16\xd5\xeb\x23\x95\x0f\xe1\xeb\xed\x59\x9e\
+\xee\x71\xf9\x7c\x4c\xaa\xf5\x29\xbd\xe5\x63\xbe\x26\x76\x6b\xe1\
+\xbe\x58\xe5\x79\xb9\xbf\xec\x89\xaa\x9d\x87\x79\xd9\xc3\x69\x78\
+\x6e\x64\x6c\x86\xd3\xde\x91\xa9\x17\x7e\x02\x89\xd6\x9e\x30\xb9\
+\xca\xca\xa2\xa9\x4e\x13\x69\x23\x90\xae\x06\xab\xf7\x66\x21\xc7\
+\x97\xb3\x42\x0f\x7d\x21\x1d\x09\x38\x8b\xe2\x2e\xd0\x6b\x0a\x40\
+\x5e\xdf\x46\x24\x09\xef\xa1\xef\xf0\x7b\xd8\xab\x86\xc7\x1e\x42\
+\x23\x18\x86\xdf\xa3\x6a\x38\x63\x07\xc9\x09\x50\x27\x46\x3c\xef\
+\x3c\x67\x84\x70\x91\x59\xcb\x26\xf1\x58\x45\x37\xa0\x9c\xef\x8b\
+\x1e\x85\x09\xa5\x60\xe7\xc3\x7d\xf8\x37\xfe\x25\x0d\x77\xb2\x0d\
+\x57\x1d\xdd\xe2\x68\x5d\x35\x45\x75\x79\x63\x03\x1c\xd4\x5f\xf4\
+\xf2\x94\xe7\xed\xfc\x98\x68\xde\xb3\x34\x08\x8c\xf4\x97\xb4\xa7\
+\xce\xc6\xab\xfe\xfa\x97\x1d\x78\x03\x9c\xe6\xdf\xfb\x41\xea\x3f\
+\xcd\xfd\x8c\xb5\x8d\x4a\x30\xba\x56\x32\x1d\xe3\x23\x80\xb6\xed\
+\x49\xf3\xcd\x1c\xb7\x6a\x7d\x70\x12\x3c\x38\xce\x9e\x3c\x52\x3c\
+\x5b\x91\x52\x71\xde\x3b\xa9\x95\xa2\xbc\x9b\x33\xd6\x6f\x2d\xb6\
+\x40\x14\x04\x07\x77\x41\xea\xcf\x1e\xeb\xed\xb1\xc2\x99\x51\x93\
+\x32\x54\x84\x0a\x65\x32\x62\xe1\x69\x91\xa3\x79\x62\xac\x3e\x6b\
+\xac\x5b\xb3\xbd\x67\xd2\x60\x96\x43\x66\x95\xfd\x91\x6c\x96\x43\
+\x66\x95\x5a\xb3\x64\x94\xd8\xcc\xf2\xd9\x72\xaa\xda\xc7\x7b\x36\
+\xc6\x35\x07\xa2\x30\x2e\x89\xa6\x25\xe3\x63\x2d\xdf\xc3\x53\xb0\
+\x5d\xea\x60\xad\x73\x70\xfa\x33\x69\x76\x95\xda\x33\x79\x11\x7d\
+\x87\x8b\xae\x35\x75\x64\xbe\x45\x83\x50\xa7\x15\x96\x3e\xb6\xdc\
+\xb9\xd0\x48\xa5\x35\x6a\x41\x5f\x8f\xc2\x4b\xf8\xd5\x87\x1e\x83\
+\xaa\xeb\xe9\xd6\x6f\xa1\xf3\x22\x16\x79\x37\xc4\xc0\x46\x3f\x64\
+\x73\x7e\x8a\x7c\xdb\xa3\x32\x09\x5a\xc1\x43\x3c\xb6\xe2\xf9\x59\
+\xf3\x50\x8e\x2c\x54\x0d\x6b\x71\x85\x3f\x1e\xd2\xc5\x15\x1a\x8b\
+\x74\x81\x85\x05\xa3\x76\x71\xc5\xaa\x35\x6d\x45\x4b\xd3\x47\x09\
+\x33\x0d\x5b\x06\x07\x2b\x5d\xa7\xd1\xc8\x59\x0a\x67\xc7\x45\x96\
+\xfe\xc8\x9a\xf0\x9d\xc4\xc5\x8a\x87\x2a\x51\x6e\x60\x5b\x66\x4b\
+\xc3\xb7\xee\x9a\x51\x3b\xb6\xf5\x69\xee\x29\xe3\x4a\xa5\x83\x6d\
+\x1d\xf7\x11\x47\xd2\xda\x75\x6b\x0c\xe1\x87\x89\xae\x35\x71\x54\
+\x74\xad\xbd\xbb\x39\xb7\x53\xd9\x33\xf9\x77\x26\x94\xd6\x88\xed\
+\x89\xe7\x01\x78\x29\xbf\x7a\x27\xab\x37\x05\x2d\xdd\xfa\x0d\xb4\
+\x2e\xc4\x26\xef\xf6\xde\xfe\xe0\xa4\x5a\x96\x6f\x7b\x44\x46\x41\
+\xd3\x52\x2e\xf7\xf3\xbd\x70\xf3\xea\xc4\x25\xd2\x4f\x4f\x79\x9d\
+\x93\xba\x26\x56\x5b\x3f\x84\xbb\x93\x48\x47\x6b\x7e\xcd\x17\xc5\
+\x92\x9d\xbf\x0a\xf3\xef\xe0\x42\x86\x43\x46\xd4\xdc\x8f\xa2\x24\
+\x89\x2b\xba\xb4\x5f\x9d\xb1\x5f\x6d\xf8\xe9\xac\x00\xe1\x83\x0b\
+\xf4\x9e\x7c\x7b\x91\x94\xe8\xa4\xbc\x27\x58\xc8\x55\x04\xf2\xe4\
+\x9f\x69\x7c\x97\xcc\x4b\x05\xff\x8f\x51\x48\x4b\x75\xd9\xb6\xf7\
+\xc3\x0b\x1a\xbd\xe6\x1d\x59\x64\x92\xd1\xe2\x42\xbf\x2a\x17\xbb\
+\x03\x38\x90\xe1\x9a\x4b\x13\x11\xd4\x5a\x28\x45\x97\xa2\x4c\x38\
+\xe4\x1b\x27\x96\xfa\xf6\x08\xf1\x97\x4a\x43\xee\xe7\x4e\xa8\xe2\
+\x14\x77\x52\x34\x54\xd2\xdc\x9e\xde\x71\xe9\x19\x41\x8a\x8c\xd7\
+\x78\xd1\x49\xed\x0e\xb1\x51\xbd\x43\xd6\xe2\x8f\xfc\x03\xd0\x13\
+\x20\xed\x7d\x1d\x15\x7d\x31\x2c\xe3\xd7\x1a\x88\xa1\x10\x37\x7b\
+\x5c\x3b\x1b\x2f\x2c\x49\xc5\x28\x5d\x5d\x8f\xe8\x12\x2c\xf4\x1d\
+\x6b\xed\x49\xd7\x23\xd4\x49\x2d\xe6\x74\xbd\x7c\x8d\x26\x90\xc4\
+\x4d\x5c\xf8\x7f\x75\xde\x80\x40\x7f\xd5\xc5\x08\x65\x46\xe9\x02\
+\x4a\xd7\x81\xff\xd3\x73\xee\xbb\xee\xc3\x00\xdb\x7c\x17\x99\xff\
+\x09\xbe\xcb\x5c\xbe\xb4\x6e\x5b\x3b\x3f\xa0\x8a\xa9\xb9\xae\x4a\
+\x2c\xc7\xb9\xae\x86\x64\x4e\xdc\xbf\xee\xb9\x28\x79\xaa\xe3\xe2\
+\x45\xb0\xa3\xba\x17\x65\x2b\x96\xe2\x29\xfe\x45\x85\x61\x06\x6b\
+\xba\x09\xa9\x9a\x37\x1d\x34\x38\x17\x2d\x76\xd9\xbb\xe8\x91\xd7\
+\x9d\x0b\xe7\x50\xff\x2d\x1c\x8b\x7b\x51\x11\xe8\xbf\x31\x6b\x3a\
+\xaa\xc3\xaf\x59\xaa\x89\x28\x31\x2f\xd0\xd3\xd5\xa6\x66\x5c\xfc\
+\x96\x64\x97\xcd\x1b\xaf\xda\x4f\x2c\x17\xeb\xab\x5b\x71\x04\xd1\
+\x5f\xa9\xbf\xdb\x61\xf2\x37\x02\x72\xf2\xad\xfe\x4c\x42\x27\xb8\
+\x96\x02\x8e\xb9\x0c\xcd\xbd\x34\x1d\x40\xd3\xd7\x0f\xac\xf7\xf4\
+\x74\x1b\x1a\x1c\x9a\x0d\xd2\x50\x19\x54\x77\xf9\xaa\xef\x24\xf2\
+\x7d\xee\x0b\x51\xb0\x99\xa3\xbe\x2f\xa4\xfb\xf2\x82\x7e\x7b\xe1\
+\x08\x6d\xdb\x10\xbb\xa4\xdf\xa5\x56\x77\xa1\x83\x3f\xfc\x52\x20\
+\x27\xe8\xea\xea\x4a\x7b\x82\x87\x8b\xc3\xcc\xc4\x01\x71\x48\xfc\
+\xdb\x21\xe7\x26\x6c\x14\xd2\x21\x7f\x0a\xc2\x71\xc9\x0f\x16\xb3\
+\x40\x9d\xff\x07\xb1\x4c\xd7\x4c\
\x00\x00\x01\x0d\
\x3c\
\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
@@ -430,13 +430,13 @@
\x00\x00\x00\x44\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf8\
\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\xef\
-\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6f\
-\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x80\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x7c\
-\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x62\
-\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x34\
-\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x1a\
-\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xec\
+\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6c\
+\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x7d\
+\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x79\
+\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5f\
+\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x31\
+\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x17\
+\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xe9\
"
qt_resource_struct_v2 = b"\
@@ -447,25 +447,25 @@
\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x44\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf8\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\xef\
-\x00\x00\x01\x8d\xda\xd5\x9c\x81\
-\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6f\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf9\
-\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x80\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf9\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x7c\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
-\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x62\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
-\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x34\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
-\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x1a\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf8\
-\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xec\
-\x00\x00\x01\x88\xaa\xcd\x7d\xf9\
+\x00\x00\x01\x90\x40\x3f\xfe\xde\
+\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6c\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x7d\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x79\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
+\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5f\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
+\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x31\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x17\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
+\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xe9\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py
index dfc98d193..a002fa4b9 100644
--- a/rare/resources/stylesheets/RareStyle/__init__.py
+++ b/rare/resources/stylesheets/RareStyle/__init__.py
@@ -2,7 +2,7 @@
# Resource object code
#
-# Created by: The Resource Compiler for PyQt5 (Qt v5.15.11)
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
#
# WARNING! All changes made in this file will be lost!
@@ -44,9 +44,9 @@
\x31\x2d\x34\x2e\x34\x2d\x34\x31\x20\x31\x37\x2d\x34\x31\x7a\x22\
\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\
\x22\x23\x63\x63\x63\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x0c\x8c\
+\x00\x00\x0c\x90\
\x00\
-\x00\x4a\xae\x78\x9c\xcd\x1c\xdb\x6e\xdb\x38\xf6\xdd\x5f\xc1\x4d\
+\x00\x4a\x9e\x78\x9c\xcd\x1c\xdb\x6e\xdb\x38\xf6\xdd\x5f\xc1\x4d\
\x50\xa0\xc9\x5a\xb5\x2c\xcb\x76\xa2\xa0\x0f\x93\xce\xee\xec\x02\
\x33\xd8\xe9\x24\xd8\x79\x28\xfa\x20\x5b\x4c\x2c\x54\x96\x5c\x49\
\x6e\xda\x19\xe4\xdf\xf7\xf0\x26\x91\x14\xa9\x8b\xed\x74\x27\x45\
@@ -88,165 +88,165 @@
\x25\x73\x86\x85\x73\x69\x21\xba\x9a\xb7\x2d\x94\x04\x08\x0b\x3d\
\x79\x21\xf5\x02\x8d\x85\xfb\xb4\x49\xec\xf9\xd2\x65\x0b\x05\x95\
\xf2\xc2\x6a\x81\xb4\xb4\x26\xf7\x7c\xee\x0a\x85\x99\xf7\x5a\x5a\
-\x13\x0c\x4e\xd7\x95\x9c\x96\x6d\xe9\xe5\x64\x34\xba\x44\x7f\x52\
-\xa3\xa2\x27\x16\x18\xe2\xd5\x0d\x9d\x66\xe7\xea\x48\x50\xaa\xf5\
-\x72\xa8\xea\x8c\x15\x48\xc5\xed\xdf\x8c\x9e\x47\x97\x81\xa0\x75\
-\x0c\xef\x2b\xa3\xac\x54\xaf\x41\x92\xaa\xb5\x56\x92\x4c\x50\x3d\
-\x49\x1a\xbd\xff\x39\x5c\xe1\x64\xcc\x7f\xeb\xb4\x70\x64\xa0\xb5\
-\xe5\x26\x40\xee\xee\xab\x6d\xf7\x32\x0f\xd3\x02\x8c\x10\x54\x9e\
-\x81\xec\xc2\x28\x02\xf7\x29\x2d\xaa\x7c\xbd\x63\x23\x4e\x76\xfa\
-\x8c\xb8\x5f\x70\xba\x27\xb4\x81\xef\x25\x0e\x57\x7a\x1b\x04\x71\
-\x89\xb7\x30\x40\x5c\x32\x9f\x13\x6f\xeb\x39\xe1\xa9\xe5\xf7\xd5\
-\x2c\x8b\x42\x6c\xa8\x60\xa4\xc9\x70\x88\xbd\x7d\x97\xe5\x29\xce\
-\x59\xe8\x92\xe1\xfe\x99\x87\x5b\xfc\xe1\x81\xbc\xde\x6d\xc2\x1d\
-\x7e\x7b\xb6\x38\xfb\x08\xe3\x3f\x01\x63\xbb\xdb\xec\x2b\xa5\x35\
-\xc5\xc4\x4d\x92\x5d\xb9\xc7\x24\x6f\xe3\xad\x18\xfd\x11\xdc\x8b\
-\xf4\x56\x9a\xb9\xcf\xb2\x84\x6d\xf2\x2e\xdb\xae\x32\xf5\x6d\xa5\
-\x3a\xd2\x18\x7a\xff\xc3\xaa\x80\x53\x58\x97\xff\x06\xee\x38\xcf\
-\x77\xbb\x38\x65\x4b\x7f\xcc\xf6\x00\x5f\x7f\x96\xdc\x36\x81\x13\
-\xe1\xcb\x78\xec\xd3\xea\xd8\xd9\x70\x51\x7e\x23\xa1\xa4\xc8\x92\
-\x38\x52\x26\x88\xcf\xdb\x17\x01\xf2\xc4\x82\x4a\x09\xe8\x08\x39\
-\xd0\xe3\x64\x7e\x84\x40\xbf\xb7\xec\x64\xc5\x56\xc2\x6c\xbb\x7d\
-\xca\x69\xde\xe1\x66\x73\x02\x39\x0d\x96\xc0\x0f\x90\xef\x91\xa9\
-\x7d\xb1\x61\x07\xc7\xe5\xb1\x8d\x53\x67\x83\x59\x3e\x30\x7b\xe3\
-\xba\x98\xeb\xc6\xe4\x52\x99\x9a\xbe\x99\xb9\x78\x7b\x83\xc0\x39\
-\x9b\x66\xaf\x40\x81\xc8\xdc\x33\x37\x8d\x83\x30\x4c\xdb\x30\xcc\
-\x2b\x0c\x26\xdb\x76\xcf\x3e\xda\x5d\xe2\xb3\xc5\x1b\xa8\x2b\x84\
-\x75\xf8\x7c\x49\xa5\x7d\x7f\xb6\x69\x84\x54\xab\x28\xab\x1a\x9e\
-\xda\xbc\x5c\xaa\x55\xd4\xe5\x7f\xab\xc2\x0f\x0d\xbd\xed\xbb\x28\
-\x35\x00\x8b\x64\xd4\x89\x06\x4c\x39\x49\x3c\x6b\x31\x26\xbe\xf7\
-\x70\x45\x06\x2c\x24\x1d\x74\x48\x3e\x38\x56\x3e\x49\x56\x0c\xc3\
-\xfb\x9d\xb3\xa2\x0a\xc1\x80\x60\x9e\x7f\x16\x98\xf7\xab\x35\x14\
-\x8c\xa0\xa5\x4e\x96\xc7\x8f\x31\x54\x1b\xec\x4c\x6e\x4e\xea\xed\
-\xf8\x78\x09\x34\x26\xf8\xa1\xac\x00\x5c\x0d\x60\x95\x01\x6d\x5b\
-\x03\x8c\xca\xb1\x92\x2c\x18\x58\x57\xe7\x2b\x19\x68\xcb\x6a\x61\
-\x58\x62\xfb\xe0\x44\x42\x09\xf5\x2a\xc9\x4d\x79\xef\xb2\x22\x66\
-\xf5\x1d\x88\x05\xe5\xc4\xd6\x06\x65\x56\x0c\x8a\x8a\x4a\x06\x55\
-\x6a\x89\x1b\x62\xcb\x86\xca\x4a\x94\x0c\xd4\xa8\x0f\xd7\x9e\xa3\
-\x1c\xba\x52\x2d\xf4\xd4\x69\x8e\x57\xe8\xa3\x2f\xd4\x27\xde\x86\
-\x8f\xa0\x89\xfb\x3c\x79\x7d\x16\x4c\xa8\x5e\x16\x1b\x0c\xd5\xc4\
-\xe4\x37\x38\x8d\x3b\xf2\x79\x52\xed\xf6\xa6\xf8\xf2\x78\x26\x30\
-\x76\xb1\x28\xa3\x22\xc2\x9c\x2e\xd0\xdf\x91\x77\x09\xa6\xa0\x18\
-\x07\x7a\x4b\xdd\xa4\x08\xeb\x00\x33\xa3\x9f\x72\x5a\xe8\xb0\x12\
-\x48\x08\xbb\x42\xd9\x4f\x27\x08\x56\x31\x8e\xc2\x12\xca\x3c\x5c\
-\xcf\x42\x4a\x4c\xf2\x01\xe1\xb9\x55\x33\x12\xb4\xf7\x97\x51\x91\
-\xe5\xa5\xb3\xdf\x29\x12\x6a\x75\x1a\x35\xc1\x0c\xa7\x85\x66\x79\
-\xd2\x4c\x32\x71\x0d\x07\xd2\xab\x9e\xa9\x12\x82\x39\xc1\xcd\x8c\
-\xbb\x84\xd8\xef\x84\x60\x06\x40\xf9\x1a\xce\x88\x38\xbc\x67\x65\
-\x69\x10\xac\x37\xfb\xf4\x93\x75\x07\x4b\xfe\xcf\x3f\x7b\xaf\xd8\
-\xc7\x6d\x98\x53\xa7\xda\x52\x1f\xd8\x32\x15\x4b\xf6\xa4\xc4\x4a\
-\x85\xb4\x69\x07\x0e\xa5\xc9\x43\xd9\xad\x50\x04\x10\xe7\xca\x78\
-\x1d\x26\x9a\xd6\x4f\x79\x40\xae\x01\x37\x10\x26\xfe\x80\xc3\xaf\
-\x40\xab\x2c\xa1\x09\x1b\x00\x65\x4e\x02\x09\x57\xb5\xfd\x58\x99\
-\x06\x3d\x6a\x9b\xae\x56\xd7\x38\x2d\xeb\x1b\x44\x31\x59\x05\x28\
-\xcd\x52\x7c\xa3\x90\x69\x38\x88\x86\xdf\x6e\x65\xa1\xc3\x68\x6f\
-\x6c\x61\x95\x69\x82\xbe\x7d\x43\x04\xdd\x26\x36\x10\x83\x41\x8a\
-\x6d\x38\xa4\x38\x34\x9c\x89\x7e\x28\x48\xc8\x1a\x88\x61\x13\xa6\
-\x51\xe5\xfd\x0f\x4c\x4a\x0e\xec\x54\x34\xcb\x0e\x5b\x92\xa3\x24\
-\xdb\xae\x3c\xca\x49\x9d\xb9\xcd\x5a\xcf\xe8\x5f\x9e\x8d\xd5\x60\
-\x53\xbc\x4d\xaf\xc4\xc4\x47\xb3\x82\xe6\x68\xce\x2d\xb5\x05\x85\
-\xa6\x86\x56\x04\xa0\xe9\xcd\x41\xa6\x9f\xed\x08\x6a\x1e\x82\x87\
-\x38\x2f\x4a\x51\xa8\xc8\x74\xf7\x21\xd0\xb4\x9a\x12\x25\x16\x4b\
-\x8d\x11\xb9\x0f\x52\x95\xd3\x6c\x65\xb6\x2f\xa9\xe6\x22\x97\x71\
-\xf2\x98\xc7\x11\x19\x68\x73\x9c\x54\x73\x37\xd9\x93\x13\x61\x08\
-\x65\xb4\xb7\xea\x88\x6c\xbf\xda\xa8\x2d\xa5\x6f\x74\x84\xfa\xb5\
-\xa4\x08\x64\xd5\x7a\xb5\x55\x0a\x0d\x27\x5f\x4b\x02\x29\xc5\x2f\
-\x97\x89\x3a\x58\x37\x1b\xc4\xa8\x45\x3f\x5b\xba\x4d\x6c\x40\x3d\
-\x19\x55\xf3\x20\x39\xb8\x87\x24\x86\x9d\x20\xc8\x69\x4b\x92\xa4\
-\xb8\x80\x44\xa1\x0c\xd7\x1b\x92\x3e\x95\x19\x4d\x73\x64\x3b\x81\
-\x74\x61\x72\x29\x91\xf8\x61\xbd\xcf\x89\x04\xdf\x65\xc9\x7e\x9b\
-\xd2\x32\xd4\x84\x59\xd5\xa8\xc6\xea\xdf\xb2\x27\xeb\x52\x59\x9d\
-\x00\xbb\xc6\x31\x2b\x0e\x1b\x7c\xd7\xc3\x6a\x53\x4d\xad\x25\x8f\
-\xf2\x48\x7a\xc5\xa9\x13\x26\x55\x9e\x1a\x6d\xf2\x8c\x46\x9e\x98\
-\x3a\x09\x85\xcd\x64\xa6\xee\x7d\x8c\x0d\x6d\x8a\x9e\x05\x7e\xbd\
-\x89\x54\xc9\x49\xbb\x1d\x58\xf8\x4b\xdb\x56\x87\x57\xef\x29\x86\
-\xcc\xce\x6c\x78\x7f\xa0\x4b\x14\x2f\xd2\x5f\x94\x46\xb8\x45\x2c\
-\xf4\x61\x6e\xa2\x0b\x61\xa2\x8a\x5c\x02\x30\xd1\xbd\x13\xa7\x11\
-\xb8\xde\x32\xd3\x24\xa4\x4d\x76\x66\x17\x55\xc2\x6d\x49\x01\x38\
-\x45\x6c\x9e\x51\xeb\xe8\x9d\x04\x2e\x08\x96\xdf\x51\xf3\x54\xda\
-\xcb\xef\x36\x78\xfd\x89\xbd\xfd\x0d\x24\x93\x75\x68\x9b\x9e\xff\
-\x89\x9d\xc0\x36\x24\x96\xc5\xa6\xea\xa8\xb4\xbf\x3a\x21\x59\xa5\
-\x2c\xb7\xda\x22\xe5\x51\xc9\x1a\x35\x39\xf6\xac\xb1\x87\xaa\x4d\
-\xcf\x87\x20\x7f\x29\x51\x28\x55\x89\xb1\xf6\x30\x50\x6b\x4b\xb0\
-\x0c\xa0\xb2\x57\x31\x70\x28\x4f\x9b\x59\x95\x21\x0c\x3c\x2b\x5e\
-\xab\xc9\xbc\x32\x6d\x90\xc2\xf0\x2e\xd5\xb3\x8d\x50\x73\x49\x39\
-\x7f\x35\xf8\xc8\x4f\xab\xe4\x8a\x17\xb3\x9c\xd1\x9a\xd0\x61\x3d\
-\xa2\x7a\xd6\x24\xff\x7a\xd6\x24\x7e\x69\xd6\x24\x7d\x3e\xdd\x42\
-\x31\x19\xef\xd5\xb5\xf8\xbc\x87\xf7\x75\xcb\xc2\xc8\x27\xbc\xc3\
-\xe0\x25\xa1\x7c\x80\x6c\xcf\xc2\xad\x0e\x63\xe2\x59\x87\x31\x71\
-\xde\x80\x31\xf1\xaf\x00\x9d\x40\x0a\x9b\x30\x79\x70\x1a\xa2\xb0\
-\x18\x56\xab\xf0\xe7\xaf\xfa\x63\x5d\xc7\xf9\x3a\xe9\x92\x3d\xc7\
-\xd6\xe5\x0f\x0c\x60\x2d\x5a\xd7\x65\xfd\x26\xb0\x16\x3d\xd4\xbd\
-\x41\x7f\xc5\xab\xae\x05\x0c\xd1\xc0\x2e\x59\x58\x81\x3b\x75\xb2\
-\x4b\x2e\x76\xe0\x4e\x2d\x3d\x44\x46\x92\x5a\x9a\x04\xd5\xae\x9f\
-\x87\x20\x64\x1a\x69\xc0\x55\x9f\x0a\xdf\x8d\x5c\xed\x73\x9e\x78\
-\xcc\x5b\x65\x49\x54\x3f\xcc\x53\xca\xfe\x37\x73\xf2\x30\x0f\x86\
-\xff\xf3\xf0\x50\xe0\x52\x54\x53\x64\x56\xeb\xba\x1e\x9a\x66\xea\
-\xcd\x47\x5e\x2b\xbd\xf1\x00\xb1\xac\x4e\x1f\xa8\x5c\x08\x5f\x6f\
-\xcf\xca\x7c\x8f\xab\x07\x7f\x4a\x1b\x81\xd2\x5b\x3d\xbf\xec\x62\
-\xb7\x11\xc9\xf9\xaa\x20\x28\xc3\xd5\x58\x56\xe5\x32\x2e\xab\xa6\
-\x51\xc7\x83\x2e\x6b\x0f\x9e\x36\xab\x6c\x2d\xf8\x13\x48\xb4\xf1\
-\x48\xcc\xd7\x56\xf2\x5e\x3e\xcd\x9c\xad\x40\x1d\x75\x5a\xb3\x45\
-\x0c\xf9\xbd\x9a\x06\x06\xe8\x33\xe9\x7b\xc0\xb1\xf0\xeb\x59\xaf\
-\x29\x00\xf9\xf9\x3a\x25\x09\xf8\x18\x7d\x83\xdf\xee\xb8\x1e\xf6\
-\x02\x84\x00\xcd\x37\xf8\x3d\xad\x87\x0b\x76\xa6\x06\x5a\x74\x98\
-\xa9\x21\xe7\xe4\x04\x0b\x99\x5a\x0a\xb8\xfa\xfe\x5e\x43\x01\x64\
-\x07\xa1\x69\xc2\xa9\x9e\xf2\x99\x8a\xc8\xd1\xfb\xbb\xf8\x0f\xfc\
-\x53\x1e\xef\x54\xcb\xaf\x1b\xd0\x5c\x31\x7c\x3d\x77\xf5\x45\x43\
-\x05\xdc\xd9\xef\xf4\x0a\x5c\x10\xec\xc2\x94\xe8\xed\xb3\x32\x08\
-\xcc\x39\x2b\xfa\x34\x80\x8d\xd7\x4f\x06\x3e\xef\xf2\x6c\x87\xf3\
-\xf2\x9b\x13\xe5\xe1\xd3\x6d\x58\xb0\x7e\x56\x05\x46\xd7\x2a\x86\
-\x67\x7d\x8e\x31\xb4\x9b\x6a\xbf\xdc\xe4\xd7\x2d\x17\x41\x42\x00\
-\xc7\x3e\x56\x47\xf8\x83\x21\x25\x47\x17\x3d\x9b\x46\xe5\x2a\xba\
-\x48\x9e\x79\x6b\xb9\xf5\xa2\x21\x38\xa4\xfb\xd2\x7c\xbe\xda\xec\
-\xdb\x71\xaf\x48\x6d\xd3\x52\x4b\x6a\x44\xaa\x34\x48\x4f\xbd\x66\
-\x86\x67\xe5\x2d\x8f\x4b\x9b\x1e\xa2\x77\xaf\xa6\xc3\xd4\x5d\x66\
-\xe9\xce\x54\x35\x75\x97\x59\xba\xd5\xd4\x15\xfa\x7a\x9a\xfa\x73\
-\x8b\x32\x18\x1f\x65\x76\x09\xc9\x7e\x8e\x06\x21\x99\x24\x3a\x50\
-\x48\x9e\x51\x46\xee\xcb\x89\xa8\x52\xf3\x46\x2f\xe3\x65\x4e\xf5\
-\x10\x07\x6e\x3c\xd5\xa3\xa8\x1e\x26\xe6\x13\xd0\x4c\x40\x0f\xeb\
-\x88\x9a\xb4\xad\xa5\xdf\x6f\xed\xbb\x18\x24\x78\x0c\x41\x92\xa1\
-\x1c\x4b\x0d\x91\x8d\x39\x92\x76\xdb\x98\x99\x31\xf3\x6e\x1d\x0e\
-\xb0\xe5\xc4\xfa\x04\xfa\x9e\xde\xb4\xcd\x9b\x6b\xc7\x72\x14\x56\
-\xdb\xf9\x68\x28\x49\x34\xd2\x02\x1c\x6b\xa9\xaa\x01\x94\x6a\x7a\
-\x23\x7c\x8a\xc7\x73\xa6\xf0\x49\x43\xae\x29\x7e\xb2\x98\x7b\x70\
-\xf8\x6c\xd5\xbb\xa1\x02\xa7\xe9\xb6\x42\x04\x8d\xce\x96\xd8\xd0\
-\xb8\x19\x65\x97\xbe\x12\xc0\x8f\x0e\xa0\xce\xb4\x35\x57\x7e\xc1\
-\xe8\x20\xeb\x82\xc2\x9a\x45\x44\x4d\xbe\xed\x32\x6a\x88\xf3\x18\
-\x11\x99\xab\x89\x97\x0f\x9f\xb5\x9a\x0f\x8d\x44\x07\x1e\xea\x09\
-\x62\x91\xc1\x02\x5f\x54\xcc\x27\x20\x99\x8a\xf9\x98\x70\x65\xcf\
-\xa8\x75\xfe\x7b\x04\x2c\x26\xc0\x63\xc8\x69\x2f\x02\x86\x51\x43\
-\x65\x63\x0e\x15\x9d\xe6\x68\x64\xcc\xbc\x57\x97\xf7\x6b\x3b\xb1\
-\xa3\x22\x59\xef\x62\x48\x3d\x96\xa3\x70\x5a\xcf\x87\x16\xe6\x65\
-\x58\xee\xa5\xcb\x80\x27\x2e\x78\xff\x22\x95\xc8\xec\x3b\xb8\x52\
-\xd6\x69\xb9\x8f\x77\x27\x91\x64\x97\x0b\xe8\xbe\xe7\x98\xed\xc2\
-\x75\x5c\x7e\x03\x3f\xe7\xba\x8c\xbe\xdb\x30\x49\xb2\x2c\xad\x49\
-\xec\xfa\x12\x5b\xef\x8b\x37\xff\x4f\x5e\x81\xb3\xc9\x25\xfa\x85\
-\x7c\x2b\x9a\x34\x72\x48\x13\x88\x20\x24\x17\x65\xc8\xbd\x14\x66\
-\x54\xe7\x64\x5e\x69\x0b\xbd\x8c\xa2\xf7\xeb\x36\x0c\xed\x2f\x8a\
-\xf2\xd4\xac\xc6\x27\x6d\x3a\x10\x00\xfe\x75\x19\x5d\x70\xed\x4e\
-\x68\x80\x44\x6c\xce\x56\xc6\xd5\x68\xca\xf1\xbe\x57\x95\xa4\xa9\
-\x77\xa7\x5a\x5a\x1f\xc7\x1d\x55\xa5\x6b\xe4\xc6\xfa\x9c\xea\x1b\
-\xbf\x68\x65\x20\x98\xd6\x59\xf4\xe2\xd6\xd8\x0a\xc2\xeb\x0c\xeb\
-\xf5\x3e\xbd\xf5\xc8\x46\xcd\xa1\xc2\x88\x3f\x09\x7b\xa0\x27\x40\
-\xc6\x4b\x68\x3a\x7a\x3e\xac\xe2\x37\xda\x95\xa5\x05\xd3\x2b\x00\
-\xb4\x73\x74\xba\x5e\x83\x25\x03\xa9\xef\xf2\x9c\x13\xdc\xf4\x1d\
-\x6b\x2c\x2b\x77\x79\xf4\xc9\xae\xdb\xef\xfd\x6e\x6b\xe9\xbb\x9a\
-\x6f\x6f\x59\xa1\x5a\x2e\xc2\x68\x4d\x78\xf0\x92\x77\x71\x84\xdb\
-\xbc\x24\x99\xff\x0e\x5e\xb2\x57\x45\x39\xf8\x21\xcc\xec\xbb\x15\
-\x96\x0d\x27\x59\xcb\xed\x30\x27\xd9\x3f\xb7\x95\x51\x35\x7d\x24\
-\x25\x5a\x77\x91\xa2\xb3\x31\xd3\xbd\x97\xb6\x15\x4b\x73\x35\xf7\
-\xa5\xc3\x30\x7f\x60\xbb\x5e\xac\x5b\x00\x1d\xb4\xf8\x2e\x23\x76\
-\xd5\x79\x99\x91\x37\x7d\x97\xe0\xd0\xfc\x85\xb9\x16\xef\xa5\x23\
-\x30\x7f\xa3\xde\x76\x6a\xfd\x2f\x2c\xeb\x69\x37\x31\x45\x50\xe4\
-\xf5\xa6\x61\x88\xe2\x66\xf1\x39\x9b\xb7\x7e\xc1\x65\xde\xf5\x95\
-\x19\xf5\x66\x3e\xc3\xf9\x7b\x1e\xee\x76\x98\xfc\xed\x93\x92\xfc\
-\x89\x92\x42\xc1\x2c\x79\x24\x0e\xc7\x3c\x8d\xe1\x36\xa6\x09\xe0\
-\x44\xce\xd0\xb0\xb3\xc5\x21\xb6\x41\xf6\x76\x8a\xd2\x77\x90\xc5\
-\x86\x77\x5c\x38\x6c\xe6\x05\xbe\x9c\x2d\x7f\x79\xc3\x8c\x54\x3a\
-\xf5\x9e\xf7\xd8\x89\x55\xd3\x3f\xc4\xa0\x6f\x48\x07\x5f\xfc\xf6\
-\x2c\xa7\xed\xfc\xfa\xfa\xda\x7a\xe8\xc7\xc8\xcb\xce\xda\x49\x1f\
-\x5b\x37\xff\xf0\xc6\xe4\x7f\x2f\xba\xdf\x85\
+\x13\x0c\x4e\xd7\x95\x9c\x96\x6d\xe9\xe5\x64\x34\x1a\x5d\xa2\x3f\
+\xa9\x55\xd1\x23\x0b\x0c\x01\xeb\x86\x4e\xb3\x83\x75\x24\x28\xd5\
+\x7c\x39\x54\x75\xc8\x0a\xa4\xe2\xf7\x6f\x46\xcf\xa3\xcb\x40\x10\
+\x3b\x86\xf7\x95\x55\x56\xba\xd7\x20\x49\x55\x5b\x2b\x49\x26\xa8\
+\x9e\x24\x8d\xde\xff\x1c\xae\x70\x32\xe6\xbf\x75\x5a\x38\x32\x50\
+\xdb\x72\x13\x20\x77\xf7\xd5\xb6\x7b\x99\x87\x69\x01\x56\x08\x3a\
+\xcf\x40\x76\x61\x14\x81\xff\x94\x16\x55\xce\xde\xb1\x11\x27\x7b\
+\x7d\x46\xdc\x2f\x38\xdd\x13\xda\xc0\xf9\x12\x8f\x2b\xbd\x0d\x82\
+\xb8\xc4\x5b\x18\x20\x3e\x99\xcf\x89\xb7\xf5\x9c\x70\xd5\xf2\xfb\
+\x6a\x96\x85\x21\x36\x54\x30\xd2\x64\x38\xc4\xde\xbe\xcb\xf2\x14\
+\xe7\x2c\x76\xc9\x70\xff\xcc\xc3\x2d\xfe\xf0\x40\x5e\xef\x36\xe1\
+\x0e\xbf\x3d\x5b\x9c\x7d\x84\xf1\x9f\x80\xb1\xdd\x6d\xf6\x95\xd2\
+\x9a\x62\xe2\x27\xc9\xae\xdc\x65\x92\xb7\xf1\x56\x8c\xfe\x08\xfe\
+\x45\x7a\x2b\xcd\xdc\x67\x59\xc2\x36\x79\x97\x6d\x57\x99\xfa\xb6\
+\x52\x1d\x69\x0c\xbd\xff\x61\x55\xc0\x29\xac\xcb\x7f\x03\x77\x9c\
+\xe7\xbb\x5d\x9c\xb2\xa5\x3f\x66\x7b\x80\xaf\x3f\x4b\x7e\x9b\xc0\
+\x89\xf8\x65\x3c\xf6\x69\x75\xec\x6c\xb8\x28\xbf\x91\x58\x52\x64\
+\x49\x1c\x29\x13\xc4\xe9\xed\x8b\x00\x79\x62\x41\xa5\x04\x74\x84\
+\x1c\xe8\x71\x32\x3f\x42\xa0\xdf\x5b\x76\xb2\x62\x2b\x71\xb6\xdd\
+\x3e\xe5\x3c\xef\x70\xb3\x39\x81\x9c\x06\x4b\xe0\x07\x48\xf8\xc8\
+\xd4\xbe\xd8\xb0\x83\xe3\xf2\xd8\xc6\xa9\xb3\xc1\x2c\x21\x98\xbd\
+\x71\x5d\xcc\x75\x63\x72\xa9\x4c\x4d\xdf\xcc\x5c\xbc\xbd\x41\xe0\
+\x9d\x4d\xb3\x57\xa0\x40\x64\xee\x99\x9b\xc6\x41\x18\xa6\x6d\x18\
+\xe6\x15\x06\x93\x6d\xbb\x67\x1f\xed\x2e\xf1\xd9\xe2\x0d\xd4\x15\
+\xc2\x3a\x7c\xbe\xa4\xd2\xbe\x3f\xdb\x34\x42\x2a\x56\x94\x55\x0d\
+\x4f\x6d\x5e\x2e\x15\x2b\xea\xf2\xbf\x55\xe1\x87\xc6\xde\xf6\x5d\
+\x94\x22\x80\x45\x32\xea\x44\x03\xa6\x9c\x24\x9e\xb5\x18\x13\xdf\
+\x7b\xb8\x22\x03\x16\x92\x0f\x3a\x24\x21\x1c\x2b\x9f\x24\x2b\x86\
+\xe1\xfd\xce\x59\x51\x85\x60\x40\x30\xcf\x3f\x0b\xcc\xfb\xd5\x1a\
+\x2a\x46\xd0\x52\x27\xcb\xe3\xc7\x18\xca\x0d\x76\x26\x37\x27\xf5\
+\x76\x7c\xbc\x04\x1a\x13\xfc\x50\x56\x00\xae\x06\xb0\xca\x80\xb6\
+\xad\x01\x46\xe5\x58\x49\x16\x0c\xac\xab\xf3\x95\x0c\xb4\x65\xb5\
+\x30\x2c\xb1\x7d\x70\x22\xa1\x84\x7a\x95\xe4\xa6\xbc\x77\x59\x11\
+\xb3\x02\x0f\xc4\x82\x72\x62\x6b\x83\x32\x2b\x06\x45\x45\x25\x83\
+\x2a\xc5\xc4\x0d\xb1\x65\x43\x69\x25\x6a\x06\x6a\xd4\x87\x6b\xcf\
+\x51\x0e\x5d\x29\x17\x7a\xea\x34\xc7\x2b\xf4\xd1\x17\xea\x13\x6f\
+\xc3\x47\xd0\xc4\x7d\x9e\xbc\x3e\x0b\x26\x54\x2f\x8b\x0d\x86\x72\
+\x62\xf2\x1b\x9c\xc6\x1d\xf9\x3c\xa9\x76\x7b\x53\x7c\x79\x3c\x13\
+\x18\xbb\x58\x94\x51\x11\x61\x4e\x17\xe8\xef\xc8\xbb\x04\x53\x50\
+\x8c\x03\xbd\xa5\x6e\x52\x84\x75\x80\x99\xd1\x4f\x39\xad\x74\x58\
+\x0d\x24\x84\x5d\xa1\xec\xa7\x13\x04\xab\x18\x47\x61\x09\x75\x1e\
+\xae\x67\x21\x25\x26\xf9\x80\xf0\xdc\xaa\x19\x09\xda\xfb\xcb\xa8\
+\xc8\xf2\xd2\xd9\xef\x14\x09\xb5\x3a\x8d\x9a\x60\x86\xd3\x42\xb3\
+\x3c\x69\x26\x99\xb8\x86\x03\xe9\x55\xcf\x54\x09\xc1\x9c\xe0\x66\
+\xc6\x5d\x42\xec\x77\x42\x30\x03\xa0\x7c\x0d\x67\x44\x1c\xde\xb3\
+\xb2\x34\x08\xd6\x9b\x7d\xfa\xc9\xba\x83\x25\xff\xe7\x9f\xbd\x57\
+\xec\xe3\x36\xcc\xa9\x53\x6d\xa9\x0f\x6c\x99\x8a\x25\x7b\x52\x62\
+\xa5\x42\xda\xb4\x03\x87\xd2\xe5\xa1\xec\x56\x28\x02\x88\x73\x65\
+\xbc\x0e\x13\x4d\xeb\xa7\x3c\x20\xd7\x80\x1b\x08\x13\x7f\xc0\xe1\
+\x57\xa0\x55\x96\xd0\x84\x0d\x80\x32\x27\x81\x84\xab\xda\x7e\xac\
+\x4c\x83\x1e\xb5\x4d\x57\xab\x6b\x9c\x96\xf5\x0d\xa2\x98\xac\x02\
+\x94\x66\x29\xbe\x51\xc8\x34\x1c\x44\xc3\x6f\xb7\xb2\xd0\x61\xb4\
+\x37\xb6\xb0\xca\x34\x41\xdf\xbe\x21\x82\x6e\x13\x1b\x88\xc1\x20\
+\xc5\x36\x1c\x52\x1c\x1a\xce\x44\x3f\x14\x24\x64\x0d\xc4\xb0\x09\
+\xd3\xa8\xf2\xfe\x07\x26\x25\x07\x76\x2a\x9a\x65\x87\x2d\xc9\x51\
+\x92\x6d\x57\x1e\xe5\xa4\xce\xdc\x66\xad\x67\xf4\x2f\xcf\xc6\x6a\
+\xb0\x29\xde\xa6\x57\x62\xe2\xa3\x59\x41\x73\x34\xe7\x96\xda\x82\
+\x42\x53\x43\x2b\x02\xd0\xf4\xe6\x20\xd3\xcf\x76\x04\x35\x0f\xc1\
+\x43\x9c\x17\xa5\x28\x54\x64\xba\xfb\x10\x68\x5a\x4d\x89\x12\x8b\
+\xa5\xc6\x88\xdc\x07\xa9\xca\x69\xb6\x32\xdb\x97\x54\x73\x91\xcb\
+\x38\x79\xcc\xe3\x88\x0c\xb4\x39\x4e\xaa\xb9\x9b\xec\xc9\x89\x30\
+\x84\x32\xda\x5c\x75\x44\xb6\x5f\x6d\xd4\x96\xd2\x37\x3a\x42\xfd\
+\x5a\x52\x04\xb2\xea\xbd\xda\x2a\x85\x86\x93\xaf\x25\x81\x94\xe2\
+\x97\xcb\x44\x1d\xac\x9b\x0d\x62\xd4\xa2\x9f\x2d\xdd\x26\x36\xa0\
+\x9e\x8c\xaa\x79\x90\x1c\xdc\x43\x12\xc3\x4e\x10\xe4\xb4\x25\x49\
+\x52\x5c\x40\xa2\x50\x86\xeb\x0d\x49\x9f\xca\x8c\xa6\x39\xb2\x9d\
+\x40\xba\x30\xb9\x94\x48\xfc\xb0\xde\xe7\x44\x82\xef\xb2\x64\xbf\
+\x4d\x69\x19\x6a\xc2\xac\x6a\x54\x63\xf5\x6f\xd9\x93\x75\xa9\xac\
+\x4e\x80\x5d\xe3\x98\x15\x87\x0d\xbe\xeb\x61\xb5\xa9\xa6\xd6\x92\
+\x47\x79\x24\xbd\xe2\xd4\x09\x93\x2a\x4f\x8d\x36\x79\x46\x23\x4f\
+\x4c\x9d\x84\xc2\x66\x32\x53\xf7\x3e\xc6\x86\x36\x45\xcf\x02\xbf\
+\xde\x44\xaa\xe4\xa4\xdd\x0e\x2c\xfc\xa5\x6d\xab\xc3\xab\xf7\x14\
+\x43\x66\x67\x36\xbc\x3f\xd0\x25\x8a\x17\xe9\x2f\x4a\x23\xdc\x22\
+\x16\xfa\x30\x37\xd1\x85\x30\x51\x45\x2e\x01\x98\xe8\xde\x89\xd3\
+\x08\x5c\x6f\x99\x69\x12\xd2\x26\x3b\xb3\x8b\x2a\xe1\xb6\xa4\x00\
+\x9c\x22\x36\xcf\xa8\x75\xf4\x4e\x02\x17\x04\xcb\xef\xa8\x79\x2a\
+\xed\xe5\x77\x1b\xbc\xfe\xc4\xde\xfe\x06\x92\xc9\x3a\xb4\x4d\xcf\
+\xff\xc4\x4e\x60\x1b\x12\xcb\x62\x53\x75\x54\xda\x5f\x9d\x90\xac\
+\x52\x96\x5b\x6d\x91\xf2\xa8\x64\x8d\x9a\x1c\x7b\xd6\xd8\x43\xd5\
+\xa6\xe7\x43\x90\xbf\x94\x28\x94\xaa\xc4\x58\x7b\x18\xa8\xb5\x25\
+\x58\x06\x50\xd9\xab\x18\x38\x94\xa7\xcd\xac\xca\x10\x06\x9e\x15\
+\xaf\xd5\x64\x5e\x99\x36\x48\x61\x78\x97\xea\xd9\x46\xa8\xb9\xa4\
+\x9c\xbf\x1a\x7c\xe4\xa7\x55\x72\xc5\x8b\x59\xce\x68\x4d\xe8\xb0\
+\x1e\x51\x3d\x6b\x92\x7f\x3d\x6b\x12\xbf\x34\x6b\x92\x3e\x9f\x6e\
+\xa1\x98\x8c\xf7\xea\x5a\x7c\xde\xc3\xfb\xba\x65\x61\xe4\x13\xde\
+\x61\xf0\x92\x50\x3e\x40\xb6\x67\xe1\x56\x87\x31\xf1\xac\xc3\x98\
+\x38\x6f\xc0\x98\xf8\x57\x80\x4e\x20\x85\x4d\x98\x3c\x38\x0d\x51\
+\x58\x0c\xab\x55\xf8\xf3\x57\xfd\xb1\xae\xe3\x7c\x9d\x74\xc9\x9e\
+\x63\xeb\xf2\x07\x06\xb0\x16\xad\xeb\xb2\x7e\x13\x58\x8b\x1e\xea\
+\xde\xa0\xbf\xe2\x55\xf7\x02\x86\x68\x60\x97\x2c\xac\xc0\x9d\x3a\
+\xd9\x25\x17\x3b\x70\xa7\x96\x1e\x22\x23\x49\x2d\x4d\x82\x6a\xd7\
+\xcf\x43\x10\x32\x8d\x34\xe0\xaa\x4f\x85\xef\x46\xee\xf6\x39\x4f\
+\x3c\xe6\xad\xb2\x24\xaa\x1f\xe6\x29\x65\xff\x9b\x39\x79\x98\x07\
+\xc3\xff\x79\x78\x28\x70\x29\xaa\x29\x32\xab\x75\x5d\x0f\x4d\x33\
+\xf5\xe6\x23\xaf\x95\xde\x78\x80\x58\x56\xa7\x0f\x54\x2e\x84\xaf\
+\xb7\x67\x65\xbe\xc7\xd5\x83\x3f\xa5\x8d\x40\xe9\xad\x9e\x5f\x76\
+\xb1\xdb\x88\xe4\x7c\x55\x10\x94\xe1\x6a\x2c\xab\x72\x19\x97\x55\
+\xd3\xa8\xe3\x41\x97\xb5\x07\x4f\x9b\x55\xb6\x16\xfc\x09\x24\xda\
+\x78\x24\xe6\x6b\x2b\x79\x2f\x9f\x66\xce\x56\xa0\x8e\x3a\xad\xd9\
+\x22\x86\xfc\x5e\x4d\x03\x03\xf4\x99\xf4\x3d\xe0\x58\xf8\xfd\xac\
+\xd7\x14\x80\xfc\x7c\x9d\x92\x04\x7c\x8c\xbe\xc1\x6f\x77\x5c\x0f\
+\x7b\x01\x42\x80\xe6\x1b\xfc\x9e\xd6\xc3\x05\x3b\x53\x03\x2d\x3a\
+\xcc\xd4\x90\x73\x72\x82\x85\x4c\x2d\x05\x5c\x7d\x81\xaf\xa1\x00\
+\xb2\x83\xd0\x34\xe1\x54\x4f\xf9\x4c\x45\xe4\xe8\xfd\x5d\xfc\x07\
+\xfe\x29\x8f\x77\xaa\xe5\xd7\x0d\x68\xae\x18\xbe\x9e\xbb\xfa\xa2\
+\xa1\x02\xee\xec\x77\x7a\x07\x2e\x08\x76\x61\x4a\xf4\xf6\x59\x19\
+\x04\xe6\x9c\x15\x7d\x1a\xc0\xc6\xeb\x27\x03\x9f\x77\x79\xb6\xc3\
+\x79\xf9\xcd\x89\xf2\xf0\xe9\x36\x2c\x58\x3f\xab\x02\xa3\x6b\x15\
+\xc3\xb3\x3e\xc7\x18\xda\x4d\xb5\x5f\x6e\xf2\xeb\x96\x8b\x20\x21\
+\x80\x63\x1f\xab\x23\xfc\xc1\x90\x92\xa3\x8b\x9e\x4d\xa3\x72\x15\
+\x5d\x24\xcf\xbc\xb5\xdc\x7a\xd1\x10\x1c\xd2\x7d\x69\x3e\x5f\x6d\
+\xf6\xed\xb8\x57\xa4\xb6\x69\xa9\x25\x35\x22\x55\x1a\xa4\xa7\x5e\
+\x33\xc3\xb3\xf2\x96\xc7\xa5\x4d\x0f\xd1\xbb\x57\xd3\x61\xea\x2e\
+\xb3\x74\x67\xaa\x9a\xba\xcb\x2c\xdd\x6a\xea\x0a\x7d\x3d\x4d\xfd\
+\xb9\x45\x19\x8c\x8f\x32\xbb\x84\x64\x3f\x47\x83\x90\x4c\x12\x1d\
+\x28\x24\xcf\x28\x23\xf7\xe5\x44\x54\xa9\x79\xa3\x97\xf1\x32\xa7\
+\x7a\x88\x03\x37\x9e\xea\x51\x54\x0f\x13\xf3\x09\x68\x26\xa0\x87\
+\x75\x44\x4d\xda\xd6\xd2\xef\xb7\xf6\x5d\x0c\x12\x3c\x86\x20\xc9\
+\x50\x8e\xa5\x86\xc8\xc6\x1c\x49\xbb\x6d\xcc\xcc\x98\x79\xb7\x0e\
+\x07\xd8\x72\x62\x7d\x02\x7d\x4f\x6f\xda\xe6\xcd\xb5\x63\x39\x0a\
+\xab\xed\x7c\x34\x94\x24\x1a\x69\x01\x8e\xb5\x54\xd5\x00\x4a\x35\
+\xbd\x11\x3e\xc5\xe3\x39\x53\xf8\xa4\x21\xd7\x14\x3f\x59\xcc\x3d\
+\x38\x7c\xb6\xea\xdd\x50\x81\xd3\x74\x5b\x21\x82\x46\x67\x4b\x6c\
+\x68\xdc\x8c\xb2\x4b\x5f\x09\xe0\x47\x07\x50\x67\xda\x9a\x2b\xbf\
+\x60\x74\x90\x75\x41\x61\xcd\x22\xa2\x26\xdf\x76\x19\x35\xc4\x79\
+\x8c\x88\xcc\xd5\xc4\xcb\x87\xcf\x5a\xcd\x87\x46\xa2\x03\x0f\xf5\
+\x04\xb1\xc8\x60\x81\x2f\x2a\xe6\x13\x90\x4c\xc5\x7c\x4c\xb8\xb2\
+\x67\xd4\x3a\xff\x3d\x02\x16\x13\xe0\x31\xe4\xb4\x17\x01\xc3\xa8\
+\xa1\xb2\x31\x87\x8a\x4e\x73\x34\x32\x66\xde\xab\xcb\xfb\xb5\x9d\
+\xd8\x51\x91\xac\x77\x31\xa4\x1e\xcb\x51\x38\xad\xe7\x43\x0b\xf3\
+\x32\x2c\xf7\xd2\x65\xc0\x13\x17\xbc\x7f\x91\x4a\x64\xf6\x1d\x5c\
+\x29\xeb\xb4\xdc\xc7\xbb\x93\x48\xb2\xcb\x05\x74\xdf\x73\xcc\x76\
+\xe1\x3a\x2e\xbf\x81\x9f\x73\x5d\x46\xdf\x6d\x98\x24\x59\x96\xd6\
+\x24\x76\x7d\x89\xad\xf7\xc5\x9b\xff\x27\xaf\xc0\xd9\xe4\x12\xfd\
+\x42\xbe\x16\x4d\x1a\x39\xa4\x09\x44\x10\x92\x8b\x32\xe4\x5e\x0a\
+\x33\xaa\x73\x32\xaf\xb4\x85\x5e\x46\xd1\xfb\x75\x1b\x86\xf6\x17\
+\x45\x79\x6a\x56\xe3\x93\x36\x1d\x08\x00\xff\xba\x8c\x2e\xb8\x76\
+\x27\x34\x40\x22\x36\x67\x2b\xe3\x6a\x34\xe5\x78\xdf\xab\x4a\xd2\
+\xd4\xbb\x53\x2d\xad\x8f\xe3\x8e\xaa\xd2\x35\x72\x63\x7d\x4e\xf5\
+\x8d\x5f\xb4\x32\x10\x4c\xeb\x2c\x7a\x71\x6b\x6c\x05\xe1\x75\x86\
+\xf5\x7a\x9f\xde\x7a\x64\xa3\xe6\x50\x61\xc4\x9f\x84\x3d\xd0\x13\
+\x20\xe3\x25\x34\x1d\x3d\x1f\x56\xf1\x1b\xed\xca\xd2\x82\xe9\x15\
+\x00\xda\x39\x3a\x5d\xaf\xc1\xf6\x5d\xd6\xfa\x32\xcf\x39\x41\x4e\
+\xdf\xb1\xce\xb2\x72\x99\x47\x9f\xb4\x13\x64\xbf\x9c\xa5\xef\x61\
+\xbe\xac\x65\x85\x6a\xb9\xf7\xa2\xf5\xdc\xc1\x29\xde\xc5\x11\x6e\
+\x73\x8a\x64\xfe\x3b\x38\xc5\x5e\x05\xe4\xe0\x67\x2e\xb3\xef\x56\
+\x47\x36\x7c\x62\x2d\xb7\xc3\x7c\x62\xff\x54\x56\x46\xd5\x74\x89\
+\x94\x68\xdd\x23\x8a\x46\xc6\x4c\x77\x56\xda\x56\x2c\xab\xd5\xbc\
+\x95\x0e\xc3\xcc\xdf\x76\x9b\x58\x77\x16\x74\xd0\xe2\xaa\x8c\xd8\
+\x55\x5f\x65\x46\xde\x74\x55\x82\x43\xf3\xf7\xe3\x5a\x9c\x95\x8e\
+\xc0\xfc\x05\x7a\xdb\xa9\xf5\xbf\x9f\xac\x67\xd9\xc4\x14\x41\x91\
+\xd7\x9b\x86\x21\x8a\x8b\xc4\xe7\x6c\xde\xfa\x7d\x96\x79\xd7\x37\
+\x64\xd4\x8b\xf8\x0c\xe7\xef\x79\xb8\xdb\x61\xf2\xb7\x4e\x4a\xf2\
+\x27\x49\x0a\x05\xb3\xe4\x91\x38\x1c\xf3\x34\x86\xcb\x97\x26\x80\
+\xae\x6f\xfe\xf4\x74\x86\x86\x9d\x2d\x0e\xb1\x0d\xb2\xb7\x53\x94\
+\xbe\x72\x2c\x36\xbc\xe3\xc2\x61\x33\x2f\xf0\x5d\x6c\xf9\xbb\x1a\
+\x66\xa4\xd2\xa9\xf7\xbc\xb6\x4e\xac\x9a\xfe\xdd\x05\x7d\x43\x3a\
+\xf8\xe2\x97\x65\x39\x6d\xe7\xd7\xd7\xd7\xd6\x43\x3f\x46\x5e\x76\
+\xd6\x4e\xfa\x94\xba\xf9\x77\x36\x26\xff\x03\xb1\x1b\xda\x8b\
\x00\x00\x01\x0a\
\x3c\
\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
@@ -429,13 +429,13 @@
\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf5\
\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\xe9\
-\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x79\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x87\
-\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x83\
-\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x69\
-\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3b\
-\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x21\
-\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf3\
+\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x7d\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x8b\
+\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x87\
+\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x6d\
+\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3f\
+\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x25\
+\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf7\
"
qt_resource_struct_v2 = b"\
@@ -446,25 +446,25 @@
\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x8d\xcd\x0a\x44\x0d\
+\x00\x00\x01\x90\x35\x20\x19\x0c\
\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf5\
-\x00\x00\x01\x8d\xcd\x0a\x44\x0d\
+\x00\x00\x01\x90\x35\x20\x19\x0c\
\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\xe9\
-\x00\x00\x01\x8d\xda\xd5\x9c\x81\
-\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x79\
-\x00\x00\x01\x8d\xcd\x0a\x44\x0d\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x87\
-\x00\x00\x01\x80\xe6\x9c\x3e\xe9\
-\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x83\
-\x00\x00\x01\x80\xbe\xdc\x4e\x35\
-\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x69\
-\x00\x00\x01\x80\xe6\x9b\xde\xfc\
-\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3b\
-\x00\x00\x01\x80\xe6\x9b\xed\x87\
-\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x21\
-\x00\x00\x01\x80\xbe\xdc\x4e\x35\
-\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf3\
-\x00\x00\x01\x80\xbe\xdc\x4e\x35\
+\x00\x00\x01\x90\x40\x40\x2f\x92\
+\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x7d\
+\x00\x00\x01\x90\x35\x20\x19\x0c\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x8b\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x87\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x6d\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3f\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x25\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
+\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf7\
+\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
diff --git a/rare/ui/components/tabs/settings/rare.py b/rare/ui/components/tabs/settings/rare.py
index 427ab175e..9c1a08753 100644
--- a/rare/ui/components/tabs/settings/rare.py
+++ b/rare/ui/components/tabs/settings/rare.py
@@ -146,7 +146,7 @@ def retranslateUi(self, RareSettings):
self.save_size.setText(_translate("RareSettings", "Restore window size on application startup"))
self.notification.setText(_translate("RareSettings", "Show notifications when downloads complete"))
self.log_games.setText(_translate("RareSettings", "Show console window when launching games"))
- self.sys_tray.setText(_translate("RareSettings", "Exit to system tray"))
+ self.sys_tray.setText(_translate("RareSettings", "Close to system tray"))
self.auto_update.setText(_translate("RareSettings", "Queue game updates on application startup"))
self.confirm_start.setText(_translate("RareSettings", "Confirm before launching games"))
self.auto_sync_cloud.setText(_translate("RareSettings", "Automatically upload/download cloud saves"))
From f964079f6e6e22d57e686c3b7d3f081db63d7d12 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 21:52:35 +0300
Subject: [PATCH 20/43] CollapsilbeBase: match class arguments
---
rare/widgets/collapsible_widget.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rare/widgets/collapsible_widget.py b/rare/widgets/collapsible_widget.py
index 60d8d49af..0f99709e6 100644
--- a/rare/widgets/collapsible_widget.py
+++ b/rare/widgets/collapsible_widget.py
@@ -24,7 +24,7 @@ class CollapsibleBase(object):
# Adapted from python version
https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt
"""
- def __init__(self):
+ def __init__(self, parent=None):
self.animation_duration = None
self.toggle_animation = None
self.content_area = None
From 65d6a6fd42815859f0fb785fd92fd64feec1cd3e Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 22:02:27 +0300
Subject: [PATCH 21/43] EGLSyncListItem: don't set parent
---
.../tabs/games/integrations/egl_sync_group.py | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/rare/components/tabs/games/integrations/egl_sync_group.py b/rare/components/tabs/games/integrations/egl_sync_group.py
index 71ac5a37d..d7366c638 100644
--- a/rare/components/tabs/games/integrations/egl_sync_group.py
+++ b/rare/components/tabs/games/integrations/egl_sync_group.py
@@ -188,9 +188,9 @@ def update_lists(self):
class EGLSyncListItem(QListWidgetItem):
- def __init__(self, game: Union[EGLManifest,InstalledGame], parent=None):
- super(EGLSyncListItem, self).__init__(parent=parent)
- self.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
+ def __init__(self, game: Union[EGLManifest, InstalledGame]):
+ super(EGLSyncListItem, self).__init__()
+ self.setFlags(Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable)
self.setCheckState(Qt.CheckState.Unchecked)
self.core = RareCore.instance().core()
self.game = game
@@ -214,8 +214,8 @@ def app_title(self) -> str:
class EGLSyncExportItem(EGLSyncListItem):
- def __init__(self, game: InstalledGame, parent=None):
- super(EGLSyncExportItem, self).__init__(game=game, parent=parent)
+ def __init__(self, game: InstalledGame):
+ super(EGLSyncExportItem, self).__init__(game=game)
def action(self) -> Union[str,bool]:
error = False
@@ -231,8 +231,8 @@ def app_title(self) -> str:
class EGLSyncImportItem(EGLSyncListItem):
- def __init__(self, game: EGLManifest, parent=None):
- super(EGLSyncImportItem, self).__init__(game=game, parent=parent)
+ def __init__(self, game: EGLManifest):
+ super(EGLSyncImportItem, self).__init__(game=game)
def action(self) -> Union[str,bool]:
error = False
@@ -317,9 +317,9 @@ def populate(self, enabled: bool):
self.ui.list.clear()
for item in self.core.egl_get_exportable():
try:
- i = EGLSyncExportItem(item, self.ui.list)
- except AttributeError:
- logger.error(f"{item.app_name} does not work. Ignoring")
+ i = EGLSyncExportItem(item)
+ except AttributeError as e:
+ logger.error("%s(%s) constructor failed with %s", type(self).__name__, item.app_name, e)
else:
self.ui.list.addItem(i)
super(EGLSyncExportGroup, self).populate(enabled)
@@ -356,9 +356,9 @@ def populate(self, enabled: bool):
self.ui.list.clear()
for item in self.core.egl_get_importable():
try:
- i = EGLSyncImportItem(item, self.ui.list)
- except AttributeError:
- logger.error(f"{item.app_name} does not work. Ignoring")
+ i = EGLSyncImportItem(item)
+ except AttributeError as e:
+ logger.error("%s(%s) constructor failed with %s", type(self).__name__, item.app_name, e)
else:
self.ui.list.addItem(i)
super(EGLSyncImportGroup, self).populate(enabled)
From 62f21633c1f5686ad064cb48e3f791f40e67b8eb Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 22:43:53 +0300
Subject: [PATCH 22/43] Diesel: return empty tuples instead of none for
iterable fields
---
.../tabs/store/api/models/diesel.py | 110 ++++++++----------
1 file changed, 46 insertions(+), 64 deletions(-)
diff --git a/rare/components/tabs/store/api/models/diesel.py b/rare/components/tabs/store/api/models/diesel.py
index 20a4f07a3..bf71e420b 100644
--- a/rare/components/tabs/store/api/models/diesel.py
+++ b/rare/components/tabs/store/api/models/diesel.py
@@ -1,6 +1,6 @@
import logging
from dataclasses import dataclass, field
-from typing import List, Dict, Any, Type, Optional
+from typing import List, Dict, Any, Type, Optional, Tuple
logger = logging.getLogger("DieselModels")
@@ -10,104 +10,92 @@
@dataclass
class DieselSystemDetailItem:
- _type: Optional[str] = None
- minimum: Optional[str] = None
- recommended: Optional[str] = None
- title: Optional[str] = None
+ _type: str = None
+ minimum: str = None
+ recommended: str = None
+ title: str = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetailItem"], src: Dict[str, Any]) -> "DieselSystemDetailItem":
d = src.copy()
- tmp = cls(
+ return cls(
_type=d.pop("_type", ""),
minimum=d.pop("minimum", ""),
recommended=d.pop("recommended", ""),
title=d.pop("title", ""),
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
@dataclass
class DieselSystemDetail:
- _type: Optional[str] = None
- details: Optional[List[DieselSystemDetailItem]] = None
- systemType: Optional[str] = None
+ _type: str = None
+ details: Tuple[DieselSystemDetailItem, ...] = None
+ systemType: str = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetail"], src: Dict[str, Any]) -> "DieselSystemDetail":
d = src.copy()
- _details = d.pop("details", [])
- details = [] if _details else None
- for item in _details:
- detail = DieselSystemDetailItem.from_dict(item)
- details.append(detail)
- tmp = cls(
+ details = tuple(map(DieselSystemDetailItem.from_dict, d.pop("details", [])))
+ return cls(
_type=d.pop("_type", ""),
details=details,
systemType=d.pop("systemType", ""),
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
@dataclass
class DieselSystemDetails:
- _type: Optional[str] = None
- languages: Optional[List[str]] = None
- rating: Optional[Dict] = None
- systems: Optional[List[DieselSystemDetail]] = None
+ _type: str = None
+ languages: List[str] = None
+ rating: Dict = None
+ systems: Tuple[DieselSystemDetail, ...] = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselSystemDetails"], src: Dict[str, Any]) -> "DieselSystemDetails":
d = src.copy()
- _systems = d.pop("systems", [])
- systems = [] if _systems else None
- for item in _systems:
- system = DieselSystemDetail.from_dict(item)
- systems.append(system)
- tmp = cls(
+ systems = tuple(map(DieselSystemDetail.from_dict, d.pop("systems", [])))
+ return cls(
_type=d.pop("_type", ""),
languages=d.pop("languages", []),
rating=d.pop("rating", {}),
systems=systems,
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
@dataclass
class DieselProductAbout:
- _type: Optional[str] = None
- desciption: Optional[str] = None
- developerAttribution: Optional[str] = None
- publisherAttribution: Optional[str] = None
- shortDescription: Optional[str] = None
+ _type: str = None
+ desciption: str = None
+ developerAttribution: str = None
+ publisherAttribution: str = None
+ shortDescription: str = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselProductAbout"], src: Dict[str, Any]) -> "DieselProductAbout":
d = src.copy()
- tmp = cls(
+ return cls(
_type=d.pop("_type", ""),
desciption=d.pop("description", ""),
developerAttribution=d.pop("developerAttribution", ""),
publisherAttribution=d.pop("publisherAttribution", ""),
shortDescription=d.pop("shortDescription", ""),
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
@dataclass
class DieselProductDetail:
- _type: Optional[str] = None
- about: Optional[DieselProductAbout] = None
- requirements: Optional[DieselSystemDetails] = None
- socialLinks: Optional[DieselSocialLinks] = None
+ _type: str = None
+ about: DieselProductAbout = None
+ requirements: DieselSystemDetails = None
+ socialLinks: DieselSocialLinks = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
@@ -115,40 +103,35 @@ def from_dict(cls: Type["DieselProductDetail"], src: Dict[str, Any]) -> "DieselP
d = src.copy()
about = DieselProductAbout.from_dict(x) if (x := d.pop("about"), {}) else None
requirements = DieselSystemDetails.from_dict(x) if (x := d.pop("requirements", {})) else None
- tmp = cls(
+ return cls(
_type=d.pop("_type", ""),
about=about,
requirements=requirements,
socialLinks=d.pop("socialLinks", {}),
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
@dataclass
class DieselProduct:
- _id: Optional[str] = None
- _images_: Optional[List[str]] = None
- _locale: Optional[str] = None
- _slug: Optional[str] = None
- _title: Optional[str] = None
- _urlPattern: Optional[str] = None
- namespace: Optional[str] = None
- pages: Optional[List["DieselProduct"]] = None
- data: Optional[DieselProductDetail] = None
- productName: Optional[str] = None
+ _id: str = None
+ _images_: List[str] = None
+ _locale: str = None
+ _slug: str = None
+ _title: str = None
+ _urlPattern: str = None
+ namespace: str = None
+ pages: Tuple["DieselProduct", ...] = None
+ data: DieselProductDetail = None
+ productName: str = None
unmapped: Dict[str, Any] = field(default_factory=dict)
@classmethod
def from_dict(cls: Type["DieselProduct"], src: Dict[str, Any]) -> "DieselProduct":
d = src.copy()
- _pages = d.pop("pages", [])
- pages = [] if _pages else None
- for item in _pages:
- page = DieselProduct.from_dict(item)
- pages.append(page)
+ pages = tuple(map(DieselProduct.from_dict, d.pop("pages", [])))
data = DieselProductDetail.from_dict(x) if (x := d.pop("data", {})) else None
- tmp = cls(
+ return cls(
_id=d.pop("_id", ""),
_images_=d.pop("_images_", []),
_locale=d.pop("_locale", ""),
@@ -159,6 +142,5 @@ def from_dict(cls: Type["DieselProduct"], src: Dict[str, Any]) -> "DieselProduct
pages=pages,
data=data,
productName=d.pop("productName", ""),
+ unmapped=d
)
- tmp.unmapped = d
- return tmp
From fa376b88766d71a76df848b30d67ae471b3e45ab Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 22:47:09 +0300
Subject: [PATCH 23/43] QtRequests: explicitly check the error code in
QNetworkReply
---
rare/components/tabs/store/store_api.py | 10 +++++-----
rare/utils/qt_requests.py | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/rare/components/tabs/store/store_api.py b/rare/components/tabs/store/store_api.py
index cd0c15a82..1ac665137 100644
--- a/rare/components/tabs/store/store_api.py
+++ b/rare/components/tabs/store/store_api.py
@@ -1,5 +1,5 @@
from logging import getLogger
-from typing import List, Callable, Tuple
+from typing import Callable, Tuple
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QApplication
@@ -97,13 +97,13 @@ def __handle_wishlist(data, handle_func):
except KeyError as e:
if DEBUG():
raise e
- logger.exception("Free games API request failed")
+ logger.error("Free games API request failed")
handle_func(["error", "Key error"])
return
except Exception as e:
if DEBUG():
raise e
- logger.exception(f"Free games API request failed")
+ logger.error(f"Free games API request failed")
handle_func(["error", e])
return
@@ -133,14 +133,14 @@ def __handle_search(data, handler):
response = ResponseModel.from_dict(data)
handler(response.data.catalog.searchStore.elements)
except KeyError as e:
- logger.error(str(e))
if DEBUG():
raise e
+ logger.error(str(e))
handler([])
except Exception as e:
- logger.error(f"Search Api request failed: {e}")
if DEBUG():
raise e
+ logger.error(f"Search Api request failed: {e}")
handler([])
return
diff --git a/rare/utils/qt_requests.py b/rare/utils/qt_requests.py
index 9f1c36420..268cde310 100644
--- a/rare/utils/qt_requests.py
+++ b/rare/utils/qt_requests.py
@@ -107,7 +107,7 @@ def __on_finished(self, reply: QNetworkReply):
self.log.error("QNetworkReply: %s without associated item", reply.url().toString())
reply.deleteLater()
return
- if reply.error():
+ if reply.error() != QNetworkReply.NetworkError.NoError:
self.log.error(reply.errorString())
else:
mimetype, charset = self.__parse_content_type(reply.header(QNetworkRequest.KnownHeaders.ContentTypeHeader))
From ea9b9b49f325c6c4aa7458b6545564b0123ad9d0 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sat, 22 Jun 2024 23:50:55 +0300
Subject: [PATCH 24/43] MoveDialog: work around crash due to accessing widget
from thread
This should be properly solved in the future by refactoring MoveDialog
---
rare/components/dialogs/move_dialog.py | 6 +++---
rare/components/tabs/games/game_info/details.py | 14 +++++++-------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/rare/components/dialogs/move_dialog.py b/rare/components/dialogs/move_dialog.py
index 26cc08ece..ce0452537 100644
--- a/rare/components/dialogs/move_dialog.py
+++ b/rare/components/dialogs/move_dialog.py
@@ -106,7 +106,6 @@ def refresh_indicator(self):
def path_edit_callback(self, path: str) -> Tuple[bool, str, int]:
self.accept_button.setEnabled(True)
- self.warn_label.setHidden(False)
self.req_space.setText("...")
self.avail_space.setText("...")
@@ -177,10 +176,11 @@ def __update_widget(self):
self.path_edit.setText(self.rgame.install_path)
# FIXME: Make edit_func lighter instead of blocking signals
# self.path_edit.line_edit.blockSignals(False)
- self.setActive(False)
self.warn_label.setText(
- self.tr("Moving here will overwrite {}").format(os.path.basename(self.rgame.install_path))
+ self.warn_label.tr("Moving here will overwrite {}").format(os.path.basename(self.rgame.install_path))
)
+ self.warn_label.setHidden(False)
+ self.setActive(False)
self.refresh_indicator()
def update_game(self, rgame: RareGame):
diff --git a/rare/components/tabs/games/game_info/details.py b/rare/components/tabs/games/game_info/details.py
index cf61153ed..42490edcc 100644
--- a/rare/components/tabs/games/game_info/details.py
+++ b/rare/components/tabs/games/game_info/details.py
@@ -131,7 +131,7 @@ def repair_game(self, rgame: RareGame):
"There is an update for {} from {} to {}. "
"Do you want to update the game while repairing it?"
).format(rgame.app_title, rgame.version, rgame.remote_version),
- ) == QMessageBox.Yes
+ ) == QMessageBox.StandardButton.Yes
rgame.repair(repair_and_update=ans)
@pyqtSlot(RareGame, str)
@@ -200,10 +200,10 @@ def __on_verify_result(self, rgame: RareGame, success, failed, missing):
"{} failed verification, {} file(s) corrupted, {} file(s) are missing. "
"Do you want to repair them?"
).format(rgame.app_title, failed, missing),
- QMessageBox.Yes | QMessageBox.No,
- QMessageBox.Yes,
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.Yes,
)
- if ans == QMessageBox.Yes:
+ if ans == QMessageBox.StandardButton.Yes:
self.repair_game(rgame)
@pyqtSlot()
@@ -232,11 +232,11 @@ def move_game(self, rgame: RareGame, model: MoveGameModel):
"Destination {} already exists. "
"Are you sure you want to overwrite it?"
).format(new_install_path),
- QMessageBox.Yes | QMessageBox.No,
- QMessageBox.Yes,
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.Yes,
)
- if ans == QMessageBox.Yes:
+ if ans == QMessageBox.StandardButton.Yes:
if os.path.isdir(new_install_path):
shutil.rmtree(new_install_path)
else:
From 8c433f570636ec9fdbbc91b5cff5dd80c642f8a9 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Sun, 23 Jun 2024 14:21:42 +0300
Subject: [PATCH 25/43] GameWidget: work-around crash in `eventFilter`
For an unknown reason presently, the eventFilter is called with
a QRunnable as the second argument instead of a QEvent. This causes
a crash because a QRunnable doesn't have a `type` attribute. The target
object seems to be the launch button.
Work-around it by filtering out the event early if the second argument
is not a QEevent instance and log an error.
---
rare/components/tabs/games/game_widgets/game_widget.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/rare/components/tabs/games/game_widgets/game_widget.py b/rare/components/tabs/games/game_widgets/game_widget.py
index ae8435fbc..f69ee5c58 100644
--- a/rare/components/tabs/games/game_widgets/game_widget.py
+++ b/rare/components/tabs/games/game_widgets/game_widget.py
@@ -200,6 +200,10 @@ def update_actions(self):
self.addAction(self.uninstall_action)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
+ if not isinstance(a1, QEvent):
+ # FIXME: investigate why this happens
+ logger.error("Supplied arg1 %s with target %s is not a QEvent object", type(a1), type(a0))
+ return True
if a0 is self.ui.launch_btn:
if a1.type() == QEvent.Type.Enter:
if not self.rgame.can_launch:
From 837d4740b41ff797609d82a0593d8fc00093be63 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Sun, 23 Jun 2024 14:16:19 +0300
Subject: [PATCH 26/43] UninstallOptionsModel: fix values order
---
rare/models/install.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/rare/models/install.py b/rare/models/install.py
index e17e7939b..496a08db6 100644
--- a/rare/models/install.py
+++ b/rare/models/install.py
@@ -91,7 +91,7 @@ class UninstallOptionsModel:
@property
def __values(self) -> Tuple[bool, bool, bool, bool, bool]:
- return self.accepted, self.keep_config, self.keep_folder, self.keep_files, self.keep_overlay_keys
+ return self.accepted, self.keep_files, self.keep_folder, self.keep_config, self.keep_overlay_keys
@__values.setter
def __values(self, values: Tuple[bool, bool, bool, bool, bool]):
@@ -103,8 +103,8 @@ def __bool__(self):
def __iter__(self):
return iter(self.__values)
- def set_accepted(self, keep_config, keep_folder, keep_files, keep_overlay_keys):
- self.__values = True, keep_config, keep_folder, keep_files, keep_overlay_keys
+ def set_accepted(self, keep_files, keep_folder, keep_config, keep_overlay_keys):
+ self.__values = True, keep_files, keep_folder, keep_config, keep_overlay_keys
def set_rejected(self):
self.__values = False, None, None, None, None
From 8ac78ac9c46b7f58572a6131fbec5dddb321f4b5 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Mon, 24 Jun 2024 12:43:58 +0300
Subject: [PATCH 27/43] GameWidget: accept left click so it won't propagate
---
rare/components/tabs/games/game_widgets/game_widget.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/rare/components/tabs/games/game_widgets/game_widget.py b/rare/components/tabs/games/game_widgets/game_widget.py
index f69ee5c58..07be1712b 100644
--- a/rare/components/tabs/games/game_widgets/game_widget.py
+++ b/rare/components/tabs/games/game_widgets/game_widget.py
@@ -236,6 +236,7 @@ def mousePressEvent(self, e: QMouseEvent) -> None:
# left button
if e.button() == Qt.MouseButton.LeftButton:
self.show_info.emit(self.rgame)
+ e.accept()
# right
elif e.button() == Qt.MouseButton.RightButton:
super(GameWidget, self).mousePressEvent(e)
From 7efe324ada125b97b8d7324bb517662fa27bf82e Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Mon, 24 Jun 2024 12:50:21 +0300
Subject: [PATCH 28/43] MovePathEditReasons: Use prefix to for enumeration
member for clarity
---
rare/components/dialogs/move_dialog.py | 50 +++++++++++++-------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/rare/components/dialogs/move_dialog.py b/rare/components/dialogs/move_dialog.py
index ce0452537..5dd7e54a5 100644
--- a/rare/components/dialogs/move_dialog.py
+++ b/rare/components/dialogs/move_dialog.py
@@ -19,12 +19,12 @@
class MovePathEditReasons(IndicatorReasons):
- DST_MISSING = auto()
- NO_WRITE_PERM = auto()
- SAME_DIR = auto()
- DST_IN_SRC = auto()
- NESTED_DIR = auto()
- NO_SPACE = auto()
+ MOVEDIALOG_DST_MISSING = auto()
+ MOVEDIALOG_NO_WRITE_PERM = auto()
+ MOVEDIALOG_SAME_DIR = auto()
+ MOVEDIALOG_DST_IN_SRC = auto()
+ MOVEDIALOG_NESTED_DIR = auto()
+ MOVEDIALOG_NO_SPACE = auto()
class MoveDialog(ActionDialog):
@@ -42,12 +42,12 @@ def __init__(self, rgame: RareGame, parent=None):
self.path_edit = PathEdit("", QFileDialog.FileMode.Directory, edit_func=self.path_edit_callback)
self.path_edit.extend_reasons({
- MovePathEditReasons.DST_MISSING: self.tr("You need to provide the destination directory."),
- MovePathEditReasons.NO_WRITE_PERM: self.tr("No write permission on destination."),
- MovePathEditReasons.SAME_DIR: self.tr("Same directory or subdirectory selected."),
- MovePathEditReasons.DST_IN_SRC: self.tr("Destination is inside source directory"),
- MovePathEditReasons.NESTED_DIR: self.tr("Game install directories cannot be nested."),
- MovePathEditReasons.NO_SPACE: self.tr("Not enough space available on drive."),
+ MovePathEditReasons.MOVEDIALOG_DST_MISSING: self.tr("You need to provide the destination directory."),
+ MovePathEditReasons.MOVEDIALOG_NO_WRITE_PERM: self.tr("No write permission on destination."),
+ MovePathEditReasons.MOVEDIALOG_SAME_DIR: self.tr("Same directory or subdirectory selected."),
+ MovePathEditReasons.MOVEDIALOG_DST_IN_SRC: self.tr("Destination is inside source directory"),
+ MovePathEditReasons.MOVEDIALOG_NESTED_DIR: self.tr("Game install directories cannot be nested."),
+ MovePathEditReasons.MOVEDIALOG_NO_SPACE: self.tr("Not enough space available on drive."),
})
self.warn_label = ElideLabel("", parent=self)
@@ -105,16 +105,17 @@ def refresh_indicator(self):
self.path_edit.setText(text)
def path_edit_callback(self, path: str) -> Tuple[bool, str, int]:
- self.accept_button.setEnabled(True)
+ self.setActive(True)
self.req_space.setText("...")
self.avail_space.setText("...")
def helper_func(reason: int) -> Tuple[bool, str, int]:
+ self.setActive(False)
self.accept_button.setEnabled(False)
return False, path, reason
if not self.rgame.install_path or not path:
- return helper_func(MovePathEditReasons.DST_MISSING)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_DST_MISSING)
src_path = os.path.realpath(self.rgame.install_path)
dst_path = os.path.realpath(path)
@@ -132,20 +133,20 @@ def helper_func(reason: int) -> Tuple[bool, str, int]:
self.avail_space.setText(format_size(free_space))
if not os.access(path, os.W_OK) or not os.access(self.rgame.install_path, os.W_OK):
- return helper_func(MovePathEditReasons.NO_WRITE_PERM)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_NO_WRITE_PERM)
if src_path in {dst_path, dst_install_path}:
- return helper_func(MovePathEditReasons.SAME_DIR)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_SAME_DIR)
if str(src_path) in str(dst_path):
- return helper_func(MovePathEditReasons.DST_IN_SRC)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_DST_IN_SRC)
if str(dst_install_path) in str(src_path):
- return helper_func(MovePathEditReasons.DST_IN_SRC)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_DST_IN_SRC)
for rgame in self.rcore.installed_games:
if not rgame.is_non_asset and rgame.install_path in path:
- return helper_func(MovePathEditReasons.NESTED_DIR)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_NESTED_DIR)
is_existing_dir = is_game_dir(src_path, dst_install_path)
@@ -158,9 +159,10 @@ def helper_func(reason: int) -> Tuple[bool, str, int]:
self.warn_label.setHidden(False)
if free_space <= source_size and not is_existing_dir:
- return helper_func(MovePathEditReasons.NO_SPACE)
+ return helper_func(MovePathEditReasons.MOVEDIALOG_NO_SPACE)
# Fallback
+ self.setActive(False)
self.accept_button.setEnabled(True)
return True, path, IndicatorReasonsCommon.VALID
@@ -173,15 +175,15 @@ def __update_widget(self):
# FIXME: Make edit_func lighter instead of blocking signals
# self.path_edit.line_edit.blockSignals(True)
self.setActive(True)
- self.path_edit.setText(self.rgame.install_path)
- # FIXME: Make edit_func lighter instead of blocking signals
- # self.path_edit.line_edit.blockSignals(False)
self.warn_label.setText(
self.warn_label.tr("Moving here will overwrite {}").format(os.path.basename(self.rgame.install_path))
)
self.warn_label.setHidden(False)
+ self.path_edit.setText(self.rgame.install_path)
+ # FIXME: Make edit_func lighter instead of blocking signals
+ # self.path_edit.line_edit.blockSignals(False)
self.setActive(False)
- self.refresh_indicator()
+ # self.refresh_indicator()
def update_game(self, rgame: RareGame):
self.rgame = rgame
From 4efde54abb92faff603cb0a821bdcff799df3664 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Mon, 24 Jun 2024 15:58:45 +0300
Subject: [PATCH 29/43] SideTabBar: fix stylesheet painting in PySide6
---
rare/widgets/side_tab.py | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/rare/widgets/side_tab.py b/rare/widgets/side_tab.py
index ce73d5c98..c7e9aa28a 100644
--- a/rare/widgets/side_tab.py
+++ b/rare/widgets/side_tab.py
@@ -33,6 +33,8 @@ def __init__(self, padding: int = -1, parent=None):
self.padding = padding
self.fm = QFontMetrics(self.font())
+ # NOTE: if we ever implement a QProxyStyle, this is likely to conflict
+
def tabSizeHint(self, index):
width = QTabBar.tabSizeHint(self, index).height()
if self.padding < 0:
@@ -47,19 +49,9 @@ def paintEvent(self, event):
for i in range(self.count()):
self.initStyleOption(opt, i)
- painter.drawControl(QStyle.ControlElement.CE_TabBarTabShape, opt)
painter.save()
-
- s = opt.rect.size()
- s.transpose()
- r = QRect(QPoint(), s)
- r.moveCenter(opt.rect.center())
- opt.rect = r
-
- c = self.tabRect(i).center()
- painter.translate(c)
- painter.rotate(90)
- painter.translate(-c)
+ painter.drawControl(QStyle.ControlElement.CE_TabBarTabShape, opt)
+ opt.shape = QTabBar.Shape.RoundedNorth
painter.drawControl(QStyle.ControlElement.CE_TabBarTabLabel, opt)
painter.restore()
From 202045d128b7b84b1a6c1114e117dc7f6b35ea46 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Mon, 24 Jun 2024 18:40:00 +0300
Subject: [PATCH 30/43] Project: update misc scripts
---
freeze.py | 4 ++--
misc/generate_version_name.py | 8 ++++++--
misc/nuitka_build.sh | 2 ++
misc/py2ts.sh | 6 ++----
misc/qrc2py.sh | 15 ++++++++++-----
misc/ts2qm.py | 1 +
misc/ui2py.sh | 2 +-
pyproject.toml | 32 ++++++++++++++++++--------------
setup.py | 14 ++++++++------
9 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/freeze.py b/freeze.py
index 99c1b49a2..e5e970364 100644
--- a/freeze.py
+++ b/freeze.py
@@ -3,8 +3,8 @@
from rare import __version__
name = 'Rare'
-author = 'Dummerle'
-description = 'A GUI for Legendary'
+author = 'RareDevs'
+description = 'A gui for legendary'
shortcut_table = [
("DesktopShortcut", # Shortcut
diff --git a/misc/generate_version_name.py b/misc/generate_version_name.py
index 1c29b6cb2..fdedebd33 100644
--- a/misc/generate_version_name.py
+++ b/misc/generate_version_name.py
@@ -5,5 +5,9 @@
core = LegendaryCore()
core.login()
-print(" ".join(map(lambda game: game.app_name,
- random.choices(list(filter(lambda x: len(x.app_name) != 32, core.get_game_list(False))), k=2))))
+print(" ".join(
+ map(
+ lambda game: game.app_name,
+ random.choices(list(filter(lambda x: len(x.app_name) != 32, core.get_game_list(False))), k=2)
+ )
+))
diff --git a/misc/nuitka_build.sh b/misc/nuitka_build.sh
index f20d79cf6..09b2c95ae 100755
--- a/misc/nuitka_build.sh
+++ b/misc/nuitka_build.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/bash
+
python -m nuitka \
--assume-yes-for-downloads \
--mingw64 \
diff --git a/misc/py2ts.sh b/misc/py2ts.sh
index 6b1e330a8..1315177b9 100755
--- a/misc/py2ts.sh
+++ b/misc/py2ts.sh
@@ -1,11 +1,9 @@
-#!/bin/sh
+#!/usr/bin/env bash
cwd="$(pwd)"
cd "$(dirname "$0")"/.. || exit
-#py_files=$(find rare -iname "*.py" -not -path rare/ui)
-#ui_files=$(find rare/ui -iname "*.ui")
-
+# shellcheck disable=SC2046
pylupdate5 -noobsolete $(find rare/ -iname "*.py") -ts rare/resources/languages/source.ts
cd "$cwd" || exit
diff --git a/misc/qrc2py.sh b/misc/qrc2py.sh
index 04a740828..4f79182ee 100755
--- a/misc/qrc2py.sh
+++ b/misc/qrc2py.sh
@@ -1,7 +1,8 @@
-#!/bin/bash
+#!/usr/bin/env bash
+_rcc_cmd="pyrcc5 -compress 6 -threshold 0"
cwd="$(pwd)"
-cd "$(dirname "$0")"/../ || exit
+cd "$(dirname "${0}")"/../ || exit
resources=(
"rare/resources/images/"
@@ -10,6 +11,10 @@ resources=(
)
resources_changed=0
+if [[ "$1" == "--force" ]]
+then
+ resources_changed=1
+fi
for r in "${resources[@]}"
do
@@ -22,7 +27,7 @@ done
if [[ $resources_changed -eq 1 ]]
then
echo "Re-compiling main resources"
- pyrcc5 -compress 6 \
+ $_rcc_cmd \
rare/resources/resources.qrc \
-o rare/resources/resources.py
fi
@@ -30,7 +35,7 @@ fi
if [[ $(git diff --name-only HEAD "rare/resources/stylesheets/RareStyle/") ]]
then
echo "Re-compiling RareStyle stylesheet resources"
- pyrcc5 -compress 6 \
+ $_rcc_cmd \
rare/resources/stylesheets/RareStyle/stylesheet.qrc \
-o rare/resources/stylesheets/RareStyle/__init__.py
fi
@@ -39,7 +44,7 @@ fi
if [[ $(git diff --name-only HEAD "rare/resources/stylesheets/ChildOfMetropolis/") ]]
then
echo "Re-compiling ChildOfMetropolis stylesheet resources"
- pyrcc5 -compress 6 \
+ $_rcc_cmd \
rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qrc \
-o rare/resources/stylesheets/ChildOfMetropolis/__init__.py
fi
diff --git a/misc/ts2qm.py b/misc/ts2qm.py
index 9575495e9..797d46d26 100644
--- a/misc/ts2qm.py
+++ b/misc/ts2qm.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
import os
for f in os.listdir(os.path.join(os.path.dirname(__file__), "../rare/resources/languages/")):
diff --git a/misc/ui2py.sh b/misc/ui2py.sh
index b89f1215e..33e18451d 100755
--- a/misc/ui2py.sh
+++ b/misc/ui2py.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
if [ -n "${1}" ]; then
if [ ! -f "${1}" ]; then
diff --git a/pyproject.toml b/pyproject.toml
index 39fb9b892..5f7d3c6ed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.black]
line-length = 120
-target-version = ['py39', 'py310', 'py311']
+target-version = ['py39', 'py310', 'py311', 'py312']
include = '\.py$'
force-exclude = '''
/(
@@ -13,27 +13,27 @@ force-exclude = '''
[tool.poetry]
name = "rare"
version = "1.10.11"
-description = "A GUI for Legendary"
-authors = ["Dummerle"]
+description = "A gui for legendary"
+authors = ["RareDevs"]
license = "GPL3"
readme = "README.md"
repository = "https://github.com/RareDevs/Rare"
[tool.poetry.dependencies]
python = "^3.9"
-PyQt5 = "^5.15.7"
requests = "^2.28.1"
+PyQt5 = "^5.15.7"
QtAwesome = "^1.1.1"
-pypresence = { version = "^4.2.1", optional = true }
-pywin32 = { version = "^304", markers = "platform_system == 'Windows'" }
+legendary-gl = "^0.20.34"
pywebview = [
{ version = "^3.6.3", extras = ["cef"], platform = "windows", optional = true },
{ version = "^3.6.3", extras = ["gtk"], platform = "linux", optional = true },
{ version = "^3.6.3", extras = ["gtk"], platform = "freebsd", optional = true },
]
-legendary-gl = "^0.20.34"
orjson = "^3.8.0"
vdf = "^4.3"
+pywin32 = { version = "^304", markers = "platform_system == 'Windows'" }
+pypresence = { version = "^4.2.1", optional = true }
[tool.poetry.scripts]
start = "rare.main:main"
@@ -50,22 +50,26 @@ PyQt5-stubs = "^5.15.6.0"
[nuitka]
assume-yes-for-downloads = true
-follow-imports = true
prefer-source-code = true
mingw64 = true
-lto = true
+lto = false
+jobs = 4
static-libpython = false
standalone = true
show-scons = false
enable-plugin = ["anti-bloat", "pyqt5"]
show-anti-bloat-changes = true
-nofollow-import-to = ["*.tests", "*.distutils"]
+follow-stdlib = true
+follow-imports = true
+nofollow-import-to = ["*.tests", "*.distutils", "distutils", "unittest", "pydoc", "tkinter", "test"]
+prefer-source-code = true
+include-package = "pypresence"
include-package-data = "qtawesome"
-include-data-dir = "rare/resources/images=rare/resources/images"
-include-data-files = "rare/resources/languages=rare/resources/laguanges=*.qm"
+include-data-dir = "rare/resources/images/=rare/resources/images/"
+include-data-files = "rare/resources/languages/=rare/resources/laguanges/=rare_*.qm"
windows-icon-from-ico = "rare/resources/images/Rare.ico"
windows-company-name = "Rare"
windows-product-name = "Rare"
-windows-file-version = "1.9.0"
-windows-product-version = "1.9.0"
+windows-file-version = "1.10.11.0"
+windows-product-version = "1.10.11.0"
windows-disable-console = true
diff --git a/setup.py b/setup.py
index bad9d7fa6..97646a5fc 100644
--- a/setup.py
+++ b/setup.py
@@ -7,12 +7,13 @@
requirements = [
"requests<3.0",
- "legendary-gl>=0.20.34",
- "orjson",
- "setuptools",
- "wheel",
"PyQt5",
"QtAwesome",
+ "wheel",
+ "setuptools",
+ "legendary-gl>=0.20.34",
+ "orjson",
+ "vdf"
'pywin32; platform_system == "Windows"',
]
@@ -28,9 +29,9 @@
setuptools.setup(
name="Rare",
version=version,
- author="Dummerle",
+ author="RareDevs",
license="GPL-3",
- description="A gui for Legendary",
+ description="A gui for legendary",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/Dummerle/Rare",
@@ -40,6 +41,7 @@
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
"Operating System :: OS Independent"
],
From 2ba2c2555aef3072e40f00dcda9a42eb18a045dd Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Mon, 24 Jun 2024 18:55:58 +0300
Subject: [PATCH 31/43] AppImage: add vdf dependency
---
AppImageBuilder.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml
index cef9f3db8..75e2182a9 100644
--- a/AppImageBuilder.yml
+++ b/AppImageBuilder.yml
@@ -12,7 +12,7 @@ script:
# copy Logo
- cp AppDir/usr/src/rare/resources/images/Rare.png AppDir/usr/share/icons/hicolor/256x256/apps/
# Install application dependencies
- - python3 -m pip install --ignore-installed --prefix=/usr --root=AppDir pypresence qtawesome legendary-gl orjson
+ - python3 -m pip install --ignore-installed --prefix=/usr --root=AppDir pypresence qtawesome legendary-gl orjson vdf
AppDir:
path: AppDir
From cdedee5aaa3a82b0c03225168fa7e4aa51569005 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Tue, 25 Jun 2024 09:21:10 +0300
Subject: [PATCH 32/43] GameProcess: re-word warning dialog message
---
rare/commands/launcher/__init__.py | 2 +-
rare/shared/game_process.py | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/rare/commands/launcher/__init__.py b/rare/commands/launcher/__init__.py
index fe30bbe4f..ab83b6451 100644
--- a/rare/commands/launcher/__init__.py
+++ b/rare/commands/launcher/__init__.py
@@ -313,7 +313,7 @@ def launch_game(self, args: LaunchArgs):
if self.rgame.app_name in DETACHED_APP_NAMES and platform.system() == "Windows":
if self.console:
- self.console.log(f"Launching as a detached process")
+ self.console.log("Launching as a detached process")
subprocess.Popen([args.executable] + args.arguments, cwd=args.working_directory,
env={i: args.environment.value(i) for i in args.environment.keys()})
self.stop() # stop because we do not attach to the output
diff --git a/rare/shared/game_process.py b/rare/shared/game_process.py
index 8cbfbb525..af5200395 100644
--- a/rare/shared/game_process.py
+++ b/rare/shared/game_process.py
@@ -68,9 +68,9 @@ def __connect(self):
None,
self.tr("Error - {}").format(self.game.app_title),
self.tr(
- "Connection to game launcher for {} failed due to timeout.\n"
- "This is usually do it the game or Rare's game launcher already running"
- ).format(self.game.app_name)
+ "Connection to game launcher failed for {}.\n"
+ "This normally means that the game is already running."
+ ).format(self.game.app_title)
)
self.timer.stop()
self.tried_connections = 0
From 6221cedee8306cdf92ff530501b72a9546b12313 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Tue, 25 Jun 2024 09:24:06 +0300
Subject: [PATCH 33/43] project: fix pyproject
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 5f7d3c6ed..d896a37bf 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -50,7 +50,6 @@ PyQt5-stubs = "^5.15.6.0"
[nuitka]
assume-yes-for-downloads = true
-prefer-source-code = true
mingw64 = true
lto = false
jobs = 4
From c393af31010c36e2416124c3d7f536b6e4037d41 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 26 Jun 2024 13:06:31 +0300
Subject: [PATCH 34/43] stylesheets: remove minimum size based on font metrics
---
.../ChildOfMetropolis/stylesheet.qss | 24 ++-----------------
.../stylesheets/RareStyle/stylesheet.qss | 23 +-----------------
2 files changed, 3 insertions(+), 44 deletions(-)
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
index 8e3b63f80..0be8478e3 100644
--- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
+++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
@@ -96,27 +96,6 @@ QScrollBar {
selection-background-color: #71DA7E;
}
-QLineEdit,
-QTextEdit,
-QTimeEdit,
-QDateEdit,
-QDateTimeEdit,
-QComboBox,
-QSpinBox,
-QDoubleSpinBox,
-QProgressBar,
-QScrollArea,
-QPushButton {
- min-height: 3.00ex;
- /* min-height: 1.30em; */
- /* min-height: 18px; */
-}
-QToolButton {
- min-height: 3.00ex;
- /* min-height: 1.10em; */
- /* min-height: 15px; */
-}
-
QFrame[frameShape="0"] {
border-width: 0px;
}
@@ -322,7 +301,7 @@ QToolButton {
border-width: 1px;
border-style: solid;
border-radius: 2px;
- padding: 2px;
+ padding: 3px;
padding-left: 6px;
padding-right: 6px;
}
@@ -693,6 +672,7 @@ QTabBar#MainTabBar::tab:top:selected {
border-color: #5CD3FF;
border-bottom-color: #C2C4C5;
}
+
QPushButton#TabButtonWidget,
QToolButton#TabButtonWidget {
border-color: rgb( 51, 54, 59);
diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss
index 80a898dba..d026c8207 100644
--- a/rare/resources/stylesheets/RareStyle/stylesheet.qss
+++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss
@@ -96,27 +96,6 @@ QScrollBar {
selection-background-color: rgb( 39, 66, 66);
}
-QLineEdit,
-QTextEdit,
-QTimeEdit,
-QDateEdit,
-QDateTimeEdit,
-QComboBox,
-QSpinBox,
-QDoubleSpinBox,
-QProgressBar,
-QScrollArea,
-QPushButton {
- min-height: 3.00ex;
- /* min-height: 1.30em; */
- /* min-height: 18px; */
-}
-QToolButton {
- min-height: 3.00ex;
- /* min-height: 1.10em; */
- /* min-height: 15px; */
-}
-
QFrame[frameShape="0"] {
border-width: 0px;
}
@@ -322,7 +301,7 @@ QToolButton {
border-width: 1px;
border-style: solid;
border-radius: 2px;
- padding: 2px;
+ padding: 3px;
padding-left: 6px;
padding-right: 6px;
}
From f405833149821602be986b728b96acaf57ab691b Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 26 Jun 2024 13:31:11 +0300
Subject: [PATCH 35/43] MainTabBar: fix button after removing size restriction
from stylesheet
---
rare/components/tabs/tab_widgets.py | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/rare/components/tabs/tab_widgets.py b/rare/components/tabs/tab_widgets.py
index 4c0bc5076..844cdd157 100644
--- a/rare/components/tabs/tab_widgets.py
+++ b/rare/components/tabs/tab_widgets.py
@@ -24,7 +24,7 @@ def tabSizeHint(self, index):
size.setWidth(max(size.width(), size.width() + offset))
return size
- def __center_button(self):
+ def __align_button(self):
self.button.move(QPoint(
self.tabRect(self.expanded).right() - self.button.width() - self.style().PixelMetric.PM_DefaultFrameWidth,
self.tabRect(self.expanded).bottom() - self.button.height()
@@ -32,24 +32,27 @@ def __center_button(self):
def resizeEvent(self, e: QResizeEvent):
super().resizeEvent(e)
- self.__center_button()
+ self.__align_button()
def event(self, e):
if e.type() == QEvent.Type.StyleChange:
- self.__center_button()
+ self.button.setFixedHeight(self.button.minimumSizeHint().height())
+ self.button.setFixedWidth(self.button.minimumSizeHint().width())
+ self.__align_button()
return super().event(e)
def setButton(self, widget: QPushButton):
widget.setParent(self)
- widget.setFixedHeight(self.style().PixelMetric.PM_TabBarTabVSpace)
+ widget.setFixedHeight(widget.minimumSizeHint().height())
widget.setFixedWidth(widget.minimumSizeHint().width())
self.button = widget
class TabButtonWidget(QPushButton):
- def __init__(self, icon: QIcon, tooltip: str = "", parent=None):
+ def __init__(self, icon: QIcon, text: str = "", tooltip: str = "", parent=None):
super(TabButtonWidget, self).__init__(parent=parent)
self.setObjectName(type(self).__name__)
self.setIcon(icon)
+ self.setText(text)
self.setToolTip(tooltip)
self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
From 559f3ecadf472823a89dd5aa22268d627333aca1 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 26 Jun 2024 15:36:50 +0300
Subject: [PATCH 36/43] RareLauncher: reformat file
---
rare/commands/launcher/__init__.py | 36 +++++++++++++-----------------
1 file changed, 15 insertions(+), 21 deletions(-)
diff --git a/rare/commands/launcher/__init__.py b/rare/commands/launcher/__init__.py
index ab83b6451..4960353ca 100644
--- a/rare/commands/launcher/__init__.py
+++ b/rare/commands/launcher/__init__.py
@@ -110,7 +110,7 @@ def run(self) -> None:
class RareLauncherException(RareAppException):
- def __init__(self, app: 'RareLauncher', args: Namespace, parent=None):
+ def __init__(self, app: "RareLauncher", args: Namespace, parent=None):
super(RareLauncherException, self).__init__(parent=parent)
self.__app = app
self.__args = args
@@ -153,9 +153,8 @@ def __init__(self, args: InitArgs):
language = self.settings.value(*options.language)
self.load_translator(language)
- if (
- QSettings(self).value(*options.log_games)
- or (game.app_name in DETACHED_APP_NAMES and platform.system() == "Windows")
+ if QSettings(self).value(*options.log_games) or (
+ game.app_name in DETACHED_APP_NAMES and platform.system() == "Windows"
):
self.console = ConsoleDialog(game.app_title)
self.console.show()
@@ -271,15 +270,12 @@ def on_exit(self, exit_code: int):
if self.console:
self.console.on_process_exit(self.core.get_game(self.rgame.app_name).app_title, exit_code)
- self.send_message(
- FinishedModel(
- action=Actions.finished,
- app_name=self.rgame.app_name,
- exit_code=exit_code,
- playtime=int(time.time() - self.start_time)
- )
-
- )
+ self.send_message(FinishedModel(
+ action=Actions.finished,
+ app_name=self.rgame.app_name,
+ exit_code=exit_code,
+ playtime=int(time.time() - self.start_time),
+ ))
self.stop()
@pyqtSlot(object)
@@ -323,12 +319,10 @@ def launch_game(self, args: LaunchArgs):
self.game_process.setWorkingDirectory(args.working_directory)
self.game_process.setProcessEnvironment(args.environment)
# send start message after process started
- self.game_process.started.connect(lambda: self.send_message(
- StateChangedModel(
- action=Actions.state_update, app_name=self.rgame.app_name,
- new_state=StateChangedModel.States.started
- )
- ))
+ self.game_process.started.connect(lambda: self.send_message(StateChangedModel(
+ action=Actions.state_update, app_name=self.rgame.app_name,
+ new_state=StateChangedModel.States.started
+ )))
# self.logger.debug("Executing prelaunch command %s, %s", args.executable, args.arguments)
self.game_process.start(args.executable, args.arguments)
@@ -338,8 +332,8 @@ def error_occurred(self, error_str: str):
self.console.on_process_exit(self.core.get_game(self.rgame.app_name).app_title, error_str)
self.send_message(ErrorModel(
error_string=error_str, app_name=self.rgame.app_name,
- action=Actions.error)
- )
+ action=Actions.error
+ ))
self.stop()
def start_prepare(self, sync_action=None):
From 2b95ba5f9b8eb1d4f0904a2f476e8857c1449055 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 26 Jun 2024 16:38:49 +0300
Subject: [PATCH 37/43] stylesheets: update resources
---
.../stylesheets/ChildOfMetropolis/__init__.py | 935 +++++++++---------
.../stylesheets/RareStyle/__init__.py | 935 +++++++++---------
2 files changed, 901 insertions(+), 969 deletions(-)
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
index be09c944b..62dd69484 100644
--- a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
+++ b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
@@ -1,485 +1,450 @@
-# -*- coding: utf-8 -*-
-
-# Resource object code
-#
-# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
-#
-# WARNING! All changes made in this file will be lost!
-
-from PyQt5 import QtCore
-
-qt_resource_data = b"\
-\x00\x00\x00\xf4\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x36\x34\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x34\x31\x20\x32\x33\x36\x2e\x34\x37\x35\x68\
-\x32\x33\x38\x63\x32\x31\x2e\x34\x20\x30\x20\x33\x32\x2e\x31\x20\
-\x32\x35\x2e\x39\x20\x31\x37\x20\x34\x31\x6c\x2d\x31\x31\x39\x20\
-\x31\x31\x39\x63\x2d\x39\x2e\x34\x20\x39\x2e\x34\x2d\x32\x34\x2e\
-\x36\x20\x39\x2e\x34\x2d\x33\x33\x2e\x39\x20\x30\x6c\x2d\x31\x31\
-\x39\x2e\x31\x2d\x31\x31\x39\x63\x2d\x31\x35\x2e\x31\x2d\x31\x35\
-\x2e\x31\x2d\x34\x2e\x34\x2d\x34\x31\x20\x31\x37\x2d\x34\x31\x7a\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\
-\x3d\x22\x23\x45\x37\x42\x44\x35\x34\x22\x2f\x3e\x0a\x3c\x2f\x73\
-\x76\x67\x3e\
-\x00\x00\x00\xf3\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x33\x32\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x34\x31\x20\x37\x36\x2e\x34\x37\x35\x68\x32\
-\x33\x38\x63\x32\x31\x2e\x34\x20\x30\x20\x33\x32\x2e\x31\x20\x32\
-\x35\x2e\x39\x20\x31\x37\x20\x34\x31\x6c\x2d\x31\x31\x39\x20\x31\
-\x31\x39\x63\x2d\x39\x2e\x34\x20\x39\x2e\x34\x2d\x32\x34\x2e\x36\
-\x20\x39\x2e\x34\x2d\x33\x33\x2e\x39\x20\x30\x6c\x2d\x31\x31\x39\
-\x2e\x31\x2d\x31\x31\x39\x63\x2d\x31\x35\x2e\x31\x2d\x31\x35\x2e\
-\x31\x2d\x34\x2e\x34\x2d\x34\x31\x20\x31\x37\x2d\x34\x31\x7a\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\
-\x22\x23\x45\x37\x42\x44\x35\x34\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\
-\x67\x3e\
-\x00\x00\x0c\x79\
-\x00\
-\x00\x45\x3a\x78\x9c\xcd\x1c\xdb\x6e\xdb\x38\xf6\xdd\x5f\xc1\x8d\
-\x51\xa0\xc9\xda\xf5\x45\x72\xec\x28\xe8\x43\x1c\x37\x33\x0b\x4c\
-\x31\xd3\x49\xb0\xf3\x50\xf4\x41\xb6\x18\x5b\xa8\x2c\xb9\x92\xdc\
-\xb4\x33\xc8\xbf\xef\x21\x29\x4a\x24\x45\x52\x96\xe3\x16\xeb\xa2\
-\x89\x4d\x1e\xf2\x5c\x78\xee\xa2\x33\xb8\xe8\x7c\x7c\xc0\xdf\xf2\
-\x4f\x9d\x38\x49\xb7\x7e\xe4\x21\x78\x75\x31\x7d\xa1\xae\x73\xe9\
-\x5c\x39\x77\x64\x08\xf5\xfb\x68\xeb\x87\x31\x7a\x4c\xe2\x1c\xad\
-\x92\x28\x49\x3b\x41\x98\xf9\xcb\x08\x07\xb0\xa6\xeb\x3a\xee\xd4\
-\x0d\x50\x77\x7a\x39\x9d\x4e\x67\x7c\x05\x87\x10\x57\xa1\xda\x2b\
-\x5d\x2f\xfd\xd7\xe8\x72\xda\x43\x68\x3a\x22\x3f\xe0\xdd\x64\xf2\
-\xea\x1c\xbd\x7d\x8b\xba\x8b\x9b\xc5\x62\xf1\xee\xc0\x55\x63\xbe\
-\xea\x66\x76\x73\x73\x33\xef\x7c\x9c\xfb\xab\xcf\xeb\x34\xd9\xc7\
-\x81\xcc\xe0\x78\x38\x1e\x8f\x27\xa8\x7b\x3b\xbe\x75\x6f\x27\x12\
-\x83\xcb\x72\x49\x41\x30\x0e\xc2\x9c\x70\x41\xd8\x74\xe0\xe5\xba\
-\x9c\x2a\xbe\x4e\x5d\x02\xec\xa6\x28\xc5\xfe\x2a\x0f\xbf\xe2\x01\
-\x5f\x8f\x9e\xc2\x60\x8d\xf3\x0c\xbd\x26\x02\x7f\x07\xa3\x59\x0f\
-\xfd\x91\x26\xeb\x14\x67\xd9\xdc\x4f\x33\x84\xf3\xd5\x79\x67\x93\
-\x7c\xc5\x29\xa5\x12\xc8\x84\x97\xe3\xa0\xee\x7c\xbc\x70\x2c\xe8\
-\x9e\x36\x38\x46\x74\x5d\x18\xaf\x11\xf9\x5d\x62\xaf\x90\xce\xf7\
-\x79\x9e\xc4\x80\xf2\x57\xec\x07\x38\xcd\xce\x3b\x19\x8e\x30\x00\
-\x25\xb1\x07\x98\x1e\x5d\xf8\x07\xe7\x37\x5a\xdc\x4c\xed\x8c\xb1\
-\x65\x22\x47\x1d\x3f\xca\x71\x1a\xfb\x39\x26\x3b\xcd\xc6\xfe\x18\
-\x74\x67\x7e\x3b\x7f\x37\xbf\xb3\xee\xc4\x97\x11\xaa\xd3\xe4\x29\
-\x43\x20\xfe\xdf\xc2\x2c\x1f\x3c\xa4\x18\x0f\x1e\x08\x8a\xff\x86\
-\x18\xc6\xfd\x38\xa0\x0b\xee\x57\x69\x12\x45\x44\x56\x1d\x38\xdb\
-\x24\x05\x3e\xe4\x73\x75\x67\x4e\x30\x5b\xa2\xee\xe4\x76\xe1\xdc\
-\x55\xc8\x29\xa4\x80\x78\x9b\x64\x79\x49\xbc\x49\xb5\xa6\x63\xd0\
-\xaa\x4b\x50\xad\x91\x73\x25\xa8\x16\x3b\x0b\x49\x2b\x0c\xc2\x53\
-\xb1\xb6\x55\x84\x70\xbd\x89\xe0\x7f\x0e\x42\x9d\x8c\xdd\x4b\x7f\
-\xd8\xc8\x57\x90\x26\xbb\x20\x79\x8a\x39\x86\x1e\xf2\xd1\x32\xcc\
-\x11\xdd\x06\x20\xf3\x8d\x1f\xf3\x55\x4c\x0e\x29\x86\xf3\xdc\xf9\
-\xa9\x4f\xf4\xe0\x00\x8b\x16\x16\x97\xc6\xad\xd3\x02\x67\xe5\x3c\
-\xba\x23\x30\x44\x67\x01\x96\x68\x24\x78\x9d\xfa\x41\x88\xc1\x37\
-\x54\xfa\x91\xa1\xa4\xa4\x1f\x08\xff\x8c\x11\x28\x02\x53\x81\x3f\
-\x92\xdd\x7e\x47\x8e\xfe\x7e\x87\x57\xa1\x1f\x7d\xea\x84\x71\x96\
-\xfb\x51\xd4\x17\x74\x00\x75\x87\x53\x90\xd4\xdd\xd5\xcd\x94\x4a\
-\x0a\xd0\x16\x50\x25\xb4\x60\x62\x00\x3d\x01\xe8\xf9\x7c\xba\x98\
-\x1b\xa0\x05\xa1\x00\xf4\x18\xa0\xa7\x8b\x89\x33\x1b\xca\xd0\xfb\
-\xb8\x4e\x4b\x77\x3a\x24\x94\xdc\xcd\x87\xb3\x09\x83\x2e\xa1\x04\
-\xf8\x8a\x9a\xee\x84\xc0\xcf\xef\x66\xee\xa5\x6b\x86\xaf\xe8\x01\
-\x37\x06\xf0\xb3\xe1\x64\xe6\x3a\x2a\xfc\xc5\xa0\xd3\xe9\x5c\xa0\
-\x7f\xa8\x7a\x53\x81\x7b\xdc\x9f\x5f\xd3\x31\x76\x16\x7d\x3e\xc5\
-\x34\xab\x98\x2a\x0f\xa3\x9c\x66\x8e\xf2\xba\xf3\xdc\xb9\xf0\x38\
-\x01\x3d\x78\x5f\x9a\x41\xa9\x0d\x32\x46\xa6\x3d\x5a\x8c\xd2\x94\
-\x0d\x63\xe7\xc3\x6f\xfe\x12\x47\xbd\xe2\xb7\x8a\xaa\xd8\x16\x54\
-\x26\xdf\x78\x68\xb8\xfb\x66\xda\x32\x4f\xfd\x38\x03\x5d\x07\x7d\
-\x63\x20\x3b\x3f\x08\xc0\xf7\x08\x8b\x4a\x97\xd8\xd7\x50\xc4\xcc\
-\x9b\x51\xf4\x1e\xc7\x7b\x42\x10\x78\x2b\xe2\xa2\x84\xb7\x9e\x17\
-\xe6\x78\x0b\x03\xc4\x89\x15\x73\xfc\x6d\x35\xc7\x7d\x9b\xf8\xbe\
-\x9c\x65\x1e\x9a\x0d\x65\x8c\x1e\x11\x0e\xb1\xb7\xb7\x49\x1a\xe3\
-\x94\xb9\x75\x11\xee\x2e\xf5\xb7\xf8\xe3\x23\xf9\x79\xbf\xf1\x77\
-\xf8\xed\xd9\xe5\xd9\x27\x18\xff\x05\xb8\xd9\xcd\x93\x6f\x94\xd6\
-\x18\x13\xbf\x43\x76\x2d\x5c\x10\x79\x1b\x6e\xf9\xe8\x02\xac\x58\
-\x78\x2b\xcc\x3c\x24\x49\xc4\x36\xb9\x4d\xb6\xcb\x44\x7e\x5b\xaa\
-\x83\x30\x86\x3e\xdc\x2c\x33\x10\xfd\x2a\xff\x0f\x70\x57\xf0\x7c\
-\xbf\x0b\x63\xb6\x74\x91\xec\x01\xbe\xfa\x2c\xf8\x41\x02\xc7\x1d\
-\xbe\xf6\xac\x47\xe5\x59\xb3\xe1\x2c\xff\x4e\x1c\x72\x96\x44\x61\
-\x20\x4d\x10\x2f\xb3\xcf\x3c\x34\xe6\x0b\xca\x93\xa7\x23\xe4\x40\
-\x5f\x26\xf3\x17\x08\xf4\x67\xcb\x4e\xd5\x66\x83\xf9\xb1\x0c\xa7\
-\xa5\x55\x9c\x40\x0c\xad\x19\xbc\x81\x54\x87\x4c\xed\xb3\x0d\x3b\
-\x97\x82\xdd\x6d\x18\xf7\x37\x98\xc5\x4f\xe7\xcd\x70\x88\x8b\xa3\
-\x1f\x5c\x48\x53\xa3\x37\xce\x10\x6f\xaf\x11\xf8\x4b\xdd\xec\x0c\
-\xf4\x83\xcc\x3d\x17\x9a\x7f\x14\x86\x91\x0d\xc3\xa4\xc4\xa0\x33\
-\xdd\xe1\xd9\x27\xb3\x9b\x7b\x36\x18\xbb\xbc\x82\x2b\xbf\x5b\x2c\
-\x29\x95\xeb\x9f\xa6\xb3\x17\x80\x6b\x4e\xb7\xbe\x8a\xe5\xdc\xf2\
-\xaa\x7f\x95\xf1\x81\x46\x39\xf3\x62\x96\x55\xb1\xf8\x42\xdd\xa0\
-\xc7\x94\x8e\x44\x19\x8b\x39\x14\x1b\x1e\xa8\xa0\xb0\x35\xc9\x90\
-\xfa\x24\x45\xea\x49\x9f\x04\xe3\x83\xe1\xfd\xae\xbf\xa4\x07\xcd\
-\x80\x60\xbe\xf8\xcc\xd1\xed\x97\x2b\x28\x68\x40\xfb\xfa\x49\x1a\
-\xae\x43\x48\xa0\x99\xac\xaf\x4f\xea\xa4\x8a\xf1\x1c\x68\x8c\xf0\
-\x63\x5e\x02\x0c\x15\x80\x65\x02\xb4\x6d\x35\x30\x32\xc7\x52\xdc\
-\xd6\xb0\x2e\xcf\x97\x32\x50\x96\x55\xc2\x30\xc4\xe1\xc3\xc2\xbb\
-\x14\x8b\x65\x3a\xeb\x42\xde\x25\x59\xc8\xea\x14\x90\x05\x4a\x89\
-\xe1\x34\xe7\x30\x6c\x8a\x0a\x45\x99\x27\x26\xc8\x33\x69\x9e\x19\
-\x53\x03\x3c\x5e\x23\xda\xf9\x56\x96\x14\x1f\xa8\x91\x05\x06\xae\
-\x4d\x2e\x3f\xfc\x70\xeb\xaf\x41\x8f\xf6\x69\xf4\xfa\xcc\x1b\x50\
-\xad\xca\x36\x18\x92\xe6\xc1\xed\x26\x8c\x82\xdf\x1f\xdf\x63\x10\
-\xde\x0e\xd4\x2c\x1b\x94\xbb\xbe\xc9\xbe\xae\xcf\xce\x0b\xcc\x4d\
-\x4c\x89\x28\x89\xcc\x46\x97\xe8\xdf\x68\x7c\x01\x0a\x2d\xa9\x38\
-\x7a\x4b\x9d\x18\x8f\xa9\x00\xe3\xd0\x4f\x29\xcd\xeb\x59\xc6\xcf\
-\xc5\x5b\xa2\x3c\xec\x90\x09\x56\x3e\x8e\xfc\x1c\xea\x17\x5c\xcd\
-\x42\x8e\x49\x82\x31\xf7\xab\xb2\x31\x70\xda\xdb\xcb\x2a\x4b\xd2\
-\xbc\xbf\xdf\x49\x92\xb2\xba\x80\x8a\x70\x86\xdb\x40\xbb\x38\xa9\
-\x27\x9d\x18\xfa\x0b\xe9\x96\xcf\x58\x0a\x98\x05\xe1\xf5\x9c\x37\
-\x87\x48\xdd\xf7\xc1\x10\x80\x83\x15\x9c\x19\x71\x63\xcf\xd2\x52\
-\xcf\x5b\x6d\xf6\xf1\x67\xe3\x0e\x86\x0c\xbc\xf8\x3c\x7e\xc5\x3e\
-\x6e\xfd\x94\xba\x4a\x4b\x86\x2e\x25\x13\x86\xfc\x45\x0a\x67\x12\
-\x3d\x23\xcb\xc6\xac\x1b\x41\x19\x2b\xf7\xf5\x20\x22\xe5\xe1\xca\
-\x8f\x14\x7d\x1f\x15\x81\xb2\x02\xdc\x80\x9b\xff\x1b\x8e\xbb\x04\
-\x2d\xa3\x77\x1d\xd6\x03\x72\xfa\x11\x24\x42\xe5\xf6\x3d\x69\x1a\
-\x34\xc7\x36\x5d\xae\xae\x70\x1a\xd6\xd7\x88\x62\x02\xf2\x50\x9c\
-\xc4\xf8\x5a\x22\x53\x23\xf2\x9a\x0b\xb6\xb2\xd0\x60\xae\xd7\xa6\
-\xb0\xc8\xce\x5c\xdd\xbe\x26\x82\x66\xa3\x6a\x89\x41\x23\x45\x1b\
-\x0e\x21\xa4\xb4\x67\xe2\x30\x14\x24\x10\xb5\xc4\xb0\xf1\xe3\xa0\
-\xf4\xff\x47\x26\x15\x07\x96\xf7\x62\xb6\x6f\x4a\x47\xa4\x74\x77\
-\x28\x8e\x16\x44\x39\xc3\x7a\x31\xa5\xf5\x19\xcf\xda\x72\xab\x2e\
-\xc8\xba\xa7\x61\x82\xa2\x51\xbd\x3e\x9a\x16\x36\x69\x41\xa1\x28\
-\x9c\x11\x01\xe8\x74\x7d\x90\x69\xa2\x1d\x41\xc5\x83\xf7\x18\xa6\
-\x59\xce\x4b\x05\x91\xee\x43\x08\xd4\xad\xa6\x44\xf1\xc5\x42\xe7\
-\x41\x6c\x34\x94\xf5\x2a\x5b\x99\xec\x73\xaa\xa3\x68\xc8\x38\x59\
-\xa7\x61\x40\x06\x6a\x7e\x91\x2a\xe6\x26\x79\xea\x07\x18\x62\x13\
-\xed\x06\xf6\x79\x06\x5e\xae\xb6\xa5\xd9\xb5\xe6\x8a\xa5\xa5\x43\
-\xa6\xcb\x66\xa1\x2e\x65\xaf\xbc\x75\xc5\x28\x92\xaa\xcb\x82\x65\
-\x79\xb0\x2a\xd6\xf9\xa8\x41\xfd\x2c\xdd\x1a\x36\x20\x0b\x5e\x56\
-\x2c\x88\xeb\x0f\x90\x87\xb0\x03\x02\x89\x6c\x49\x9e\x13\x66\x10\
-\xe3\x73\x7f\xb5\x21\x19\x50\x9e\xd0\x4c\x45\x34\x03\x88\xf4\x83\
-\x0b\x81\xc4\x8f\xab\x7d\x4a\x64\x75\x9b\x44\xfb\x6d\x4c\xeb\x3c\
-\x1d\x66\x59\x61\x6a\xab\xff\x4c\x9e\x8c\x4b\x45\x6d\x01\xec\x0a\
-\xc7\xac\x1e\xab\xf1\x5d\x0d\xcb\x4d\x29\xb9\x7c\x6b\xe5\x5a\xaa\
-\xca\x4e\x25\x41\xa8\xf0\x14\x2a\xc4\x19\x85\x10\x3e\x75\x14\x2d\
-\x62\x7a\x51\x35\x0c\x7a\x9a\xda\xde\x5e\x15\x57\x6b\x85\xea\x48\
-\xd8\xa4\x5d\xb5\x2c\xec\x56\x8a\xbf\xda\x8a\x0f\xe9\xbd\xcd\x81\
-\x45\x75\x13\xb7\x3f\xa4\xad\x26\x8c\x14\x8a\x7c\xa9\x0e\x17\x96\
-\x75\xc9\x2d\x4b\x12\x86\x07\x96\xb5\xef\x87\x71\x00\x0e\x31\x4f\
-\x14\xb1\x28\x93\x8d\xd1\xbd\x4c\x6d\x0d\x21\xb8\xa0\x88\xcd\x33\
-\x6a\xfb\x6a\x25\x5e\x08\x82\xe5\x57\xd4\xaa\xa4\xae\xea\xed\x06\
-\xaf\x3e\xb3\xb7\x7f\x82\x64\x92\x06\x85\x52\xf3\x2f\xbe\x13\x28\
-\xba\xc0\x32\xdf\x54\x1e\x15\xf6\x97\x27\x04\x13\x13\xe5\x56\x99\
-\x97\x38\x2a\x98\x96\x22\x47\x5b\x3d\xdb\x56\x57\x6c\xad\xfd\xff\
-\x2b\xa6\xa5\xfc\x5f\x9b\xe5\x6b\xa8\x35\x25\x38\x1a\x50\xd1\x57\
-\x68\x38\x14\xa7\xf5\xac\x8a\x10\x1a\x9e\x25\x5f\x54\x67\x5e\x9a\
-\xd6\x48\xe1\xc0\x7e\xce\xb3\x89\x3a\x7d\x99\x36\x79\xd5\xfa\x9c\
-\x4f\xab\xc3\x92\x93\x32\x1c\xcc\x8a\xd0\x61\x3c\x97\x6a\x56\x27\
-\xf4\x6a\x56\x27\x73\x61\x56\x27\xf2\x62\xda\x42\x31\x19\x6f\xd5\
-\x06\xf8\xb2\x07\x97\x52\xf5\x00\xb4\xfc\xc2\x3b\x0c\xce\x10\x72\
-\x77\x48\xc0\x0c\x5c\xab\x30\x3a\xde\x55\x18\x9d\x04\x6a\x30\x3a\
-\x39\x48\x40\x27\x94\xc6\xc6\x8f\x1e\xfb\x35\x91\x18\xac\xcb\x7a\
-\x18\x93\x57\xed\xb1\xaf\xc2\x74\x15\x35\x9d\x45\x81\xb5\xc9\x39\
-\x68\xc0\x2c\xda\xd8\xe4\x0a\x74\x60\x16\xfd\x54\x5d\x43\x7b\x85\
-\x2c\x9f\x5a\xb7\xd1\xcc\x26\x99\x18\x81\x1b\x75\xb5\x49\x3e\x66\
-\xe0\x46\xed\x7d\x89\xac\x04\x75\xd5\x09\xcc\xae\xb7\x2f\x41\xcc\
-\x34\x55\x83\xb3\x3a\xa5\x62\x57\x72\x93\xab\xff\x54\x04\xc6\x65\
-\x12\x05\xd5\x33\x2f\xa9\x36\x7f\x33\x21\xcf\xbc\x60\xf8\xf7\xc7\
-\xc7\x0c\xe7\xbc\x26\x22\xb3\x4a\xdb\xf3\xd8\xac\x53\x6d\x00\x16\
-\x15\xcf\x9b\x31\x20\x16\xd5\xeb\x23\x95\x0f\xe1\xeb\xed\x59\x9e\
-\xee\x71\xf9\x7c\x4c\xaa\xf5\x29\xbd\xe5\x63\xbe\x26\x76\x6b\xe1\
-\xbe\x58\xe5\x79\xb9\xbf\xec\x89\xaa\x9d\x87\x79\xd9\xc3\x69\x78\
-\x6e\x64\x6c\x86\xd3\xde\x91\xa9\x17\x7e\x02\x89\xd6\x9e\x30\xb9\
-\xca\xca\xa2\xa9\x4e\x13\x69\x23\x90\xae\x06\xab\xf7\x66\x21\xc7\
-\x97\xb3\x42\x0f\x7d\x21\x1d\x09\x38\x8b\xe2\x2e\xd0\x6b\x0a\x40\
-\x5e\xdf\x46\x24\x09\xef\xa1\xef\xf0\x7b\xd8\xab\x86\xc7\x1e\x42\
-\x23\x18\x86\xdf\xa3\x6a\x38\x63\x07\xc9\x09\x50\x27\x46\x3c\xef\
-\x3c\x67\x84\x70\x91\x59\xcb\x26\xf1\x58\x45\x37\xa0\x9c\xef\x8b\
-\x1e\x85\x09\xa5\x60\xe7\xc3\x7d\xf8\x37\xfe\x25\x0d\x77\xb2\x0d\
-\x57\x1d\xdd\xe2\x68\x5d\x35\x45\x75\x79\x63\x03\x1c\xd4\x5f\xf4\
-\xf2\x94\xe7\xed\xfc\x98\x68\xde\xb3\x34\x08\x8c\xf4\x97\xb4\xa7\
-\xce\xc6\xab\xfe\xfa\x97\x1d\x78\x03\x9c\xe6\xdf\xfb\x41\xea\x3f\
-\xcd\xfd\x8c\xb5\x8d\x4a\x30\xba\x56\x32\x1d\xe3\x23\x80\xb6\xed\
-\x49\xf3\xcd\x1c\xb7\x6a\x7d\x70\x12\x3c\x38\xce\x9e\x3c\x52\x3c\
-\x5b\x91\x52\x71\xde\x3b\xa9\x95\xa2\xbc\x9b\x33\xd6\x6f\x2d\xb6\
-\x40\x14\x04\x07\x77\x41\xea\xcf\x1e\xeb\xed\xb1\xc2\x99\x51\x93\
-\x32\x54\x84\x0a\x65\x32\x62\xe1\x69\x91\xa3\x79\x62\xac\x3e\x6b\
-\xac\x5b\xb3\xbd\x67\xd2\x60\x96\x43\x66\x95\xfd\x91\x6c\x96\x43\
-\x66\x95\x5a\xb3\x64\x94\xd8\xcc\xf2\xd9\x72\xaa\xda\xc7\x7b\x36\
-\xc6\x35\x07\xa2\x30\x2e\x89\xa6\x25\xe3\x63\x2d\xdf\xc3\x53\xb0\
-\x5d\xea\x60\xad\x73\x70\xfa\x33\x69\x76\x95\xda\x33\x79\x11\x7d\
-\x87\x8b\xae\x35\x75\x64\xbe\x45\x83\x50\xa7\x15\x96\x3e\xb6\xdc\
-\xb9\xd0\x48\xa5\x35\x6a\x41\x5f\x8f\xc2\x4b\xf8\xd5\x87\x1e\x83\
-\xaa\xeb\xe9\xd6\x6f\xa1\xf3\x22\x16\x79\x37\xc4\xc0\x46\x3f\x64\
-\x73\x7e\x8a\x7c\xdb\xa3\x32\x09\x5a\xc1\x43\x3c\xb6\xe2\xf9\x59\
-\xf3\x50\x8e\x2c\x54\x0d\x6b\x71\x85\x3f\x1e\xd2\xc5\x15\x1a\x8b\
-\x74\x81\x85\x05\xa3\x76\x71\xc5\xaa\x35\x6d\x45\x4b\xd3\x47\x09\
-\x33\x0d\x5b\x06\x07\x2b\x5d\xa7\xd1\xc8\x59\x0a\x67\xc7\x45\x96\
-\xfe\xc8\x9a\xf0\x9d\xc4\xc5\x8a\x87\x2a\x51\x6e\x60\x5b\x66\x4b\
-\xc3\xb7\xee\x9a\x51\x3b\xb6\xf5\x69\xee\x29\xe3\x4a\xa5\x83\x6d\
-\x1d\xf7\x11\x47\xd2\xda\x75\x6b\x0c\xe1\x87\x89\xae\x35\x71\x54\
-\x74\xad\xbd\xbb\x39\xb7\x53\xd9\x33\xf9\x77\x26\x94\xd6\x88\xed\
-\x89\xe7\x01\x78\x29\xbf\x7a\x27\xab\x37\x05\x2d\xdd\xfa\x0d\xb4\
-\x2e\xc4\x26\xef\xf6\xde\xfe\xe0\xa4\x5a\x96\x6f\x7b\x44\x46\x41\
-\xd3\x52\x2e\xf7\xf3\xbd\x70\xf3\xea\xc4\x25\xd2\x4f\x4f\x79\x9d\
-\x93\xba\x26\x56\x5b\x3f\x84\xbb\x93\x48\x47\x6b\x7e\xcd\x17\xc5\
-\x92\x9d\xbf\x0a\xf3\xef\xe0\x42\x86\x43\x46\xd4\xdc\x8f\xa2\x24\
-\x89\x2b\xba\xb4\x5f\x9d\xb1\x5f\x6d\xf8\xe9\xac\x00\xe1\x83\x0b\
-\xf4\x9e\x7c\x7b\x91\x94\xe8\xa4\xbc\x27\x58\xc8\x55\x04\xf2\xe4\
-\x9f\x69\x7c\x97\xcc\x4b\x05\xff\x8f\x51\x48\x4b\x75\xd9\xb6\xf7\
-\xc3\x0b\x1a\xbd\xe6\x1d\x59\x64\x92\xd1\xe2\x42\xbf\x2a\x17\xbb\
-\x03\x38\x90\xe1\x9a\x4b\x13\x11\xd4\x5a\x28\x45\x97\xa2\x4c\x38\
-\xe4\x1b\x27\x96\xfa\xf6\x08\xf1\x97\x4a\x43\xee\xe7\x4e\xa8\xe2\
-\x14\x77\x52\x34\x54\xd2\xdc\x9e\xde\x71\xe9\x19\x41\x8a\x8c\xd7\
-\x78\xd1\x49\xed\x0e\xb1\x51\xbd\x43\xd6\xe2\x8f\xfc\x03\xd0\x13\
-\x20\xed\x7d\x1d\x15\x7d\x31\x2c\xe3\xd7\x1a\x88\xa1\x10\x37\x7b\
-\x5c\x3b\x1b\x2f\x2c\x49\xc5\x28\x5d\x5d\x8f\xe8\x12\x2c\xf4\x1d\
-\x6b\xed\x49\xd7\x23\xd4\x49\x2d\xe6\x74\xbd\x7c\x8d\x26\x90\xc4\
-\x4d\x5c\xf8\x7f\x75\xde\x80\x40\x7f\xd5\xc5\x08\x65\x46\xe9\x02\
-\x4a\xd7\x81\xff\xd3\x73\xee\xbb\xee\xc3\x00\xdb\x7c\x17\x99\xff\
-\x09\xbe\xcb\x5c\xbe\xb4\x6e\x5b\x3b\x3f\xa0\x8a\xa9\xb9\xae\x4a\
-\x2c\xc7\xb9\xae\x86\x64\x4e\xdc\xbf\xee\xb9\x28\x79\xaa\xe3\xe2\
-\x45\xb0\xa3\xba\x17\x65\x2b\x96\xe2\x29\xfe\x45\x85\x61\x06\x6b\
-\xba\x09\xa9\x9a\x37\x1d\x34\x38\x17\x2d\x76\xd9\xbb\xe8\x91\xd7\
-\x9d\x0b\xe7\x50\xff\x2d\x1c\x8b\x7b\x51\x11\xe8\xbf\x31\x6b\x3a\
-\xaa\xc3\xaf\x59\xaa\x89\x28\x31\x2f\xd0\xd3\xd5\xa6\x66\x5c\xfc\
-\x96\x64\x97\xcd\x1b\xaf\xda\x4f\x2c\x17\xeb\xab\x5b\x71\x04\xd1\
-\x5f\xa9\xbf\xdb\x61\xf2\x37\x02\x72\xf2\xad\xfe\x4c\x42\x27\xb8\
-\x96\x02\x8e\xb9\x0c\xcd\xbd\x34\x1d\x40\xd3\xd7\x0f\xac\xf7\xf4\
-\x74\x1b\x1a\x1c\x9a\x0d\xd2\x50\x19\x54\x77\xf9\xaa\xef\x24\xf2\
-\x7d\xee\x0b\x51\xb0\x99\xa3\xbe\x2f\xa4\xfb\xf2\x82\x7e\x7b\xe1\
-\x08\x6d\xdb\x10\xbb\xa4\xdf\xa5\x56\x77\xa1\x83\x3f\xfc\x52\x20\
-\x27\xe8\xea\xea\x4a\x7b\x82\x87\x8b\xc3\xcc\xc4\x01\x71\x48\xfc\
-\xdb\x21\xe7\x26\x6c\x14\xd2\x21\x7f\x0a\xc2\x71\xc9\x0f\x16\xb3\
-\x40\x9d\xff\x07\xb1\x4c\xd7\x4c\
-\x00\x00\x01\x0d\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x33\x32\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x32\x37\x39\x2e\x30\x31\x35\x34\x36\x20\x32\
-\x34\x33\x2e\x35\x32\x35\x68\x2d\x32\x33\x37\x2e\x39\x39\x39\x39\
-\x39\x37\x63\x2d\x32\x31\x2e\x34\x20\x30\x2d\x33\x32\x2e\x31\x30\
-\x30\x30\x30\x30\x31\x2d\x32\x35\x2e\x39\x2d\x31\x37\x2d\x34\x31\
-\x6c\x31\x31\x38\x2e\x39\x39\x39\x39\x39\x37\x2d\x31\x31\x39\x63\
-\x39\x2e\x34\x2d\x39\x2e\x34\x20\x32\x34\x2e\x36\x2d\x39\x2e\x34\
-\x20\x33\x33\x2e\x39\x20\x30\x6c\x31\x31\x39\x20\x31\x31\x39\x63\
-\x31\x35\x2e\x32\x20\x31\x35\x2e\x31\x20\x34\x2e\x35\x20\x34\x31\
-\x2d\x31\x36\x2e\x39\x20\x34\x31\x7a\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\x23\x45\x37\x42\x44\
-\x35\x34\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xf8\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x68\x33\x35\x32\x63\x32\x36\x2e\x35\x20\x30\x20\x34\x38\x2d\x32\
-\x31\x2e\x35\x20\x34\x38\x2d\x34\x38\x76\x2d\x33\x35\x32\x63\x30\
-\x2d\x32\x36\x2e\x35\x2d\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\
-\x2d\x34\x38\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x66\x69\x6c\x6c\x3d\x22\x23\x46\x46\x41\x41\x43\x45\x22\x2f\x3e\
-\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xe2\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x6c\x34\x30\x30\x2d\x34\x30\x30\x63\x30\x2d\x32\x36\x2e\x35\x2d\
-\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\x2d\x34\x38\x7a\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\
-\x23\x41\x38\x41\x41\x41\x42\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\
-\x3e\
-\x00\x00\x00\xce\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x33\x36\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x37\x33\
-\x36\x20\x37\x33\x36\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x37\x33\
-\x36\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x33\x36\x38\x20\x31\x32\x30\x63\x2d\x31\x33\
-\x37\x20\x30\x2d\x32\x34\x38\x20\x31\x31\x31\x2d\x32\x34\x38\x20\
-\x32\x34\x38\x73\x31\x31\x31\x20\x32\x34\x38\x20\x32\x34\x38\x20\
-\x32\x34\x38\x20\x32\x34\x38\x2d\x31\x31\x31\x20\x32\x34\x38\x2d\
-\x32\x34\x38\x2d\x31\x31\x31\x2d\x32\x34\x38\x2d\x32\x34\x38\x2d\
-\x32\x34\x38\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x46\x46\x41\
-\x41\x43\x45\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xe2\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x6c\x34\x30\x30\x2d\x34\x30\x30\x63\x30\x2d\x32\x36\x2e\x35\x2d\
-\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\x2d\x34\x38\x7a\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\
-\x23\x46\x46\x41\x41\x43\x45\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\
-\x3e\
-\x00\x00\x00\xce\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x33\x36\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x37\x33\
-\x36\x20\x37\x33\x36\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x37\x33\
-\x36\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x33\x36\x38\x20\x31\x32\x30\x63\x2d\x31\x33\
-\x37\x20\x30\x2d\x32\x34\x38\x20\x31\x31\x31\x2d\x32\x34\x38\x20\
-\x32\x34\x38\x73\x31\x31\x31\x20\x32\x34\x38\x20\x32\x34\x38\x20\
-\x32\x34\x38\x20\x32\x34\x38\x2d\x31\x31\x31\x20\x32\x34\x38\x2d\
-\x32\x34\x38\x2d\x31\x31\x31\x2d\x32\x34\x38\x2d\x32\x34\x38\x2d\
-\x32\x34\x38\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x41\x38\x41\
-\x41\x41\x42\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xf8\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x68\x33\x35\x32\x63\x32\x36\x2e\x35\x20\x30\x20\x34\x38\x2d\x32\
-\x31\x2e\x35\x20\x34\x38\x2d\x34\x38\x76\x2d\x33\x35\x32\x63\x30\
-\x2d\x32\x36\x2e\x35\x2d\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\
-\x2d\x34\x38\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x66\x69\x6c\x6c\x3d\x22\x23\x41\x38\x41\x41\x41\x42\x22\x2f\x3e\
-\x0a\x3c\x2f\x73\x76\x67\x3e\
-"
-
-qt_resource_name = b"\
-\x00\x0b\
-\x0c\x6b\x3c\xf3\
-\x00\x73\
-\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x73\
-\x00\x11\
-\x0a\xf7\x1a\xc3\
-\x00\x43\
-\x00\x68\x00\x69\x00\x6c\x00\x64\x00\x4f\x00\x66\x00\x4d\x00\x65\x00\x74\x00\x72\x00\x6f\x00\x70\x00\x6f\x00\x6c\x00\x69\x00\x73\
-\
-\x00\x0d\
-\x02\x0d\x3c\x07\
-\x00\x64\
-\x00\x72\x00\x6f\x00\x70\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0d\
-\x02\x33\xbc\x47\
-\x00\x73\
-\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0e\
-\x03\xc2\xd5\xc3\
-\x00\x73\
-\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x2e\x00\x71\x00\x73\x00\x73\
-\x00\x0b\
-\x04\x37\x88\x27\
-\x00\x73\
-\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x75\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0a\
-\x08\x8b\x0b\xa7\
-\x00\x73\
-\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x18\
-\x08\xb9\x19\xc7\
-\x00\x68\
-\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
-\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0a\
-\x0a\x2d\x1b\xc7\
-\x00\x63\
-\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0f\
-\x0d\xb0\xb1\xa7\
-\x00\x68\
-\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x13\
-\x0d\xf4\xfe\xa7\
-\x00\x63\
-\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
-\x00\x76\x00\x67\
-\x00\x13\
-\x0f\xf8\x57\x27\
-\x00\x73\
-\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
-\x00\x76\x00\x67\
-"
-
-qt_resource_struct_v1 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
-\x00\x00\x00\x44\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf8\
-\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\xef\
-\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6c\
-\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x7d\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x79\
-\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5f\
-\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x31\
-\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x17\
-\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xe9\
-"
-
-qt_resource_struct_v2 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x44\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
-\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf8\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\xef\
-\x00\x00\x01\x90\x40\x3f\xfe\xde\
-\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x6c\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x7d\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x79\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
-\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5f\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
-\x00\x00\x01\x2c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x31\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x01\x50\x00\x00\x00\x00\x00\x01\x00\x00\x13\x17\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe1\
-\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xe9\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-"
-
-qt_version = [int(v) for v in QtCore.qVersion().split('.')]
-if qt_version < [5, 8, 0]:
- rcc_version = 1
- qt_resource_struct = qt_resource_struct_v1
-else:
- rcc_version = 2
- qt_resource_struct = qt_resource_struct_v2
-
-def qInitResources():
- QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-def qCleanupResources():
- QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-qInitResources()
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x00\xbe\
+\x00\
+\x00\x00\xf7\x78\x9c\x25\x4e\x5d\x0b\x83\x30\x0c\x7c\x1f\xec\x3f\
+\x84\xec\xd9\xb6\x69\xab\xce\x61\x7d\x90\xed\x87\x8c\x7d\x58\x41\
+\xb7\x31\x8b\x95\xfd\xfa\xc5\x1a\x48\xb8\x24\xc7\xdd\xd5\xd3\xdc\
+\x81\x7f\xf4\x9d\x0f\x0e\x0b\xab\x10\xe6\xfe\x11\xdb\xf7\xe2\x50\
+\x81\x02\xa3\x15\xa4\x6b\xec\xef\xc1\x3b\xe4\x1d\x61\x19\x87\xd7\
+\xe4\xd0\x87\xf0\x39\x49\x19\x63\x14\xd1\x88\xf7\xb7\x93\x5a\x29\
+\x25\x59\x10\x9b\xfd\x0e\xb8\xea\xcf\x35\x78\xb8\x3b\x1c\x2d\x81\
+\x36\x85\xb0\x65\xee\xb5\x39\xde\x34\x09\x9b\xd4\x05\xdf\x73\x51\
+\x01\x95\x60\x69\xc8\x88\x18\x52\x75\xcb\x2a\xfe\x73\x67\xda\x8a\
+\x22\x01\x63\x98\xa5\x12\x43\x50\x96\x38\x94\xaf\x68\x1d\x96\x09\
+\xec\x40\x25\xcf\x1f\x6e\xde\x5b\x3d\xfb\x61\x70\x78\xb8\x94\xed\
+\x39\xb7\x28\x39\x57\xbd\x06\x6c\xfe\xce\xd8\x3a\xb9\
+\x00\x00\x00\xbd\
+\x00\
+\x00\x00\xf6\x78\x9c\x2d\x8e\xdd\x0a\xc2\x30\x0c\x85\xef\x05\xdf\
+\x21\xc4\xeb\xb5\x4d\xdb\x59\x27\xeb\x2e\x44\x1f\x44\xfc\x59\x07\
+\x9b\x1b\x5a\xec\xf0\xe9\xcd\xaa\x81\x84\x43\xf2\x71\x72\xea\xd7\
+\xbb\x85\x70\xeb\xda\x10\x3d\x1a\xad\x10\xde\xdd\x2d\x1d\xc6\xd9\
+\xa3\x02\x05\xbc\x81\xbc\x4d\xdd\x35\x86\x3f\x31\x0f\xfd\xe3\xe5\
+\x31\xc4\x38\xed\xa5\x4c\x29\x89\x64\xc4\xf8\x6c\xa5\x56\x4a\x49\
+\x36\xc4\x66\xbd\x02\xae\x7a\x3a\xc7\x00\x57\x8f\x83\x25\x70\x5b\
+\x61\x5d\x19\xb4\xd9\x5d\x34\x09\x9b\xcd\x05\x81\x2e\x45\x05\xe4\
+\xc0\x52\x5f\x10\xb1\xa4\xea\x52\x54\x7c\xe7\x2e\xb4\x15\xdb\x2c\
+\x8c\x61\x4a\x65\x42\x50\x91\x19\x2a\x17\xb5\x0c\xcb\x00\x3f\x20\
+\xc7\xf3\x83\xbf\xd7\xbf\xba\x77\x7d\xef\x71\x73\x72\x87\x63\x69\
+\x51\x72\xac\x7a\xc9\xd7\x7c\x01\x8e\xea\x3a\x81\
+\x00\x00\x0c\x70\
+\x00\
+\x00\x46\xf4\x78\x9c\xcd\x1c\x5d\x6f\xdb\x38\xf2\x3d\x40\xfe\x03\
+\x2f\x46\x81\x26\x67\xd7\x1f\xb2\xe3\x44\x45\x1f\xe2\xb8\xd9\x3b\
+\x60\x8b\xed\x6e\x82\xdb\x87\xa2\x0f\xb2\xcd\xd8\x42\x65\xc9\x95\
+\xe4\xa6\xdd\x45\xfe\xfb\x0d\xbf\x24\x92\x22\x29\x4b\x49\xae\x97\
+\xa2\x89\x43\x0e\x39\xdf\xc3\x99\x11\x95\xfe\xd9\xf1\xd1\xa7\x3b\
+\xfc\x3d\xff\x7c\x7c\x14\x27\xe9\x36\x88\x7c\x04\x5f\x1d\x4c\xbf\
+\x50\xc7\x3b\xf7\x2e\xbd\x1b\x32\x84\x7a\x3d\xb4\x0d\xc2\x18\xdd\
+\x27\x71\x8e\x96\x49\x94\xa4\xc7\x47\xab\x30\x0b\x16\x11\x5e\xc1\
+\xa2\xce\xd8\x1b\x4f\xc7\x2b\xd4\x99\x9e\x4f\xa7\xd3\x0b\xb1\x44\
+\x40\x28\xcb\x50\xe5\x2b\x5d\x2f\x82\xd7\xe8\x7c\xda\x45\x68\x3a\
+\x24\xdf\xe0\xd3\x64\xf2\xea\x14\xbd\x7b\x87\x3a\xf3\xab\xf9\x7c\
+\xfe\xfe\xd0\x65\x23\xb1\xec\xea\xe2\xea\xea\x6a\x06\xfc\xcd\x82\
+\xe5\x97\x75\x9a\xec\xe3\x95\xc6\xe5\x68\x30\x1a\x8d\x26\xa8\x73\
+\x3d\xba\x1e\x5f\x4f\x14\x2e\x17\xc5\x1a\x41\x34\x5e\x85\x39\x61\
+\x85\xf0\xea\xc1\xd7\x78\x2c\x28\x13\x0b\xf5\x35\xc0\x73\x8a\x52\
+\x1c\x2c\xf3\xf0\x1b\xee\x8b\xf5\xe8\x21\x5c\xad\x71\x9e\xa1\xd7\
+\x44\xee\xef\x61\x34\xeb\xa2\x8f\x69\xb2\x4e\x71\x96\xcd\x82\x34\
+\x43\x38\x5f\x9e\x1e\x1f\x6d\x92\x6f\x38\xa5\x74\x02\xa1\xf0\xe5\
+\x79\xa8\x33\x1b\xcd\x3d\x07\xbe\x87\x0d\x8e\x11\x5d\x17\xc6\x6b\
+\x44\x7e\x16\xe8\x4b\xac\xb3\x7d\x9e\x27\x31\xe0\xfc\x17\x0e\x56\
+\x38\xcd\x00\x55\x86\x23\x0c\x50\x49\xec\x03\xaa\xfb\x31\xfc\x03\
+\x35\x0e\xe7\x57\x53\x37\x6b\x6c\x99\xcc\xd3\xf1\x51\x10\xe5\x38\
+\x8d\x83\x1c\x93\xad\x2e\x46\xc1\x08\x8c\x68\x76\x3d\x7b\x3f\xbb\
+\x71\x6e\x25\x96\x11\xba\xd3\xe4\x21\x43\xa0\x82\x5f\xc3\x2c\xef\
+\xdf\xa5\x18\xf7\xef\x08\x8e\xff\x84\x18\xc6\x83\x78\x45\x17\xdc\
+\x2e\xd3\x24\x8a\x88\xb8\x8e\x8f\x88\x8a\x93\x14\x78\xd1\xd4\x3b\
+\xbe\xf0\x56\x17\x0b\xd4\x99\x5c\xcf\xbd\x9b\x12\x3f\x05\x95\x70\
+\x6f\x93\x2c\x2f\x19\xb0\x19\xd9\x74\x04\xf6\x75\x0e\x46\x36\xf4\
+\x2e\x25\x23\x63\x1a\x51\xad\xc3\x22\x42\x1d\x6f\x63\x83\x08\xd7\
+\x9b\x08\xfe\xe7\x20\xda\xc9\x68\x7c\x1e\x0c\x6a\x59\x5b\xa5\xc9\
+\x6e\x95\x3c\xc4\x02\x45\x17\x05\x68\x11\xe6\x88\x6e\x03\x90\xf9\
+\x26\x88\xc5\x2a\x26\x8a\x14\x83\x5a\x77\x41\x1a\x10\x73\x38\xc4\
+\xc1\xa5\xd5\x85\xaf\x1b\xad\xc1\x5b\x7a\xf7\xe3\x21\xb8\xa5\x37\
+\x07\xbf\xb4\x92\xbc\x4e\x83\x55\x88\x21\x56\x94\x76\x92\xa1\xa4\
+\xe0\x00\x48\xff\x82\x11\x18\x04\x33\x85\x8f\xc9\x6e\xbf\x63\x26\
+\x70\xbb\xc3\xcb\x30\x88\xc0\x06\xc2\x38\xcb\x83\x28\xea\x49\xb6\
+\x80\x3a\x83\x29\x88\xeb\xe6\xf2\x6a\x4a\xc5\x05\x98\x39\x54\x09\
+\x2e\x39\x1c\x80\x4f\x00\x7c\x36\x9b\xce\x67\x36\x70\x49\x34\x00\
+\x3e\x02\xf0\xe9\x7c\xe2\x5d\x0c\x34\xf0\x7d\x5c\x25\xa7\x33\x1d\
+\x10\x62\x6e\x66\x83\x8b\x09\x03\x2f\xa0\xe4\x05\x25\x41\x9d\x09\
+\x59\x30\xbb\xb9\x18\x9f\x8f\x1d\x0b\x4a\x92\x20\xb4\xc1\x82\x8b\
+\xc1\xe4\x62\xec\x55\x16\x9c\xf5\x89\xc0\xe0\x27\xfa\x9b\xd9\x3b\
+\x95\xbe\x2f\xa2\xfd\x5b\x36\xc8\x34\xd3\x13\x73\xcc\xd2\xc4\x5c\
+\xa1\x9b\x62\x9e\xc5\x50\x98\x7f\x84\x8d\x7d\x41\x49\x97\xfc\x52\
+\xf8\x46\x61\x20\x1a\x5e\x66\x51\x66\xbc\xea\x9c\x1b\xef\xf1\xd1\
+\xef\xbf\x06\x0b\x1c\x75\xc5\x87\x0a\x46\xbe\x39\x18\x53\xbe\xf1\
+\xd1\x60\xf7\xdd\xba\x71\x9e\x06\x71\x06\x8e\x00\xa6\xc8\x61\x76\
+\xc1\x6a\x05\xf1\x49\x5e\x56\x04\xce\x9e\x81\x32\xe6\xfe\x05\x65\
+\x1f\x70\xbc\xa7\x84\x41\x58\x23\xb1\x4c\xfe\xec\xfb\x61\x8e\xb7\
+\x64\x84\xc4\x3b\x31\x2b\x3e\x4b\xb3\x22\x10\x2a\xbf\x94\xf3\x2c\
+\xa4\xb3\xb1\x8c\x51\xa6\x40\x22\xf6\xf1\x3a\x49\x63\x9c\xb2\x83\
+\x40\x01\xbc\x49\x83\x2d\xfe\x74\x4f\xbe\xdf\x6e\x82\x1d\x7e\x77\
+\x72\x7e\xf2\x99\x4c\xfc\x02\xac\xed\x66\xc9\x77\x46\x74\x8c\x49\
+\x94\xa2\x3b\xf3\x88\x45\x3f\x87\xdb\x62\x7c\x0e\x3e\x2f\x7f\x96\
+\xe7\xee\x92\x24\xe2\x5b\x5d\x27\xdb\x45\xa2\x7d\x2e\xcc\x45\x1e\
+\x44\xbf\x5f\x2d\x32\x50\xc9\x32\xff\x37\xb0\x2a\x24\x70\xbb\x0b\
+\x63\xbe\x7a\x9e\xec\x61\x89\x34\x20\x05\x50\x0a\x2a\xce\x0b\xb3\
+\x25\x0c\x4b\x4b\x60\xe3\x59\xfe\x83\x04\xf3\x2c\x89\xc2\x95\x3a\
+\x43\xe2\xd3\x3e\xf3\xd1\xa8\x58\x52\x18\x06\x1b\x62\xea\x7e\xaa\
+\x2a\x9e\x2a\xe5\x9f\x23\xce\x8a\xed\x5b\xbc\x96\x25\x4e\x2d\xbc\
+\xa8\x6a\xa1\x83\x93\xcf\x2e\xef\x7e\xb4\x99\xb5\xb6\x48\xa8\x75\
+\x5c\xac\x2a\x84\xf5\x77\x3d\x1b\x32\x7c\x35\xe8\x54\x17\xb2\xdc\
+\x54\x5f\xf8\x8f\x22\x52\xd2\xd0\xef\x58\xcf\xd2\x0e\x11\x6d\xa9\
+\xff\xfb\x4c\x8c\x34\xe6\x3a\x14\x2d\x36\x3d\x58\xe8\xb0\x3d\x49\
+\x23\x7a\x24\x8f\xe8\xaa\xbf\xca\xb6\x05\xe3\xfb\x5d\x6f\x41\x0d\
+\x99\x83\x01\x04\x1f\x28\x90\xee\x17\x4b\xa8\x03\xc0\x76\x7a\x49\
+\x1a\xae\x43\x48\x38\x99\xf8\xdf\x3e\xbb\x53\xf2\x89\x1c\x48\x8d\
+\xf0\x7d\x5e\x40\x0c\x74\x88\x45\x02\x14\x6e\x4d\x40\x1a\xf3\xea\
+\xa1\x66\x90\x82\x06\x50\x88\x43\x5f\x58\xca\xc5\x76\x3e\x1d\x78\
+\xf8\xa9\x67\x94\x46\xae\x41\xe6\xbb\x24\x0b\x59\x9a\x0f\x62\x41\
+\x29\x49\x02\x0f\x39\xec\xd9\x1c\x15\x90\x06\x80\xfa\x67\x45\x0e\
+\x2a\x72\x4a\x92\x5d\xe8\x92\x6b\x6a\x27\x0d\xa3\x09\x4b\x29\x0f\
+\x37\x57\x81\x46\xd8\xd9\xb8\xb0\x89\x70\x1b\xac\xc1\xc2\xf6\x69\
+\xf4\xfa\xc4\xef\x53\x7b\xcb\x36\x18\xf2\xce\xfe\xf5\x26\x8c\x56\
+\xbf\xdd\x7f\xc0\x20\xc9\x1d\x18\x60\xd6\x2f\xf6\x7d\x93\x7d\x5b\
+\x9f\x9c\x16\xe8\xeb\xd9\x93\xf1\x12\x11\x0e\xcf\xd1\x3f\xd1\xe8\
+\x0c\xec\x5d\xf1\x00\xf4\x0e\x0d\x27\x30\xc6\xcf\x17\x80\xf1\xe8\
+\x6f\x29\x4d\x8f\x59\xe2\x5c\x4a\xbb\x40\x7b\xa0\xe2\x09\x62\x31\
+\x8e\x82\x1c\x6a\x01\x5c\xce\x42\x6a\x46\xce\x25\xba\x7d\xd5\x57\
+\x04\xfd\x2d\x84\x96\x25\x69\xde\xdb\xef\x34\x91\xb9\x43\x45\x49\
+\x3d\xc3\x6f\x61\x40\x9e\xb4\xd0\x4f\xa2\xc1\x53\x89\xd7\x35\xae\
+\x1e\x8e\x82\x7c\x43\xb2\x98\xc3\x29\xde\x0b\xc0\x4d\x80\x91\x25\
+\xa8\x90\x46\xbd\x47\x75\xb9\xef\x2f\x37\xfb\xf8\x8b\x63\x17\x5b\
+\x06\xcb\x07\x46\xaf\xf8\xef\xdb\x20\xa5\xf1\xd5\x95\xe3\xea\x87\
+\xab\xed\x54\x57\xcf\x46\x85\xb0\xa1\x6b\x7b\x56\xf8\x73\x2e\x8b\
+\xcd\x7d\x38\xda\xf2\x70\x19\x44\xba\x3b\x0c\x8b\xa3\xb7\x84\xdd\
+\xc0\x39\xf1\x17\xd8\x41\x09\xbd\xc1\xac\x06\x36\x82\xfb\x40\x57\
+\x2f\x82\xd4\xa9\x40\xd2\x55\xe7\xc1\xac\x9c\xf3\xc5\xfa\x12\xb1\
+\x6d\x87\x2a\x69\x4c\x5c\x3e\x8a\x93\x18\xbf\x55\xa9\x35\xa9\xc1\
+\x10\xc0\x9d\xac\xd4\x39\xf6\xdb\xca\xb4\x38\x64\x99\x31\x54\x51\
+\x54\xa4\x71\x80\xf7\x35\xc7\x62\x90\xa9\x13\x8f\x7c\x30\xb5\x61\
+\xe6\x40\x34\xe4\x40\x6b\x8e\x65\x13\xc4\xab\xf2\x04\x69\x9d\xb0\
+\x1c\x5a\x56\x2b\x89\xb2\x35\xd9\xd9\x86\x71\x4f\x58\x9a\x37\x50\
+\x86\x39\x69\xde\xc0\x58\x9b\x58\x02\xcd\xa3\xb9\x80\x31\x48\xd6\
+\x10\xa1\x98\xe4\x68\xbe\x60\x18\x4e\xb9\xf7\x3a\xf1\xe8\xe6\x68\
+\xc7\x02\x66\x6f\x18\x65\x96\x5a\x87\xa5\xe4\xc6\xbf\x0f\xd3\x2c\
+\x17\xd8\x14\x06\x0e\x23\xd4\xb8\x01\xa5\xad\x5c\x2f\x17\xfe\x4a\
+\x99\x5f\x94\x84\x7c\x79\xb2\xcf\xa9\x1d\xa3\x01\xe7\x6a\x9d\x86\
+\x2b\x32\x52\x0d\xac\xd4\x78\x37\xc9\x43\x6f\x85\xe1\xc4\xa3\x4d\
+\xbb\x9e\xa8\x03\xca\xf5\xae\x5c\xbf\xda\xe7\x70\x35\x59\xc8\x7c\
+\xd1\xd4\x33\x55\x0e\x72\xc8\x97\x78\x46\x6a\x3d\xcb\xb9\xd7\x46\
+\xcb\xd2\x58\x0c\xdb\xcd\xd3\xd9\x3c\x61\x23\x9a\x36\x74\xc3\x83\
+\xec\xe1\x0e\x52\x1e\xa6\x38\x10\xd0\x96\x64\x55\x61\x06\x99\x44\
+\x1e\x2c\x37\x24\xdf\xca\x13\x9a\x14\xc9\xee\x42\xf2\x89\xfe\x99\
+\x4c\xec\xa7\xe5\x3e\x25\xc2\xbb\x4e\xa2\xfd\x36\xa6\xe5\xa8\x11\
+\xbd\x6e\x4d\x95\x0d\xfe\x48\x1e\xec\xab\x55\x53\x22\x54\x68\xec\
+\xb3\x8a\xb1\x2a\x04\x69\x5c\x6d\x17\x69\x25\x66\xb3\xa8\x24\x97\
+\x9f\x3a\x21\x72\x19\xaa\xd1\xa2\x4c\x69\xe4\x88\xb9\x96\x14\x69\
+\x99\xcc\xc7\x7d\xb6\x99\x89\x24\x9c\x75\x9c\xd4\x02\xa3\xa6\x96\
+\x2f\xd7\xcb\xc5\x9b\xb4\x51\xe3\x22\x5f\xda\xb1\x54\x49\xb9\x5d\
+\x31\x66\x0e\x54\x87\x77\x03\xea\x59\x7f\x81\xc6\x97\xa7\x0f\x71\
+\x73\x3f\xaf\x8c\x73\x2f\x3c\x2f\xbd\x50\x95\x8d\x0f\x6e\xb8\xef\
+\x85\xf1\x0a\xa2\x6a\x9e\xe8\x52\xd2\x66\xeb\xb3\x88\x32\xd1\xb6\
+\x1c\xf3\x9c\x2e\x0e\xc0\xa8\xee\x55\xba\x08\x5c\x28\x3c\xaf\x7b\
+\x14\x2d\x74\xa5\x2d\x7a\xbd\xc1\xcb\x2f\xfc\xf3\x1f\x20\xaa\xa4\
+\xce\xe2\xaa\xc9\x9f\xd8\x0e\x5c\x42\x16\x80\xd8\x59\x1b\x96\x90\
+\x68\x33\x92\x47\x2a\x82\x2c\xbd\x51\x19\x96\x3c\x51\x97\xac\xb3\
+\x10\x6f\x6e\x48\xee\xf6\xfd\xff\x21\xff\x6a\x69\x62\x29\x3f\x0c\
+\x64\x3b\xf2\x2a\x03\xb4\x12\x63\x0c\xdc\x2a\xf3\x66\xb6\x15\x10\
+\x03\xff\x6a\x18\xab\x0a\x42\x9d\x37\x48\xe4\xe0\x56\xd5\xa3\x95\
+\x46\x4b\x55\x39\x79\xd5\x4a\xfd\xcf\x6e\xe4\x6a\x7c\xb3\xa9\x6a\
+\x49\xa8\xb1\x6b\x4a\x9a\x36\x69\x41\x9a\x36\x29\x41\x9e\x36\xe9\
+\x80\xcf\x3b\x09\x27\x13\x8d\x9a\x1a\x5f\xf7\x10\x83\xe4\x8e\x86\
+\x91\x6f\xf8\x84\x21\x92\x42\x49\x01\x99\x9f\x8d\xfb\x0a\x90\x49\
+\x06\x15\x20\x93\x24\xaa\x40\x26\x79\x28\x50\xcf\x2a\x95\x4d\x10\
+\xdd\xf7\x0c\xa2\xb1\x78\x9f\x5b\x31\x93\x57\x2d\x28\x58\x86\xe9\
+\x32\xaa\xd7\x0b\xc7\x5c\x1b\x42\x4c\x70\x0e\x0b\xad\x8d\x17\x46\
+\x38\x87\xcd\x56\xe2\x47\x73\x1b\x2d\x9e\x6f\x37\x33\xd6\x5a\xd1\
+\xd8\xa1\x6b\xcd\xb7\x56\x4c\x0e\xe8\x5a\x83\x7e\x92\xc8\x24\x03\
+\x36\xcb\xcd\x6d\xc9\x4f\xc2\xcd\x4c\xd7\x88\x56\x52\x98\xd8\x99\
+\xdc\x0c\xeb\x3d\xf0\x63\x75\x91\x44\x22\x5b\x80\x02\x4d\x6d\x25\
+\xbc\x99\xe0\x2d\xed\xfa\xfe\x76\x7f\x9f\xe1\x5c\xd4\x67\x64\x56\
+\x6f\xf4\xb6\xcf\x6e\x2b\x3d\x4e\x5e\x7b\xbd\x19\xe1\xad\x66\x71\
+\x9f\xa8\xac\x08\x8b\xef\x4e\xf2\x74\x8f\xcb\x67\x8a\x4a\x73\x82\
+\x92\xcd\x8b\x3e\xf6\xe8\xbb\x8e\x73\x43\xd6\xc0\x57\xfa\x7e\x1e\
+\x2c\xba\x8a\xd5\xe7\x61\x5e\xf6\xa3\xea\x1e\xb0\x59\x9f\x09\xd0\
+\x66\x98\xed\x91\xc0\xf3\x48\xb8\xf2\x28\x6e\xac\xaf\xe5\x8f\x17\
+\x68\xe6\x6e\x87\x32\x96\x84\x86\x86\x34\x29\x2d\xd4\xac\xd3\x47\
+\x5f\x49\x1b\x05\x94\xc3\x2f\x19\xbd\x66\x10\xe4\xeb\xfb\x90\x24\
+\xfe\x5d\xf4\x03\x7e\x0e\xba\xd2\xf8\xc8\x47\x68\x08\xe3\xf0\x73\
+\x28\x8d\x67\x4c\xb9\x82\x8c\xca\xcc\x50\xe4\xb6\xa7\x9c\x9c\x42\
+\x7e\x35\xf5\x9b\xac\x69\x25\x60\x68\x2a\x7f\xe2\xb3\x43\xa5\x3a\
+\x25\x2d\xce\xf0\x2f\xfc\x4b\x1a\xee\x34\x7f\x97\x5a\xd9\x5c\xe3\
+\xe3\x4a\x2a\x3c\x96\x9a\x32\x10\xd5\xfe\xa4\x37\xb5\x7c\x7f\x17\
+\xc4\xd4\x2e\x1f\xd5\x61\x60\xab\xb7\x60\x8f\x18\xf8\x8c\xf4\xc0\
+\xe1\xeb\x0e\x62\x08\x4e\xf3\x1f\xbd\x55\x1a\x3c\xcc\x82\x8c\x77\
+\xc1\x4a\x48\xba\x81\xea\x67\xf6\xc7\x23\xcd\x1b\xb2\x8e\x6b\x3f\
+\x63\xb9\x77\x23\x28\xf1\x41\xd9\x5d\x6d\x88\x3f\x88\x52\x4b\x00\
+\xd1\x00\xaa\x54\xcf\x45\x63\x6a\x64\xdb\x5f\xe9\xe1\x68\x58\x1a\
+\xb4\x71\xaa\x8f\x71\x0d\xbd\x3f\x1e\x0c\xa9\x07\x5a\xeb\x54\x8d\
+\x3e\x0d\xbb\xf4\x90\xcd\xd3\xe5\x4f\xe6\x2a\x4f\x6d\xab\x11\xa0\
+\xa6\xeb\x53\xe7\xc7\x03\xe6\xc6\xbd\xa1\xe6\xc7\x03\xe6\xc6\x66\
+\x3f\x66\xe4\xb8\xfd\x58\x67\x5e\xd5\xb4\xf1\x21\xa9\x53\x04\x26\
+\x05\x69\x22\x50\xa5\xd4\x54\x04\x23\xb3\x04\x06\xcf\x25\x80\xc2\
+\x3a\xab\x6d\x8e\x17\x51\xd2\x21\xc1\xd6\xac\xa4\x27\x92\xd9\x44\
+\x90\x6d\x88\x24\x10\x8d\x5a\xa0\x26\x63\x71\xf5\xf2\xf5\x5e\x8b\
+\x41\x42\x2d\xf0\x4b\xc6\xdc\x16\x39\xe1\xdc\x72\x94\xd9\x5c\xc1\
+\x42\xbf\x65\x17\x63\xcc\x71\xc9\xbf\xee\x64\xad\x0f\x5c\xee\x90\
+\xa9\x89\xbb\x0d\x3a\xab\xdc\x75\x5c\x24\xdc\xeb\x27\x07\xeb\x8c\
+\x6a\xc7\x13\x35\xd1\xea\xe1\x24\x9e\xa4\x99\x0f\x27\x7a\xa6\x19\
+\x4f\x27\x76\xa8\x35\x3d\x9c\xdc\xe6\xd4\x5c\xd2\x34\x71\x55\xd1\
+\xd3\xf3\xcf\x16\x9b\x95\x3b\x4e\x26\xb9\x2b\x07\x63\xdb\xe3\xa9\
+\x37\x74\xa7\x99\xcf\x16\x9d\x15\x45\x2b\x1c\xd8\x04\xa0\xf2\x67\
+\x92\x80\xe9\x1a\x58\x53\x01\x58\xd2\xec\xe7\x3e\x9c\x4a\xeb\x6c\
+\x1e\xf6\x5b\xe9\xa8\x4d\xe0\x37\x39\xca\x4b\x0a\xb2\x0d\x8d\x54\
+\x90\x2d\x4e\x07\x47\x1a\xa9\xf3\x69\x3f\x1f\x98\x80\x5a\x60\xaf\
+\xc9\x74\x0f\x42\x4e\x39\xb7\xc4\x67\x8b\xaf\x98\xe9\xb7\xec\x61\
+\x0e\x38\x4e\xf9\xb7\x39\x2e\x1a\xe4\xf3\xaa\xb8\xdb\x20\xb3\xcb\
+\x9d\x57\x9a\x79\x90\xef\xe5\xbb\x72\xcf\x5f\xb3\xfd\x8c\x54\xdb\
+\x7b\xfe\x68\xc6\xbb\x01\x77\xa1\x5e\x62\x3d\xd7\x7d\xa3\x06\xd7\
+\xfb\x92\x5d\xb0\x0c\xf3\x1f\x10\x73\x06\x83\x82\xba\x59\x10\x45\
+\x49\x12\x4b\x04\x9a\x5f\x25\xaa\xb9\x51\xf2\x73\xb8\xa2\x2c\xf4\
+\xcf\xd0\x07\xf2\xbe\x27\x69\x2a\x90\xae\x04\xc1\x45\xee\x7e\xd0\
+\x2b\x16\xcc\x2f\x3a\x04\x40\x6d\x53\xbc\x98\xc5\xba\xea\xdf\xe6\
+\xfd\x2c\x51\x62\x59\x4c\xb3\x7d\x1d\x4c\x86\xf9\xcd\xe3\xaa\x90\
+\x6a\x62\xc6\xa1\xbc\x1b\xa2\xa1\x8c\xa4\xda\x06\xe2\x1d\x96\x32\
+\xa7\x51\x2f\xfe\xb8\x0a\xf1\x56\xfa\x90\x6f\x3f\xa0\x09\x33\x29\
+\x71\x37\xc8\x40\x2c\x2d\x31\xe8\x6d\xa3\xae\x1d\x86\xa7\xdb\xf6\
+\xeb\x68\x95\x4e\x17\x1b\xb6\xc5\x74\x23\x11\x51\x70\x08\x0d\x04\
+\xca\x7c\x85\xaa\x42\x03\x1f\xd7\x88\x30\xbb\x90\xad\x6f\xe0\x88\
+\xd8\x35\xec\x3c\xb9\x6c\xd6\xdf\x21\x2c\xaf\xa3\x74\x08\x2e\xfa\
+\x89\x75\x2f\xd5\xeb\x28\xfa\xac\x99\x80\x74\xbd\x78\x8d\x26\x90\
+\x36\x4e\xc6\xf0\xff\x52\xe4\x57\x76\x24\x96\x1b\x47\x56\x30\x07\
+\xda\x31\xa0\x1d\x7b\xf0\x7f\x7a\x2a\x05\xbc\xdb\x70\x85\x9d\x01\
+\x8f\x00\xfc\x8f\x02\x9e\xa3\xa0\x6a\xd1\xbf\xf7\x5e\xa8\xb0\x32\
+\xc4\xbb\x52\x46\x6d\xe3\x5d\x6d\xfe\x28\xe3\x30\x84\x3b\x4a\x66\
+\x25\xda\x89\x82\xdd\xab\x06\x24\x6d\x3b\x96\x56\xea\x11\x49\x07\
+\x62\xbe\x6d\xbd\xde\x5a\x89\x05\x74\xd4\x1a\x8e\x8c\x24\x68\xf1\
+\xc8\x4c\x81\x21\x1c\x09\x56\x2d\xaf\x74\x39\x03\x92\x8e\xc4\xf2\
+\x6a\xb2\x55\x79\x0d\x6e\xcf\x1a\x72\x60\xe2\x84\x60\xc6\xcb\x4d\
+\xd5\x05\xc5\xd5\xd7\x0e\x03\xb0\xbf\x8c\x31\x71\xbd\x79\x21\x5f\
+\x66\xa4\xe8\xfe\x4c\x83\xdd\x0e\x93\xbf\xd9\x90\x93\x3f\xb2\x90\
+\xa9\x48\xa5\x60\xc4\x01\x59\x8c\x31\xdd\x23\x34\x41\xd4\xbf\xaf\
+\x52\x73\xcb\xd2\xb4\xa9\x2d\x0e\xba\x40\x6d\x65\x8a\x7c\x13\x93\
+\x5d\xe6\xbf\x4a\x71\x20\xb6\xba\xe5\x42\x61\x33\x2d\x5f\x42\x33\
+\xbf\xec\x62\x46\x21\x6b\xd5\xbd\x13\xf5\x5f\xfa\x2e\xbb\xbe\x13\
+\x1d\x7c\xf9\xb7\x99\x25\x67\xe8\x5c\x5e\x5e\x9a\xb5\xda\x48\x36\
+\x76\x6e\x0e\x39\xd2\xe4\x3f\xf6\x72\x6a\xc5\x48\x41\x3d\xf2\x27\
+\x3b\xbc\x31\xf9\x26\xce\x3f\x62\xed\xff\x05\xb3\xf4\x9e\x4c\
+\x00\x00\x00\xce\
+\x00\
+\x00\x01\x10\x78\x9c\x2d\x8e\xdd\x8a\x02\x31\x0c\x85\xef\x05\xdf\
+\x21\x74\xaf\x9b\x26\x69\x3b\xb5\x32\xf5\x42\xdc\x07\x59\xfc\x99\
+\x0e\x8c\xab\xac\xc5\x8a\x4f\xbf\x1d\xf5\x83\x84\x70\x72\x38\x9c\
+\xfe\x76\x1f\x20\x1f\xc7\x21\x97\xa4\xac\x90\x82\xfb\x78\xac\xdb\
+\xcb\x23\x29\x02\x82\xa6\xc0\x4b\xad\xe3\xa1\xe4\x8f\xe3\x71\x9e\
+\x7e\x6f\x49\xe5\x52\xae\x6b\x63\x6a\xad\x58\x2d\x5e\xfe\x06\x23\
+\x44\x64\x5a\xa0\xda\x2c\x17\xd0\xe8\xaf\x3f\x25\xc3\x21\xa9\xb3\
+\x84\x88\xc4\xde\x75\x20\xce\xa2\x17\x9f\xb5\xd8\x80\x71\x26\xec\
+\xb5\x30\x3a\x20\x6d\x05\x99\x66\x58\x8b\xc7\xa8\x39\x68\xc7\x13\
+\xf3\xea\x63\xd4\xcc\x71\x1f\xd1\xe9\x36\x2d\x08\xbb\xd7\x61\x2d\
+\x46\xa0\x66\x8b\x30\xff\xd9\xa3\x40\x5b\x0c\x0e\x3d\x38\xd6\xdc\
+\xb5\xbf\xe3\xa7\x7a\x97\x7a\x73\x1a\xa7\x29\xa9\xaf\xef\xb0\xdd\
+\x79\xa7\x4c\x2b\xdc\xcf\xcd\x37\xff\xdd\x7f\x3f\xf3\
+\x00\x00\x00\xb4\
+\x00\
+\x00\x00\xfb\x78\x9c\x2d\x4e\xed\x0a\x83\x30\x0c\xfc\x3f\xd8\x3b\
+\x84\xec\x77\x6d\xac\x1f\xc8\xb0\x82\x1b\xf3\x3d\xc6\x74\xb6\xa0\
+\x53\x66\xb1\xb2\xa7\x5f\x5b\x3d\x02\x21\x77\xc9\xe5\xca\x65\xed\
+\x41\x75\xba\x57\x46\x62\x5e\x14\x08\xab\xee\xec\x6d\xda\x24\x12\
+\x10\x38\x06\x02\x6b\x75\x6b\xd4\xb1\xb1\x8d\xc3\x67\x91\xa8\x8c\
+\x99\xaf\x9c\x5b\x6b\x23\x9b\x44\xd3\xb7\xe7\x82\x88\xb8\x33\xc4\
+\xea\x7c\x02\x87\x72\x7e\x1a\x05\xad\xc4\x31\x13\x04\xb1\x20\xc5\
+\x92\x4c\xbc\x98\xc8\xa3\x0c\x88\xa5\x05\x88\x38\xca\x7c\x4f\x8b\
+\xd5\x2b\x04\x41\xf2\x2c\x04\xd6\x95\xf2\xc2\x7e\xe1\x26\x76\x68\
+\xee\x68\x0d\x66\x14\xdc\xd8\x61\xb4\xd7\x0f\xf7\xff\x3b\xde\x7a\
+\x18\x24\x5e\x9a\xa6\xae\xef\x0f\xe4\x2e\x5b\xe9\x43\x56\x7f\x18\
+\x95\x3c\x7c\
+\x00\x00\x00\xab\
+\x00\
+\x00\x00\xe5\x78\x9c\x2d\x4e\xdb\x0a\x83\x30\x0c\x7d\x1f\xec\x1f\
+\x42\xf6\xdc\x36\xd6\x0b\x65\x58\xa1\xfe\xc9\x50\x67\x85\x3a\x65\
+\x16\x2b\xfb\xfa\xd5\x4b\x38\x10\x38\x97\xe4\x94\xcb\xda\x83\xed\
+\x86\xde\x7a\x8d\x85\x52\x08\xeb\xd0\x85\x7a\xda\x34\x12\x10\x44\
+\x06\x0e\x36\x0c\xad\xb7\x97\x63\x1b\xdd\x67\xd1\x68\xbd\x9f\x9f\
+\x42\x84\x10\x78\x48\xf9\xf4\xed\x85\x24\x22\x11\x0f\x62\x75\xbf\
+\x41\x9c\x72\x7e\x79\x0b\xad\xc6\x31\x97\x04\x89\x24\xcb\xd2\x5c\
+\x36\x4c\x16\x3c\x07\x62\x99\x02\x99\xf0\x7c\xdf\x99\x5a\x77\x85\
+\xe0\x90\x76\x16\x0e\x36\xc2\x65\x14\xad\x44\x0d\x1d\x39\x76\x45\
+\x4e\xfc\xf0\xfc\x74\xce\x7b\x70\x4e\xe3\xc3\x28\x63\x4c\x8d\x22\
+\xb6\x28\xf7\x3a\xd5\x1f\x18\xcb\x37\xc4\
+\x00\x00\x00\x9f\
+\x00\
+\x00\x00\xd0\x78\x9c\x35\x8d\xe1\x0a\x83\x30\x0c\x84\xff\x0f\xf6\
+\x0e\x21\xfb\xdd\x35\xb5\x43\xc7\xb0\x82\x1b\xf3\x3d\xc6\x74\xb6\
+\xa0\x53\x66\xb1\xb2\xa7\x5f\x26\x35\x70\xe4\xcb\x11\xee\xf2\x69\
+\x6e\xc1\x36\xae\xb5\xde\x60\xa6\x53\x84\xd9\x35\xe1\x3a\x2c\x06\
+\x09\x08\xd8\x81\xd5\x0d\xae\xf6\x36\x7e\x2c\x7d\xf7\x9e\x0c\x5a\
+\xef\xc7\x8b\x94\x21\x84\x63\xd0\xc7\xe1\xd3\xca\x84\x88\x24\x07\
+\x62\xb1\xdf\x01\x4f\x3e\x3e\xbc\x85\xda\x60\xaf\xd3\x33\xa8\x84\
+\x9e\x42\xe9\x0c\x48\x24\x27\x3e\x95\x5a\x37\x6b\x62\x86\xc8\x9b\
+\x44\xf4\x44\x64\xb1\x31\xeb\x8b\xf0\x72\x5d\x67\xf0\x50\x55\x65\
+\x79\xbb\xa3\xe4\xc2\xfc\xdf\x5c\xfc\x00\x9e\xb9\x33\xe1\
+\x00\x00\x00\xad\
+\x00\
+\x00\x00\xe5\x78\x9c\x2d\x4e\xdb\x0a\x83\x30\x0c\x7d\x1f\xec\x1f\
+\x42\xf6\xac\x8d\x55\x47\x19\x56\x70\x63\xfe\xc7\x50\x67\x0b\x75\
+\xca\x2c\x56\xf6\xf5\x6b\xd5\x70\x20\x70\x2e\xc9\x29\xe6\xa5\x07\
+\xd5\xe9\x5e\x59\x89\x57\x21\x10\x16\xdd\xb9\xfb\xb8\x4a\x24\x20\
+\xf0\x0c\x6c\xac\xd3\xad\x55\x87\x63\x1d\xcc\x67\x96\xa8\xac\x9d\
+\x6e\x8c\x39\xe7\x62\x97\xc6\xe3\xb7\x67\x9c\x88\x98\x3f\x88\xe5\
+\xf9\x04\x7e\x8a\xe9\x65\x15\xb4\x12\x87\x9c\x13\x24\x9c\x54\x94\
+\xe6\xbc\x89\xf8\x35\xce\x81\xa2\x4c\x00\x4f\xe2\x3c\xec\x4c\x2c\
+\x41\x21\xd8\xa4\xc0\xc2\xc6\x7a\x98\x8c\xbc\x95\xa8\xa1\x2d\x17\
+\x1d\x91\x1d\x3f\xdc\x3f\xed\xf3\xd6\xc6\x48\xbc\xd4\x75\x55\x3d\
+\x9e\xc8\x7c\x8b\x22\xd4\x29\xff\x1a\x3e\x37\xdc\
+\x00\x00\x00\x9c\
+\x00\
+\x00\x00\xd0\x78\x9c\x35\x8d\xe1\x0a\x83\x30\x0c\x84\xff\x0f\xf6\
+\x0e\x21\xfb\xdd\x35\xb5\x43\x65\x58\xa1\xbe\xc9\x98\xce\x16\x74\
+\xca\x2c\x56\xf6\xf4\xcb\xa4\x06\x8e\x7c\x39\xc2\x5d\xb5\xac\x3d\
+\xb8\xce\xf7\x2e\x18\x2c\x74\x8e\xb0\xfa\x2e\x36\xd3\x66\x90\x80\
+\x80\x1d\xd8\xdd\xe8\xdb\xe0\xd2\xc7\x36\x0e\xef\xc5\xa0\x0b\x61\
+\xbe\x4b\x19\x63\xbc\x46\x7d\x9d\x3e\xbd\xcc\x88\x48\x72\x20\xd6\
+\xe7\x13\xf0\x54\xf3\x23\x38\x68\x0d\x8e\x3a\x2f\x41\x65\xf4\x14\
+\x4a\x17\x40\x22\xbb\xf1\xa9\xd4\xbe\x59\x0b\x33\x24\x3e\x24\x92\
+\x27\x12\x8b\x83\x59\x5f\x84\x97\x1f\x06\x83\x17\x5b\x5a\x6b\x1b\
+\x94\x5c\x58\xfd\x9b\xeb\x1f\x9d\x46\x33\xc9\
+\x00\x00\x00\xb2\
+\x00\
+\x00\x00\xfb\x78\x9c\x2d\x4e\xd1\x0a\x83\x30\x0c\x7c\x1f\xec\x1f\
+\x42\xf6\x5c\x1b\xab\x1d\x65\x58\xa1\xfe\xc9\x98\xce\x0a\x3a\x65\
+\x16\x2b\xfb\xfa\xb5\xd5\x23\x10\x72\x97\x5c\xae\x5a\xb7\x1e\x6c\
+\x37\xf4\xd6\x69\xbc\x2b\x85\xb0\x0d\x9d\x6f\xe6\x5d\x23\x01\x41\
+\x60\x20\xb1\x7e\x68\x9d\x3d\x37\xf6\x69\xfc\xac\x1a\xad\x73\xcb\
+\x83\x73\xef\x7d\xe6\x8b\x6c\xfe\xf6\x5c\x10\x11\x0f\x86\x58\x5f\
+\x2f\x10\x50\x2d\x4f\x67\xa1\xd5\x38\x49\x41\x90\x0b\xb2\xac\x90\
+\xe2\xc5\xc4\x3d\x93\x40\xac\x54\x20\xf2\x4c\xc6\x5e\xaa\x2d\x2a\
+\x04\x49\x8a\x2c\x24\x36\x94\x8d\xc2\x71\x11\x26\x76\x6a\xe1\x68\
+\x4b\x66\x94\xdc\xd8\x69\x74\xd4\x0f\x8f\xff\x07\xde\xc3\x38\x6a\
+\xbc\x19\x65\x8c\x69\x90\x87\x6c\x55\x0c\x59\xff\x01\x17\x22\x3c\
+\x64\
+"
+
+qt_resource_name = b"\
+\x00\x0b\
+\x0c\x6b\x3c\xf3\
+\x00\x73\
+\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x73\
+\x00\x11\
+\x0a\xf7\x1a\xc3\
+\x00\x43\
+\x00\x68\x00\x69\x00\x6c\x00\x64\x00\x4f\x00\x66\x00\x4d\x00\x65\x00\x74\x00\x72\x00\x6f\x00\x70\x00\x6f\x00\x6c\x00\x69\x00\x73\
+\
+\x00\x0d\
+\x02\x0d\x3c\x07\
+\x00\x64\
+\x00\x72\x00\x6f\x00\x70\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0d\
+\x02\x33\xbc\x47\
+\x00\x73\
+\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0e\
+\x03\xc2\xd5\xc3\
+\x00\x73\
+\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x2e\x00\x71\x00\x73\x00\x73\
+\x00\x0b\
+\x04\x37\x88\x27\
+\x00\x73\
+\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x75\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x08\x8b\x0b\xa7\
+\x00\x73\
+\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x18\
+\x08\xb9\x19\xc7\
+\x00\x68\
+\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
+\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\x2d\x1b\xc7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x0d\xb0\xb1\xa7\
+\x00\x68\
+\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x13\
+\x0d\xf4\xfe\xa7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+\x00\x13\
+\x0f\xf8\x57\x27\
+\x00\x73\
+\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
+\x00\x00\x00\x44\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x00\xc2\
+\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\x83\
+\x00\x00\x00\xa6\x00\x01\x00\x00\x00\x01\x00\x00\x0d\xf7\
+\x00\x00\x00\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xc9\
+\x00\x00\x00\xdc\x00\x01\x00\x00\x00\x01\x00\x00\x0f\x81\
+\x00\x00\x01\x12\x00\x01\x00\x00\x00\x01\x00\x00\x10\x30\
+\x00\x00\x01\x2c\x00\x01\x00\x00\x00\x01\x00\x00\x10\xd3\
+\x00\x00\x01\x50\x00\x01\x00\x00\x00\x01\x00\x00\x11\x84\
+\x00\x00\x01\x7c\x00\x01\x00\x00\x00\x01\x00\x00\x12\x24\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x44\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x86\xbc\x9a\x01\x50\
+\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x00\xc2\
+\x00\x00\x01\x86\xbc\x9a\x01\x53\
+\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01\x83\
+\x00\x00\x01\x90\x54\xc2\x8c\xf4\
+\x00\x00\x00\xa6\x00\x01\x00\x00\x00\x01\x00\x00\x0d\xf7\
+\x00\x00\x01\x86\xbc\x9a\x01\x54\
+\x00\x00\x00\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xc9\
+\x00\x00\x01\x86\xbc\x9a\x01\x55\
+\x00\x00\x00\xdc\x00\x01\x00\x00\x00\x01\x00\x00\x0f\x81\
+\x00\x00\x01\x86\xbc\x9a\x01\x51\
+\x00\x00\x01\x12\x00\x01\x00\x00\x00\x01\x00\x00\x10\x30\
+\x00\x00\x01\x86\xbc\x9a\x01\x4f\
+\x00\x00\x01\x2c\x00\x01\x00\x00\x00\x01\x00\x00\x10\xd3\
+\x00\x00\x01\x86\xbc\x9a\x01\x52\
+\x00\x00\x01\x50\x00\x01\x00\x00\x00\x01\x00\x00\x11\x84\
+\x00\x00\x01\x86\xbc\x9a\x01\x4e\
+\x00\x00\x01\x7c\x00\x01\x00\x00\x00\x01\x00\x00\x12\x24\
+\x00\x00\x01\x86\xbc\x9a\x01\x54\
+"
+
+qt_version = [int(v) for v in QtCore.qVersion().split('.')]
+if qt_version < [5, 8, 0]:
+ rcc_version = 1
+ qt_resource_struct = qt_resource_struct_v1
+else:
+ rcc_version = 2
+ qt_resource_struct = qt_resource_struct_v2
+
+def qInitResources():
+ QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py
index a002fa4b9..23f429f45 100644
--- a/rare/resources/stylesheets/RareStyle/__init__.py
+++ b/rare/resources/stylesheets/RareStyle/__init__.py
@@ -1,484 +1,451 @@
-# -*- coding: utf-8 -*-
-
-# Resource object code
-#
-# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
-#
-# WARNING! All changes made in this file will be lost!
-
-from PyQt5 import QtCore
-
-qt_resource_data = b"\
-\x00\x00\x00\xf1\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x36\x34\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x34\x31\x20\x32\x33\x36\x2e\x34\x37\x35\x68\
-\x32\x33\x38\x63\x32\x31\x2e\x34\x20\x30\x20\x33\x32\x2e\x31\x20\
-\x32\x35\x2e\x39\x20\x31\x37\x20\x34\x31\x6c\x2d\x31\x31\x39\x20\
-\x31\x31\x39\x63\x2d\x39\x2e\x34\x20\x39\x2e\x34\x2d\x32\x34\x2e\
-\x36\x20\x39\x2e\x34\x2d\x33\x33\x2e\x39\x20\x30\x6c\x2d\x31\x31\
-\x39\x2e\x31\x2d\x31\x31\x39\x63\x2d\x31\x35\x2e\x31\x2d\x31\x35\
-\x2e\x31\x2d\x34\x2e\x34\x2d\x34\x31\x20\x31\x37\x2d\x34\x31\x7a\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\
-\x3d\x22\x23\x63\x63\x63\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\
-\x00\x00\x00\xf0\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x33\x32\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x34\x31\x20\x37\x36\x2e\x34\x37\x35\x68\x32\
-\x33\x38\x63\x32\x31\x2e\x34\x20\x30\x20\x33\x32\x2e\x31\x20\x32\
-\x35\x2e\x39\x20\x31\x37\x20\x34\x31\x6c\x2d\x31\x31\x39\x20\x31\
-\x31\x39\x63\x2d\x39\x2e\x34\x20\x39\x2e\x34\x2d\x32\x34\x2e\x36\
-\x20\x39\x2e\x34\x2d\x33\x33\x2e\x39\x20\x30\x6c\x2d\x31\x31\x39\
-\x2e\x31\x2d\x31\x31\x39\x63\x2d\x31\x35\x2e\x31\x2d\x31\x35\x2e\
-\x31\x2d\x34\x2e\x34\x2d\x34\x31\x20\x31\x37\x2d\x34\x31\x7a\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\
-\x22\x23\x63\x63\x63\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x0c\x90\
-\x00\
-\x00\x4a\x9e\x78\x9c\xcd\x1c\xdb\x6e\xdb\x38\xf6\xdd\x5f\xc1\x4d\
-\x50\xa0\xc9\x5a\xb5\x2c\xcb\x76\xa2\xa0\x0f\x93\xce\xee\xec\x02\
-\x33\xd8\xe9\x24\xd8\x79\x28\xfa\x20\x5b\x4c\x2c\x54\x96\x5c\x49\
-\x6e\xda\x19\xe4\xdf\xf7\xf0\x26\x91\x14\xa9\x8b\xed\x74\x27\x45\
-\x1d\x9b\x3c\xe4\xb9\xf0\xdc\x45\x67\x72\x39\xfa\x70\x8f\xbf\x96\
-\x1f\x47\x69\x96\x6f\xc3\x24\x40\xf0\x73\x8e\xe9\x0f\xca\x1f\x57\
-\xaf\xbd\xd9\xd5\x18\x89\x97\x0b\x32\x8b\x1c\x07\x6d\xc3\x38\x45\
-\x0f\x59\x5a\xa2\x75\x96\x64\xf9\x28\x8a\x8b\x70\x95\xe0\x08\x96\
-\x9f\xfb\x33\x7f\xe9\x47\x74\x31\x5a\x2c\xc7\x08\x2d\xa7\xe4\x65\
-\x59\x2d\x16\xc0\xf2\x06\xa8\xf1\x03\xeb\x43\x75\x83\x31\x9a\xcf\
-\x5f\x5d\xa0\xb7\x6f\xd9\xde\x73\x18\x9d\xfb\xf0\xff\xfa\xa2\xe7\
-\x72\x4f\x5e\xee\xc3\xa8\x3f\x83\xff\xcb\x8b\xd1\x87\xdb\x70\xfd\
-\xe9\x31\xcf\xf6\x69\xa4\x0a\xc2\x73\x3d\xcf\x9b\xb3\x05\x33\x0f\
-\xb6\x99\xf9\xe4\x65\xa9\x0a\x62\x55\xad\xe6\xdc\xe0\x28\x2e\x09\
-\x8b\x44\x1c\xde\xd2\x5b\xce\x66\x7c\x8b\x2b\xb2\x9a\xbc\xcc\xa7\
-\xd5\x16\xfa\x6a\x10\x4b\x8e\x72\x1c\xae\xcb\xf8\x0b\x9e\x88\xad\
-\xd0\x53\x1c\x3d\xe2\xb2\x40\xaf\xc9\x71\xfd\x03\x46\x8b\x31\xfa\
-\x35\xcf\x1e\x73\x5c\x14\xb7\x61\x5e\x20\x5c\xae\x2f\x46\x9b\xec\
-\x0b\xce\x29\xed\x80\x19\x7e\x2a\xcc\xbe\x20\xbe\x0d\xf3\xd3\x06\
-\xa7\x88\x6e\x11\xa7\x8f\x88\xfc\xae\x08\xa9\xf1\xdf\xee\xcb\x32\
-\x4b\x01\xfb\xbf\x70\x18\xe1\xbc\xb8\x18\x15\x38\xc1\x00\x94\xa5\
-\x01\x61\xd7\xf7\x7c\x8f\x23\xbd\x06\x7c\x8b\x05\x7d\x69\x67\x97\
-\xed\x20\xf3\x39\x0a\x93\x12\xe7\x69\x58\x62\xb2\xe9\x95\x17\x7a\
-\x98\x9f\x9b\x0b\xfb\xf9\xe4\x2c\xfc\x8e\x4d\xc5\x0e\x84\x97\x3c\
-\x7b\x2a\x10\x1c\xd5\xcf\x71\x51\x4e\xee\x73\x8c\x27\xf7\x04\xdb\
-\x7f\x63\x0c\xe3\x61\x1a\xd1\x05\x77\xeb\x3c\x4b\x12\x22\xcc\x11\
-\xa8\x44\x96\x03\x77\xaa\x3a\xf8\x57\xb3\xe8\x6a\xc5\xe8\x58\x12\
-\x12\x16\xa0\x44\xd3\xd9\x75\x4d\x07\x5d\x24\xd1\xb0\xcd\x8a\xb2\
-\x62\xc9\xa6\xa5\xf2\x56\xba\x96\xc2\x14\xe1\x78\x31\xbb\x50\xb5\
-\xea\xc1\x87\x7f\x1c\x86\x2a\xf9\x35\x7d\xb1\x53\x32\x54\x91\xe2\
-\xc7\x4d\x02\xff\x4b\x10\xff\xdc\xf3\x17\xa1\xcb\x90\x5d\x11\x5a\
-\x97\x40\xd1\x74\xe1\xda\x91\x45\x79\xb6\x8b\xb2\xa7\x54\x20\x1b\
-\xa3\x10\xad\xe2\x12\xd1\x1d\x01\xb2\xdc\x84\xa9\x58\xc5\xc4\x94\
-\x63\x50\x82\x5d\x98\x87\x44\x8f\x86\xf9\x13\x69\x9f\xca\xb5\x98\
-\xb4\x68\xb6\x9e\x3d\xf8\x53\xbe\x11\xd1\xa2\xc5\x8c\xbc\xcc\xed\
-\x6c\x3c\xe6\x61\x14\x63\x70\x52\xb5\x7e\x15\x28\xab\xb8\x02\x76\
-\x3e\x61\x04\x8a\xc4\x54\xe8\xd7\x6c\xb7\xdf\x11\xd5\xb9\xdb\xe1\
-\x75\x1c\x26\x1f\x47\x71\x5a\x94\x61\x92\x38\x92\x0e\xa1\x73\x77\
-\xc9\x45\x89\x88\x14\xa7\xe4\xdc\x10\x15\x25\x50\xc0\x17\x54\x0b\
-\x25\x73\x86\x85\x73\x69\x21\xba\x9a\xb7\x2d\x94\x04\x08\x0b\x3d\
-\x79\x21\xf5\x02\x8d\x85\xfb\xb4\x49\xec\xf9\xd2\x65\x0b\x05\x95\
-\xf2\xc2\x6a\x81\xb4\xb4\x26\xf7\x7c\xee\x0a\x85\x99\xf7\x5a\x5a\
-\x13\x0c\x4e\xd7\x95\x9c\x96\x6d\xe9\xe5\x64\x34\x1a\x5d\xa2\x3f\
-\xa9\x55\xd1\x23\x0b\x0c\x01\xeb\x86\x4e\xb3\x83\x75\x24\x28\xd5\
-\x7c\x39\x54\x75\xc8\x0a\xa4\xe2\xf7\x6f\x46\xcf\xa3\xcb\x40\x10\
-\x3b\x86\xf7\x95\x55\x56\xba\xd7\x20\x49\x55\x5b\x2b\x49\x26\xa8\
-\x9e\x24\x8d\xde\xff\x1c\xae\x70\x32\xe6\xbf\x75\x5a\x38\x32\x50\
-\xdb\x72\x13\x20\x77\xf7\xd5\xb6\x7b\x99\x87\x69\x01\x56\x08\x3a\
-\xcf\x40\x76\x61\x14\x81\xff\x94\x16\x55\xce\xde\xb1\x11\x27\x7b\
-\x7d\x46\xdc\x2f\x38\xdd\x13\xda\xc0\xf9\x12\x8f\x2b\xbd\x0d\x82\
-\xb8\xc4\x5b\x18\x20\x3e\x99\xcf\x89\xb7\xf5\x9c\x70\xd5\xf2\xfb\
-\x6a\x96\x85\x21\x36\x54\x30\xd2\x64\x38\xc4\xde\xbe\xcb\xf2\x14\
-\xe7\x2c\x76\xc9\x70\xff\xcc\xc3\x2d\xfe\xf0\x40\x5e\xef\x36\xe1\
-\x0e\xbf\x3d\x5b\x9c\x7d\x84\xf1\x9f\x80\xb1\xdd\x6d\xf6\x95\xd2\
-\x9a\x62\xe2\x27\xc9\xae\xdc\x65\x92\xb7\xf1\x56\x8c\xfe\x08\xfe\
-\x45\x7a\x2b\xcd\xdc\x67\x59\xc2\x36\x79\x97\x6d\x57\x99\xfa\xb6\
-\x52\x1d\x69\x0c\xbd\xff\x61\x55\xc0\x29\xac\xcb\x7f\x03\x77\x9c\
-\xe7\xbb\x5d\x9c\xb2\xa5\x3f\x66\x7b\x80\xaf\x3f\x4b\x7e\x9b\xc0\
-\x89\xf8\x65\x3c\xf6\x69\x75\xec\x6c\xb8\x28\xbf\x91\x58\x52\x64\
-\x49\x1c\x29\x13\xc4\xe9\xed\x8b\x00\x79\x62\x41\xa5\x04\x74\x84\
-\x1c\xe8\x71\x32\x3f\x42\xa0\xdf\x5b\x76\xb2\x62\x2b\x71\xb6\xdd\
-\x3e\xe5\x3c\xef\x70\xb3\x39\x81\x9c\x06\x4b\xe0\x07\x48\xf8\xc8\
-\xd4\xbe\xd8\xb0\x83\xe3\xf2\xd8\xc6\xa9\xb3\xc1\x2c\x21\x98\xbd\
-\x71\x5d\xcc\x75\x63\x72\xa9\x4c\x4d\xdf\xcc\x5c\xbc\xbd\x41\xe0\
-\x9d\x4d\xb3\x57\xa0\x40\x64\xee\x99\x9b\xc6\x41\x18\xa6\x6d\x18\
-\xe6\x15\x06\x93\x6d\xbb\x67\x1f\xed\x2e\xf1\xd9\xe2\x0d\xd4\x15\
-\xc2\x3a\x7c\xbe\xa4\xd2\xbe\x3f\xdb\x34\x42\x2a\x56\x94\x55\x0d\
-\x4f\x6d\x5e\x2e\x15\x2b\xea\xf2\xbf\x55\xe1\x87\xc6\xde\xf6\x5d\
-\x94\x22\x80\x45\x32\xea\x44\x03\xa6\x9c\x24\x9e\xb5\x18\x13\xdf\
-\x7b\xb8\x22\x03\x16\x92\x0f\x3a\x24\x21\x1c\x2b\x9f\x24\x2b\x86\
-\xe1\xfd\xce\x59\x51\x85\x60\x40\x30\xcf\x3f\x0b\xcc\xfb\xd5\x1a\
-\x2a\x46\xd0\x52\x27\xcb\xe3\xc7\x18\xca\x0d\x76\x26\x37\x27\xf5\
-\x76\x7c\xbc\x04\x1a\x13\xfc\x50\x56\x00\xae\x06\xb0\xca\x80\xb6\
-\xad\x01\x46\xe5\x58\x49\x16\x0c\xac\xab\xf3\x95\x0c\xb4\x65\xb5\
-\x30\x2c\xb1\x7d\x70\x22\xa1\x84\x7a\x95\xe4\xa6\xbc\x77\x59\x11\
-\xb3\x02\x0f\xc4\x82\x72\x62\x6b\x83\x32\x2b\x06\x45\x45\x25\x83\
-\x2a\xc5\xc4\x0d\xb1\x65\x43\x69\x25\x6a\x06\x6a\xd4\x87\x6b\xcf\
-\x51\x0e\x5d\x29\x17\x7a\xea\x34\xc7\x2b\xf4\xd1\x17\xea\x13\x6f\
-\xc3\x47\xd0\xc4\x7d\x9e\xbc\x3e\x0b\x26\x54\x2f\x8b\x0d\x86\x72\
-\x62\xf2\x1b\x9c\xc6\x1d\xf9\x3c\xa9\x76\x7b\x53\x7c\x79\x3c\x13\
-\x18\xbb\x58\x94\x51\x11\x61\x4e\x17\xe8\xef\xc8\xbb\x04\x53\x50\
-\x8c\x03\xbd\xa5\x6e\x52\x84\x75\x80\x99\xd1\x4f\x39\xad\x74\x58\
-\x0d\x24\x84\x5d\xa1\xec\xa7\x13\x04\xab\x18\x47\x61\x09\x75\x1e\
-\xae\x67\x21\x25\x26\xf9\x80\xf0\xdc\xaa\x19\x09\xda\xfb\xcb\xa8\
-\xc8\xf2\xd2\xd9\xef\x14\x09\xb5\x3a\x8d\x9a\x60\x86\xd3\x42\xb3\
-\x3c\x69\x26\x99\xb8\x86\x03\xe9\x55\xcf\x54\x09\xc1\x9c\xe0\x66\
-\xc6\x5d\x42\xec\x77\x42\x30\x03\xa0\x7c\x0d\x67\x44\x1c\xde\xb3\
-\xb2\x34\x08\xd6\x9b\x7d\xfa\xc9\xba\x83\x25\xff\xe7\x9f\xbd\x57\
-\xec\xe3\x36\xcc\xa9\x53\x6d\xa9\x0f\x6c\x99\x8a\x25\x7b\x52\x62\
-\xa5\x42\xda\xb4\x03\x87\xd2\xe5\xa1\xec\x56\x28\x02\x88\x73\x65\
-\xbc\x0e\x13\x4d\xeb\xa7\x3c\x20\xd7\x80\x1b\x08\x13\x7f\xc0\xe1\
-\x57\xa0\x55\x96\xd0\x84\x0d\x80\x32\x27\x81\x84\xab\xda\x7e\xac\
-\x4c\x83\x1e\xb5\x4d\x57\xab\x6b\x9c\x96\xf5\x0d\xa2\x98\xac\x02\
-\x94\x66\x29\xbe\x51\xc8\x34\x1c\x44\xc3\x6f\xb7\xb2\xd0\x61\xb4\
-\x37\xb6\xb0\xca\x34\x41\xdf\xbe\x21\x82\x6e\x13\x1b\x88\xc1\x20\
-\xc5\x36\x1c\x52\x1c\x1a\xce\x44\x3f\x14\x24\x64\x0d\xc4\xb0\x09\
-\xd3\xa8\xf2\xfe\x07\x26\x25\x07\x76\x2a\x9a\x65\x87\x2d\xc9\x51\
-\x92\x6d\x57\x1e\xe5\xa4\xce\xdc\x66\xad\x67\xf4\x2f\xcf\xc6\x6a\
-\xb0\x29\xde\xa6\x57\x62\xe2\xa3\x59\x41\x73\x34\xe7\x96\xda\x82\
-\x42\x53\x43\x2b\x02\xd0\xf4\xe6\x20\xd3\xcf\x76\x04\x35\x0f\xc1\
-\x43\x9c\x17\xa5\x28\x54\x64\xba\xfb\x10\x68\x5a\x4d\x89\x12\x8b\
-\xa5\xc6\x88\xdc\x07\xa9\xca\x69\xb6\x32\xdb\x97\x54\x73\x91\xcb\
-\x38\x79\xcc\xe3\x88\x0c\xb4\x39\x4e\xaa\xb9\x9b\xec\xc9\x89\x30\
-\x84\x32\xda\x5c\x75\x44\xb6\x5f\x6d\xd4\x96\xd2\x37\x3a\x42\xfd\
-\x5a\x52\x04\xb2\xea\xbd\xda\x2a\x85\x86\x93\xaf\x25\x81\x94\xe2\
-\x97\xcb\x44\x1d\xac\x9b\x0d\x62\xd4\xa2\x9f\x2d\xdd\x26\x36\xa0\
-\x9e\x8c\xaa\x79\x90\x1c\xdc\x43\x12\xc3\x4e\x10\xe4\xb4\x25\x49\
-\x52\x5c\x40\xa2\x50\x86\xeb\x0d\x49\x9f\xca\x8c\xa6\x39\xb2\x9d\
-\x40\xba\x30\xb9\x94\x48\xfc\xb0\xde\xe7\x44\x82\xef\xb2\x64\xbf\
-\x4d\x69\x19\x6a\xc2\xac\x6a\x54\x63\xf5\x6f\xd9\x93\x75\xa9\xac\
-\x4e\x80\x5d\xe3\x98\x15\x87\x0d\xbe\xeb\x61\xb5\xa9\xa6\xd6\x92\
-\x47\x79\x24\xbd\xe2\xd4\x09\x93\x2a\x4f\x8d\x36\x79\x46\x23\x4f\
-\x4c\x9d\x84\xc2\x66\x32\x53\xf7\x3e\xc6\x86\x36\x45\xcf\x02\xbf\
-\xde\x44\xaa\xe4\xa4\xdd\x0e\x2c\xfc\xa5\x6d\xab\xc3\xab\xf7\x14\
-\x43\x66\x67\x36\xbc\x3f\xd0\x25\x8a\x17\xe9\x2f\x4a\x23\xdc\x22\
-\x16\xfa\x30\x37\xd1\x85\x30\x51\x45\x2e\x01\x98\xe8\xde\x89\xd3\
-\x08\x5c\x6f\x99\x69\x12\xd2\x26\x3b\xb3\x8b\x2a\xe1\xb6\xa4\x00\
-\x9c\x22\x36\xcf\xa8\x75\xf4\x4e\x02\x17\x04\xcb\xef\xa8\x79\x2a\
-\xed\xe5\x77\x1b\xbc\xfe\xc4\xde\xfe\x06\x92\xc9\x3a\xb4\x4d\xcf\
-\xff\xc4\x4e\x60\x1b\x12\xcb\x62\x53\x75\x54\xda\x5f\x9d\x90\xac\
-\x52\x96\x5b\x6d\x91\xf2\xa8\x64\x8d\x9a\x1c\x7b\xd6\xd8\x43\xd5\
-\xa6\xe7\x43\x90\xbf\x94\x28\x94\xaa\xc4\x58\x7b\x18\xa8\xb5\x25\
-\x58\x06\x50\xd9\xab\x18\x38\x94\xa7\xcd\xac\xca\x10\x06\x9e\x15\
-\xaf\xd5\x64\x5e\x99\x36\x48\x61\x78\x97\xea\xd9\x46\xa8\xb9\xa4\
-\x9c\xbf\x1a\x7c\xe4\xa7\x55\x72\xc5\x8b\x59\xce\x68\x4d\xe8\xb0\
-\x1e\x51\x3d\x6b\x92\x7f\x3d\x6b\x12\xbf\x34\x6b\x92\x3e\x9f\x6e\
-\xa1\x98\x8c\xf7\xea\x5a\x7c\xde\xc3\xfb\xba\x65\x61\xe4\x13\xde\
-\x61\xf0\x92\x50\x3e\x40\xb6\x67\xe1\x56\x87\x31\xf1\xac\xc3\x98\
-\x38\x6f\xc0\x98\xf8\x57\x80\x4e\x20\x85\x4d\x98\x3c\x38\x0d\x51\
-\x58\x0c\xab\x55\xf8\xf3\x57\xfd\xb1\xae\xe3\x7c\x9d\x74\xc9\x9e\
-\x63\xeb\xf2\x07\x06\xb0\x16\xad\xeb\xb2\x7e\x13\x58\x8b\x1e\xea\
-\xde\xa0\xbf\xe2\x55\xf7\x02\x86\x68\x60\x97\x2c\xac\xc0\x9d\x3a\
-\xd9\x25\x17\x3b\x70\xa7\x96\x1e\x22\x23\x49\x2d\x4d\x82\x6a\xd7\
-\xcf\x43\x10\x32\x8d\x34\xe0\xaa\x4f\x85\xef\x46\xee\xf6\x39\x4f\
-\x3c\xe6\xad\xb2\x24\xaa\x1f\xe6\x29\x65\xff\x9b\x39\x79\x98\x07\
-\xc3\xff\x79\x78\x28\x70\x29\xaa\x29\x32\xab\x75\x5d\x0f\x4d\x33\
-\xf5\xe6\x23\xaf\x95\xde\x78\x80\x58\x56\xa7\x0f\x54\x2e\x84\xaf\
-\xb7\x67\x65\xbe\xc7\xd5\x83\x3f\xa5\x8d\x40\xe9\xad\x9e\x5f\x76\
-\xb1\xdb\x88\xe4\x7c\x55\x10\x94\xe1\x6a\x2c\xab\x72\x19\x97\x55\
-\xd3\xa8\xe3\x41\x97\xb5\x07\x4f\x9b\x55\xb6\x16\xfc\x09\x24\xda\
-\x78\x24\xe6\x6b\x2b\x79\x2f\x9f\x66\xce\x56\xa0\x8e\x3a\xad\xd9\
-\x22\x86\xfc\x5e\x4d\x03\x03\xf4\x99\xf4\x3d\xe0\x58\xf8\xfd\xac\
-\xd7\x14\x80\xfc\x7c\x9d\x92\x04\x7c\x8c\xbe\xc1\x6f\x77\x5c\x0f\
-\x7b\x01\x42\x80\xe6\x1b\xfc\x9e\xd6\xc3\x05\x3b\x53\x03\x2d\x3a\
-\xcc\xd4\x90\x73\x72\x82\x85\x4c\x2d\x05\x5c\x7d\x81\xaf\xa1\x00\
-\xb2\x83\xd0\x34\xe1\x54\x4f\xf9\x4c\x45\xe4\xe8\xfd\x5d\xfc\x07\
-\xfe\x29\x8f\x77\xaa\xe5\xd7\x0d\x68\xae\x18\xbe\x9e\xbb\xfa\xa2\
-\xa1\x02\xee\xec\x77\x7a\x07\x2e\x08\x76\x61\x4a\xf4\xf6\x59\x19\
-\x04\xe6\x9c\x15\x7d\x1a\xc0\xc6\xeb\x27\x03\x9f\x77\x79\xb6\xc3\
-\x79\xf9\xcd\x89\xf2\xf0\xe9\x36\x2c\x58\x3f\xab\x02\xa3\x6b\x15\
-\xc3\xb3\x3e\xc7\x18\xda\x4d\xb5\x5f\x6e\xf2\xeb\x96\x8b\x20\x21\
-\x80\x63\x1f\xab\x23\xfc\xc1\x90\x92\xa3\x8b\x9e\x4d\xa3\x72\x15\
-\x5d\x24\xcf\xbc\xb5\xdc\x7a\xd1\x10\x1c\xd2\x7d\x69\x3e\x5f\x6d\
-\xf6\xed\xb8\x57\xa4\xb6\x69\xa9\x25\x35\x22\x55\x1a\xa4\xa7\x5e\
-\x33\xc3\xb3\xf2\x96\xc7\xa5\x4d\x0f\xd1\xbb\x57\xd3\x61\xea\x2e\
-\xb3\x74\x67\xaa\x9a\xba\xcb\x2c\xdd\x6a\xea\x0a\x7d\x3d\x4d\xfd\
-\xb9\x45\x19\x8c\x8f\x32\xbb\x84\x64\x3f\x47\x83\x90\x4c\x12\x1d\
-\x28\x24\xcf\x28\x23\xf7\xe5\x44\x54\xa9\x79\xa3\x97\xf1\x32\xa7\
-\x7a\x88\x03\x37\x9e\xea\x51\x54\x0f\x13\xf3\x09\x68\x26\xa0\x87\
-\x75\x44\x4d\xda\xd6\xd2\xef\xb7\xf6\x5d\x0c\x12\x3c\x86\x20\xc9\
-\x50\x8e\xa5\x86\xc8\xc6\x1c\x49\xbb\x6d\xcc\xcc\x98\x79\xb7\x0e\
-\x07\xd8\x72\x62\x7d\x02\x7d\x4f\x6f\xda\xe6\xcd\xb5\x63\x39\x0a\
-\xab\xed\x7c\x34\x94\x24\x1a\x69\x01\x8e\xb5\x54\xd5\x00\x4a\x35\
-\xbd\x11\x3e\xc5\xe3\x39\x53\xf8\xa4\x21\xd7\x14\x3f\x59\xcc\x3d\
-\x38\x7c\xb6\xea\xdd\x50\x81\xd3\x74\x5b\x21\x82\x46\x67\x4b\x6c\
-\x68\xdc\x8c\xb2\x4b\x5f\x09\xe0\x47\x07\x50\x67\xda\x9a\x2b\xbf\
-\x60\x74\x90\x75\x41\x61\xcd\x22\xa2\x26\xdf\x76\x19\x35\xc4\x79\
-\x8c\x88\xcc\xd5\xc4\xcb\x87\xcf\x5a\xcd\x87\x46\xa2\x03\x0f\xf5\
-\x04\xb1\xc8\x60\x81\x2f\x2a\xe6\x13\x90\x4c\xc5\x7c\x4c\xb8\xb2\
-\x67\xd4\x3a\xff\x3d\x02\x16\x13\xe0\x31\xe4\xb4\x17\x01\xc3\xa8\
-\xa1\xb2\x31\x87\x8a\x4e\x73\x34\x32\x66\xde\xab\xcb\xfb\xb5\x9d\
-\xd8\x51\x91\xac\x77\x31\xa4\x1e\xcb\x51\x38\xad\xe7\x43\x0b\xf3\
-\x32\x2c\xf7\xd2\x65\xc0\x13\x17\xbc\x7f\x91\x4a\x64\xf6\x1d\x5c\
-\x29\xeb\xb4\xdc\xc7\xbb\x93\x48\xb2\xcb\x05\x74\xdf\x73\xcc\x76\
-\xe1\x3a\x2e\xbf\x81\x9f\x73\x5d\x46\xdf\x6d\x98\x24\x59\x96\xd6\
-\x24\x76\x7d\x89\xad\xf7\xc5\x9b\xff\x27\xaf\xc0\xd9\xe4\x12\xfd\
-\x42\xbe\x16\x4d\x1a\x39\xa4\x09\x44\x10\x92\x8b\x32\xe4\x5e\x0a\
-\x33\xaa\x73\x32\xaf\xb4\x85\x5e\x46\xd1\xfb\x75\x1b\x86\xf6\x17\
-\x45\x79\x6a\x56\xe3\x93\x36\x1d\x08\x00\xff\xba\x8c\x2e\xb8\x76\
-\x27\x34\x40\x22\x36\x67\x2b\xe3\x6a\x34\xe5\x78\xdf\xab\x4a\xd2\
-\xd4\xbb\x53\x2d\xad\x8f\xe3\x8e\xaa\xd2\x35\x72\x63\x7d\x4e\xf5\
-\x8d\x5f\xb4\x32\x10\x4c\xeb\x2c\x7a\x71\x6b\x6c\x05\xe1\x75\x86\
-\xf5\x7a\x9f\xde\x7a\x64\xa3\xe6\x50\x61\xc4\x9f\x84\x3d\xd0\x13\
-\x20\xe3\x25\x34\x1d\x3d\x1f\x56\xf1\x1b\xed\xca\xd2\x82\xe9\x15\
-\x00\xda\x39\x3a\x5d\xaf\xc1\xf6\x5d\xd6\xfa\x32\xcf\x39\x41\x4e\
-\xdf\xb1\xce\xb2\x72\x99\x47\x9f\xb4\x13\x64\xbf\x9c\xa5\xef\x61\
-\xbe\xac\x65\x85\x6a\xb9\xf7\xa2\xf5\xdc\xc1\x29\xde\xc5\x11\x6e\
-\x73\x8a\x64\xfe\x3b\x38\xc5\x5e\x05\xe4\xe0\x67\x2e\xb3\xef\x56\
-\x47\x36\x7c\x62\x2d\xb7\xc3\x7c\x62\xff\x54\x56\x46\xd5\x74\x89\
-\x94\x68\xdd\x23\x8a\x46\xc6\x4c\x77\x56\xda\x56\x2c\xab\xd5\xbc\
-\x95\x0e\xc3\xcc\xdf\x76\x9b\x58\x77\x16\x74\xd0\xe2\xaa\x8c\xd8\
-\x55\x5f\x65\x46\xde\x74\x55\x82\x43\xf3\xf7\xe3\x5a\x9c\x95\x8e\
-\xc0\xfc\x05\x7a\xdb\xa9\xf5\xbf\x9f\xac\x67\xd9\xc4\x14\x41\x91\
-\xd7\x9b\x86\x21\x8a\x8b\xc4\xe7\x6c\xde\xfa\x7d\x96\x79\xd7\x37\
-\x64\xd4\x8b\xf8\x0c\xe7\xef\x79\xb8\xdb\x61\xf2\xb7\x4e\x4a\xf2\
-\x27\x49\x0a\x05\xb3\xe4\x91\x38\x1c\xf3\x34\x86\xcb\x97\x26\x80\
-\xae\x6f\xfe\xf4\x74\x86\x86\x9d\x2d\x0e\xb1\x0d\xb2\xb7\x53\x94\
-\xbe\x72\x2c\x36\xbc\xe3\xc2\x61\x33\x2f\xf0\x5d\x6c\xf9\xbb\x1a\
-\x66\xa4\xd2\xa9\xf7\xbc\xb6\x4e\xac\x9a\xfe\xdd\x05\x7d\x43\x3a\
-\xf8\xe2\x97\x65\x39\x6d\xe7\xd7\xd7\xd7\xd6\x43\x3f\x46\x5e\x76\
-\xd6\x4e\xfa\x94\xba\xf9\x77\x36\x26\xff\x03\xb1\x1b\xda\x8b\
-\x00\x00\x01\x0a\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x30\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x33\x32\
-\x30\x20\x33\x32\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x32\
-\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x32\x37\x39\x2e\x30\x31\x35\x34\x36\x20\x32\
-\x34\x33\x2e\x35\x32\x35\x68\x2d\x32\x33\x37\x2e\x39\x39\x39\x39\
-\x39\x37\x63\x2d\x32\x31\x2e\x34\x20\x30\x2d\x33\x32\x2e\x31\x30\
-\x30\x30\x30\x30\x31\x2d\x32\x35\x2e\x39\x2d\x31\x37\x2d\x34\x31\
-\x6c\x31\x31\x38\x2e\x39\x39\x39\x39\x39\x37\x2d\x31\x31\x39\x63\
-\x39\x2e\x34\x2d\x39\x2e\x34\x20\x32\x34\x2e\x36\x2d\x39\x2e\x34\
-\x20\x33\x33\x2e\x39\x20\x30\x6c\x31\x31\x39\x20\x31\x31\x39\x63\
-\x31\x35\x2e\x32\x20\x31\x35\x2e\x31\x20\x34\x2e\x35\x20\x34\x31\
-\x2d\x31\x36\x2e\x39\x20\x34\x31\x7a\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\x23\x63\x63\x63\x22\
-\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xf8\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x68\x33\x35\x32\x63\x32\x36\x2e\x35\x20\x30\x20\x34\x38\x2d\x32\
-\x31\x2e\x35\x20\x34\x38\x2d\x34\x38\x76\x2d\x33\x35\x32\x63\x30\
-\x2d\x32\x36\x2e\x35\x2d\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\
-\x2d\x34\x38\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x66\x69\x6c\x6c\x3d\x22\x23\x34\x38\x33\x64\x38\x62\x22\x2f\x3e\
-\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xe2\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x6c\x34\x30\x30\x2d\x34\x30\x30\x63\x30\x2d\x32\x36\x2e\x35\x2d\
-\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\x2d\x34\x38\x7a\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\
-\x23\x34\x33\x34\x37\x34\x64\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\
-\x3e\
-\x00\x00\x00\xce\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x33\x36\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x37\x33\
-\x36\x20\x37\x33\x36\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x37\x33\
-\x36\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x33\x36\x38\x20\x31\x32\x30\x63\x2d\x31\x33\
-\x37\x20\x30\x2d\x32\x34\x38\x20\x31\x31\x31\x2d\x32\x34\x38\x20\
-\x32\x34\x38\x73\x31\x31\x31\x20\x32\x34\x38\x20\x32\x34\x38\x20\
-\x32\x34\x38\x20\x32\x34\x38\x2d\x31\x31\x31\x20\x32\x34\x38\x2d\
-\x32\x34\x38\x2d\x31\x31\x31\x2d\x32\x34\x38\x2d\x32\x34\x38\x2d\
-\x32\x34\x38\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x34\x38\x33\
-\x64\x38\x62\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xe2\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x6c\x34\x30\x30\x2d\x34\x30\x30\x63\x30\x2d\x32\x36\x2e\x35\x2d\
-\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\x2d\x34\x38\x7a\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6c\x6c\x3d\x22\
-\x23\x34\x38\x33\x64\x38\x62\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\
-\x3e\
-\x00\x00\x00\xce\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x33\x36\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x37\x33\
-\x36\x20\x37\x33\x36\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x37\x33\
-\x36\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x33\x36\x38\x20\x31\x32\x30\x63\x2d\x31\x33\
-\x37\x20\x30\x2d\x32\x34\x38\x20\x31\x31\x31\x2d\x32\x34\x38\x20\
-\x32\x34\x38\x73\x31\x31\x31\x20\x32\x34\x38\x20\x32\x34\x38\x20\
-\x32\x34\x38\x20\x32\x34\x38\x2d\x31\x31\x31\x20\x32\x34\x38\x2d\
-\x32\x34\x38\x2d\x31\x31\x31\x2d\x32\x34\x38\x2d\x32\x34\x38\x2d\
-\x32\x34\x38\x7a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x34\x33\x34\
-\x37\x34\x64\x22\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
-\x00\x00\x00\xf8\
-\x3c\
-\x73\x76\x67\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x38\x38\x22\
-\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x36\x38\
-\x38\x20\x36\x38\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x38\
-\x38\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\
-\x2f\x73\x76\x67\x22\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x20\x64\x3d\x22\x6d\x35\x32\x30\x20\x31\x32\x30\x68\x2d\x33\x35\
-\x32\x63\x2d\x32\x36\x2e\x35\x20\x30\x2d\x34\x38\x20\x32\x31\x2e\
-\x35\x2d\x34\x38\x20\x34\x38\x76\x33\x35\x32\x63\x30\x20\x32\x36\
-\x2e\x35\x20\x32\x31\x2e\x35\x20\x34\x38\x20\x34\x38\x20\x34\x38\
-\x68\x33\x35\x32\x63\x32\x36\x2e\x35\x20\x30\x20\x34\x38\x2d\x32\
-\x31\x2e\x35\x20\x34\x38\x2d\x34\x38\x76\x2d\x33\x35\x32\x63\x30\
-\x2d\x32\x36\x2e\x35\x2d\x32\x31\x2e\x35\x2d\x34\x38\x2d\x34\x38\
-\x2d\x34\x38\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x66\x69\x6c\x6c\x3d\x22\x23\x34\x33\x34\x37\x34\x64\x22\x2f\x3e\
-\x0a\x3c\x2f\x73\x76\x67\x3e\
-"
-
-qt_resource_name = b"\
-\x00\x0b\
-\x0c\x6b\x3c\xf3\
-\x00\x73\
-\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x73\
-\x00\x09\
-\x08\xaa\x11\x25\
-\x00\x52\
-\x00\x61\x00\x72\x00\x65\x00\x53\x00\x74\x00\x79\x00\x6c\x00\x65\
-\x00\x0d\
-\x02\x0d\x3c\x07\
-\x00\x64\
-\x00\x72\x00\x6f\x00\x70\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0d\
-\x02\x33\xbc\x47\
-\x00\x73\
-\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0e\
-\x03\xc2\xd5\xc3\
-\x00\x73\
-\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x2e\x00\x71\x00\x73\x00\x73\
-\x00\x0b\
-\x04\x37\x88\x27\
-\x00\x73\
-\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x75\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0a\
-\x08\x8b\x0b\xa7\
-\x00\x73\
-\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x18\
-\x08\xb9\x19\xc7\
-\x00\x68\
-\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
-\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0a\
-\x0a\x2d\x1b\xc7\
-\x00\x63\
-\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0f\
-\x0d\xb0\xb1\xa7\
-\x00\x68\
-\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x13\
-\x0d\xf4\xfe\xa7\
-\x00\x63\
-\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
-\x00\x76\x00\x67\
-\x00\x13\
-\x0f\xf8\x57\x27\
-\x00\x73\
-\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
-\x00\x76\x00\x67\
-"
-
-qt_resource_struct_v1 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
-\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf5\
-\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\xe9\
-\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x7d\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x8b\
-\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x87\
-\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x6d\
-\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3f\
-\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x25\
-\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf7\
-"
-
-qt_resource_struct_v2 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x90\x35\x20\x19\x0c\
-\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x00\xf5\
-\x00\x00\x01\x90\x35\x20\x19\x0c\
-\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\xe9\
-\x00\x00\x01\x90\x40\x40\x2f\x92\
-\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x7d\
-\x00\x00\x01\x90\x35\x20\x19\x0c\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x8b\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x10\x87\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x11\x6d\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x12\x3f\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x00\x13\x25\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-\x00\x00\x01\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xf7\
-\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\
-"
-
-qt_version = [int(v) for v in QtCore.qVersion().split('.')]
-if qt_version < [5, 8, 0]:
- rcc_version = 1
- qt_resource_struct = qt_resource_struct_v1
-else:
- rcc_version = 2
- qt_resource_struct = qt_resource_struct_v2
-
-def qInitResources():
- QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-def qCleanupResources():
- QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-qInitResources()
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x00\xba\
+\x00\
+\x00\x00\xf4\x78\x9c\x25\x4e\xd1\x0e\x82\x30\x0c\x7c\x37\xf1\x1f\
+\x9a\xfa\xcc\xb6\x6e\x03\xc4\x30\x1f\xfc\x13\x33\x90\x91\x80\x10\
+\x59\x9c\xf1\xeb\x2d\xb3\x49\x9b\x6b\x7b\xb9\xbb\x76\x7b\x0f\x10\
+\xfa\x71\x08\xd1\x61\x65\x15\xc2\x7b\xec\xd3\x6d\xf9\x38\x54\xa0\
+\xc0\x68\x05\xf9\x9a\xc6\x2e\x06\x87\xbc\x23\x7c\xe6\xe9\xb9\x39\
+\x0c\x31\xae\x17\x29\x53\x4a\x22\x19\xb1\xbc\x06\xa9\x95\x52\x92\
+\x05\xf1\x7a\x3c\x00\x57\xbb\xde\x63\x80\xce\xe1\x6c\x09\xb4\xa9\
+\x84\xad\xcb\xa0\xcd\xd9\x6b\x12\x36\xab\x0b\xbe\x97\xa2\x01\xaa\
+\xc1\xd2\x54\x10\x31\xa4\xc6\x17\x0d\xff\xb9\x0b\x6d\x45\x95\x81\
+\x31\xcc\x52\x99\x21\xa8\xc8\x1c\x2a\x77\xb4\x0f\xcb\x04\x76\xa0\
+\x9a\xe7\x17\xff\xde\xff\x7a\x8c\xd3\xe4\xf0\xe4\xbd\x47\xc9\xa1\
+\xda\x3d\xdd\xf5\x07\x25\x24\x3a\x77\
+\x00\x00\x00\xb9\
+\x00\
+\x00\x00\xf3\x78\x9c\x2d\x8e\xd1\x0a\xc2\x30\x0c\x45\xdf\x05\xff\
+\x21\xc4\xe7\xb5\x4d\xdb\x39\x27\xab\x0f\xfe\x89\x74\x73\x1d\x6c\
+\x4e\xb4\xac\xc3\xaf\x37\xab\x06\x12\x2e\xc9\xe1\xe6\x36\xef\xa5\
+\x87\xd0\x0d\x7d\x88\x0e\x8d\x56\x08\xcb\xd0\xa5\xeb\xbc\x3a\x54\
+\xa0\x80\x37\x90\xb7\x69\x68\x63\xf8\x13\xeb\x34\x3e\xde\x0e\x43\
+\x8c\xcf\xb3\x94\x29\x25\x91\x8c\x98\x5f\xbd\xd4\x4a\x29\xc9\x86\
+\x78\xd9\xef\x80\xab\x79\xde\x62\x80\xd6\xe1\x64\x09\xaa\xa3\xb0\
+\x55\x19\xb4\x39\x79\x4d\xc2\x66\x73\x41\xa0\x4b\x51\x03\x55\x60\
+\x69\x2c\x88\x58\x52\xed\x8b\x9a\xef\xdc\x85\xb6\xe2\x98\x85\x31\
+\x4c\xa9\x4c\x08\x2a\x32\x43\xe5\xa6\xb6\x61\x19\xe0\x07\x54\xf1\
+\xfc\xe0\xef\xf5\xaf\xee\xc3\x38\x3a\x3c\x78\xef\x51\x72\xa6\x66\
+\x0b\x77\xf9\x02\xe5\xcf\x3a\x3f\
+\x00\x00\x0c\x81\
+\x00\
+\x00\x4c\x56\x78\x9c\xcd\x1c\x6b\x6f\xdb\x46\xf2\xbb\x01\xff\x87\
+\x3d\x1b\x01\x12\x9f\x14\xbd\x28\xc9\x66\x90\x0f\x75\xda\xeb\x1d\
+\xd0\xe2\xd2\xd8\xb8\x7e\x08\xf2\x81\x92\xd6\x16\x11\x8a\x54\x48\
+\x2a\x8e\x5b\xf8\xbf\xdf\xec\x8b\xdc\x37\x49\x49\x4e\xeb\x20\xb2\
+\xbc\x3b\x3b\x33\x3b\x3b\x6f\xae\x34\xb8\x38\x3d\xf9\x78\x8b\xbf\
+\x95\x9f\x4e\x4f\xd2\x2c\xdf\x44\x49\x88\xe0\xe7\x1c\xd3\x1f\x94\
+\xdf\x2f\x5e\x8e\x27\x97\x3d\x24\x5e\x5e\x91\x59\xd4\xef\xa3\x4d\
+\x14\xa7\xe8\x2e\x4b\x4b\xb4\xcc\x92\x2c\x3f\x3d\x59\xc5\x45\xb4\
+\x48\xf0\x0a\xd6\x9f\x07\x93\x60\x1e\xac\xe8\x6a\x34\x9b\xf7\x10\
+\x9a\x8f\xc8\xcb\xbc\x5a\x2d\x80\x15\x0c\xc8\xf8\x01\x04\x91\x8a\
+\xa1\x87\xa6\xd3\x17\xaf\xd0\xdb\xb7\x0c\xf9\x14\x46\xa7\x01\xfc\
+\xbf\x7a\xd5\x76\xfd\x58\x5e\x1f\xc0\x68\x30\x81\xff\x73\x58\xff\
+\xf1\x3a\x5a\x7e\xbe\xcf\xb3\x5d\xba\xd2\xa4\x31\x1e\x8e\xc7\xe3\
+\x29\x5b\x32\x19\x03\xa2\x49\x40\x5e\xe6\xaa\x34\x16\xd5\x72\xb1\
+\x23\xbc\x8a\x4b\xb2\x4f\x22\x93\xf1\x7c\x3c\x9f\x4c\x38\x8e\x4b\
+\xb2\x9c\xbc\x4c\x47\x15\x0e\x7d\x39\xc8\x26\x47\x39\x8e\x96\x65\
+\xfc\x15\x0f\x04\x2a\xf4\x10\xaf\xee\x71\x59\xa0\x97\xe4\xd4\x7e\
+\x82\xd1\xa2\x87\xde\xe7\xd9\x7d\x8e\x8b\xe2\x3a\xca\x0b\x84\xcb\
+\x25\x6c\x66\x9d\x7d\xc5\x39\xe5\x1e\x48\xc3\x4f\x45\x3a\x10\xec\
+\xfb\x48\x3f\xac\x71\x8a\x28\x8a\x38\xbd\x47\xe4\x77\xc5\x49\xcd\
+\xc0\xf5\xae\x2c\xb3\x14\xc8\xff\x1b\x47\x2b\x9c\x17\x40\xb5\xc0\
+\x09\x06\xa8\x2c\x0d\xc9\x86\x83\x71\x30\xe6\x54\xaf\x80\xe0\x6c\
+\x46\x5f\xfc\x1b\x66\x18\xe4\x9d\x9e\x9e\x44\x49\x89\xf3\x34\x2a\
+\x31\xc1\x7a\x39\x8e\xc6\x98\x9f\xde\x10\x10\x06\xe4\x3c\x82\x06\
+\xac\x02\x03\xd9\x4d\x9e\x3d\x14\x08\x8e\xeb\x97\xb8\x28\x07\xb7\
+\x39\xc6\x83\x5b\x42\xee\x7f\x31\x86\xf1\x28\x5d\xd1\x05\x37\xcb\
+\x3c\x4b\x12\x22\xcf\xd3\x13\xa2\x19\x59\x0e\x3b\xd4\xb4\x22\xb8\
+\x9c\xac\x2e\x17\x8c\x95\x39\xe1\x62\x06\xda\x34\x9a\x5c\xd5\xac\
+\xd0\x55\x12\x1b\x9b\xac\x28\xeb\x6d\xb9\xf4\x55\xc6\xa5\xeb\x2b\
+\x4c\x91\x5d\xcf\x26\xaf\x34\xed\xba\x0b\xe0\x1f\x07\xa2\xfa\x7e\
+\x45\x5f\xdc\xbc\x74\x56\xa8\xf8\x7e\x9d\xc0\xff\x12\x0e\x61\x3a\
+\x0e\x66\xd1\x90\x51\xbb\x24\xdc\xce\x81\xa7\xd1\x6c\xe8\xa6\xb6\
+\xca\xb3\xed\x2a\x7b\x48\x05\xb5\x1e\x8a\xd0\x22\x2e\x11\xc5\x08\
+\x90\xe5\x3a\x4a\xc5\x2a\x26\xa9\x1c\x83\x2e\x6c\xa3\x3c\x22\xea\
+\xd4\xd1\xbd\x48\x88\x2a\x4f\x63\xd5\xa6\xc9\x72\x72\x17\x8c\x38\
+\x26\xa2\x4d\xb3\x09\x79\x99\xba\x37\x72\x9f\x47\xab\x18\x83\xd3\
+\xaa\xf5\xac\x40\x59\xb5\x2f\xd8\xd0\x67\x8c\x40\xa1\x98\x2a\xbd\
+\xcf\xb6\xbb\x2d\x53\xa1\x9b\x2d\x5e\xc6\x51\x02\x3a\x14\xa7\x45\
+\x19\x25\x49\x5f\xd2\x25\x74\x3e\x9c\x73\x79\x22\x22\xca\x11\x39\
+\x3d\x44\xe5\x09\x4c\xf0\x05\xf5\x4a\xc9\xb8\x61\xe5\x54\x5a\x89\
+\x2e\xa7\xde\x95\x92\x18\x61\xe5\x58\x5e\x49\x9d\x82\xb9\x72\x97\
+\x9a\xfc\x9e\xcf\x87\x6c\xa5\x60\x54\x5e\x59\x2d\x90\xd7\xd6\x1c\
+\x9f\x4f\x87\x42\x73\xa6\xed\xd6\xd6\x3c\x83\x23\x1e\x4a\x6e\xcc\
+\xb9\xf6\x62\x40\x44\x7e\x81\xfe\x64\x46\x46\x4f\x2f\xb4\x04\xb3\
+\x37\x6c\x9e\x1d\x72\x5f\x02\x53\xed\x59\x80\x55\x27\xae\x80\x2a\
+\x01\x01\x40\x9f\x80\x72\x28\x78\xee\x91\x3f\x2a\x43\xad\x94\xd1\
+\x64\x4c\x55\x64\x37\x63\x56\xb0\xd6\x8c\x9d\x9e\xfc\xf6\x4b\xb4\
+\xc0\x49\x4f\xbc\x31\x58\xe2\x24\x41\x9d\xcb\x75\x88\x86\xdb\x6f\
+\x4e\x1a\x65\x1e\xa5\x05\x18\x28\x18\x03\x87\xd9\x46\xab\x15\x78\
+\x58\x79\x59\x15\x10\xfa\x2e\x26\xe5\xc8\x50\x31\xf9\x2b\x4e\x77\
+\x94\x47\xf0\xd1\xc4\x31\xcb\xef\xc3\x30\x2e\xf1\x86\x8c\x10\xe7\
+\x2d\x66\xc5\x7b\x69\x56\x78\x75\xe5\x8f\x7a\x9e\x45\x2d\x36\x56\
+\x30\x26\x15\x48\xc4\xde\xbe\xcb\xf2\x14\xe7\x2c\xd6\x29\x80\xff\
+\xca\xa3\x0d\xfe\x78\x47\x5e\x6f\xd6\xd1\x16\xbf\x3d\x9b\x9d\x7d\
+\x22\x13\x3f\xc3\x2e\xb7\xd7\xd9\x37\xc6\x74\x8a\x89\x4f\xa5\x98\
+\xb9\x7f\xa5\xef\xe3\x4d\x35\xfe\x23\xf8\x22\xf9\xbd\x3c\x77\x9b\
+\x65\x09\x47\xf5\x2e\xdb\x2c\x32\xed\x7d\xa5\x5a\xf2\x20\xfa\xed\
+\x87\x45\x01\xa7\xb3\x2c\xff\x03\x5b\x15\x12\xb8\xd9\xc6\x29\x5f\
+\xfd\x63\xb6\x83\x25\xd2\x80\xe4\xee\x29\xa8\x08\x7e\x76\xa5\x18\
+\xd5\x4a\xc1\xc6\x8b\xf2\x91\x44\xa1\x22\x4b\xe2\x95\x3a\x43\x9c\
+\xe5\xae\x08\xd1\xb8\x5a\x52\xe9\x08\x1b\xa2\xc7\x7d\x84\xc3\x38\
+\x54\xce\x7f\x8d\x40\x65\x43\x50\xa2\x76\x83\x61\xcb\xe9\xe3\x61\
+\x86\x66\x2a\xf1\xf0\xec\x93\xcf\x17\x3c\xb9\x34\x5f\x5b\x24\x4e\
+\x3e\xa8\x56\x55\xd2\xfc\xd3\xbb\x39\x29\xa5\xd7\x16\x9a\xbe\xca\
+\x8e\x41\x4a\xea\x75\x0c\xff\xa8\x5c\x31\x0d\x48\x0d\x88\x94\x5c\
+\x59\x78\x76\xea\x3f\x42\x26\x6e\xea\xdf\x3d\x6a\x22\xf0\xef\x73\
+\x38\x40\x89\x24\x4d\x7d\x92\x35\xf5\xd4\x3f\x65\x25\x85\xf1\xdd\
+\xb6\xbf\xa0\x16\xc1\xc1\x00\x82\x0f\x54\xf4\x77\x8b\x25\x14\x5a\
+\xa0\x84\xfd\x2c\x8f\xef\x63\x48\xcf\xd9\x31\xbd\x39\xba\x7d\xf3\
+\x89\x12\x58\x4d\xf0\x5d\x59\x41\x0c\x75\x88\x45\x06\x1c\x6e\x6c\
+\x40\xda\xe6\xd5\x58\x6a\x91\x82\x06\x50\x89\x43\x5f\x58\xcb\xc5\
+\x15\xf5\xba\x07\x5a\x35\x08\x6a\x9c\x5b\xc4\xbf\xcd\x8a\x98\xd5\
+\x47\x20\x21\x94\x93\xec\xb7\x63\x12\xc2\xc0\xa8\xd8\x64\x58\x25\
+\x0d\x7f\x83\x06\x17\xb6\xba\x44\x64\xdb\x24\x3f\xd2\xa5\xdc\x55\
+\xa7\x0e\x73\x61\x4a\xb2\xdd\x5e\xe1\x05\x71\xa1\xa9\x41\xa5\x55\
+\xf1\x26\xba\x07\x1d\xdd\xe5\xc9\xcb\xb3\x70\x40\x35\xb6\x58\x63\
+\xc8\xc8\x07\x1f\xe0\x74\x6e\xc8\xdf\x83\x0a\xdf\xeb\xe2\xeb\xfd\
+\x59\x4d\xb6\x79\xb3\x32\x3d\x22\xdb\xd1\x0c\xfd\x13\x8d\x2f\xc0\
+\x52\x14\xdb\x41\x6f\xd1\x68\x0a\x63\x3c\xc8\x01\xcc\x84\xfe\x95\
+\xd3\x82\x81\x95\x12\xb5\xec\x2b\xb2\x2d\xf5\x84\x10\x16\xe3\x28\
+\x2a\xa1\x66\xc2\xf5\x2c\xe4\x92\x24\x34\x52\xf4\xa6\x95\x09\xfe\
+\x3b\x08\xab\xc8\xf2\xb2\xbf\xdb\x6a\xa2\xf2\x3b\x97\x9a\x6b\x46\
+\xd7\xc1\xb8\x3c\xe9\xe0\x9b\xf8\x8f\x7d\x99\xd6\x4f\x58\x8d\xc7\
+\x82\x6d\x4b\xb2\x5a\x42\xe2\xd0\x8f\xc0\x48\x60\x03\x4b\x38\x32\
+\xea\x1f\x9f\xd4\xe5\x61\xb8\x5c\xef\xd2\xcf\x1e\x2c\xae\x0c\x9a\
+\x0f\x8c\x5f\xf0\xbf\x37\x51\x4e\x3d\xb1\x2f\xc7\xf6\x44\x6e\x57\
+\x4e\xa1\x06\x5e\x85\xc7\x51\x13\x25\xa5\xa1\xc2\xf7\x5e\xd1\x09\
+\x21\x60\x96\xf1\x32\x4a\x74\xa3\x18\x55\x21\xbe\x86\x5d\x43\x9c\
+\xf9\x03\xb4\xa2\x86\x5e\x63\xd6\x3c\xb0\x82\x87\xc0\x62\x3f\x81\
+\x1c\xae\x22\xd2\x53\xe7\x41\xc9\xbc\xf3\xd5\xfa\x9a\xb0\x0b\x83\
+\xc9\x1a\x93\x5c\x88\xd2\x2c\xc5\x6f\x54\x6e\x6d\x87\x63\xf1\xfa\
+\xde\xad\x34\x99\xf7\x1b\x63\x5a\x04\x69\xa6\x22\x26\x09\x43\x1a\
+\x2d\x6c\xb1\x3b\x15\x8b\x4c\xbd\x74\xe4\x68\xb6\xcf\x66\x5a\x92\
+\x21\xa1\xaf\x3b\x95\x75\x94\xae\xea\xf8\xb1\x77\xc2\xb3\x6f\x8f\
+\xc0\x92\xb1\x3b\x53\xa8\x4d\x9c\xf6\x85\xfe\x4d\x86\xca\x30\x67\
+\x78\x32\xac\x8b\x27\xa9\x74\x72\x38\xa5\x27\x7b\x7d\x65\x91\xb7\
+\xc5\x9b\x31\x79\xd2\x7c\xc3\x32\x9c\x73\x9b\xf6\xd2\xd1\x95\xd4\
+\x4d\x05\x8c\xc1\x32\xca\xf4\xb7\x89\x4a\xbd\x9b\xf0\x2e\xce\x8b\
+\x52\x50\x53\x36\xd0\x8e\x51\x2b\x02\xca\x5b\xbd\x5e\xee\x4c\x28\
+\x7d\x88\xaa\x62\xe5\xcb\xb3\x5d\x49\xb5\x1b\x0d\xf9\xae\xee\xf3\
+\x78\x45\x46\xbc\x9e\x97\x6a\xf7\x3a\x7b\xe8\xaf\x30\x04\x48\xda\
+\x03\xed\x8b\x9a\xa3\x46\xe5\xab\x2b\xcc\xf6\x4c\xcb\x36\x11\x01\
+\xad\x7a\xa4\xae\x82\xc5\x12\x29\x24\xa1\x20\xb5\x1e\xe7\xe2\xd1\
+\x46\xeb\xd2\x5e\x0c\xbb\xf5\xd7\xdb\xfe\x61\x23\xda\x71\xe9\x9a\
+\x09\x29\xc8\x2d\xe4\x4b\xec\x64\x41\x6c\x1b\x92\x92\xc5\x05\xa4\
+\x23\x65\xb4\x5c\x93\x64\xad\xcc\x68\x46\x25\xdb\x13\x49\x4a\x06\
+\x17\x32\xb3\x1f\x97\xbb\x9c\x88\xf4\x5d\x96\xec\x36\x29\xad\x96\
+\xad\xe4\x75\x75\x33\x10\x7c\xc8\x1e\xdc\xab\x55\x5d\x23\x5c\x68\
+\xdb\x67\xe5\xab\x29\x04\x69\x5c\x6d\x78\x69\xf5\xee\x61\xce\xcc\
+\x2c\x8b\x75\xf6\xe4\xf2\x58\xe3\x50\x99\xd2\x98\x14\x73\x47\xe2\
+\xd3\x9a\x37\xbd\xdf\x15\xeb\x6b\x91\xed\xb3\xfe\x9a\x5a\xd7\xb4\
+\x6d\x4b\xd4\x88\xe4\x42\x53\xc2\xb8\x7f\xbf\x42\x42\x5d\x1f\x68\
+\x8d\xb7\x1a\xb3\xfb\xc1\xbd\x1a\x1b\xcd\x72\x79\x86\x1e\xe0\x44\
+\x1f\xe2\x76\x33\x33\xc6\xb9\x39\xcf\x6a\x73\x56\xc5\x14\x82\x3d\
+\xef\xfa\x71\xba\x02\xff\x5d\x66\xba\xc0\xb4\xd9\xe6\x2c\xa6\x4e\
+\xff\x1d\x69\x06\xe7\x8b\x03\x30\xae\xfb\x46\x17\x84\x0b\x85\xe7\
+\x95\x4f\xe2\xc1\x84\xd2\x21\x7e\xb7\xc6\xcb\xcf\xfc\xfd\x07\x10\
+\x55\xd6\xa4\x8e\x66\xf2\x29\xd0\x81\x15\xc9\x02\x10\x98\xb5\x61\
+\x89\x88\x36\x23\x19\xb1\x22\xc8\xda\x80\x95\x61\xc9\x78\x75\xc9\
+\xb6\x6d\x0e\x74\xd7\xa9\xd6\x8f\x3a\xfe\x86\x52\x51\x0b\x26\x47\
+\x51\x64\x61\xdb\x93\xd7\x59\xa0\x15\x6f\x64\xd9\xad\x32\x6f\xdf\
+\xb6\x02\x62\xd9\xbf\xea\xf0\x4c\x41\xa8\xf3\x16\x89\xec\xd3\x80\
+\x7b\x72\xb2\xeb\xa8\x80\xa7\x2f\xf6\xd2\x84\xa3\x5b\x81\xea\x00\
+\x5d\xa7\xb6\x24\xdc\xb8\x0f\x4d\x9a\xb6\x1d\x88\x34\x6d\x3b\x0f\
+\x79\xda\x76\x1c\x7c\xde\xcb\x38\x99\x68\xd5\x83\xf9\xb2\x83\xf7\
+\x72\x03\xc6\xba\x5f\x78\x87\xc1\xc5\x42\x55\x03\x69\xa6\x6b\xd7\
+\x06\x90\x6d\xef\x06\x90\x4d\x02\x26\x90\x4d\x0e\x0a\xd4\x51\xa4\
+\xb1\x8e\x92\xbb\xbe\x45\x24\x0e\xc3\xf3\x1f\xc4\xf4\x45\x07\xca\
+\xcb\x38\x5f\x26\xcd\xe7\xc0\x29\x36\x7a\x0d\x1b\x9c\x47\x13\x1b\
+\x5d\x84\x15\xce\xa3\x9b\x86\xcb\x68\xaf\x8b\xd5\x0d\x82\x6e\x4a\
+\xd9\x28\x12\x37\x74\xa3\x9a\x36\x8a\xc7\x03\xdd\xa8\xb8\x7b\x89\
+\x4a\x52\x54\xbb\xbc\xfc\x1a\xbb\x17\x4d\xa6\xa2\x56\x72\xd2\x01\
+\x09\x8c\xe4\xae\x60\xff\x81\x47\xcc\x45\x96\x88\x9c\x00\x4a\x3b\
+\xb5\x4b\xf1\x7a\x8a\x37\xb4\xe9\xfc\xdf\xbb\xbb\x02\x97\xa2\xb2\
+\x23\xb3\x7a\x9f\x79\xff\x74\xd6\xe8\xaf\xf2\xaa\xed\xf5\x18\x6f\
+\x34\x0d\xfb\x48\x65\x44\xb6\xf8\xf6\xac\xcc\x77\xb8\x7e\x58\xaa\
+\xf4\x3d\x28\xdb\xbc\x5c\x64\x8f\xfd\x9b\x76\x6e\x49\x08\xf8\xca\
+\x30\x2c\xa3\x45\x4f\xd1\xf2\x32\x2e\xeb\x06\x58\xd3\x13\x41\xe7\
+\xa3\x08\xda\x7d\x73\x3d\x89\x38\x8e\x84\x8d\x67\x87\x81\xbe\x96\
+\x3f\xd5\xa0\xa9\xba\x1b\xaa\xa9\x6c\xb4\xf4\xc5\x49\x59\xa1\xa6\
+\x99\x21\xfa\x42\x9a\x35\x70\x4e\xfc\xe2\xd7\x4b\x06\x41\x7e\xbe\
+\x8d\x48\xd2\xdf\x43\x8f\xf0\x7b\xd8\x93\xc6\xc7\x21\x42\x40\xeb\
+\x11\x7e\x8f\xa4\xf1\x82\x9d\xb3\x85\x23\x03\x68\x64\xc9\x6b\x05\
+\xdf\x95\x80\x1d\xe5\x64\x7d\x47\xd0\xa2\x13\x8a\x2b\xd1\x94\xe3\
+\x78\x8f\x45\xed\x75\x2d\xe9\xc8\xc6\x7f\xe0\x9f\xf3\x78\xab\x79\
+\x09\xa9\xf3\xce\xf5\x25\x30\x72\xe4\x40\x6a\x06\x81\x0f\xfc\x9d\
+\x5e\xb8\x0b\xc3\x6d\x94\x52\xad\x7e\x52\x87\x61\xab\xfd\x05\x7b\
+\x38\xc2\x67\xa4\x47\x25\x5f\xb6\x79\xb6\xc5\x79\xf9\xd8\x5f\xe5\
+\xd1\xc3\x75\x54\xf0\xf6\x5c\x0d\x49\x11\xa8\x56\xea\x7e\xc6\xd3\
+\xbd\x7f\xec\xb9\x3b\x15\xc8\x3d\x23\xc1\x49\x08\x4a\xd1\xd3\x86\
+\xf8\x53\x34\xb5\x36\x10\x8d\x27\xa3\xd8\xae\x1a\x62\x63\x17\x7e\
+\xa5\x77\xa4\x51\xd9\xaf\x7d\x64\x3e\xaa\xb6\x34\x25\xb9\x57\xa5\
+\xa6\xec\xac\x70\x35\x56\x35\x46\xa4\x87\x85\x13\xfd\x28\xc8\x9c\
+\xef\xc1\xb3\xe9\x55\xda\x77\x9b\x9a\x7c\xc3\x90\xb9\x86\xfe\x48\
+\xf3\x0d\x43\xe6\x1a\xdc\xbe\x41\x61\xb2\xb5\x6f\xd0\x05\xa5\x2a\
+\x88\xf5\x81\x70\xa3\xb8\x3c\xe7\x6a\x11\x97\x55\xb8\x5d\xc5\x35\
+\xb6\x4b\x6b\xf8\xbc\xc2\xaa\x0c\xc0\x6c\xbc\x3c\xdb\x31\xef\x17\
+\x02\xec\xc7\x7c\x20\xf3\x5d\x85\x7e\x1c\xd6\x09\xf0\xbe\x3d\x5f\
+\x9b\x12\xfa\x9e\x79\x78\x3a\x45\x16\x69\x1e\xc6\x95\x64\x45\x47\
+\x60\x89\x48\xc9\x11\x99\x5b\xd8\xa0\x63\x83\x0e\x84\x4d\xee\xd2\
+\x77\x82\xad\xd2\x87\xb6\xee\xd7\x1f\x03\xb4\x53\x3a\x90\xb2\xf3\
+\xb8\x74\xb2\x24\x94\xe9\x01\x92\xf5\x8b\xb5\x28\x4c\xad\xc0\x8c\
+\xc1\xe2\x49\xa6\x3d\x06\xd3\xd0\x6d\x0d\xc2\x2c\x76\x1f\x10\x83\
+\xfd\x0a\xd9\x5d\xfe\x34\xd1\x57\x39\xa1\x61\xde\x15\x56\x8c\xeb\
+\x6a\x9e\xd3\x50\x52\x81\x23\x44\xe1\xfe\xc8\x9f\xa1\x3f\x73\x60\
+\x51\xf4\x43\xd9\xa2\x4b\x58\xa6\x00\x3c\xd2\x32\x24\x7b\x98\xb0\
+\x1c\xd5\xcc\xf7\x89\xc1\xb5\x01\x74\x8f\x63\x7b\x9f\xf2\x71\x22\
+\x99\xcd\x42\x9f\x5b\xe8\xc7\xe1\x9c\x0a\xfd\xb0\x70\xe7\x49\xde\
+\x75\x41\xb4\x0a\x78\x4c\x98\x87\xf1\xd4\x50\x75\x74\x65\x89\x4a\
+\xc9\x11\x65\x9a\xed\xd5\xbe\x41\x07\xba\x46\x5f\xe9\x3d\xc1\x03\
+\x43\x61\x87\x3a\x4c\x3d\xa5\x03\xe9\xba\x8f\x8b\xf7\x0d\xca\xa8\
+\xdc\xc9\xd7\x37\x8f\x5f\x81\xff\x7d\x2a\xa0\xc9\xf7\xf2\xbe\xbc\
+\x37\x74\x1b\xeb\x15\xf5\x33\x5c\x8c\xeb\x70\x3b\x35\xdb\x46\xcb\
+\xb8\x7c\x04\xc7\x38\x1c\x56\x8c\x5e\x47\x49\x92\x65\xa9\xc4\x6b\
+\xe3\xc7\xfa\xda\xdf\x77\xfa\xcb\xb7\x4d\xf7\x38\xb8\x40\xbf\x92\
+\x0f\x92\x93\xd6\x13\xe9\x5d\x11\xb2\xe4\x66\x12\xbd\x00\xc4\x4c\
+\xef\x9c\x00\xa8\xcd\xac\x67\xb3\x84\x96\xfd\x90\xee\x3d\x53\x51\
+\x30\x3b\xf4\xfc\xd8\x7d\x11\x02\xc1\x6f\xdd\x9b\x52\x6c\xf0\x5b\
+\x5d\x84\xe3\xf6\xd3\x32\x3d\xb3\xb1\xc8\x7b\x76\x75\x1e\xa8\x5e\
+\x61\xf3\xf5\x68\x0e\x3d\x3b\xf9\x26\x0e\x9a\x32\x4d\x14\x17\xde\
+\x2c\x7c\xd3\x72\x8f\x5e\xa1\xeb\xb9\x61\x78\x91\xe3\xbe\x84\x69\
+\xb4\x51\xd9\xb0\x2b\xda\x58\x99\x48\xa2\x36\x3c\x10\x28\xfb\xbd\
+\x40\x83\x07\x3e\xae\x31\x61\xb7\x3c\x57\xc7\xa8\x5d\x00\x69\xd8\
+\xd9\x31\xfb\x21\x9e\x8f\x01\xd7\x77\xa7\xce\x09\x07\xf4\x1d\xeb\
+\x9d\xab\x77\xa7\xf4\x59\x0f\x5b\xbe\x2b\x72\x3a\x1a\xc7\x95\x39\
+\x27\x98\xef\x62\x91\xf9\x98\x01\x1c\xe9\x4d\xbc\xc2\x5e\x47\x4a\
+\x00\xbe\x93\x23\x6d\x57\xd1\xee\xf1\xec\x69\xf2\x5d\x2b\x5b\x8b\
+\x1f\xad\x85\xb8\xaf\x1f\xed\x92\x3c\xcb\xe4\x2c\x6e\x94\x32\x6f\
+\x78\x51\xd1\x73\x99\x98\xde\x4d\x43\xc7\x12\x69\xdd\xbd\xe9\x40\
+\xcc\x51\x38\x6f\x88\x1b\x8e\x85\x8e\x3a\x7d\x9b\x95\x05\xcd\xb9\
+\xd9\x39\xb0\xf8\x36\xb1\x55\xc7\x67\x2d\xbd\xde\x4d\x27\xe2\xf8\
+\xaa\x02\xe7\x39\x76\xb8\x75\x6e\xc9\xef\x89\xc1\x82\x9e\x2f\xd7\
+\xa6\xb9\x8a\xcb\xe1\xe7\x0c\xc0\xfd\x81\xa7\x69\xe3\xe7\xa8\xb4\
+\x0f\x61\x08\xca\xbf\xe7\xd1\x76\x8b\xc9\x57\xcf\x94\xe4\x0b\x62\
+\x0a\x95\xbe\xe4\xc3\x38\x20\x73\x4d\xb6\xbb\xb2\x36\x88\xe6\x4f\
+\x8a\xb5\xf6\xa1\x16\xec\x2e\x3f\xea\x03\xed\xe2\x4b\xf9\x47\x68\
+\x7e\xc8\x71\x24\x70\xde\x70\x31\xb1\x99\xe7\xf9\x44\xbb\xf2\xe1\
+\x1d\x3b\x61\x59\x11\x5a\x7f\x46\x81\x5a\x3f\xfd\xe2\x0b\x1d\x29\
+\x1d\x7c\xfe\xef\x3b\x90\x4c\xe9\xfc\xea\xea\xca\xad\x08\x07\x0a\
+\xcf\xbd\xc7\x23\x3f\xe4\xb7\x7d\xfb\xc9\xe0\xff\x4c\xe3\xa1\x74\
+\
+\x00\x00\x00\xcb\
+\x00\
+\x00\x01\x0d\x78\x9c\x2d\x8e\xc1\x6a\x03\x31\x0c\x44\xef\x85\xfe\
+\x83\x50\xcf\x96\x25\xd9\xde\xad\xcb\x3a\x87\xfe\x49\x71\xd2\xf5\
+\xc2\xa6\x09\x8d\x89\x43\xbf\xbe\xde\x24\x0f\x24\xc4\x68\x18\x66\
+\xba\x5c\x67\x28\x87\x65\x2e\x35\xa1\x53\x46\xb8\x2e\x87\xf6\x79\
+\xba\x25\x64\x60\xe8\x0a\xdc\xd5\xb6\xec\x6b\x79\x3a\x6e\xc7\xf5\
+\xe7\x92\xb0\xd4\x7a\xfe\xb0\xb6\xb5\x46\xcd\xd1\xe9\x77\xb6\xca\
+\xcc\xb6\x07\xe2\xee\xf5\x05\x3a\xd3\xf9\xab\x16\xd8\x27\x3c\xea\
+\x18\x89\x25\xf8\x01\xd4\x3b\x0a\x1a\x8a\x51\x37\x52\xdc\x18\xb3\
+\x51\x21\x0f\x6c\x9c\x92\xf0\x86\x18\x0d\x14\x8d\x8c\xc6\xcb\x2a\
+\xf2\xfe\x34\x1a\x91\x98\x23\x79\xd3\xa7\x07\xd1\x70\x3f\x9c\xa3\
+\x08\xdc\x6d\x11\xb6\xbf\x04\x52\xe8\x4b\xc0\x53\x00\x2f\x46\x86\
+\xfe\xf7\xf2\x87\x8f\x52\x0f\xbe\x97\x75\x4d\xf8\x96\x73\x46\xdb\
+\xdb\x4e\x5b\xed\xdd\x3f\x24\x1d\x3f\xb1\
+\x00\x00\x00\xb2\
+\x00\
+\x00\x00\xfb\x78\x9c\x2d\x4e\x5d\x0b\x83\x30\x0c\x7c\x1f\xec\x3f\
+\x84\xec\xb9\x36\x56\x3b\xca\xb0\x3e\xec\x9f\x6c\xd3\x59\x41\xa7\
+\xcc\xd2\xca\x7e\xfd\xfa\xe1\x11\x08\xb9\x4b\x2e\xd7\x6c\x6e\x00\
+\xd3\x8f\x83\xb1\x1a\xaf\x4a\x21\xb8\xb1\xf7\xf7\x65\xd7\x48\x40\
+\x10\x18\x48\xac\x1f\x3b\x6b\x8e\x8d\x7d\x9e\x3e\x9b\x46\x63\xed\
+\x7a\xe3\xdc\x7b\x5f\xf8\xaa\x58\xbe\x03\x17\x44\xc4\x83\x21\xb6\
+\xe7\x13\x04\x34\xeb\xc3\x1a\xe8\x34\xce\x52\x10\x94\x82\x0c\xab\
+\xa4\x78\x31\x71\x2d\x24\x10\xab\x15\x88\xb2\x90\xb1\xd7\xca\x45\
+\x85\x20\x49\x91\x85\xc4\x86\x32\x51\xc8\x17\x61\x62\x87\x16\x8e\
+\x5c\x32\xa3\xe4\xc6\x0e\xa3\x5c\x3f\xcc\xff\x33\xde\xe3\x34\x69\
+\xbc\xd4\xaa\xea\xd4\x13\x79\xc8\xd6\xc4\x90\xed\x1f\x18\x68\x3c\
+\x83\
+\x00\x00\x00\xab\
+\x00\
+\x00\x00\xe5\x78\x9c\x2d\x4e\xdb\x0a\x83\x30\x0c\x7d\x1f\xec\x1f\
+\x42\xf6\x5c\x1b\x6b\xeb\xca\xb0\x3e\xec\x4f\x86\x3a\x2b\xe8\x94\
+\x59\xac\xec\xeb\xd7\x56\xc3\x81\xc0\xb9\x24\xa7\x5a\xb7\x1e\x6c\
+\x37\xf4\xd6\x19\x2c\xb5\x46\xd8\x86\xce\x3f\xe7\xdd\x20\x01\x41\
+\x60\x20\xb1\x7e\x68\x9d\x3d\x1d\xfb\x34\x7e\x56\x83\xd6\xb9\xe5\
+\xc1\xb9\xf7\x3e\xf3\x45\x36\x7f\x7b\x2e\x88\x88\x87\x83\x58\x5f\
+\x2f\x10\xa6\x5a\x5e\xce\x42\x6b\x70\x52\x82\x20\x17\x64\x59\xa1\
+\x44\xc3\x44\x99\x29\x20\x26\x35\x88\x3c\x53\x71\x4b\xbd\x45\x85\
+\x20\x49\x91\x85\xc4\x06\x8c\x92\x82\x95\xa8\xa1\x94\x63\x67\xe4\
+\xc0\x0f\x8f\x4f\xc7\xbc\x87\x71\x34\x78\x93\x85\xbc\xcb\x16\x79\
+\x68\x51\xc5\x3a\xf5\x1f\x17\x3e\x37\xb0\
+\x00\x00\x00\x9c\
+\x00\
+\x00\x00\xd0\x78\x9c\x35\x8d\xd1\x0a\x83\x30\x0c\x45\xdf\x07\xfb\
+\x87\x90\x3d\xd7\xa6\x56\xb4\x0c\xeb\xc3\xfe\x64\x9b\xce\x16\x74\
+\xca\x2c\x56\xf6\xf5\xcb\xa4\x06\x2e\x39\xb9\x84\x7b\xeb\x65\xed\
+\xc1\x75\xbe\x77\xc1\x62\xa5\x4b\x84\xd5\x77\xf1\x36\x6d\x16\x09\
+\x08\xd8\x81\xdd\x8d\xbe\x0d\x2e\x7d\x6c\xe3\xf0\x5e\x2c\xba\x10\
+\xe6\xab\x94\x31\xc6\x2c\xea\x6c\xfa\xf4\x32\x27\x22\xc9\x81\xd8\
+\x9c\x4f\xc0\x53\xcf\xf7\xe0\xa0\xb5\x38\xea\xd2\x80\xca\xe9\x29\
+\x94\xae\x80\x44\x5e\xf0\xa9\xd4\xbe\x59\x0b\x33\x24\x3e\x24\x92\
+\x27\x12\x8b\x83\x59\x5f\x84\x97\x1f\x06\x8b\x97\xc2\xe8\xd6\x3c\
+\x50\x72\x61\xfd\x6f\x6e\x7e\x9e\x8c\x33\xe8\
+\x00\x00\x00\xab\
+\x00\
+\x00\x00\xe5\x78\x9c\x2d\x4e\xdb\x0a\x83\x30\x0c\x7d\x1f\xec\x1f\
+\x42\xf6\xac\x8d\xb5\x95\x32\xac\x0f\xfb\x93\x4d\x9d\x2d\xd4\x29\
+\xb3\x58\xd9\xd7\xaf\x56\xc3\x81\xc0\xb9\x24\xa7\x5e\xd6\x01\x4c\
+\x6f\x07\xe3\x35\x56\x4a\x21\xac\xb6\x0f\x8f\x69\xd3\x48\x40\x10\
+\x19\x48\x6c\xb0\x9d\x37\xa7\x63\x1b\xdd\x67\xd1\x68\xbc\x9f\xef\
+\x8c\x85\x10\xf2\x50\xe6\xd3\x77\x60\x9c\x88\x58\x3c\x88\xcd\xf5\
+\x02\x71\xea\xf9\xe9\x0d\x74\x1a\x47\xc9\x09\x0a\x4e\x26\x2b\x25\
+\x6f\x33\x5e\xe5\x12\x28\x13\x0a\x78\x91\xcb\x7d\x0b\xb5\xee\x0a\
+\x41\x92\x76\x16\x12\x1b\xe1\x04\x45\x2b\x51\x4b\x29\x97\x9d\x91\
+\x03\x3f\x3c\x3e\x1d\xf3\xb6\xce\x69\xbc\x09\x55\x76\xea\x85\x2c\
+\xb6\xa8\xf7\x3a\xcd\x1f\x1a\x11\x37\xe3\
+\x00\x00\x00\x9c\
+\x00\
+\x00\x00\xd0\x78\x9c\x35\x8d\xd1\x0a\x83\x30\x0c\x45\xdf\x07\xfb\
+\x87\x90\x3d\xd7\xa6\xb6\xe8\x18\xad\x0f\xfb\x93\x31\x9d\x2d\xe8\
+\x94\x59\xac\xec\xeb\x97\x49\x0d\x5c\x72\x72\x09\xf7\xda\x65\xed\
+\xc1\x77\xa1\xf7\xd1\x61\xad\x2b\x84\x35\x74\xe9\x3e\x6d\x0e\x09\
+\x08\xd8\x81\xdd\x4d\xa1\x8d\x3e\x7f\x6c\xe3\xf0\x5e\x1c\xfa\x18\
+\xe7\x9b\x94\x29\xa5\x22\xe9\x62\xfa\xf4\xb2\x24\x22\xc9\x81\xd8\
+\x9c\x4f\xc0\x63\xe7\x47\xf4\xd0\x3a\x1c\x75\x75\x05\x55\xd2\x53\
+\x28\x5d\x03\x89\xd2\xf0\xa9\xd4\xbe\x59\x0b\x33\x64\x3e\x24\xb2\
+\x27\x32\x8b\x83\x59\x5f\x84\x57\x18\x06\x87\x17\xa3\x4d\x6d\x5a\
+\x94\x5c\x68\xff\xcd\xcd\x0f\x9b\xb9\x33\xb5\
+\x00\x00\x00\xb2\
+\x00\
+\x00\x00\xfb\x78\x9c\x2d\x4e\xd1\x0a\x83\x30\x0c\x7c\x1f\xec\x1f\
+\x42\xf6\x5c\x1b\x6b\xbb\x95\x61\x7d\xd8\x9f\x8c\xe9\x6c\x41\xa7\
+\xcc\x62\x65\x5f\xbf\xb6\x7a\x04\x42\xee\x92\xcb\xd5\xcb\xda\x83\
+\xed\x5c\x6f\xbd\xc1\xab\xd6\x08\xab\xeb\xc2\x63\xda\x0c\x12\x10\
+\x44\x06\x32\x1b\x5c\xeb\xed\xb1\xb1\x8d\xc3\x67\x31\x68\xbd\x9f\
+\xef\x9c\x87\x10\x8a\x50\x15\xd3\xb7\xe7\x82\x88\x78\x34\xc4\xe6\
+\x7c\x82\x88\x7a\x7e\x7a\x0b\xad\xc1\x51\x09\x82\x52\x90\x65\x95\
+\x12\x2f\x26\xae\x85\x02\x62\x52\x83\x28\x0b\x95\xba\xd4\x6b\x52\
+\x08\xb2\x94\x58\xc8\x6c\x2c\x9b\x84\xfd\x22\x4e\xec\xd0\xe2\xd1\
+\x9a\xcd\x28\xbb\xb1\xc3\x68\xaf\x1f\xee\xff\x77\xbc\xdd\x30\x18\
+\xbc\xc8\x4a\xde\x64\x8b\x3c\x66\xab\x53\xc8\xe6\x0f\x15\x95\x3c\
+\x50\
+"
+
+qt_resource_name = b"\
+\x00\x0b\
+\x0c\x6b\x3c\xf3\
+\x00\x73\
+\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x73\
+\x00\x09\
+\x08\xaa\x11\x25\
+\x00\x52\
+\x00\x61\x00\x72\x00\x65\x00\x53\x00\x74\x00\x79\x00\x6c\x00\x65\
+\x00\x0d\
+\x02\x0d\x3c\x07\
+\x00\x64\
+\x00\x72\x00\x6f\x00\x70\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0d\
+\x02\x33\xbc\x47\
+\x00\x73\
+\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0e\
+\x03\xc2\xd5\xc3\
+\x00\x73\
+\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x2e\x00\x71\x00\x73\x00\x73\
+\x00\x0b\
+\x04\x37\x88\x27\
+\x00\x73\
+\x00\x6f\x00\x72\x00\x74\x00\x2d\x00\x75\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x08\x8b\x0b\xa7\
+\x00\x73\
+\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x18\
+\x08\xb9\x19\xc7\
+\x00\x68\
+\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
+\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\x2d\x1b\xc7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x0d\xb0\xb1\xa7\
+\x00\x68\
+\x00\x61\x00\x6c\x00\x66\x00\x2d\x00\x73\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x13\
+\x0d\xf4\xfe\xa7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+\x00\x13\
+\x0f\xf8\x57\x27\
+\x00\x73\
+\x00\x71\x00\x75\x00\x61\x00\x72\x00\x65\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
+\x00\x00\x00\x34\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x54\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbe\
+\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\x7b\
+\x00\x00\x00\x96\x00\x01\x00\x00\x00\x01\x00\x00\x0e\x00\
+\x00\x00\x00\xb2\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xcf\
+\x00\x00\x00\xcc\x00\x01\x00\x00\x00\x01\x00\x00\x0f\x85\
+\x00\x00\x01\x02\x00\x01\x00\x00\x00\x01\x00\x00\x10\x34\
+\x00\x00\x01\x1c\x00\x01\x00\x00\x00\x01\x00\x00\x10\xd4\
+\x00\x00\x01\x40\x00\x01\x00\x00\x00\x01\x00\x00\x11\x83\
+\x00\x00\x01\x6c\x00\x01\x00\x00\x00\x01\x00\x00\x12\x23\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x34\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x8e\x2e\x40\x37\xd2\
+\x00\x00\x00\x54\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbe\
+\x00\x00\x01\x8e\x2e\x40\x37\xd2\
+\x00\x00\x00\x74\x00\x01\x00\x00\x00\x01\x00\x00\x01\x7b\
+\x00\x00\x01\x90\x54\xc2\x8c\xfd\
+\x00\x00\x00\x96\x00\x01\x00\x00\x00\x01\x00\x00\x0e\x00\
+\x00\x00\x01\x8e\x2e\x40\x37\xd2\
+\x00\x00\x00\xb2\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xcf\
+\x00\x00\x01\x86\xbc\x9a\x01\x62\
+\x00\x00\x00\xcc\x00\x01\x00\x00\x00\x01\x00\x00\x0f\x85\
+\x00\x00\x01\x86\xbc\x9a\x01\x5f\
+\x00\x00\x01\x02\x00\x01\x00\x00\x00\x01\x00\x00\x10\x34\
+\x00\x00\x01\x86\xbc\x9a\x01\x5d\
+\x00\x00\x01\x1c\x00\x01\x00\x00\x00\x01\x00\x00\x10\xd4\
+\x00\x00\x01\x86\xbc\x9a\x01\x60\
+\x00\x00\x01\x40\x00\x01\x00\x00\x00\x01\x00\x00\x11\x83\
+\x00\x00\x01\x86\xbc\x9a\x01\x5d\
+\x00\x00\x01\x6c\x00\x01\x00\x00\x00\x01\x00\x00\x12\x23\
+\x00\x00\x01\x86\xbc\x9a\x01\x62\
+"
+
+qt_version = [int(v) for v in QtCore.qVersion().split('.')]
+if qt_version < [5, 8, 0]:
+ rcc_version = 1
+ qt_resource_struct = qt_resource_struct_v1
+else:
+ rcc_version = 2
+ qt_resource_struct = qt_resource_struct_v2
+
+def qInitResources():
+ QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
From 0e77e4563730a4171e177fe6221051e2048c9ed6 Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 26 Jun 2024 16:42:57 +0300
Subject: [PATCH 38/43] stylesheets: add version iterator
---
rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss | 3 +++
rare/resources/stylesheets/RareStyle/stylesheet.qss | 3 +++
2 files changed, 6 insertions(+)
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
index 0be8478e3..ea5ab56ec 100644
--- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
+++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
@@ -26,6 +26,9 @@ install-disabled: #020 #7D5380 -- install
uninstall-normal: #700 #FFB085 -- uninstall
uninstall-hover: #500 #BF8464 -- uninstall
uninstall-disabled: #200 #805843 -- uninstall
+
+If you want to regenerate the file without any change, increase the following value
+Version iterator: 1
*/
* {
diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss
index d026c8207..986be9031 100644
--- a/rare/resources/stylesheets/RareStyle/stylesheet.qss
+++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss
@@ -26,6 +26,9 @@ install-disabled: #020 rgb( 0, 34, 0) -- install
uninstall-normal: #700 rgb(119, 0, 0) -- uninstall
uninstall-hover: #500 rgb( 85, 0, 0) -- uninstall
uninstall-disabled: #200 rgb( 34, 0, 0) -- uninstall
+
+If you want to regenerate the file without any change, increase the following value
+Version iterator: 1
*/
* {
From cfb441b939f4e0c28070bfae29ec3dd26a08f7d5 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 26 Jun 2024 20:37:41 +0300
Subject: [PATCH 39/43] HeadBar: add icon to integrations button for alignment
---
rare/components/tabs/__init__.py | 7 +++----
rare/components/tabs/games/head_bar.py | 4 ++--
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py
index 741a0117f..647d4f1d0 100644
--- a/rare/components/tabs/__init__.py
+++ b/rare/components/tabs/__init__.py
@@ -7,7 +7,6 @@
from .downloads import DownloadsTab
from .games import GamesLibrary
from .settings import SettingsTab
-from .settings.debug import DebugSettings
from .store import StoreTab
from .tab_widgets import MainTabBar, TabButtonWidget
@@ -29,18 +28,18 @@ def __init__(self, parent):
# Generate Tabs
self.games_tab = GamesLibrary(self)
- self.games_index = self.addTab(self.games_tab, qta_icon("mdi.gamepad-circle"), self.tr("Games"))
+ self.games_index = self.addTab(self.games_tab, self.tr("Games"))
# Downloads Tab after Games Tab to use populated RareCore games list
self.downloads_tab = DownloadsTab(self)
- self.downloads_index = self.addTab(self.downloads_tab, qta_icon("mdi.download-circle"), "")
+ self.downloads_index = self.addTab(self.downloads_tab, "")
self.downloads_tab.update_title.connect(self.__on_downloads_update_title)
self.downloads_tab.update_queues_count()
self.setTabEnabled(self.downloads_index, not self.args.offline)
if not self.args.offline:
self.store_tab = StoreTab(self.core, parent=self)
- self.store_index = self.addTab(self.store_tab, qta_icon("mdi.storefront"), self.tr("Store (Beta)"))
+ self.store_index = self.addTab(self.store_tab, self.tr("Store (Beta)"))
self.setTabEnabled(self.store_index, not self.args.offline)
# Space Tab
diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py
index b2ca6d195..2811f8bf5 100644
--- a/rare/components/tabs/games/head_bar.py
+++ b/rare/components/tabs/games/head_bar.py
@@ -1,7 +1,6 @@
import logging
-from PyQt5.QtCore import QSettings, pyqtSlot, QSize, Qt
-from PyQt5.QtCore import pyqtSignal
+from PyQt5.QtCore import QSettings, pyqtSignal, pyqtSlot, QSize, Qt
from PyQt5.QtWidgets import (
QHBoxLayout,
QWidget,
@@ -108,6 +107,7 @@ def __init__(self, parent=None):
integrations = QPushButton(parent=self)
integrations.setText(self.tr("Integrations"))
+ integrations.setIcon(qta_icon("mdi.tools"))
integrations.setMenu(integrations_menu)
self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search"))
From 1cdc856b440d8e3c88d6df75e0467ff0cbfb5930 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Wed, 3 Jul 2024 17:14:44 +0300
Subject: [PATCH 40/43] project: fix setup.py
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index 97646a5fc..b86f253b3 100644
--- a/setup.py
+++ b/setup.py
@@ -13,7 +13,7 @@
"setuptools",
"legendary-gl>=0.20.34",
"orjson",
- "vdf"
+ "vdf",
'pywin32; platform_system == "Windows"',
]
From f1cbf07605422205a5f5571b9babc0c6cd3fa597 Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sun, 7 Jul 2024 22:31:43 +0300
Subject: [PATCH 41/43] MainWindow: remove subtitle from window
---
rare/components/main_window.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rare/components/main_window.py b/rare/components/main_window.py
index 4f46b97ec..301f194fa 100644
--- a/rare/components/main_window.py
+++ b/rare/components/main_window.py
@@ -44,7 +44,7 @@ def __init__(self, parent=None):
self.args = RareCore.instance().args()
self.settings = QSettings()
- self.setWindowTitle("Rare - GUI for legendary")
+ self.setWindowTitle(QApplication.applicationName())
self.tab_widget = MainTabWidget(self)
self.tab_widget.exit_app.connect(self.__on_exit_app)
self.setCentralWidget(self.tab_widget)
From 06b88c9dbbc227d707c992d46de6d1f77fb0c29a Mon Sep 17 00:00:00 2001
From: Stelios Tsampas
Date: Wed, 3 Jul 2024 11:20:40 +0300
Subject: [PATCH 42/43] requirements: don't use cefpython3 on windows and macos
---
requirements-webview.txt | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/requirements-webview.txt b/requirements-webview.txt
index 27c762606..b57677fc9 100644
--- a/requirements-webview.txt
+++ b/requirements-webview.txt
@@ -1,6 +1,7 @@
# pywebview with QtWebEngine backend has issues with EGS login form, so use GTK
pywebview[gtk]; platform_system == "Linux"
pywebview[gtk]; platform_system == "FreeBSD"
-pythonnet>=3.0.0rc4; platform_system == "Windows"
-cefpython3; platform_system == "Windows"
-pywebview[cef]; platform_system == "Windows"
+pythonnet; platform_system == "Windows"
+pywebview; platform_system == "Windows"
+pyobjc; platform_system == "Darwin"
+pywebview; platform_system == "Darwin"
From 25a0ee4be5492ed28bd1e248284c11950098599d Mon Sep 17 00:00:00 2001
From: loathingKernel <142770+loathingKernel@users.noreply.github.com>
Date: Sun, 14 Jul 2024 12:49:45 +0300
Subject: [PATCH 43/43] workflows: install pypresence on MacOS
---
.github/workflows/job_macos.yml | 5 +++--
.github/workflows/job_nuitka-win.yml | 19 ++++++++++++-------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/job_macos.yml b/.github/workflows/job_macos.yml
index 16e7a5928..bdf86401d 100644
--- a/.github/workflows/job_macos.yml
+++ b/.github/workflows/job_macos.yml
@@ -23,12 +23,13 @@ jobs:
- name: Install Target Dependencies
run: |
pip install -r requirements.txt
+ pip install -r requirements-presence.txt
- name: Move files
run: mv rare/__main__.py __main__.py
- name: Build
run: >-
pyinstaller -F --name Rare
- --add-data "rare/resources/languages/*:rare/resources/languages"
+ --add-data "rare/resources/languages/rare_*.qm:rare/resources/languages/"
--add-data "rare/resources/images/*:rare/resources/images/"
--windowed
--icon rare/resources/images/Rare.icns
@@ -43,4 +44,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: Rare-${{ inputs.version }}.dmg
- path: Rare.dmg
\ No newline at end of file
+ path: Rare.dmg
diff --git a/.github/workflows/job_nuitka-win.yml b/.github/workflows/job_nuitka-win.yml
index 3cf181427..d10f59153 100644
--- a/.github/workflows/job_nuitka-win.yml
+++ b/.github/workflows/job_nuitka-win.yml
@@ -16,7 +16,7 @@ jobs:
- uses: actions/setup-python@v4
with:
cache: pip
- python-version: '3.9'
+ python-version: '3.12'
check-latest: true
architecture: x64
- name: Install build dependencies
@@ -31,7 +31,7 @@ jobs:
--assume-yes-for-downloads
--msvc=latest
--lto=yes
- --jobs=2
+ --jobs=4
--static-libpython=no
--standalone
--enable-plugin=anti-bloat
@@ -42,18 +42,23 @@ jobs:
--follow-imports
--nofollow-import-to="*.tests"
--nofollow-import-to="*.distutils"
+ --nofollow-import-to="distutils"
+ --nofollow-import-to="unittest"
+ --nofollow-import-to="pydoc"
+ --nofollow-import-to="tkinter"
+ --nofollow-import-to="test"
--prefer-source-code
--include-package=pypresence
--include-package-data=qtawesome
- --include-data-dir=rare\resources\images=rare\resources\images
- --include-data-files=rare\resources\languages=rare\resources\languages="*.qm"
+ --include-data-dir=rare\resources\images\=rare\resources\images\
+ --include-data-files=rare\resources\languages\=rare\resources\languages\="rare_*.qm"
--windows-icon-from-ico=rare\resources\images\Rare.ico
- --windows-company-name=Rare
+ --windows-company-name=RareDevs
--windows-product-name=Rare
--windows-file-description=rare.exe
--windows-file-version=${{ inputs.version }}
--windows-product-version=${{ inputs.version }}
- --disable-console
+ --windows-console-mode=disable
rare
- name: Fix QtNetwork SSL
run: |
@@ -67,4 +72,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: Rare-Windows-${{ inputs.version }}.zip
- path: Rare-Windows.zip
\ No newline at end of file
+ path: Rare-Windows.zip