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