pax_global_header00006660000000000000000000000064151431460770014522gustar00rootroot0000000000000052 comment=7b9c8e150bca3e7833d5cebf7a0b502ca86be879 kolunmi-bazaar-7b9c8e1/000077500000000000000000000000001514314607700150625ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.clang-format000066400000000000000000000007531514314607700174420ustar00rootroot00000000000000BasedOnStyle: GNU AlwaysBreakAfterDefinitionReturnType: All BreakBeforeBinaryOperators: None BinPackParameters: false SpaceAfterCStyleCast: true PointerAlignment: Right ColumnLimit: 0 AlignArrayOfStructures: Right AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignConsecutiveBitFields: true AlignConsecutiveDeclarations: true AlignConsecutiveMacros: true AllowShortCaseLabelsOnASingleLine: true AlignEscapedNewlines: true AlignOperands: true AlignTrailingComments: Always kolunmi-bazaar-7b9c8e1/.devcontainer/000077500000000000000000000000001514314607700176215ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.devcontainer/Dockerfile000066400000000000000000000007241514314607700216160ustar00rootroot00000000000000FROM fedora:rawhide RUN dnf update -y && dnf install -y \ meson \ ninja \ cmake \ just \ git \ blueprint-compiler \ desktop-file-utils \ gtk4-devel \ libadwaita-devel \ libdex-devel \ flatpak-devel \ libxmlb-devel \ appstream-devel \ glycin-devel \ glycin-gtk4-devel \ libyaml-devel \ libsoup3-devel \ json-glib-devel \ md4c-devel \ webkitgtk6.0-devel \ libsecret-devel \ clangd kolunmi-bazaar-7b9c8e1/.devcontainer/devcontainer.json000066400000000000000000000013661514314607700232030ustar00rootroot00000000000000{ "name": "Bazaar devcontainer", "build": { "dockerfile": "Dockerfile" }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { "installZsh": "false", "username": "vscode", "userUid": "1000", "userGid": "1000", "upgradePackages": "true" } }, "remoteUser": "vscode", "customizations": { "vscode": { "extensions": [ "ms-vscode.cpptools-extension-pack", "bodil.blueprint-gtk" ] } }, // Wayland support "containerEnv": { "WAYLAND_DISPLAY": "${localEnv:WAYLAND_DISPLAY}", "XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}", "XDG_SESSION_TYPE": "${localEnv:XDG_SESSION_TYPE}" }, "mounts": [ "source=${localEnv:XDG_RUNTIME_DIR},target=${localEnv:XDG_RUNTIME_DIR},type=bind,consistency=cached" ] }kolunmi-bazaar-7b9c8e1/.foundry/000077500000000000000000000000001514314607700166265ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.foundry/.gitignore000066400000000000000000000000221514314607700206100ustar00rootroot00000000000000tmp/ user/ cache/ kolunmi-bazaar-7b9c8e1/.github/000077500000000000000000000000001514314607700164225ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.github/FUNDING.yml000066400000000000000000000001201514314607700202300ustar00rootroot00000000000000github: [kolunmi] ko_fi: kolunmi custom: - https://ko-fi.com/alexandervanhee kolunmi-bazaar-7b9c8e1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001514314607700206055ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.github/ISSUE_TEMPLATE/bug_form.yml000066400000000000000000000037321514314607700231350ustar00rootroot00000000000000name: Bug Report description: Report an issue about using Bazaar body: - type: markdown attributes: value: | Thank you for taking the time to fill out this bug report! - type: textarea id: describe-bug attributes: label: Describe the bug description: A clear and concise description of what the bug is. If you are reporting a crash with the flatpak version please follow https://docs.flatpak.org/en/latest/debugging.html placeholder: Tell us what happened! value: "When I entered 2 + 2, I got the answer 6." validations: required: true - type: input id: os attributes: label: OS description: Operating system (and desktop environment) placeholder: , validations: required: true - type: textarea id: version attributes: label: Version description: | Please check the current version of Bazaar (Main Window > About Bazaar) so we can more easily indentify issues. Output of `flatpak info io.github.kolunmi.Bazaar`. If you are on Bazzite please run `rpm -qi bazaar` validations: required: true - type: textarea id: flatpak-remotes attributes: label: Configured Flatpak Remotes description: | Currently there are issues with user remotes. Please run `flatpak remotes`. placeholder: | Name Options flathub system validations: required: true - type: textarea id: hardware attributes: label: Hardware description: | If you are reporting performance issues or crashes then please fill this out. placeholder: | CPU: Ryzen 5 7600 GPU: RX 6750 XT RAM: 16GB validations: required: false - type: textarea id: extra-context attributes: label: Extra information or context description: Add any other context about the problem here. kolunmi-bazaar-7b9c8e1/.github/workflows/000077500000000000000000000000001514314607700204575ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/.github/workflows/build-flatpak.yml000066400000000000000000000017201514314607700237210ustar00rootroot00000000000000on: push: branches: [main] pull_request: paths-ignore: - "**.md" - "docs/*" - "screenshots/*" - "translators.sh" - ".github/ISSUE_TEMPLATE/**" name: CI Build Flatpak jobs: flatpak: name: "Flatpak" container: image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-49 options: --privileged strategy: matrix: variant: - arch: x86_64 runner: ubuntu-latest # no latest for ARM :( - arch: aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.variant.runner }} steps: - uses: actions/checkout@v4 with: submodules: recursive - uses: flatpak/flatpak-github-actions/flatpak-builder@v6 with: bundle: Bazaar.flatpak manifest-path: build-aux/flatpak/io.github.kolunmi.Bazaar.json cache-key: flatpak-builder-${{ github.sha }} arch: ${{ matrix.variant.arch }} verbose: true kolunmi-bazaar-7b9c8e1/.gitignore000066400000000000000000000001641514314607700170530ustar00rootroot00000000000000build .cache .flatpak-builder rpmbuild repo *.flatpak *.mo gpgme libassuan libxml2 /subprojects/blueprint-compiler kolunmi-bazaar-7b9c8e1/.gitmodules000066400000000000000000000002141514314607700172340ustar00rootroot00000000000000[submodule "flatpak-builder-tools"] path = build-aux/flatpak/flatpak-builder-tools url = https://github.com/flatpak/flatpak-builder-tools kolunmi-bazaar-7b9c8e1/CODESTYLE.md000066400000000000000000000042161514314607700167420ustar00rootroot00000000000000# Bazaar Code Style Rules Thanks for your interest in contributing to Bazaar! Here are the code style rules which you must adhere to in order to keep a clean and consistent codebase: ## Formatting Bazaar uses the GNU C style. The `.clang-format` file at the root project directory will configure `clang-format` to follow the proper conventions. ## General Rules * _Always_ prefer using `g_auto`, `g_autofree`, `g_autoptr`, `g_autolist`, and `g_autoslist` over calling `*_unref` or `*_free` manually. If a variable needs to escape the scope, either increment its reference count or use `g_steal_pointer`. * When you are otherwise forced to call `*_unref` or `*_free` manually, _always_ use `g_clear_pointer` or `g_clear_object`. This prevents use-after-free bugs. * _Always_ prefer using the libdex API over the older GTask API for async operations. It is cleaner and easier to read, and it prevents callbacks from cluttering the source file. This often means spawning a fiber and using `dex_await`. To wrap a call to a function which uses GTask, use [dex_async_pair_new](https://gnome.pages.gitlab.gnome.org/libdex/libdex-1/class.AsyncPair.html). See `src/bz-download-worker.c` for an example of this. * _Always_ declare variables first and initialize them to `0` or `NULL`. Function calls must not be made in the declaration section of a scope. * The general layout of a `.c` file must be in this order: 1. License comment with your name mentioned 2. `#include "config.h"` 3. Include external headers, like `#include ` 4. Include internal headers, like `#include "bz-env.h"` 5. If applicable, define the class's internal struct 6. If applicable, `G_DEFINE_TYPE (...)` or equivalent 7. If applicable, the property enums and `static GParamSpec *props[LAST_PROP] = { 0 };` 8. Declare static functions (which are not virtual methods) 9. If applicable, define class virtual methods (`dispose`, `class_init`, `snapshot`, etc) 10. Define the public API (non-`static` functions which were declared in this `.c` file's associated `.h` header file) 11. Define the static functions which were previously declared in this file kolunmi-bazaar-7b9c8e1/CONTRIBUTING.md000066400000000000000000000067551514314607700173300ustar00rootroot00000000000000# Contributing Guide Thank you for contributing to Bazaar! Here are some instructions to get you started. * [New Contributor Guide](#contributing-guide) * [Ways to Contribute](#ways-to-contribute) * [Find an Issue](#find-an-issue) * [Ask for Help](#ask-for-help) * [Pull Request Lifecycle](#pull-request-lifecycle) * [Development Environment Setup](#development-environment-setup) * [Sign Your Commits](#sign-your-commits) * [Pull Request Checklist](#pull-request-checklist) Welcome! We are glad that you are here! 💖 As you get started, you are in the best position to give us feedback on areas of our project that we need help with including: * Problems found during setting up a new developer environment * Documentation * Bugs in our automation scripts and actions If anything doesn't make sense, or doesn't work when you run it, please open a bug report and let us know! ## Ways to Contribute We welcome many different types of contributions including: * New features * Builds, CI/CD * Bug fixes * Documentation * Issue Triage * Answering questions in Discussions * Release management * [Translations](https://github.com/kolunmi/bazaar/blob/master/TRANSLATORS.md) - follow the dedicated instructions in that document ## Find an Issue These are the issues that need the most amount of attention and would be an effective way to get started: - [Help Wanted issues](https://github.com/kolunmi/bazaar/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22) - [Good first issues](https://github.com/kolunmi/bazaar/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) Sometimes there won’t be any issues with these labels. That’s ok! There is likely still something for you to work on. If you want to contribute but you don’t know where to start or can't find a suitable issue then feel free to post on the [discussion forum](https://github.com/kolunmi/bazaar/discussions) Once you see an issue that you'd like to work on, please post a comment saying that you want to work on it. Something like "I want to work on this" is fine. ## Ask for Help The best way to reach us with a question when contributing is to ask on: * The original github issue you want to contribute to * The [discussions](https://github.com/kolunmi/bazaar/discussions) area ## Building GNOME Builder or ```sh just build-flatpak ``` See [Flatpak Docs](https://docs.flatpak.org/en/latest/flatpak-builder.html) ### Find out which version is installed for bug reports ```sh flatpak info io.github.kolunmi.Bazaar ``` ### Verbose output ```sh G_MESSAGES_DEBUG=all flatpak run io.github.kolunmi.Bazaar ``` ## Pull Request Lifecycle [Instructions](https://contribute.cncf.io/maintainers/github/templates/required/contributing/#pull-request-lifecycle) ⚠️ **Explain your pull request process** ## Sign Your Commits [Instructions](https://contribute.cncf.io/maintainers/github/templates/required/contributing/#sign-your-commits) ## Pull Request Checklist When you submit your pull request, or you push new commits to it, our automated systems will run some checks on your new code. We require that your pull request passes these checks, but we also have more criteria than just that before we can accept and merge it. We recommend that you check the following things locally before you submit your code: - [ ] Use the GNU Style Guide - [ ] Format your commits using `clang-format`; see [.clang-format](/.clang-format) - [ ] Follow the [GNOME Commit Style](https://handbook.gnome.org/development/commit-messages.html) kolunmi-bazaar-7b9c8e1/COPYING000066400000000000000000001045201514314607700161170ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . kolunmi-bazaar-7b9c8e1/Justfile000066400000000000000000000046751514314607700166060ustar00rootroot00000000000000# These are just convenience scripts, NOT a build system! appid := env("BAZAAR_APPID", "io.github.kolunmi.Bazaar") manifest := "./build-aux/flatpak/" + appid + ".json" branch := env("BAZAAR_BRANCH", "master") just := just_executable() alias run := run-base run-base: build-base ./build/src/bazaar build-base: meson setup build --wipe ninja -C build build-flatpak $manifest=manifest $branch=branch: #!/usr/bin/env bash set -xeuo pipefail flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo FLATPAK_BUILDER_DIR=$(realpath ".flatpak-builder") BUILDER_ARGS+=(--default-branch="${branch}") BUILDER_ARGS+=(--state-dir="${FLATPAK_BUILDER_DIR}/flatpak-builder") BUILDER_ARGS+=("--user") BUILDER_ARGS+=("--ccache") BUILDER_ARGS+=("--force-clean") BUILDER_ARGS+=("--install") BUILDER_ARGS+=("--disable-rofiles-fuse") BUILDER_ARGS+=("${FLATPAK_BUILDER_DIR}/build-dir") BUILDER_ARGS+=("${manifest}") if which flatpak-builder &>/dev/null ; then flatpak-builder "${BUILDER_ARGS[@]}" else flatpak run org.flatpak.Builder "${BUILDER_ARGS[@]}" fi build-flatpak-bundle $appid=appid: flatpak build-export repo "${FLATPAK_BUILDER_DIR}/build-dir" flatpak build-bundle repo "${appid}".flatpak "${appid}" build-rpm: #!/usr/bin/env bash mkdir -p rpmbuild podman run --rm -i -v .:/build:Z -v ./rpmbuild:/root/rpmbuild:Z registry.fedoraproject.org/fedora:latest <<'EOF' set -xeuo pipefail dnf install -y rpmdevtools mkdir -p $HOME/rpmbuild/SOURCES RPMDIR="/build/build-aux/rpm" cp "${RPMDIR}"/* $HOME/rpmbuild/SOURCES spectool -agR "${RPMDIR}"/bazaar.spec dnf builddep -y "${RPMDIR}"/bazaar.spec rpmbuild -bb "${RPMDIR}"/bazaar.spec EOF [private] default: @{{ just }} --list # Check just Syntax [group('just')] check: #!/usr/bin/bash find . -type f -name "*.just" | while read -r file; do echo "Checking syntax: $file" {{ just }} --unstable --fmt --check -f $file done echo "Checking syntax: Justfile" {{ just }} --unstable --fmt --check -f Justfile # Fix {{ just }} Syntax [group('{{ just }}')] fix: #!/usr/bin/bash find . -type f -name "*.just" | while read -r file; do echo "Checking syntax: $file" {{ just }} --unstable --fmt -f $file done echo "Checking syntax: Justfile" {{ just }} --unstable --fmt -f Justfile || { exit 1; } update-flatpak: kolunmi-bazaar-7b9c8e1/README.md000066400000000000000000000146501514314607700163470ustar00rootroot00000000000000


Bazaar

Discover and install applications

Screenshot showing Bazaar's Flathub page
> [!NOTE] > If you are a distributor/packager who would like to learn how to > customize Bazaar, take a look at the [docs](/docs/overview.md). > [!NOTE] > If you are interested in contributing code to Bazaar (Thank you!), > please see the [style rules](/CODESTYLE.md). > [!NOTE] > If you are interested in contributing translations to Bazaar (Thank > you!), please see the [translators introduction](/TRANSLATORS.md). Bazaar is a new app store for GNOME with a focus on discovering and installing applications and add-ons from Flatpak remotes, particularly [Flathub](https://flathub.org/). It emphasizes supporting the developers who make the Linux desktop possible. Bazaar features a "curated" tab that can be configured by distributors to allow for a more localized experience. Bazaar is fast and highly multi-threaded, guaranteeing a smooth experience in the user interface. You can queue as many downloads as you wish and run them while perusing Flathub's latest releases. This is due to the UI being completely decoupled from all backend operations. It runs as a service, meaning state will be maintained even if you close all windows, and implements the gnome-shell search provider dbus interface. A krunner [plugin](https://github.com/ublue-os/krunner-bazaar) is available for use on the KDE Plasma desktop. Thanks to [Tobias Bernard](https://tobiasbernard.com/), [Jakub Steiner](http://jimmac.eu), and [Sam Hewitt](https://snwh.org) for designing Bazaar's market stall icon. ### Installing Pre-built binaries are distributed via Flathub and GitHub actions: Get it on Flathub [![Build Flatpak and Upload Artifact](https://github.com/kolunmi/bazaar/actions/workflows/build-flatpak.yml/badge.svg)](https://github.com/kolunmi/bazaar/actions/workflows/build-flatpak.yml) ### Supporting If you would like to support me and the development of this application (Thank you!), I have a ko-fi here! [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/kolunmi) Thanks to everyone in the GNOME development community for creating such an awesome desktop environment! ### Contributing If you would like to try this project on your local machine, clone it on the cli and type these commands inside the project root: ```sh meson setup build --prefix=/usr/local ninja -C build sudo ninja -C build install bazaar ``` You will need the following dependencies installed, along with a C compiler, meson, and ninja: | Dep Name | `pkg-config` Name | Min Version | Justification | |---------------------------------------------------------|-------------------|------------------------|-----------------------------------------------------| | [gtk4](https://gitlab.gnome.org/GNOME/gtk/) | `gtk4` | enforced by libadwaita | GUI | | [libadwaita](https://gitlab.gnome.org/GNOME/libadwaita) | `libadwaita-1` | `1.8` | GNOME styling | | [libdex](https://gitlab.gnome.org/GNOME/libdex) | `libdex-1` | `1.0` | Async helpers | | [flatpak](https://github.com/flatpak/flatpak) | `flatpak` | `1.9` | Flatpak installation management | | [appstream](https://github.com/ximion/appstream) | `appstream` | `1.0` | Download application metadata | | [xmlb](https://github.com/hughsie/libxmlb) | `xmlb` | `0.3.4` | Handle binary xml appstream bundles/Parse plain xml | | [glycin](https://gitlab.gnome.org/GNOME/glycin) | `glycin-2` | `2.0` | Retrieve and decode image uris | | [glycin-gtk4](https://gitlab.gnome.org/GNOME/glycin) | `glycin-gtk4-2` | `2.0` | Convert glycin frames to `GdkTexture`s | | [libyaml](https://github.com/yaml/libyaml) | `yaml-0.1` | `0.2.5` | Parse YAML configs | | [libsoup](https://gitlab.gnome.org/GNOME/libsoup) | `libsoup-3.0` | `3.6.0` | HTTP operations | | [json-glib](https://gitlab.gnome.org/GNOME/json-glib) | `json-glib-1.0` | `1.10.0` | Parse HTTP replies from Flathub | | [md4c](https://github.com/mity/md4c) | `md4c` | `0.5.1` | Parse markdown (.md) | | [webkitgtk](https://webkitgtk.org/) | `webkitgtk-6.0` | `2.50.2` | Render web views | | [libsecret](https://gitlab.gnome.org/GNOME/libsecret) | `libsecret-1` | `0.20` | Store Flathub account information | #### Code of Conduct This project adheres to the [GNOME Code of Conduct](https://conduct.gnome.org/). By participating through any means, including PRs, Issues or Discussions, you are expected to uphold this code. ### What people are saying - [Why Bazaar Is the Best Flatpak App Store You’re Not Using](https://fossforce.com/2025/10/why-bazaar-is-the-best-flatpak-app-store-youre-not-using/) - [Bazaar is a game changer](https://gardinerbryant.com/linux-software-management-is-about-to-change-with-bazaar/) - [Bazaar is a Slick New Desktop Flathub Frontend](https://www.omgubuntu.co.uk/2025/08/bazaar-new-flatpak-app-store-gnome-linux) - [Bazaar Is the Flatpak Store GNOME Always Needed](https://linuxiac.com/bazaar-is-the-flatpak-store-gnome-always-needed/) kolunmi-bazaar-7b9c8e1/TRANSLATORS-FR.md000066400000000000000000000122561514314607700175330ustar00rootroot00000000000000# Instructions pour les traducteurs Merci pour votre intérêt à traduire Bazaar ! 🏷️🗺️💜 Ceci est une adaptation française de `TRANSLATORS.md` pour la traduction française spécifiquement. Voici quelques règles simples: * Vous devez parler couramment Français et avoir une bonne compréhension de l'anglais * L'utilisation de modèles de langue (IA) pour générer du texte dans les fichiers est interdite (N'importe qui pourrait le faire). Si vous le faite, vous serez banni du projet par le créateur * Le but n'est pas de fournir une traduction littérale, mais une expérience claire et complète aux utilisateurs francophones * Utilisez `chore(po): update French translation` comme titre de Pull Request pour être uniforme avec les autres langues > Note : La section "Recommandées" dépend du système dans lequel est fourni Bazaar - de plus il n'y a pas encore de système de traduction pour cette page là. ## Installation > Pour traduire et soumettre votre traduction, il est recommandé de savoir utiliser Git, la plateforme Github et un éditeur de traductions comme [celui fourni par Gnome](https://flathub.org/fr/apps/org.gnome.Gtranslator) par exemple. Vous devrez fork le projet et le cloner sur votre machine - afin de pouvoir soumettre votre traduction dans un Pull Request après. Ensuite vous devrez vous assurez que le dossier actuellement ouvert est le dossier racine de Bazaar. ## Mise en place ### Automatique Une fois que c'est fait, vous pourrez exécuter `./translators.sh` et suivre les différentes instructions (en anglais). Le script va vous montrer l'état actuel de `po/LINGUAS`. Si tout est correct, tappez `Y` et appuyez sur entrée. Après cela, le script va vous demander votre code de langue (`fr`), écrivez le et appuyez sur entrée. Le script va générer un nouveau fichier `po` ou mettre à jour le fichier existant avec de nouvelles entrées traduisibles. Vous êtes dorénavant prêts à ouvrir le fichier `po` dans votre éditeur de texte ou votre éditeur de traduction ([POEdit](https://flathub.org/apps/net.poedit.Poedit), [GTranslator](https://flathub.org/apps/org.gnome.Gtranslator), [Lokalize](https://flathub.org/apps/org.kde.lokalize), etc.) et à commencer à traduire. Une fois que vous avez fini, envoyez vos commits et soumettez un Pull Request sur Github. Faites attention à n'envoyez que le(s) fichier(s) liés à votre traduction. ### Manuelle Une fois que c'est fait, mettez en place meson avec le flag `im_a_translator` mis à `true`: ```sh meson setup build -Dim_a_translator=true ``` Ensuite ouvrez le dossier `build`: ```sh cd build ``` Et exécutez la commande suivante pour générer le fichier `pot` (**P**ortable **O**bject **T**emplate) principal : ```sh meson compile bazaar-pot ``` Il se pourrait que vous verrez pas mal de messages disant que l'extension `blp` est inconnue - vous pouvez les ignorer. Enfin, toujours dans le dossier build, exécutez la commande suivante pour mettre à jour ou créer le fichier `po` : ```sh meson compile bazaar-update-po ``` Vous êtes dorénavant prêts à ouvrir le fichier `po` dans votre éditeur de texte ou votre éditeur de traduction ([POEdit](https://flathub.org/apps/net.poedit.Poedit), [GTranslator](https://flathub.org/apps/org.gnome.Gtranslator), [Lokalize](https://flathub.org/apps/org.kde.lokalize), etc.) et à commencer à traduire. Une fois que vous avez fini, envoyez vos commits et soumettez un Pull Request sur Github. Faites attention à n'envoyez que le(s) fichier(s) liés à votre traduction. ## Mettre à jour la traduction existante Générez à nouveau un fichier `.pot` (si nécessaire) à l'aide des commandes ci-dessus. ```sh msgmerge --update --verbose po/fr.po po/bazaar.pot ``` Veuillez créer un commit séparé pour la mise à jour précédente dans votre Pull Request afin de faciliter la révision. Merci ! ## Tester la traduction Depuis le dossier de Bazaar, exécutez la commande suivante : ```sh msgfmt po/fr.po -o bazaar.mo ``` Ensuite copiez le fichier `.mo` pour que Bazaar puisse le voir : ```sh sudo cp bazaar.mo /var/lib/flatpak/runtime/io.github.kolunmi.Bazaar.Locale/x86_64/stable/active/files/fr/share/fr/LC_MESSAGES/ ``` Assurez-vous d'abord de tuer le processus d'arrière-plan de Bazaar afin que les modifications/la langue souhaitées soient utilisées : ```sh killall bazaar ``` Et ensuite redémarrez Bazaar pour voir vos traductions ! >Si vous n'avez pas votre système en français, vous pouvez utiliser la commande suivante pour lancer Bazaar en français: ```sh LANGUAGE=fr flatpak run io.github.kolunmi.Bazaar ``` ## Notes des traducteurs Les processus automatiques et manuels peuvent générer des entrées marquées comme « floues » (`fuzzy`). Cela signifie que pour ces entrées, `gettext` a tenté de dériver une traduction préexistante. Certaines suites de traduction, comme Lokalize, utilisent ce marquage pour définir les chaînes comme non révisées et les supprimer lorsque l'entrée est marquée comme terminée. Lorsque vous travaillez avec des fichiers pot à l'aide d'un éditeur de texte, veillez à supprimer vous-même les marques `fuzzy` des entrées que vous considérez comme terminées, sinon votre traduction n'apparaîtra pas dans Bazaar. kolunmi-bazaar-7b9c8e1/TRANSLATORS-PL.md000066400000000000000000000103671514314607700175400ustar00rootroot00000000000000# Instrukcje dla tłumaczy Dziękuję za wasze zainteresowanie w tłumaczeniu Bazaar'u! 🏷️🗺️💜 Oto parę podstawowych zasad: * Musisz być biegły w języku, na który będziesz tłumaczyć. * Nie korzystaj z [SI](https://pl.wikipedia.org/wiki/Sztuczna_inteligencja), aby wygenerować tłumaczenie (Sam mógłbym to zrobić). Jeśli to zrobisz, zablokuję cię. * Jeśli edytujesz istniejące tłumaczenie zapoznaj się z `TRANSLATORS-[kod języka].md`, aby zapoznać się z zasadami obecnymi dla tego języka. Tłumaczenie na język polski: * Zanim rozpoczniesz tłumaczenie zapoznaj się z http://fsc.com.pl/poradnik/ * Przydatne strony: - Słownik Diki - https://www.diki.pl/ - Słownik Bab.la - https://bab.la/ - Słownik Cambridge - https://dictionary.cambridge.org/ * Słowniki zapisane w podpunkcie "Przydatne strony" mają funkcje tłumaczenia całych wyrażen i zdań, lecz proszę z nich nie korzystać, bo to nie są dokładne tłumaczenia. * Proszę również ogranicznyć korzystanie z serwisów takich jak Google Tłumacz, DeepL, itp. ## Procedury podstawowe Utwórz fork projektu (tak abyś mógł później zrobić pull request) i skonuj repozytorium. Następnie upewnij się, że jesteś w folderze odpowiadającym budową do podstawy repozytorium: ``` # Zmień '...' na adress URL twojego forku Bazaar'u, # w którym masz uprawnienia do zapisywania git clone ... cd bazaar ``` Nie zamykaj okna terminala # Konfiguracja Automatyczna Dodaj kod języka docelowego do `po/LINGUAS`. Na przykład, jeśli dodajesz hiszpańskie tłumaczenie, wstaw `es` do nowej linijki, upewniając się, że lista jest w kolejności alfabetycznej. Zatem jeśli `po/LINGUAS` wygląda następująco: ``` # Please keep this file sorted alphabetically. ab en_GB ms ``` musisz zmienić to na: ``` # Please keep this file sorted alphabetically. ab en_GB es ms ``` Jak już to zrobisz, możesz uruchomić `./translators.sh` i podążać za instrukcjami widocznymi na ekranie. Skrypt pokaże ci jak plik `po/LINGUAS` aktualnie wygląda, jeśli wszystko się zgadza naciśnij Y, a następnie enter. Następnie skrypt poprosi cię o wprowadzenie kodu języka docelowego, wpisz go, a następnie naciśnij enter. Następnie skrypt wygeneruje nowy plik `po` lub zaktualizuje istniejący, tak aby wszystkie przetłumaczalne linijki były dostępne. Teraz jesteś gotowy, aby otworzyć swój plik `po` w wybranym edytorze tekstu lub edytorze tłumaczeń (POEdit, GTranslator, Lokalize, itp.) i rozpocząć proces tłumaczenia. Jak już skończysz, skommituj swoje zmiany i utwórz pull request na githubie. # Konfiguracja Ręczna Jak już to zrobisz, skonfiguruj projekt za pomocą mesona z flagą `im_a_translator` ustawioną na `true`: ```sh meson setup build -Dim_a_translator=true ``` Dodaj kod języka docelowego do `po/LINGUAS`. Na przykład, jeśli dodajesz hiszpańskie tłumaczenie, wstaw `es` do nowej linijki, upewniając się, że lista jest w kolejności alfabetycznej. Zatem jeśli `po/LINGUAS` wygląda następująco: ``` # Please keep this file sorted alphabetically. ab en_GB ms ``` musisz zmienić to na: ``` # Please keep this file sorted alphabetically. ab en_GB es ms ``` Następnie, przejdź do katalogu `build`: ```sh cd build ``` Uruchom tą komendę, aby wygenerować główny plik `pot` (**P**ortable **O**bject **T**emplate): ```sh meson compile bazaar-pot ``` Na wierszu poleceń może wyskoczyć mnóstwo błędów o tym, że rozszerzenie `blp` jest nieznane. Możesz je zignorować. Wreszcie, wciąż będąc w katalogu `build`, uruchom następującą komendę, aby zaktualizować i/lub stworzyć pliki `po` (**P**ortable **O**bject): ```sh meson compile bazaar-update-po ``` Teraz jesteś gotowy, aby otworzyć swój plik `po` w wybranym edytorze tekstu lub edytorze tłumaczeń (POEdit, GTranslator, Lokalize, itp.) i rozpocząć proces tłumaczenia. Jak już skończysz, skommituj swoje zmiany i utwórz pull request na githubie. ## Testowanie swojego tłumaczenia Dostosuj do swojego [kodu języka](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)! ``` msgfmt po/de.po -o bazaar.mo sudo cp bazaar.mo /usr/share/locale/de/LC_MESSAGES/ ``` Upewnij się, że zatrzymasz wszystkie utuchomione instancje Bazaar'u. ``` killall bazaar ``` ``` LANGUAGE=de bazaar ``` kolunmi-bazaar-7b9c8e1/TRANSLATORS-ZH-CN.md000066400000000000000000000101051514314607700200320ustar00rootroot00000000000000# 翻译者指南 感谢你对翻译 Bazaar 的兴趣!🏷️🗺️💜 一些基本规则: * 你必须精通你所贡献的语言。 * **严禁**使用 LLM 生成译文。如果你这样做,你将被项目作者禁止参与此项目。 * flathub.org 本身就有良好的中文支持,因此 Bazaar 里 Flathub 页面的翻译应当和 flathub.org 高度一致。 即使 flathub.org 中个别翻译可能并不恰当,也请直接采用 flathub.org 的原文。 例如 https://flathub.org/zh-Hans/apps/category/game/subcategories/ArcadeGame 里将 Arcade 翻译为“游乐中心”,虽然实际上是“街机”更合适,但我们依旧选择直接采用“游乐中心”作为翻译 ## 统一术语 Uninstall 为“卸载”而非“删除” 根据: ```bash ❯ flatpak uninstall --help 用法: flatpak uninstall [选项…] [引用…] - 卸载应用程序或运行时 ... ``` Donate 为“捐助”而非“捐赠” 根据 flathub.org ## 基本流程 Fork 本项目(以便稍后开启 PR)并克隆仓库。然后确保你的当前目录位于 Bazaar 项目的根目录: ```sh # 将 '...' 替换为你拥有写入权限的 Bazaar Fork 的 URL git clone ... cd bazaar ``` # 自动设置 完成上述操作后,你可以运行 `./translators.sh` 并按照屏幕上的提示进行操作。该脚本会显示当前 `po/LINGUAS` 的内容。如果一切正确,输入 `Y` 并按回车。随后脚本会要求你输入语言代码,请输入并回车。脚本现在将生成一个新的 `po` 文件或更新现有文件,以便所有新的待翻译字符串都可用。 现在,你可以使用文本编辑器或翻译编辑器(POEdit、GTranslator、Lokalize 等)打开 `po` 文件并开始翻译。完成后,提交你的更改并在 GitHub 上提交 Pull Request(PR)。 # 手动设置 完成克隆后,使用 Meson 设置项目,并将 `im_a_translator` 标志设为 `true`: ```sh meson setup build -Dim_a_translator=true ``` 接下来,进入构建目录: ```sh cd build ``` 运行以下命令生成主 `pot`(**P**ortable **O**bject **T**emplate)文件: ```sh meson compile bazaar-pot ``` 你可能会看到一堆警告 `blp` 扩展名未知的输出,可以安全忽略它。 最后,仍然在构建目录内,运行以下命令来更新和/或创建 `po`(**P**ortable **O**bject)文件: ```sh meson compile bazaar-update-po ``` 现在,你可以使用文本编辑器或翻译编辑器([POEdit](https://flathub.org/apps/net.poedit.Poedit)、[GTranslator](https://flathub.org/apps/org.gnome.Gtranslator)、[Lokalize](https://flathub.org/apps/org.kde.lokalize) 等)打开 `po` 文件并开始翻译。 完成后,提交你的更改并在 GitHub 上提交 PR。请确保只提交与你的翻译相关的文件。 ## 更新现有翻译 根据上述命令再次生成全新的 `.pot` 文件(如有必要)。 ```sh msgmerge --update --verbose po/zh_CN.po po/bazaar.pot ``` 请在 PR 中将上述更新步骤作为一个单独的提交(Commit),以便于代码审查。谢谢! ## 测试你的翻译 确保使用简体中文对应的[语言代码](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)"zh_CN"! ```sh msgfmt po/zh_CN.po -o bazaar.mo ``` 复制 `.mo` 文件,使 Bazaar 能够识别它: ```sh sudo cp bazaar.mo /var/lib/flatpak/runtime/io.github.kolunmi.Bazaar.Locale/x86_64/stable/active/files/zh/share/zh_CN/LC_MESSAGES/ ``` 确保先结束 Bazaar 的后台进程,以便应用所需的更改/语言。 ```sh killall bazaar ``` 覆盖使用的语言并启动 Bazaar: ```sh LANGUAGE=zh_CN flatpak run io.github.kolunmi.Bazaar ``` # 翻译者注意事项 自动和手动流程都可能生成标记为 `fuzzy`(模糊)的条目。这意味着对于这些条目,`gettext` 尝试从现有的翻译中推导结果。某些翻译软件(如 Lokalize)会利用此标记将字符串设为“未审核”,并在条目被标记为完成时移除标记。如果你使用文本编辑器处理 pot 文件,请务必手动删除你认为已完成条目的 `fuzzy` 标记,否则你的翻译将不会出现在 Bazaar 中。 kolunmi-bazaar-7b9c8e1/TRANSLATORS.md000066400000000000000000000101671514314607700172250ustar00rootroot00000000000000# Instructions for Translators Thank you for your interest in translating Bazaar! 🏷️🗺️💜 Some basic rules: * You must be fluent in the language you contribute * You may not use llms to generate the strings (I could do that). If you do, I will ban you from the project * If you are editing existing translation, make sure to check rules for that language in `TRANSLATORS-[language code].md` file. ## Basic Process Fork the project (so you can open a PR later) and clone the repo. Then make sure your current directory is the bazaar project root: ```sh # Replace '...' with the URL of your Bazaar fork # for which you have write permissions git clone ... cd bazaar ``` # Automatic Setup Once you've done that, you can run `./translators.sh` and follow instructions present on the screen. The script will show you what `po/LINGUAS` currently looks like. If everything is correct, type `Y` and press enter. After that the script will ask you to enter language code, please enter it, and press enter. The script will now generate a new `po` file or update an existing one such that any new translatable strings will be available. You are now ready to open your `po` file in your text editor or translation editor (POEdit, GTranslator, Lokalize, etc.) and begin translating. When you are done, commit your changes and submit a pull request on github. # Manual Setup Once you've done that, setup the project with meson with the `im_a_translator` flag set to `true`: ```sh meson setup build -Dim_a_translator=true ``` Add your language identifier to `po/LINGUAS`. For example, if you are adding a Spanish translation, insert `es` into the newline-separated list, keeping it sorted alphabetically. So if the `po/LINGUAS` file currently looks like this: ``` # Please keep this file sorted alphabetically. ab en_GB ms ``` you will edit the file to look like this: ``` # Please keep this file sorted alphabetically. ab en_GB es ms ``` Next, enter the build directory: ```sh cd build ``` Run this command to generate the main `pot` (**P**ortable **O**bject **T**emplate) file: ```sh meson compile bazaar-pot ``` You might get a bunch of output complaining that the `blp` extension is unknown. You can ignore this. Finally, still inside the build directory, run the following command to update and/or create the `po` (**P**ortable **O**bject) files: ```sh meson compile bazaar-update-po ``` You are now ready to open your `po` file in your text editor or translation editor ([POEdit](https://flathub.org/apps/net.poedit.Poedit), [GTranslator](https://flathub.org/apps/org.gnome.Gtranslator), [Lokalize](https://flathub.org/apps/org.kde.lokalize), etc.)and begin translating. When you are done, commit your changes and submit a pull request on GitHub. Make sure to only commit files that are related to your translation. ## Update existing translations Generate a fresh `.pot` file again (if necessary) with the commands from above. ```sh msgmerge --update --verbose po/de.po po/bazaar.pot ``` Please make the previous update step a separate commit in your PR so it is easier to review. Thanks! ## Test your translations Replace "de" with your [Language code](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)! ```sh msgfmt po/de.po -o bazaar.mo ``` Copy the `.mo` file so Bazaar can see it ```sh sudo cp bazaar.mo /var/lib/flatpak/runtime/io.github.kolunmi.Bazaar.Locale/x86_64/stable/active/files/de/share/de/LC_MESSAGES/ ``` Make sure to kill the background process from Bazaar first so the desired changes/language will be used. ```sh killall bazaar ``` Override the used Language and launch Bazaar ```sh LANGUAGE=de flatpak run io.github.kolunmi.Bazaar ``` # Notes From Translators Both automatic and manual processes may generate entries marked as `fuzzy`. This means that for such entries, `gettext` attempted to derive previously existing translation. Some translation suites, like Lokalize, will utilize this marking to set strings as unreviewed and remove when the entry is marked finished. When working with pot-files using text editor, be sure to remove `fuzzy` marks yourself from entries you deem finished, else your translation will not appear in Bazaar. kolunmi-bazaar-7b9c8e1/bazaar.doap000066400000000000000000000025251514314607700171730ustar00rootroot00000000000000 bazaar Discover and install applications A new app store for Linux with a focus on discovering and installing applications and addons from Flatpak remotes, particularly Flathub. C GTK 4 Libadwaita Kolunmi kolunmi kolunmi-bazaar-7b9c8e1/build-aux/000077500000000000000000000000001514314607700167545ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/build-aux/flatpak/000077500000000000000000000000001514314607700203765ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/build-aux/flatpak/flatpak-builder-tools/000077500000000000000000000000001514314607700246025ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/build-aux/flatpak/fuse-2.9.2-closefrom.patch000066400000000000000000000007001514314607700250130ustar00rootroot00000000000000--- fuse-2.9.2/util/ulockmgr_server.c.closefromfix 2019-01-04 05:33:33.000000000 -0800 +++ fuse-2.9.2/util/ulockmgr_server.c 2022-07-12 12:29:56.445402244 -0700 @@ -124,7 +124,7 @@ return res; } -static int closefrom(int minfd) +static int _closefrom(int minfd) { DIR *dir = opendir("/proc/self/fd"); if (dir) { @@ -384,7 +384,7 @@ dup2(nullfd, 1); } close(3); - closefrom(5); + _closefrom(5); while (1) { char c; int sock; kolunmi-bazaar-7b9c8e1/build-aux/flatpak/fuse-2.9.2-namespace-conflict-fix.patch000066400000000000000000000010641514314607700273450ustar00rootroot00000000000000diff -up fuse-2.9.2/include/fuse_kernel.h.conflictfix fuse-2.9.2/include/fuse_kernel.h --- fuse-2.9.2/include/fuse_kernel.h.conflictfix 2013-06-26 09:31:57.862198038 -0400 +++ fuse-2.9.2/include/fuse_kernel.h 2013-06-26 09:32:19.679198365 -0400 @@ -88,12 +88,16 @@ #ifndef _LINUX_FUSE_H #define _LINUX_FUSE_H -#include +#ifdef __linux__ +#include +#else +#include #define __u64 uint64_t #define __s64 int64_t #define __u32 uint32_t #define __s32 int32_t #define __u16 uint16_t +#endif /* * Version negotiation: kolunmi-bazaar-7b9c8e1/build-aux/flatpak/fuse-disable-sys-mount-under-flatpak.patch000066400000000000000000000011671514314607700304760ustar00rootroot00000000000000From 1ec935f4abecd08957affc7b21bae6bf5be78931 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 12 Apr 2018 01:47:57 -0700 Subject: [PATCH] libfuse: disable sys mount under flatpak --- lib/mount.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mount.c b/lib/mount.c index 7a18c11..1667db2 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -392,6 +392,9 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, int fd; int res; + /* disable in flatpak */ + return -2; + if (!mnt) { fprintf(stderr, "fuse: missing mountpoint parameter\n"); return -1; -- 2.17.0.rc2 kolunmi-bazaar-7b9c8e1/build-aux/flatpak/fusermount-wrapper.sh000066400000000000000000000006431514314607700246220ustar00rootroot00000000000000#!/bin/sh set -eo pipefail echo "Running fusermount wrapper, redirecting to host..." export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/flatpak/bus binary="fusermount" if flatpak-spawn --host fusermount3 --version &> /dev/null ; then binary="fusermount3" fi [ ! -z "$_FUSE_COMMFD" ] && export FD_ARGS="--env=_FUSE_COMMFD=${_FUSE_COMMFD} --forward-fd=${_FUSE_COMMFD}" exec flatpak-spawn --host ${FD_ARGS} "$binary" "$@" kolunmi-bazaar-7b9c8e1/build-aux/flatpak/io.github.kolunmi.Bazaar.json000066400000000000000000000252631514314607700260450ustar00rootroot00000000000000{ "id": "io.github.kolunmi.Bazaar", "runtime": "org.gnome.Platform", "runtime-version": "49", "sdk": "org.gnome.Sdk", "command": "bazaar", "sdk-extensions": [ "org.freedesktop.Sdk.Extension.llvm20" ], "tags": [ "nightly" ], "desktop-file-name-suffix": " (Nightly)", "finish-args": [ "--share=network", "--share=ipc", "--socket=fallback-x11", "--socket=wayland", "--device=dri", "--filesystem=/var/lib/flatpak", "--filesystem=xdg-data/flatpak", "--filesystem=~/.var/app", "--talk-name=org.freedesktop.Flatpak", "--system-talk-name=org.freedesktop.Flatpak.SystemHelper", "--filesystem=/var/tmp", "--system-talk-name=org.freedesktop.Accounts" ], "cleanup": [ "/share/zsh", "/share/gettext", "/include", "/lib/pkgconfig", "/lib/cmake", "/share/applications/mimeinfo.cache", "/share/bash-completion", "/share/zsh/site-functions", "/share/icons/hicolor/icon-theme.cache", "/share/man", "/share/pkgconfig", "*.la", "*.a" ], "modules": [ { "name": "bazaar", "buildsystem": "meson", "build-options": { "append-path": "/usr/lib/sdk/llvm20/bin", "prepend-ld-library-path": "/usr/lib/sdk/llvm20/lib" }, "config-opts": [ "-Ddevelopment=true", "-Dsandboxed_libflatpak=true", "-Dhardcoded_main_config_path=/run/host/etc/bazaar/bazaar.yaml", "-Dhardcoded_content_config_path=/run/host/etc/bazaar/config.yaml", "-Dhardcoded_blocklist_path=/run/host/etc/bazaar/blocklist.txt" ], "sources": [ { "type": "dir", "path": "../.." } ], "modules": [ { "name": "md4c", "buildsystem": "cmake", "config-opts": [ "-DBUILD_MD2HTML_EXECUTABLE=Off" ], "sources": [ { "type": "git", "url": "https://github.com/mity/md4c.git", "commit": "729e6b8b320caa96328968ab27d7db2235e4fb47", "tag": "release-0.5.2", "x-checker-data": { "type": "git", "tag-pattern": "^release-([\\d.]+)$" } } ] }, { "name": "flatpak", "buildsystem": "meson", "config-opts": [ "-Dgtkdoc=disabled", "-Ddocbook_docs=disabled", "-Dtests=false", "-Dman=disabled", "-Dseccomp=disabled", "-Dselinux_module=disabled", "-Dmalcontent=disabled", "-Dsandboxed_triggers=false", "-Dsystem_helper=enabled", "-Dhttp_backend=curl", "-Dsystemd=disabled", "-Dsystem_install_dir=/var/lib/flatpak", "-Dsystem_bubblewrap=bwrap", "-Dsystem_dbus_proxy=xdg-dbus-proxy", "-Dgir=disabled", "--sysconfdir=/var/run/host/etc" ], "cleanup": [ "/bin/flatpak-bisect", "/bin/flatpak-coredumpctl", "/etc/profile.d", "/lib/systemd", "/share/dbus-1/interfaces/org.freedesktop.*", "/share/dbus-1/services/org.freedesktop.*", "/share/flatpak/triggers", "/share/gdm", "/share/zsh", "/share/fish", "/lib/sysusers.d", "/lib/tmpfiles.d" ], "post-install": [ "install -Dpm0755 -t /app/bin /usr/bin/update-{mime,desktop}-database" ], "sources": [ { "type": "git", "url": "https://github.com/flatpak/flatpak", "commit": "0835c0272f3a0389f97b02cad4b208f80fec99ed", "tag": "1.17.0", "x-checker-data": { "type": "git", "url-template": "$version", "is-important": true } } ], "modules": [ { "name": "python3-pyparsing", "buildsystem": "simple", "cleanup": [ "*" ], "build-commands": [ "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} pyparsing" ], "sources": [ { "type": "file", "url": "https://files.pythonhosted.org/packages/f2/a5/181488fc2b9d093e3972d2a472855aae8a03f000592dbfce716a512b3359/pyparsing-3.2.5.tar.gz", "sha256": "2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6", "x-checker-data": { "type": "pypi", "name": "pyparsing" } }, { "type": "file", "url": "https://files.pythonhosted.org/packages/69/59/b6fc2188dfc7ea4f936cd12b49d707f66a1cb7a1d2c16172963534db741b/flit_core-3.12.0.tar.gz", "sha256": "18f63100d6f94385c6ed57a72073443e1a71a4acb4339491615d0f16d6ff01b2", "x-checker-data": { "type": "pypi", "name": "flit_core" } } ] }, { "name": "polkit", "buildsystem": "meson", "config-opts": [ "-Dlibs-only=true", "-Dintrospection=false", "-Dauthfw=shadow" ], "rm-configure": true, "build-options": { "env": { "CFLAGS": "-Wno-implicit-function-declaration" } }, "cleanup": [ "/bin/*", "/etc/dbus-1", "/etc/pam.d", "/include", "/lib/pkgconfig", "/lib/polkit-1", "/share/dbus-1/system-services/*", "/share/polkit-1" ], "sources": [ { "type": "git", "url": "https://github.com/polkit-org/polkit", "commit": "d627b0d1e1108563658dabe3fb8d2a065e64df10", "tag": "126", "x-checker-data": { "type": "git", "tag-pattern": "^([\\d.]+)$" } } ], "modules": [ { "name": "ostree", "build-options": { "env": { "BASH_COMPLETIONSDIR": "/app/share/bash-completion/completions" }, "config-opts": [ "--disable-man", "--enable-introspection=no", "--with-curl", "--without-libsystemd" ] }, "cleanup": [ "/bin", "/etc/grub.d", "/etc/ostree", "/share/ostree", "/libexec" ], "sources": [ { "type": "git", "url": "https://github.com/ostreedev/ostree", "tag": "v2025.7", "commit": "134d144cb52ff018cfedfb936b661189bccc76e6", "x-checker-data": { "type": "anitya", "project-id": 10899, "tag-template": "v$version", "is-important": true } } ], "modules": [ { "name": "libfuse", "build-options": { "env": { "MOUNT_FUSE_PATH": "../tmp/" } }, "config-opts": [ "UDEV_RULES_PATH=/app/etc/udev/rules.d", "INIT_D_PATH=/app/etc/init.d" ], "cleanup": [ "/bin/ulockmgr_server", "/etc" ], "post-install": [ "install -Dpm0755 ./fusermount-wrapper.sh /app/bin/fusermount" ], "sources": [ { "type": "archive", "url": "https://github.com/libfuse/libfuse/releases/download/fuse-2.9.9/fuse-2.9.9.tar.gz", "sha256": "d0e69d5d608cc22ff4843791ad097f554dd32540ddc9bed7638cc6fea7c1b4b5" }, { "type": "patch", "path": "fuse-2.9.2-namespace-conflict-fix.patch" }, { "type": "patch", "path": "fuse-disable-sys-mount-under-flatpak.patch" }, { "type": "patch", "path": "fuse-2.9.2-closefrom.patch" }, { "type": "file", "path": "fusermount-wrapper.sh" } ] } ] }, { "name": "xdg-dbus-proxy", "buildsystem": "meson", "config-opts": [ "-Dman=disabled", "-Dtests=false" ], "sources": [ { "type": "git", "url": "https://github.com/flatpak/xdg-dbus-proxy", "commit": "1c1989e56f94b9eb3b7567f8a6e8a0aa16cba496", "tag": "0.1.6", "x-checker-data": { "type": "git", "url-template": "$version" } } ] } ] } ] } ] }, { "name": "bubblewrap", "buildsystem": "meson", "config-opts": [ "-Dman=disabled", "-Dselinux=disabled", "-Dtests=false" ], "sources": [ { "type": "git", "url": "https://github.com/containers/bubblewrap", "commit": "9ca3b05ec787acfb4b17bed37db5719fa777834f", "tag": "v0.11.0", "x-checker-data": { "type": "git", "url-template": "$version" } } ] } ] } kolunmi-bazaar-7b9c8e1/data/000077500000000000000000000000001514314607700157735ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/dbus/000077500000000000000000000000001514314607700167305ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/dbus/io.github.kolunmi.Bazaar.service.in000066400000000000000000000001731514314607700254640ustar00rootroot00000000000000[D-BUS Service] Name=io.github.kolunmi.Bazaar SystemdService=io.github.kolunmi.Bazaar.service Exec=@bindir@/bazaar service kolunmi-bazaar-7b9c8e1/data/dbus/meson.build000066400000000000000000000004701514314607700210730ustar00rootroot00000000000000service_conf = configuration_data() service_conf.set('bindir', get_option('prefix') / get_option('bindir')) configure_file( input: 'io.github.kolunmi.Bazaar.service.in', output: 'io.github.kolunmi.Bazaar.service', configuration: service_conf, install_dir: get_option('datadir') / 'dbus-1' / 'services' ) kolunmi-bazaar-7b9c8e1/data/icons/000077500000000000000000000000001514314607700171065ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/000077500000000000000000000000001514314607700205455ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/scalable/000077500000000000000000000000001514314607700223135ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/scalable/apps/000077500000000000000000000000001514314607700232565ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/scalable/apps/io.github.kolunmi.Bazaar.Devel.svg000066400000000000000000000102551514314607700316040ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/scalable/apps/io.github.kolunmi.Bazaar.svg000066400000000000000000000103051514314607700305420ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/symbolic/000077500000000000000000000000001514314607700223665ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/symbolic/apps/000077500000000000000000000000001514314607700233315ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/data/icons/hicolor/symbolic/apps/io.github.kolunmi.Bazaar-symbolic.svg000066400000000000000000000047301514314607700324410ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/data/icons/io.github.kolunmi.Bazaar.Source.svg000066400000000000000000007446121514314607700256500ustar00rootroot00000000000000 Adwaita Icon Template image/svg+xml GNOME Design Team Adwaita Icon Template Hicolor Symbolic kolunmi-bazaar-7b9c8e1/data/icons/meson.build000066400000000000000000000010731514314607700212510ustar00rootroot00000000000000application_id = 'io.github.kolunmi.Bazaar' scalable_dir = 'hicolor' / 'scalable' / 'apps' if get_option('development') icon_file = '@0@.Devel.svg'.format(application_id) else icon_file = '@0@.svg'.format(application_id) endif install_data( scalable_dir / icon_file, install_dir: get_option('datadir') / 'icons' / scalable_dir, rename: '@0@.svg'.format(application_id) ) symbolic_dir = 'hicolor' / 'symbolic' / 'apps' install_data( symbolic_dir / ('@0@-symbolic.svg').format(application_id), install_dir: get_option('datadir') / 'icons' / symbolic_dir ) kolunmi-bazaar-7b9c8e1/data/io.github.kolunmi.Bazaar.desktop.in000066400000000000000000000007011514314607700245350ustar00rootroot00000000000000[Desktop Entry] Name=Bazaar Comment=Add, remove or update flatpak software on this computer Exec=bazaar %U Icon=io.github.kolunmi.Bazaar Terminal=false Type=Application Categories=Utility; Keywords=GTK;System;PackageManager;Discover;Flatpak;Software;Store; StartupNotify=true MimeType=x-scheme-handler/appstream;x-scheme-handler/flatpak;x-scheme-handler/flatpak+https; Actions=new-window; [Desktop Action new-window] Name=New Window Exec=bazaar %U kolunmi-bazaar-7b9c8e1/data/io.github.kolunmi.Bazaar.gschema.xml000066400000000000000000000053501514314607700246720ustar00rootroot00000000000000 true Hide EOL Entries Hide EOL entries and entries depending on them false Only Show Free Software Hide proprietary software false Show Only Flathub Content Hide applications which do not originate from Flathub false Show Only Verified Content Hide applications which are not verified on Flathub true Debounce Search Inputs Add a delay before searching to prevent instant replies while typing 'accent-color' Global Progress Bar Theme Describes the look of the global progress bar false Rotate selected flag by 90 degrees (1220, 900) Saved Window Dimensions The window dimensions to be used by the next Bazaar window kolunmi-bazaar-7b9c8e1/data/io.github.kolunmi.Bazaar.metainfo.xml.in000066400000000000000000000474361514314607700255050ustar00rootroot00000000000000 io.github.kolunmi.Bazaar CC0-1.0 GPL-3.0-or-later Bazaar Discover and install applications

A new app store for Linux with a focus on discovering and installing applications and addons from Flatpak remotes, particularly Flathub.

It emphasizes supporting the developers who make the Linux desktop possible. Bazaar features a "curated" tab that can be configured by distributors to allow for a more localized experience.

pointing keyboard touch 360 Adam Masciola https://github.com/kolunmi/bazaar https://github.com/kolunmi/bazaar https://github.com/kolunmi/bazaar/issues https://github.com/kolunmi/bazaar/tree/master/po https://github.com/kolunmi/bazaar/blob/master/README.md https://github.com/kolunmi/bazaar/discussions https://github.com/sponsors/kolunmi https://github.com/kolunmi https://github.com/kolunmi/bazaar bazaar io.github.kolunmi.Bazaar.desktop #ffbe6f #c11c2b https://github.com/user-attachments/assets/b7d749fb-ecc0-4f3e-a965-15b6771c54d3 The home page displaying Flathub apps https://github.com/user-attachments/assets/7d306fbe-e1a7-4c74-91b2-f5061aba2c56 Exhibit app page https://github.com/user-attachments/assets/cf0914b7-f256-436e-bbd5-6822cf3d0786 Library page https://github.com/user-attachments/assets/733bff33-a206-43b9-bbaf-08df9d1c65f3 Search page https://github.com/user-attachments/assets/fd721125-1842-4cf1-9ab3-a70ef6b9ce10 Category page https://github.com/kolunmi/bazaar/releases/tag/v0.7.8

This release lets you view and remove user-scoped installed apps from the library page in the Flatpak version of the app. Installing from user remotes is not supported yet.

https://github.com/kolunmi/bazaar/releases/tag/v0.7.7

This release comes with the following improvements:

  • Merges the task sidebar and install page into the library page
  • Add installed version numbers of each app on the library and app pages
  • Add donations dialog
  • Fix broken addon and runtime eol detection
  • Add `enable-bulk-install` key to curated sections
  • Add `override-eol-markings` main config string list
https://github.com/kolunmi/bazaar/releases/tag/v0.7.6

This release comes with the following improvements:

  • Improve context dialogs
  • Fix leftover data bar being shown prematurely
  • Have a rotation toggle for flags
  • Add hard check to prevent removing Bazaar flatpak
  • Improve download statistics tooltips
  • Add read support for flatpak bundles
  • Fix critical output sometimes during transactions
  • Fix error popover refusing to spawn in transaction sidebar
https://github.com/kolunmi/bazaar/releases/tag/v0.7.5

Minor bugfix release

https://github.com/kolunmi/bazaar/releases/tag/v0.7.4

This release comes with the following improvements:

  • Fix issue where installed page is empty on opening second window
  • Fix screenshot flickering in search results
  • Fix pride flags sometimes not showing on certain locales
  • Add "Install all" to favorites page
https://github.com/kolunmi/bazaar/releases/tag/v0.7.3

This release comes with the following improvements:

  • Trash user data instead of deleting
  • Tweaks to permissions dialog
  • Fix broken EOL filtering
  • Add text filter to installed page
  • Add optional translations mappings for string properties in YAML configs
  • Hide EOL apps by default
  • Many other minor bug fixes and improvements
https://github.com/kolunmi/bazaar/releases/tag/v0.7.2

This small release ensures the new icon is rendered correctly on KDE Plasma.

https://github.com/kolunmi/bazaar/releases/tag/v0.7.1

This release comes with the following improvements:

  • New market stall icon
  • Remove Flathub styling
  • Add horizontal versions of pride flags
  • Text selection in app descriptions can be made across paragraph breaks
  • Support YAML anchors and aliases in config parsing
  • Drastically reduce disk cache writes over time by skipping unchanged entries
  • Show background status in popover
  • Add app permission system
  • Add back release URLs
  • Fix sync-remotes action in shortcut dialog
  • Fix visual hiccups in comet animations
https://github.com/kolunmi/bazaar/releases/tag/v0.7.0

This release comes with the following improvements:

  • Flathub account support with the ability to manage bookmarks
  • Flathub bookmarks replace star count; you can add or remove bookmarks from app pages
  • An "Only Show Verified" option
  • Exhaustive category pages for most categories
  • An "Adwaita" or "KDE" category shown based on desktop environment
  • Updated installed indicator for app tiles
  • 3 new flag options
  • Fixed GNOME search provider to show the app page instead of search
  • Fixed issue where flatpakref URIs did not open when the app wasn't running in the background
  • Fixed issue where some proprietary apps were marked as "Special License"
  • Fixed issue where graphs did not work with touch
https://github.com/kolunmi/bazaar/releases/tag/v0.6.3

Another quick release to restore alphabetical sorting on the installed page

https://github.com/kolunmi/bazaar/releases/tag/v0.6.2

Quick release to allow manual refresh if flathub is being flaky

https://github.com/kolunmi/bazaar/releases/tag/v0.6.1

This release comes with the following improvements:

  • Fix frequent disk writes; set refresh frequency to 1 day rather than 1 hour
  • Add "Delete User Data" option when uninstalling an application
  • Version cache to prevent incompatibility between Bazaar versions
https://github.com/kolunmi/bazaar/releases/tag/v0.6.0

This release comes with the following improvements:

  • Reworked loading to be substantially faster after first start via async loading
  • A gaming section on the Flathub page
  • Improved UI on mobile, especially on app pages
  • Verified badges next to most places where apps are shown
  • A popover that explains what verification and non-verification mean
  • An "other apps by" page for when a developer has more than 6 apps
  • Tags that show other apps with the same tag when pressed
  • An age rating dialog
  • Changed search filters into global content filters
  • 5 new pride flags
https://github.com/kolunmi/bazaar/releases/tag/v0.5.10

This release comes with the following improvements:

  • Add "hide-eol" preferences option to prevent Bazaar from showing end-of-life applications or applications which depend on end-of-life runtimes
  • Fix global progress bar theme sometimes not syncing with preferences
  • Show version next to addon name in the addons dialog
https://github.com/kolunmi/bazaar/releases/tag/v0.5.9

This release comes with the following improvements:

  • Add "On the go" section and mobile cateogry
  • Greatly decrease reported memory usage
  • Rework search UI
  • Rework page stack navigation
  • Change screenshot dialog to page
https://github.com/kolunmi/bazaar/releases/tag/v0.5.8

This release comes with the following improvements:

  • Fix slow/inconsistent image loading
  • Fix context row in full view
https://github.com/kolunmi/bazaar/releases/tag/v0.5.7

This release comes with the following improvements:

  • Rework full view layout
  • Improve progress bar theme selection
  • Reduce quantity and improve quality of search results
  • Allow the application window to fit on mobile screen sizes
https://github.com/kolunmi/bazaar/releases/tag/v0.5.6

This release comes with the following improvements:

  • Add interactive screenshot dialog
  • Fix empty update dialogs
  • Greatly improve look of app description rendering
  • Add pending state to the global progress bar
  • Add featured apps carousel
https://github.com/kolunmi/bazaar/releases/tag/v0.5.5

More improvements:

  • Improve design of transaction dialog
  • Update remove button pulse effect and comet size curve
  • Reap and reload cached textures after a day
  • Eliminate some crashes caused by race conditions
  • Change preferences group to context bar in full view
  • Switch side panels to sidebars and use flat header bar designs
  • Add really useful app size dialog :)
https://github.com/kolunmi/bazaar/releases/tag/v0.5.4

Some improvements:

  • Make the global progress bar customizable with pride flags! Check preferences
  • Add a new world map page to the download statistics dialog
  • Allow clicking on entries on transaction sidebar to navigate to the original store page
  • Add Alexander Vanhee to the developer credits
https://github.com/kolunmi/bazaar/releases/tag/v0.5.3

Some improvements:

  • Overhaul download history graph; make it interactive
  • Smarter "back" functionality
  • Hide bottom bar more often on small window sizes
  • Make "light-banner" and "dark-banner" keys available to curated configs
https://github.com/kolunmi/bazaar/releases/tag/v0.5.2

This release includes:

  • 553d041 * chore(po): update Ukrainian translation (#408)
  • 711732a * Rework Version History (#407)
  • d2d3771 * Calculate detailed app tiles text color based on luminance of background accent color (#405)
  • 3787e6e * Save window size in gsettings
  • 18ba76c * AsyncTexture: increase HTTP timeout to 5 seconds
  • 980f752 * SearchWidget: prevent invalid item selection
  • ab95593 * Add installed icons to app tiles (#404)
  • 203754b * (UI) Improve visiblility of add-on feature (#403)
  • 069ce61 * fix installed page list outline ring (#402)
  • da9f7b8 * (UX) Refine the Flathub views to be denser and have less partial lines (#401)
  • a6939ba * fix(po): fix Ukrainian translation (#400)
  • 35c9611 * decrease app-tile description width reqs
  • 6098be7 * chore(po): update Polish translation (#397)
  • 2944d1e * change per section limit to 12 from 9 (#396)
  • 0b04284 * Update Japanese Translation (#394)
  • fa60f4f * Move to brand new shiny Adw.ShortcutsDialog (#395)
https://github.com/kolunmi/bazaar/releases/tag/v0.5.1 https://github.com/kolunmi/bazaar/releases/tag/v0.5.0 https://github.com/kolunmi/bazaar/releases/tag/v0.4.11 https://github.com/kolunmi/bazaar/releases/tag/v0.4.10 https://github.com/kolunmi/bazaar/releases/tag/v0.4.9 https://github.com/kolunmi/bazaar/releases/tag/v0.4.8 https://github.com/kolunmi/bazaar/releases/tag/v0.4.7 https://github.com/kolunmi/bazaar/releases/tag/v0.4.6 https://github.com/kolunmi/bazaar/releases/tag/v0.4.5 https://github.com/kolunmi/bazaar/releases/tag/v0.4.4 https://github.com/kolunmi/bazaar/releases/tag/v0.4.3 https://github.com/kolunmi/bazaar/releases/tag/v0.4.2 https://github.com/kolunmi/bazaar/releases/tag/v0.4.1 https://github.com/kolunmi/bazaar/releases/tag/v0.4.0 https://github.com/kolunmi/bazaar/releases/tag/v0.3.2 https://github.com/kolunmi/bazaar/releases/tag/v0.3.1 https://github.com/kolunmi/bazaar/releases/tag/v0.3.0 https://github.com/kolunmi/bazaar/releases/tag/v0.2.3 https://github.com/kolunmi/bazaar/releases/tag/v0.2.2 https://github.com/kolunmi/bazaar/releases/tag/v0.2.1 https://github.com/kolunmi/bazaar/releases/tag/v0.2.0 https://github.com/kolunmi/bazaar/releases/tag/v0.1.0
kolunmi-bazaar-7b9c8e1/data/io.github.kolunmi.Bazaar.search-provider.ini.in000066400000000000000000000002411514314607700267360ustar00rootroot00000000000000[Shell Search Provider] DesktopId=io.github.kolunmi.Bazaar.desktop BusName=io.github.kolunmi.Bazaar ObjectPath=/io/github/kolunmi/Bazaar/SearchProvider Version=2kolunmi-bazaar-7b9c8e1/data/io.github.kolunmi.Bazaar.service.in000066400000000000000000000002361514314607700245270ustar00rootroot00000000000000[Unit] Description=Bazaar Service PartOf=graphical-session.target [Service] Type=dbus BusName=io.github.kolunmi.Bazaar ExecStart=@bindir@/bazaar --no-window kolunmi-bazaar-7b9c8e1/data/meson.build000066400000000000000000000034411514314607700201370ustar00rootroot00000000000000desktop_file = i18n.merge_file( input: 'io.github.kolunmi.Bazaar.desktop.in', output: 'io.github.kolunmi.Bazaar.desktop', type: 'desktop', po_dir: '../po', install: true, install_dir: get_option('datadir') / 'applications' ) desktop_utils = find_program('desktop-file-validate', required: false) if desktop_utils.found() test('Validate desktop file', desktop_utils, args: [desktop_file]) endif appstream_file = i18n.merge_file( input: 'io.github.kolunmi.Bazaar.metainfo.xml.in', output: 'io.github.kolunmi.Bazaar.metainfo.xml', po_dir: '../po', install: true, install_dir: get_option('datadir') / 'metainfo' ) appstreamcli = find_program('appstreamcli', required: false, disabler: true) test('Validate appstream file', appstreamcli, args: ['validate', '--no-net', '--explain', appstream_file]) install_data('io.github.kolunmi.Bazaar.gschema.xml', install_dir: get_option('datadir') / 'glib-2.0' / 'schemas' ) compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) test('Validate schema file', compile_schemas, args: ['--strict', '--dry-run', meson.current_source_dir()]) service_conf = configuration_data() service_conf.set('bindir', get_option('prefix') / get_option('bindir')) configure_file( input: 'io.github.kolunmi.Bazaar.service.in', output: 'io.github.kolunmi.Bazaar.service', configuration: service_conf, install_dir: get_option('prefix') / 'lib' / 'systemd' / 'user' ) service_conf = configuration_data() configure_file( input: 'io.github.kolunmi.Bazaar.search-provider.ini.in', output: 'io.github.kolunmi.Bazaar.search-provider.ini', configuration: service_conf, install_dir: get_option('datadir') / 'gnome-shell' / 'search-providers' ) subdir('icons') subdir('dbus') kolunmi-bazaar-7b9c8e1/docs/000077500000000000000000000000001514314607700160125ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/docs/overview.md000066400000000000000000000641041514314607700202070ustar00rootroot00000000000000# Bazaar Overview These docs are intended for distributors of Bazaar to learn how to configure the application. ## Features Here is a short list of some of the things Bazaar can do, beyond the basics of managing software through the GUI: * Queue an arbitrary number of transactions (a catch-all term for installations, updates, and removals) during which you may close all windows or continue to append new transactions freely * Display a "Curated" page which you may extensively customize with YAML. * This is a way to highlight applications which you believe might be of interest. * Curated configuration files are constantly monitored for filesystem events, changes immediately reflected in the GUI * Any number of curated configuration files; they will concatenate in the GUI in the order they were provided * Access data from [Flathub](https://flathub.org/), such as the latest or most popular applications, and allow users to sign in to Flathub to manage bookmarked applications * Run in the background and respond to desktop search queries with application info, using the same search routine as in-application - GNOME will work out of the box, as Bazaar implements the `org.gnome.Shell.SearchProvider2` dbus interface - KDE Plasma will require a [krunner plugin](https://github.com/ublue-os/krunner-bazaar) * Hide applications you do not want users to see with blocklists, which is useful for discouraging the use of certain packages which you deem to be broken. * Manage an arbitrary amount of windows and keep them synchronized * Communicate with, and invoke operations on, the main daemon through the command line ## CLI Usage You can start the bazaar daemon like this: ``` bazaar [ARGS] [PACKAGE PATH/URI] ``` To avoid spawning an initial window, use: ``` bazaar --no-window [ARGS] [PACKAGE PATH/URI] ``` `[PACKAGE PATH/URI]` could be a `.flatpakref` file. flatpak+https and regular https is supported. ## Comptime Configuration The only compile time meson option you should concern yourself with for production is `hardcoded_main_config_path`. This embeds a path to the main configuration file into Bazaar. If this is not defined at compile time, Bazaar will never attempt to read a main config. See the next section of this document to see an example config file. ## Main Configuration This is the primary YAML configuration file for bazaar, as designated by the `hardcoded_main_config_path` meson option. Here, you will point bazaar to where your other configs are located. You can also define hooks in this file. See the "Hooks" section of this document for an overview of the hooks system and an example of integration into the main config. ### Example ```yaml yaml-blocklist-paths: - /path/to/yaml/blocklist.yaml - /path/to/another/yaml/blocklist.yaml # Flatpak path with host-etc permission - /run/host/etc/bazaar/blocklist.yaml txt-blocklist-paths: - /path/to/txt/blocklist.txt - /path/to/another/txt/blocklist.txt # Flatpak path with host-etc permission - /run/host/etc/bazaar/blocklist.txt curated-config-paths: - /path/to/yaml/file.yaml - /path/to/another/yaml/file.yaml # Flatpak path with host-etc permission - /run/host/etc/bazaar/curated.yaml ``` ### EOL Overrides In this file, you can also specify a list of apps for which to hide EOL warnings and therefore prevent users from being deterred from installing them: ```yaml override-eol-markings: - com.obsproject.Studio - net.lutris.Lutris ``` (At the time of writing, the projects listed above rely on EOL runtimes but are otherwise widely used) ## Blocklists Blocklists are a way to ensure that users will never interact with a certain application inside Bazaar by searching or browsing, either on the Flathub page or via search. Blocked applications which are already installed still appear in the library or when there are updates available for them and via the system's flatpak configuration. Under no circumstance does Bazaar touch the underlying flatpak configuration in order to block or allow apps. The `flatpak` command line tool is unaffected. ### Blocklist Types There are two kinds of blocklists supported by Bazaar: #### YAML Blocklists For those who are learn more effectively by seeing an example: ```yaml blocklists: - priority: 0 block-regex: # block all ids matching this regex unconditionally - com\.place\..* - priority: -1 # lower number = more priority conditions: - match-locale: # only apply this rule if we have the Arabic locale regex: ar allow: - com.place.App3 - com.place.App5 allow-regex: - com\.place\..*\.ar - priority: -1 conditions: - match-locale: regex: en.* # invert the result of this condition; so all locales which don't match # the regex post-process: invert - match-envvar: var: PATH regex: .*/usr/local/bin.* block: - com.other.App1 allow: - com.place.App1 - com.place.App2 ``` YAML blocklists files are comprised of a list of sub "blocklists," which to Bazaar means a **list of appids to block or allow**. These are optionally **applied based on a list of provided conditions** and **composed with other blocklists in the list based on a priority**. Each blocklist may contain these fields: * `priority`: a number which tells Bazaar how to layer this blocklist with the others, or how "important" this blocklist is. **A lower number means more priority**. * `conditions`: a list of conditions to apply. Two condition types exist at the moment: `match-locale` and `match-envvar`. TODO: describe these * `block`: a list of appids to block. These are matched without regex. * `block-regex`: a list of appids to block. These allow regex syntax for special matching. * `allow`: a list of appids to allow. These are matched without regex. * `allow-regex`: a list of appids to allow. These allow regex syntax for special matching. #### Basic Newline Separated TXT Blocklists This type of blocklist is what Bazaar originally supported. They still function, but it is encouraged to use YAML blocklists if any sort of pattern matching or conditional inclusion is required. ``` # comments are supported com.jetbrains.CLion com.valvesoftware.Steam # empty lines are allowed io.neovim.nvim net.lutris.Lutris ``` Warning: **Incorrect Buzzer** TXT blocklists do not support regular expressions. This matches the literal text provided ``` com\.place\..* ``` ### Blocklist FAQ #### No Worky Check that the path of the blocklist exists and that Bazaar can access it. This command is useful for debugging this: ``` flatpak run --command=bash io.github.kolunmi.Bazaar ``` The `/etc` of the host system accessed from a Flatpak requires the `host-etc` permission. This means `/etc/bazaar/banner.png` turns into `/run/host/etc/bazaar/banner.png`. #### I want to to block a list of applications all the time, and also another list only on desktop environment X: Say you want to block Bazaar and Steam unconditionally and Kate and KWrite if the desktop is Plasma. You can use an environment variable condition to check the value of `XDG_CURRENT_DESKTOP`: ```yaml blocklists: - block: - io.github.kolunmi.Bazaar - com.valvesoftware.Steam - block: - org.kde.kate - org.kde.kwrite conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: KDE ``` Let's add another for GNOME: ```yaml blocklists: - block: - io.github.kolunmi.Bazaar - com.valvesoftware.Steam - block: - org.kde.kate - org.kde.kwrite conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: KDE - block: - org.gnome.eog - org.gnome.Extensions conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: GNOME ``` #### What about blocking an application by default, but allowing it if a condition resolves to true? Taking from the previous example, let's allow Steam on KDE and GNOME, but block it on other desktops. We'll need to give the DE-specific blocklists more priority: ```yaml blocklists: - priority: 1 block: - io.github.kolunmi.Bazaar - com.valvesoftware.Steam - block: - org.kde.kate - org.kde.kwrite allow: - com.valvesoftware.Steam conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: KDE - block: - org.gnome.eog - org.gnome.Extensions allow: - com.valvesoftware.Steam conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: GNOME ``` You could also make a new blocklist matching both `KDE` and `GNOME`: ```yaml blocklists: - priority: 1 block: - io.github.kolunmi.Bazaar - com.valvesoftware.Steam - block: - org.kde.kate - org.kde.kwrite conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: KDE - block: - org.gnome.eog - org.gnome.Extensions conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: GNOME - allow: - com.valvesoftware.Steam conditions: - match-envvar: var: XDG_CURRENT_DESKTOP regex: KDE|GNOME ``` ## Curated Section If Bazaar is provided a non-zero amount of curated configs, an extra tab will appear on the window's header bar called "Curated". This section is intended for distributors to curate applications for users with a customizable interface. Curated configs are YAML files. They are constantly monitored by Bazaar for filesystem events, so when the config changes, Bazaar will automatically reload the content. Right now, curated configs are essentially composed of a list of "sections" which appear stacked on top of each other inside of a scrollable viewport in the order they appear in the YAML. Each section has certain properties you can customize, like a title, an image banner URI, and of course a list of appids. Bazaar maps the appids you provide to the best matching "entry group" from the table of applications it was able to pull from remote sources (Simply put, an entry group in Bazaar is a collection of applications which share the same appid but come from different sources or installations). The entry group has a designated "ui entry" which was previously determined in the refresh process to have the most useful content associated with it as it pertains to presenting things like icons, descriptions, screenshots, etc to the user. When the user selects the app in the section, they are brought to a "full view" where they can see a bunch of information stored inside or referenced by the ui entry and choose to invoke transactions on the entry group, like installation or removal. Additionally, curated configs allow you to define a css block from which you can reference classes inside sections and change the way gtk renders the content. ### Example Here are practical examples: - [Aurora](https://github.com/get-aurora-dev/common/tree/0d86028dd0d737d1d0eee08205c33fc91997f155/system_files/shared/etc/bazaar) - https://getaurora.dev - [Bluefin](https://github.com/projectbluefin/common/tree/a868eba107b91c4eae60b6d1d6d2e2cdf05eb1c8/system_files/bluefin/etc/bazaar) - https://projectbluefin.io - [Bazzite](https://github.com/ublue-os/bazzite/blob/4cb928b7268d0cae38592ff112e061f972caed63/system_files/desktop/shared/usr/share/ublue-os/bazaar) - https://bazzite.gg Here is a basic curated config: ```yaml # Some css names at your disposal: # - banner # - banner-text # - banners # - description # - subtitle # - title # - app-tile # - app-tile-title # - app-tile-verified-check # - app-tile-description # - app-tile-installed-indicator # - app-tile-installed-pill css: | .main-section { margin: 15px; border-radius: 25px; } .main-section banner-text { margin: 15px; color: white; } .background-1 { background: linear-gradient(45deg, #170a49, #52136c); } .background-1 title { border-bottom: 5px solid white; } .background-1 app-tile > button { background-color: alpha(white, 0.1); } .background-1 app-tile > button:hover { background-color: alpha(var(--accent-bg-color), 0.5); } .background-2 { background: linear-gradient(75deg, #51263c, #7104a9); } .background-2 app-tile > button:focus { background-color: alpha(var(--accent-bg-color), 0.5); } .background-2 app-tile-verified-check { color: orange; } rows: - sections: - expand-horizontally: true category: title: "My Favorite Apps" subtitle: "These are really good and you should download them!" # can be https as well # If you want this to work with the Flatpak then use this path # file:///run/host/etc/bazaar/banner-1.jxl banner: file:///home/kolunmi/banner-1.jxl # Dynamically switching between light/dark variants of banners light-banner: file:///home/kolunmi/banner-light.png dark-banner: file:///home/kolunmi/banner-dark.png # can be "fill", "contain", "cover", or "scale-down" # see https://docs.gtk.org/gtk4/enum.ContentFit.html banner-fit: contain # can be "fill", "start", "end", or "center" # see https://docs.gtk.org/gtk4/enum.Align.html # halign -> "horizontal alignment" banner-text-halign: start # valign -> "vertical alignment" banner-text-valign: center # size in pixels banner-height: 400 # "The horizontal alignment of the label text inside its size # allocation." # see https://docs.gtk.org/gtk4/property.Label.xalign.html banner-text-label-xalign: 0.0 # appid list appids: - com.usebottles.bottles - io.mgba.mGBA - net.pcsx2.PCSX2 - org.blender.Blender - org.desmume.DeSmuME - org.duckstation.DuckStation - org.freecad.FreeCAD # Show an "Install All" button enable-bulk-install: true # reference the classes we defined earlier classes: - main-section - background-1 # The `classes` key (above) is for styling which we want to apply # all the time. If you want a style class to only be active in # light or dark mode, use `light-classes` or `dark-classes`: light-classes: - light-section dark-classes: - dark-section - sections: - category: title: "Some more awesome apps!" subtitle: "These are also pretty cool" banner: file:///home/kolunmi/banner-2.png banner-fit: contain banner-text-halign: end banner-text-valign: center banner-text-label-xalign: 1.0 appids: - org.gimp.GIMP - org.gnome.Builder - org.gnome.Loupe - org.inkscape.Inkscape classes: - main-section - background-2 ``` ### Integrate the curated section + blocklist with the official Flatpak for Administrators/Vendors For more practical examples check out the configuration from [Bluefin](https://github.com/projectbluefin/common/tree/a868eba107b91c4eae60b6d1d6d2e2cdf05eb1c8/system_files/bluefin/etc/bazaar) and [Aurora](https://github.com/get-aurora-dev/common/tree/0d86028dd0d737d1d0eee08205c33fc91997f155/system_files/shared/etc/bazaar). Bazaar by default looks for a config file in `/etc/bazaar` or `/run/host/etc/bazaar` inside the sandbox, this is [configured on build time](https://github.com/flathub/io.github.kolunmi.Bazaar/blob/709faccd8c4198c5fdabf20eb4a98db98a5aa1c6/io.github.kolunmi.Bazaar.yaml#L43-L46) This needs permission to `/etc` which can be granted with the `filesystem=host-etc` permission, the build on Flathub doesn't have this permission by default. This is not super straightforward to setup currently as Flatpak doesn't support overriding permissions in `/etc` or `/usr` yet, so you have to resort to `systemd-tmpfiles` to create this permission override in `/var/lib/flatpak/overrides/io.github.kolunmi.Bazaar`. Here is how they did it: - [tmpfiles](https://github.com/get-aurora-dev/common/blob/0d86028dd0d737d1d0eee08205c33fc91997f155/system_files/shared/usr/lib/tmpfiles.d/bazaar-flatpak.conf) - [actual permission override](https://github.com/get-aurora-dev/common/blob/0d86028dd0d737d1d0eee08205c33fc91997f155/system_files/shared/usr/share/ublue-os/flatpak-overrides/io.github.kolunmi.Bazaar), the filepath for this doesn't really matter, just a way for you to ship the symlink with tmpfiles ## Hooks Hooks are an advanced feature of Bazaar. In essence, they allow you to programmatically react to events and define dialogs with which you can query user input. Currently, the only events you can subscribe to are the "before-transaction" and "after-transaction" events: * `before-transaction`: run the hook right before a transaction is scheduled to begin * `after-transaction`: run the hook after a transaction successfully completes Hooks are run like a signal emission. After an event occurs, hooks that are found to be of the appropriate type are evaluated in an order of priority. Higher priority hooks have the ability to stop the emission from propagating further downwards. In the case of some events, like "before-transaction", a hook can also hint to Bazaar some action to take, in this case whether the transaction should be aborted. A shell snippet which is defined by you is evaluated with `/bin/sh -c` multiple times over the course of a hook's execution. An invocation of the shell snippet is referred to as a "stage". Your shell snippet (which of course could just invoke another script written in whatever language you prefer) will be provided a number of environment variables which together will describe the current stage. Your snippet must react accordingly by printing a response to stdout, which Bazaar will read back. This opens up a lot of possibilities for customization; here are a few examples: * You would like a certain appid to be added to steam after the user installs it, so you register a hook on "after-transaction" to query the user's permission with a custom dialog. If they confirm, your script will go forward with the task of setting up a steam shortcut. * You would like to prevent users from installing a certain appid, as some other method of installation, such as a system package, would provide a superior experience. A blocklist could achieve this, but you don't like the idea of hiding anything from the user. A hook subscribed to the "before-transaction" event could issue a warning and ask for extra confirmation. If the user decides to listen to the warning, you can signal to Bazaar that the transaction should be aborted. Here is an overview of the environment variables the shell snippet will receive: * `BAZAAR_HOOK_INITIATED_UNIX_STAMP`: the unix timestamp in seconds at which this hook was first invoked (the number of seconds that have elapsed since 1970-01-01 00:00:00 UTC) * `BAZAAR_HOOK_INITIATED_UNIX_STAMP_USEC`: the unix timestamp in microseconds at which this hook was first invoked (the number of microseconds that have elapsed since 1970-01-01 00:00:00 UTC) * `BAZAAR_HOOK_STAGE_IDX`: the number of stages this hook has run so far * `BAZAAR_HOOK_ID`: the value of the "id" mapping * `BAZAAR_HOOK_TYPE`: the value of the "when" mapping * `BAZAAR_HOOK_WAS_ABORTED`: "true" if a dialog aborted the hook * `BAZAAR_HOOK_DIALOG_ID`: if applicable, the id of the current dialog * `BAZAAR_HOOK_DIALOG_RESPONSE_ID`: if applicable, the user response given through the current dialog * `BAZAAR_TS_APPID`: if applicable, the appid of the entry Bazaar is currently dealing with * `BAZAAR_TS_TYPE`: if applicable, the type of transaction being run. Can be "install", "update", or "removal". * `BAZAAR_HOOK_STAGE`: the stage at which the hook is running. This will indicate what the shell body is instructed to do at this time. The shell body must respond by outputting to stdout with a valid answer; the structure of a valid answer will depend on the stage, and if the structure is not valid the hook will be abandoned. The shell body might be run multiple times by Bazaar over the course of a hook with this variable set to differing values in order know how to orchestrate events in the UI, so the shell body must be able to branch depending on the value. The value may be any of the following: * `setup`: the hook is starting. Respond with "ok" to continue the execution of this hook, or "pass" to skip it and move on to the next registered hook * `setup-dialog` Bazaar is ready to ask the user a question with one of the dialogs you've defined inside the "dialogs" mapping. `BAZAAR_HOOK_DIALOG_ID` will tell you which one. Respond with "ok" to spawn the dialog, or "pass" to skip the dialog. * `teardown-dialog` Bazaar has received input from the user after asking them a question with one of the dialogs you've defined inside the "dialogs" mapping. `BAZAAR_HOOK_DIALOG_ID` will tell you which one. `BAZAAR_HOOK_DIALOG_RESPONSE_ID` will tell you the response the user chose. Respond with "ok" to continue, or "abort" to stop the execution of this hook. * `catch` One of your dialogs has aborted. This is your chance to handle the error. Respond with "recover" to continue, or "abort" to confirm that the execution of this hook should indeed skip to the teardown stage. * `action` Everything so far has gone according to plan, so it is time to take whatever external action this hook exists for. Bazaar requires no response at this time. * `teardown` The hook is cleaning up. Respond with "continue" to propagate the signal emission to lower priority hooks, or "stop" to indicate the emission should stop. Alternatively, if this hook type should hint to Bazaar an action to take (such as the "before-transaction" hook), respond with "confirm" to hint that the action should be taken, or "deny" to prevent the action from being taken. Both "confirm" and "deny" imply the effect of "stop", and "stop" implies "confirm". ### Example Hooks are defined in the main yaml config as indicated by the `hardcoded_main_config_path` comptime var. Here is a basic example demonstrating how to define a hook: `hardcoded_main_config_path`: ```yaml hooks: - id: handle-jetbrains when: before-transaction dialogs: - id: jetbrains-warning title: >- Jetbrains IDEs are not supported in this format # If true, render inline markup commands in body; see # https://docs.gtk.org/Pango/pango_markup.html body-use-markup: true body: >- This is a Jetbrains application and is not officially supported on Flatpak. We recommend using the Toolbox app to manage Jetbrains IDEs. # Determines which option will be assumed if the user hits the # escape key or otherwise cancels the dialog default-response-id: cancel options: - id: cancel string: "Cancel" - id: goto-web string: "Download Jetbrains Toolbox" # can be "destructive" or "suggested" or omit for no # styling style: suggested shell: exec /absolute/path/to/bazaar-jetbrains-hook.bash ``` `/absolute/path/to/bazaar-jetbrains-hook.bash`: ```bash #!/usr/bin/env bash handle_setup_stage() { # only proceed if the user is installing something if [ "$BAZAAR_TS_TYPE" = install ]; then case "$BAZAAR_TS_APPID" in com\.jetbrains\.*) # since the appid belongs to jetbrains, we continue # with the hook echo 'ok' ;; *) # otherwise, skip this hook echo 'pass' ;; esac else echo 'pass' fi } handle_setup_dialog_stage() { # we don't need to do anything here right now, just let Bazaar # know we should continue setting up the dialog echo 'ok' } handle_teardown_dialog_stage() { case "$BAZAAR_HOOK_DIALOG_RESPONSE_ID" in goto-web) # if the user pressed "Download Jetbrains Toolbox", # continue echo 'ok' ;; *) # otherwise, let's not do anything echo 'abort' ;; esac } handle_catch_stage() { # this only happens if the `teardown-dialog` stage echoed "abort", # we could echo "recover" at this point to still go to the # `action` stage, but we have no reason to do that right now echo 'abort' } handle_action_stage() { # this is where we do the thing! it is important to use `nohup` # here so bazaar doesn't hang nohup xdg-open 'https://www.jetbrains.com/toolbox-app/' } handle_teardown_stage() { # Let's always prevent the user from installing Jetbrains stuff echo 'deny' } # Branch based on the stage case "$BAZAAR_HOOK_STAGE" in setup) handle_setup_stage ;; setup-dialog) handle_setup_dialog_stage ;; teardown-dialog) handle_teardown_dialog_stage ;; catch) handle_catch_stage ;; action) handle_action_stage ;; teardown) handle_teardown_stage ;; esac # exit successfully exit 0 ``` ## Translations in YAML Configs For any string scalar property in YAML configs parsed by bazaar, you can optionally provide a map of language code ids -> translated strings. This is for strings only, thus it doesn't apply to scalars which are explicitly parsed as numbers, etc. For instance, this is valid: ```yaml # ... category: title: "My Favorite Apps" subtitle: "These are really good and you should download them!" # ... ``` This is also valid: ```yaml # ... category: title: en: "My Favorite Apps" es: "Mis Aplicaciones Favoritas" ko: "내가 가장 좋아하는 앱들" subtitle: en: "These are really good and you should download them!" es: "¡Son realmente buenos y deberías descargarlos!" ko: "이것들은 정말 좋으니 꼭 다운로드하세요!" # ... ``` (I just used google translate for these, sorry if they are bad) kolunmi-bazaar-7b9c8e1/meson.build000066400000000000000000000071201514314607700172240ustar00rootroot00000000000000project('bazaar', 'c', version: run_command('version.sh', 'get-vcs').stdout().strip(), meson_version: '>= 1.0.0', default_options: [ 'warning_level=2', 'werror=false', 'c_std=gnu11', ], ) i18n = import('i18n') if get_option('im_a_translator') subdir('po') else gnome = import('gnome') cc = meson.get_compiler('c') config_h = configuration_data() config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) config_h.set_quoted('GETTEXT_PACKAGE', 'bazaar') config_h.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) config_h.set_quoted('DONATE_LINK', 'https://ko-fi.com/kolunmi') config_h.set_quoted('RELEASE_PAGE', run_command('version.sh', 'get-gh-release').stdout().strip()) dl_worker_bin_name = 'bazaar-dl-worker' config_h.set_quoted('DL_WORKER_BIN_NAME', dl_worker_bin_name) if get_option('hardcoded_main_config_path') != '' config_h.set_quoted('HARDCODED_MAIN_CONFIG', get_option('hardcoded_main_config_path')) endif if get_option('hardcoded_blocklist_path') != '' config_h.set_quoted('HARDCODED_BLOCKLIST', get_option('hardcoded_blocklist_path')) endif if get_option('hardcoded_content_config_path') != '' config_h.set_quoted('HARDCODED_CONTENT_CONFIG', get_option('hardcoded_content_config_path')) endif if get_option('sandboxed_libflatpak') config_h.set_quoted('SANDBOXED_LIBFLATPAK', '1') endif if get_option('development') config_h.set10('DEVELOPMENT_BUILD', get_option('development')) endif configure_file(output: 'config.h', configuration: config_h) add_project_arguments(['-I' + meson.project_build_root()], language: 'c') project_c_args = [] test_c_args = [ '-Wcast-align', '-Wdeclaration-after-statement', '-Werror=address', '-Werror=array-bounds', '-Werror=empty-body', '-Werror=implicit', '-Werror=implicit-function-declaration', '-Werror=incompatible-pointer-types', '-Werror=init-self', '-Werror=int-conversion', '-Werror=int-to-pointer-cast', '-Werror=main', '-Werror=misleading-indentation', '-Werror=missing-braces', '-Werror=missing-include-dirs', '-Werror=nonnull', '-Werror=overflow', '-Werror=parenthesis', '-Werror=pointer-arith', '-Werror=pointer-to-int-cast', '-Werror=redundant-decls', '-Werror=return-type', '-Werror=sequence-point', '-Werror=shadow', '-Werror=strict-prototypes', '-Werror=trigraphs', '-Werror=undef', '-Werror=write-strings', '-Wformat-nonliteral', '-Wignored-qualifiers', '-Wimplicit-function-declaration', '-Wlogical-op', '-Wmissing-declarations', '-Wmissing-format-attribute', '-Wmissing-include-dirs', '-Wmissing-noreturn', '-Wnested-externs', '-Wno-cast-function-type', '-Wno-dangling-pointer', '-Wno-missing-field-initializers', '-Wno-sign-compare', '-Wno-unused-parameter', '-Wold-style-definition', '-Wpointer-arith', '-Wredundant-decls', '-Wstrict-prototypes', '-Wswitch-default', '-Wswitch-enum', '-Wundef', '-Wuninitialized', '-Wunused', '-fno-strict-aliasing', ['-Werror=format-security', '-Werror=format=2'], ] if get_option('buildtype') != 'plain' test_c_args += '-fstack-protector-strong' endif foreach arg: test_c_args if cc.has_multi_arguments(arg) project_c_args += arg endif endforeach add_project_arguments(project_c_args, language: 'c') subdir('data') subdir('src') subdir('po') gnome.post_install( glib_compile_schemas: true, gtk_update_icon_cache: true, update_desktop_database: true, ) endif kolunmi-bazaar-7b9c8e1/meson_options.txt000066400000000000000000000017231514314607700205220ustar00rootroot00000000000000option('hardcoded_main_config_path', type: 'string', value: '', description: 'Hardcoded absolute path to a main yaml config which will be read at runtime') option('hardcoded_blocklist_path', type: 'string', value: '', description: 'Hardcoded absolute path to a package name blocklist which will be read at runtime') option('hardcoded_content_config_path', type: 'string', value: '', description: 'Hardcoded absolute path to a yaml content configuration which will be read at runtime') option('im_a_translator', type: 'boolean', value: false, description: 'Whether to set up the environment for translation work') option('sandboxed_libflatpak', type: 'boolean', value: false, description: 'Whether to treat libflatpak as being sandboxed or not') option('development', type: 'boolean', value: false, description: 'If this is a development build') kolunmi-bazaar-7b9c8e1/po/000077500000000000000000000000001514314607700155005ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/po/.gitignore000066400000000000000000000000121514314607700174610ustar00rootroot00000000000000bazaar.potkolunmi-bazaar-7b9c8e1/po/LINGUAS000066400000000000000000000002111514314607700165170ustar00rootroot00000000000000# Please keep this file sorted alphabetically. ar bg bs cs de el es fa_IR fr ga hu id it ja kw nl pl pt_BR pt_PT ru tr uk vi zh_CN zh_TW kolunmi-bazaar-7b9c8e1/po/POTFILES.in000066400000000000000000000062101514314607700172540ustar00rootroot00000000000000# List of source files containing translatable strings. # Please keep this file sorted alphabetically. data/io.github.kolunmi.Bazaar.desktop.in data/io.github.kolunmi.Bazaar.metainfo.xml.in src/bz-addons-dialog.blp src/bz-addons-dialog.c src/bz-age-rating-dialog.blp src/bz-age-rating-dialog.c src/bz-all-apps-page.blp src/bz-all-apps-page.c src/bz-app-permissions.c src/bz-app-size-dialog.blp src/bz-app-size-dialog.c src/bz-app-tile.blp src/bz-app-tile.c src/bz-apps-page.blp src/bz-apps-page.c src/bz-application-map-factory.c src/bz-application.c src/bz-appstream-parser.c src/bz-async-texture.c src/bz-backend.c src/bz-comet-overlay.c src/bz-content-provider.c src/bz-curated-view.blp src/bz-curated-view.c src/bz-data-graph.c src/bz-decorated-screenshot.blp src/bz-decorated-screenshot.c src/bz-developer-badge.blp src/bz-developer-badge.c src/bz-donations-dialog.blp src/bz-donations-dialog.c src/bz-download-worker.c src/bz-dynamic-list-view.c src/bz-entry-cache-manager.c src/bz-entry-group.c src/bz-entry-group-util.c src/bz-entry-inspector.blp src/bz-entry-inspector.c src/bz-entry-selection-row.blp src/bz-entry-selection-row.c src/bz-entry.c src/bz-env.c src/bz-error.c src/bz-favorite-button.c src/bz-favorite-button.blp src/bz-favorites-tile.c src/bz-favorites-tile.blp src/bz-favorites-page.c src/bz-favorites-page.blp src/bz-featured-carousel.blp src/bz-featured-tile.blp src/bz-flathub-category-section.c src/bz-flathub-category.c src/bz-flathub-page.blp src/bz-flathub-page.c src/bz-flathub-state.c src/bz-flatpak-entry.c src/bz-flatpak-instance.c src/bz-full-view.blp src/bz-full-view.c src/bz-global-net.c src/bz-gnome-shell-search-provider.c src/bz-group-tile-css-watcher.c src/bz-hardware-support-dialog.blp src/bz-hardware-support-dialog.c src/bz-inhibited-scrollable.c src/bz-inspector.blp src/bz-inspector.c src/bz-installed-tile.blp src/bz-installed-tile.c src/bz-io.c src/bz-lazy-async-texture-model.c src/bz-library-page.blp src/bz-library-page.c src/bz-license-dialog.blp src/bz-license-dialog.c src/bz-license-dialog.h src/bz-login-page.blp src/bz-login-page.c src/bz-login-page.h src/bz-preferences-dialog.blp src/bz-preferences-dialog.c src/bz-progress-bar.blp src/bz-progress-bar.c src/bz-releases-dialog.blp src/bz-releases-list.blp src/bz-releases-list.c src/bz-result.c src/bz-rich-app-tile.blp src/bz-rich-app-tile.c src/bz-safety-calculator.c src/bz-safety-dialog.blp src/bz-safety-dialog.c src/bz-screenshot.c src/bz-screenshot-page.blp src/bz-screenshots-carousel.blp src/bz-search-engine.c src/bz-search-widget.blp src/bz-search-widget.c src/bz-section-view.blp src/bz-section-view.c src/bz-serializable.c src/bz-share-list.c src/bz-stats-dialog.blp src/bz-stats-dialog.c src/bz-tag-list.c src/bz-transaction-dialog.c src/bz-transaction-list-dialog.blp src/bz-transaction-list-dialog.c src/bz-transaction-manager.c src/bz-transaction-tile.blp src/bz-transaction-tile.c src/bz-transaction.c src/bz-updates-card.blp src/bz-updates-card.c src/bz-user-data-page.c src/bz-user-data-page.blp src/bz-user-data-tile.c src/bz-user-data-tile.blp src/bz-window.blp src/bz-window.c src/bz-world-map.c src/bz-yaml-parser.c src/dl-worker.c src/gtk/shortcuts-dialog.blp src/main.c kolunmi-bazaar-7b9c8e1/po/ar.po000066400000000000000000001074701514314607700164530ustar00rootroot00000000000000# Arabic translations for bazaar package. # Copyright (C) 2025 bazaar's COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Ahmed Najmawi , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 11:25+0300\n" "PO-Revision-Date: 2025-10-17 20:15+0300\n" "Last-Translator: Ahmed Najmawi \n" "Language-Team: Arabic\n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && " "n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" "X-Generator: Poedit 3.7\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:51 msgid "Bazaar" msgstr "بازار" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "أضِف، أو أزل، أو حدث برمجيات فلاتباك على هذا الحاسوب" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "جتك;النظام;مدير حزم;مدير " "الحزم;الاستكشاف;فلاتباك;البرمجيات;المتجر;التطبيقات;GTK;System;PackageManager;Discover;Flatpak;Software;Store;Bazaar;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Git Forge Star Counts" msgstr "إظهار نجوم مستودع جِت" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the full " "view" msgstr "أيظهر مقدار نجوم مستودع جِت للمشروع أم لا؟" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 src/bz-preferences-dialog.blp:25 msgid "Only Show Free Software" msgstr "إظهار البرمجيات الحرة حصرًا" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software when searching" msgstr "يخفي البرمجيات المحتكرة عند البحث" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "إظهار محتوى فلاتهَب حصرًا" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Filter search results to only show applications available on Flathub" msgstr "يرشِّح نتائج البحث لتظهر التطبيقات المتوفرة على فلاتهَب حصرًا" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "تجاهل ارتداد مدخلات البحث" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "يؤخر إظهار النتائج لمنع ظهورها فوريًا أثناء الكتابة" #: data/io.github.kolunmi.Bazaar.gschema.xml:40 msgid "Global Progress Bar Theme" msgstr "سمة شريط التقدم العامة" #: data/io.github.kolunmi.Bazaar.gschema.xml:41 msgid "Describes the look of the global progress bar" msgstr "يشرح المظهر العام لشريط التقدم" #: data/io.github.kolunmi.Bazaar.gschema.xml:45 msgid "Saved Window Dimensions" msgstr "أبعاد النافذة المحفوظة" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "The window dimensions to be used by the next Bazaar window" msgstr "أبعاد النافذة التي ستستخدمها نافذة بازار التالية" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "استكشف ونصِّب التطبيقات" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "متجر تطبيقات جديد لجنوم يركز على استكشاف وتنصيب التطبيقات والإضافات من فلاتباك، " "وبالأخص مستودع فلاتهَب." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "يُشدِّد «بازار» على دعم المطورين الواقفين وراء إتاحة سطح مكتب لينكس، ويضم لسانًا " "للمحتوى المنتقى يمكن للموزِّعين إعداده لتوفير تجربة استخدام أكثر مواءمة." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:47 msgid "The home view displaying Flathub apps" msgstr "صفحة المنظور العام وهي تعرض تطبيقات فلاتهَب" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:51 msgid "Nucleus app page" msgstr "صفحة تطبيق «Nucleus»" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "Searching for Blender" msgstr "البحث عن «بلندر»" #: src/bz-addons-dialog.blp:13 msgid "Manage Addons" msgstr "أدِر الإضافات" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "من حجم الحمض الريبي النووي منزوع الأكسجين للإنسان" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 مليارات زوج قاعدي" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "من نواة لينكس" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "من حاسوب توجيه أبولو 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "إجمالي ذاكرة القراءة والذاكرة العشوائية" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "من لعبة «سوبر ماريو بروز» الأصلية" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "على نينتندو إنترتينمنت سِستم" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "من حجم ويكيبيديا" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "دون أي وسائط" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- م‌ب" #: src/bz-app-size-dialog.blp:53 src/bz-full-view.blp:351 msgid "Download Size" msgstr "حجم التنزيل" #: src/bz-application.c:392 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "هذه الوظيفة معطَّلة حاليًا. ينصح بتنصيب «فلاتسيل» لإدارة أذونات التطبيق." #: src/bz-application.c:456 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:457 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "أحمد النجماوي " #: src/bz-application.c:462 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "أحمد النجماوي" #: src/bz-application.c:463 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:464 msgctxt "About Dialog Translator Credit" msgid "Azenyr" msgstr "AtomHare" #: src/bz-application.c:465 msgctxt "About Dialog Translator Credit" msgid "Goudarz Jafari" msgstr "Goudarz Jafari" #: src/bz-application.c:466 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore (Lumaeris)" msgstr "Jill Fiore (Lumaeris)" #: src/bz-application.c:467 msgctxt "About Dialog Translator Credit" msgid "João Victor (Leal)" msgstr "João Victor (Leal)" #: src/bz-application.c:468 msgctxt "About Dialog Translator Credit" msgid "KiKaraage" msgstr "KiKaraage" #: src/bz-application.c:469 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:470 msgctxt "About Dialog Translator Credit" msgid "Léane GRASSER" msgstr "Léane GRASSER" #: src/bz-application.c:471 msgctxt "About Dialog Translator Credit" msgid "Marcel Mrówka (Microwave)" msgstr "Marcel Mrówka (Microwave)" #: src/bz-application.c:472 msgctxt "About Dialog Translator Credit" msgid "Peter Dave Hello" msgstr "Peter Dave Hello" #: src/bz-application.c:473 msgctxt "About Dialog Translator Credit" msgid "Pietro F." msgstr "Pietro F." #: src/bz-application.c:474 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:475 msgctxt "About Dialog Translator Credit" msgid "Shinsei" msgstr "Shinsei" #: src/bz-application.c:476 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:477 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:478 msgctxt "About Dialog Translator Credit" msgid "camegone" msgstr "camegone" #: src/bz-application.c:479 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:480 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-application.c:496 msgid "Adam Masciola" msgstr "Adam Masciola" #: src/bz-application.c:1019 msgid "Constructing Flatpak instance..." msgstr "تُبنى نسخة فلاتباك..." #: src/bz-application.c:1036 msgid "Reusing last Flatpak instance..." msgstr "يعاد استخدام آخر نسخة فلاتباك..." #: src/bz-application.c:1061 msgid "Flathub is not registered on this system" msgstr "لم يُسجِّل فلاتهَب على هذا النظام" #: src/bz-application.c:1064 msgid "" "Would you like to add Flathub as a remote? If you decline, the Flathub page will " "not be available. You can change this later." msgstr "" "أتود إضافة فلاتهَب كمستودع؟ لن تتوفر صفحة فلاتهَب إن رفضت ذلك. يمكنك تغيير ذلك " "لاحقًا." #: src/bz-application.c:1069 src/bz-update-dialog.blp:6 msgid "Later" msgstr "لاحقًا" #: src/bz-application.c:1070 msgid "Add Flathub" msgstr "أضِف فلاتهَب" #: src/bz-application.c:1102 #, c-format msgid "Identifying installed entries..." msgstr "يتعرف على المدخلات المنصَّبة..." #: src/bz-application.c:1114 #, c-format msgid "Beginning remote entry retrieval while referencing %d blocklist(s)..." msgstr "يبدأ جلب مدخلات المستودع أثناء إحالة %d قائمة حجب..." #: src/bz-application.c:1262 #, c-format msgid "Receiving Entries" msgstr "يستلم المدخلات" #: src/bz-application.c:1263 #, c-format msgid "%'d of %'d" msgstr "%'d من %'d" #: src/bz-application.c:1273 #, c-format msgid "Waiting for background indexing tasks to catch up..." msgstr "ينتظر اكتمال مهام فهرسة الخلفية..." #: src/bz-application.c:1309 #, c-format msgid "Completed initialization in %0.2f seconds" msgstr "اكتمل التمهيد خلال %0.2f ثانية" #: src/bz-application.c:1314 msgid "Checking for updates..." msgstr "يلتمس التحديثات..." #: src/bz-application.c:1353 msgid "Synchronizing..." msgstr "يُزامن..." #: src/bz-browse-widget.blp:11 src/bz-flathub-page.blp:11 src/bz-full-view.blp:10 #: src/bz-installed-page.blp:11 src/bz-window.blp:151 msgid "Empty" msgstr "فارغ" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "لا تطبيقات منتقاة" #: src/bz-browse-widget.blp:16 msgid "" "Bazaar was not provided a curated content configuration. Contact your operating " "system's support channels for assistance." msgstr "" "لم يُزوَّد بازار بإعدادات محتوى منتقى. تواصل مع قنوات دعم نظام تشغيلك للحصول على " "المساعدة." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:22 msgid "Browser" msgstr "المتصفح" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "فاحص المدخلات" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "سَلسِل" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "حوِّل إلى JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "حدث خطأ" #: src/bz-error.c:89 msgid "Close" msgstr "أغلِق" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "انسخ وأغلِق" #: src/bz-flathub-category.c:290 msgid "Audio & Video" msgstr "صوت وفيديو" #: src/bz-flathub-category.c:292 msgid "Development" msgstr "تطوير" #: src/bz-flathub-category.c:294 msgid "Education" msgstr "تعليم" #: src/bz-flathub-category.c:296 msgid "Games" msgstr "ألعاب" #: src/bz-flathub-category.c:298 msgid "Graphics" msgstr "رسوميات" #: src/bz-flathub-category.c:300 msgid "Networking" msgstr "شبكات" #: src/bz-flathub-category.c:302 msgid "Office" msgstr "مكتب" #: src/bz-flathub-category.c:304 msgid "Science" msgstr "علوم" #: src/bz-flathub-category.c:306 msgid "System" msgstr "نظام" #: src/bz-flathub-category.c:308 msgid "Utilities" msgstr "أدوات" #: src/bz-flathub-page.blp:15 msgid "Flathub Not Added" msgstr "لم يُضف فلاتهَب" #: src/bz-flathub-page.blp:16 msgid "The Flathub remote was not found on any of your flatpak installations" msgstr "لم يعثر على مستودع فلاتهَب في أي من تنصيبات فلاتباك خاصتك" #: src/bz-flathub-page.blp:70 src/bz-flathub-page.c:185 msgid "Trending" msgstr "الرائجة" #: src/bz-flathub-page.blp:101 msgid "More Trending" msgstr "المزيد من التطبيقات الرائجة" #: src/bz-flathub-page.blp:117 msgid "Categories" msgstr "التصنيفات" #: src/bz-flathub-page.blp:154 src/bz-flathub-page.c:195 msgid "Recently Updated" msgstr "حُدِّثت مؤخرًا" #: src/bz-flathub-page.blp:185 msgid "More Updated" msgstr "المزيد من التطبيقات المُحدَّثة" #: src/bz-flathub-page.blp:206 src/bz-flathub-page.c:205 msgid "Recently Added" msgstr "أُضيفت مؤخرًا" #: src/bz-flathub-page.blp:237 msgid "More Added" msgstr "المزيد من التطبيقات المضافة مؤخرًا" #: src/bz-flathub-page.blp:258 src/bz-flathub-page.c:215 msgid "Popular" msgstr "الشائعة" #: src/bz-flathub-page.blp:289 msgid "More Popular" msgstr "المزيد من التطبيقات الشائعة" #: src/bz-flatpak-entry.c:507 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "صفحة فلاتهَب" #: src/bz-flatpak-entry.c:526 msgctxt "Project URL Type" msgid "Homepage" msgstr "الصفحة الرئيسة" #: src/bz-flatpak-entry.c:529 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "متعقب العلل" #: src/bz-flatpak-entry.c:532 msgctxt "Project URL Type" msgid "FAQ" msgstr "الأسئلة الشائعة" #: src/bz-flatpak-entry.c:535 msgctxt "Project URL Type" msgid "Help" msgstr "المساعدة" #: src/bz-flatpak-entry.c:538 msgctxt "Project URL Type" msgid "Donate" msgstr "التبرع" #: src/bz-flatpak-entry.c:543 msgctxt "Project URL Type" msgid "Translate" msgstr "الترجمة" #: src/bz-flatpak-entry.c:546 msgctxt "Project URL Type" msgid "Contact" msgstr "التواصل" #: src/bz-flatpak-entry.c:549 msgctxt "Project URL Type" msgid "Source Code" msgstr "المصدر البرمجي" #: src/bz-flatpak-entry.c:554 msgctxt "Project URL Type" msgid "Contribute" msgstr "المساهمة" #: src/bz-full-view.blp:14 msgid "No Results" msgstr "لا توجد نتائج" #: src/bz-full-view.blp:15 msgid "Try a different search query" msgstr "جرِّب عبارة بحث مختلفة" #: src/bz-full-view.blp:21 src/bz-window.blp:161 msgid "Content" msgstr "المحتوى" #: src/bz-full-view.blp:129 msgid "This flatpak is verified by the original developers of the software." msgstr "وثَّق مطوروا البرمجية فلاتباك هذا." #: src/bz-full-view.blp:156 msgid "Support" msgstr "ادعَم" #: src/bz-full-view.blp:176 msgid "Repository Star Count" msgstr "نجوم المستودع" #: src/bz-full-view.blp:207 msgid "Run Application" msgstr "شغِّل التطبيق" #: src/bz-full-view.blp:221 msgid "Download & Install Application" msgstr "نزِّل التطبيق ونصِّبه" #: src/bz-full-view.blp:224 src/bz-transaction-view.blp:108 src/bz-window.c:1071 msgid "Install" msgstr "نصِّب" #: src/bz-full-view.blp:236 msgid "Uninstall Application" msgstr "أزِل التطبيق" #: src/bz-full-view.blp:251 src/bz-installed-page.blp:125 msgid "Manage Add-ons" msgstr "أدِر الإضافات" #: src/bz-full-view.blp:264 msgid "Install Other Version" msgstr "نصِّب إصدارًا آخر" #: src/bz-full-view.blp:279 msgid "Share this application" msgstr "شارِك هذا التطبيق" #: src/bz-full-view.blp:362 msgid "Excludes shared components" msgstr "يستبعد المكونات المشتركة" #: src/bz-full-view.blp:418 msgid "Free Software" msgstr "برمجية حرة" #: src/bz-full-view.blp:460 msgid "Proprietary" msgstr "محتكرة" #: src/bz-full-view.blp:471 msgid "Source code may not be available" msgstr "قد لا يتوفر المصدر البرمجي" #: src/bz-full-view.blp:526 msgid "Click for details" msgstr "انقر للتفاصيل" #: src/bz-full-view.blp:592 msgid "Repositories" msgstr "المستودعات" #: src/bz-full-view.blp:623 src/bz-full-view.blp:631 msgid "Project Website" msgstr "موقع المشروع" #: src/bz-full-view.blp:639 msgid "Open in browser" msgstr "افتح في المتصفح" #: src/bz-full-view.c:213 #, c-format msgid "%'d Monthly Downloads" msgstr "%'d تنزيل شهري" #: src/bz-full-view.c:215 msgid "--- Downloads" msgstr "--- تنزيل" #: src/bz-full-view.c:241 msgid "Unknown" msgstr "مجهول" #. Translators: This is a date format for timestamps from previous years. Used in the app releases section. #. * %B is the full month name, %e is the day, %Y is the year. #. * Example: "October 1, 2025" #. * See https://docs.gtk.org/glib/method.DateTime.format.html for format options #. * Please modify to make it sound natural in your locale. #. * #: src/bz-full-view.c:268 msgid "%B %-d, %Y" msgstr "%-Od %B، %OY" #. Translators: This is a date format for timestamps from the current year. Used in the app releases section. #. * %B is the full month name, %e is the day. #. * Example: "October 1" #. * See https://docs.gtk.org/glib/method.DateTime.format.html for format options #. * Please modify to make it sound natural in your locale. #. * #: src/bz-full-view.c:276 msgid "%B %-d" msgstr "%-Od %B" #: src/bz-full-view.c:287 msgid "No URL" msgstr "لا رابط" #: src/bz-full-view.c:305 msgid "" "This application has a FLOSS license, meaning the source code can be audited for " "safety." msgstr "هذا التطبيق مرخص تحت رخصة حرَّة، مما يعني أنه يمكن فحص المصدر البرمجي أمنيًا." #: src/bz-full-view.c:306 msgid "" "This application has a proprietary license, meaning the source code is developed " "privately and cannot be audited by an independent third party." msgstr "" "هذا التطبيق مرخص تحت رخصة احتكارية، مما يعني أنه يطوَّر بشكل خاص ولا يمكن الوصول " "للمصدر البرمجي أو فحصه أمنيًا بواسطة طرف ثالث." #: src/bz-full-view.c:596 #, c-format msgid "Version %s" msgstr "الإصدار %s" #: src/bz-full-view.c:621 msgid "No details for this release" msgstr "لا تفاصيل لهذه الإصدارة" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "متعقب «بازار»" #: src/bz-inspector.blp:22 msgid "Active Blocklists" msgstr "قوائم الحجب النشطة" #: src/bz-inspector.blp:44 msgid "Active Curated-Configs" msgstr "ضبط التطبيقات «المنتقاة» النشط" #: src/bz-inspector.blp:66 msgid "All Entry Groups" msgstr "جميع مجموعات المدخلات" #: src/bz-inspector.blp:69 msgid "Filter..." msgstr "رشِّح..." #: src/bz-inspector.blp:110 msgid "Decache and Inspect" msgstr "امحُ الاختزان وافحص" #: src/bz-installed-page.blp:15 msgid "No Flatpaks Installed" msgstr "لا حزم فلاتباك منصَّبة" #: src/bz-installed-page.blp:21 src/bz-window.blp:302 src/bz-window.blp:395 msgid "Installed" msgstr "المنصَّبة" #: src/bz-installed-page.blp:101 msgid "Support this application" msgstr "ادعم هذا التطبيق" #: src/bz-installed-page.blp:151 src/bz-window.c:1093 msgid "Remove" msgstr "أزِل" #: src/bz-installed-page.blp:178 msgid "More actions" msgstr "إجراءات إضافية" #: src/bz-installed-page.blp:197 msgid "Run this application" msgstr "شغِّل هذا التطبيق" #: src/bz-installed-page.blp:209 msgid "Run" msgstr "شغِّل" #: src/bz-installed-page.blp:221 src/bz-installed-page.blp:232 msgid "View Store Page" msgstr "أظهِر صفحة المتجر" #: src/bz-installed-page.c:649 msgid "Choose an Installation" msgstr "اختر تنصيبًا" #: src/bz-installed-page.c:652 msgid "" "You have multiple versions of this app installed. Which one would you like to " "proceed with? " msgstr "لديك عدة إصدارات منصَّبة من هذا التطبيق. أي واحد ستشرع به؟ " #: src/bz-installed-page.c:656 src/bz-window.c:1070 src/bz-window.c:1092 msgid "Cancel" msgstr "ألغِ" #: src/bz-preferences-dialog.blp:9 msgid "Preferences" msgstr "التفضيلات" #: src/bz-preferences-dialog.blp:13 msgid "Application Details" msgstr "تفاصيل التطبيق" #: src/bz-preferences-dialog.blp:16 msgid "Git Forge Star Counts" msgstr "نجوم مستودع جِت" #: src/bz-preferences-dialog.blp:17 msgid "Not having a GitHub access token may trigger rate limits" msgstr "قد يُحدّ وصولك إن لم يكن لديك رمز وصول جِت‌هَب" #: src/bz-preferences-dialog.blp:22 src/bz-window.blp:43 src/bz-window.blp:58 #: src/bz-window.blp:334 msgid "Search" msgstr "ابحث" #: src/bz-preferences-dialog.blp:26 msgid "Hide proprietary applications from search results" msgstr "إخفاء التطبيقات المحتكرة من نتائج البحث" #: src/bz-preferences-dialog.blp:30 msgid "Show Only Flathub Apps" msgstr "إظهار تطبيقات فلاتهَب حصرًا" #: src/bz-preferences-dialog.blp:31 msgid "Limit search results to applications available on Flathub" msgstr "يحدّ نتائج البحث إلى التطبيقات المتوفرة على فلاتهَب حصرًا" #: src/bz-preferences-dialog.blp:35 msgid "Debounce Search Results" msgstr "تجاهل ارتداد نتائج البحث" #: src/bz-preferences-dialog.blp:36 msgid "Wait for a brief pause to reduce system load" msgstr "ينتظر وهلة لتخفيف حِمل النظام عند البحث" #: src/bz-preferences-dialog.blp:41 msgid "Global Progress Bar" msgstr "شريط التقدم العام" #: src/bz-preferences-dialog.blp:44 msgid "Theme" msgstr "السمة" #: src/bz-preferences-dialog.blp:45 msgid "Choose a fun theme for the global progress bar!" msgstr "يحدِّد سمة مرحة لشريط التقدم العام!" #: src/bz-preferences-dialog.blp:48 msgid "Accent Color" msgstr "لون النظام" #: src/bz-preferences-dialog.blp:49 msgid "Pride Rainbow Flag" msgstr "علم فخر قوس قزح" #: src/bz-preferences-dialog.blp:50 msgid "Lesbian Pride Flag" msgstr "علم فخر السحاقيات" #: src/bz-preferences-dialog.blp:51 msgid "Transgender Flag" msgstr "علم التحول جنسانيًا" #: src/bz-preferences-dialog.blp:52 msgid "Nonbinary Flag" msgstr "علم اللاثنائية" #: src/bz-preferences-dialog.blp:53 msgid "Bisexual Flag" msgstr "علم ازدواج التوجه الجنسي" #: src/bz-preferences-dialog.blp:54 msgid "Asexual Flag" msgstr "علم اللاجنسية" #: src/bz-preferences-dialog.blp:55 msgid "Pansexual Flag" msgstr "علم الشمولية الجنسية" #: src/bz-preferences-dialog.blp:56 msgid "Aromantic Flag" msgstr "علم اللارومانسية" #: src/bz-preferences-dialog.blp:57 msgid "Genderfluid Flag" msgstr "علم الانسياب الجنساني" #: src/bz-preferences-dialog.blp:58 msgid "Polysexual Flag" msgstr "علم التعدد الجنسي" #: src/bz-preferences-dialog.blp:59 msgid "Omnisexual Flag" msgstr "علم الشمولية الجنسية" #: src/bz-search-widget.blp:69 msgid "Search Apps" msgstr "ابحث التطبيقات" #: src/bz-share-dialog.blp:13 msgid "Share" msgstr "شارِك" #: src/bz-share-dialog.c:62 msgid "Copied!" msgstr "نُسِخ!" #: src/bz-share-dialog.c:106 msgid "Copy Link" msgstr "انسخ الوصلة" #: src/bz-share-dialog.c:117 msgid "Open Link" msgstr "افتح الوصلة" #: src/bz-stats-dialog.blp:26 msgid "Timeline" msgstr "الخط الزمني" #: src/bz-stats-dialog.blp:31 msgid "Installs:" msgstr "التنصيبات:" #: src/bz-stats-dialog.blp:37 msgid "World" msgstr "العالم" #: src/bz-transaction-manager.c:1140 #, c-format msgid "Finished in %.02f seconds" msgstr "انتهى خلال %.02f ثانية" #: src/bz-transaction-view.blp:95 msgid "Install Size" msgstr "حجم التنصيب" #: src/bz-transaction-view.blp:238 msgid "Error Details" msgstr "تفاصيل الخطأ" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "نُقِل %s حتى الآن" #: src/bz-transaction.c:336 msgid "Pending" msgstr "ينتظر" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "نصِّب الآن" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "تتوفر تحديثات" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to install " "them?" msgstr "التطبيقات التالية متاحة للتحديث. أتنصبها؟" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to install " "them?" msgstr "تتوفر تحديثات ل‍ %d من بيئات التشغيل و\\أو الإضافات. أتنصبها؟" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "بالإضافة إلى ذلك، ستُحدَّث %d من بيئات التشغيل و\\أو الإضافات." #: src/bz-window.blp:80 msgid "Transactions" msgstr "العمليات" #: src/bz-window.blp:95 src/bz-window.blp:414 msgid "Toggle transaction sidebar" msgstr "بدِّل الشريط الجانبي للعمليات" #: src/bz-window.blp:131 msgid "Stop Active Tasks" msgstr "أوقف المهام النشطة" #: src/bz-window.blp:139 msgid "Clear History" msgstr "امحُ التأريخ" #: src/bz-window.blp:155 msgid "No Tasks Yet" msgstr "لا توجد مهام حتى الآن" #: src/bz-window.blp:210 src/bz-window.blp:214 msgid "Offline" msgstr "غير متصل" #: src/bz-window.blp:220 msgid "Loading" msgstr "يحمِّل" #: src/bz-window.blp:268 msgid "Browse" msgstr "تصفَّح" #: src/bz-window.blp:278 msgid "App View" msgstr "منظور التطبيق" #: src/bz-window.blp:292 src/bz-window.blp:388 msgid "Flathub" msgstr "فلاتهَب" #: src/bz-window.blp:322 msgid "Go Back" msgstr "ارجِع" #: src/bz-window.blp:347 msgid "Update" msgstr "حدِّث" #: src/bz-window.blp:377 msgid "View curated applications" msgstr "اعرِض التطبيقات المنتقاة" #: src/bz-window.blp:381 msgid "Curated" msgstr "المنتقاة" #: src/bz-window.blp:385 msgid "View the latest on Flathub" msgstr "اعرِض آخر المستجدات على فلاتهَب" #: src/bz-window.blp:392 msgid "View installed applications" msgstr "اعرِض التطبيقات المنصَّبة" #: src/bz-window.blp:437 msgid "Main Menu" msgstr "القائمة الرئيسة" #: src/bz-window.blp:471 msgid "_Quit Service" msgstr "أ_نهِ الخدمة" #: src/bz-window.blp:476 msgid "_Refresh Content" msgstr "أ_عِد تحميل المحتوى" #: src/bz-window.blp:481 msgid "_Preferences" msgstr "ال_تفضيلات" #: src/bz-window.blp:486 msgid "_Keyboard Shortcuts" msgstr "ا_ختصارات لوحة المفاتيح" #: src/bz-window.blp:491 msgid "_About Bazaar" msgstr "_عَنْ بازار" #: src/bz-window.blp:496 msgid "_Donate to Bazaar ❤️" msgstr "ت_برَّع إلى بازار ❤️" #: src/bz-window.c:628 msgid "Up to date!" msgstr "مُحدَّث!" #: src/bz-window.c:800 msgid "" "The ability to inspect and install local .flatpak bundle files is coming soon! " "In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "قابلة فحص وتنصيب ملفات حزم .flatpak قادمة. أثناء ذلك، يمكنك تشغيل\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "في الطرفية." #: src/bz-window.c:935 msgid "Can't do that right now!" msgstr "لا يمكن فعل ذلك الآن!" #: src/bz-window.c:1064 #, c-format msgid "Install %s?" msgstr "أتُنصِّب %s؟" #: src/bz-window.c:1067 msgid "May install additional shared components" msgstr "قد تُنصَّب مكونات إضافية مشتركة" #: src/bz-window.c:1086 #, c-format msgid "Remove %s?" msgstr "أتُزيل %s؟" #: src/bz-window.c:1089 msgid "Settings & user data will be kept" msgstr "ستبقى الإعدادات وبيانات المستخدم مخزَّنة" #: src/bz-window.c:1257 msgid "Resume Current Tasks" msgstr "استأنف المهام الحالية" #: src/bz-window.c:1263 msgid "Pause Current Tasks" msgstr "ألبث المهام الحالية" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u تنزيل" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "عام" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "افتح حواريَّة البحث" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Refresh" msgstr "أعِد التحميل" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "بدِّل مدير المعاملات" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "أظهِر الاختصارات" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Quit" msgstr "اخرُج" #~ msgid "Calligraphy application page" #~ msgstr "صفحة تطبيق «كالِغرَفي»" #~ msgid "Download graph for Blender" #~ msgstr "تنزيل رسم بياني ل‍«بلندر»" #~ msgid "Open this image in the default image viewer" #~ msgstr "افتح هذه الصورة في عارض الصور المبدئي" #~ msgid "Copy this image to the clipboard" #~ msgstr "انسخ هذه الصورة إلى الحافظة" #~ msgid "App Details" #~ msgstr "تفاصيل التطبيق" #~ msgid "License" #~ msgstr "الرخصة" #~ msgid "Download Statistics" #~ msgstr "إحصاءات التنزيل" #~ msgid "Show Downloads Over Time" #~ msgstr "أظهِر التنزيلات عبر الزمن" #~ msgid "Remote repo name" #~ msgstr "اسم المستودع" #, c-format #~ msgid "%'d downloads in the last month" #~ msgstr "%'d تنزيلًا خلال الشهر الماضي" #~ msgid "Updated Size" #~ msgstr "الحجم المحدَّث" #~ msgid "Freed Space" #~ msgstr "المساحة المفرغة" #~ msgid "Transactions Will Appear Here" #~ msgstr "ستظهر العمليات هنا" #~ msgid "Halt the execution of transactions" #~ msgstr "أوقِف تنفيذ العمليات" #~ msgid "Clear all finished transactions" #~ msgstr "امحُ كل العمليات المنتهية" #~ msgid "Resume the execution of transactions" #~ msgstr "استَئنف تنفيذ العمليات" #~ msgid "Pause the execution of transactions" #~ msgstr "أوقِف تنفيذ العمليات مؤقتًا" #~ msgid "Apps Of The Week" #~ msgstr "تطبيقات الأسبوع" #~ msgid "Show More" #~ msgstr "أظهر المزيد" #, c-format #~ msgid "Released %x" #~ msgstr "أُصدِر في %x" #~ msgid "Downloads Over Time" #~ msgstr "التنزيلات عبر الزمن" #~ msgid "Minimize Lower Bound" #~ msgstr "صغِّر الحد الأدنى" #~ msgid "Maximize Upper Bound" #~ msgstr "كبِّر الحد الأعلى" #~ msgid "Confirm Action" #~ msgstr "تأكيد الإجراء" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "أنت على وشك إزالة حزمة فلاتباك التالية:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "أمتأكد؟" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "أنت على وشك تنصيب حزمة فلاتباك التالية:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "أمتأكد؟" #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "المستودع" #~ msgid "Full Application View" #~ msgstr "عرض التطبيق الكامل" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "يغيِّر المحتوى المعروض عند إظهار التطبيقات" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause GitHub " #~ "to eventually rate limit you." #~ msgstr "" #~ "قد يؤدي تفعيل هذا الإعداد إلى حدِّك من الوصول إلى GitHub إن لم يكن لديك رمز " #~ "وصول." #~ msgid "Type to filter" #~ msgstr "اكتب للترشيح" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "استبعِد النتائج ذات الرخص الاحتكارية" #~ msgid "Exclude results not originating from Flathub" #~ msgstr "استبعِد النتائج التي ليست من فلاتهَب" #~ msgid "Advanced" #~ msgstr "متقدم" #~ msgid "Open this link externally" #~ msgstr "افتح هذه الوصلة خارجيًا" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "استُلمت %'d من أصل %'d (انقضت %0.1f ثانية)" #~ msgid "Open in Image Viewer" #~ msgstr "افتح في عارض الصور" #~ msgid "Installing" #~ msgstr "ينصَّب" #~ msgid "Updating" #~ msgstr "يحدَّث" #~ msgid "Removing" #~ msgstr "يُزال" #~ msgid "Show Animated Background" #~ msgstr "إظهار الخلفية المتحركة" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "أتُعرَض خلفية الأيقونات المتحركة في الصفحة الرئيسة أم لا" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this application's " #~ "download statistics." #~ msgstr "عدد التنزيلات في آخر 30 يومًا. انقر لعرض إحصائيات تنزيل هذا التطبيق." #~ msgid "Support this developer" #~ msgstr "ادعَم هذا المطور" #~ msgid "Edit Permissions" #~ msgstr "حرِّر الأذونات" #~ msgid "How the application looks" #~ msgstr "كيف يبدو التطبيق" #~ msgid "Appearance" #~ msgstr "المظهر" #~ msgid "Show animated background" #~ msgstr "إظهار الخلفية المتحركة" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "أبقِ الملخص مختصرًا، بين 10 و 35 حرفًا" #~ msgid "No description" #~ msgstr "لا يوجد وصف" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "نافذة بازار الرئيسية تعرض تطبيق بلندر" #~ msgid "Match using regular expressions" #~ msgstr "طابِق باستخدام التعابير النمطية" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "أخفِ الترشيح والفرز خلف تأثير التلاشي المتداخل" kolunmi-bazaar-7b9c8e1/po/bg.po000066400000000000000000001102611514314607700164310ustar00rootroot00000000000000# Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # twlvnn kraftwerk , 2025 # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-18 06:40+0200\n" "PO-Revision-Date: 2025-10-19 11:04+0200\n" "Last-Translator: twlvnn kraftwerk \n" "Language-Team: Bulgarian\n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.8\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 src/bz-window.blp:51 msgid "Bazaar" msgstr "Базар" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Добавяйте, премахвайте или обновете flatpak софтуер на този компютър" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;PackageManager;Discover;Flatpak;Software;Store;система;мениджър на пакети;откриване;софтуер;програми;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Git Forge Star Counts" msgstr "Показване на броя на звездите в Git Forge" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Whether to attempt to detect and show \"star counts\" for projects in the full view" msgstr "Дали да се опита да се засече и покаже „броя на звездите“ за проектите в пълния изглед" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 src/bz-preferences-dialog.blp:25 msgid "Only Show Free Software" msgstr "Показване само на свободен софтуер" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software when searching" msgstr "Скриване на собственически софтуер при търсене" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "Показване само на Flathub съдържание" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Filter search results to only show applications available on Flathub" msgstr "Филтриране на резултатите от търсенето, за да се показват само програмите, налични в Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "Забавяне на входа за търсене" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "Добавяне на закъснение преди търсенето, за да се предотвратят незабавни резултати по време на писане" #: data/io.github.kolunmi.Bazaar.gschema.xml:40 msgid "Global Progress Bar Theme" msgstr "Тема за глобалната лента за напредък" #: data/io.github.kolunmi.Bazaar.gschema.xml:41 msgid "Describes the look of the global progress bar" msgstr "Описва вида на глобалната лента за напредък" #: data/io.github.kolunmi.Bazaar.gschema.xml:45 msgid "Saved Window Dimensions" msgstr "Запазени размери на прозореца" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "The window dimensions to be used by the next Bazaar window" msgstr "Размерите на прозореца, които ще се използват от следващия прозорец на Базар" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Открийте и инсталирайте програми" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "A new app store for GNOME with a focus on discovering and installing applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Нов магазин за програми за GNOME, предназначен за откриването и инсталирането на програми и добавки от Flatpak отдалечени хранилища, по-" "специфично Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. Bazaar features a \"curated\" tab that can be configured by " "distributors to allow for a more localized experience." msgstr "" "Той взема под внимание подкрепата на разработчиците, които правят Луникс за настолни компютри възможен. Bazaar разполага с раздел „подбрани“, " "който може да бъде настроен от дистрибуторите, за да позволи по-специализирано потребителско изживяване." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:22 src/bz-application.c:496 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:47 msgid "The home view displaying Flathub apps" msgstr "Началната страница, показваща програми на Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:51 msgid "Nucleus app page" msgstr "Страницата на Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:55 msgid "Searching for Blender" msgstr "Търсене за Blender" #: src/bz-addons-dialog.blp:13 msgid "Manage Addons" msgstr "Управление на добавки" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- МБ" #: src/bz-app-size-dialog.blp:53 src/bz-full-view.blp:351 msgid "Download Size" msgstr "Размер за изтегляне" #: src/bz-application.c:392 msgid "This functionality is currently disabled. It is recommended you download and install Flatseal to manage app permissions." msgstr "Тази функционалност е деактивирана в момента. Препоръчваме да изтеглите и инсталирате Flatseal, за да управлявате права̀та на програмите." #: src/bz-application.c:456 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:457 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "twlvnn kraftwerk" #: src/bz-application.c:462 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "Ahmed Najmawi" #: src/bz-application.c:463 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:464 msgctxt "About Dialog Translator Credit" msgid "Azenyr" msgstr "Azenyr" #: src/bz-application.c:465 msgctxt "About Dialog Translator Credit" msgid "Goudarz Jafari" msgstr "Goudarz Jafari" #: src/bz-application.c:466 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore (Lumaeris)" msgstr "Jill Fiore (Lumaeris)" #: src/bz-application.c:467 msgctxt "About Dialog Translator Credit" msgid "João Victor (Leal)" msgstr "João Victor (Leal)" #: src/bz-application.c:468 msgctxt "About Dialog Translator Credit" msgid "KiKaraage" msgstr "KiKaraage" #: src/bz-application.c:469 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:470 msgctxt "About Dialog Translator Credit" msgid "Léane GRASSER" msgstr "Léane GRASSER" #: src/bz-application.c:471 msgctxt "About Dialog Translator Credit" msgid "Marcel Mrówka (Microwave)" msgstr "Marcel Mrówka (Microwave)" #: src/bz-application.c:472 msgctxt "About Dialog Translator Credit" msgid "Peter Dave Hello" msgstr "Peter Dave Hello" #: src/bz-application.c:473 msgctxt "About Dialog Translator Credit" msgid "Pietro F." msgstr "Pietro F." #: src/bz-application.c:474 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:475 msgctxt "About Dialog Translator Credit" msgid "Shinsei" msgstr "Shinsei" #: src/bz-application.c:476 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:477 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:478 msgctxt "About Dialog Translator Credit" msgid "camegone" msgstr "camegone" #: src/bz-application.c:479 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:480 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-application.c:1019 msgid "Constructing Flatpak instance..." msgstr "Изграждане на Flatpak инстанция..." #: src/bz-application.c:1036 msgid "Reusing last Flatpak instance..." msgstr "Преизползване на последната Flatpak инстанция…" #: src/bz-application.c:1061 msgid "Flathub is not registered on this system" msgstr "Flathub не е регистриран в тази система" #: src/bz-application.c:1064 msgid "Would you like to add Flathub as a remote? If you decline, the Flathub page will not be available. You can change this later." msgstr "" "Искате ли да добавите Flathub като отдалечено хранилище? Ако откажете, страницата на Flathub няма да бъде достъпна. Може да промените това по-" "късно." #: src/bz-application.c:1069 src/bz-update-dialog.blp:6 msgid "Later" msgstr "По-късно" #: src/bz-application.c:1070 msgid "Add Flathub" msgstr "Добавяне на Flathub" #: src/bz-application.c:1102 #, c-format msgid "Identifying installed entries..." msgstr "Идентифициране на инсталираните записи..." #: src/bz-application.c:1114 #, c-format msgid "Beginning remote entry retrieval while referencing %d blocklist(s)..." msgstr "Получаване на отдалечените записи и четене от %d списък(а) за блокиране..." #: src/bz-application.c:1262 #, c-format msgid "Receiving Entries" msgstr "Получаване на записите" #: src/bz-application.c:1263 #, c-format msgid "%'d of %'d" msgstr "%'d от %'d" #: src/bz-application.c:1273 #, c-format msgid "Waiting for background indexing tasks to catch up..." msgstr "Изчакване на задачите за индексиране във фона да настигнат…" #: src/bz-application.c:1309 #, c-format msgid "Completed initialization in %0.2f seconds" msgstr "Инициализацията завърши за %0.2f секунди" #: src/bz-application.c:1314 msgid "Checking for updates..." msgstr "Проверяване за обновления..." #: src/bz-application.c:1353 msgid "Synchronizing..." msgstr "Синхронизиране..." #: src/bz-browse-widget.blp:11 src/bz-flathub-page.blp:11 src/bz-full-view.blp:10 src/bz-installed-page.blp:11 src/bz-window.blp:151 msgid "Empty" msgstr "Празно" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "Няма подбрани програми" #: src/bz-browse-widget.blp:16 msgid "Bazaar was not provided a curated content configuration. Contact your operating system's support channels for assistance." msgstr "Bazaar не разполага с настройки за подбрано съдържание. Свържете се с каналите за поддръжка на вашата операционна система за помощ." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:22 msgid "Browser" msgstr "Браузър" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Инспектор на записите" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Сериализиране" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Преобразуване в JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Възникна грешка" #: src/bz-error.c:89 msgid "Close" msgstr "Затваряне" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Копиране и затваряне" #: src/bz-flathub-category.c:290 msgid "Audio & Video" msgstr "Аудио & видео" #: src/bz-flathub-category.c:292 msgid "Development" msgstr "Разработка" #: src/bz-flathub-category.c:294 msgid "Education" msgstr "Образование" #: src/bz-flathub-category.c:296 msgid "Games" msgstr "Игри" #: src/bz-flathub-category.c:298 msgid "Graphics" msgstr "Графика" #: src/bz-flathub-category.c:300 msgid "Networking" msgstr "Интернет" #: src/bz-flathub-category.c:302 msgid "Office" msgstr "Офис" #: src/bz-flathub-category.c:304 msgid "Science" msgstr "Наука" #: src/bz-flathub-category.c:306 msgid "System" msgstr "Система" #: src/bz-flathub-category.c:308 msgid "Utilities" msgstr "Инструменти" #: src/bz-flathub-page.blp:15 msgid "Flathub Not Added" msgstr "Flathub не беше добавен" #: src/bz-flathub-page.blp:16 msgid "The Flathub remote was not found on any of your flatpak installations" msgstr "Отдалеченото Flathub хранилище не беше намерено в нито една от вашите инсталации на flatpak" #: src/bz-flathub-page.blp:70 src/bz-flathub-page.c:185 msgid "Trending" msgstr "Популярни" #: src/bz-flathub-page.blp:101 msgid "More Trending" msgstr "Още набиращи популярност" #: src/bz-flathub-page.blp:117 msgid "Categories" msgstr "Категории" #: src/bz-flathub-page.blp:154 src/bz-flathub-page.c:195 msgid "Recently Updated" msgstr "Наскоро обновени" #: src/bz-flathub-page.blp:185 msgid "More Updated" msgstr "Още обновени" #: src/bz-flathub-page.blp:206 src/bz-flathub-page.c:205 msgid "Recently Added" msgstr "Наскоро добавени" #: src/bz-flathub-page.blp:237 msgid "More Added" msgstr "Още добавени" #: src/bz-flathub-page.blp:258 src/bz-flathub-page.c:215 msgid "Popular" msgstr "Популярни" #: src/bz-flathub-page.blp:289 msgid "More Popular" msgstr "Още популярни" #: src/bz-flatpak-entry.c:507 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub страницата" #: src/bz-flatpak-entry.c:526 msgctxt "Project URL Type" msgid "Homepage" msgstr "Начална страница" #: src/bz-flatpak-entry.c:529 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Система за проблеми" #: src/bz-flatpak-entry.c:532 msgctxt "Project URL Type" msgid "FAQ" msgstr "ЧЗВ" #: src/bz-flatpak-entry.c:535 msgctxt "Project URL Type" msgid "Help" msgstr "Помощ" #: src/bz-flatpak-entry.c:538 msgctxt "Project URL Type" msgid "Donate" msgstr "Дарете" #: src/bz-flatpak-entry.c:543 msgctxt "Project URL Type" msgid "Translate" msgstr "Превод" #: src/bz-flatpak-entry.c:546 msgctxt "Project URL Type" msgid "Contact" msgstr "Контакти" #: src/bz-flatpak-entry.c:549 msgctxt "Project URL Type" msgid "Source Code" msgstr "Изходен код" #: src/bz-flatpak-entry.c:554 msgctxt "Project URL Type" msgid "Contribute" msgstr "Допринесете" #: src/bz-full-view.blp:14 msgid "No Results" msgstr "Няма резултати" #: src/bz-full-view.blp:15 msgid "Try a different search query" msgstr "Oпитайте различно търсене" #: src/bz-full-view.blp:21 src/bz-window.blp:161 msgid "Content" msgstr "Съдържание" #: src/bz-full-view.blp:129 msgid "This flatpak is verified by the original developers of the software." msgstr "Този flatpak е проверен от оригиналните разработчици на софтуера." #: src/bz-full-view.blp:156 msgid "Support" msgstr "Подкрепи" #: src/bz-full-view.blp:176 msgid "Repository Star Count" msgstr "Брой звезди на хранилището" #: src/bz-full-view.blp:207 msgid "Run Application" msgstr "Изпълняване на програмата" #: src/bz-full-view.blp:221 msgid "Download & Install Application" msgstr "Изтегляне и инсталиране на програмата" #: src/bz-full-view.blp:224 src/bz-transaction-view.blp:108 src/bz-window.c:1071 msgid "Install" msgstr "Инсталиране" #: src/bz-full-view.blp:236 msgid "Uninstall Application" msgstr "Деинсталиране на програмата" #: src/bz-full-view.blp:251 src/bz-installed-page.blp:125 msgid "Manage Add-ons" msgstr "Управление на добавки" #: src/bz-full-view.blp:264 msgid "Install Other Version" msgstr "Инсталиране на друга версия" #: src/bz-full-view.blp:279 msgid "Share this application" msgstr "Споделете тази програма" #: src/bz-full-view.blp:362 msgid "Excludes shared components" msgstr "Изключва споделени компоненти" #: src/bz-full-view.blp:418 msgid "Free Software" msgstr "Свободен софтуер" #: src/bz-full-view.blp:460 msgid "Proprietary" msgstr "Собственически" #: src/bz-full-view.blp:471 msgid "Source code may not be available" msgstr "Изходният код може да не е наличен" #: src/bz-full-view.blp:526 msgid "Click for details" msgstr "Натиснете за подробности" #: src/bz-full-view.blp:592 msgid "Repositories" msgstr "Хранилища" #: src/bz-full-view.blp:623 src/bz-full-view.blp:631 msgid "Project Website" msgstr "Уеб сайт на проекта" #: src/bz-full-view.blp:639 msgid "Open in browser" msgstr "Отваряне в Интернет браузър" #: src/bz-full-view.c:213 #, c-format msgid "%'d Monthly Downloads" msgstr "%'d месечни изтегляния" #: src/bz-full-view.c:215 msgid "--- Downloads" msgstr "--- изтегляния" #: src/bz-full-view.c:241 msgid "Unknown" msgstr "Неизвестно" #. Translators: This is a date format for timestamps from previous years. Used in the app releases section. #. * %B is the full month name, %e is the day, %Y is the year. #. * Example: "October 1, 2025" #. * See https://docs.gtk.org/glib/method.DateTime.format.html for format options #. * Please modify to make it sound natural in your locale. #. * #: src/bz-full-view.c:268 msgid "%B %-d, %Y" msgstr "%-d %B, %Y" #. Translators: This is a date format for timestamps from the current year. Used in the app releases section. #. * %B is the full month name, %e is the day. #. * Example: "October 1" #. * See https://docs.gtk.org/glib/method.DateTime.format.html for format options #. * Please modify to make it sound natural in your locale. #. * #: src/bz-full-view.c:276 msgid "%B %-d" msgstr "%-d %B" #: src/bz-full-view.c:287 msgid "No URL" msgstr "Няма адрес" #: src/bz-full-view.c:305 msgid "This application has a FLOSS license, meaning the source code can be audited for safety." msgstr "Това приложение има FLOSS лиценз, което означава, че изходният код може да бъде проверен за сигурност." #: src/bz-full-view.c:306 msgid "" "This application has a proprietary license, meaning the source code is developed privately and cannot be audited by an independent third party." msgstr "" "Тази програма има собственически лиценз, което означава, че изходният код е разработен частно и не може да бъде проверен от независими трети " "лица." #: src/bz-full-view.c:596 #, c-format msgid "Version %s" msgstr "Версия %s" #: src/bz-full-view.c:621 msgid "No details for this release" msgstr "Няма подробности за това издание" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Базар инспектор" #: src/bz-inspector.blp:22 msgid "Active Blocklists" msgstr "Активни списъци за блокиране" #: src/bz-inspector.blp:44 msgid "Active Curated-Configs" msgstr "" #: src/bz-inspector.blp:66 msgid "All Entry Groups" msgstr "Всички групи за запис" #: src/bz-inspector.blp:69 msgid "Filter..." msgstr "Филтриране…" #: src/bz-inspector.blp:110 msgid "Decache and Inspect" msgstr "Декаширане и изследване" #: src/bz-installed-page.blp:15 msgid "No Flatpaks Installed" msgstr "Няма инсталирани Flatpak програми" #: src/bz-installed-page.blp:21 src/bz-window.blp:302 src/bz-window.blp:395 msgid "Installed" msgstr "Инсталирани" #: src/bz-installed-page.blp:101 msgid "Support this application" msgstr "Подкрепете тази програма" #: src/bz-installed-page.blp:151 src/bz-window.c:1093 msgid "Remove" msgstr "Премахване" #: src/bz-installed-page.blp:178 msgid "More actions" msgstr "Допълнителни действия" #: src/bz-installed-page.blp:197 msgid "Run this application" msgstr "Изпълняване на тази програма" #: src/bz-installed-page.blp:209 msgid "Run" msgstr "Изпълняване" #: src/bz-installed-page.blp:221 src/bz-installed-page.blp:232 msgid "View Store Page" msgstr "Вижте страницата в магазина" #: src/bz-installed-page.c:649 msgid "Choose an Installation" msgstr "Изберете инсталация" #: src/bz-installed-page.c:652 msgid "You have multiple versions of this app installed. Which one would you like to proceed with? " msgstr "Имате инсталирани няколко версии на тази програма. Коя от тях искате да използвате? " #: src/bz-installed-page.c:656 src/bz-window.c:1070 src/bz-window.c:1092 msgid "Cancel" msgstr "Отказване" #: src/bz-preferences-dialog.blp:9 msgid "Preferences" msgstr "Настройки" #: src/bz-preferences-dialog.blp:13 msgid "Application Details" msgstr "Подробности за програмата" #: src/bz-preferences-dialog.blp:16 msgid "Git Forge Star Counts" msgstr "Брой звезди в Git Forge" #: src/bz-preferences-dialog.blp:17 msgid "Not having a GitHub access token may trigger rate limits" msgstr "Липсата на токен за достъп до GitHub може да доведе до ограничения на скоростта" #: src/bz-preferences-dialog.blp:22 src/bz-window.blp:43 src/bz-window.blp:58 src/bz-window.blp:334 msgid "Search" msgstr "Търсене" #: src/bz-preferences-dialog.blp:26 msgid "Hide proprietary applications from search results" msgstr "Скриване на собственическите програми от резултатите от търсенето" #: src/bz-preferences-dialog.blp:30 msgid "Show Only Flathub Apps" msgstr "Показване само на Flathub програми" #: src/bz-preferences-dialog.blp:31 msgid "Limit search results to applications available on Flathub" msgstr "Ограничаване на резултатите от търсенето до програмите, налични в Flathub" #: src/bz-preferences-dialog.blp:35 msgid "Debounce Search Results" msgstr "Забавяне на резултатите за търсене" #: src/bz-preferences-dialog.blp:36 msgid "Wait for a brief pause to reduce system load" msgstr "Изчакване за кратко, за да се намали натоварването на системата" #: src/bz-preferences-dialog.blp:41 msgid "Global Progress Bar" msgstr "Глобална лента за напредъка" #: src/bz-preferences-dialog.blp:44 msgid "Theme" msgstr "Тема" #: src/bz-preferences-dialog.blp:45 msgid "Choose a fun theme for the global progress bar!" msgstr "Изберете забавна тема за глобалната лента за напредъка!" #: src/bz-preferences-dialog.blp:48 msgid "Accent Color" msgstr "Акцентиращ цвят" #: src/bz-preferences-dialog.blp:49 msgid "Pride Rainbow Flag" msgstr "Прайд ЛГБТ флаг" #: src/bz-preferences-dialog.blp:50 msgid "Lesbian Pride Flag" msgstr "" #: src/bz-preferences-dialog.blp:51 msgid "Transgender Flag" msgstr "" #: src/bz-preferences-dialog.blp:52 msgid "Nonbinary Flag" msgstr "" #: src/bz-preferences-dialog.blp:53 msgid "Bisexual Flag" msgstr "" #: src/bz-preferences-dialog.blp:54 msgid "Asexual Flag" msgstr "" #: src/bz-preferences-dialog.blp:55 msgid "Pansexual Flag" msgstr "" #: src/bz-preferences-dialog.blp:56 msgid "Aromantic Flag" msgstr "" #: src/bz-preferences-dialog.blp:57 msgid "Genderfluid Flag" msgstr "" #: src/bz-preferences-dialog.blp:58 msgid "Polysexual Flag" msgstr "" #: src/bz-preferences-dialog.blp:59 msgid "Omnisexual Flag" msgstr "" #: src/bz-search-widget.blp:69 msgid "Search Apps" msgstr "Търсете програми" #: src/bz-share-dialog.blp:13 msgid "Share" msgstr "Споделяне" #: src/bz-share-dialog.c:62 msgid "Copied!" msgstr "Копирано!" #: src/bz-share-dialog.c:106 msgid "Copy Link" msgstr "Копиране на връзката" #: src/bz-share-dialog.c:117 msgid "Open Link" msgstr "Отваряне на връзката" #: src/bz-stats-dialog.blp:26 msgid "Timeline" msgstr "Хронология" #: src/bz-stats-dialog.blp:31 msgid "Installs:" msgstr "Инсталации:" #: src/bz-stats-dialog.blp:37 msgid "World" msgstr "Глобално" #: src/bz-transaction-manager.c:1140 #, c-format msgid "Finished in %.02f seconds" msgstr "Завърши за %.02f секунди" #: src/bz-transaction-view.blp:95 msgid "Install Size" msgstr "Размер за инсталирани" #: src/bz-transaction-view.blp:238 msgid "Error Details" msgstr "Подробности за грешката" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Прехвърлени са %s до момента" #: src/bz-transaction.c:336 msgid "Pending" msgstr "В опашката" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Инсталиране сега" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Налични са обновления" #: src/bz-update-dialog.blp:11 msgid "The following applications are eligible for updates. Would you like to install them?" msgstr "Следните програми имат обновления. Искате ли да ги инсталирате?" #: src/bz-update-dialog.c:134 #, c-format msgid "%d runtimes and/or addons are eligible for updates. Would you like to install them?" msgstr "%d среди за изпълнение и/или добавки имат обновления. Искате ли да ги инсталирате?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Освен това, %d среди за изпълнение и/или добавки ще бъдат обновени." #: src/bz-window.blp:80 msgid "Transactions" msgstr "Операции" #: src/bz-window.blp:95 src/bz-window.blp:414 msgid "Toggle transaction sidebar" msgstr "Превключване на страничната лента за операции" #: src/bz-window.blp:131 msgid "Stop Active Tasks" msgstr "Спиране на работещите задачи" #: src/bz-window.blp:139 msgid "Clear History" msgstr "Изчистване на историята" #: src/bz-window.blp:155 msgid "No Tasks Yet" msgstr "Все още няма задачи" #: src/bz-window.blp:210 src/bz-window.blp:214 msgid "Offline" msgstr "Няма връзка" #: src/bz-window.blp:220 msgid "Loading" msgstr "Зареждане" #: src/bz-window.blp:268 msgid "Browse" msgstr "Разглеждане" #: src/bz-window.blp:278 msgid "App View" msgstr "Изглед на програмата" #: src/bz-window.blp:292 src/bz-window.blp:388 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:322 msgid "Go Back" msgstr "Назад" #: src/bz-window.blp:347 msgid "Update" msgstr "Обновяване" #: src/bz-window.blp:377 msgid "View curated applications" msgstr "Вижте подбрани програми" #: src/bz-window.blp:381 msgid "Curated" msgstr "Подбрани" #: src/bz-window.blp:385 msgid "View the latest on Flathub" msgstr "Вижте най-новите програми във Flathub" #: src/bz-window.blp:392 msgid "View installed applications" msgstr "Вижте инсталираните програми" #: src/bz-window.blp:437 msgid "Main Menu" msgstr "Основно меню" #: src/bz-window.blp:471 msgid "_Quit Service" msgstr "_Спиране на услугата" #: src/bz-window.blp:476 msgid "_Refresh Content" msgstr "_Опресняване на съдържанието" #: src/bz-window.blp:481 msgid "_Preferences" msgstr "_Настройки" #: src/bz-window.blp:486 msgid "_Keyboard Shortcuts" msgstr "_Клавишни комбинации" #: src/bz-window.blp:491 msgid "_About Bazaar" msgstr "_Относно Базар" #: src/bz-window.blp:496 msgid "_Donate to Bazaar ❤️" msgstr "_Дарете за Базар ❤️" #: src/bz-window.c:628 msgid "Up to date!" msgstr "Всичко е обновено!" #: src/bz-window.c:800 msgid "" "The ability to inspect and install local .flatpak bundle files is coming soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Функцията за проверяване и инсталиране на локални .flatpak пакетни файлове ще бъде достъпна скоро! Междувременно, опитайте да изпълните\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "в командния ред." #: src/bz-window.c:935 msgid "Can't do that right now!" msgstr "Това действие не може да се извърши сега!" #: src/bz-window.c:1064 #, c-format msgid "Install %s?" msgstr "Инсталиране на %s?" #: src/bz-window.c:1067 msgid "May install additional shared components" msgstr "Може да инсталира допълнителни споделени компоненти" #: src/bz-window.c:1086 #, c-format msgid "Remove %s?" msgstr "Премахване на %s?" #: src/bz-window.c:1089 msgid "Settings & user data will be kept" msgstr "Настройките и потребителските данни ще бъдат запазени" #: src/bz-window.c:1257 msgid "Resume Current Tasks" msgstr "Възобновяване на текущите задачи" #: src/bz-window.c:1263 msgid "Pause Current Tasks" msgstr "Пауза на текущите задачи" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u изтегляния" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Общи" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Отваряне на търсачката" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Refresh" msgstr "Опресняване" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Превключване на мениджъра на операциите" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Показване на клавишните комбинации" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Quit" msgstr "Спиране на програмата" #~ msgid "Show Animated Background" #~ msgstr "Animierten Hintergrund anzeigen" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Den animierten Hintergrund auf der Startseite anzeigen" #~ msgid "It emphasizes supporting the developers who make the Linux desktop possible." #~ msgstr "Es legt Wert darauf, die Entwickler zu unterstützen, die den Linux-Desktop möglich machen." #~ msgid "Calligraphy application page" #~ msgstr "Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "Downloadkurve für Blender" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "%'d Einträge von %'d empfangen (%0.1f Sekunden vergangen)" #~ msgid "Apps Of The Week" #~ msgstr "Anwendungen der Woche" #~ msgid "Show More" #~ msgstr "Mehr anzeigen" #~ msgid "The number of downloads in the last 30 days. Click to view this application's download statistics." #~ msgstr "Die Anzahl der Downloads in den letzten 30 Tagen. Klicken Sie hier, um die Download-Statistiken für diese Anwendung anzuzeigen." #~ msgid "Support this developer" #~ msgstr "Diesen Entwickler unterstützen" #~ msgid "Remote repo name" #~ msgstr "Namen des Repository" #, c-format #~ msgid "Released %x" #~ msgstr "Veröffentlicht %x" #~ msgid "Edit Permissions" #~ msgstr "Berechtigungen bearbeiten" #~ msgid "How the application looks" #~ msgstr "Wie die Anwendung aussieht" #~ msgid "Appearance" #~ msgstr "Erscheinungsbild" #~ msgid "Show animated background" #~ msgstr "Animierten Hintergrund anzeigen" #~ msgid "Type to filter" #~ msgstr "Zum Filtern hier tippen" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Ergebnisse mit proprietären Lizenzen ausschließen" #~ msgid "Exclude results not originating from Flathub" #~ msgstr "Ergebnisse ausschließen, die nicht von Flathub stammen" #~ msgid "Advanced" #~ msgstr "Erweitert" #~ msgid "Open this link externally" #~ msgstr "Diesen Link extern öffnen" #~ msgid "Downloads Over Time" #~ msgstr "Downloads im Laufe der Zeit" #~ msgid "Minimize Lower Bound" #~ msgstr "Untere Grenze verringern" #~ msgid "Maximize Upper Bound" #~ msgstr "Obere Grenze vergrößern" #~ msgid "Installing" #~ msgstr "Wird installiert" #~ msgid "Updating" #~ msgstr "Wird aktualisiert" #~ msgid "Removing" #~ msgstr "Wird entfernt" #~ msgid "Transactions Will Appear Here" #~ msgstr "Transaktionen werden hier erscheinen" #~ msgid "Halt the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen anhalten" #~ msgid "Clear all finished transactions" #~ msgstr "Alle abgeschlossenen Transaktionen leeren" #~ msgid "Confirm Action" #~ msgstr "Aktion bestätigen" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Sie sind dabei, die folgende Anwendung zu entfernen:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sind Sie sich sicher?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Sie sind dabei, die folgende Anwendung zu installieren:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sind Sie sich sicher?" #~ msgid "Resume the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen fortsetzen" #~ msgid "Pause the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen pausieren" #~ msgid "No description" #~ msgstr "Keine Beschreibung" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Bazaar-Hauptfenster zeigt Blender" #~ msgid "Match using regular expressions" #~ msgstr "Übereinstimmung mit regulären Ausdrücken" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "Filterung und Sortierung hinter einem Überblendungseffekt verstecken" kolunmi-bazaar-7b9c8e1/po/bs.po000066400000000000000000000347111514314607700164520ustar00rootroot00000000000000# Bosnian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Manually modified from a previous translation, 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-09-02 08:40+0200\n" "PO-Revision-Date: 2025-09-02 09:06+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: bs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Poedit 3.6\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Dodajte, uklonite ili ažurirajte flatpak softver na ovom računaru" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistem;UpraviteljPaketa;Otkrijte;Flatpak;Softver;Prodavnica;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Animated Background" msgstr "Prikaži animiranu pozadinu" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Whether to show the animated icon background on the home page" msgstr "Da li već prikazati animiranu pozadinu ikone na početnoj stranici" #. FIXME: add descriptions and summary #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:9 msgid "Keep the summary shorter, between 10 and 35 characters" msgstr "Sažetak neka bude kraći, između 10 i 35 znakova" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:11 msgid "No description" msgstr "Nema opisa" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:15 src/bz-application.c:1215 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:41 msgid "Main Bazaar window showing Blender" msgstr "Glavni prozor Bazaara koji prikazuje Blender" #: src/bz-addons-dialog.blp:13 src/bz-installed-page.blp:162 #: src/bz-installed-page.blp:174 msgid "Manage Addons" msgstr "Upravljanje dodacima" #: src/bz-app-tile.blp:65 src/bz-full-view.blp:139 msgid "This flatpak is verified by the original developers of the software." msgstr "Ovaj flatpak je verifikovan od strane originalnih programera softvera." #: src/bz-application.c:1186 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "SecularSteve" #: src/bz-application.c:1191 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "Ahmed Najmawi" #: src/bz-application.c:1192 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:1193 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore" msgstr "Jill Fiore" #: src/bz-application.c:1194 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:1195 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:1196 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:1197 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:1198 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:1199 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-browse-widget.blp:11 src/bz-full-view.blp:11 #: src/bz-installed-page.blp:11 src/bz-window.blp:32 msgid "Empty" msgstr "Prazno" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "Nema izloženih aplikacija" #: src/bz-browse-widget.blp:16 msgid "Bazaar was not provided a curated content configuration. Contact your operating system's support channels for assistance." msgstr "Bazaaru nije pružena konfiguracija izloženog sadržaja. Za pomoć kontaktirajte kanale podrške vašeg operativnog sistema." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:11 msgid "Browser" msgstr "Pretraživač" #: src/bz-error.c:45 msgid "An Error Occurred" msgstr "Došlo je do greške" #: src/bz-error.c:51 msgid "Close" msgstr "Zatvori" #: src/bz-error.c:52 msgid "Copy and Close" msgstr "Kopiraj i zatvori" #: src/bz-flathub-page.blp:41 msgid "Apps Of The Week" msgstr "Aplikacije sedmice" #: src/bz-flathub-page.blp:85 msgid "Trending" msgstr "U trendu" #: src/bz-flathub-page.blp:117 msgid "Recently Updated" msgstr "Zadnje ažurirano" #: src/bz-flathub-page.blp:149 msgid "Recently Added" msgstr "Zadnje dodano" #: src/bz-flathub-page.blp:181 msgid "Popular" msgstr "Popularno" #: src/bz-full-view.blp:15 msgid "No Results" msgstr "Nema rezultata" #: src/bz-full-view.blp:16 msgid "Try a different search query" msgstr "Pokušajte s drugim upitom za pretragu" #: src/bz-full-view.blp:22 src/bz-window.blp:42 msgid "Content" msgstr "Sadržaj" #: src/bz-full-view.blp:180 msgid "Run this application" msgstr "Pokreni ovu aplikaciju" #: src/bz-full-view.blp:204 msgid "Download and install this application" msgstr "Preuzmite i instalirajte ovu aplikaciju" #: src/bz-full-view.blp:222 src/bz-window.c:987 msgid "Install" msgstr "Instaliraj" #: src/bz-full-view.blp:236 msgid "Uninstall this application" msgstr "Deinstalirajte ovu aplikaciju" #: src/bz-full-view.blp:262 msgid "Share this application" msgstr "Podijelite ovu aplikaciju" #: src/bz-full-view.blp:274 msgid "The number of downloads in the last 30 days. Click to view this application's download statistics." msgstr "Broj preuzimanja u posljednjih 30 dana. Kliknite za pregled statistike preuzimanja ove aplikacije." #: src/bz-full-view.blp:316 msgid "Support this developer" msgstr "Podržite ovog programera" #: src/bz-full-view.blp:329 msgid "Support" msgstr "Podrška" #: src/bz-full-view.blp:387 msgid "Remote repo name" msgstr "Naziv udaljenog repozitorija" #: src/bz-full-view.blp:400 msgid "Project URL" msgstr "URL projekta" #: src/bz-full-view.blp:412 msgid "Download size" msgstr "Veličina preuzimanja" #: src/bz-full-view.c:214 #, c-format msgid "Released %x" msgstr "Objavljeno %x" #: src/bz-full-view.c:225 msgid "No URL" msgstr "Nema URL-a" #: src/bz-full-view.c:233 msgid "This application has a FLOSS license, meaning the source code can be audited for safety." msgstr "Ova aplikacija ima FLOSS licencu, što znači da se izvorni kod može revidirati radi sigurnosti." #: src/bz-full-view.c:234 msgid "This application has a proprietary license, meaning the source code is developed privately and cannot be audited by an independent third party." msgstr "Ova aplikacija ima vlasničku licencu, što znači da je izvorni kod razvijen privatno i ne može ga revidirati nezavisna treća strana." #: src/bz-installed-page.blp:15 msgid "No Flatpaks Installed" msgstr "Nema instaliranih Flatpak uređaja" #: src/bz-installed-page.blp:21 src/bz-window.blp:201 src/bz-window.blp:336 msgid "Installed" msgstr "Instalirano" #: src/bz-installed-page.blp:143 msgid "More actions" msgstr "Više akcija" #: src/bz-installed-page.blp:187 src/bz-installed-page.blp:198 msgid "Edit Permissions" msgstr "Uredi dozvole" #: src/bz-preferences-dialog.blp:9 msgid "Preferences" msgstr "Postavke" #: src/bz-preferences-dialog.blp:13 msgid "How the application looks" msgstr "Kako izgleda aplikacija" #: src/bz-preferences-dialog.blp:14 msgid "Appearance" msgstr "Izgled" #: src/bz-preferences-dialog.blp:17 msgid "Show animated background" msgstr "Prikaži animiranu pozadinu" #: src/bz-search-widget.blp:69 msgid "Type to filter" msgstr "Upišite tekst za filtriranje" #: src/bz-search-widget.blp:98 src/bz-search-widget.blp:115 msgid "Search Options" msgstr "Opcije pretrage" #: src/bz-search-widget.blp:119 msgid "Exclude results with proprietary licenses" msgstr "Isključi rezultate s vlasničkim licencama" #: src/bz-search-widget.blp:124 msgid "Exclude results not originating from Flathub" msgstr "Isključi rezultate koji ne potiču sa Flathub-a" #: src/bz-search-widget.blp:139 msgid "Advanced" msgstr "Napredno" #: src/bz-search-widget.blp:143 msgid "Match using regular expressions" msgstr "Uparivanje pomoću običnih izraza" #: src/bz-search-widget.blp:148 msgid "Hide filtering and sorting behind a crossfade effect" msgstr "Sakrij filtriranje i sortiranje iza efekta prelaza" #: src/bz-search-widget.blp:153 msgid "Debounce input to prevent instant replies" msgstr "Otodskočite unos kako bi se spriječili brzi odgovori" #: src/bz-share-dialog.blp:13 msgid "Share" msgstr "Podijeli" #: src/bz-share-dialog.blp:64 msgid "Copy this link" msgstr "Kopiraj ovu vezu" #: src/bz-share-dialog.blp:71 msgid "Open this link externally" msgstr "Otvorite ovu vezu eksterno" #: src/bz-stats-dialog.blp:15 msgid "Downloads Over Time" msgstr "Preuzimanja tokom vremena" #: src/bz-stats-dialog.blp:31 msgid "Minimize Lower Bound" msgstr "Minimiziraj donju granicu" #: src/bz-stats-dialog.blp:36 msgid "Maximize Upper Bound" msgstr "Maksimiziraj gornju granicu" #: src/bz-transaction-manager.c:451 #, c-format msgid "Finished in %.02f seconds" msgstr "Završeno za %.02f sekundi" #: src/bz-transaction-view.blp:34 msgid "Installing" msgstr "Instaliranje" #: src/bz-transaction-view.blp:63 msgid "Updating" msgstr "Ažuriranje" #: src/bz-transaction-view.blp:92 msgid "Removing" msgstr "Uklanjanje" #: src/bz-transaction.c:268 msgid "Pending" msgstr "Na čekanju" #: src/bz-update-dialog.blp:6 msgid "Later" msgstr "Kasnije" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Instaliraj odmah" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Dostupna su ažuriranja" #: src/bz-update-dialog.blp:11 msgid "The following applications are eligible for updates. Would you like to install them?" msgstr "Sljedeće aplikacije ispunjavaju uslove za ažuriranja. Želite li ih instalirati?" #: src/bz-update-dialog.c:135 #, c-format msgid "%d runtimes and/or addons are eligible for updates. Would you like to install them?" msgstr "%d okruženja za izvršavanje i/ili dodaci ispunjavaju uslove za ažuriranja. Želite li ih instalirati?" #: src/bz-update-dialog.c:143 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Pored toga, ažurirat će se i sljedeći broj runtime okruženja i/ili dodataka: %d." #: src/bz-window.blp:36 msgid "Transactions Will Appear Here" msgstr "Transakcije će se pojaviti ovdje" #: src/bz-window.blp:97 msgid "Halt the execution of transactions" msgstr "Zaustaviti izvršenje transakcija" #: src/bz-window.blp:105 msgid "Clear all finished transactions" msgstr "Obriši sve završene transakcije" #: src/bz-window.blp:136 src/bz-window.blp:140 msgid "Offline" msgstr "Bez mreže" #: src/bz-window.blp:146 msgid "Loading" msgstr "Učitavanje" #: src/bz-window.blp:170 msgid "Browse" msgstr "Pregledaj" #: src/bz-window.blp:180 msgid "App View" msgstr "Prikaz aplikacije" #: src/bz-window.blp:191 src/bz-window.blp:315 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:220 msgid "Go Back" msgstr "Idi nazad" #: src/bz-window.blp:228 msgid "Refresh" msgstr "Osvježi" #: src/bz-window.blp:237 msgid "Search" msgstr "Pretraži" #: src/bz-window.blp:249 msgid "Update" msgstr "Ažuriraj" #: src/bz-window.blp:263 msgid "Checking for updates" msgstr "Provjera ažuriranja" #: src/bz-window.blp:279 msgid "View curated applications" msgstr "Pogledajte izložene aplikacije" #: src/bz-window.blp:294 msgid "Curated" msgstr "Izloženo" #: src/bz-window.blp:300 msgid "View the latest on Flathub" msgstr "Pogledajte najnovije na Flathub-u" #: src/bz-window.blp:321 msgid "View installed applications" msgstr "Pogledajte instalirane aplikacije" #: src/bz-window.blp:350 msgid "Main Menu" msgstr "Glavni meni" #: src/bz-window.blp:361 msgid "Toggle transaction sidebar" msgstr "Uključi/isključi bočnu traku transakcija" #: src/bz-window.blp:400 msgid "Up to date!" msgstr "Ažurno!" #: src/bz-window.blp:425 msgid "_Keyboard Shortcuts" msgstr "_Prečice na tastaturi" #: src/bz-window.blp:430 msgid "_About Bazaar" msgstr "_O Bazaar-u" #: src/bz-window.blp:435 msgid "_Donate to Bazaar ❤️" msgstr "_Donirajte Bazaaru ❤️" #: src/bz-window.c:856 msgid "" "The ability to inspect and install local .flatpak bundle files is coming soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Mogućnost pregleda i instaliranja lokalnih .flatpak datoteka paketa uskoro stiže! U međuvremenu, pokušajte pokrenuti\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "u komandnom redu." #: src/bz-window.c:927 msgid "Can't do that right now!" msgstr "To se sada ne može uraditi!" #: src/bz-window.c:940 msgid "Confirm Action" msgstr "Potvrdi radnju" #: src/bz-window.c:958 #, c-format msgid "" "You are about to remove the following Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Are you sure?" msgstr "" "Namjeravate ukloniti sljedeći Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Jeste li sigurni?" #: src/bz-window.c:966 src/bz-window.c:986 msgid "Cancel" msgstr "Otkaži" #: src/bz-window.c:967 msgid "Remove" msgstr "Ukloni" #: src/bz-window.c:978 #, c-format msgid "" "You are about to install the following Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Are you sure?" msgstr "" "Instalirat ćete sljedeći Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Jeste li sigurni?" #: src/bz-window.c:1012 msgid "More details" msgstr "Više detalja" #: src/bz-window.c:1138 msgid "Resume the execution of transactions" msgstr "Nastavite izvršavanje transakcija" #: src/bz-window.c:1144 msgid "Pause the execution of transactions" msgstr "Pauzirajte izvršavanje transakcija" #: src/gtk/help-overlay.blp:11 msgctxt "shortcut window" msgid "General" msgstr "Općenito" #: src/gtk/help-overlay.blp:14 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Otvori dijalog za pretragu" #: src/gtk/help-overlay.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Osvježi" #: src/gtk/help-overlay.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Uključi/isključi Upravitelja za transakcije" #: src/gtk/help-overlay.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Prikaži prečice" #: src/gtk/help-overlay.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Odustani" kolunmi-bazaar-7b9c8e1/po/cs.po000066400000000000000000001730521514314607700164550ustar00rootroot00000000000000# Czech translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-09-06 13:08+0200\n" "PO-Revision-Date: 2025-12-21 07:27+0100\n" "Last-Translator: Vlastimil Dědek \n" "Language-Team: Czech\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:234 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Přidejte, odstraňte nebo aktualizujte flatpaky na tomto počítači." #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Systém;SprávceBalíčků;Discover;Flatpak;Software;Obchod;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Skrýt Zastaralé Položky" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Skrýt zastaralé položky a aplikace na nich závislé" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Only Show Free Software" msgstr "Zobrazit pouze svobodný software" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 #, fuzzy msgid "Hide proprietary software" msgstr "Skrýt propertiární software" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "Zobrazit pouze obsah z Flathubu" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 #, fuzzy msgid "Hide applications which do not originate from Flathub" msgstr "Skrýt aplikace mimo Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "Debouncing Vstupů Vyhledávání" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 #, fuzzy msgid "Add a delay before searching to prevent instant replies while typing" msgstr "Omezit frekvenci reakce" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "Global Progress Bar Theme" msgstr "Téma Globálního Ukazatele Postupu" #: data/io.github.kolunmi.Bazaar.gschema.xml:47 msgid "Describes the look of the global progress bar" msgstr "Popisuje vzhled globáního ukazatele postupu" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "Saved Window Dimensions" msgstr "Uložené rozměry okna" #: data/io.github.kolunmi.Bazaar.gschema.xml:52 msgid "The window dimensions to be used by the next Bazaar window" msgstr "Rozměry okna použitá dalšími okny Bazaaru" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Objevit a nainstalovat aplikace" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 #, fuzzy msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Nový obchod s aplikacemi pro GNOME se zaměřením na objevování a instalování " "aplikací a doplňků z Flatpak remotů, hlavně Flathubu" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 #, fuzzy msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Zdůrazňuje podporu vývojářů, kteří umožňují existenci Linuxu na počítačích. " "Bazaar má kartu \"vybrané\" která může být nastavena distribucemi pro více " "přizpůsobený zážitek" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:683 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 #, fuzzy msgid "The home page displaying Flathub apps" msgstr "Domovské zobrazení ukazující Flathub aplikace a kategorie" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Stránka aplikace Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 #, fuzzy msgid "Search page" msgstr "Vyhledat Aplikace" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 #, fuzzy msgid "Category page" msgstr "Kategorie" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:686 #: src/bz-installed-tile.blp:99 #, fuzzy msgid "Manage Add-ons" msgstr "Správce doplňků" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:477 #: src/bz-installed-tile.blp:117 src/bz-transaction-view.blp:213 #: src/bz-window.c:1314 msgid "Remove" msgstr "Odstranit" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:166 #: src/bz-full-view.blp:249 src/bz-full-view.blp:464 #: src/bz-transaction-view.blp:187 src/bz-window.c:1291 msgid "Install" msgstr "Instalovat" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:50 #: src/bz-full-view.c:374 src/bz-full-view.c:381 msgid "Age Rating" msgstr "Věkové hodnocení" #: src/bz-age-rating-dialog.blp:40 src/bz-age-rating-dialog.c:790 msgid "?" msgstr "?" #: src/bz-age-rating-dialog.c:139 msgid "Cartoon Violence" msgstr "Cartoon Violence" #: src/bz-age-rating-dialog.c:140 msgid "No information regarding cartoon violence" msgstr "Žádná informace o cartoon violence" #: src/bz-age-rating-dialog.c:143 msgid "Fantasy Violence" msgstr "Fantasy Violence" #: src/bz-age-rating-dialog.c:144 msgid "No information regarding fantasy violence" msgstr "Žádná informace o fantasy violence" #: src/bz-age-rating-dialog.c:147 msgid "Realistic Violence" msgstr "Realistické násilí" #: src/bz-age-rating-dialog.c:148 msgid "No information regarding realistic violence" msgstr "Žádná informace o realistickém násilí" #: src/bz-age-rating-dialog.c:151 msgid "Violence Depicting Bloodshed" msgstr "Násilí zobrazující zabíjení" #: src/bz-age-rating-dialog.c:152 msgid "No information regarding bloodshed" msgstr "Žádná informace o zabíjení" #: src/bz-age-rating-dialog.c:155 msgid "Sexual Violence" msgstr "Sexuální násilí" #: src/bz-age-rating-dialog.c:156 msgid "No information regarding sexual violence" msgstr "Žádná informace o sexuálním násilí" #: src/bz-age-rating-dialog.c:159 msgid "Alcohol" msgstr "Alkohol" #: src/bz-age-rating-dialog.c:160 msgid "No information regarding references to alcohol" msgstr "Žádná informace o odkazech na alkohol" #: src/bz-age-rating-dialog.c:163 msgid "Narcotics" msgstr "Narkotika" #: src/bz-age-rating-dialog.c:164 msgid "No information regarding references to illicit drugs" msgstr "Žádná informace o odkazech na nelegální drogy" #: src/bz-age-rating-dialog.c:167 msgid "Tobacco" msgstr "Tabák" #: src/bz-age-rating-dialog.c:168 msgid "No information regarding references to tobacco products" msgstr "Žádná informace o odkazech na tabák" #: src/bz-age-rating-dialog.c:171 src/bz-age-rating-dialog.c:358 msgid "Nudity" msgstr "Nahota" #: src/bz-age-rating-dialog.c:172 msgid "No information regarding nudity of any sort" msgstr "Žádná informace o nahotě jakéhokoli druhu" #: src/bz-age-rating-dialog.c:175 msgid "Sexual Themes" msgstr "Sexuální Téma" #: src/bz-age-rating-dialog.c:176 msgid "No information regarding references to or depictions of sexual nature" msgstr "Žádná informace o odkazech na obsah sexuálního charakteru" #: src/bz-age-rating-dialog.c:179 msgid "Profanity" msgstr "Profanity" #: src/bz-age-rating-dialog.c:180 msgid "No information regarding profanity of any kind" msgstr "Žádná informace o profanity jakéhokoli druhu" #: src/bz-age-rating-dialog.c:183 msgid "Inappropriate Humor" msgstr "Nepřípustný Humor" #: src/bz-age-rating-dialog.c:184 msgid "No information regarding inappropriate humor" msgstr "Žádné informace o nepřípustném humoru" #: src/bz-age-rating-dialog.c:187 msgid "Discrimination" msgstr "Diskriminace" #: src/bz-age-rating-dialog.c:188 msgid "No information regarding discriminatory language of any kind" msgstr "Žádná informace o diskriminačním jazyku jakéhokoli druhu" #: src/bz-age-rating-dialog.c:191 msgid "Advertising" msgstr "Reklama" #: src/bz-age-rating-dialog.c:192 msgid "No information regarding advertising of any kind" msgstr "Žádná informace o reklamě jakéhokoli druhu" #: src/bz-age-rating-dialog.c:195 msgid "Gambling" msgstr "Gambling" #: src/bz-age-rating-dialog.c:196 msgid "No information regarding gambling of any kind" msgstr "Žádné informace o gamblingu jakéhokoli druhu" #: src/bz-age-rating-dialog.c:199 msgid "Purchasing" msgstr "Nákupy v aplikaci" #: src/bz-age-rating-dialog.c:200 msgid "No information regarding the ability to spend money" msgstr "Žádná informace o možnosti nákupu v aplikaci" #: src/bz-age-rating-dialog.c:203 msgid "Chat Between Users" msgstr "Sociální interakce (textová)" #: src/bz-age-rating-dialog.c:204 msgid "No information regarding ways to chat with other users" msgstr "Žádná informace o možnosti chatování s ostatními uživateli" #: src/bz-age-rating-dialog.c:207 msgid "Audio Chat Between Users" msgstr "Sociální interakce (voice chat)" #: src/bz-age-rating-dialog.c:208 msgid "No information regarding ways to talk with other users" msgstr "Žádná informace o možnosti hovoru s ostatními uživateli" #: src/bz-age-rating-dialog.c:211 #, fuzzy msgid "Contact Details" msgstr "Podrobnosti chyby" #: src/bz-age-rating-dialog.c:212 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Žádná informace o sdílení uživatelských jména nebo " "e-mailových adres" #: src/bz-age-rating-dialog.c:215 msgid "Identifying Information" msgstr "Indentifikační Informace" #: src/bz-age-rating-dialog.c:216 msgid "No information regarding sharing of user information with third parties" msgstr "Žádné informace o sdílení uživatelských informací s třetími stranami" #: src/bz-age-rating-dialog.c:219 msgid "Location Sharing" msgstr "Sdílení Lokace" #: src/bz-age-rating-dialog.c:220 msgid "No information regarding sharing of physical location with other users" msgstr "Žádná informace o sdílení lokace s ostatními uživateli" #: src/bz-age-rating-dialog.c:223 msgid "Prostitution" msgstr "Prostituce" #: src/bz-age-rating-dialog.c:224 msgid "No information regarding references to prostitution" msgstr "Žádné informace o odkazech na prostituci" #: src/bz-age-rating-dialog.c:227 msgid "Adultery" msgstr "Adultery" #: src/bz-age-rating-dialog.c:228 msgid "No information regarding references to adultery" msgstr "No information regarding references to adultery" #: src/bz-age-rating-dialog.c:231 msgid "Sexualized Characters" msgstr "Sexualized Characters" #: src/bz-age-rating-dialog.c:232 msgid "No information regarding sexualized characters" msgstr "No information regarding sexualized characters" #: src/bz-age-rating-dialog.c:235 #, fuzzy msgid "Desecration" msgstr "Desecration" #: src/bz-age-rating-dialog.c:236 msgid "No information regarding references to desecration" msgstr "No information regarding references to desecration" #: src/bz-age-rating-dialog.c:239 msgid "Human Remains" msgstr "Human Remains" #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "No information regarding visible dead human remains" #: src/bz-age-rating-dialog.c:243 msgid "Slavery" msgstr "Slavery" #: src/bz-age-rating-dialog.c:244 msgid "No information regarding references to slavery" msgstr "No information regarding references to slavery" #: src/bz-age-rating-dialog.c:307 msgid "Does not include references to drugs" msgstr "Neobsahuje odkazy na drogy" #: src/bz-age-rating-dialog.c:309 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Does not include swearing, profanity, and other kinds of strong language" #: src/bz-age-rating-dialog.c:311 msgid "Does not include ads or monetary transactions" msgstr "Neobsahuje reklamy nebo jiné finanční transakce" #: src/bz-age-rating-dialog.c:313 msgid "Does not include sex or nudity" msgstr "Neobsahuje sexuální obsah nebo nahotu" #: src/bz-age-rating-dialog.c:315 msgid "Does not include uncontrolled chat functionality" msgstr "Does not include uncontrolled chat functionality" #: src/bz-age-rating-dialog.c:317 msgid "Does not include violence" msgstr "Neobsahuje násilí" #: src/bz-age-rating-dialog.c:352 msgid "Drugs" msgstr "Drogy" #: src/bz-age-rating-dialog.c:354 msgid "Strong Language" msgstr "Strong Language" #: src/bz-age-rating-dialog.c:356 msgid "Money" msgstr "Peníze" #: src/bz-age-rating-dialog.c:360 msgid "Social" msgstr "Sociální" #: src/bz-age-rating-dialog.c:362 #, fuzzy msgid "Violence" msgstr "Násilí" #: src/bz-age-rating-dialog.c:564 #, c-format msgid "%s • %s" msgstr "%s • %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:752 src/bz-full-view.c:364 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:782 msgctxt "Age rating" msgid "All" msgstr "Všichni" #: src/bz-age-rating-dialog.c:846 #, c-format msgid "%s has an unknown age rating" msgstr "%s má neznámé věkové hodnocení" #: src/bz-age-rating-dialog.c:854 #, c-format msgid "%s is suitable for everyone" msgstr "%s je vhodné pro každého" #: src/bz-age-rating-dialog.c:857 #, c-format msgid "%s is suitable for toddlers" msgstr "%s je vhodné pro mládež" #: src/bz-age-rating-dialog.c:860 #, c-format msgid "%s is suitable for young children" msgstr "%s je vhodné pro malé děti" #: src/bz-age-rating-dialog.c:863 #, c-format msgid "%s is suitable for children" msgstr "%s je vhodné pro děti" #: src/bz-age-rating-dialog.c:866 #, c-format msgid "%s is suitable for teenagers" msgstr "%s je vhodné pro teenagery" #: src/bz-age-rating-dialog.c:869 #, c-format msgid "%s is suitable for adults" msgstr "%s je vhodné pro dospělé" #: src/bz-age-rating-dialog.c:872 #, c-format msgid "%s is suitable for %s" msgstr "%s je vhodné pro %s" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Velikost ke stažení" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Velikosti lidské DNA" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 miliardy bazických párů" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "Linuxového jádra" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "Naváděcího počítače Apolla 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "Kompletní ROM a RAM" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "Originálního Super Mario Bros" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "Na NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "Velikosti Wikipedie" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Bez žádných medií" #: src/bz-app-tile.blp:84 src/bz-installed-page.blp:25 src/bz-window.blp:298 msgid "Installed" msgstr "Nainstalované" #: src/bz-apps-page.blp:14 src/bz-full-view.blp:43 src/bz-user-data-page.blp:15 #: src/bz-window.blp:443 msgid "Main Menu" msgstr "Hlavní Menu" #: src/bz-apps-page.blp:17 src/bz-user-data-page.blp:18 src/bz-window.blp:522 msgid "_Donate to Bazaar ❤️" msgstr "_Podpořte Vývoj ❤️" #: src/bz-apps-page.blp:18 src/bz-user-data-page.blp:19 #, fuzzy msgid "_Refresh Content" msgstr "Obnovit" #: src/bz-apps-page.blp:22 src/bz-user-data-page.blp:22 src/bz-window.blp:529 msgid "_Preferences" msgstr "Předvolby" #: src/bz-apps-page.blp:23 src/bz-user-data-page.blp:23 src/bz-window.blp:550 msgid "_Keyboard Shortcuts" msgstr "_Klávesové Zkratky" #: src/bz-apps-page.blp:24 src/bz-user-data-page.blp:24 src/bz-window.blp:555 msgid "_About Bazaar" msgstr "_O Bazaaru" #: src/bz-apps-page.blp:28 src/bz-user-data-page.blp:27 src/bz-window.blp:562 #, fuzzy msgid "_Quit Bazaar" msgstr "_O Bazaaru" #: src/bz-application.c:578 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Tato funkce je aktuálně vypnutá. Doporučujeme stáhnout a nainstalovat " "Flatseal pro správu oprávnění aplikací." #: src/bz-application.c:660 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:661 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:686 msgid "translator-credits" msgstr "Vlastimil Dědek" #: src/bz-application.c:750 msgid "Logged Out Successfully!" msgstr "Uživatel Úspěšně Odhlášen!" #: src/bz-application.c:877 msgid "Performing setup..." msgstr "Provádím nastavení..." #: src/bz-application.c:956 src/bz-application.c:965 #, fuzzy msgid "Set Up Flathub" msgstr "Nastavuji Flathub" #: src/bz-application.c:959 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub není nastaven na tomto systému.Nebudete moct procházet a instalovat " "aplikace v Bazaaru.\n" "\n" "Stále můžete používat Bazaar ke správě nainstalovaných aplikací." #: src/bz-application.c:964 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Později" #: src/bz-application.c:1366 msgid "Synchronizing..." msgstr "Synchronizuji..." #: src/bz-application.c:1505 #, fuzzy, c-format msgid "Receiving %d entries..." msgstr "Získávání položek" #: src/bz-application.c:1510 #, fuzzy msgid "Checking for updates" msgstr "Kontroluji aktualizace" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:65 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:15 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Prázdné" #: src/bz-curated-view.blp:15 #, fuzzy msgid "No Curation" msgstr "Žádné vybrané aplikace" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Na vašem systému nejsou dostupné žádné informace o vybraných aplikacích. " "Stále můžete procházet aplikace na Flathubu." #: src/bz-curated-view.blp:18 #, fuzzy msgid "Browse Flathub" msgstr "Prohlížet Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Offline" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Prohlížeč" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Developer information not available." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Vlastnictví ID aplikace %s není ověřeno a může se jednat o " "komunitní balíček." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Vlastnictví ID aplikace %s bylo manuálně ověřeno týmem Flathubu." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %s app ID has been verified by %s on %s." msgstr "" "Vlastnictví ID aplikace %s bylo ověřeno %s na %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %s app ID has been verified using %s." msgstr "Vlastnictví ID aplikace %s bylo ověřeno pomocí %s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Vlastnictví ID aplikace %s bylo ověřeno." #: src/bz-entry-group-util.c:73 #, fuzzy msgid "Choose an Installation" msgstr "Vyberte Instalaci" #: src/bz-entry-group-util.c:76 #, fuzzy msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Máte více verzí této aplikace nainstalované. " "Se kterou chcete pokračovat?" #: src/bz-entry-group-util.c:80 src/bz-window.c:1290 src/bz-window.c:1313 msgid "Cancel" msgstr "Zrušit" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Otevřít Inspector" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Serialize" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Převést do JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Chyba" #: src/bz-error.c:89 msgid "Close" msgstr "Zavřít" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Zkopírovat a zavřít" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Přihlašte se pomocí Flathubu pro správu oblíbených aplikací" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Přihlásit Se" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Počet Oblíbených" #: src/bz-favorites-tile.c:164 #, fuzzy msgid "Uninstall" msgstr "Instalovat" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Sdílet tuto aplikaci" #: src/bz-favorites-tile.blp:118 msgid "Remove from Favorites" msgstr "Odebrat z Oblíbených" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:75 #: src/bz-window.blp:580 msgid "Favorites" msgstr "Oblíbené" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:420 msgid "Toggle transaction sidebar" msgstr "Zobrazit/skrýt přehled translakcí" #: src/bz-favorites-page.blp:53 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Načítání" #: src/bz-favorites-page.blp:68 msgid "No Favorites" msgstr "Žádné Oblíbené Aplikace" #: src/bz-favorites-page.blp:69 msgid "Applications you mark as favorite will appear here" msgstr "Aplikace, které označíte jako oblíbené se zobrazí zde" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Předchozí" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Další" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Aplikace Dne" #: src/bz-flathub-category.c:78 msgid "Audio & Video" msgstr "Audio & Video" #: src/bz-flathub-category.c:78 msgid "Media" msgstr "Multimédia" #: src/bz-flathub-category.c:78 #, fuzzy msgid "More Audio & Video" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:79 #, fuzzy msgid "Developer Tools" msgstr "Vývojářské Nástroje" #: src/bz-flathub-category.c:79 #, fuzzy msgid "Develop" msgstr "Vývoj" #: src/bz-flathub-category.c:79 msgid "More Developer Tools" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:80 msgid "Education" msgstr "Vzdělávání" #: src/bz-flathub-category.c:80 msgid "Learn" msgstr "Učení" #: src/bz-flathub-category.c:80 #, fuzzy msgid "More Education" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:81 msgid "Gaming" msgstr "Gaming" #: src/bz-flathub-category.c:81 msgid "Play" msgstr "Hrát" #: src/bz-flathub-category.c:81 #, fuzzy msgid "More Gaming" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:82 msgid "Graphics & Photography" msgstr "Grafika & Fotografie" #: src/bz-flathub-category.c:82 msgid "Create" msgstr "Vytvořit" #: src/bz-flathub-category.c:82 msgid "More Graphics & Photography" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:83 msgid "Networking" msgstr "Internet" #: src/bz-flathub-category.c:83 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:83 #, fuzzy msgid "More Networking" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:84 msgid "Productivity" msgstr "Prodiktivita" #: src/bz-flathub-category.c:84 msgid "Work" msgstr "Práce" #: src/bz-flathub-category.c:84 msgid "More Productivity" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:85 msgid "Science" msgstr "Věda" #: src/bz-flathub-category.c:85 #, fuzzy msgid "More Science" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:86 msgid "System" msgstr "Systém" #: src/bz-flathub-category.c:86 #, fuzzy msgid "More System" msgstr "Systém" #: src/bz-flathub-category.c:87 msgid "Utilities" msgstr "Nástroje" #: src/bz-flathub-category.c:87 msgid "Tools" msgstr "Nástroje" #: src/bz-flathub-category.c:87 #, fuzzy msgid "More Utilities" msgstr "Zobrazit Více" #: src/bz-flathub-category.c:88 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Trendy" #: src/bz-flathub-category.c:88 #, fuzzy msgid "More Trending" msgstr "Více Trendy" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populární" #: src/bz-flathub-category.c:89 #, fuzzy msgid "More Popular" msgstr "Více Populárních" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Nedávno přidané" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nové" #: src/bz-flathub-category.c:90 #, fuzzy msgid "More New" msgstr "Více Nedávno Přidaných" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Nedávno aktualizované" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:137 #, fuzzy msgid "Updated" msgstr "Aktualizavané" #: src/bz-flathub-category.c:91 #, fuzzy msgid "More Updated" msgstr "Více Aktualizovaných" #: src/bz-flathub-category.c:92 msgid "Mobile" msgstr "Mobile" #: src/bz-flathub-category.c:92 #, fuzzy msgid "More Mobile" msgstr "Zobrazit Více" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub Nebyl Přidán" #: src/bz-flathub-page.blp:24 #, fuzzy msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Flathub remote nebyl nalezen na žádné z instalacích flatpaku" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub vrátil chybu" #: src/bz-flathub-page.blp:41 #, fuzzy msgid "Retry Flathub Connection" msgstr "Zobrazit pouze obsah z Flathubu" #: src/bz-flathub-page.blp:57 #, fuzzy msgid "Flathub Unavailable" msgstr "Stránka na Flathubu" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Nemůžeme se připojit k Flathubu. Ovšem můžeze stále spravovat a hledat aplikace." #: src/bz-flathub-page.blp:61 #, fuzzy msgid "Search Apps" msgstr "Vyhledat Aplikace" #: src/bz-flathub-page.blp:270 #, fuzzy msgid "On the Go" msgstr "Na Cesty" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Aplikace pro vaše Linuxové telefony a tablety" #: src/bz-flathub-page.blp:293 msgid "More Mobile Apps" msgstr "Více Mobilních Aplikací" #: src/bz-flathub-page.blp:328 msgid "More Mobile apps" msgstr "Více Mobilních Aplikací" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "We​ ♥​ Games" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Hry a aplikace pro vaše oblíbené tituly" #: src/bz-flathub-page.blp:435 #, fuzzy msgid "More Games" msgstr "Více Her" #: src/bz-flatpak-entry.c:600 #, fuzzy msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Stránka na Flathubu" #: src/bz-flatpak-entry.c:621 #, fuzzy msgctxt "Project URL Type" msgid "Project Website" msgstr "Stránka projektu" #: src/bz-flatpak-entry.c:625 #, fuzzy msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Sledovač chyb" #: src/bz-flatpak-entry.c:629 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Help" msgstr "Nápověda" #: src/bz-flatpak-entry.c:637 #, fuzzy msgctxt "Project URL Type" msgid "Donate" msgstr "Podpořit" #: src/bz-flatpak-entry.c:643 msgctxt "Project URL Type" msgid "Translate" msgstr "Překlad" #: src/bz-flatpak-entry.c:647 #, fuzzy msgctxt "Project URL Type" msgid "Contact" msgstr "Kontakt" #: src/bz-flatpak-entry.c:651 msgctxt "Project URL Type" msgid "Source Code" msgstr "Zdrojový kód" #: src/bz-flatpak-entry.c:657 msgctxt "Project URL Type" msgid "Contribute" msgstr "Přispět" #: src/bz-full-view.blp:57 msgid "No Results" msgstr "Žádné výsledky" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Zkuste jiný dotaz" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Obsah" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Podpořit" #: src/bz-full-view.blp:233 src/bz-full-view.blp:488 #, fuzzy msgid "Open" msgstr "Otevřít odkaz" #: src/bz-full-view.blp:246 src/bz-full-view.blp:461 #, fuzzy msgid "Download & Install Application" msgstr "Stáhnout a nainstalovat tuto aplikaci" #: src/bz-full-view.blp:261 #, fuzzy msgid "Uninstall Application" msgstr "Odinstalovat tuto aplikaci" #: src/bz-full-view.blp:276 src/bz-full-view.blp:503 msgid "Install Other Version" msgstr "Nainstalovat další verzi" #: src/bz-full-view.blp:300 msgid "Size" msgstr "Velikost" #: src/bz-full-view.blp:405 #, fuzzy msgid "Downloads /mo" msgstr "Stažení /měsíc" #: src/bz-full-view.blp:522 msgid "Stopped Receiving Core Updates" msgstr "Stopped Receiving Core Updates" #: src/bz-full-view.blp:536 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Tato aplikace používá runtime, který již nedostává aktualizace nebo bezpečnostní opravy. " "Může se stát, že bude nebezpečné ji používat." #: src/bz-full-view.blp:619 src/bz-window.c:1260 msgid "Delete Data" msgstr "Smazat Data" #: src/bz-full-view.blp:753 msgid "Tags:" msgstr "Tagy:" #: src/bz-full-view.c:290 #, fuzzy msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:297 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:304 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:314 #, fuzzy, c-format msgid "%d downloads in the last 30 days" msgstr "%'d stažení za poslední měsíc" #: src/bz-full-view.c:346 #, fuzzy, c-format msgid "Download size of %s" msgstr "Velikost ke stažení" #: src/bz-full-view.c:379 msgid "All Ages" msgstr "Pro Všechny" #: src/bz-full-view.c:391 msgid "Age rating information unavailable" msgstr "Hondocení věku není k dispozici" #: src/bz-full-view.c:396 msgid "Suitable for all ages" msgstr "Vhodné pro všechny věkové skupiny" #: src/bz-full-view.c:398 #, c-format msgid "Suitable for ages %d and up" msgstr "Vhodné pro věkové skupiny od %d a více" #: src/bz-full-view.c:431 src/bz-full-view.c:436 src/bz-full-view.c:464 #: src/bz-full-view.c:475 msgid "Unknown" msgstr "Neznámé" #: src/bz-full-view.c:441 #, c-format msgid "Free software licensed under %s" msgstr "Svobodný software licencovaný pod licencí %s" #: src/bz-full-view.c:446 #, fuzzy msgid "Free software" msgstr "Svobodný software" #: src/bz-full-view.c:449 #, fuzzy msgid "Proprietary Software" msgstr "Propriétární Software" #: src/bz-full-view.c:452 #, c-format msgid "Special License: %s" msgstr "Speciální Licencie: %s" #: src/bz-full-view.c:469 msgid "Free" msgstr "Free" #: src/bz-full-view.c:472 src/bz-license-dialog.c:118 msgid "Proprietary" msgstr "Propriétární" #: src/bz-full-view.c:477 src/bz-license-dialog.c:120 #, fuzzy msgid "Special License" msgstr "Speciální Licence" #: src/bz-full-view.c:497 msgid "Adaptive" msgstr "Adaptivní" #: src/bz-full-view.c:497 msgid "Desktop Only" msgstr "Pouze pro Desktop" #: src/bz-full-view.c:503 msgid "Works on desktop, tablets, and phones" msgstr "Funkční na desktopu, tabletu a telefonu" #: src/bz-full-view.c:504 msgid "May not work on mobile devices" msgstr "Možná nefunguje na mobilních zařízeních" #: src/bz-full-view.c:515 msgid "No URL" msgstr "Žádná URL" #: src/bz-full-view.c:533 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Tato aplikace má FLOSS licenci. To znamená že kód může být ověřen pro " "bezpečnost." #: src/bz-full-view.c:534 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Tato aplikace má proprietární licenci. To znamená že kód je vyvíjen v " "soukromý a nemůže být ověřen třetí stranou." #: src/bz-full-view.c:541 #, fuzzy msgid "More Apps" msgstr "Více přidaných" #: src/bz-full-view.c:542 #, c-format msgid "More Apps by %s" msgstr "Více Aplikací od %s" #: src/bz-full-view.c:549 #, fuzzy msgid "Other Apps by this Developer" msgstr "Více Aplikací od tohoto Vývojáře" #: src/bz-full-view.c:551 src/bz-full-view.c:659 #, c-format msgid "Other Apps by %s" msgstr "Ostatní Aplikace od %s" #: src/bz-full-view.c:559 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s is not installed, but it still has %s of data present." #: src/bz-full-view.c:661 #, fuzzy msgid "Other Apps" msgstr "Ostatní Aplikace" #: src/bz-full-view.c:663 #, fuzzy, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Aplikace" msgstr[1] "%d Aplikace" msgstr[2] "%d Aplikace" #: src/bz-full-view.c:1011 #, fuzzy msgid "Show Less" msgstr "Zobrazit Méně" #: src/bz-full-view.c:1011 msgid "Show More" msgstr "Zobrazit Více" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 #, fuzzy msgid "Hardware Support" msgstr "Podpořit" #: src/bz-hardware-support-dialog.c:69 #, fuzzy msgid "Keyboard support" msgstr "Podpora klávesnice" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Vyřaduje klávesnici" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Doporučuje klávesnici" #: src/bz-hardware-support-dialog.c:73 #, fuzzy msgid "Supports keyboards" msgstr "Podporuje klávesnici" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Neznámá podpora klávesnice" #: src/bz-hardware-support-dialog.c:76 #, fuzzy msgid "Mouse support" msgstr "Podpora myši" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Požaduje myš" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Doporučuje myš" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Podporuje myš" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Neznámá podpora pro myš" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Podpora dotykových obrazovek" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Požaduje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Doporučuje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:87 #, fuzzy msgid "Supports touchscreens" msgstr "Podporuje dotykové obrazovky" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Neznámá podpora pro dotykové obrazovky" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Mobile support" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Funguje na mobilních zařízeních" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Nemusí fungovat dobře na mobilních zařízeních" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Desktop support" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Funguje dobře na velkých obrazovkách" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s funguje nejlépe na konkrétním hardware" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s funguje na většině zařízení" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Bazaar Inspertor" #: src/bz-inspector.blp:33 msgid "Background Task Info:" msgstr "Informace Služby na Pozadí:" #: src/bz-inspector.blp:43 msgid "Enable Global Debug Mode" msgstr "Povolit Globální Režim Ladění" #: src/bz-inspector.blp:50 msgid "Active Blocklists" msgstr "Aktivní Blokovací Seznamy" #: src/bz-inspector.blp:67 msgid "Active Curated-Configs" msgstr "Aktivní Nastavení Vybraného Obsahu" #: src/bz-inspector.blp:85 msgid "All Entry Groups" msgstr "Všechny Skupiny Vstupů" #: src/bz-inspector.blp:93 msgid "Filter..." msgstr "Filtrovat..." #: src/bz-inspector.blp:134 msgid "Decache and Inspect" msgstr "Decache and Inspect" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Žádné Flatpaky Nejsou Nainstalované." #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 #, fuzzy msgid "Stopped Receiving Updates" msgstr "Stopped Receiving Updates" #: src/bz-license-dialog.blp:160 msgid "Get Involved" msgstr "Get Involved" #: src/bz-license-dialog.c:107 src/bz-license-dialog.c:112 #, fuzzy msgid "Unknown License" msgstr "Neznámá Licence" #: src/bz-license-dialog.c:115 msgid "Community Built" msgstr "Postavené Komunitou" #: src/bz-license-dialog.c:148 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" #: src/bz-license-dialog.c:156 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" #: src/bz-license-dialog.c:161 msgid "The license of this app is not known" msgstr "" #: src/bz-license-dialog.c:165 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" #: src/bz-license-dialog.c:174 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Předvolby" #: src/bz-preferences-dialog.blp:23 #, fuzzy msgid "Content Filters" msgstr "Filtry Obsahu" #: src/bz-preferences-dialog.blp:26 #, fuzzy msgid "Free Software Only" msgstr "Pouze Svobodný Software" #: src/bz-preferences-dialog.blp:27 #, fuzzy msgid "Hide proprietary applications when browsing and searching" msgstr "Skrýt propertiární aplikace z výsledků vyhledávání" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Pouze Výsledky z Flathubu" #: src/bz-preferences-dialog.blp:32 #, fuzzy msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "Limitovat výsledky vyhledávání na aplikace dostupné na Flathubu" #: src/bz-preferences-dialog.blp:36 msgid "Hide EOL Apps" msgstr "Skrýt EOL Aplikace" #: src/bz-preferences-dialog.blp:37 msgid "Hide apps which are no longer supported by their developers" msgstr "Skrýt aplikace, které nejsou podporované jejich vývojáři" #: src/bz-preferences-dialog.blp:42 src/bz-window.blp:313 msgid "Search" msgstr "Vyhledávání" #: src/bz-preferences-dialog.blp:45 #, fuzzy msgid "Delay Search Results" msgstr "Debouncing Výsledků Vyhledávání" #: src/bz-preferences-dialog.blp:46 msgid "Improve results performance by debouncing search terms" msgstr "Vylepšit výkon výsledků vyhledávání debouncingem vyhledávacích termínů" #: src/bz-preferences-dialog.blp:51 #, fuzzy msgid "Progress Bar" msgstr "Globální Ukazatel Postupu" #: src/bz-preferences-dialog.blp:52 #, fuzzy msgid "Choose a theme for the progress bar!" msgstr "Vyberte vtipné téma pro globální ukazatel postupu!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Barva akcentu" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Pride Colors" #: src/bz-preferences-dialog.c:34 #, fuzzy msgid "Lesbian Pride Colors" msgstr "Lesbian Pride Colors" #: src/bz-preferences-dialog.c:35 #, fuzzy msgid "Transgender Pride Colors" msgstr "Transgender Pride Colors" #: src/bz-preferences-dialog.c:36 #, fuzzy msgid "Nonbinary Pride Colors" msgstr "Nonbinary Pride Colors" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Bisexual Pride Colors" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Asexual Pride Colors" #: src/bz-preferences-dialog.c:39 #, fuzzy msgid "Pansexual Pride Colors" msgstr "Pansexual Pride Colors" #: src/bz-preferences-dialog.c:40 #, fuzzy msgid "Aromantic Pride Colors" msgstr "Aromantic Pride Colors" #: src/bz-preferences-dialog.c:41 #, fuzzy msgid "Genderfluid Pride Colors" msgstr "Genderfluid Pride Colors" #: src/bz-preferences-dialog.c:42 #, fuzzy msgid "Polysexual Pride Colors" msgstr "Polysexual Pride Colors" #: src/bz-preferences-dialog.c:43 #, fuzzy msgid "Omnisexual Pride Colors" msgstr "Omnisexual Pride Colors" #: src/bz-preferences-dialog.c:44 msgid "Aroace Pride Colors" msgstr "Aroace Pride Colors" #: src/bz-preferences-dialog.c:45 msgid "Agender Pride Colors" msgstr "Agender Pride Colors" #: src/bz-preferences-dialog.c:46 msgid "Genderqueer Pride Colors" msgstr "Genderqueer Pride Colors" #: src/bz-preferences-dialog.c:47 msgid "Intersex Pride Colors" msgstr "Intersex Pride Colors" #: src/bz-preferences-dialog.c:48 msgid "Demigender Pride Colors" msgstr "Demigender Pride Colors" #: src/bz-preferences-dialog.c:49 msgid "Biromantic Pride Colors" msgstr "Biromantic Pride Colors" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 #, fuzzy msgid "Version History" msgstr "Verze %s" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "Verze %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "Žádné informace o této verzi" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Získat" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Snímky Obrazovky" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Předchozí Snímek Obrazovky" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Další Snímek Obrazovky" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Kopírovat Obrázek" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Resetovat Pohled" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Zoom Out" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Zoom In" #: src/bz-screenshots-carousel.blp:6 msgid "Screenshots Carousel" msgstr "Screenshots Carousel" #: src/bz-screenshots-carousel.blp:104 #, fuzzy msgid "Open Screenshot Viewer" msgstr "Otevřít v prohlížeči obrázků" #: src/bz-search-widget.blp:106 msgid "Search Apps, Games, Software" msgstr "Vyhledat Aplikace, Hry, Software" #: src/bz-search-widget.blp:150 #, fuzzy msgid "Categories Unavailable" msgstr "Aktualizace k dispozici" #: src/bz-search-widget.blp:151 msgid "Search for apps using the search bar above." msgstr "Vyhledejte aplikace pomocí vyhledávacího pole nahoře." #: src/bz-search-widget.blp:235 #, fuzzy msgid "No Applications Found" msgstr "Žádné vybrané aplikace" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Žádné výsledky pro \"%s\" v Flathubu" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Zkopírováno!" #: src/bz-share-list.c:116 #, fuzzy msgid "Copy Link" msgstr "Kopírovat odkaz" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Otevřít odkaz" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Časová osa" #: src/bz-stats-dialog.blp:46 #, fuzzy msgid "Installs:" msgstr "Instalace:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Svět" #: src/bz-tag-list.c:96 #, fuzzy msgid "No Results Found" msgstr "Žádné výsledky" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikace s Tagem \"%s\"" #: src/bz-tag-list.c:109 #, fuzzy, c-format msgid "%d Applications" msgstr "%d Aplikací" #: src/bz-tag-list.c:124 #, fuzzy msgid "Search failed" msgstr "Vyhledávání bylo neúspěšné" #: src/bz-transaction-manager.c:1135 #, c-format msgid "Finished in %.02f seconds" msgstr "Dokončeno v %.02f sekundách" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Doplňky aplikace" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 #, fuzzy msgid "Install Size" msgstr "Velikost na disku" #: src/bz-transaction-view.blp:200 msgid "Update" msgstr "Aktualizace" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Přeneseno %s" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Čeká" #: src/bz-update-dialog.blp:7 #, fuzzy msgid "Update Now" msgstr "Aktualizace" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Aktualizace k dispozici" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "Následující aplikace mají aktualizace. Přejete si je nainstalovat?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "%d runtime a/nebo doplňky mají aktualizace. Přejete si je nainstalovat?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Také následující %d runtime a/nebo dopňky budou aktualizované" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Spravovat Zbylá Uživatelské Data" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Žádná uživatelská data nebyla nalezena" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Uživatelská Data" #: src/bz-user-data-tile.c:144 #, c-format msgid "Removed User Data for %s" msgstr "Uživatelská Data pro %s byla odstraněna" #: src/bz-user-data-tile.blp:74 #, fuzzy msgid "Remove User Data" msgstr "Odstranit Uživatelská Data" #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Inspect UI Entry" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "All Debug Actions" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Úlohy" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Zastavit Aktivní Úlohy" #: src/bz-window.blp:171 #, fuzzy msgid "Clear History" msgstr "Historie verzí" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Žádné úlohy" #: src/bz-window.blp:258 #, fuzzy msgid "Refreshing Store Content" msgstr "Obnovit" #: src/bz-window.blp:273 msgid "Curated" msgstr "Vybrané" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:450 msgid "Network connection is metered — automatic store data sync is paused" msgstr "Připojení k síti je měřené - automatická synchronizace dat je pozastavena" #: src/bz-window.blp:451 src/bz-window.blp:460 msgid "Sync Manually" msgstr "Synchronizovat ručně" #: src/bz-window.blp:459 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Máte připojení k síti, ale prohlížíte si cached verzi Flathubu" #: src/bz-window.blp:534 msgid "_Login with Flathub" msgstr "_Přihlásit se pomocí Flathubu" #: src/bz-window.blp:540 msgid "_Manage Leftover User Data" msgstr "_Spravovat Zbylá Uživatelská Data" #: src/bz-window.blp:545 msgid "_Synchronize Remotes" msgstr "_Synchronizovat Remoty" #: src/bz-window.blp:571 #, fuzzy msgid "Open Bazaar Inspector" msgstr "Bazaar Inspertor" #: src/bz-window.blp:586 msgid "Log Out" msgstr "Odhlásit se" #: src/bz-window.c:484 #, fuzzy, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "Aktualizace k dispozici" msgstr[1] "Aktualizace k dispozici" msgstr[2] "Aktualizace k dispozici" #: src/bz-window.c:982 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Možnost prohlížet a instalovat loální .flatpak soubory bude brzy hotová. " "Mezitím zkuste spustit\n" "\n" "flatpak install --bundle tvuj-bundle.flatpak\n" "\n" "v terminálu." #: src/bz-window.c:1120 msgid "Can't do that right now!" msgstr "Toto teď nelze provést!" #: src/bz-window.c:1251 msgid "Keep Data" msgstr "Ponechat Data" #: src/bz-window.c:1252 msgid "Allow restoring settings and content" msgstr "Povolit obnovení nastavení a obsahu" #: src/bz-window.c:1261 msgid "Permanently remove app data to save space" msgstr "Navždy odstranit data aplikace pro šetření místa" #: src/bz-window.c:1284 #, fuzzy, c-format msgid "Install %s?" msgstr "Instalovat %s?" #: src/bz-window.c:1287 msgid "May install additional shared components" msgstr "Může nainstalovat dodatečné sdílené komponenty" #: src/bz-window.c:1306 #, fuzzy, c-format msgid "Remove %s?" msgstr "Odstranit %s?" #: src/bz-window.c:1310 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Po odinstalování nebude %s možné použít." #: src/bz-window.c:1373 msgid "Resume Current Tasks" msgstr "Obnovit Aktivní Úlohy" #: src/bz-window.c:1379 msgid "Pause Current Tasks" msgstr "Pozastavit Aktivní Úlohy" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u stažení" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Obecné" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Otevřít Vyhledávání" #: src/gtk/shortcuts-dialog.blp:14 #, fuzzy msgctxt "shortcut window" msgid "Open Preferences" msgstr "Otevřít Předvolby" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Obnovit" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Otevřít/zavřít Přehled translakcí" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Zobrazit Zkratky" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Ukončit" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Počet Hvězd Git Forge" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "" #~ "Pokusit se detekovat a zobrazit \"počet hvězd\" pro projekt v plném " #~ "zobrazení" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "" #~ "Filtrovat výsledky vyhledávání pro zobrazení pouze aplikacích dostupných " #~ "na Flathubu" #~ msgid "Manage Addons" #~ msgstr "Správce doplňků" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "João Victor (Leal)" #~ msgstr "João Victor (Leal)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Léane GRASSER" #~ msgstr "Léane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel Mrówka (Microwave)" #~ msgstr "Marcel Mrówka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Sabri Ünal" #~ msgstr "Sabri Ünal" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "camegone" #~ msgstr "camegone" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "Constructing Flatpak instance..." #~ msgstr "Sestavuji Flatpak instanci..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "Používám poslední Flatpak instanci..." #~ msgid "Flathub is not registered on this system" #~ msgstr "Flathub není registrovaný na tomto systému" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "Přejete si přidat Flathub jako remote? Pokud ne, Flathub karta nebude " #~ "dostupná. Toto můžete změnit později." #~ msgid "Add Flathub" #~ msgstr "Přidat Flathub" #, c-format #~ msgid "Identifying installed entries..." #~ msgstr "Identifikuji instalované položky..." #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "Probíhá stahování vzdálených položek s odkazem na %d blokovací " #~ "seznam(y)..." #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d z %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "Čekám na procesy na pozadí..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "Dokončeno během %0.2f sekund." #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Bazaar nezískal konfiguraci vybraného obsahu. Kontaktujte podporu své " #~ "distribuce." #~ msgid "Graphics" #~ msgstr "Grafika" #~ msgid "Office" #~ msgstr "Kancelář" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "Domovská stránka" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "Tento Flatpak je ověřený jeho původním vývojářem" #, fuzzy #~ msgid "Repository Star Count" #~ msgstr "Počet Hvězd Repozitáře" #~ msgid "Share this application" #~ msgstr "Sdílet tuto aplikaci" #~ msgid "Excludes shared components" #~ msgstr "Vynechané sdílené komponenty" #~ msgid "Source code may not be available" #~ msgstr "Zdrojový kód nemusí být k dispozici" #, fuzzy #~ msgid "Click for details" #~ msgstr "Klikněte pro podrobnosti" #~ msgid "Repositories" #~ msgstr "Repozitáře" #~ msgid "Open in browser" #~ msgstr "Otevřít v prohlížeči" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "%'d Měsíční stažení" #~ msgid "%B %-d, %Y" #~ msgstr "%e. %B %Y" #~ msgid "%B %-d" #~ msgstr "%e. %B" #~ msgid "Run this application" #~ msgstr "Sdílej tuto aplikaci" #~ msgid "Run" #~ msgstr "Spustit" #~ msgid "View Store Page" #~ msgstr "Otevřít Stránku Obchodu" #, fuzzy #~ msgid "Application Details" #~ msgstr "Podrobnosti" #~ msgid "Git Forge Star Counts" #~ msgstr "Počet Hvězd Git Forge" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "Pokud nemáte Github acess token, můžte narazit na limity" #~ msgid "Show Only Flathub Apps" #~ msgstr "Zobrazit Pouze Flathub Aplikace" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "Krátce vyčkejte ke snížení systémové zátěže" #~ msgid "Theme" #~ msgstr "Téma" #~ msgid "Pride Rainbow Flag" #~ msgstr "Pride Vlajka" #~ msgid "Bisexual Flag" #~ msgstr "Bisexual Vlajka" #~ msgid "Asexual Flag" #~ msgstr "Asexual Vlajka" #~ msgid "Share" #~ msgstr "Sdílet" #~ msgid "Install Now" #~ msgstr "Nainstalovat nyní" #~ msgid "Browse" #~ msgstr "Prohlížet" #~ msgid "App View" #~ msgstr "Aplikace" #~ msgid "Go Back" #~ msgstr "Zpět" #~ msgid "View curated applications" #~ msgstr "Zobraz vybrané aplikace" #~ msgid "View the latest on Flathub" #~ msgstr "Zobrazit to nejnovější z Flathubu" #~ msgid "View installed applications" #~ msgstr "Zobrazit nainstalované aplikace" #~ msgid "_Quit Service" #~ msgstr "_Ukončit Službu" #~ msgid "Settings & user data will be kept" #~ msgstr "Nastavení a uživatelská data budou zachována" #~ msgid "Calligraphy application page" #~ msgstr "Stránka aplikace Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "Graf stažení Blenderu" #~ msgid "Open this image in the default image viewer" #~ msgstr "Otevřít obrázek ve výchozím prohlížeči obrázků" #, fuzzy #~ msgid "Copy this image to the clipboard" #~ msgstr "Zkopírovat obrázek" #, fuzzy #~ msgid "App Details" #~ msgstr "Podrobnosti" #~ msgid "Download Statistics" #~ msgstr "Statistiky Stažení" #~ msgid "Show Downloads Over Time" #~ msgstr "Stažení za čas" #~ msgid "Remote repo name" #~ msgstr "Jméno remotu" #, fuzzy #~ msgid "Updated Size" #~ msgstr "Velikost aktualizace" #~ msgid "Freed Space" #~ msgstr "Uvolněné místo" #~ msgid "Transactions Will Appear Here" #~ msgstr "Translakce Se Zobrazí Zde" #~ msgid "Halt the execution of transactions" #~ msgstr "Zastavit přůběh translakcí" #~ msgid "Clear all finished transactions" #~ msgstr "Vymazat všechny dokončené translakce" #~ msgid "Up to date!" #~ msgstr "Vše je aktualizované" #~ msgid "Confirm Action" #~ msgstr "Potvrď akci" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Budou se odstraňovat následující Flatpaky:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Jste si jistý?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Budou se instalovat následující Flatpaky:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Jste si jistý?" #~ msgid "Resume the execution of transactions" #~ msgstr "Obnov prováděné translakce" #~ msgid "Pause the execution of transactions" #~ msgstr "Pozastav prováděné translakce" #~ msgid "Downloads Over Time" #~ msgstr "Stažení za čas" #~ msgid "Apps Of The Week" #~ msgstr "Aplikace týdne" #, fuzzy #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "VCS Prohlížeč" #, c-format #~ msgid "Released %x" #~ msgstr "Vydáno %x" #~ msgid "Full Application View" #~ msgstr "Plné zobrazení aplikace" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "Změnit jaký obsah je zobrazen při prohlížení aplikací" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause " #~ "GitHub to eventually rate limit you." #~ msgstr "" #~ "Pokud nemáte přístupový token, zapínání tohoto nastavení může způsobit že " #~ "dosáhnete přístupového limitu (omezení) Githubu" #~ msgid "Type to filter" #~ msgstr "Pište pro filtrování" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Skrýt výsledky s proprietárními licencemi" #~ msgid "Advanced" #~ msgstr "Pokročilé" #~ msgid "Open this link externally" #~ msgstr "Otevřít externě" #~ msgid "Minimize Lower Bound" #~ msgstr "Minimalizuj dolní hranici" #~ msgid "Maximize Upper Bound" #~ msgstr "Maximalizuj horní hranici" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "Získáno %'d položek z celkových %'d (%0.1f sekund uplynulo)" #~ msgid "VCS Forge Star Count" #~ msgstr "Počet Hvězd VCS Forge" #~ msgid "This application does not provide a donation link" #~ msgstr "Tato aplikace nemá odkaz na stránku s dary" #~ msgid "Edit Permissions" #~ msgstr "Správce oprávnění" #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try looking at their project page for " #~ "more information." #~ msgstr "" #~ "\"%s\" nemá odkaz na stránku s dary. To znamená že je nemůžete podpořit! " #~ "Zkuste se podívat na jejich webové stránky pro více " #~ "informací." #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try finding their project page for more information." #~ msgstr "" #~ "\"%s\" nemá odkaz na stránku s dary. To znamená že je nemůžete podpořit! " #~ "Zkuste najít jejich webovou stránku pro více infomací." #~ msgid "Installing" #~ msgstr "Instalace" #~ msgid "Updating" #~ msgstr "Aktualizace" #~ msgid "Removing" #~ msgstr "Odinstalace" #~ msgid "Show Animated Background" #~ msgstr "Ukázat animované pozadí" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Zda se mají na domovské stránce zobrazovat animované pozadí ikony" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "Počet staženích v posledních 30 dnech. Klikni pro zobrazení statistiky " #~ "stažení aplikace." #~ msgid "How the application looks" #~ msgstr "Jak aplikace vypadá" #~ msgid "Appearance" #~ msgstr "Vzhled" #~ msgid "Show animated background" #~ msgstr "Zobrazit animované pozadí" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Nechej schnutí krátké, mezi 10 až 35 znaky" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Hlavní okno Bazaaru ukazující Blender" #~ msgid "BzInstalledPage" #~ msgstr "BzInstalledPage" #~ msgid "Match using regular expressions" #~ msgstr "Použít regulérní výrazy" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "Skrýt filtrování a řazení za efekt prolínání" kolunmi-bazaar-7b9c8e1/po/de.po000066400000000000000000002311401514314607700164310ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # # SPDX-FileCopyrightText: 2025, 2026 renner # renner , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-23 18:17+0100\n" "PO-Revision-Date: 2026-01-23 20:42+0100\n" "Last-Translator: renner \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Lokalize 25.12.1\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Hinzufügen, Entfernen oder Aktualisieren von Apps auf diesem Computer" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;Paketverwaltung;Discover;Flatpak;Software;Store;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Apps entdecken und installieren" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Ein neuer App Store für GNOME mit Schwerpunkt auf der Suche und Installation " "von Apps und Erweiterungen aus Flatpak-Remotes, insbesondere Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Es legt Wert darauf, die Entwickler zu unterstützen, die den Linux-Desktop " "möglich machen. Bazaar verfügt über ein „vorgestellt”-Unterfenster, der von " "Distributoren eingerichtet werden kann, um eine lokalisiertere Erfahrung zu " "ermöglichen." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:706 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Die Startseite mit den Flathub-Apps" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Seite der Nucleus App" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Auf Seite suchen" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Kategorienseite" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:697 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Erweiterungen verwalten" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:225 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "Entfernen" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:202 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Installieren" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:338 src/bz-full-view.c:345 msgid "Age Rating" msgstr "Alterseinstufung" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Cartoon-Gewalt" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Keine Informationen über Cartoon-Gewalt" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Fantasie-Gewalt" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Keine Informationen über Fantasie-Gewalt" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Realistische Gewalt" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Keine Informationen über realistische Gewaltdarstellung" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Darstellung von Blutvergießen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Keine Informationen über Blutvergießen" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Sexuelle Gewalt" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Keine Informationen über Sexuelle Gewalt" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alkohol" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Keine Informationen über Alkohol" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Betäubungsmittel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Keine Informationen über unerlaubten Drogen/Medikamente" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabak" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Keine Informationen über Tabakprodukte" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nacktheit" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Keine Informationen über Nacktszenen irgendeiner Form" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Sexuelle Themen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Keine Informationen über Anspielungen oder Darstellungen sexueller Natur" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Obszönität" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Keine Informationen über Obszönität irgendeiner Art" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Unangemessener Humor" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Keine Informationen über unangemessenen Humor" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Diskriminierung" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Keine Informationen über diskriminierender Sprache irgendeiner Art" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Werbung" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Keine Informationen über Werbung irgendeiner Art" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Glücksspiel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Keine Informationen über Glücksspiel irgendeiner Art" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Einkauf" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Keine Informationen über die Möglichkeit, reales Geld auszugeben" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Mit anderen Nutzern chatten" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Keine Informationen über die Möglichkeit, mit anderen Nutzern zu chatten." #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Audio-Chat zwischen Nutzern" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Keine Informationen über die Möglichkeit, mit anderen Nutzern zu sprechen" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Kontaktdetails" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Keine Informationen über das Teilen von Benutzernamen und E-Mail-Adressen " "über soziale Netzwerke" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Identifizierende Informationen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "Keine Informationen über das Teilen von Benutzerinformationen mit Dritten" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Standortfreigabe" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Keine Informationen über das Teilen des physischen Aufenthaltsortes mit " "anderen Nutzern" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostitution" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Keine Informationen über die Erwähnung von Prostitution" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Ehebruch" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Keine Informationen über die Erwähnung von Ehebruch" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Sexualisierten Figuren" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Keine Informationen über sexualisierte Figuren" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Schändung" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Keine Informationen über Erwähnungen von Schändung" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Menschliche Überreste" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Keine Informationen über sichtbare menschliche Überreste" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Sklaverei" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Keine Informationen über die Erwähnung von Sklaverei" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Enthält keine Erwähnungen von Drogen" #: src/bz-age-rating-dialog.c:426 msgid "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "Enthält keine Schimpfwörter, Obszönitäten und andere Arten von vulgärer " "Sprache" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Enthält keine Werbung oder Geldtransaktionen" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Enthält keine sexuellen Inhalte oder Nacktheit" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Enthält keine unkontrollierte Chat-Funktion" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Enthält keine Gewalt" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drogen" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Kraftwörter" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Geld" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Soziales" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Gewalt" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:328 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Alle" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s hat ein unbekannte Alterseinstufung" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s ist für alle geeignet" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s ist für junge Kinder geeignet" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s ist für Kinder geeignet" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s ist für Jugendliche geeignet" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s ist für Erwachsene geeignet" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s is geeignet für %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:483 msgid "Main Menu" msgstr "Hauptmenü" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:556 msgid "_Donate to Bazaar ❤️" msgstr "An Bazaar _spenden ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 #, fuzzy msgid "_Refresh Content" msgstr "Store-Inhalt aktualisieren" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:563 msgid "_Preferences" msgstr "_Einstellungen" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:584 msgid "_Keyboard Shortcuts" msgstr "_Tastaturkurzbefehle" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:589 msgid "_About Bazaar" msgstr "Ü_ber Bazaar" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:596 msgid "_Quit Bazaar" msgstr "Bazaar b_eenden" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "" #: src/bz-app-permissions.c:169 #, fuzzy, c-format msgid "Desktop subfolder %s" msgstr "Desktop-Unterstützung" #: src/bz-app-permissions.c:170 #, fuzzy msgid "Desktop folder" msgstr "Desktop-Unterstützung" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Dokumentenordner" #: src/bz-app-permissions.c:177 #, fuzzy, c-format msgid "Music subfolder %s" msgstr "%s is geeignet für %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Musikordner" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Bilderordner" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Öffentlicher Ordner" #: src/bz-app-permissions.c:189 #, fuzzy, c-format msgid "Videos subfolder %s" msgstr "%s is geeignet für %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Videoordner" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Vorlagenordner" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Downloadgröße" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "" #: src/bz-app-size-dialog.blp:76 #, fuzzy msgid "Installed Size" msgstr "Installationsgöße" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "" #: src/bz-app-size-dialog.blp:99 #, fuzzy msgid "User Data Size" msgstr "Installationsgöße" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "" #. Translators: As in 'The app is installed'. #. Translators: . #: src/bz-app-tile.blp:86 src/bz-full-view.c:292 src/bz-installed-page.blp:86 #: src/bz-window.blp:299 msgid "Installed" msgstr "Installiert" #: src/bz-apps-page.blp:103 msgid "Show All" msgstr "Alle anzeigen" #: src/bz-apps-page.c:232 #, fuzzy, c-format msgid "All \"%s\"" msgstr "Alle Altersgruppen" #: src/bz-apps-page.c:506 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Apps" #: src/bz-application.c:677 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:678 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:709 msgid "translator-credits" msgstr "" "renner\n" "Mandarinoo" #: src/bz-application.c:720 msgid "Special Thanks" msgstr "" #: src/bz-application.c:778 msgid "Logged Out Successfully!" msgstr "" #: src/bz-application.c:905 msgid "Performing setup..." msgstr "Einrichtung wird durchgeführt …" #: src/bz-application.c:984 src/bz-application.c:993 msgid "Set Up Flathub" msgstr "Flathub einrichten" #: src/bz-application.c:987 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" #: src/bz-application.c:992 src/bz-window.c:875 msgid "Later" msgstr "Später" #: src/bz-application.c:1380 src/bz-application.c:3086 msgid "Synchronizing..." msgstr "Abgleichen …" #: src/bz-application.c:1521 src/bz-application.c:3082 #, c-format msgid "Receiving %d entries..." msgstr "%d Einträge empfangen …" #: src/bz-application.c:1526 #, fuzzy msgid "Checking for updates" msgstr "Es wird nach Aktualisierungen gesucht …" #: src/bz-application.c:3088 msgid "Indexing Data..." msgstr "" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:75 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Leer" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Keine vorgestellten Apps" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Flathub durchsuchen" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Offline" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Browser" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "" #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Installationsart auswählen" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Sie haben mehrere Versionen dieser App installiert.Mit welcher möchten " "Sie fortfahren?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:201 #: src/bz-transaction-dialog.c:224 src/bz-transaction-dialog.c:269 #: src/bz-transaction-dialog.c:576 msgid "Cancel" msgstr "Abbrechen" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Es ist ein Fehler aufgetreten" #: src/bz-error.c:89 msgid "Close" msgstr "Schließen" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Kopieren und Schließen" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Anmelden" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Deinstallieren" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Diese App unterstützen" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:85 #: src/bz-window.blp:614 msgid "Favorites" msgstr "" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:460 msgid "Toggle transaction sidebar" msgstr "Seitenleiste für Transaktionen anzeigen" #: src/bz-favorites-page.blp:46 src/bz-transaction-dialog.c:577 msgid "Install All" msgstr "Alle installieren" #: src/bz-favorites-page.blp:63 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Wird geladen" #: src/bz-favorites-page.blp:78 msgid "No Favorites" msgstr "" #: src/bz-favorites-page.blp:79 msgid "Applications you mark as favorite will appear here" msgstr "" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Zurück" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Weiter" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "App des Tages" #: src/bz-flathub-category.c:79 msgid "Audio & Video" msgstr "Audio & Video" #: src/bz-flathub-category.c:79 msgid "Media" msgstr "Media" #: src/bz-flathub-category.c:79 msgid "More Audio & Video" msgstr "Mehr Audio & Video" #: src/bz-flathub-category.c:80 msgid "Developer Tools" msgstr "Entwicklungswerkzeuge" #: src/bz-flathub-category.c:80 msgid "Develop" msgstr "Entwickeln" #: src/bz-flathub-category.c:80 msgid "More Developer Tools" msgstr "Mehr Entwicklerwerkzeuge" #: src/bz-flathub-category.c:81 msgid "Education" msgstr "Bildung" #: src/bz-flathub-category.c:81 msgid "Learn" msgstr "Lerne" #: src/bz-flathub-category.c:81 msgid "More Education" msgstr "Mehr Bildung" #: src/bz-flathub-category.c:82 msgid "Gaming" msgstr "Gaming" #: src/bz-flathub-category.c:82 msgid "Play" msgstr "Spielen" #: src/bz-flathub-category.c:82 msgid "More Gaming" msgstr "Mehr Gaming" #: src/bz-flathub-category.c:83 msgid "Graphics & Photography" msgstr "" #: src/bz-flathub-category.c:83 msgid "Create" msgstr "Erstelle" #: src/bz-flathub-category.c:83 msgid "More Graphics & Photography" msgstr "" #: src/bz-flathub-category.c:84 msgid "Networking" msgstr "Netzwerk" #: src/bz-flathub-category.c:84 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:84 msgid "More Networking" msgstr "Mehr Netzwerk" #: src/bz-flathub-category.c:85 msgid "Productivity" msgstr "Produktivität" #: src/bz-flathub-category.c:85 msgid "Work" msgstr "Arbeit" #: src/bz-flathub-category.c:85 msgid "More Productivity" msgstr "Mehr Produktivität" #: src/bz-flathub-category.c:86 msgid "Science" msgstr "Wissenschaft" #: src/bz-flathub-category.c:86 msgid "More Science" msgstr "Mehr Wissenschaft" #: src/bz-flathub-category.c:87 msgid "System" msgstr "System" #: src/bz-flathub-category.c:87 msgid "More System" msgstr "Mehr System" #: src/bz-flathub-category.c:88 msgid "Utilities" msgstr "Dienstprogramme" #: src/bz-flathub-category.c:88 msgid "Tools" msgstr "Werkzeuge" #: src/bz-flathub-category.c:88 msgid "More Utilities" msgstr "Mehr Dienstprogramme" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Im Trend" #: src/bz-flathub-category.c:89 msgid "More Trending" msgstr "Mehr von „Im Trend“" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Beliebt" #: src/bz-flathub-category.c:90 msgid "More Popular" msgstr "Mehr von „Beliebt“" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Kürzlich hinzugefügt" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:131 msgid "New" msgstr "Kürzlich hinzugefügt" #: src/bz-flathub-category.c:91 msgid "More New" msgstr "Mehr von „Kürzlich hinzugefügt“" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Kürzlich aktualisiert" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Kürzlich aktualisiert" #: src/bz-flathub-category.c:92 msgid "More Updated" msgstr "Mehr von „Kürzlich aktualisiert“" #: src/bz-flathub-category.c:93 msgid "Mobile" msgstr "Mobil" #: src/bz-flathub-category.c:93 msgid "More Mobile" msgstr "Mehr Mobil" #: src/bz-flathub-category.c:94 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:94 #, fuzzy msgid "More Adwaita" msgstr "Mehr von „Kürzlich aktualisiert“" #: src/bz-flathub-category.c:95 msgid "KDE Apps" msgstr "KDE-Apps" #: src/bz-flathub-category.c:95 msgid "More KDE Apps" msgstr "Mehr Apps" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub wurde nicht hinzugefügt" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Flathub wurde auf keiner Ihrer Flatpak-Installationen gefunden." #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Nur Flathub-Apps anzeigen" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub nicht erreichbar" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Anwedungen suchen" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Unterwegs" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Mehr Mobile Apps" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Wir ♥​ Spiele" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Mehr Spiele" #: src/bz-flatpak-entry.c:663 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub-Seite" #: src/bz-flatpak-entry.c:684 msgctxt "Project URL Type" msgid "Project Website" msgstr "Projekt-Webseite" #: src/bz-flatpak-entry.c:688 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Bugtracker" #: src/bz-flatpak-entry.c:692 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:696 msgctxt "Project URL Type" msgid "Help" msgstr "Hilfe" #: src/bz-flatpak-entry.c:700 msgctxt "Project URL Type" msgid "Donate" msgstr "Spenden" #: src/bz-flatpak-entry.c:706 msgctxt "Project URL Type" msgid "Translate" msgstr "Übersetzen" #: src/bz-flatpak-entry.c:710 msgctxt "Project URL Type" msgid "Contact" msgstr "Kontakt" #: src/bz-flatpak-entry.c:714 msgctxt "Project URL Type" msgid "Source Code" msgstr "Quellcode" #: src/bz-flatpak-entry.c:720 msgctxt "Project URL Type" msgid "Contribute" msgstr "Mitmachen" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Keine Ergebnisse" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Versuchen Sie eine andere Suchanfrage" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Inhalt" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Unterstützen" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Öffnen" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Apps herunterladen & installieren" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "App deinstallieren" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Andere Version installieren" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "Downloads/Monat" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Diese App verwendet eine Laufzeitumgebung, die keine Updates und " "Sicherheitsaktualisierungen mehr enthält. Sie könnte unsicher zu verwenden " "werden." #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "" #: src/bz-full-view.blp:772 msgid "Tags:" msgstr "Stichwörter:" #: src/bz-full-view.c:235 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:242 #, c-format msgid "%.*fM" msgstr "" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:249 #, c-format msgid "%.*fK" msgstr "" #: src/bz-full-view.c:259 #, c-format msgid "%d downloads in the last 30 days" msgstr "" #. Translators: . #: src/bz-full-view.c:292 #, fuzzy msgid "Download" msgstr "Downloadgröße" #: src/bz-full-view.c:310 #, c-format msgid "Download size of %s" msgstr "Downloadgröße von %s" #: src/bz-full-view.c:343 msgid "All Ages" msgstr "Alle Altersgruppen" #: src/bz-full-view.c:355 msgid "Age rating information unavailable" msgstr "" #: src/bz-full-view.c:360 msgid "Suitable for all ages" msgstr "Geeignet für alle Altersgruppen" #: src/bz-full-view.c:362 #, c-format msgid "Suitable for ages %d and up" msgstr "" #: src/bz-full-view.c:395 src/bz-full-view.c:400 src/bz-full-view.c:428 #: src/bz-full-view.c:439 msgid "Unknown" msgstr "Unbekannt" #: src/bz-full-view.c:405 #, c-format msgid "Free software licensed under %s" msgstr "Freie Software lizenziert unter %s" #: src/bz-full-view.c:410 #, fuzzy msgid "Free software" msgstr "Nur freie Software" #: src/bz-full-view.c:413 msgid "Proprietary Software" msgstr "Proprietäre Software" #: src/bz-full-view.c:416 #, c-format msgid "Special License: %s" msgstr "Besondere Lizenz: %s" #: src/bz-full-view.c:433 msgid "Free" msgstr "Frei" #: src/bz-full-view.c:436 src/bz-license-dialog.c:190 msgid "Proprietary" msgstr "Proprietär" #: src/bz-full-view.c:441 src/bz-license-dialog.c:192 msgid "Special License" msgstr "Besondere Lizenz" #: src/bz-full-view.c:461 msgid "Adaptive" msgstr "Adaptiv" #: src/bz-full-view.c:461 msgid "Desktop Only" msgstr "" #: src/bz-full-view.c:467 msgid "Works on desktop, tablets, and phones" msgstr "" #: src/bz-full-view.c:468 msgid "May not work on mobile devices" msgstr "" #: src/bz-full-view.c:479 msgid "No URL" msgstr "Keine URL" #: src/bz-full-view.c:497 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Diese App steht unter einer FLOSS-Lizenz, was bedeutet, dass der " "Quellcode auf Sicherheit geprüft werden kann." #: src/bz-full-view.c:498 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Diese App hat eine proprietäre Lizenz, das bedeute, dass der Quellcode " "privat entwickelt wird und kann nicht von einer unabhängigen dritten Partei " "überprüft werden." #: src/bz-full-view.c:505 msgid "More Apps" msgstr "Mehr Apps" #: src/bz-full-view.c:506 #, c-format msgid "More Apps by %s" msgstr "Mehr Apps von %s" #: src/bz-full-view.c:513 msgid "Other Apps by this Developer" msgstr "Andere Apps von diesem Entwickler" #: src/bz-full-view.c:515 src/bz-full-view.c:715 #, c-format msgid "Other Apps by %s" msgstr "Andere Apps von %s" #: src/bz-full-view.c:524 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" #: src/bz-full-view.c:597 src/bz-full-view.c:614 msgid "N/A" msgstr "N/V" #: src/bz-full-view.c:604 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Sicher" #: src/bz-full-view.c:606 src/bz-full-view.c:608 msgid "Low Risk" msgstr "Geringes Risiko" #: src/bz-full-view.c:610 msgid "Medium Risk" msgstr "Mittleres Risiko" #: src/bz-full-view.c:612 msgid "High Risk" msgstr "Hohes Risiko" #: src/bz-full-view.c:717 msgid "Other Apps" msgstr "Andere Apps" #: src/bz-full-view.c:719 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d App" msgstr[1] "%d Apps" #: src/bz-full-view.c:1058 msgid "Show Less" msgstr "Weniger anzeigen" #: src/bz-full-view.c:1058 msgid "Show More" msgstr "Mehr anzeigen" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Hardwareunterstützung" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Tastaturunterstützung" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Benötigt Tastatur" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Tastatur empfohlen" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Unterstützt Tastaturen" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Tastaturunterstützung unbekannt" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Mausunterstützung" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Benötigt Maus oder anderes Zeigegerät" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Maus oder anderes Zeigegerät empfohlen" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Unterstützt Mäuse und andere Zeigegeräte" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Mausunterstützung unbekannt" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Touchscreen-Unterstützung" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Benötigt einen Touchscreen" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Empfiehlt Touchscreen" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Unterstützt Touchscreens" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Touchscreen-Unterstützung unbekannt" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Mobilgeräteunterstützung" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Funktioniert auf Mobilgeräten" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Könnte auf Mobilgeräten nicht gut funktionieren" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Desktop-Unterstützung" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Funktioniert gut auf großen Bildschirmen" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "Installierte Apps anzeigen" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "Keine Apps gefunden" #: src/bz-installed-page.c:157 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Erhält keine Aktualisierungen mehr" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Machen Sie mit" #: src/bz-license-dialog.c:184 #, fuzzy msgid "Unknown License" msgstr "Unbekannt" #: src/bz-license-dialog.c:187 msgid "Community Built" msgstr "Entwickelt von der Gemeinschaft" #: src/bz-license-dialog.c:235 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" #: src/bz-license-dialog.c:238 msgid "The license of this app is not known" msgstr "" #: src/bz-license-dialog.c:244 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" #: src/bz-license-dialog.c:252 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" #: src/bz-license-dialog.c:258 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 #, fuzzy msgid "Connect to Flathub" msgstr "Flathub einrichten" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Leider ist ein Fehler aufgetreten" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Fertigstellen" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Einstellungen" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:494 msgid "Sync Manually" msgstr "" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Inhaltsfilter" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Nur freie Software" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "" "Proprietäre Apps beim Durchsuchen und bei den Suchergebnissen " "ausblenden" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Nur Flathub Ergebnisse" #: src/bz-preferences-dialog.blp:40 msgid "Limit search and browse results to applications only available on Flathub" msgstr "Suchergebnisse auf Apps beschränken, die auf Flathub verfügbar sind" #: src/bz-preferences-dialog.blp:44 #, fuzzy msgid "Verified Results Only" msgstr "Nur Flathub Ergebnisse" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Apps ausschließen, die nicht von Flathub stammen" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "EOL-Apps ausblenden" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:314 msgid "Search" msgstr "Suchen" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Suchergebnisse verzögern" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Fortschrittsbalken" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Wählen Sie ein tolles Design für den globalen Fortschrittsbalken." #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from top to bottom" msgstr "" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Akzentfarbe" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Pride-Farben" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Lesben-Pride-Flagge" #: src/bz-preferences-dialog.c:35 #, fuzzy msgid "Male Homosexual Pride Colors" msgstr "Pansexuellenflagge" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Transgender-Flagge" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Nichtbinären-Flagge" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Pansexuellenflagge" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Aromantischenflagge" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Genderfluidenflagge" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Polysexuellenflagge" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Omnisexuellenflagge" #: src/bz-preferences-dialog.c:45 #, fuzzy msgid "Aroace Pride Colors" msgstr "Aromantischenflagge" #: src/bz-preferences-dialog.c:46 #, fuzzy msgid "Agender Pride Colors" msgstr "Transgender-Flagge" #: src/bz-preferences-dialog.c:47 #, fuzzy msgid "Genderqueer Pride Colors" msgstr "Genderfluidenflagge" #: src/bz-preferences-dialog.c:48 #, fuzzy msgid "Intersex Pride Colors" msgstr "Pansexuellenflagge" #: src/bz-preferences-dialog.c:49 #, fuzzy msgid "Demigender Pride Colors" msgstr "Transgender-Flagge" #: src/bz-preferences-dialog.c:50 #, fuzzy msgid "Biromantic Pride Colors" msgstr "Aromantischenflagge" #: src/bz-preferences-dialog.c:51 #, fuzzy msgid "Disability Pride Colors" msgstr "Lesben-Pride-Flagge" #: src/bz-preferences-dialog.c:52 #, fuzzy msgid "Femboy Pride Colors" msgstr "Pride-Farben" #: src/bz-preferences-dialog.c:53 #, fuzzy msgid "Neutrois Pride Colors" msgstr "Nichtbinären-Flagge" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "Versionsgeschichte" #: src/bz-releases-list.c:135 #, c-format msgid "Version %s" msgstr "Version: %s" #: src/bz-releases-list.c:173 msgid "No details for this release" msgstr "Keine Details für diese Veröffentlichung" #: src/bz-releases-list.c:185 #, fuzzy msgid "Get More Information" msgstr "Identifizierende Informationen" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Installieren" #: src/bz-safety-calculator.c:82 #, fuzzy msgid "Unknown Permissions" msgstr "Berechtigungen bearbeiten" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "" #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Keine Berechtigungen" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "App ist vollständig isoliert" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Netzwerk-Zugriff" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Hat Zugriff auf das Internet" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Kein Netzwerk-Zugriff" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Hat keinen Zugriff auf das Internet" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "" #: src/bz-safety-calculator.c:156 #, fuzzy msgid "Arbitrary Permissions" msgstr "Berechtigungen bearbeiten" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Kein Dateisystemzugriff" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "" #: src/bz-safety-calculator.c:331 #, fuzzy msgid "Verified App Developer" msgstr "Andere Apps von diesem Entwickler" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Proprietärer Code" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Auditierbarer Code" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "KDE Connect-Integration" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Sicherheit" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Details" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Lizenz" #: src/bz-safety-dialog.blp:62 msgid "App ID" msgstr "App-ID" #: src/bz-safety-dialog.blp:71 msgid "SDK" msgstr "" #: src/bz-safety-dialog.blp:98 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Bild kopieren" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Ansicht zurücksetzen" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Verkleinern" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Vergrößern" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Nach Apps, Spielen und Software suchen" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Kategorien nicht verfügbar" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "" #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Keine App gefunden" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Kopiert." #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Link kopieren" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Link öffnen" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Zeitleiste" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Installationen:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Welt" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Keine Ergebnisse gefunden" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Suchen fehlgeschlagen" #: src/bz-transaction-dialog.c:160 msgid "Keep Data" msgstr "Daten behalten" #: src/bz-transaction-dialog.c:161 msgid "Allow restoring settings and content" msgstr "" #: src/bz-transaction-dialog.c:170 msgid "Delete Data" msgstr "Daten löschen" #: src/bz-transaction-dialog.c:171 msgid "Permanently remove app data to save space" msgstr "" #: src/bz-transaction-dialog.c:195 #, c-format msgid "Install %s?" msgstr "%s installieren?" #: src/bz-transaction-dialog.c:198 msgid "May install additional shared components" msgstr "Es könnten zusätzliche gemeinsam genutzte Komponenten installiert werden" #: src/bz-transaction-dialog.c:217 #, c-format msgid "Remove %s?" msgstr "%s entfernen?" #: src/bz-transaction-dialog.c:221 #, fuzzy, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "" "Es wird nicht mehr möglich sein, %s nach der Deinstallation auszuführen.\n" "\n" "Einstellungen und Benutzerdaten werden behalten werden." #: src/bz-transaction-dialog.c:241 #, c-format msgid "“%s” is High Risk" msgstr "" #: src/bz-transaction-dialog.c:245 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" #: src/bz-transaction-dialog.c:254 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" #: src/bz-transaction-dialog.c:270 msgid "Install Anyway" msgstr "Trotzdem installieren" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "" #: src/bz-transaction-dialog.c:549 msgid "OK" msgstr "OK" #: src/bz-transaction-dialog.c:565 #, fuzzy, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "%s installieren?" msgstr[1] "%s installieren?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "" #: src/bz-transaction-dialog.c:575 #, fuzzy msgid "Additionally, addons will be installed." msgstr "Zusätzlich werden %d Laufzeitumgebungen und/oder Erweiterungen aktualisiert." #: src/bz-transaction-manager.c:1150 #, c-format msgid "Finished in %.02f seconds" msgstr "In %.02f Sekunden abgeschlossen" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "App Erweiterung" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Laufzeitumgebung" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Installationsgöße" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "Ausstehend" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "Aktualisieren" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "%s bis jetzt übertragen" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Aufgaben" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Aktiven Aufgaben stoppen" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Verlauf leeren" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Noch keine Aufgaben" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "Store-Inhalt aktualisieren" #: src/bz-window.blp:273 msgid "Curated" msgstr "Vorgestellt" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:435 msgid "No background tasks!" msgstr "" #: src/bz-window.blp:493 msgid "You have a network connection but are viewing a cached version of Flathub" msgstr "" #: src/bz-window.blp:568 msgid "_Login with Flathub" msgstr "Mit Flathub _anmelden" #: src/bz-window.blp:574 msgid "_Manage Leftover User Data" msgstr "" #: src/bz-window.blp:579 msgid "_Synchronize Remotes" msgstr "" #: src/bz-window.blp:620 msgid "Log Out" msgstr "Abmelden" #: src/bz-window.c:440 #, fuzzy, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "Es sind Aktualisierungen verfügbar" msgstr[1] "Es sind Aktualisierungen verfügbar" #: src/bz-window.c:734 msgid "You can't remove Bazaar from Bazaar!" msgstr "" #: src/bz-window.c:871 msgid "Updates Are Available" msgstr "Es sind Aktualisierungen verfügbar" #: src/bz-window.c:872 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Für die folgenden Apps sind Aktualisierungen erhältlich. Möchten Sie " "diese installieren?" #: src/bz-window.c:873 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d Laufzeitumgebungen und/oder Erweiterungen haben neue Aktualisierungen " "erhalten. Möchten Sie diese installieren?" #: src/bz-window.c:874 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Zusätzlich werden %d Laufzeitumgebungen und/oder Erweiterungen aktualisiert." #: src/bz-window.c:876 msgid "Update Now" msgstr "Jetzt aktualisieren" #: src/bz-window.c:891 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Die Möglichkeit, lokale .flatpak-Bundle-Dateien zu überprüfen und zu " "installieren, wird in Kürze verfügbar sein!\n" "In der Zwischenzeit können Sie versuchen, folgenden Befehl in der " "Befehlszeile auszuführen:\n" "\n" "flatpak install --bundle dein-bundle.flatpak" #: src/bz-window.c:1030 src/bz-window.c:1080 msgid "Can't do that right now!" msgstr "Das kann momentan nicht getan werden." #: src/bz-window.c:1155 msgid "Resume Current Tasks" msgstr "Die aktuelle Ausgabe fortsetzen" #: src/bz-window.c:1161 msgid "Pause Current Tasks" msgstr "Die aktuelle Aufgabe pausieren" #: src/bz-world-map.c:587 msgid "Downloads" msgstr "Downloads" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Allgemein" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Suchdialog öffnen" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Einstellungen öffnen" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Transaktionsverwaltung umschalten" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Kurzbefehle anzeigen" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Beenden" #~ msgid "Hide EOL Entries" #~ msgstr "EOL-Einträge ausblenden" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "EOL-Einträge und davon abhängige Einträge ausblenden" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Git Forge Sterneanzahl anzeigen" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "" #~ "Ob versucht werden soll, die Sternanzahl für Projekte in der Vollansicht " #~ "anzuzeigen" #~ msgid "Only Show Free Software" #~ msgstr "Nur freie Software anzeigen" #~ msgid "Hide proprietary software" #~ msgstr "Proprietäre Software ausblenden" #~ msgid "Debounce Search Inputs" #~ msgstr "Sucheingaben verzögern" #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "" #~ "Eine Verzögerung hinzufügen, um sofortige Antworten während der Eingabe " #~ "zu verhindern" #~ msgid "Global Progress Bar Theme" #~ msgstr "Globales Fortschrittsbalken-Design" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Beschreibt das Aussehen des globalen Fortschrittsbalkens" #~ msgid "Saved Window Dimensions" #~ msgstr "Gespeicherte Fensterabmessungen" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "" #~ "Die Fensterabmessungen, die vom nächsten Bazaar-Fenster verwendet werden " #~ "sollen" #~ msgid "?" #~ msgstr "?" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s ist für Kleinkinder geeignet" #~ msgid "--- MB" #~ msgstr "--- MB" #~ msgid "Of the size of human DNA" #~ msgstr "Der Größe der menschlichen DNA" #~ msgid "3 billion base pairs" #~ msgstr "3 Milliarden Basenpaare" #~ msgid "Of the Linux Kernel" #~ msgstr "Des Linux Kernels" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "Des Apollo 11 Guidance-Computers" #~ msgid "Total ROM and RAM" #~ msgstr "Gesamt-ROM und RAM" #~ msgid "Of the original Super Mario Bros" #~ msgstr "Des ursprünglichen Super Mario Bros." #~ msgid "On the NES" #~ msgstr "Auf dem NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "Der Größe von Wikipedia" #~ msgid "Without any media" #~ msgstr "Ohne jegliche Medien" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "Diese Funktion ist derzeit nicht freigeschaltet. Es wird empfohlen, " #~ "Flatseal herunterzuladen und zu installieren, um Berechtigungen von " #~ "Anwendungen einzustellen." #~ msgid "Entry Inspector" #~ msgstr "Eintragsinspektor" #~ msgid "Serialize" #~ msgstr "Serialisierung der Anfrage ist fehlgeschlagen" #~ msgid "Convert to JSON" #~ msgstr "In JSON umwandeln" #~ msgid "We ♥ Games" #~ msgstr "Wir ♥ Spiele" #~ msgid "Repository Star Count" #~ msgstr "Repository Sterneanzahl" #~ msgid "Size" #~ msgstr "Größe" #~ msgid "Bazaar Inspector" #~ msgstr "Bazaar-Inspektor" #~ msgid "Active Blocklists" #~ msgstr "Aktive Blocklisten" #~ msgid "Active Curated-Configs" #~ msgstr "Aktive Vorgestellte Einrichtung" #~ msgid "All Entry Groups" #~ msgstr "Alle Eintragsgruppen" #~ msgid "Filter..." #~ msgstr "Filtern ..." #~ msgid "Decache and Inspect" #~ msgstr "Entcachen und Inspizieren" #~ msgid "No Flatpaks Installed" #~ msgstr "Keine Anwendungen installiert" #~ msgid "Application Details" #~ msgstr "Anwendungsdetails" #~ msgid "Display Star Count" #~ msgstr "Sterneanzahl anzeigen" #~ msgid "Open Bazaar Inspector" #~ msgstr "Bazaar-Inspektor öffnen" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %u Downloads" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Aktualisieren" #~ msgid "Hide proprietary software when searching" #~ msgstr "Proprietäre Anwendungen in Suchergebnissen ausblenden" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "" #~ "Suchergebnisse auf Anwendungen beschränken, die auf Flathub verfügbar sind" #~ msgid "Constructing Flatpak instance..." #~ msgstr "Flatpak-Instanz wird erstellt …" #~ msgid "Reusing last Flatpak instance..." #~ msgstr "Letzte Flatpak-Instanz wiederverwenden …" #~ msgid "Flathub is not registered on this system" #~ msgstr "Flathub ist auf diesem System nicht eingerichtet" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "Möchten Sie Flathub hinzufügen? Wenn Sie ablehnen, ist die Flathub-Seite " #~ "nicht verfügbar. Sie können dies später ändern." #~ msgid "Add Flathub" #~ msgstr "Flathub hinzufügen" #~ msgid "Identifying installed entries..." #~ msgstr "Installierte Einträge werden erkannt …" #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d von %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "Warten auf Hintergrund-Indizierung …" #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "Initialisierung in %0.2f Sekunden abgeschlossen" #~ msgid "Verified by the original developers" #~ msgstr "" #~ "Diese Anwendung wurde von den ursprünglichen Entwicklern der Software " #~ "verifiziert." #~ msgid "Manage Addons" #~ msgstr "Erweiterungen verwalten" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "João Victor (Leal)" #~ msgstr "João Victor (Leal)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Léane GRASSER" #~ msgstr "Léane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel Mrówka (Microwave)" #~ msgstr "Marcel Mrówka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "camegone" #~ msgstr "camegone" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "Abfragenbeginn der Gegenstelleneinträge unter Bezugnahme auf %d " #~ "Blockliste(n) …" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Bazaar wurde nicht mit vorgestellten Inhalten eingerichtet. Nehmen Sie " #~ "Kontakt mit den Entwicklern Ihres Betriebssystems auf, um Hilfe zu " #~ "erhalten." #~ msgid "Games" #~ msgstr "Spiele" #~ msgid "Graphics" #~ msgstr "Grafik" #~ msgid "Office" #~ msgstr "Büro" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "Startseite" #~ msgid "Share this application" #~ msgstr "Diese Anwendung teilen" #~ msgid "Excludes shared components" #~ msgstr "Gemeinsame Komponenten ausgeschlossen" #~ msgid "Source code may not be available" #~ msgstr "Der Quellcode ist möglicherweise nicht verfügbar." #~ msgid "Click for details" #~ msgstr "Klicken Sie, um Details anzusehen" #~ msgid "Repositories" #~ msgstr "Repositories" #~ msgid "Open in browser" #~ msgstr "Im Webbrowser öffnen" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "%'d monatliche Downloads" #~ msgid "%B %-d, %Y" #~ msgstr "%B %-d, %Y" #~ msgid "%B %-d" #~ msgstr "%B %-d" #~ msgid "Run this application" #~ msgstr "Diese Anwendung ausführen" #~ msgid "Run" #~ msgstr "Ausführen" #~ msgid "View Store Page" #~ msgstr "Store-Seite anzeigen" #~ msgid "Git Forge Star Counts" #~ msgstr "Git Forge Sterneanzahl" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "" #~ "Wenn Sie keinen GitHub-Token haben, kann dies zu Ratenbegrenzungen führen." #~ msgid "Show Only Flathub Apps" #~ msgstr "Nur Flathub-Anwendungen anzeigen" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "EIne kurze Weile warten, um die Systemlast zu verringern" #~ msgid "Theme" #~ msgstr "Design" #~ msgid "Pride Rainbow Flag" #~ msgstr "Pride-Regenbogenflagge" #~ msgid "Bisexual Flag" #~ msgstr "Bisexuellenflagge" #~ msgid "Asexual Flag" #~ msgstr "Asexuellenflagge" #~ msgid "Share" #~ msgstr "Teilen" #~ msgid "Transactions" #~ msgstr "Aufgaben" #~ msgid "Browse" #~ msgstr "Durchsuchen" #~ msgid "App View" #~ msgstr "Anwendungsansicht" #~ msgid "Go Back" #~ msgstr "Zurück" #~ msgid "View curated applications" #~ msgstr "Vorgestellte Anwendungen ansehen" #~ msgid "View the latest on Flathub" #~ msgstr "Das neueste auf Flathub ansehen" #~ msgid "_Quit Service" #~ msgstr "Dienst _beenden" #~ msgid "Up to date!" #~ msgstr "Auf neuestem Stand" #~ msgid "Settings & user data will be kept" #~ msgstr "Einstellungen und Benutzerdaten werden beibehalten" #~ msgid "Show Animated Background" #~ msgstr "Animierten Hintergrund anzeigen" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Den animierten Hintergrund auf der Startseite anzeigen" #~ msgid "" #~ "It emphasizes supporting the developers who make the Linux desktop " #~ "possible." #~ msgstr "" #~ "Es legt Wert darauf, die Entwickler zu unterstützen, die den Linux-" #~ "Desktop möglich machen." #~ msgid "Calligraphy application page" #~ msgstr "Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "Downloadkurve für Blender" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "%'d Einträge von %'d empfangen (%0.1f Sekunden vergangen)" #~ msgid "Apps Of The Week" #~ msgstr "Anwendungen der Woche" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "Die Anzahl der Downloads in den letzten 30 Tagen. Klicken Sie hier, um " #~ "die Download-Statistiken für diese Anwendung anzuzeigen." #~ msgid "Remote repo name" #~ msgstr "Namen des Repository" #, c-format #~ msgid "Released %x" #~ msgstr "Veröffentlicht %x" #~ msgid "How the application looks" #~ msgstr "Wie die Anwendung aussieht" #~ msgid "Appearance" #~ msgstr "Erscheinungsbild" #~ msgid "Show animated background" #~ msgstr "Animierten Hintergrund anzeigen" #~ msgid "Type to filter" #~ msgstr "Zum Filtern hier tippen" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Ergebnisse mit proprietären Lizenzen ausschließen" #~ msgid "Advanced" #~ msgstr "Erweitert" #~ msgid "Open this link externally" #~ msgstr "Diesen Link extern öffnen" #~ msgid "Downloads Over Time" #~ msgstr "Downloads im Laufe der Zeit" #~ msgid "Minimize Lower Bound" #~ msgstr "Untere Grenze verringern" #~ msgid "Maximize Upper Bound" #~ msgstr "Obere Grenze vergrößern" #~ msgid "Installing" #~ msgstr "Wird installiert" #~ msgid "Updating" #~ msgstr "Wird aktualisiert" #~ msgid "Removing" #~ msgstr "Wird entfernt" #~ msgid "Transactions Will Appear Here" #~ msgstr "Transaktionen werden hier erscheinen" #~ msgid "Halt the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen anhalten" #~ msgid "Clear all finished transactions" #~ msgstr "Alle abgeschlossenen Transaktionen leeren" #~ msgid "Confirm Action" #~ msgstr "Aktion bestätigen" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Sie sind dabei, die folgende Anwendung zu entfernen:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sind Sie sich sicher?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Sie sind dabei, die folgende Anwendung zu installieren:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sind Sie sich sicher?" #~ msgid "Resume the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen fortsetzen" #~ msgid "Pause the execution of transactions" #~ msgstr "Die Ausführung von Transaktionen pausieren" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Bazaar-Hauptfenster zeigt Blender" #~ msgid "Match using regular expressions" #~ msgstr "Übereinstimmung mit regulären Ausdrücken" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "" #~ "Filterung und Sortierung hinter einem Überblendungseffekt verstecken" kolunmi-bazaar-7b9c8e1/po/el.po000066400000000000000000001755671514314607700164650ustar00rootroot00000000000000# Greek translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-12-18 02:22+0200\n" "PO-Revision-Date: 2025-12-18 04:30+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.8\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:234 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Προσθήκη, αφαίρεση ή ενημέρωση λογισμικού flatpak σε αυτόν τον υπολογιστή" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;Σύστημα;Διαχειριστής πακέτων;Ανακάλυψη;Flatpak;Λογισμικό;Κατάστημα;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Απόκρυψη καταχωρήσεων EOL" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Απόκρυψη καταχωρήσεων EOL και καταχωρήσεων που εξαρτώνται από αυτές" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Only Show Free Software" msgstr "Εμφάνιση μόνο δωρεάν λογισμικού" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software" msgstr "Απόκρυψη ιδιόκτητου λογισμικού" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "Εμφάνιση μόνο περιεχομένου Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Hide applications which do not originate from Flathub" msgstr "Απόκρυψη εφαρμογών που δεν προέρχονται από το Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "Αναζήτηση εισόδων χωρίς αναπήδηση" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "" "Προσθέστε μια καθυστέρηση πριν από την αναζήτηση για να αποτρέψετε τις " "άμεσες απαντήσεις κατά την πληκτρολόγηση" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "Global Progress Bar Theme" msgstr "Καθολικό θέμα μπάρας προόδου" #: data/io.github.kolunmi.Bazaar.gschema.xml:47 msgid "Describes the look of the global progress bar" msgstr "Περιγράφει την εμφάνιση της καθολικής μπάρας προόδου" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "Saved Window Dimensions" msgstr "Αποθηκευμένες διαστάσεις παραθύρου" #: data/io.github.kolunmi.Bazaar.gschema.xml:52 msgid "The window dimensions to be used by the next Bazaar window" msgstr "" "Οι διαστάσεις του παραθύρου που θα χρησιμοποιηθούν από το επόμενο παράθυρο " "Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Ανακαλύψτε και εγκαταστήστε εφαρμογές" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Ένα νέο κατάστημα εφαρμογών για το GNOME με έμφαση στην αναζήτηση και " "εγκατάσταση εφαρμογών και πρόσθετων από απομακρυσμένους διακομιστές Flatpak, " "ιδίως το Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Δίνει έμφαση στην υποστήριξη των προγραμματιστών που καθιστούν δυνατή τη " "λειτουργία του Linux desktop. Το Bazaar διαθέτει μια καρτέλα \"curated\" που " "μπορεί να διαμορφωθεί από τους διανομείς ώστε να προσφέρει μια πιο τοπική " "εμπειρία." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Η αρχική σελίδα που εμφανίζει τις εφαρμογές Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Σελίδα εφαρμογής Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Σελίδα αναζήτησης" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Σελίδα κατηγορίας" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:711 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Διαχείριση πρόσθετων" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:502 #: src/bz-installed-tile.blp:117 src/bz-transaction-view.blp:213 #: src/bz-window.c:1294 msgid "Remove" msgstr "Κατάργηση" #: src/bz-addons-dialog.c:95 src/bz-full-view.blp:274 src/bz-full-view.blp:489 #: src/bz-transaction-view.blp:187 src/bz-window.c:1271 msgid "Install" msgstr "Εγκατάσταση" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:50 #: src/bz-full-view.c:373 src/bz-full-view.c:380 msgid "Age Rating" msgstr "Βαθμολογία ηλικίας" #: src/bz-age-rating-dialog.blp:40 src/bz-age-rating-dialog.c:790 msgid "?" msgstr "?" #: src/bz-age-rating-dialog.c:139 msgid "Cartoon Violence" msgstr "Βία στα κινούμενα σχέδια" #: src/bz-age-rating-dialog.c:140 msgid "No information regarding cartoon violence" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με τη βία στα κινούμενα σχέδια" #: src/bz-age-rating-dialog.c:143 msgid "Fantasy Violence" msgstr "Φανταστική βία" #: src/bz-age-rating-dialog.c:144 msgid "No information regarding fantasy violence" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με τη φανταστική βία" #: src/bz-age-rating-dialog.c:147 msgid "Realistic Violence" msgstr "Ρεαλιστική βία" #: src/bz-age-rating-dialog.c:148 msgid "No information regarding realistic violence" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με ρεαλιστική βία" #: src/bz-age-rating-dialog.c:151 msgid "Violence Depicting Bloodshed" msgstr "Βία που απεικονίζει αιματοχυσία" #: src/bz-age-rating-dialog.c:152 msgid "No information regarding bloodshed" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με βία που απεικονίζει αιματοχυσία" #: src/bz-age-rating-dialog.c:155 msgid "Sexual Violence" msgstr "Σεξουαλική βία" #: src/bz-age-rating-dialog.c:156 msgid "No information regarding sexual violence" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με σεξουαλική βία" #: src/bz-age-rating-dialog.c:159 msgid "Alcohol" msgstr "Αλκοόλ" #: src/bz-age-rating-dialog.c:160 msgid "No information regarding references to alcohol" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές στο αλκοόλ" #: src/bz-age-rating-dialog.c:163 msgid "Narcotics" msgstr "Ναρκωτικά" #: src/bz-age-rating-dialog.c:164 msgid "No information regarding references to illicit drugs" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές σε παράνομες ναρκωτικές ουσίες" #: src/bz-age-rating-dialog.c:167 msgid "Tobacco" msgstr "Καπνός" #: src/bz-age-rating-dialog.c:168 msgid "No information regarding references to tobacco products" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές σε προϊόντα καπνού" #: src/bz-age-rating-dialog.c:171 src/bz-age-rating-dialog.c:358 msgid "Nudity" msgstr "Γυμνότητα" #: src/bz-age-rating-dialog.c:172 msgid "No information regarding nudity of any sort" msgstr "Καμία πληροφορία σχετικά με γυμνότητα οποιουδήποτε είδους" #: src/bz-age-rating-dialog.c:175 msgid "Sexual Themes" msgstr "Σεξουαλικά θέματα" #: src/bz-age-rating-dialog.c:176 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές ή απεικονίσεις σεξουαλικού " "χαρακτήρα" #: src/bz-age-rating-dialog.c:179 msgid "Profanity" msgstr "Βωμολοχίες" #: src/bz-age-rating-dialog.c:180 msgid "No information regarding profanity of any kind" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με οποιαδήποτε μορφή βωμολοχίας" #: src/bz-age-rating-dialog.c:183 msgid "Inappropriate Humor" msgstr "Ακατάλληλο χιούμορ" #: src/bz-age-rating-dialog.c:184 msgid "No information regarding inappropriate humor" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με ακατάλληλο χιούμορ" #: src/bz-age-rating-dialog.c:187 msgid "Discrimination" msgstr "Διακρίσεις" #: src/bz-age-rating-dialog.c:188 msgid "No information regarding discriminatory language of any kind" msgstr "Καμία πληροφορία σχετικά με διακριτική γλώσσα οποιουδήποτε είδους" #: src/bz-age-rating-dialog.c:191 msgid "Advertising" msgstr "Διαφήμιση" #: src/bz-age-rating-dialog.c:192 msgid "No information regarding advertising of any kind" msgstr "Καμία πληροφορία σχετικά με διαφημίσεις οποιουδήποτε είδους" #: src/bz-age-rating-dialog.c:195 msgid "Gambling" msgstr "Τυχερά παιχνίδια" #: src/bz-age-rating-dialog.c:196 msgid "No information regarding gambling of any kind" msgstr "Καμία πληροφορία σχετικά με τυχερά παιχνίδια οποιουδήποτε είδους" #: src/bz-age-rating-dialog.c:199 msgid "Purchasing" msgstr "Αγορές" #: src/bz-age-rating-dialog.c:200 msgid "No information regarding the ability to spend money" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με τη δυνατότητα δαπάνης χρημάτων" #: src/bz-age-rating-dialog.c:203 msgid "Chat Between Users" msgstr "Συνομιλία μεταξύ χρηστών" #: src/bz-age-rating-dialog.c:204 msgid "No information regarding ways to chat with other users" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με τους τρόπους επικοινωνίας με άλλους " "χρήστες" #: src/bz-age-rating-dialog.c:207 msgid "Audio Chat Between Users" msgstr "Ηχητική συνομιλία μεταξύ χρηστών" #: src/bz-age-rating-dialog.c:208 msgid "No information regarding ways to talk with other users" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με τους τρόπους επικοινωνίας με άλλους " "χρήστες" #: src/bz-age-rating-dialog.c:211 msgid "Contact Details" msgstr "Στοιχεία επικοινωνίας" #: src/bz-age-rating-dialog.c:212 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με την κοινοποίηση ονομάτων χρήστη " "κοινωνικών δικτύων ή διευθύνσεων ηλεκτρονικού ταχυδρομείου" #: src/bz-age-rating-dialog.c:215 msgid "Identifying Information" msgstr "Πληροφορίες ταυτοποίησης" #: src/bz-age-rating-dialog.c:216 msgid "No information regarding sharing of user information with third parties" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με την κοινοποίηση πληροφοριών χρηστών σε " "τρίτους" #: src/bz-age-rating-dialog.c:219 msgid "Location Sharing" msgstr "Κοινή χρήση τοποθεσίας" #: src/bz-age-rating-dialog.c:220 msgid "No information regarding sharing of physical location with other users" msgstr "" "Δεν υπάρχουν πληροφορίες σχετικά με την κοινοποίηση της φυσικής τοποθεσίας " "σε άλλους χρήστες" #: src/bz-age-rating-dialog.c:223 msgid "Prostitution" msgstr "Πορνεία" #: src/bz-age-rating-dialog.c:224 msgid "No information regarding references to prostitution" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές σε πορνεία" #: src/bz-age-rating-dialog.c:227 msgid "Adultery" msgstr "Μοιχεία" #: src/bz-age-rating-dialog.c:228 msgid "No information regarding references to adultery" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές σε μοιχεία" #: src/bz-age-rating-dialog.c:231 msgid "Sexualized Characters" msgstr "Σεξουαλικοποιημένοι χαρακτήρες" #: src/bz-age-rating-dialog.c:232 msgid "No information regarding sexualized characters" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με Σεξουαλικοποιημένους χαρακτήρες" #: src/bz-age-rating-dialog.c:235 msgid "Desecration" msgstr "Βεβήλωση" #: src/bz-age-rating-dialog.c:236 msgid "No information regarding references to desecration" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές σε βεβήλωση" #: src/bz-age-rating-dialog.c:239 msgid "Human Remains" msgstr "Ανθρώπινα λείψανα" #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με ορατά ανθρώπινα λείψανα" #: src/bz-age-rating-dialog.c:243 msgid "Slavery" msgstr "Δουλεία" #: src/bz-age-rating-dialog.c:244 msgid "No information regarding references to slavery" msgstr "Δεν υπάρχουν πληροφορίες σχετικά με αναφορές στη δουλεία" #: src/bz-age-rating-dialog.c:307 msgid "Does not include references to drugs" msgstr "Δεν περιλαμβάνει αναφορές σε φάρμακα" #: src/bz-age-rating-dialog.c:309 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "Δεν περιλαμβάνει βρισιές, χυδαίες εκφράσεις και άλλα είδη σκληρής γλώσσας" #: src/bz-age-rating-dialog.c:311 msgid "Does not include ads or monetary transactions" msgstr "Δεν περιλαμβάνει διαφημίσεις ή χρηματικές συναλλαγές" #: src/bz-age-rating-dialog.c:313 msgid "Does not include sex or nudity" msgstr "Δεν περιλαμβάνει σεξ ή γυμνότητα" #: src/bz-age-rating-dialog.c:315 msgid "Does not include uncontrolled chat functionality" msgstr "Δεν περιλαμβάνει λειτουργία ανεξέλεγκτης συνομιλίας" #: src/bz-age-rating-dialog.c:317 msgid "Does not include violence" msgstr "Δεν περιλαμβάνει βία" #: src/bz-age-rating-dialog.c:352 msgid "Drugs" msgstr "Ναρκωτικά" #: src/bz-age-rating-dialog.c:354 msgid "Strong Language" msgstr "Σκληρή γλώσσα" #: src/bz-age-rating-dialog.c:356 msgid "Money" msgstr "Χρήματα" #: src/bz-age-rating-dialog.c:360 msgid "Social" msgstr "Κοινωνικά" #: src/bz-age-rating-dialog.c:362 msgid "Violence" msgstr "Βία" #: src/bz-age-rating-dialog.c:564 #, c-format msgid "%s • %s" msgstr "%s • %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:752 src/bz-full-view.c:363 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:782 msgctxt "Age rating" msgid "All" msgstr "Όλα" #: src/bz-age-rating-dialog.c:846 #, c-format msgid "%s has an unknown age rating" msgstr "Το %s έχει άγνωστη ηλικιακή βαθμολογία" #: src/bz-age-rating-dialog.c:854 #, c-format msgid "%s is suitable for everyone" msgstr "Το %s είναι κατάλληλο για όλους" #: src/bz-age-rating-dialog.c:857 #, c-format msgid "%s is suitable for toddlers" msgstr "Το %s είναι κατάλληλο για νήπια" #: src/bz-age-rating-dialog.c:860 #, c-format msgid "%s is suitable for young children" msgstr "Το %s είναι κατάλληλο για μικρά παιδιά" #: src/bz-age-rating-dialog.c:863 #, c-format msgid "%s is suitable for children" msgstr "Το %s είναι κατάλληλο για παιδιά" #: src/bz-age-rating-dialog.c:866 #, c-format msgid "%s is suitable for teenagers" msgstr "Το %s είναι κατάλληλο για εφήβους" #: src/bz-age-rating-dialog.c:869 #, c-format msgid "%s is suitable for adults" msgstr "Το %s είναι κατάλληλο για ενήλικες" #: src/bz-age-rating-dialog.c:872 #, c-format msgid "%s is suitable for %s" msgstr "Το %s είναι κατάλληλο για %s" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Μέγεθος λήψης" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Του μεγέθους του ανθρώπινου DNA" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 δισεκατομμύρια ζεύγη βάσεων" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "Του πυρήνα Linux" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "Του υπολογιστή πλοήγησης του Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "Συνολική ROM και RAM" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "Από το αρχικό Super Mario Bros" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "Στο NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "Του μεγέθους της Wikipedia" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Χωρίς κανένα πολυμέσο" #: src/bz-app-tile.blp:84 src/bz-installed-page.blp:25 src/bz-window.blp:298 msgid "Installed" msgstr "Εγκατεστημένες" #: src/bz-apps-page.blp:14 src/bz-full-view.blp:43 src/bz-user-data-page.blp:15 #: src/bz-window.blp:443 msgid "Main Menu" msgstr "Κύριο μενού" #: src/bz-apps-page.blp:17 src/bz-user-data-page.blp:18 src/bz-window.blp:522 msgid "_Donate to Bazaar ❤️" msgstr "_Δωρίστε στο Bazaar ❤️" #: src/bz-apps-page.blp:18 src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Ανανέωση περιεχομένου" #: src/bz-apps-page.blp:22 src/bz-user-data-page.blp:22 src/bz-window.blp:529 msgid "_Preferences" msgstr "_Προτιμήσεις" #: src/bz-apps-page.blp:23 src/bz-user-data-page.blp:23 src/bz-window.blp:550 msgid "_Keyboard Shortcuts" msgstr "_Συντομεύσεις πληκτρολογίου" #: src/bz-apps-page.blp:24 src/bz-user-data-page.blp:24 src/bz-window.blp:555 msgid "_About Bazaar" msgstr "_Σχετικά με το Bazaar" #: src/bz-apps-page.blp:28 src/bz-user-data-page.blp:27 src/bz-window.blp:562 msgid "_Quit Bazaar" msgstr "_Κλείστε το Bazaar" #: src/bz-application.c:577 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Αυτή η λειτουργία είναι προς το παρόν απενεργοποιημένη. Συνιστάται να " "κατεβάσετε και να εγκαταστήσετε το Flatseal για να διαχειριστείτε τις άδειες " "της εφαρμογής." #: src/bz-application.c:659 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:660 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #: src/bz-application.c:682 msgid "Adam Masciola" msgstr "Adam Masciola" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:685 msgid "translator-credits" msgstr "Xarishark-Zacharias Xenakis" #: src/bz-application.c:749 msgid "Logged Out Successfully!" msgstr "Αποσύνδεση με επιτυχία!" #: src/bz-application.c:855 msgid "Performing setup..." msgstr "Εκτέλεση εγκατάστασης..." #: src/bz-application.c:934 src/bz-application.c:943 msgid "Set Up Flathub" msgstr "Ρύθμιση του Flathub" #: src/bz-application.c:937 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Το Flathub δεν είναι εγκατεστημένο σε αυτό το σύστημα. Δεν θα μπορείτε να " "περιηγηθείτε και να εγκαταστήσετε εφαρμογές στο Bazaar εάν δεν είναι " "διαθέσιμο.\n" "\n" "Μπορείτε ακόμα να χρησιμοποιήσετε το Bazaar για να περιηγηθείτε και να " "καταργήσετε ήδη εγκατεστημένες εφαρμογές." #: src/bz-application.c:942 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Αργότερα" #: src/bz-application.c:1344 msgid "Synchronizing..." msgstr "Συγχρονισμός..." #: src/bz-application.c:1483 #, c-format msgid "Receiving %d entries..." msgstr "Λήψη %d καταχωρήσεων..." #: src/bz-application.c:1488 msgid "Checking for updates" msgstr "Έλεγχος για ενημερώσεις" #: src/bz-curated-view.blp:11 src/bz-flathub-page.blp:19 #: src/bz-full-view.blp:53 src/bz-installed-page.blp:15 #: src/bz-user-data-page.blp:52 src/bz-window.blp:183 msgid "Empty" msgstr "Άδειο" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Χωρίς επιμέλεια" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Δεν παρέχονται πληροφορίες σχετικά με την επιμέλεια σε αυτό το σύστημα. " "Μπορείτε να συνεχίσετε να περιηγείστε στις εφαρμογές στο Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Περιήγηση στο Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Εκτός σύνδεσης" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Πρόγραμμα περιήγησης" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Οι πληροφορίες για τον προγραμματιστή δεν είναι διαθέσιμες." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Η ιδιοκτησία του αναγνωριστικού εφαρμογής %s δεν έχει επαληθευτεί και " "ενδέχεται να πρόκειται για πακέτο κοινότητας." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Η ιδιοκτησία του αναγνωριστικού εφαρμογής %s έχει επαληθευτεί χειροκίνητα " "από την ομάδα του Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %s app ID has been verified by %s on %s." msgstr "" "Η ιδιοκτησία του αναγνωριστικού εφαρμογής %s έχει επαληθευτεί από τον %s στις %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %s app ID has been verified using %s." msgstr "" "Η ιδιοκτησία του αναγνωριστικού εφαρμογής %s έχει επαληθευτεί " "χρησιμοποιώντας το %s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Η ιδιοκτησία του αναγνωριστικού εφαρμογής %s έχει επαληθευτεί." #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Επιθεωρητής εισόδου" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Σειριοποίηση" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Μετατροπή σε JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Παρουσιάστηκε σφάλμα" #: src/bz-error.c:89 msgid "Close" msgstr "Κλείσιμο" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Αντιγραφή και κλείσιμο" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Προηγούμενο" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Επόμενο" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Εφαρμογή της ημέρας" #: src/bz-flathub-category.c:78 msgid "Audio & Video" msgstr "Ήχος & Βίντεο" #: src/bz-flathub-category.c:78 msgid "Media" msgstr "Πολυμέσα" #: src/bz-flathub-category.c:78 msgid "More Audio & Video" msgstr "Περισσότερα Ήχος & Βίντεο" #: src/bz-flathub-category.c:79 msgid "Developer Tools" msgstr "Εργαλεία προγραμματιστή" #: src/bz-flathub-category.c:79 msgid "Develop" msgstr "Προγραμματισμός" #: src/bz-flathub-category.c:79 msgid "More Developer Tools" msgstr "Περισσότερα εργαλεία προγραμματιστή" #: src/bz-flathub-category.c:80 msgid "Education" msgstr "Εκπαίδευση" #: src/bz-flathub-category.c:80 msgid "Learn" msgstr "Μάθηση" #: src/bz-flathub-category.c:80 msgid "More Education" msgstr "Περισσότερη Μάθηση" #: src/bz-flathub-category.c:81 msgid "Gaming" msgstr "Παιχνίδια" #: src/bz-flathub-category.c:81 msgid "Play" msgstr "Παιχνίδι" #: src/bz-flathub-category.c:81 msgid "More Gaming" msgstr "Περισσότερα παιχνίδια" #: src/bz-flathub-category.c:82 msgid "Graphics & Photography" msgstr "Γραφικά & Φωτογραφία" #: src/bz-flathub-category.c:82 msgid "Create" msgstr "Δημιουργία" #: src/bz-flathub-category.c:82 msgid "More Graphics & Photography" msgstr "Περισσότερα Γραφικά & Φωτογραφία" #: src/bz-flathub-category.c:83 msgid "Networking" msgstr "Δικτύωση" #: src/bz-flathub-category.c:83 msgid "Internet" msgstr "Διαδίκτυο" #: src/bz-flathub-category.c:83 msgid "More Networking" msgstr "Περισσότερη Δικτύωση" #: src/bz-flathub-category.c:84 msgid "Productivity" msgstr "Παραγωγικότητα" #: src/bz-flathub-category.c:84 msgid "Work" msgstr "Εργασία" #: src/bz-flathub-category.c:84 msgid "More Productivity" msgstr "Περισσότερη Παραγωγικότητα" #: src/bz-flathub-category.c:85 msgid "Science" msgstr "Επιστήμη" #: src/bz-flathub-category.c:85 msgid "More Science" msgstr "Περισσότερη Επιστήμη" #: src/bz-flathub-category.c:86 msgid "System" msgstr "Σύστημα" #: src/bz-flathub-category.c:86 msgid "More System" msgstr "Περισσότερο Σύστημα" #: src/bz-flathub-category.c:87 msgid "Utilities" msgstr "Βοηθητικά προγράμματα" #: src/bz-flathub-category.c:87 msgid "Tools" msgstr "Εργαλεία" #: src/bz-flathub-category.c:87 msgid "More Utilities" msgstr "Περισσότερα βοηθητικά προγράμματα" #: src/bz-flathub-category.c:88 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Τάσεις" #: src/bz-flathub-category.c:88 msgid "More Trending" msgstr "Περισσότερες Τάσεις" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Δημοφιλείς" #: src/bz-flathub-category.c:89 msgid "More Popular" msgstr "Περισσότερα Δημοφιλή" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Πρόσφατα Προστέθηκαν" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:131 msgid "New" msgstr "Νέες" #: src/bz-flathub-category.c:90 msgid "More New" msgstr "Περισσότερες Νέες" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Πρόσφατα Ενημερωμένες" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Ενημερωμένες" #: src/bz-flathub-category.c:91 msgid "More Updated" msgstr "Περισσότερες Ενημερωμένες" #: src/bz-flathub-category.c:92 msgid "Mobile" msgstr "Κινητό" #: src/bz-flathub-category.c:92 msgid "More Mobile" msgstr "Περισσότερα για κινητό" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Το Flathub δεν έχει προστεθεί" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "O απομακρυσμένος διακομιστής Flathub δεν βρέθηκε σε καμία από τις " "εγκαταστάσεις Flatpak σας" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Το Flathub επέστρεψε ένα σφάλμα" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Επανάληψη σύνδεσης με το Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Το Flathub δεν είναι διαθέσιμο" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Δεν μπορέσαμε να συνδεθούμε στο Flathub. Μπορείτε ακόμα να διαχειριστείτε " "και να αναζητήσετε εφαρμογές." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Αναζήτηση εφαρμογών" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Εν κινήσει" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Εφαρμογές για τα τηλέφωνα και τα tablet σας με Linux" #: src/bz-flathub-page.blp:293 msgid "More Mobile Apps" msgstr "Περισσότερες εφαρμογές για κινητά" #: src/bz-flathub-page.blp:328 msgid "More Mobile apps" msgstr "Περισσότερες εφαρμογές για κινητά" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "♥ τα παιχνίδια" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Παιχνίδια και εφαρμογές για να τρέξετε τους αγαπημένους σας τίτλους" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Περισσότερα παιχνίδια" #: src/bz-flatpak-entry.c:600 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Σελίδα Flathub" #: src/bz-flatpak-entry.c:621 msgctxt "Project URL Type" msgid "Project Website" msgstr "Ιστοσελίδα του έργου" #: src/bz-flatpak-entry.c:625 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Παρακολούθηση ζητημάτων" #: src/bz-flatpak-entry.c:629 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Help" msgstr "Βοήθεια" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "Donate" msgstr "Δωρεά" #: src/bz-flatpak-entry.c:643 msgctxt "Project URL Type" msgid "Translate" msgstr "Μετάφραση" #: src/bz-flatpak-entry.c:647 msgctxt "Project URL Type" msgid "Contact" msgstr "Επικοινωνία" #: src/bz-flatpak-entry.c:651 msgctxt "Project URL Type" msgid "Source Code" msgstr "Πηγαίος κώδικας" #: src/bz-flatpak-entry.c:657 msgctxt "Project URL Type" msgid "Contribute" msgstr "Συνεισφέρετε" #: src/bz-full-view.blp:20 src/bz-window.blp:126 src/bz-window.blp:420 msgid "Toggle transaction sidebar" msgstr "Εναλλαγή πλευρικής γραμμής συναλλαγών" #: src/bz-full-view.blp:57 msgid "No Results" msgstr "Κανένα αποτέλεσμα" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Δοκιμάστε μια διαφορετική αναζήτηση" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Περιεχόμενο" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Υποστήριξη" #: src/bz-full-view.blp:226 msgid "Favorite Count" msgstr "Αριθμός αγαπημένων" #: src/bz-full-view.blp:258 src/bz-full-view.blp:513 msgid "Open" msgstr "Ανοιχτό" #: src/bz-full-view.blp:271 src/bz-full-view.blp:486 msgid "Download & Install Application" msgstr "Λήψη και εγκατάσταση εφαρμογής" #: src/bz-full-view.blp:286 msgid "Uninstall Application" msgstr "Απεγκατάσταση εφαρμογής" #: src/bz-full-view.blp:301 src/bz-full-view.blp:528 msgid "Install Other Version" msgstr "Εγκατάσταση άλλης έκδοσης" #: src/bz-full-view.blp:325 msgid "Size" msgstr "Μέγεθος" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "Λήψεις /mo" #: src/bz-full-view.blp:547 msgid "Stopped Receiving Core Updates" msgstr "Δεν λαμβάνετε πλέον βασικές ενημερώσεις" #: src/bz-full-view.blp:561 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Αυτή η εφαρμογή χρησιμοποιεί ένα περιβάλλον εκτέλεσης που δεν λαμβάνει πλέον " "ενημερώσεις ή διορθώσεις ασφαλείας. Η χρήση της ενδέχεται να μην είναι " "ασφαλής." #: src/bz-full-view.blp:644 src/bz-window.c:1240 msgid "Delete Data" msgstr "Διαγραφή δεδομένων" #: src/bz-full-view.blp:778 msgid "Tags:" msgstr "Ετικέτες:" #: src/bz-full-view.c:289 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:296 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:303 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:313 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d λήψεις τις τελευταίες 30 ημέρες" #: src/bz-full-view.c:345 #, c-format msgid "Download size of %s" msgstr "Μέγεθος λήψης του %s" #: src/bz-full-view.c:378 msgid "All Ages" msgstr "Όλες οι ηλικίες" #: src/bz-full-view.c:390 msgid "Age rating information unavailable" msgstr "Πληροφορίες σχετικά με την ηλικιακή βαθμολογία δεν είναι διαθέσιμες" #: src/bz-full-view.c:395 msgid "Suitable for all ages" msgstr "Κατάλληλο για όλες τις ηλικίες" #: src/bz-full-view.c:397 #, c-format msgid "Suitable for ages %d and up" msgstr "Κατάλληλο για ηλικίες %d και άνω" #: src/bz-full-view.c:430 src/bz-full-view.c:435 src/bz-full-view.c:463 #: src/bz-full-view.c:474 msgid "Unknown" msgstr "Άγνωστο" #: src/bz-full-view.c:440 #, c-format msgid "Free software licensed under %s" msgstr "Ελεύθερο λογισμικό με άδεια χρήσης %s" #: src/bz-full-view.c:445 msgid "Free software" msgstr "Ελεύθερο λογισμικό" #: src/bz-full-view.c:448 msgid "Proprietary Software" msgstr "Ιδιόκτητο λογισμικό" #: src/bz-full-view.c:451 #, c-format msgid "Special License: %s" msgstr "Ειδική άδεια: %s" #: src/bz-full-view.c:468 msgid "Free" msgstr "Ελεύθερο" #: src/bz-full-view.c:471 src/bz-license-dialog.c:118 msgid "Proprietary" msgstr "Ιδιόκτητο" #: src/bz-full-view.c:476 src/bz-license-dialog.c:120 msgid "Special License" msgstr "Ειδική άδεια" #: src/bz-full-view.c:496 msgid "Adaptive" msgstr "Προσαρμοστικό" #: src/bz-full-view.c:496 msgid "Desktop Only" msgstr "Μόνο για επιτραπέζιους υπολογιστές" #: src/bz-full-view.c:502 msgid "Works on desktop, tablets, and phones" msgstr "Λειτουργεί σε επιτραπέζιους υπολογιστές, tablet και κινητά τηλέφωνα" #: src/bz-full-view.c:503 msgid "May not work on mobile devices" msgstr "Ενδέχεται να μην λειτουργεί σε κινητές συσκευές" #: src/bz-full-view.c:514 msgid "No URL" msgstr "Χωρίς διεύθυνση URL" #: src/bz-full-view.c:532 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Αυτή η εφαρμογή διαθέτει άδεια FLOSS, που σημαίνει ότι ο πηγαίος κώδικας " "μπορεί να ελεγχθεί για λόγους ασφαλείας." #: src/bz-full-view.c:533 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Αυτή η εφαρμογή διαθέτει ιδιόκτητη άδεια χρήσης, που σημαίνει ότι ο πηγαίος " "κώδικας έχει αναπτυχθεί ιδιωτικά και δεν μπορεί να ελεγχθεί από ανεξάρτητο " "τρίτο μέρος." #: src/bz-full-view.c:540 msgid "More Apps" msgstr "Περισσότερες εφαρμογές" #: src/bz-full-view.c:541 #, c-format msgid "More Apps by %s" msgstr "Περισσότερες εφαρμογές από %s" #: src/bz-full-view.c:548 msgid "Other Apps by this Developer" msgstr "Άλλες εφαρμογές από αυτόν τον προγραμματιστή" #: src/bz-full-view.c:550 src/bz-full-view.c:658 #, c-format msgid "Other Apps by %s" msgstr "Άλλες εφαρμογές από %s" #: src/bz-full-view.c:558 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "Το %s δεν είναι εγκατεστημένο, αλλά εξακολουθεί να περιέχει %s " "δεδομένων." #: src/bz-full-view.c:660 msgid "Other Apps" msgstr "Άλλες εφαρμογές" #: src/bz-full-view.c:662 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Εφαρμογή" msgstr[1] "%d Εφαρμογές" #: src/bz-full-view.c:1010 msgid "Show Less" msgstr "Εμφάνιση λιγότερων" #: src/bz-full-view.c:1010 msgid "Show More" msgstr "Εμφάνιση περισσότερων" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Υποστήριξη υλικού" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Υποστήριξη πληκτρολογίου" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Απαιτεί πληκτρολόγια" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Συνιστά πληκτρολόγια" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Υποστηρίζει πληκτρολόγια" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Άγνωστη υποστήριξη για πληκτρολόγια" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Υποστήριξη ποντικιού" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Απαιτεί ποντίκια ή συσκευές κατάδειξης" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Συνιστά ποντίκια ή συσκευές κατάδειξης" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Υποστηρίζει ποντίκια ή συσκευές κατάδειξης" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Άγνωστη υποστήριξη για ποντίκια ή συσκευές κατάδειξης" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Υποστήριξη οθόνης αφής" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Απαιτεί οθόνες αφής" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Συνιστά οθόνες αφής" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Υποστηρίζει οθόνες αφής" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Άγνωστη υποστήριξη για οθόνες αφής" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Υποστήριξη για κινητά" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Λειτουργεί σε κινητές συσκευές" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Μπορεί να μην λειτουργεί καλά σε κινητές συσκευές" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Υποστήριξη επιτραπέζιων υπολογιστών" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Λειτουργεί καλά σε μεγάλες οθόνες" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "Το %s λειτουργεί καλύτερα σε συγκεκριμένο υλικό" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "Το %s λειτουργεί στις περισσότερες συσκευές" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Επιθεωρητής Bazaar" #: src/bz-inspector.blp:33 msgid "Background Task Info:" msgstr "Πληροφορίες για την εργασία παρασκηνίου:" #: src/bz-inspector.blp:43 msgid "Enable Global Debug Mode" msgstr "Ενεργοποίηση καθολικής λειτουργίας αποσφαλμάτωσης" #: src/bz-inspector.blp:50 msgid "Active Blocklists" msgstr "Ενεργές λίστες αποκλεισμένων" #: src/bz-inspector.blp:67 msgid "Active Curated-Configs" msgstr "Ενεργές Επιμελημένες-Ρυθμίσεις" #: src/bz-inspector.blp:85 msgid "All Entry Groups" msgstr "Όλες οι ομάδες εισόδου" #: src/bz-inspector.blp:93 msgid "Filter..." msgstr "Φίλτρο..." #: src/bz-inspector.blp:134 msgid "Decache and Inspect" msgstr "Καθαρισμός cache και Έλεγχος" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Δεν έχουν εγκατασταθεί Flatpaks" #: src/bz-installed-page.c:395 msgid "Choose an Installation" msgstr "Επιλέξτε μια εγκατάσταση" #: src/bz-installed-page.c:398 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "Έχετε εγκαταστήσει πολλές εκδόσεις αυτής της εφαρμογής. Με ποια από αυτές " "θέλετε να συνεχίσετε; " #: src/bz-installed-page.c:402 src/bz-window.c:1270 src/bz-window.c:1293 msgid "Cancel" msgstr "Ακύρωση" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Δεν λαμβάνετε πλέον ενημερώσεις" #: src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Υποστηρίξτε αυτήν την εφαρμογή" #: src/bz-license-dialog.blp:160 msgid "Get Involved" msgstr "Συμμετέχε" #: src/bz-license-dialog.c:107 src/bz-license-dialog.c:112 msgid "Unknown License" msgstr "Άγνωστη άδεια χρήσης" #: src/bz-license-dialog.c:115 msgid "Community Built" msgstr "Δημιουργήθηκε από την Κοινότητα" #: src/bz-license-dialog.c:148 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Αυτή η εφαρμογή έχει αναπτυχθεί ανοιχτά από μια διεθνή κοινότητα και " "διατίθεται με άδεια χρήσης %s.\n" "\n" "Μπορείτε να συμμετάσχετε και να βοηθήσετε να γίνει ακόμα καλύτερη." #: src/bz-license-dialog.c:156 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Αυτή η εφαρμογή έχει αναπτυχθεί ανοιχτά από μια διεθνή κοινότητα.\n" "\n" "Μπορείτε να συμμετάσχετε και να βοηθήσετε να γίνει ακόμα καλύτερη." #: src/bz-license-dialog.c:161 msgid "The license of this app is not known" msgstr "Η άδεια χρήσης αυτής της εφαρμογής δεν είναι γνωστή" #: src/bz-license-dialog.c:165 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Αυτή η εφαρμογή δεν έχει αναπτυχθεί ανοιχτά, επομένως μόνο οι " "προγραμματιστές της γνωρίζουν πώς λειτουργεί. Μπορεί να είναι ανασφαλής με " "τρόπους που είναι δύσκολο να εντοπιστούν και μπορεί να αλλάξει χωρίς " "εποπτεία.\n" "\n" "Μπορεί να έχετε ή να μην έχετε τη δυνατότητα να συνεισφέρετε σε αυτήν την " "εφαρμογή." #: src/bz-license-dialog.c:174 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Αυτή η εφαρμογή έχει αναπτυχθεί με την ειδική άδεια %s.\n" "\n" "Μπορεί να έχετε ή να μην έχετε τη δυνατότητα να συνεισφέρετε σε αυτήν την " "εφαρμογή." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Προτιμήσεις" #: src/bz-preferences-dialog.blp:23 msgid "Content Filters" msgstr "Φίλτρα περιεχομένου" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Μόνο ελεύθερο λογισμικό" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications when browsing and searching" msgstr "Απόκρυψη ιδιόκτητων εφαρμογών κατά την περιήγηση και την αναζήτηση" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Αποτελέσματα μόνο από το Flathub" #: src/bz-preferences-dialog.blp:32 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Περιορίστε τα αποτελέσματα αναζήτησης και περιήγησης σε εφαρμογές που είναι " "διαθέσιμες μόνο στο Flathub" #: src/bz-preferences-dialog.blp:36 msgid "Hide EOL Apps" msgstr "Απόκρυψη εφαρμογών EOL" #: src/bz-preferences-dialog.blp:37 msgid "Hide apps which are no longer supported by their developers" msgstr "" "Απόκρυψη εφαρμογών που δεν υποστηρίζονται πλέον από τους προγραμματιστές τους" #: src/bz-preferences-dialog.blp:42 src/bz-window.blp:313 msgid "Search" msgstr "Αναζήτηση" #: src/bz-preferences-dialog.blp:45 msgid "Delay Search Results" msgstr "Αναβολή αποτελεσμάτων αναζήτησης" #: src/bz-preferences-dialog.blp:46 msgid "Improve results performance by debouncing search terms" msgstr "" "Βελτιώστε την απόδοση των αποτελεσμάτων με την απομάκρυνση των όρων " "αναζήτησης" #: src/bz-preferences-dialog.blp:51 msgid "Progress Bar" msgstr "Μπάρα προόδου" #: src/bz-preferences-dialog.blp:52 msgid "Choose a theme for the progress bar!" msgstr "Επιλέξτε ένα θέμα για τη μπάρα προόδου!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Χρώμα έμφασης" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Χρώματα υπερηφάνειας" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Χρώματα Υπερηφάνειας Λεσβιών" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Χρώματα Υπερηφάνειας Τρανς" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Χρώματα Υπερηφάνειας Nonbinary" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Χρώματα Υπερηφάνειας Bisexual" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Χρώματα Υπερηφάνειας Asexual" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "Χρώματα Υπερηφάνειας Pansexual" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Χρώματα Υπερηφάνειας Aromantic" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Χρώματα Υπερηφάνειας Genderfluid" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Χρώματα Υπερηφάνειας Polysexual" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Χρώματα Υπερηφάνειας Omnisexual" #: src/bz-preferences-dialog.c:44 msgid "Aroace Pride Colors" msgstr "Χρώματα Υπερηφάνειας Aroace" #: src/bz-preferences-dialog.c:45 msgid "Agender Pride Colors" msgstr "Χρώματα Υπερηφάνειας Agender" #: src/bz-preferences-dialog.c:46 msgid "Genderqueer Pride Colors" msgstr "Χρώματα Υπερηφάνειας Genderqueer" #: src/bz-preferences-dialog.c:47 msgid "Intersex Pride Colors" msgstr "Χρώματα Υπερηφάνειας Intersex" #: src/bz-preferences-dialog.c:48 msgid "Demigender Pride Colors" msgstr "Χρώματα Υπερηφάνειας Demigender" #: src/bz-preferences-dialog.c:49 msgid "Biromantic Pride Colors" msgstr "Χρώματα Υπερηφάνειας Biromantic" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "Ιστορικό εκδόσεων" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "Έκδοση %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "Δεν υπάρχουν λεπτομέρειες για αυτήν την έκδοση" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Λήψη" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Στιγμιότυπα οθόνης" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Προηγούμενο στιγμιότυπο οθόνης" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Επόμενο στιγμιότυπο οθόνης" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Αντιγραφή εικόνας" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Επαναφορά προβολής" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Σμίκρυνση" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Μεγέθυνση" #: src/bz-screenshots-carousel.blp:6 msgid "Screenshots Carousel" msgstr "Καρουζέλ Στιγμιότυπων Οθόνης" #: src/bz-screenshots-carousel.blp:104 msgid "Open Screenshot Viewer" msgstr "Άνοιγμα προγράμματος προβολής στιγμιότυπων οθόνης" #: src/bz-search-widget.blp:106 msgid "Search Apps, Games, Software" msgstr "Αναζήτηση εφαρμογών, παιχνιδιών, λογισμικού" #: src/bz-search-widget.blp:150 msgid "Categories Unavailable" msgstr "Κατηγορίες Μη διαθέσιμες" #: src/bz-search-widget.blp:151 msgid "Search for apps using the search bar above." msgstr "Αναζητήστε εφαρμογές χρησιμοποιώντας τη γραμμή αναζήτησης παραπάνω." #: src/bz-search-widget.blp:235 msgid "No Applications Found" msgstr "Δεν βρέθηκαν εφαρμογές" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Δεν βρέθηκαν αποτελέσματα για το \"%s\" στο Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Αντιγράφηκε!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Αντιγραφή συνδέσμου" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Άνοιγμα συνδέσμου" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Χρονοδιάγραμμα" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Εγκαταστάσεις:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Κόσμος" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Δεν βρέθηκαν αποτελέσματα" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Εφαρμογές με ετικέτα \"%s\"" #: src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Εφαρμογές" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Η αναζήτηση απέτυχε" #: src/bz-transaction-manager.c:1135 #, c-format msgid "Finished in %.02f seconds" msgstr "Ολοκληρώθηκε σε %.02f δευτερόλεπτα" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Πρόσθετο εφαρμογής" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Περιβάλλον εκτέλεσης" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Μέγεθος εγκατάστασης" #: src/bz-transaction-view.blp:200 msgid "Update" msgstr "Ενημέρωση" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Μεταφέρθηκαν %s μέχρι τώρα" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Σε εκκρεμότητα" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Εγκατάσταση τώρα" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Διατίθενται ενημερώσεις" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Οι ακόλουθες εφαρμογές είναι επιλέξιμες για ενημερώσεις. Θέλετε να τις " "εγκαταστήσετε;" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d περιβάλλοντα εκτέλεσης και/ή πρόσθετα είναι επιλέξιμα για ενημερώσεις. " "Θέλετε να τα εγκαταστήσετε;" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Επιπλέον, θα ενημερωθούν %d περιβάλλοντα εκτέλεσης και/ή πρόσθετα." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Διαχείριση υπολειπόμενων δεδομένων χρήστη" #: src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Φόρτωση" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Δεν βρέθηκαν δεδομένα χρήστη" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Δεδομένα χρήστη" #: src/bz-user-data-tile.c:144 #, c-format msgid "Removed User Data for %s" msgstr "Διαγράφηκαν τα δεδομένα χρήστη για %s" #: src/bz-user-data-tile.blp:74 msgid "Remove User Data" msgstr "Κατάργηση δεδομένων χρήστη" #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Επιθεώρηση εισόδου UI" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "Όλες οι ενέργειες εντοπισμού σφαλμάτων" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Εργασίες" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Διακοπή ενεργών εργασιών" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Εκκαθάριση ιστορικού" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Δεν υπάρχουν ακόμη εργασίες" #: src/bz-window.blp:258 msgid "Refreshing Store Content" msgstr "Ανανέωση περιεχομένου καταστήματος" #: src/bz-window.blp:273 msgid "Curated" msgstr "Επιμελημένες" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:450 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Η σύνδεση δικτύου μετράται — η αυτόματη συγχρονισμός δεδομένων του " "καταστήματος έχει παυθεί" #: src/bz-window.blp:451 src/bz-window.blp:460 msgid "Sync Manually" msgstr "Χειροκίνητος συγχρονισμός" #: src/bz-window.blp:459 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Έχετε σύνδεση στο δίκτυο, αλλά βλέπετε μια προσωρινά αποθηκευμένη έκδοση του " "Flathub" #: src/bz-window.blp:534 msgid "_Login with Flathub" msgstr "_Σύνδεση με το Flathub" #: src/bz-window.blp:540 msgid "_Manage Leftover User Data" msgstr "_Διαχείριση υπολειπόμενων δεδομένων χρήστη" #: src/bz-window.blp:545 msgid "_Synchronize Remotes" msgstr "_Συγχρονισμός απομακρυσμένου διακομιστής" #: src/bz-window.blp:571 msgid "Open Bazaar Inspector" msgstr "Άνοιγμα Επιθεωρητή Bazaar" #: src/bz-window.blp:580 msgid "Log Out" msgstr "Αποσύνδεση" #: src/bz-window.c:475 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d Διαθέσιμη ενημέρωση" msgstr[1] "%d Διαθέσιμες ενημερώσεις" #: src/bz-window.c:973 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Η δυνατότητα ελέγχου και εγκατάστασης τοπικών αρχείων πακέτων .flatpak θα " "είναι διαθέσιμη σύντομα! Εν τω μεταξύ, δοκιμάστε να εκτελέσετε την εντολή\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "στη γραμμή εντολών." #: src/bz-window.c:1100 msgid "Can't do that right now!" msgstr "Δεν μπορεί να γίνει αυτή τη στιγμή!" #: src/bz-window.c:1231 msgid "Keep Data" msgstr "Διατήρηση δεδομένων" #: src/bz-window.c:1232 msgid "Allow restoring settings and content" msgstr "Επιτρέψτε την επαναφορά ρυθμίσεων και περιεχομένου" #: src/bz-window.c:1241 msgid "Permanently remove app data to save space" msgstr "Διαγράψτε μόνιμα τα δεδομένα των εφαρμογών για να εξοικονομήσετε χώρο" #: src/bz-window.c:1264 #, c-format msgid "Install %s?" msgstr "Εγκατάσταση %s?" #: src/bz-window.c:1267 msgid "May install additional shared components" msgstr "Μπορεί να εγκαταστήσει επιπλέον κοινόχρηστα στοιχεία" #: src/bz-window.c:1286 #, c-format msgid "Remove %s?" msgstr "Αφαίρεση %s?" #: src/bz-window.c:1290 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Δεν θα είναι δυνατή η χρήση του %s μετά την απεγκατάστασή του." #: src/bz-window.c:1353 msgid "Resume Current Tasks" msgstr "Συνέχιση τρεχουσών εργασιών" #: src/bz-window.c:1359 msgid "Pause Current Tasks" msgstr "Παύση τρέχουσων εργασιών" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u λήψεις" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Γενικά" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Άνοιγμα Διαλόγου Αναζήτησης" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Άνοιγμα Προτιμήσεων" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Ανανέωση" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Εναλλαγή Διαχειριστή Συναλλαγών" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Εμφάνιση συντομεύσεων" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Έξοδος" kolunmi-bazaar-7b9c8e1/po/es.po000066400000000000000000001142541514314607700164560ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2025 Spanish translations for bazaar package # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025 robotta # robotta <>, 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-30 01:38+0100\n" "PO-Revision-Date: 2025-10-30 12:15+0100\n" "Last-Translator: robotta <>\n" "Language-Team: Spanish\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:56 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Añade, elimine o actualice programas flatpak en este ordenador" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistema;GestorDePaquetes;Discover;Flatpak;Software;Store;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Git Forge Star Counts" msgstr "Mostrar las estadísticas de los forks de Git" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the " "full view" msgstr "" "Decidir si intentar detectar y mostrar la cantidad de estrellas de los " "proyectos en vista completa" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 #: src/bz-preferences-dialog.blp:35 msgid "Only Show Free Software" msgstr "Solo mostrar Software Libre" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software when searching" msgstr "Ocultar software propietario al buscar" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "Mostrar solo contenido de Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Filter search results to only show applications available on Flathub" msgstr "" "Filtrar los resultados de búsqueda para que solo aparezcan aplicaciones que " "están en Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "Rebotar los inputs de búsqueda" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "" "Aplicar un pequeño retardo al escribir para evitar resultados instantáneos" #: data/io.github.kolunmi.Bazaar.gschema.xml:40 msgid "Global Progress Bar Theme" msgstr "Tema de la barra de progreso global" #: data/io.github.kolunmi.Bazaar.gschema.xml:41 msgid "Describes the look of the global progress bar" msgstr "Describe como se ve la barra de progreso global" #: data/io.github.kolunmi.Bazaar.gschema.xml:45 msgid "Saved Window Dimensions" msgstr "Dimensiones de ventana guardadas" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "The window dimensions to be used by the next Bazaar window" msgstr "Las dimensiones de la venta que usará la siguiente ventana de Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Descubrir e instalar aplicaciones" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Una nueva tienda de aplicaciones para GNOME, enfocada a descubrir e instalar " "aplicaciones y complementos de repositorios flatpaks, particularmente de " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Enfatiza el apoyar a los desarrolladores que hacen que Linux en el " "escritorio sea posible. Bazaar contiene una lista de aplicaciones " "\"Elegidas\" que puede ser configurada por distribuidores para ofrecer una " "experiencia más centrada a sus usuarios." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:505 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home view displaying Flathub apps" msgstr "La vista principal mostrando aplicaciones de Flathub y sus categorías." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Página de Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Searching for Blender" msgstr "Buscando Blender" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:271 #: src/bz-installed-page.blp:132 msgid "Manage Add-ons" msgstr "Gestionar los complementos" #: src/bz-addons-dialog.c:88 src/bz-installed-page.blp:158 #: src/bz-transaction-view.blp:212 src/bz-window.c:1125 msgid "Remove" msgstr "Eliminar" #: src/bz-addons-dialog.c:95 src/bz-full-view.blp:244 #: src/bz-transaction-view.blp:186 src/bz-window.c:1103 msgid "Install" msgstr "Instalar" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Del tamaño del ADN humano" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 billones de pares base" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "del kernel de Linux" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "del ordenador guía Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "ROM y RAM total" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "del Super Mario Bros original" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "En la NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "Del tamaño de Wikipedia" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Sin nada" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Tamaño de la descarga" #: src/bz-application.c:400 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Esta funcionalidad está desactivada. Se recomienda que descargues e " "installes Flatseal para modificar los permisos de la aplicación." #: src/bz-application.c:464 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:465 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "robotta" #: src/bz-application.c:470 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "Ahmed Najmawi" #: src/bz-application.c:471 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:472 msgctxt "About Dialog Translator Credit" msgid "Azenyr" msgstr "Azenyr" #: src/bz-application.c:473 msgctxt "About Dialog Translator Credit" msgid "Goudarz Jafari" msgstr "Goudarz Jafari" #: src/bz-application.c:474 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore (Lumaeris)" msgstr "Jill Fiore (Lumaeris)" #: src/bz-application.c:475 msgctxt "About Dialog Translator Credit" msgid "João Victor (Leal)" msgstr "João Victor (Leal)" #: src/bz-application.c:476 msgctxt "About Dialog Translator Credit" msgid "KiKaraage" msgstr "KiKaraage" #: src/bz-application.c:477 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:478 msgctxt "About Dialog Translator Credit" msgid "Léane GRASSER" msgstr "Léane GRASSER" #: src/bz-application.c:479 msgctxt "About Dialog Translator Credit" msgid "Marcel Mrówka (Microwave)" msgstr "Marcel Mrówka (Microwave)" #: src/bz-application.c:480 msgctxt "About Dialog Translator Credit" msgid "Peter Dave Hello" msgstr "Peter Dave Hello" #: src/bz-application.c:481 msgctxt "About Dialog Translator Credit" msgid "Pietro F." msgstr "Pietro F." #: src/bz-application.c:482 msgctxt "About Dialog Translator Credit" msgid "Sabri Ünal" msgstr "Sabri Ünal" #: src/bz-application.c:483 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:484 msgctxt "About Dialog Translator Credit" msgid "Shinsei" msgstr "Shinsei" #: src/bz-application.c:485 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:486 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:487 msgctxt "About Dialog Translator Credit" msgid "camegone" msgstr "camegone" #: src/bz-application.c:488 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:489 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-application.c:1032 msgid "Constructing Flatpak instance..." msgstr "Construyendo instancia de Flatpak..." #: src/bz-application.c:1049 msgid "Reusing last Flatpak instance..." msgstr "Reutilizando la última instancia de Flatpak..." #: src/bz-application.c:1074 msgid "Flathub is not registered on this system" msgstr "Flathub no está registrado en este sistema" #: src/bz-application.c:1077 msgid "" "Would you like to add Flathub as a remote? If you decline, the Flathub page " "will not be available. You can change this later." msgstr "" "Le gustaría añadir Flathub como un repositorio? De lo contrario, la página " "de Flathub no estará disponible. Puede cambiarlo más tarde." #: src/bz-application.c:1082 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Más tarde" #: src/bz-application.c:1083 msgid "Add Flathub" msgstr "Añadir Flathub" #: src/bz-application.c:1115 #, c-format msgid "Identifying installed entries..." msgstr "Identificando las entradas instaladas..." #: src/bz-application.c:1127 #, c-format msgid "Beginning remote entry retrieval while referencing %d blocklist(s)..." msgstr "" "Empezando la recuperación de entradas mientras se referencia %d bloqueada(as)" #: src/bz-application.c:1275 #, c-format msgid "Receiving Entries" msgstr "Recibiendo entradas..." #: src/bz-application.c:1276 #, c-format msgid "%'d of %'d" msgstr "%'d de %'d" #: src/bz-application.c:1286 #, c-format msgid "Waiting for background indexing tasks to catch up..." msgstr "Esperando que las tareas en segundo plano se pongan al día..." #: src/bz-application.c:1322 #, c-format msgid "Completed initialization in %0.2f seconds" msgstr "Se ha completado el inicio en %0.2f segundos" #: src/bz-application.c:1327 src/bz-application.c:1482 msgid "Checking for updates..." msgstr "Viendo si hay actualizaciones..." #: src/bz-application.c:1366 msgid "Synchronizing..." msgstr "Sincronizando..." #: src/bz-browse-widget.blp:11 src/bz-flathub-page.blp:15 #: src/bz-full-view.blp:10 src/bz-installed-page.blp:15 src/bz-window.blp:161 msgid "Empty" msgstr "Vacío" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "Aplicaciones no seleccionadas " #: src/bz-browse-widget.blp:16 msgid "" "Bazaar was not provided a curated content configuration. Contact your " "operating system's support channels for assistance." msgstr "" "Bazaar no ha recibido una configuración dedicada para contenido " "seleccionado. Contacta con los canales de soporte de tu sistema operativo " "para soliticar asistencia." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:26 msgid "Browser" msgstr "Buscador" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Inspeccionar entrada" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Serializar" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Convertir a JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Ha ocurrido un error" #: src/bz-error.c:89 msgid "Close" msgstr "Cerrar" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Copiar y Cerrar" #: src/bz-featured-tile.blp:89 msgid "App of the Day" msgstr "Aplicación del día" #: src/bz-flathub-category.c:325 msgid "Audio & Video" msgstr "Audio y Video" #: src/bz-flathub-category.c:327 msgid "Developer Tools" msgstr "Herramientas de Desarollo" #: src/bz-flathub-category.c:329 msgid "Education" msgstr "Educación" #: src/bz-flathub-category.c:331 msgid "Gaming" msgstr "Gaming" #: src/bz-flathub-category.c:333 msgid "Graphics & Photography" msgstr "Fotografía y Edición de gráficos" #: src/bz-flathub-category.c:335 msgid "Networking" msgstr "Conexiones y Redes" #: src/bz-flathub-category.c:337 msgid "Productivity" msgstr "Productividad" #: src/bz-flathub-category.c:339 msgid "Science" msgstr "Ciencia" #: src/bz-flathub-category.c:341 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:343 msgid "Utilities" msgstr "Utilidades" #: src/bz-flathub-category-section.c:137 #, c-format msgid "%d applications" msgstr "%d aplicaciones" #: src/bz-flathub-category-section.c:336 #, c-format msgid "More %s" msgstr "Más %s" #: src/bz-flathub-page.blp:19 msgid "Flathub Not Added" msgstr "Flathub no está añadido" #: src/bz-flathub-page.blp:20 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "El remoto de Flathub no se encontró en ninguna de sus instalaciones de " "Flatpak." #: src/bz-flathub-page.blp:71 src/bz-flathub-page.blp:99 #: src/bz-flathub-page.c:168 msgid "Trending" msgstr "De moda" #: src/bz-flathub-page.blp:76 src/bz-flathub-page.blp:225 #: src/bz-flathub-page.c:198 msgid "Popular" msgstr "Populares" #: src/bz-flathub-page.blp:81 msgid "New" msgstr "Nuevo" #: src/bz-flathub-page.blp:86 msgid "Updated" msgstr "Actualizado" #: src/bz-flathub-page.blp:131 msgid "More Trending" msgstr "Ver más artículos de moda" #: src/bz-flathub-page.blp:141 src/bz-flathub-page.c:178 msgid "Recently Updated" msgstr "Actualizadas recientemente" #: src/bz-flathub-page.blp:173 msgid "More Updated" msgstr "Ver más actualizadas recientemente" #: src/bz-flathub-page.blp:183 src/bz-flathub-page.c:188 msgid "Recently Added" msgstr "Recién sacados del horno" #: src/bz-flathub-page.blp:215 msgid "More New" msgstr "Ver más aplicaciones nuevas" #: src/bz-flathub-page.blp:257 msgid "More Popular" msgstr "Ver más populares" #: src/bz-flatpak-entry.c:552 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Página de Flathub" #: src/bz-flatpak-entry.c:573 msgctxt "Project URL Type" msgid "Project Website" msgstr "Página del proyecto" #: src/bz-flatpak-entry.c:577 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rastreador de problemas" #: src/bz-flatpak-entry.c:581 msgctxt "Project URL Type" msgid "FAQ" msgstr "Preguntas Frecuentes" #: src/bz-flatpak-entry.c:585 msgctxt "Project URL Type" msgid "Help" msgstr "Ayuda" #: src/bz-flatpak-entry.c:589 msgctxt "Project URL Type" msgid "Donate" msgstr "Donar" #: src/bz-flatpak-entry.c:595 msgctxt "Project URL Type" msgid "Translate" msgstr "Traducir" #: src/bz-flatpak-entry.c:599 msgctxt "Project URL Type" msgid "Contact" msgstr "Contactar" #: src/bz-flatpak-entry.c:603 msgctxt "Project URL Type" msgid "Source Code" msgstr "Código fuente" #: src/bz-flatpak-entry.c:609 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuir" #: src/bz-full-view.blp:14 msgid "No Results" msgstr "Sin Resultados" #: src/bz-full-view.blp:15 msgid "Try a different search query" msgstr "Prueba con un término de búsqueda diferente" #: src/bz-full-view.blp:21 src/bz-window.blp:171 msgid "Content" msgstr "Contenido" #: src/bz-full-view.blp:151 msgid "Verified by the original developers" msgstr "Verificado por los desarrolladores originales de este programa" #: src/bz-full-view.blp:178 msgid "Support" msgstr "Apoyar" #: src/bz-full-view.blp:198 msgid "Repository Star Count" msgstr "Cantidad de estrellas de este repositorio" #: src/bz-full-view.blp:228 msgid "Open" msgstr "Abrir" #: src/bz-full-view.blp:241 msgid "Download & Install Application" msgstr "Descargar e instalar la aplicación" #: src/bz-full-view.blp:256 msgid "Uninstall Application" msgstr "Desinstalar la aplicación" #: src/bz-full-view.blp:284 msgid "Install Other Version" msgstr "Instalar otra versión" #: src/bz-full-view.blp:308 msgid "Download" msgstr "Tamaño" #: src/bz-full-view.blp:424 msgid "Downloads/mo" msgstr "Descargas por mes" #: src/bz-full-view.c:259 msgid "---" msgstr "---" #. Translators: M is the suffix for millions, \xC2\xA0 is a non-breaking space #: src/bz-full-view.c:263 #, c-format msgid "%.2f M" msgstr "%.2f M" #. Translators: K is the suffix for thousands, \xC2\xA0 is a non-breaking space #: src/bz-full-view.c:266 #, c-format msgid "%.2f K" msgstr "%.2f K" #: src/bz-full-view.c:275 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d descargas en los últimos 30 días" #: src/bz-full-view.c:296 #, c-format msgid "Download size of %s" msgstr "Tamaño de la descarga de %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-full-view.c:306 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-full-view.c:314 msgid "All Ages" msgstr "Para todas las edades" #: src/bz-full-view.c:316 msgid "Age Rating" msgstr "Calificación por edades" #: src/bz-full-view.c:324 msgid "Suitable for all ages" msgstr "Apto para todas las edades" #: src/bz-full-view.c:326 #, c-format msgid "Suitable for ages %d and up" msgstr "Apto para mayores de %d" #: src/bz-full-view.c:346 msgid "Unknown" msgstr "Desconocido" #: src/bz-full-view.c:349 msgid "Proprietary Software" msgstr "Software Propietario" #: src/bz-full-view.c:353 #, c-format msgid "Free software licensed under %s" msgstr "Software libre licendiado bajo %s" #: src/bz-full-view.c:361 msgid "Free" msgstr "Libre" #: src/bz-full-view.c:361 msgid "Proprietary" msgstr "Propietario" #: src/bz-full-view.c:381 msgid "Adaptive" msgstr "Adaptativo" #: src/bz-full-view.c:381 msgid "Desktop Only" msgstr "Sólo para escritorio" #: src/bz-full-view.c:387 msgid "Works on desktop, tablets, and phones" msgstr "Funciona en escritorio, tablets y móviles" #: src/bz-full-view.c:388 msgid "May not work on mobile devices" msgstr "Puede que no funcione en móviles" #: src/bz-full-view.c:399 msgid "No URL" msgstr "Sin enlace" #: src/bz-full-view.c:417 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Esta aplicación tiene una licencia FLOSS, lo que significa que el código " "fuente puede ser ojeado por seguridad." #: src/bz-full-view.c:418 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Esta aplicación tiene una licencia propietaria, lo que significa que el " "código fuente se desarolla de manera privada y no puede ser ojeado por " "ningún equipo de terceros." #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Soporte de Teclado" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Requiere teclado" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Recomienda teclado" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Soporta teclado" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Soporte desconocido de teclado" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Soporta ratón" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Requiere ratón o puntero" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Recomienda ratón o puntero" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Soporta ratón o puntero" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Soporte desconocido de ratón o puntero" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Soporta pantalla táctil" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Requiere pantalla táctil" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Recomienda pantalla táctil" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Soporta pantalla táctil" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Soporte desconocido de pantalla táctil" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Soporte de móviles" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Funciona en móviles" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Puede no funcionar bien en móviles" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Soporte de escritorio" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Funciona bien en pantallas grandes" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s funcionan bien en hardware específico" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s funcionan en la mayoría de dispositivos" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Soporte de hardware" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Inspector de Bazaar" #: src/bz-inspector.blp:22 msgid "Active Blocklists" msgstr "Listas bloqueadas activas" #: src/bz-inspector.blp:44 msgid "Active Curated-Configs" msgstr "Configuraciones de selecciones activas" #: src/bz-inspector.blp:66 msgid "All Entry Groups" msgstr "Grupos con todas las entradas" #: src/bz-inspector.blp:69 msgid "Filter..." msgstr "Filtrar..." #: src/bz-inspector.blp:110 msgid "Decache and Inspect" msgstr "Inspeccionar y borrar caché" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "No hay flatpaks instalados" #: src/bz-installed-page.blp:25 src/bz-window.blp:305 src/bz-window.blp:399 msgid "Installed" msgstr "Instalados" #: src/bz-installed-page.blp:108 msgid "Support this application" msgstr "Apoyar esta aplicación" #: src/bz-installed-page.blp:185 msgid "More actions" msgstr "Más acciones" #: src/bz-installed-page.blp:204 msgid "Run this application" msgstr "Iniciar esta aplicación" #: src/bz-installed-page.blp:216 msgid "Run" msgstr "Iniciar" #: src/bz-installed-page.blp:228 src/bz-installed-page.blp:239 msgid "View Store Page" msgstr "Mirar en la tienda" #: src/bz-installed-page.c:649 msgid "Choose an Installation" msgstr "Elije una instalación" #: src/bz-installed-page.c:652 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "Cuenta con varias versiones instaladas de esta aplicación. Con cual quiere " "proceder?" #: src/bz-installed-page.c:656 src/bz-window.c:1102 src/bz-window.c:1124 msgid "Cancel" msgstr "Cancelar" #: src/bz-license-dialog.c:115 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may not be able to contribute to this app." msgstr "" "Esta aplicación no se desarrolla en código abierto, así que solo sus " "desarrolladores saben como funciona. Puede ser insegura de manera que es " "difícil de detectar, y puede cambiar sin previo aviso.\n" "\n" "Puede que no pueda contribuir a esta aplicación. " #: src/bz-license-dialog.c:124 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Esta aplicación se desarrolla en código abierto por una comunidad " "internacional.\n" "\n" "Puede contribuir a esta aplicación y ayudar a mejorarla." #: src/bz-license-dialog.c:135 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Esta aplicación se desarrolla en código abierto por una comunidad " "internacional, y se lanza bajo la licencia %s\n" "\n" "Puede contribuir a esta aplicación y ayudar a mejorarla." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Ajustes" #: src/bz-preferences-dialog.blp:23 msgid "Application Details" msgstr "Detalles de la aplicación" #: src/bz-preferences-dialog.blp:26 msgid "Git Forge Star Counts" msgstr "Contador de estrellas de la forja de Git" #: src/bz-preferences-dialog.blp:27 msgid "Not having a GitHub access token may trigger rate limits" msgstr "" "El no tener acceso al token de Github puede ocasionar límites de " "clasificaciones" #: src/bz-preferences-dialog.blp:32 src/bz-window.blp:48 src/bz-window.blp:337 msgid "Search" msgstr "Buscar" #: src/bz-preferences-dialog.blp:36 msgid "Hide proprietary applications from search results" msgstr "No mostrar aplicaciones propietarias en los resultados de búsqueda" #: src/bz-preferences-dialog.blp:40 msgid "Show Only Flathub Apps" msgstr "Mostrar únicamente aplicaciones de Flathub" #: src/bz-preferences-dialog.blp:41 msgid "Limit search results to applications available on Flathub" msgstr "" "Limitar los resultados de búsqueda a sólo aplicaciones disponibles en Flathub" #: src/bz-preferences-dialog.blp:45 msgid "Debounce Search Results" msgstr "Retrasar la ejecución de las búsquedas" #: src/bz-preferences-dialog.blp:46 msgid "Wait for a brief pause to reduce system load" msgstr "Esperar por una breve pausa para reducir la carga en el sistema" #: src/bz-preferences-dialog.blp:51 msgid "Progress Bar" msgstr "Barra de progreso " #: src/bz-preferences-dialog.blp:52 msgid "Choose a theme for the progress bar!" msgstr "Escoja un tema para la barra de progreso!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Color de realce personal" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Colores del Orgullo" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Colores del Orgullo Lésbico" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Colores del Orgullo Transgénero" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Colores del Orgullo No Binario" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Colores del Orgullo Bisexual" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Colores del Orgullo Asexual" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "Colores del Orgullo Pansexual" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Colores del Orgullo Aromántico" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Colores del Orgullo de Género fluído" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Colores del Orgullo Polisexual" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Colores del Orgullo Omnisexual " #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:25 msgid "Version History" msgstr "Historial de versiones" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "Versión %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "No hay detalles de este lanzamiento" #: src/bz-search-widget.blp:69 msgid "Search Apps" msgstr "Buscar Aplicaciones" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Copiada!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Copiar enlace" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Abrir enlace" #: src/bz-stats-dialog.blp:26 msgid "Timeline" msgstr "Línea de tiempo" #: src/bz-stats-dialog.blp:31 msgid "Installs:" msgstr "Instalaciones:" #: src/bz-stats-dialog.blp:37 msgid "World" msgstr "Global" #: src/bz-transaction-manager.c:1140 #, c-format msgid "Finished in %.02f seconds" msgstr "Terminado en %.02f segundos" #: src/bz-transaction-view.blp:94 msgid "App Add-on" msgstr "Complementos para la aplicación" #: src/bz-transaction-view.blp:119 msgid "Runtime" msgstr "Tiempo de ejecución" #: src/bz-transaction-view.blp:145 src/bz-transaction-view.blp:171 msgid "Install Size" msgstr "Tamaño de instalación" #: src/bz-transaction-view.blp:199 src/bz-window.blp:350 msgid "Update" msgstr "Actualizar" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Transferidos %s por ahora" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Pendiente" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Instalar ahora" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Hay actualizaciones disponibles" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Las siguientes aplicaciones pueden ser actualizadas. ¿Le gustaría " "actualizarlas?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d tiempos de ejecución y / o los complementos pueden ser actualizados. ¿Le " "gustaría actualizarlos?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "" "Adicionalmente, %d tiempos de ejecución y / o los complementos serán " "actualizados." #: src/bz-window.blp:63 msgid "Go Home" msgstr "Ir a Inicio" #: src/bz-window.blp:86 msgid "Tasks" msgstr "Tareas" #: src/bz-window.blp:105 src/bz-window.blp:418 msgid "Toggle transaction sidebar" msgstr "Mostrar la barra lateral de las transacciones" #: src/bz-window.blp:141 msgid "Stop Active Tasks" msgstr "Detener tareas activas" #: src/bz-window.blp:149 msgid "Clear History" msgstr "Limpiar el historial" #: src/bz-window.blp:165 msgid "No Tasks Yet" msgstr "No hay tareas" #: src/bz-window.blp:219 src/bz-window.blp:223 msgid "Offline" msgstr "Sin Internet" #: src/bz-window.blp:229 msgid "Loading" msgstr "Cargando" #: src/bz-window.blp:270 msgid "Browse" msgstr "Navegar" #: src/bz-window.blp:280 msgid "App View" msgstr "Vista de Aplicación" #: src/bz-window.blp:295 src/bz-window.blp:392 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:325 msgid "Go Back" msgstr "Ir atrás" #: src/bz-window.blp:381 msgid "View curated applications" msgstr "Ver las aplicaciones seleccionadas" #: src/bz-window.blp:385 msgid "Curated" msgstr "Seleccionado" #: src/bz-window.blp:389 msgid "View the latest on Flathub" msgstr "Ver lo último en Flathub" #: src/bz-window.blp:396 msgid "View installed applications" msgstr "Ver aplicaciones instaladas" #: src/bz-window.blp:441 msgid "Main Menu" msgstr "Menú Principal" #: src/bz-window.blp:486 msgid "_Donate to Bazaar ❤️" msgstr "_Hacer un donativo a Bazaar ❤️" #: src/bz-window.blp:491 msgid "_Refresh Content" msgstr "_Actualizar el contenido" #: src/bz-window.blp:498 msgid "_Preferences" msgstr "_Preferencias" #: src/bz-window.blp:503 msgid "_Keyboard Shortcuts" msgstr "_Atajos de Teclado" #: src/bz-window.blp:508 msgid "_About Bazaar" msgstr "_Sobre Bazaar" #: src/bz-window.blp:515 msgid "_Quit Bazaar" msgstr "_Salir de Bazaar" #: src/bz-window.c:827 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "La opción de inspeccionar e instalar colleciones de .flatpak llegará pronto! " "De mientras, pruebe a iniciar\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "en el terminal." #: src/bz-window.c:967 msgid "Can't do that right now!" msgstr "¡No se puede hacer eso ahora mismo!" #: src/bz-window.c:1096 #, c-format msgid "Install %s?" msgstr "Instalar %s?" #: src/bz-window.c:1099 msgid "May install additional shared components" msgstr "Puede que instale componentes compartidos adicionales" #: src/bz-window.c:1118 #, c-format msgid "Remove %s?" msgstr "Eliminar %s?" #: src/bz-window.c:1121 msgid "Settings & user data will be kept" msgstr "Los ajustes personales y datos de usuario se mantendrán" #: src/bz-window.c:1289 msgid "Resume Current Tasks" msgstr "Reanudar las tareas" #: src/bz-window.c:1295 msgid "Pause Current Tasks" msgstr "Pausar las tareas" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u descargas" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "General" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Abrir la barra de búsqueda" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Abrir ajustes" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Refrescar" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Mostrar el administrador de transacciones" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Mostrar atajos" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Salir" #~ msgid "Calligraphy application page" #~ msgstr "Página de la aplicación \"Calligraphy\"" #~ msgid "Download graph for Blender" #~ msgstr "Gráfica de descargas de Blender" #~ msgid "Manage Addons" #~ msgstr "Gestionar complementos" #~ msgid "Open this image in the default image viewer" #~ msgstr "Abrir esta imagen en el mostrador de imágenes por defecto" #~ msgid "Copy this image to the clipboard" #~ msgstr "Copiar esta imagen al portapapeles" #~ msgid "Games" #~ msgstr "Juegos" #~ msgid "Graphics" #~ msgstr "Gráficos" #~ msgid "Office" #~ msgstr "Ofimática" #~ msgid "Categories" #~ msgstr "Categorías" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "Inicio" #~ msgid "Share this application" #~ msgstr "Compartir esta aplicación" #~ msgid "Excludes shared components" #~ msgstr "Excluye componentes compartidos" #~ msgid "Free Software" #~ msgstr "Software Libre" #~ msgid "in the last month" #~ msgstr "En el último mes" #~ msgid "Repositories" #~ msgstr "Repositorios" #~ msgid "Open in browser" #~ msgstr "Abrir en el navegador" #~ msgid "--- Downloads" #~ msgstr "--- Descargas" #~ msgid "%B %-d, %Y" #~ msgstr "%-d %B, %Y" #~ msgid "%B %-d" #~ msgstr "%-d %B" #~ msgid "Theme" #~ msgstr "Tema" #~ msgid "Pride Rainbow Flag" #~ msgstr "Bandera del Orgullo" #~ msgid "Bisexual Flag" #~ msgstr "Bandera Bisexual" #~ msgid "Asexual Flag" #~ msgstr "Bandera Asexual" #~ msgid "Share" #~ msgstr "Compartir" #~ msgid "Updated Size" #~ msgstr "Tamaño de actualización" #~ msgid "Freed Space" #~ msgstr "Espacio libre" #~ msgid "Error Details" #~ msgstr "Detalles del error" #~ msgid "Transactions Will Appear Here" #~ msgstr "Las transacciones aparecerán aquí" #~ msgid "Halt the execution of transactions" #~ msgstr "Cortar las transacciones en curso" #~ msgid "Clear all finished transactions" #~ msgstr "Limpiar todas las transacciones completas" #~ msgid "_Quit Service" #~ msgstr "_Terminar el proceso" #~ msgid "Up to date!" #~ msgstr "Al día!" #~ msgid "Resume the execution of transactions" #~ msgstr "Continuar con las transacciones" #~ msgid "Pause the execution of transactions" #~ msgstr "Pausar las transacciones" #~ msgid "Show Animated Background" #~ msgstr "Mostrar fondo animado" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr " Añade un fondo de iconos animado en la pantalla de inicio" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Mantener la descripción corta, alrededor de 10 a 35 caracteres" #~ msgid "No description" #~ msgstr "Sin descripción" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "La ventana principal de Bazaar mostrando Blender" #~ msgid "Apps Of The Week" #~ msgstr "Aplicaciones de la semana" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "El número de descargas en los últimos 30 días. Haga click aquí para ver " #~ "las estadísticas de descargas de esta aplicación." #~ msgid "Remote repo name" #~ msgstr "Nombre del repositorio remoto" #, c-format #~ msgid "Released %x" #~ msgstr "Lanzado el %x" #~ msgid "Edit Permissions" #~ msgstr "Editar permisos" #~ msgid "How the application looks" #~ msgstr "Cómo se ve la aplicación" #~ msgid "Appearance" #~ msgstr "Apariencia" #~ msgid "Show animated background" #~ msgstr "Mostrar fondo animado" #~ msgid "Type to filter" #~ msgstr "Escribe para filtrar" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "No inclúir resultados con licencia propietaria" #~ msgid "Exclude results not originating from Flathub" #~ msgstr "No incluir resultados ajenos a Flathub" #~ msgid "Advanced" #~ msgstr "Avanzado" #~ msgid "Match using regular expressions" #~ msgstr "Coincidir usando expresiones comunes" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "Esconder el filtrar y ordenar con un efecto crossfade" #~ msgid "Open this link externally" #~ msgstr "Abrir este enlace externamente" #~ msgid "Downloads Over Time" #~ msgstr "Descargas con el paso del tiempo" #~ msgid "Minimize Lower Bound" #~ msgstr "Minimizar el límite inferior" #~ msgid "Maximize Upper Bound" #~ msgstr "Maximiza el límite superior" #~ msgid "Installing" #~ msgstr "Instalando" #~ msgid "Updating" #~ msgstr "Actualizando" #~ msgid "Removing" #~ msgstr "Eliminando" #~ msgid "Refresh" #~ msgstr "Refrescar" #~ msgid "Confirm Action" #~ msgstr "Confirmar" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Está a punto de eliminar el Flatpak a continuación:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "¿Está seguro?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Está a punto de instalar el Flatpak a continuación:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "¿Está seguro?" kolunmi-bazaar-7b9c8e1/po/fa_IR.po000066400000000000000000000411521514314607700170230ustar00rootroot00000000000000# Persian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Goudarz Jafari , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-07-14 09:23+0330\n" "PO-Revision-Date: 2025-07-14 16:34+0330\n" "Last-Translator: Goudarz Jafari \n" "Language-Team: none\n" "Language: fa_IR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.6\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 msgid "Bazaar" msgstr "بازار" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "افزودن، حذف یا به‌روزرسانی نرم‌افزارهای Flatpak در این رایانه" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;سیستم;مدیر بسته‌ها;کشف ;کردن;Flatpak;نرم‌افزار;فروشگاه;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Animated Background" msgstr "نمایش پس‌زمینه متحرک" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Whether to show the animated icon background on the home page" msgstr "آیا پس‌زمینه‌ی نماد متحرک در صفحه‌ی اصلی نمایش داده شود" #. FIXME: add descriptions and summary #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:9 msgid "Keep the summary shorter, between 10 and 35 characters" msgstr "خلاصه را کوتاه نگه دارید، بین ۱۰ تا ۳۵ نویسه" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:11 msgid "No description" msgstr "بدون توضیح" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:41 msgid "Main Bazaar window showing Blender" msgstr "پنجره‌ی اصلی بازار که Blender را نمایش می‌دهد" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:50 msgid "Release description" msgstr "توضیح‌های نگارش" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:52 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:53 msgid "List of changes" msgstr "فهرست تغییرات" #: src/bz-addons-dialog.blp:13 src/bz-installed-page.blp:162 #: src/bz-installed-page.blp:174 msgid "Manage Addons" msgstr "مدیریت افزونه‌ها" #: src/bz-app-tile.blp:65 src/bz-full-view.blp:139 msgid "This flatpak is verified by the original developers of the software." msgstr "این Flatpak توسط توسعه‌دهندگان اصلی نرم‌افزار تایید شده است." #: src/bz-application.c:1194 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "Goudarz Jafari" #: src/bz-application.c:1199 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "Ahmed Najmawi" #: src/bz-application.c:1200 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:1201 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore" msgstr "Jill Fiore" #: src/bz-application.c:1202 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:1203 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:1204 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:1205 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:1206 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:1207 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-application.c:1223 msgid "Adam Masciola" msgstr "Adam Masciola" #: src/bz-browse-widget.blp:11 src/bz-full-view.blp:11 #: src/bz-installed-page.blp:11 src/bz-window.blp:32 msgid "Empty" msgstr "خالی" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "هنوز هیچ برنامه‌ی پیشنهادی‌ای وجود ندارد" #: src/bz-browse-widget.blp:16 msgid "" "Bazaar was not provided a curated content configuration. Contact your " "operating system's support channels for assistance." msgstr "" "هیچ پیکربندی‌ای برای محتوای انتخاب‌شده به بازار ارائه نشده است. برای دریافت " "کمک با پشتیبانی سیستم‌عامل خود تماس بگیرید." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:11 msgid "Browser" msgstr "مرورگر" #: src/bz-error.c:45 msgid "An Error Occurred" msgstr "یک خطا رخ داد" #: src/bz-error.c:51 msgid "Close" msgstr "بستن" #: src/bz-error.c:52 msgid "Copy and Close" msgstr "رونوشت و بستن" #: src/bz-flathub-page.blp:41 msgid "Apps Of The Week" msgstr "برنامه‌های هفته" #: src/bz-flathub-page.blp:85 msgid "Trending" msgstr "محبوب‌ها" #: src/bz-flathub-page.blp:117 msgid "Recently Updated" msgstr "اخیرا به‌روزرسانی‌شده" #: src/bz-flathub-page.blp:149 msgid "Recently Added" msgstr "اخیرا افزوده‌شده" #: src/bz-flathub-page.blp:181 msgid "Popular" msgstr "پرطرفدار" #: src/bz-full-view.blp:15 msgid "No Results" msgstr "نتیجه‌ای یافت نشد" #: src/bz-full-view.blp:16 msgid "Try a different search query" msgstr "از یک عبارت دیگر برای جستجو استفاده کنید" #: src/bz-full-view.blp:22 src/bz-window.blp:42 msgid "Content" msgstr "محتوا" #: src/bz-full-view.blp:180 msgid "Run this application" msgstr "اجرای این برنامه" #: src/bz-full-view.blp:204 msgid "Download and install this application" msgstr "بارگیری و نصب این برنامه" #: src/bz-full-view.blp:222 src/bz-window.c:987 msgid "Install" msgstr "نصب" #: src/bz-full-view.blp:236 msgid "Uninstall this application" msgstr "این برنامه را حذف کن" #: src/bz-full-view.blp:262 msgid "Share this application" msgstr "هم‌رسانی این برنامه" #: src/bz-full-view.blp:274 msgid "" "The number of downloads in the last 30 days. Click to view this " "application's download statistics." msgstr "" "تعداد بارگیری در ۳۰ روز گذشته. برای مشاهده‌ی آمار بارگیری این برنامه کلیک " "کنید." #: src/bz-full-view.blp:316 msgid "Support this developer" msgstr "حمایت از این توسعه‌دهنده" #: src/bz-full-view.blp:329 msgid "Support" msgstr "پشتیبانی" #: src/bz-full-view.blp:387 msgid "Remote repo name" msgstr "نام مخزن راه‌دور" #: src/bz-full-view.blp:400 msgid "Project URL" msgstr "نشانی اینترنتی پروژه" #: src/bz-full-view.blp:412 msgid "Download size" msgstr "اندازه‌ی بارگیری" #: src/bz-full-view.c:214 #, c-format msgid "Released %x" msgstr "منتشر شده در %x" #: src/bz-full-view.c:225 msgid "No URL" msgstr "بدون نشانی اینترنتی" #: src/bz-full-view.c:233 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "این برنامه دارای مجوز FLOSS است، به این معنا که کد منبع آن برای ایمنی قابل " "بررسی است." #: src/bz-full-view.c:234 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "این برنامه دارای مجوز مالکیتی است، به این معنا که کد منبع آن به‌صورت خصوصی " "توسعه یافته و توسط طرف ثالث مستقل قابل بررسی نیست." #: src/bz-installed-page.blp:15 msgid "No Flatpaks Installed" msgstr "هیچ Flatpakی نصب نشده است" #: src/bz-installed-page.blp:21 src/bz-window.blp:201 src/bz-window.blp:336 msgid "Installed" msgstr "نصب شده" #: src/bz-installed-page.blp:143 msgid "More actions" msgstr "اقدام‌های بیشتر" #: src/bz-installed-page.blp:187 src/bz-installed-page.blp:198 msgid "Edit Permissions" msgstr "ویرایش مجوزها" #: src/bz-preferences-dialog.blp:9 msgid "Preferences" msgstr "تنظیمات" #: src/bz-preferences-dialog.blp:13 msgid "How the application looks" msgstr "ظاهر برنامه" #: src/bz-preferences-dialog.blp:14 msgid "Appearance" msgstr "ظاهر" #: src/bz-preferences-dialog.blp:17 msgid "Show animated background" msgstr "نمایش پس‌زمینه متحرک" #: src/bz-search-widget.blp:69 msgid "Type to filter" msgstr "برای فیلتر کردن تایپ کنید" #: src/bz-search-widget.blp:98 src/bz-search-widget.blp:115 msgid "Search Options" msgstr "گزینه‌های جستجو" #: src/bz-search-widget.blp:119 msgid "Exclude results with proprietary licenses" msgstr "حذف نتایج دارای مجوز مالکیتی" #: src/bz-search-widget.blp:124 msgid "Exclude results not originating from Flathub" msgstr "حذف نتایجی که از Flathub منشا نگرفته‌اند" #: src/bz-search-widget.blp:139 msgid "Advanced" msgstr "پیشرفته" #: src/bz-search-widget.blp:143 msgid "Match using regular expressions" msgstr "همسان‌سازی با استفاده از عبارات باقاعده" #: src/bz-search-widget.blp:148 msgid "Hide filtering and sorting behind a crossfade effect" msgstr "پنهان‌سازی فیلتر و مرتب‌سازی با افکت محوشونده" #: src/bz-search-widget.blp:153 msgid "Debounce input to prevent instant replies" msgstr "مکث ورودی برای جلوگیری از پاسخ فوری" #: src/bz-share-dialog.blp:13 msgid "Share" msgstr "هم‌رسانی" #: src/bz-share-dialog.blp:64 msgid "Copy this link" msgstr "رونوشت این پیوند" #: src/bz-share-dialog.blp:71 msgid "Open this link externally" msgstr "این پیوند را در بیرون از این برنامه باز کنید" #: src/bz-stats-dialog.blp:15 msgid "Downloads Over Time" msgstr "بارگیری‌ها در طول زمان" #: src/bz-stats-dialog.blp:31 msgid "Minimize Lower Bound" msgstr "کاهش حد پایین" #: src/bz-stats-dialog.blp:36 msgid "Maximize Upper Bound" msgstr "افزایش حد بالا" #: src/bz-transaction-manager.c:451 #, c-format msgid "Finished in %.02f seconds" msgstr "اتمام در %.02f ثانیه" #: src/bz-transaction-view.blp:34 msgid "Installing" msgstr "در حال نصب" #: src/bz-transaction-view.blp:63 msgid "Updating" msgstr "در حال به‌روزرسانی" #: src/bz-transaction-view.blp:92 msgid "Removing" msgstr "در حال حذف" #: src/bz-transaction.c:268 msgid "Pending" msgstr "در انتظار" #: src/bz-update-dialog.blp:6 msgid "Later" msgstr "بعداً" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "اکنون نصب شود" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "به‌روزرسانی‌ها در دسترس‌اند" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "برنامه‌های زیر واجد شرایط به‌روزرسانی هستند. آیا مایل به نصب آن‌ها هستید؟" #: src/bz-update-dialog.c:135 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d محیط اجرایی و/یا افزونه برای به‌روزرسانی واجد شرایط هستند. آیا مایل به نصب " "آن‌ها هستید؟" #: src/bz-update-dialog.c:143 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "علاوه بر این، %d محیط اجرایی و/یا افزونه به‌روزرسانی خواهند شد." #: src/bz-window.blp:36 msgid "Transactions Will Appear Here" msgstr "تراکنش‌ها اینجا ظاهر خواهند شد" #: src/bz-window.blp:97 msgid "Halt the execution of transactions" msgstr "توقف اجرای تراکنش‌ها" #: src/bz-window.blp:105 msgid "Clear all finished transactions" msgstr "پاک‌سازی همه‌ی تراکنش‌های پایان‌یافته" #: src/bz-window.blp:136 src/bz-window.blp:140 msgid "Offline" msgstr "آفلاین" #: src/bz-window.blp:146 msgid "Loading" msgstr "در حال بارگذاری" #: src/bz-window.blp:170 msgid "Browse" msgstr "مرور" #: src/bz-window.blp:180 msgid "App View" msgstr "نمایش برنامه" #: src/bz-window.blp:191 src/bz-window.blp:315 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:220 msgid "Go Back" msgstr "بازگشت" #: src/bz-window.blp:228 msgid "Refresh" msgstr "تازه‌سازی" #: src/bz-window.blp:237 msgid "Search" msgstr "جست‌وجو" #: src/bz-window.blp:249 msgid "Update" msgstr "به‌روزرسانی" #: src/bz-window.blp:263 msgid "Checking for updates" msgstr "در حال بررسی برای به‌روزرسانی‌ها" #: src/bz-window.blp:279 msgid "View curated applications" msgstr "مشاهده‌ی برنامه‌های منتخب" #: src/bz-window.blp:294 msgid "Curated" msgstr "منتخب" #: src/bz-window.blp:300 msgid "View the latest on Flathub" msgstr "مشاهده‌ی آخرین‌ها در Flathub" #: src/bz-window.blp:321 msgid "View installed applications" msgstr "مشاهده‌ی برنامه‌های نصب‌شده" #: src/bz-window.blp:350 msgid "Main Menu" msgstr "منوی اصلی" #: src/bz-window.blp:361 msgid "Toggle transaction sidebar" msgstr "نمایش یا پنهان کردن نوار جانبی تراکنش‌ها" #: src/bz-window.blp:400 msgid "Up to date!" msgstr "به‌روز است!" #: src/bz-window.blp:425 msgid "_Keyboard Shortcuts" msgstr "_میان‌برهای صفحه‌کلید" #: src/bz-window.blp:430 msgid "_About Bazaar" msgstr "_درباره‌ی بازار" #: src/bz-window.blp:435 msgid "_Donate to Bazaar ❤️" msgstr "_به بازار اهدا کنید ❤️" #: src/bz-window.c:856 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "قابلیت بررسی و نصب پرونده‌های محلی .flatpak به‌زودی ارائه خواهد شد! در این " "فاصله، دستور\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" " را در خط فرمان امتحان کنید." #: src/bz-window.c:927 msgid "Can't do that right now!" msgstr "فعلا امکان انجام این کار وجود ندارد!" #: src/bz-window.c:940 msgid "Confirm Action" msgstr "تایید عملیات" #: src/bz-window.c:958 #, c-format msgid "" "You are about to remove the following Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Are you sure?" msgstr "" "شما در حال حذف Flatpak زیر هستید:\n" "\n" "%s\n" "%s\n" "\n" "آیا مطمئن هستید؟" #: src/bz-window.c:966 src/bz-window.c:986 msgid "Cancel" msgstr "لغو" #: src/bz-window.c:967 msgid "Remove" msgstr "حذف" #: src/bz-window.c:978 #, c-format msgid "" "You are about to install the following Flatpak:\n" "\n" "%s\n" "%s\n" "\n" "Are you sure?" msgstr "" "شما در حال نصب Flatpak زیر هستید:\n" "\n" "%s\n" "%s\n" "\n" "آیا مطمئن هستید؟" #: src/bz-window.c:1012 msgid "More details" msgstr "جزئیات بیشتر" #: src/bz-window.c:1138 msgid "Resume the execution of transactions" msgstr "ادامه دادن اجرای تراکنش‌ها" #: src/bz-window.c:1144 msgid "Pause the execution of transactions" msgstr "توقف اجرای تراکنش‌ها" #: src/gtk/help-overlay.blp:11 msgctxt "shortcut window" msgid "General" msgstr "عمومی" #: src/gtk/help-overlay.blp:14 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "باز کردن پنجره جست‌وجو" #: src/gtk/help-overlay.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "تازه‌سازی" #: src/gtk/help-overlay.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "نمایش یا پنهان کردن مدیر تراکنش" #: src/gtk/help-overlay.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "نمایش میان‌برها" #: src/gtk/help-overlay.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "خروج" kolunmi-bazaar-7b9c8e1/po/fr.po000066400000000000000000002317271514314607700164630ustar00rootroot00000000000000# French translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Atom <29772841+AtomHare@users.noreply.github.com>, 2025. # Léane GRASSER , 2025. # Irénée THIRION , 2026. # Mimolet , 2025-2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-09 00:18+0100\n" "PO-Revision-Date: 2026-02-10 02:17+0100\n" "Last-Translator: Mimolet \n" "Language-Team: French <>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:3 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:4 msgid "Add, remove or update flatpak software on this computer" msgstr "Ajoutez, désinstallez ou mettez à jour des applications flatpak" #: data/io.github.kolunmi.Bazaar.desktop.in:10 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;Système;Gestionnaire de " "paquets;Discover;Découvrir;Flatpak;Software;Logiciel;Magasin;Store;Applis;Logithèque;" #: data/io.github.kolunmi.Bazaar.desktop.in:16 msgid "New Window" msgstr "Nouvelle fenêtre" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Découvrez et installez de nouvelles applications" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Une nouvelle logithèque pour Linux, focalisée sur la découverte et " "l’installation d’applications et d’extensions à partir de dépôts Flatpak " "distants, en particulier Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Bazaar encourage activement à soutenir les développeurs qui rendent " "l’environnement de bureau Linux possible. Bazaar est doté d’un onglet " "« Sélection » qui peut être configuré par les distributeurs, pour une " "expérience personnalisée." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:701 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Page d’accueil affichant les applis de Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Page de l’application Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Page de recherche" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Page des catégories" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "Gérer les extensions" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:227 msgid "Remove" msgstr "Désinstaller" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:198 msgid "Install" msgstr "Installer" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "Limite d’âge" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Violence animée" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Aucune information concernant de la violence animée" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Violence fictive" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Aucune information concernant des scènes de violence fictive" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Violence réaliste" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Aucune information concernant des scènes de violence réaliste" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Violence sanglante" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Aucune information concernant des scènes de violence sanglante" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Violence sexuelle" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Aucune information concernant des scènes de violence sexuelle" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alcool" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Aucune information concernant des références à l’alcool" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Stupéfiants" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Aucune information concernant des références aux drogues illicites" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabac" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Aucune information concernant des références aux produits du tabac" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nudité" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Aucune information concernant des formes de nudité" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Thèmes sexuels" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Aucune information concernant des références ou scènes à caractère sexuel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Vulgarité" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Aucune information concernant des formes de vulgarité" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Humour inapproprié" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Aucune information concernant de l’humour inapproprié" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Discrimination" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Aucune information concernant un langage à caractère discriminatoire" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Publicité" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Aucune information concernant des formes de publicité" # Fait parti du système d'estimation d'âge et n'est pas une catégorie # (d'où l'utilisation du singuler par rapport au pluriel) #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Jeu d’argent" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Aucune information concernant les jeux d’argent" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Achat" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Aucune information concernant la faculté de dépenser de l’argent" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Discussions entre utilisateurs" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "" "Aucune information concernant des moyens de discuter avec d’autres " "utilisateurs" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Discussions vocales entre utilisateurs" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "" "Aucune information concernant les moyens de parler avec d’autres utilisateurs" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Détails des contacts" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Aucune information concernant le partage de pseudonymes ou d’adresses " "courriel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Données d’identification" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "" "Aucune information concernant le partage d’information utilisateur avec des " "tiers" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Partage de position" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Aucune information concernant la possibilité de partager sa position avec " "d’autres utilisateurs" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostitution" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Aucune information concernant des références à la prostitution" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Adultère" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Aucune information concernant des références à l’adultère" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Personnage sexualisés" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Aucune information concernant des personnages sexualisés" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Profanation" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Aucune information concernant des formes de profanation" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Restes humains" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Aucune information concernant la visibilité de restes humains" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Esclavage" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Aucune information concernant des références à l’esclavage" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "N’inclut pas de références aux drogues" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "Ne comporte pas de jurons, blasphèmes ou d’autres formes de langage grossier" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "N’inclut pas de publicité, ni de transactions monétaires" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "N’inclut pas de sexe, ni de nudité" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "N’inclut pas de fonctionnalités de discussion non modérées" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "N’inclut pas de violence" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drogues" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Langage grossier" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Monétisation" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Social" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Violence" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Tout" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s a une limite d’âge inconnue" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s convient à tout le monde" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s convient aux jeunes enfants" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s convient aux enfants" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s convient aux adolescents" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s convient aux adultes" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s convient aux %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "Menu principal" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "_Faire un don à Bazaar ❤️" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "_Préférences" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "Se _connecter avec Flathub" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "_Gérer les données utilisateurs orphelines" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "_Synchroniser les dépôts distants" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "_Raccourcis clavier" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "À _propos de Bazaar" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "_Quitter Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Accès au répertoire %s (Système)" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Sous-dossier %s (Dossier Personnel)" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Dossiers du système hôte" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Configuration du système hôte à partir de /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Sous-dossier %s (Bureau)" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Dossier Bureau" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Sous-dossier %s (Documents)" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Dossier Documents" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Sous-dossier %s (Musique)" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Dossier Musique" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Sous-dossier %s (Images)" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Dossier Images" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Sous-dossier %s (Public)" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Dossier Public" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Sous-dossier %s (Vidéos)" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Dossier Vidéos" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Sous-dossier %s (Modèles)" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Dossier Modèles" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Sous-dossier %s (cache utilisateur)" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Dossier du cache utilisateur" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Sous-dossier %s (configuration utilisateur)" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Dossier de configuration utilisateur" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Sous-dossier %s (données utilisateur)" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Dossier des données utilisateur" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Sous-dossier %s (environnement d’exécution utilisateur)" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Dossier d’envionnement d’exécution utilisateur" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Accès à %s dans le système de fichiers" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Chemin d’accès au système de fichiers inconnu" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Taille du téléchargement" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Volume à télécharger depuis Internet" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Taille après installation" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Taille sur le disque" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Taille des données utilisateur" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Caches, paramètres et autres données" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:178 msgid "Installed" msgstr "Installée" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "Tout afficher" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "Toutes les applis « %s »" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d applications" #: src/bz-application.c:672 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:673 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:704 msgid "translator-credits" msgstr "" "Atom <29772841+AtomHare@users.noreply.github.com>, 2025\n" "Léane GRASSER , 2025\n" "Mimolet , 2025-2026\n" "Irénée THIRION , 2026" #: src/bz-application.c:715 msgid "Special Thanks" msgstr "Remerciements particuliers à" #: src/bz-application.c:773 msgid "Logged Out Successfully!" msgstr "Déconnexion réussie !" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Configuration en cours…" #: src/bz-application.c:979 src/bz-application.c:988 msgid "Set Up Flathub" msgstr "Configurer Flathub" #: src/bz-application.c:982 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub n’a pas été configuré sur ce système. Vous ne pourrez pas parcourir " "et installer des applications dans Bazaar s’il est indisponible.\n" "\n" "Vous pouvez toujours utiliser Bazaar pour parcourir et désinstaller des " "applis déjà installées." #: src/bz-application.c:987 msgid "Later" msgstr "Plus tard" #: src/bz-application.c:1397 src/bz-application.c:3087 msgid "Synchronizing..." msgstr "Synchronisation…" #: src/bz-application.c:1544 src/bz-application.c:3083 #, c-format msgid "Receiving %d entries..." msgstr "Réception de %d applis…" #: src/bz-application.c:1549 msgid "Checking for updates" msgstr "Recherche de mises à jour" #: src/bz-application.c:3089 msgid "Indexing Data..." msgstr "Indexation des données…" #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Page Flathub" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "Site du projet" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Signaler un problème" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "Aide" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "Faire un don" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "Traduire" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "Contact" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "Code Source" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuer" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "Vide" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Aucune sélection" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Votre système ne recommande pas d’applications en particulier, mais vous " "pouvez toujours en chercher sur Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Parcourir Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Hors-ligne" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Navigateur" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Informations sur le développeur non disponibles." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "La propriété de l’identifiant applicatif %s n’a pas été vérifiée et il " "pourrait s’agir d’un paquet géré par la communauté." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "La propriété de l’identifiant applicatif %s a été vérifiée manuellement par " "l’équipe de Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "La propriété de l’identifiant applicatif %1$s a été vérifiée par %2$s " "sur %3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "" "La propriété de l’identifiant applicatif %1$s a été vérifiée en utilisant " "%2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "La propriété de l’identifiant applicatif %s a été vérifiée." #: src/bz-donations-dialog.blp:58 msgid "This Bazaar Release Was Made Possible By Users Like You!" msgstr "Cette mise à jour de Bazaar est possible grâce à vous ! " #: src/bz-donations-dialog.blp:66 msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "J'aime faire Bazaar, mais je ne peux pas le faire seule. Si vous souhaitez " "apporter votre soutient, n'hésitez pas à faire un don à la page Ko-fi du " "projet :" #: src/bz-donations-dialog.blp:76 msgid "Donate to Bazaar" msgstr "Faire un don à Bazaar" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Choisissez une installation" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Plusieurs versions de cette application sont installées. Avec quelle version " "souhaitez-vous poursuivre ?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:197 #: src/bz-transaction-dialog.c:226 src/bz-transaction-dialog.c:271 #: src/bz-transaction-dialog.c:562 msgid "Cancel" msgstr "Annuler" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Pour cet utilisateur seulement" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "cet utilisateur" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "tous les utilisateurs" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Une erreur est survenue" #: src/bz-error.c:89 msgid "Close" msgstr "Fermer" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Copier et fermer" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Connectez-vous avec Flathub pour gérer vos favoris" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Se connecter" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Nombre de favoris" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Désinstaller" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "Soutenez cette application" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Retirer des favoris" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "Favoris" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 msgid "Open App Library" msgstr "Ouvrir la bibliothèque" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:563 msgid "Install All" msgstr "Tout installer" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "Chargement" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "Pas de favoris" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "Les applications que vous marquerez comme favorites apparaîtront ici" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Précédent" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Suivant" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Appli du jour" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "Édition" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Mixage" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "Musique" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "Lecteur" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Enregistreur" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "Séquenceur" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Accordeur" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "Émulateurs" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "Action" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Aventure" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Arcade" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Blocs" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Plateau" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Jeux de cartes" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Jeux pour enfants" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "Logique" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "Jeux de rôle" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Jeux de tir" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "Simulation" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "Sports" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "Jeux de stratégie" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "Audio & Vidéo" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "Média" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Plus d’applis audio & vidéo" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Outils de Développement" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Développer" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Plus d’outils de développement" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Éducation" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Apprendre" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "Plus d’applis éducatives" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Jeux vidéos" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Jouer" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "Plus de jeux" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "Graphisme & Photographie" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Créer" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Plus d’applis de graphisme et photographie" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Réseau" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Plus d’applis réseau" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Productivité" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Travailler" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Plus d’applis de productivité" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "Sciences" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "Plus d’applis scientifiques" #: src/bz-flathub-category.c:128 msgid "System" msgstr "Système" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Plus d’applis système" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "Utilitaires" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Outils" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "Plus d’utilitaires" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Tendances" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Plus de tendances" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populaires" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Plus d’applis populaires" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Ajoutées récemment" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nouveautés" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Plus de nouveautés" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Mises à jour récemment" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Mises à jour" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "Plus d’applis mises à jour" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Mobile" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "Plus d’applis mobiles" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Plus d’applis Adwaita" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "KDE" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "Plus d’applis KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub n’a pas été ajouté" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "Le dépôt Flathub n’a été trouvé dans aucune de vos installations Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub a renvoyé une erreur" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Réessayer de se connecter à Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub est indisponible" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Nous n’avons pas pu nous connecter à Flathub. Vous pouvez toujours gérer et " "rechercher des applications." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Rechercher des applis" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Sur tous vos écrans" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Applis pour vos téléphones et tablettes Linux" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Plus d’applis mobiles" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Nous + jeux = ♥" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Jeux et applis pour lancer vos titres préférés" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Plus de jeux" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "Aucun résultat" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "Essayez une autre recherche" #: src/bz-full-view.blp:59 msgid "Content" msgstr "Contenu" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "L’installation de lots .flatpak n’est pas encore prise en charge" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Soutenir" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Ouvrir" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Télécharger et installer l’application" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Désinstaller l’application" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Installer une autre version" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "Téléchargements par mois" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Ne reçoit plus de mises à jour essentielles" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "L’environnement d’exécution utilisé par cette appli ne reçoit plus de mises " "à jour de sécurité. Son utilisation pourrait devenir risquée." #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "Supprimer les données" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "Étiquettes :" #: src/bz-full-view.c:220 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "%.*f Mio." #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "%.*f mil." #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d téléchargements ces 30 derniers jours" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "Inconnu" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "Taille" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "Informations sur la taille non disponibles" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "Taille du téléchargement de %s" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "Tout public" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "Informations sur la limite d’âge non disponibles" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "Convient à tout public" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "Approprié dès %d ans et plus" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "Inconnue" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "Logiciel libre sous licence %s" #: src/bz-full-view.c:403 msgid "Free software" msgstr "Logiciel libre" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "Logiciel propriétaire" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "Licence spéciale : %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "Libre" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Propriétaire" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Licence spéciale" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "Adaptatif" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "Ordinateur uniquement" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "Fonctionne sur ordinateur, tablette et téléphone" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "Peut ne pas fonctionner sur les appareils mobiles" #: src/bz-full-view.c:472 msgid "No URL" msgstr "Aucune URL" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Cette application est sous une licence FLOSS, la fiabilité de son code " "source peut donc être auditée." #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Cette application est soumise à une licence propriétaire, son code source " "est donc privé et ne peut pas être audité par un tiers indépendant." #: src/bz-full-view.c:498 msgid "More Apps" msgstr "Plus d’applis" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "Plus d’applis par %s" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "D’autres applis de ce développeur" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "D’autres applis par %s" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s n’est pas installé, mais a toujours %s de données présentes." #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Sûr" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "Risque faible" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "Risque moyen" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "Risque élevé" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "D’autres applis" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d application" msgstr[1] "%d applications" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "Montrer moins" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "Montrer plus" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Support matériel" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Prise en charge des claviers" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Requiert un clavier" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Recommande l’utilisation d’un clavier" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Prend en charge les claviers" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Prise en charge des claviers inconnue" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Prise en charge des souris" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Nécessite une souris ou un pointeur" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Recommande l’utilisation d’une souris ou d’un pointeur" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Prend en charge les souris et pointeurs" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Prise en charge des souris et pointeurs inconnue" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Prise en charge des écrans tactiles" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Requiert un écran tactile" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Recommande l’utilisation d’un écran tactile" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Prend en charge les écrans tactiles" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Prise en charge des écrans tactiles inconnue" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Prise en charge des appareils mobiles" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Fonctionne sur les appareils mobiles" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Pourrait ne pas fonctionner correctement sur les appareils mobiles" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Prise en charge des ordinateurs" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Fonctionne bien sur les écrans large" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s fonctionne mieux sur du matériel spécifique" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s fonctionne sur la plupart des appareils" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Ne reçoit plus de mises à jour" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "Rechercher des applis installées" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "Aucune appli trouvée" # "Bibliothèque" est trop long sous un format "mobile" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 msgid "Library" msgstr "Bibliothèque" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "Mises à jour en attente" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "Téléchargements" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "Désinstallées récemment" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "Effacer les tâches effectuées" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "Applis installées" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Aucune application installée ne correspond à « %s »" #: src/bz-library-page.c:165 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u mise à jour disponible" msgstr[1] "%u mises à jour disponibles" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "S’impliquer" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "Licence inconnue" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "Construite par la communauté" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Cette appli est développée de manière ouverte par une communauté " "internationale.\n" "\n" "Vous pouvez participer à son amélioration." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "La licence de cette appli est inconnue" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Cette appli est développée de manière ouverte par une communauté " "internationale, et publiée sous la licence %s.\n" "\n" "Vous pouvez participer à son amélioration." #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Cette appli n’est pas développée de manière ouverte : seuls ses développeurs " "connaissent son fonctionnement. Elle est susceptible de comporter des " "failles de sécurité difficiles à détecter et peut changer sans aucun " "contrôle préalable.\n" "\n" "Vous ne pourrez peut-être pas contribuer à cette application." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Cette appli est développée sous la licence spéciale %s.\n" "\n" "Vous ne pourrez peut-être pas contribuer à cette application." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Se connecter à Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Une erreur s’est produite" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Connectez votre compte Flathub à Bazaar pour gérer vos applications " "favorites." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Terminer" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Bonjour, %s !" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Préférences" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "La connexion réseau est limitée — l’actualisation automatique de la " "logithèque est suspendue" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "Actualiser manuellement" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Filtres de contenus" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Logiciels libres seulement" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Masque les applications propriétaires dans les résultats de recherche" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Logiciels Flathub seulement" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Limite les résultats de recherche aux applications disponibles sur Flathub" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Résultats vérifiés seulement" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Masque les résultats non vérifiés sur Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Masquer les applis en fin de vie" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "" "Masque les applis qui ne sont plus prises en charge par leurs développeurs" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "Recherche" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Retarder l’affichage des résultats de recherche" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "Améliore la performance des résultats en rajoutant un anti-rebond" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Barre de progression" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Choisissez un thème pour la barre de progression !" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Motifs verticaux" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Affiche les couleurs des drapeaux de gauche à droite" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Couleur d’accentuation" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Couleurs de la fierté" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Couleurs de la fierté lesbienne" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Couleurs de la fierté homosexuelle" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Couleurs de la fierté transgenre" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Couleurs de la fierté non binaire" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Couleurs de la fierté bisexuelle" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Couleurs de la fierté asexuelle" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Couleurs de la fierté pansexuelle" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Couleurs de la fierté aromantique" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Couleurs de la fierté fluide" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Couleurs de la fierté polysexuelle" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Couleurs de la fierté omnisexuelle" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Couleurs de la fierté aroace" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Couleurs du drapeau agenre" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Couleurs du drapeau genderqueer" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Couleurs du drapeau intersexe" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Couleurs du drapeau demi-genre" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Couleurs du drapeau biromantique" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Couleurs de la fierté des personnes en situation de handicap" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Couleurs de la fierté femboy" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Couleurs du drapeau neutrois" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:150 msgid "Version History" msgstr "Historique des versions" #: src/bz-releases-list.c:168 #, c-format msgid "Version %s" msgstr "Version %s" #: src/bz-releases-list.c:220 msgid "No details for this release" msgstr "Aucun détail à propos de cette version" #: src/bz-releases-list.c:232 msgid "Get More Information" msgstr "Obtenir plus d’informations" # Dans le contexte d'App Store - "Get" serait plutôt traduit en "Télécharger" ou comme ici en "Installer" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Installer" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "Autorisations inconnues" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "Des autorisations sont manquantes pour cette application." #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Aucune autorisation" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "L’application est entièrement sandboxée" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Accès à Internet" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Peut accéder à Internet" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Aucun accès Internet" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Ne peut pas accéder à Internet" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Accès à l’appareil de l’utilisateur" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "" "Peut accéder à des périphériques tels que des webcams ou des manettes de jeu" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Aucun accès aux périphériques" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Ne peut pas accéder aux périphériques système qui nécessitent des " "autorisations élevées" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Accès aux périphériques d’entrée" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Peut accéder aux périphériques d’entrée" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Accès au microphone et à la lecture audio" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "A accès aux microphones connectés et peut lire des fichiers audio sans " "demander l’autorisation" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Accès aux périphériques du système" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "" "Peut accéder aux périphériques du système qui nécessitent des autorisations " "élevées" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Accès au contenu de l’écran" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Peut accéder au contenu de l’écran ou d’autres fenêtres" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Système de fenêtrage ancien" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Utilise toujours un ancien système de fenêtrage (X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "Autorisations arbitraires" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Peut obtenir des autorisations arbitraires" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Paramètres utilisateur" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Peut accéder aux paramètres utilisateur et les modifier" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Accès complet en lecture/écriture au système de fichiers" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "Peut lire et écrire tout le contenu du système de fichiers" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Accès en lecture/écriture au dossier personnel" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "Peut lire et écrire tout le contenu de votre dossier personnel" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Accès complet en lecture au système de fichiers" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "Peut lire tout le contenu du système de fichiers" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Accès en lecture au dossier personnel" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "Peut lire tout le contenu de votre dossier personnel" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Accès en lecture/écriture au dossier Téléchargements" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "Peut lire et écrire tout le contenu de votre dossier Téléchargements" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Accès en lecture au dossier Téléchargements" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "Peut lire tout le contenu de votre dossier Téléchargements" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "Peut lire et écrire tout le contenu du répertoire" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "Peut lire tout le contenu du répertoire" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Aucun accès au système de fichiers" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "Ne peut pas accéder au système de fichiers" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Utilise les services système" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Peut demander des données à des services système hors portail" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Utilise les services de la session utilisateur" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Peut demander des données à des services de session hors portail" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Aucun accès aux services" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "" "Ne peut ni accéder à des services de session, ni à des services système hors " "portail" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Développeur vérifié" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "L’identité du développeur de cette application a été vérifiée" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Code propriétaire" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Le code source n’est pas public, il ne peut donc pas être vérifié de manière " "indépendante et pourrait ne pas être sécurisé" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Code vérifiable" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Le code source est public et peut être vérifié de manière indépendante, ce " "qui rend l’application plus sûre" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Utilise le service système %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Utilise le service de session %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Utilise le service %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Peut détecter ce service hors portail" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Peut communiquer à ce service hors portail" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Peut posséder ce service hors portail" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Intégration au menu global" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Peut afficher ses menus dans une barre de menus globale" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Intégration aux paramètres KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Peut détecter lorsque les paramètres du bureau KDE changent" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Paramètres généraux KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "" "Peut lire les préférences du bureau KDE telles que les polices et les " "couleurs" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "Service de stockage secret" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "Peut stocker et récupérer ses propres mots de passe à l’aide du trousseau " "système" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Service de notifications sur le bureau" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Peut envoyer des notifications sur le bureau" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Intégration dans la barre d’état système" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Peut afficher une icône dans la barre d’état système" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Intégration de KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "Peut interagir avec les appareils connectés avec KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Sécurité" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Détails" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Licence" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "Identifiant applicatif" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "Plateforme logicielle" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Cette application utilise une version obsolète de la plateforme logicielle " "(SDK) et peut contenir des bogues ou des failles de sécurité qui ne seront " "pas corrigés." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s est sûr" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s n’a pas d’autorisations à risque" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s est probablement sûr" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s pourrait ne pas être sûr" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s n’est pas sûr" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Captures d’écran" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Capture d’écran précédente" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Capture d’écran suivante" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Copier l’image" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Réinitialiser l’affichage" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Zoom arrière" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Zoom avant" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Carrousel de captures d’écran" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Ouvrir la visionneuse de captures d’écran" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Rechercher applis, jeux et logiciels" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Catégories non disponibles" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Cherchez des applis en utilisant l'onglet « Rechercher »." #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Aucune application trouvée" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Aucun résultat trouvé pour « %s » dans Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Copié !" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Copier le lien" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Ouvrir le lien" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Chronologie" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Installations :" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Monde" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f Mio installations en tout" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f mil. installations en tout" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d téléchargements en tout" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Aucun résultat trouvé" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Applis étiquetées « %s »" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "La recherche a échoué" #: src/bz-transaction-dialog.c:151 msgid "Keep Data" msgstr "Conserver les données" #: src/bz-transaction-dialog.c:152 msgid "Allow restoring settings and content" msgstr "Permet la restauration des paramètres et du contenu" #: src/bz-transaction-dialog.c:161 msgid "Delete Data" msgstr "Supprimer les données" #: src/bz-transaction-dialog.c:162 msgid "Permanently remove app data to save space" msgstr "" "Supprime définitivement les données de l’appli pour libérer de l’espace" #: src/bz-transaction-dialog.c:187 #, c-format msgid "Install %s?" msgstr "Installer %s ?" #: src/bz-transaction-dialog.c:192 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Sélectionnez la version à installer. Pourrait installer des composants " "partagés supplémentaires" #: src/bz-transaction-dialog.c:194 msgid "May install additional shared components" msgstr "Pourrait installer des composants partagés supplémentaires" #: src/bz-transaction-dialog.c:215 #, c-format msgid "Remove %s?" msgstr "Désinstaller %s ?" #: src/bz-transaction-dialog.c:218 msgid "Select which version to remove." msgstr "Sélectionnez la version à désinstaller." #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Il ne sera plus possible d’utiliser %s après sa désinstallation." #: src/bz-transaction-dialog.c:243 #, c-format msgid "“%s” is High Risk" msgstr "« %s » présente un risque élevé" #: src/bz-transaction-dialog.c:247 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Cette application dispose d’un accès complet à votre système, y compris à " "tous vos fichiers, à l’historique de votre navigateur, à vos mots de " "passe enregistrés, etc. Elle a également accès à Internet, ce qui " "signifie qu’elle pourrait envoyer vos données à des tiers.\n" "\n" "Comme cette application est propriétaire, il est impossible de vérifier ce " "qu’elle fait avec ces autorisations." #: src/bz-transaction-dialog.c:256 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Cette application utilise l’ancien système de fenêtrage X11, qui lui permet " "d’enregistrer toutes les frappes au clavier, de faire des captures " "d’écran et de surveiller d’autres applications. Elle a également accès à " "Internet, ce qui signifie qu’elle pourrait envoyer vos données à des tiers.\n" "\n" "Comme cette application est propriétaire, il est impossible de vérifier ce " "qu’elle fait avec ces autorisations." #: src/bz-transaction-dialog.c:272 msgid "Install Anyway" msgstr "Installer quand même" #: src/bz-transaction-dialog.c:533 msgid "All apps are already installed" msgstr "Toutes les applis sont déjà installées" #: src/bz-transaction-dialog.c:535 msgid "OK" msgstr "D’accord" #: src/bz-transaction-dialog.c:551 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Installer %u appli ?" msgstr[1] "Installer %u applis ?" #: src/bz-transaction-dialog.c:559 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Les applications suivantes seront installées. Des composants partagés " "supplémentaires pourraient également être installés" #: src/bz-transaction-dialog.c:560 #, c-format msgid "%d addons will be installed." msgstr "%d extensions seront installées." #: src/bz-transaction-dialog.c:561 msgid "Additionally, addons will be installed." msgstr "Des extensions seront aussi installées." #: src/bz-transaction-manager.c:1248 #, c-format msgid "Finished in %.02f seconds" msgstr "Terminé en %.02f secondes" #: src/bz-transaction-tile.blp:125 msgid "App Add-on" msgstr "Extension de l’appli" #: src/bz-transaction-tile.blp:154 msgid "Runtime" msgstr "Environnement d’exécution" #: src/bz-transaction-tile.blp:178 msgid "In Queue" msgstr "En attente" #: src/bz-transaction-tile.blp:202 msgid "Done" msgstr "Terminé" #: src/bz-transaction-tile.blp:243 msgid "Open App" msgstr "Ouvrir l'appli" # Pluriel car on parle d'octets #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s libérés" #: src/bz-transaction.c:342 msgid "Pending" msgstr "En attente" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "Tout mettre à jour" #: src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "Mettre à jour" #: src/bz-updates-card.c:293 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u mise à jour d'environnement d’exécution " msgstr[1] "%u mises à jour d'environnement d’exécution " #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Nettoyer les données orphelines" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "Pas de données orphelines trouvées" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "Données utilisateur" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Les données utilisateur de %s ont été mise à la corbeille" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Mettre les données utilisateurs à la corbeille" # Texte affiché lors du l'écran de chargement - la traduction fourni le contexte nécessaire pour l'utilisateur sans le bombarder de texte # # Un nouveau label sera proposé à Kolunmi. #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "Actualisation..." #: src/bz-window.blp:153 msgid "Curated" msgstr "Sélection" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "Aucune tâche en arrière-plan !" #: src/bz-window.blp:325 msgid "You are running a new version of Bazaar!" msgstr "Bazaar a été mis à jour !" #: src/bz-window.blp:326 msgid "See What's New" msgstr "Voir les nouveautés" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Vous disposez d’une connexion réseau, mais consultez une version mise en " "cache de Flathub" #: src/bz-window.blp:449 msgid "Log Out" msgstr "Se déconnecter" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "Vous ne pouvez supprimer Bazaar depuis Bazaar !" #: src/bz-window.c:891 src/bz-window.c:925 msgid "Can't do that right now!" msgstr "Impossible de faire ceci pour le moment !" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "téléchargements" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Général" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Ouvrir la recherche" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Ouvrir les préférences" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Actualiser" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Open Library" msgstr "Ouvrir la bibliothèque" #: src/gtk/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Afficher les raccourcis" #: src/gtk/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Quit" msgstr "Quitter" kolunmi-bazaar-7b9c8e1/po/ga.po000066400000000000000000002216421514314607700164360ustar00rootroot00000000000000# Irish translations for bazaar package. # Copyright (C) 2026 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2026. # # Aindriú Mac Giolla Eoin , 2026. #: src/bz-installed-page.blp:68 msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-11 20:42+0000\n" "PO-Revision-Date: 2026-01-12 18:32+0000\n" "Last-Translator: Aindriú Mac Giolla Eoin \n" "Language-Team: Irish \n" "Language: ga\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n" "X-Generator: Weblate 5.15.1\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Bogearraí flatpak a chur leis, a bhaint nó a nuashonrú ar an ríomhaire seo" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Córas;Bainisteoir Pacáistí;Faigh Amach;Flatpak;Bogearraí;Stór;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Fuinneog Nua" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Aipeanna a aimsiú agus a shuiteáil" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Siopa aipeanna nua do Linux le fócas ar fheidhmchláir agus breiseáin a " "aimsiú agus a shuiteáil ó chianrialtáin Flatpak, go háirithe Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Leagann sé béim ar thacaíocht a thabhairt do na forbróirí a chuireann ar " "chumas an deasc Linux a bheith indéanta. Tá cluaisín \"coimeádta\" ar fáil i " "Bazaar ar féidir le dáileoirí é a chumrú chun eispéireas níos logánta a " "cheadú." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:697 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "An leathanach baile a thaispeánann aipeanna Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Leathanach aip Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Leathanach cuardaigh" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Leathanach catagóire" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:694 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Bainistigh Breiseáin" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:224 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "Bain" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:166 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:201 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Suiteáil" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:409 src/bz-full-view.c:416 msgid "Age Rating" msgstr "Rátáil Aois" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Foréigean Cartúin" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Gan aon eolas maidir le foréigean cartúin" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Foréigean Fantaisíochta" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Gan aon eolas maidir le foréigean fantaisíochta" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Foréigean Réalaíoch" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Gan aon fhaisnéis maidir le foréigean réalaíoch" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Foréigean a léiríonn fuildhoirteadh" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Gan aon eolas faoi fhuildhoirteadh" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Foréigean Gnéasach" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Gan aon eolas maidir le foréigean gnéasach" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alcól" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Gan aon fhaisnéis maidir le tagairtí d'alcól" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Támhshuanacha" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Gan aon fhaisnéis maidir le tagairtí do dhrugaí mídhleathacha" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tobac" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Gan aon fhaisnéis maidir le tagairtí do tháirgí tobac" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nochtacht" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Gan aon fhaisnéis maidir le nochtas de chineál ar bith" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Téamaí Gnéis" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Gan aon fhaisnéis maidir le tagairtí nó léirithe de chineál gnéasach" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Maslaí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Gan aon fhaisnéis maidir le maslaí de chineál ar bith" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Greann Míchuí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Gan aon eolas maidir le greann míchuí" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Idirdhealú" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Gan aon fhaisnéis maidir le teanga idirdhealaitheach d'aon chineál" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Fógraíocht" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Gan aon fhaisnéis maidir le fógraíocht d'aon chineál" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Cearrbhachas" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Gan aon fhaisnéis maidir le cearrbhachas d'aon chineál" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Ceannach" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Gan aon eolas maidir leis an gcumas airgead a chaitheamh" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Comhrá idir Úsáideoirí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "" "Gan aon eolas maidir le bealaí chun comhrá a dhéanamh le húsáideoirí eile" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Comhrá Fuaime Idir Úsáideoirí" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Gan aon eolas maidir le bealaí chun labhairt le húsáideoirí eile" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Sonraí Teagmhála" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Gan aon fhaisnéis maidir le hainmneacha úsáideora ná seoltaí ríomhphoist " "líonraí sóisialta a roinnt" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Faisnéis Aitheantais" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "" "Gan aon fhaisnéis maidir le faisnéis úsáideora a roinnt le tríú páirtithe" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Comhroinnt Suímh" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Gan aon fhaisnéis maidir le suíomh fisiceach a roinnt le húsáideoirí eile" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Striapachas" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Gan aon fhaisnéis maidir le tagairtí do striapachas" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Adaltranas" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Gan aon fhaisnéis maidir le tagairtí d'adhaltranas" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Carachtair Ghnéasaithe" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Gan aon fhaisnéis maidir le carachtair ghnéasaithe" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Mí-naomhú" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Gan aon fhaisnéis maidir le tagairtí do dhí-sheacracht" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Iarsmaí Daonna" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Gan aon fhaisnéis maidir le hiarsmaí daonna marbha infheicthe" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Sclábhaíocht" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Gan aon fhaisnéis maidir le tagairtí don sclábhaíocht" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Ní áirítear tagairtí do dhrugaí" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Ní chuimsíonn sé mionnú, maslaí, agus cineálacha eile teanga ghéar" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Ní áirítear fógraí ná idirbhearta airgid" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Ní chuimsíonn sé gnéas ná nochtas" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Ní chuimsíonn sé feidhmiúlacht comhrá neamhrialaithe" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Ní áirítear foréigean" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drugaí" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Teanga Láidir" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Airgead" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Sóisialta" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Foréigean" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:399 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Gach" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "Tá rátáil aoise anaithnid ag %s" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "Tá %s oiriúnach do gach duine" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "Tá %s oiriúnach do leanaí óga" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "Tá %s oiriúnach do pháistí" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "Tá %s oiriúnach do dhéagóirí" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "Tá %s oiriúnach do dhaoine fásta" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "Tá %s oiriúnach do %s" #: src/bz-age-rating-dialog.c:849 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:480 msgid "Main Menu" msgstr "Príomh-Roghchlár" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:553 msgid "_Donate to Bazaar ❤️" msgstr "_Tabhair síntiús do Bazaar ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Athnuachan Ábhar" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:560 msgid "_Preferences" msgstr "_Sainroghanna" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:581 msgid "_Keyboard Shortcuts" msgstr "_Aicearraí Méarchláir" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:586 msgid "_About Bazaar" msgstr "_Maidir le Bazaar" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:593 msgid "_Quit Bazaar" msgstr "_Scoir den Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Fillteán córais %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Fo-fhillteán baile %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Fillteáin chórais óstach" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Cumraíocht an chórais óstach ó /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Fo-fhillteán deisce %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Fillteán deisce" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Fo-fhillteán doiciméad %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Fillteán na ndoiciméad" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Fo-fhillteán ceoil %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Fillteán ceoil" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Fo-fhillteán pictiúr %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Fillteán pictiúr" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Fo-fhillteán Comhroinnte Poiblí %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Fillteán Comhroinnte Poiblí" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Fo-fhillteán físeáin %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Fillteán físeáin" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Fo-fhillteán teimpléid %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Fillteán teimpléid" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Fo-fhillteán taisce úsáideora %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Fillteán taisce úsáideora" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Fo-fhillteán cumraíochta úsáideora %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Fillteán cumraíochta úsáideora" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Fo-fhillteán sonraí úsáideora %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Fillteán sonraí úsáideora" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Fo-fhillteán ama rite úsáideora %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Fillteán rith-ama úsáideora" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Rochtain ar chóras comhad ar %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Cosán anaithnid córas comhad" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Méid Íoslódála" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Méid le híoslódáil ón idirlíon" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Méid Suiteáilte" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Méid ar Diosca" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Méid Sonraí Úsáideora" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Taisceáin, socruithe, agus sonraí eile aipeanna" #: src/bz-app-tile.blp:85 src/bz-full-view.c:363 src/bz-installed-page.blp:85 #: src/bz-window.blp:296 msgid "Installed" msgstr "Suiteáilte" #: src/bz-apps-page.blp:103 msgid "Show All" msgstr "Taispeáin Gach Rud" #: src/bz-apps-page.c:232 #, c-format msgid "All \"%s\"" msgstr "Gach \"%s\"" #: src/bz-apps-page.c:506 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Feidhmchlár" #: src/bz-application.c:668 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:669 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:700 msgid "translator-credits" msgstr "Aindriú Mac Giolla Eoin" #: src/bz-application.c:711 msgid "Special Thanks" msgstr "Buíochas Speisialta" #: src/bz-application.c:769 msgid "Logged Out Successfully!" msgstr "Logáilte Amach go Rathúil!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Ag déanamh socraithe..." #: src/bz-application.c:975 src/bz-application.c:984 msgid "Set Up Flathub" msgstr "Socraigh Flathub" #: src/bz-application.c:978 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Níl Flathub socraithe ar an gcóras seo. Ní bheidh tú in ann brabhsáil agus " "feidhmchláir a shuiteáil i Bazaar mura bhfuil sé ar fáil.\n" "\n" "Is féidir leat Bazaar a úsáid fós chun brabhsáil agus aipeanna atá " "suiteáilte cheana féin a bhaint." #: src/bz-application.c:983 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Níos déanaí" #: src/bz-application.c:1385 src/bz-application.c:3059 msgid "Synchronizing..." msgstr "Ag sioncrónú..." #: src/bz-application.c:1524 src/bz-application.c:3055 #, c-format msgid "Receiving %d entries..." msgstr "Ag fáil %d iontráil..." #: src/bz-application.c:1529 msgid "Checking for updates" msgstr "Ag seiceáil le haghaidh nuashonruithe" #: src/bz-application.c:3061 msgid "Indexing Data..." msgstr "Ag Innéacsú Sonraí..." #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:65 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Folamh" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Gan Coimeádadh" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Níl aon fhaisnéis choimeádta curtha ar fáil ar an gcóras seo. Is féidir leat " "brabhsáil a dhéanamh ar fheidhmchláir ar Flathub fós" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Brabhsáil Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "As líne" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Brabhsálaí" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Níl faisnéis forbróra ar fáil." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Níl úinéireacht an aitheantais aip %s fíoraithe agus d'fhéadfadh gur " "pacáiste pobail atá ann." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Tá úinéireacht an aitheantais aip %s fíoraithe de láimh ag foireann Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Tá úinéireacht an aitheantais aip %1$s fíoraithe ag %2$s ar %3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "Tá úinéireacht ID an aip %1$s fíoraithe ag baint úsáide as %2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Tá úinéireacht an aitheantais aip %s fíoraithe." #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Roghnaigh Suiteáil" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Tá roinnt leaganacha den aip seo suiteáilte agat. Cé acu ceann ar mhaith " "leat leanúint ar aghaidh leis?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:200 #: src/bz-transaction-dialog.c:223 src/bz-transaction-dialog.c:268 msgid "Cancel" msgstr "Cealaigh" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Tharla Earráid" #: src/bz-error.c:89 msgid "Close" msgstr "Dún" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Cóipeáil agus Dún" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Logáil isteach le Flathub chun na cinn is fearr leat a bhainistiú" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Logáil Isteach" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Líon na bhFear is Ansa liom" #: src/bz-favorites-tile.c:164 msgid "Uninstall" msgstr "Díshuiteáil" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Tacaigh leis an iarratas seo" #: src/bz-favorites-tile.blp:118 msgid "Remove from Favorites" msgstr "Bain as na Ceanáin" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:75 #: src/bz-window.blp:611 msgid "Favorites" msgstr "Ceanáin" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:457 msgid "Toggle transaction sidebar" msgstr "Scoránaigh an taobhbharra idirbhirt" #: src/bz-favorites-page.blp:53 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Ag luchtú" #: src/bz-favorites-page.blp:68 msgid "No Favorites" msgstr "Gan aon Ceanáin" #: src/bz-favorites-page.blp:69 msgid "Applications you mark as favorite will appear here" msgstr "Beidh feidhmchláir a mharcálann tú mar is fearr leat le feiceáil anseo" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Roimhe Seo" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Ar Aghaidh" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Aip an Lae" #: src/bz-flathub-category.c:79 msgid "Audio & Video" msgstr "Fuaim & Físeán" #: src/bz-flathub-category.c:79 msgid "Media" msgstr "Meáin" #: src/bz-flathub-category.c:79 msgid "More Audio & Video" msgstr "Tuilleadh Fuaime & Físeáin" #: src/bz-flathub-category.c:80 msgid "Developer Tools" msgstr "Uirlisí Forbróra" #: src/bz-flathub-category.c:80 msgid "Develop" msgstr "Forbair" #: src/bz-flathub-category.c:80 msgid "More Developer Tools" msgstr "Tuilleadh Uirlisí Forbróra" #: src/bz-flathub-category.c:81 msgid "Education" msgstr "Oideachas" #: src/bz-flathub-category.c:81 msgid "Learn" msgstr "Foghlaim" #: src/bz-flathub-category.c:81 msgid "More Education" msgstr "Tuilleadh Oideachais" #: src/bz-flathub-category.c:82 msgid "Gaming" msgstr "Cluichíocht" #: src/bz-flathub-category.c:82 msgid "Play" msgstr "Imir" #: src/bz-flathub-category.c:82 msgid "More Gaming" msgstr "Tuilleadh Cluichíocht" #: src/bz-flathub-category.c:83 msgid "Graphics & Photography" msgstr "Grafaicí & Grianghrafadóireacht" #: src/bz-flathub-category.c:83 msgid "Create" msgstr "Cruthaigh" #: src/bz-flathub-category.c:83 msgid "More Graphics & Photography" msgstr "Tuilleadh Grafaicí & Grianghrafadóireachta" #: src/bz-flathub-category.c:84 msgid "Networking" msgstr "Líonrú" #: src/bz-flathub-category.c:84 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:84 msgid "More Networking" msgstr "Tuilleadh Líonraithe" #: src/bz-flathub-category.c:85 msgid "Productivity" msgstr "Táirgiúlacht" #: src/bz-flathub-category.c:85 msgid "Work" msgstr "Obair" #: src/bz-flathub-category.c:85 msgid "More Productivity" msgstr "Tuilleadh Táirgiúlachta" #: src/bz-flathub-category.c:86 msgid "Science" msgstr "Eolaíocht" #: src/bz-flathub-category.c:86 msgid "More Science" msgstr "Tuilleadh Eolaíochta" #: src/bz-flathub-category.c:87 msgid "System" msgstr "Córas" #: src/bz-flathub-category.c:87 msgid "More System" msgstr "Tuilleadh Córas" #: src/bz-flathub-category.c:88 msgid "Utilities" msgstr "Fóntais" #: src/bz-flathub-category.c:88 msgid "Tools" msgstr "Uirlisí" #: src/bz-flathub-category.c:88 msgid "More Utilities" msgstr "Tuilleadh Fóntais" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Ag treochtáil" #: src/bz-flathub-category.c:89 msgid "More Trending" msgstr "Tuilleadh Treochtaí" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Coitianta" #: src/bz-flathub-category.c:90 msgid "More Popular" msgstr "Níos Coitianta" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Curtha leis le Déanaí" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nua" #: src/bz-flathub-category.c:91 msgid "More New" msgstr "Tuilleadh Nua" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Nuashonraithe le Déanaí" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Nuashonraithe" #: src/bz-flathub-category.c:92 msgid "More Updated" msgstr "Tuilleadh Nuashonraithe" #: src/bz-flathub-category.c:93 msgid "Mobile" msgstr "Soghluaiste" #: src/bz-flathub-category.c:93 msgid "More Mobile" msgstr "Níos Soghluaiste" #: src/bz-flathub-category.c:94 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:94 msgid "More Adwaita" msgstr "Tuilleadh Adwaita" #: src/bz-flathub-category.c:95 msgid "KDE Apps" msgstr "Aipeanna KDE" #: src/bz-flathub-category.c:95 msgid "More KDE Apps" msgstr "Tuilleadh Aipeanna KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Níor Cuireadh Flathub Leis" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "Ní bhfuarthas an cianrialtán Flathub ar aon cheann de do shuiteálacha Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Thug Flathub earráid ar ais" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Déan iarracht eile ar nasc Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub Gan Fáil" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Ní raibh muid in ann ceangal le Flathub. Is féidir leat feidhmchláir a " "bhainistiú agus a chuardach fós." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Cuardaigh Aipeanna" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Ar an mBóthar" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Aipeanna do do ghutháin agus táibléid Linux" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Tuilleadh Aipeanna Soghluaiste" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Is breá linn ♥ Cluichí" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Cluichí agus aipeanna chun do theidil is fearr leat a rith" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Tuilleadh Cluichí" #: src/bz-flatpak-entry.c:590 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Leathanach Flathub" #: src/bz-flatpak-entry.c:611 msgctxt "Project URL Type" msgid "Project Website" msgstr "Suíomh Gréasáin an Tionscadail" #: src/bz-flatpak-entry.c:615 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rianaitheoir Fadhbanna" #: src/bz-flatpak-entry.c:619 msgctxt "Project URL Type" msgid "FAQ" msgstr "Ceisteanna Coitianta" #: src/bz-flatpak-entry.c:623 msgctxt "Project URL Type" msgid "Help" msgstr "Cabhair" #: src/bz-flatpak-entry.c:627 msgctxt "Project URL Type" msgid "Donate" msgstr "Tabhair Síntiús" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Translate" msgstr "Aistrigh" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "Contact" msgstr "Teagmháil" #: src/bz-flatpak-entry.c:641 msgctxt "Project URL Type" msgid "Source Code" msgstr "Cód Foinse" #: src/bz-flatpak-entry.c:647 msgctxt "Project URL Type" msgid "Contribute" msgstr "Cuir leis" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Gan Torthaí" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Bain triail as ceist chuardaigh dhifriúil" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Ábhar" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Tacaíocht" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Oscail" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Íoslódáil & Suiteáil Feidhmchlár" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Díshuiteáil Feidhmchlár" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Suiteáil Leagan Eile" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "Íoslódálacha /mí" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Stopadh ag fáil nuashonruithe lárnacha" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Úsáideann an aip seo am rith nach bhfaigheann nuashonruithe ná socruithe " "slándála a thuilleadh. D’fhéadfadh sé a bheith neamhshábháilte le húsáid." #: src/bz-full-view.blp:627 msgid "Trash Data" msgstr "Sonraí Bruscair" #: src/bz-full-view.blp:769 msgid "Tags:" msgstr "Clibeanna:" #: src/bz-full-view.c:307 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:314 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:321 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:331 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d íoslódálacha le 30 lá anuas" #: src/bz-full-view.c:363 msgid "Download" msgstr "Íoslódáil" #: src/bz-full-view.c:381 #, c-format msgid "Download size of %s" msgstr "Méid íoslódála %s" #: src/bz-full-view.c:414 msgid "All Ages" msgstr "Gach Aois" #: src/bz-full-view.c:426 msgid "Age rating information unavailable" msgstr "Níl faisnéis faoi rátáil aoise ar fáil" #: src/bz-full-view.c:431 msgid "Suitable for all ages" msgstr "Oiriúnach do gach aois" #: src/bz-full-view.c:433 #, c-format msgid "Suitable for ages %d and up" msgstr "Oiriúnach do dhaoine aois %d agus os a chionn" #: src/bz-full-view.c:466 src/bz-full-view.c:471 src/bz-full-view.c:499 #: src/bz-full-view.c:510 msgid "Unknown" msgstr "Anaithnid" #: src/bz-full-view.c:476 #, c-format msgid "Free software licensed under %s" msgstr "Bogearraí saor in aisce ceadúnaithe faoi %s" #: src/bz-full-view.c:481 msgid "Free software" msgstr "Bogearraí saor in aisce" #: src/bz-full-view.c:484 msgid "Proprietary Software" msgstr "Bogearraí Dílseánaigh" #: src/bz-full-view.c:487 #, c-format msgid "Special License: %s" msgstr "Ceadúnas Speisialta: %s" #: src/bz-full-view.c:504 msgid "Free" msgstr "Saor in aisce" #: src/bz-full-view.c:507 src/bz-license-dialog.c:190 msgid "Proprietary" msgstr "Dílseánaigh" #: src/bz-full-view.c:512 src/bz-license-dialog.c:192 msgid "Special License" msgstr "Ceadúnas Speisialta" #: src/bz-full-view.c:532 msgid "Adaptive" msgstr "Oiriúnaitheach" #: src/bz-full-view.c:532 msgid "Desktop Only" msgstr "Deasc Amháin" #: src/bz-full-view.c:538 msgid "Works on desktop, tablets, and phones" msgstr "Oibríonn sé ar dheasc, táibléid agus fóin" #: src/bz-full-view.c:539 msgid "May not work on mobile devices" msgstr "B’fhéidir nach n-oibreoidh sé ar ghléasanna soghluaiste" #: src/bz-full-view.c:550 msgid "No URL" msgstr "Gan URL" #: src/bz-full-view.c:568 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Tá ceadúnas FLOSS ag an bhfeidhmchlár seo, rud a chiallaíonn gur féidir an " "cód foinse a iniúchadh ar mhaithe le sábháilteacht." #: src/bz-full-view.c:569 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Tá ceadúnas dílseánaigh ag an bhfeidhmchlár seo, rud a chiallaíonn go " "bhforbraítear an cód foinse go príobháideach agus nach féidir le tríú páirtí " "neamhspleách é a iniúchadh." #: src/bz-full-view.c:576 msgid "More Apps" msgstr "Tuilleadh Aipeanna" #: src/bz-full-view.c:577 #, c-format msgid "More Apps by %s" msgstr "Tuilleadh Aipeanna ó %s" #: src/bz-full-view.c:584 msgid "Other Apps by this Developer" msgstr "Aipeanna Eile ón bhForbróir seo" #: src/bz-full-view.c:586 src/bz-full-view.c:786 #, c-format msgid "Other Apps by %s" msgstr "Aipeanna Eile ó %s" #: src/bz-full-view.c:595 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "Níl %s suiteáilte, ach tá %s sonraí ann fós." #: src/bz-full-view.c:668 src/bz-full-view.c:685 msgid "N/A" msgstr "N/B" #: src/bz-full-view.c:675 src/bz-full-view.c:677 src/bz-full-view.c:679 msgid "Low Risk" msgstr "Riosca Íseal" #: src/bz-full-view.c:681 msgid "Medium Risk" msgstr "Riosca Meánach" #: src/bz-full-view.c:683 msgid "High Risk" msgstr "Ardriosca" #: src/bz-full-view.c:788 msgid "Other Apps" msgstr "Aipeanna Eile" #: src/bz-full-view.c:790 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Feidhmchlár" msgstr[1] "%d Feidhmchláir" msgstr[2] "%d Feidhmchláir" #: src/bz-full-view.c:1129 msgid "Show Less" msgstr "Taispeáin Níos Lú" #: src/bz-full-view.c:1129 msgid "Show More" msgstr "Taispeáin Tuilleadh" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Tacaíocht Crua-earraí" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Tacaíocht méarchláir" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Éilíonn méarchláir" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Molann méarchláir" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Tacaíonn méarchláir" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Tacaíocht anaithnid do mhéarchláir" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Tacaíocht luiche" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Teastaíonn lucha nó gléasanna pointeála" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Molann lucha nó gléasanna pointeála" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Tacaíonn sé le lucha nó le gléasanna pointeála" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Tacaíocht anaithnid do lucha nó do ghléasanna pointeála" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Tacaíocht scáileáin tadhaill" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Éilíonn scáileáin tadhaill" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Molann scáileáin tadhaill" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Tacaíonn sé le scáileáin tadhaill" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Tacaíocht anaithnid do scáileáin tadhaill" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Tacaíocht shoghluaiste" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Oibríonn sé ar ghléasanna soghluaiste" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "B’fhéidir nach n-oibreoidh sé go maith ar ghléasanna soghluaiste" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Tacaíocht deisce" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Oibríonn go maith ar scáileáin mhóra" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "Oibríonn %s is fearr ar chrua-earraí sonracha" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "Oibríonn %s ar an gcuid is mó de na gléasanna" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "Cuardaigh aipeanna suiteáilte" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "Níor aimsíodh aon aipeanna" #: src/bz-installed-page.c:154 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "Níor aimsíodh aon mheaitseálacha do \"%s\" i liosta na n-aipeanna suiteáilte" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Stopadh ag fáil nuashonruithe" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Bígí Páirteach" #: src/bz-license-dialog.c:184 msgid "Unknown License" msgstr "Ceadúnas Anaithnid" #: src/bz-license-dialog.c:187 msgid "Community Built" msgstr "Tógtha ag an bPobal" #: src/bz-license-dialog.c:235 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Forbraíodh an aip seo go hoscailte ag pobal idirnáisiúnta.\n" "\n" "Is féidir leat páirt a ghlacadh agus cabhrú le feabhas a chur uirthi." #: src/bz-license-dialog.c:238 msgid "The license of this app is not known" msgstr "Níl ceadúnas an aip seo ar eolas" #: src/bz-license-dialog.c:244 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Forbraíodh an aip seo go hoscailte ag pobal idirnáisiúnta, agus eisíodh í " "faoin gceadúnas %s.\n" "\n" "Is féidir leat páirt a ghlacadh agus cabhrú le feabhas a chur uirthi." #: src/bz-license-dialog.c:252 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Níor forbraíodh an aip seo go hoscailte, mar sin níl a fhios ag ach a " "forbróirí conas a oibríonn sé. D’fhéadfadh sé a bheith neamhshábháilte ar " "bhealaí atá deacair a bhrath, agus d’fhéadfadh sé athrú gan mhaoirseacht.\n" "\n" "B’fhéidir go mbeidh tú in ann cur leis an aip seo nó nach mbeidh." #: src/bz-license-dialog.c:258 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Forbraíodh an aip seo faoin gceadúnas speisialta %s.\n" "\n" "B’fhéidir go mbeidh tú in ann cur leis an aip seo nó nach mbeidh." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Ceangail le Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Chuaigh rud éigin mícheart" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Ceangail do chuntas Flathub le Bazaar chun do chuid aipeanna is fearr leat a " "bhainistiú." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Críochnaigh" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Haigh, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Roghanna" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Tá an nasc líonra méadraithe — tá sioncrónú uathoibríoch sonraí stórála ar " "sos" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:491 msgid "Sync Manually" msgstr "Sioncrónaigh de Láimh" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Scagairí Ábhair" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Bogearraí Saor in Aisce Amháin" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Folaigh feidhmchláir dhílseánaigh agus tú ag brabhsáil agus ag cuardach" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Torthaí Flathub Amháin" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Teorainn a chur le cuardach agus torthaí brabhsála d’fheidhmchláir atá ar " "fáil ar Flathub amháin" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Torthaí Fíoraithe Amháin" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Folaigh torthaí nach bhfuil fíoraithe ar Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Folaigh Aipeanna EOL" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Folaigh aipeanna nach dtacaíonn a bhforbróirí leo a thuilleadh" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:311 msgid "Search" msgstr "Cuardaigh" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Moill ar Thorthaí Cuardaigh" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "Feabhas a chur ar fheidhmíocht na dtorthaí trí théarmaí cuardaigh a dhí-" "bhreabadh" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Barra Dul Chun Cinn" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Roghnaigh téama don bharra dul chun cinn!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Dath Aicinn" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Dathanna Bród" #: src/bz-preferences-dialog.c:34 msgid "Pride Colors (Horizontal)" msgstr "Dathanna Bród (Cothrománach)" #: src/bz-preferences-dialog.c:35 msgid "Lesbian Pride Colors" msgstr "Dathanna Bród Leispiach" #: src/bz-preferences-dialog.c:36 msgid "Lesbian Pride Colors (Horizontal)" msgstr "Dathanna Bród Leispiach (Cothrománach)" #: src/bz-preferences-dialog.c:37 msgid "Male Homosexual Pride Colors" msgstr "Dathanna Bród Fir Homaighnéasacha" #: src/bz-preferences-dialog.c:38 msgid "Male Homosexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Fir Homaighnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:39 msgid "Transgender Pride Colors" msgstr "Dathanna Bród Trasinscne" #: src/bz-preferences-dialog.c:40 msgid "Transgender Pride Colors (Horizontal)" msgstr "Dathanna Bród Trasinscne (Cothrománach)" #: src/bz-preferences-dialog.c:41 msgid "Nonbinary Pride Colors" msgstr "Dathanna Bród Neamhdhénártha" #: src/bz-preferences-dialog.c:42 msgid "Nonbinary Pride Colors (Horizontal)" msgstr "Dathanna Bród Neamhdhénártha (Cothrománach)" #: src/bz-preferences-dialog.c:43 msgid "Bisexual Pride Colors" msgstr "Dathanna Bród Déghnéasacha" #: src/bz-preferences-dialog.c:44 msgid "Bisexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Déghnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:45 msgid "Asexual Pride Colors" msgstr "Dathanna Bród Neamhghnéasacha" #: src/bz-preferences-dialog.c:46 msgid "Asexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Asexual (Cothrománach)" #: src/bz-preferences-dialog.c:47 msgid "Pansexual Pride Colors" msgstr "Dathanna Bród Panghnéasacha" #: src/bz-preferences-dialog.c:48 msgid "Pansexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Panghnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:49 msgid "Aromantic Pride Colors" msgstr "Dathanna Bród Cumhra" #: src/bz-preferences-dialog.c:50 msgid "Aromantic Pride Colors (Horizontal)" msgstr "Dathanna Bród Cumhra (Cothrománach)" #: src/bz-preferences-dialog.c:51 msgid "Genderfluid Pride Colors" msgstr "Dathanna Bród Inscnefluid" #: src/bz-preferences-dialog.c:52 msgid "Genderfluid Pride Colors (Horizontal)" msgstr "Dathanna Bród Inscnefluid (Cothrománach)" #: src/bz-preferences-dialog.c:53 msgid "Polysexual Pride Colors" msgstr "Dathanna Bród Ilghnéasacha" #: src/bz-preferences-dialog.c:54 msgid "Polysexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Ilghnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:55 msgid "Omnisexual Pride Colors" msgstr "Dathanna Bród Uileghnéasacha" #: src/bz-preferences-dialog.c:56 msgid "Omnisexual Pride Colors (Horizontal)" msgstr "Dathanna Bród Uileghnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:57 msgid "Aroace Pride Colors" msgstr "Dathanna Bród Aroace" #: src/bz-preferences-dialog.c:58 msgid "Aroace Pride Colors (Horizontal)" msgstr "Dathanna Aroace Pride (Cothrománach)" #: src/bz-preferences-dialog.c:59 msgid "Agender Pride Colors" msgstr "Dathanna Bród Agender" #: src/bz-preferences-dialog.c:60 msgid "Agender Pride Colors (Horizontal)" msgstr "Dathanna Bród Agender (Cothrománach)" #: src/bz-preferences-dialog.c:61 msgid "Genderqueer Pride Colors" msgstr "Dathanna Bród Inscnequeer" #: src/bz-preferences-dialog.c:62 msgid "Genderqueer Pride Colors (Horizontal)" msgstr "Dathanna Bród Inscnequeer (Cothrománach)" #: src/bz-preferences-dialog.c:63 msgid "Intersex Pride Colors" msgstr "Dathanna Bród Idirghnéasacha" #: src/bz-preferences-dialog.c:64 msgid "Intersex Pride Colors (Horizontal)" msgstr "Dathanna Bród Idirghnéasacha (Cothrománach)" #: src/bz-preferences-dialog.c:65 msgid "Demigender Pride Colors" msgstr "Dathanna Bród Demi-Inscne" #: src/bz-preferences-dialog.c:66 msgid "Demigender Pride Colors (Horizontal)" msgstr "Dathanna Bród Demigender (Cothrománach)" #: src/bz-preferences-dialog.c:67 msgid "Biromantic Pride Colors" msgstr "Dathanna Bród Birománsacha" #: src/bz-preferences-dialog.c:68 msgid "Biromantic Pride Colors (Horizontal)" msgstr "Dathanna Bród Biormantach (Cothrománach)" #: src/bz-preferences-dialog.c:69 msgid "Disability Pride Colors" msgstr "Dathanna Bród Míchumais" #: src/bz-preferences-dialog.c:70 msgid "Disability Pride Colors (Horizontal)" msgstr "Dathanna Bród Míchumais (Cothrománach)" #: src/bz-preferences-dialog.c:71 msgid "Femboy Pride Colors" msgstr "Dathanna Bród Femboy" #: src/bz-preferences-dialog.c:72 msgid "Femboy Pride Colors (Horizontal)" msgstr "Dathanna Bród Femboy (Cothrománach)" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "Stair Leagan" #: src/bz-releases-list.c:136 #, c-format msgid "Version %s" msgstr "Leagan %s" #: src/bz-releases-list.c:174 msgid "No details for this release" msgstr "Gan aon sonraí don eisiúint seo" #: src/bz-releases-list.c:186 msgid "Get More Information" msgstr "Faigh Tuilleadh Eolais" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Faigh" #: src/bz-safety-calculator.c:77 msgid "Unknown Permissions" msgstr "Ceadanna Anaithnid" #: src/bz-safety-calculator.c:78 msgid "Permissions are missing for this app." msgstr "Tá ceadanna ar iarraidh don aip seo." #: src/bz-safety-calculator.c:91 msgid "No Permissions" msgstr "Gan Ceadanna" #: src/bz-safety-calculator.c:92 msgid "App is fully sandboxed" msgstr "Tá an aip bosca gainimh go hiomlán" #: src/bz-safety-calculator.c:98 msgid "Network Access" msgstr "Rochtain Líonra" #: src/bz-safety-calculator.c:99 msgid "Can access the internet" msgstr "Is féidir rochtain a fháil ar an idirlíon" #: src/bz-safety-calculator.c:101 msgid "No Network Access" msgstr "Gan Rochtain Líonra" #: src/bz-safety-calculator.c:102 msgid "Cannot access the internet" msgstr "Ní féidir rochtain a fháil ar an idirlíon" #: src/bz-safety-calculator.c:107 msgid "User Device Access" msgstr "Rochtain Gléas Úsáideora" #: src/bz-safety-calculator.c:108 msgid "Can access devices such as webcams or gaming controllers" msgstr "" "Is féidir rochtain a fháil ar fheistí ar nós ceamaraí gréasáin nó rialtóirí " "cearrbhachais" #: src/bz-safety-calculator.c:110 msgid "No User Device Access" msgstr "Gan Rochtain ar Ghléas Úsáideora" #: src/bz-safety-calculator.c:111 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Ní féidir rochtain a fháil ar fheistí ar nós ceamaraí gréasáin nó rialtóirí " "cearrbhachais" #: src/bz-safety-calculator.c:116 msgid "Input Device Access" msgstr "Rochtain ar Ghléas Ionchuir" #: src/bz-safety-calculator.c:117 msgid "Can access input devices" msgstr "Is féidir rochtain a fháil ar fheistí ionchuir" #: src/bz-safety-calculator.c:123 msgid "Microphone Access and Audio Playback" msgstr "Rochtain Micreafóin agus Athsheinm Fuaime" #: src/bz-safety-calculator.c:124 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "Is féidir éisteacht le micreafóin agus fuaim a sheinm gan cead a iarraidh" #: src/bz-safety-calculator.c:130 msgid "System Device Access" msgstr "Rochtain ar Ghléas an Chórais" #: src/bz-safety-calculator.c:131 msgid "Can access system devices which require elevated permissions" msgstr "" "Is féidir rochtain a fháil ar ghléasanna córais a bhfuil ceadanna ardaithe " "ag teastáil uathu" #: src/bz-safety-calculator.c:137 msgid "Screen Contents Access" msgstr "Rochtain ar Ábhar an Scáileáin" #: src/bz-safety-calculator.c:138 msgid "Can access the contents of the screen or other windows" msgstr "Is féidir rochtain a fháil ar ábhar an scáileáin nó fuinneoga eile" #: src/bz-safety-calculator.c:144 msgid "Legacy Windowing System" msgstr "Córas Fuinneoige Oidhreachta" #: src/bz-safety-calculator.c:145 msgid "Uses a legacy windowing system" msgstr "Úsáideann córas fuinneoige oidhreachta" #: src/bz-safety-calculator.c:151 msgid "Arbitrary Permissions" msgstr "Ceadanna Treallacha" #: src/bz-safety-calculator.c:152 msgid "Can acquire arbitrary permissions" msgstr "Is féidir ceadanna treallacha a fháil" #: src/bz-safety-calculator.c:158 msgid "User Settings" msgstr "Socruithe Úsáideora" #: src/bz-safety-calculator.c:159 msgid "Can access and change user settings" msgstr "Is féidir rochtain a fháil ar shocruithe úsáideora agus iad a athrú" #: src/bz-safety-calculator.c:165 msgid "Full File System Read/Write Access" msgstr "Rochtain Léitheoireachta/Scríofa ar an gCóras Comhad Iomlán" #: src/bz-safety-calculator.c:166 msgid "Can read and write all data on the file system" msgstr "" "Is féidir leis na sonraí go léir ar an gcóras comhad a léamh agus a scríobh" #: src/bz-safety-calculator.c:173 msgid "Home Folder Read/Write Access" msgstr "Rochtain Léitheoireachta/Scríofa ar Fhillteán Baile" #: src/bz-safety-calculator.c:174 msgid "Can read and write all data in your home directory" msgstr "" "Is féidir leat na sonraí go léir i do eolaire baile a léamh agus a scríobh" #: src/bz-safety-calculator.c:181 msgid "Full File System Read Access" msgstr "Rochtain Léitheoireachta Iomlán an Chórais Comhad" #: src/bz-safety-calculator.c:182 msgid "Can read all data on the file system" msgstr "Is féidir leis na sonraí go léir ar an gcóras comhad a léamh" #: src/bz-safety-calculator.c:190 msgid "Home Folder Read Access" msgstr "Rochtain Léitheoireachta Fillteán Baile" #: src/bz-safety-calculator.c:191 msgid "Can read all data in your home directory" msgstr "Is féidir leat na sonraí go léir i do eolaire baile a léamh" #: src/bz-safety-calculator.c:199 msgid "Download Folder Read/Write Access" msgstr "Rochtain Léitheoireachta/Scríofa ar an bhFillteán Íoslódála" #: src/bz-safety-calculator.c:200 msgid "Can read and write all data in your downloads directory" msgstr "" "Is féidir leat na sonraí go léir i do eolaire íoslódálacha a léamh agus a " "scríobh" #: src/bz-safety-calculator.c:210 msgid "Download Folder Read Access" msgstr "Íoslódáil Rochtain Léitheoireachta Fillteáin" #: src/bz-safety-calculator.c:211 msgid "Can read all data in your downloads directory" msgstr "Is féidir leat na sonraí go léir i do chomhadlann íoslódálacha a léamh" #: src/bz-safety-calculator.c:224 msgid "Can read and write all data in the directory" msgstr "Is féidir na sonraí go léir san eolaire a léamh agus a scríobh" #: src/bz-safety-calculator.c:238 msgid "Can read all data in the directory" msgstr "Is féidir na sonraí go léir san eolaire a léamh" #: src/bz-safety-calculator.c:253 msgid "No File System Access" msgstr "Gan Rochtain ar Chóras Comhad" #: src/bz-safety-calculator.c:254 msgid "Cannot access the file system at all" msgstr "Ní féidir rochtain a fháil ar an gcóras comhad ar chor ar bith" #: src/bz-safety-calculator.c:261 msgid "Uses System Services" msgstr "Úsáideann Seirbhísí Córais" #: src/bz-safety-calculator.c:262 msgid "Can request data from non-portal system services" msgstr "Is féidir sonraí a iarraidh ó sheirbhísí córais neamh-thairsí" #: src/bz-safety-calculator.c:268 msgid "Uses Session Services" msgstr "Úsáideann Seirbhísí Seisiúin" #: src/bz-safety-calculator.c:269 msgid "Can request data from non-portal session services" msgstr "Is féidir sonraí a iarraidh ó sheirbhísí seisiúin neamh-thairseach" #: src/bz-safety-calculator.c:294 msgid "No Service Access" msgstr "Gan Rochtain Seirbhíse" #: src/bz-safety-calculator.c:295 msgid "Cannot access non-portal session or system services at all" msgstr "" "Ní féidir rochtain a fháil ar sheirbhísí seisiúin nó córais neamh-thairseach " "ar chor ar bith" #: src/bz-safety-calculator.c:303 msgid "Verified App Developer" msgstr "Forbróir Aipeanna Fíoraithe" #: src/bz-safety-calculator.c:304 msgid "The developer of this app has been verified to be who they say they are" msgstr "" "Tá sé fíoraithe gurb é forbróir an aip seo an duine a deir siad a bheith" #: src/bz-safety-calculator.c:313 msgid "Proprietary Code" msgstr "Cód Dílseánaigh" #: src/bz-safety-calculator.c:314 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Níl an cód foinse poiblí, mar sin ní féidir é a iniúchadh go neamhspleách " "agus d'fhéadfadh sé a bheith neamhshábháilte" #: src/bz-safety-calculator.c:324 msgid "Auditable Code" msgstr "Cód Iniúchta" #: src/bz-safety-calculator.c:325 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Tá an cód foinse poiblí agus is féidir é a iniúchadh go neamhspleách, rud a " "fhágann go bhfuil an aip níos dóchúla a bheith sábháilte" #: src/bz-safety-calculator.c:465 #, c-format msgid "Use the %s System Service" msgstr "Bain úsáid as an Seirbhís Córais %s" #: src/bz-safety-calculator.c:469 #, c-format msgid "Use the %s Session Service" msgstr "Bain úsáid as an tSeirbhís Seisiúin %s" #: src/bz-safety-calculator.c:473 #, c-format msgid "Use the %s Service" msgstr "Bain úsáid as an tseirbhís %s" #: src/bz-safety-calculator.c:483 msgid "Can see the non-portal service" msgstr "Is féidir an tseirbhís neamh-thairseach a fheiceáil" #: src/bz-safety-calculator.c:485 msgid "Can talk to the non-portal service" msgstr "Is féidir labhairt leis an tseirbhís neamh-thairseach" #: src/bz-safety-calculator.c:487 msgid "Can own the non-portal service" msgstr "Is féidir leis an tseirbhís neamh-thairsí a bheith i seilbh" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Sábháilteacht" #: src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Sábháilte" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Sonraí" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Ceadúnas" #: src/bz-safety-dialog.blp:62 msgid "App ID" msgstr "Aitheantas Aipe" #: src/bz-safety-dialog.blp:71 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:98 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Úsáideann an aip seo leagan atá as dáta den ardán bogearraí (SDK) agus " "d'fhéadfadh fabhtanna nó leochaileachtaí slándála a bheith ann nach ndéanfar " "a shocrú." #: src/bz-safety-dialog.c:222 #, c-format msgid "%s is Safe" msgstr "Tá %s sábháilte" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s has no Unsafe Permissions" msgstr "Níl aon Cheadanna Neamhshábháilte ag %s" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s is Probably Safe" msgstr "Is dócha go bhfuil %s sábháilte" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Possibly Unsafe" msgstr "B’fhéidir go bhfuil %s neamhshábháilte" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Unsafe" msgstr "Tá %s neamhshábháilte" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Seat scáileáin" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "An seat scáileán roimhe seo" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "An seat scáileán eile" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Cóipeáil íomhá" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Athshocraigh an Amharc" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Súmáil amach" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Súmáil isteach" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Roithleagán Seat scáileáin" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Oscail Amharcóir Seat scáileáin" #: src/bz-search-widget.blp:107 msgid "Search Apps, Games, Software" msgstr "Cuardaigh Aipeanna, Cluichí, Bogearraí" #: src/bz-search-widget.blp:146 msgid "Categories Unavailable" msgstr "Catagóirí Gan Fáil" #: src/bz-search-widget.blp:147 msgid "Search for apps using the search bar above." msgstr "Cuardaigh aipeanna ag baint úsáide as an mbarra cuardaigh thuas." #: src/bz-search-widget.blp:231 msgid "No Applications Found" msgstr "Níor aimsíodh aon fheidhmchláir" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Níor aimsíodh aon torthaí le haghaidh \"%s\" i Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Cóipeáilte!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Cóipeáil Nasc" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Oscail an Nasc" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Amlíne" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Suiteálacha:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Domhan" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Suiteálacha Iomlána" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK Suiteálacha Iomlána" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d Suiteálacha Iomlána" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Níor aimsíodh aon torthaí" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aipeanna atá tagáilte \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Theip ar an gcuardach" #: src/bz-transaction-dialog.c:159 msgid "Keep Data" msgstr "Coinnigh Sonraí" #: src/bz-transaction-dialog.c:160 msgid "Allow restoring settings and content" msgstr "Ceadaigh socruithe agus ábhar a athchóiriú" #: src/bz-transaction-dialog.c:169 msgid "Delete Data" msgstr "Scrios Sonraí" #: src/bz-transaction-dialog.c:170 msgid "Permanently remove app data to save space" msgstr "Bain sonraí aipeanna go buan chun spás a shábháil" #: src/bz-transaction-dialog.c:194 #, c-format msgid "Install %s?" msgstr "Suiteáil %s?" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Féadfaidh sé comhpháirteanna comhroinnte breise a shuiteáil" #: src/bz-transaction-dialog.c:216 #, c-format msgid "Remove %s?" msgstr "Bain %s?" #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Ní bheidh sé indéanta %s a úsáid tar éis é a dhíshuiteáil." #: src/bz-transaction-dialog.c:240 #, c-format msgid "“%s” is High Risk" msgstr "Tá “%s” i mbaol ard" #: src/bz-transaction-dialog.c:244 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Tá rochtain iomlán ag an aip seo ar do chóras, lena n-áirítear do chuid " "comhad go léir, stair bhrabhsálaí, pasfhocail shábháilte, agus " "tuilleadh. Tá rochtain aici ar an idirlíon freisin, rud a chiallaíonn go " "bhféadfadh sí do shonraí a sheoladh chuig páirtithe seachtracha.\n" "\n" "Ós rud é gur aip dhílseánaigh í, ní féidir iniúchadh a dhéanamh uirthi " "maidir leis an méid a dhéanann sí leis na ceadanna seo." #: src/bz-transaction-dialog.c:253 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Úsáideann an aip seo an seanchóras fuinneoige X11, rud a ligeann di gach " "eochairbhuille a thaifeadadh, scáileáin a ghabháil, agus monatóireacht a " "dhéanamh ar fheidhmchláir eile. Tá rochtain aici ar an idirlíon freisin, " "rud a chiallaíonn gur féidir léi do shonraí a sheoladh chuig páirtithe " "seachtracha.\n" "\n" "Ós rud é gur aip dhílseánaigh í, ní féidir iniúchadh a dhéanamh uirthi " "maidir leis an méid a dhéanann sí leis na ceadanna seo." #: src/bz-transaction-dialog.c:269 msgid "Install Anyway" msgstr "Suiteáil ar aon nós" #: src/bz-transaction-manager.c:1148 #, c-format msgid "Finished in %.02f seconds" msgstr "Críochnaithe i %.02f soicind" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Breiseán Aipe" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Am rith" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Méid Suiteála" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "Ar feitheamh" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "Ar siúl" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "Críochnaithe" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "Nuashonrú" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "Aistríodh %s go dtí seo" #: src/bz-update-dialog.blp:7 msgid "Update Now" msgstr "Nuashonraigh Anois" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Tá Nuashonruithe ar Fáil" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Tá na feidhmchláir seo a leanas incháilithe le haghaidh nuashonruithe. Ar " "mhaith leat iad a shuiteáil?" #: src/bz-update-dialog.c:135 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "Tá %d rith-am agus/nó breiseán incháilithe le haghaidh nuashonruithe. Ar " "mhaith leat iad a shuiteáil?" #: src/bz-update-dialog.c:143 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Ina theannta sin, déanfar %d am rith agus/nó breiseán a nuashonrú." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Bainistigh Sonraí Úsáideora atá Fágtha" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Níor aimsíodh aon sonraí úsáideora" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Sonraí Úsáideora" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Sonraí Úsáideora Bruscair do %s" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Bruscar Sonraí Úsáideora" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Tascanna" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Stop Tascanna Gníomhacha" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Glan an Stair" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Gan aon tascanna fós" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "Ábhar an tSiopa á Athnuachan" #: src/bz-window.blp:271 msgid "Curated" msgstr "Coimeádta" #: src/bz-window.blp:284 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:432 msgid "No background tasks!" msgstr "Gan aon tascanna cúlra!" #: src/bz-window.blp:490 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Tá nasc líonra agat ach tá leagan taisceáilte de Flathub á fheiceáil agat" #: src/bz-window.blp:565 msgid "_Login with Flathub" msgstr "_Logáil isteach le Flathub" #: src/bz-window.blp:571 msgid "_Manage Leftover User Data" msgstr "_Bainistigh Sonraí Úsáideora atá Fágtha" #: src/bz-window.blp:576 msgid "_Synchronize Remotes" msgstr "_Sioncrónaigh Cianrialtáin" #: src/bz-window.blp:617 msgid "Log Out" msgstr "Logáil Amach" #: src/bz-window.c:435 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d Nuashonrú Ar Fáil" msgstr[1] "%d Nuashonruithe Ar Fáil" msgstr[2] "%d Nuashonruithe Ar Fáil" #: src/bz-window.c:872 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Beidh an cumas comhaid phacáiste .flatpak áitiúla a iniúchadh agus a " "shuiteáil ag teacht go luath! Idir an dá linn, bain triail as\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "a rith ar an líne ordaithe." #: src/bz-window.c:1010 msgid "Can't do that right now!" msgstr "Ní féidir liom é sin a dhéanamh faoi láthair!" #: src/bz-window.c:1080 msgid "Resume Current Tasks" msgstr "Lean ar aghaidh le Tascanna Reatha" #: src/bz-window.c:1086 msgid "Pause Current Tasks" msgstr "Cuir Tascanna Reatha ar Sos" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u íoslódálacha" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Ginearálta" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Oscail Dialóg Cuardaigh" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Oscail Roghanna" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Sioncrónaigh Cianrialtáin" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Bainisteoir Idirbheart a Athrú" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Taispeáin Aicearraí" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Scoir" kolunmi-bazaar-7b9c8e1/po/hu.po000066400000000000000000001031731514314607700164610ustar00rootroot00000000000000# Hungarian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Benedek Dévényi , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-31 23:45+0100\n" "PO-Revision-Date: 2025-11-02 20:12+0100\n" "Last-Translator: Benedek Dévényi \n" "Language-Team: Hungarian\n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:56 msgid "Bazaar" msgstr "Bazár" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Flatpak alkalmazások telepítése, eltávolítása és frissítése" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;PackageManager;Discover;Flatpak;Software;Store;rendszer;csomagkezelő;felfedezés;szoftver;áruház;bolt;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Show Git Forge Star Counts" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the " "full view" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Only Show Free Software" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software when searching" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Filter search results to only show applications available on Flathub" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:40 msgid "Global Progress Bar Theme" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:41 msgid "Describes the look of the global progress bar" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:45 msgid "Saved Window Dimensions" msgstr "" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "The window dimensions to be used by the next Bazaar window" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Alkalmazások felfedezése és telepítése" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Egy új alkalmazásbolt GNOME-ra, amelynek fókuszában a Flatpak adattárakból, " "kifejezetten a Flathubról származó alkalmazások és kiegészítők felfedezése " "és telepítése áll." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Hangsúlyozza a Linuxos asztali rendszereket létrehozó fejlesztők " "támogatását. A Bazár egy „válogatott” füllel is rendelkezik, amelyet a " "disztrók konfigurálhatnak, hogy lokalizáltabb élményt nyújtsanak." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:506 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home view displaying Flathub apps" msgstr "A kezdőképernyő Flathub alkalmazásokkal" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Alkalmazásoldal a Nucleus alkalmazással" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Searching for Blender" msgstr "Keresés a Blenderre" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:527 #: src/bz-installed-page.blp:132 msgid "Manage Add-ons" msgstr "Kiegészítők kezelése" #: src/bz-addons-dialog.c:88 src/bz-installed-page.blp:158 #: src/bz-transaction-view.blp:212 src/bz-window.c:1125 msgid "Remove" msgstr "Eltávolítás" #: src/bz-addons-dialog.c:95 src/bz-full-view.blp:244 #: src/bz-transaction-view.blp:186 src/bz-window.c:1103 msgid "Install" msgstr "Telepítés" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Az emberi DNS méretéhez képest" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 milliárd bázispár" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "A Linux Kernelhez képest" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "Az Apollo 11 irányító számítógépéhez képest" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "A teljes ROM és RAM" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "Az eredeti Super Mario Bros méretéhez képest" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "A NES-en" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "A Wikipédia méretéhez képest" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Minden média nélkül" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Letöltési méret" #: src/bz-application.c:401 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Ez a funkció jelenleg nem elérhető. Javasoljuk, hogy telepítsd a Flatseal " "alkalmazást az alkalmazások engedélyeinek kezeléséhez." #: src/bz-application.c:465 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:466 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:481 msgid "translator-credits" msgstr "Benedek Dévényi , 2025" #: src/bz-application.c:471 msgctxt "About Dialog Translator Credit" msgid "Ahmed Najmawi" msgstr "Ahmed Najmawi" #: src/bz-application.c:472 msgctxt "About Dialog Translator Credit" msgid "AtomHare" msgstr "AtomHare" #: src/bz-application.c:473 msgctxt "About Dialog Translator Credit" msgid "Azenyr" msgstr "Azenyr" #: src/bz-application.c:474 msgctxt "About Dialog Translator Credit" msgid "Goudarz Jafari" msgstr "Goudarz Jafari" #: src/bz-application.c:475 msgctxt "About Dialog Translator Credit" msgid "Jill Fiore (Lumaeris)" msgstr "Jill Fiore (Lumaeris)" #: src/bz-application.c:476 msgctxt "About Dialog Translator Credit" msgid "João Victor (Leal)" msgstr "João Victor (Leal)" #: src/bz-application.c:477 msgctxt "About Dialog Translator Credit" msgid "KiKaraage" msgstr "KiKaraage" #: src/bz-application.c:478 msgctxt "About Dialog Translator Credit" msgid "Lucosec" msgstr "Lucosec" #: src/bz-application.c:479 msgctxt "About Dialog Translator Credit" msgid "Léane GRASSER" msgstr "Léane GRASSER" #: src/bz-application.c:480 msgctxt "About Dialog Translator Credit" msgid "Marcel Mrówka (Microwave)" msgstr "Marcel Mrówka (Microwave)" #: src/bz-application.c:481 msgctxt "About Dialog Translator Credit" msgid "Peter Dave Hello" msgstr "Peter Dave Hello" #: src/bz-application.c:482 msgctxt "About Dialog Translator Credit" msgid "Pietro F." msgstr "Pietro F." #: src/bz-application.c:483 msgctxt "About Dialog Translator Credit" msgid "Sabri Ünal" msgstr "Sabri Ünal" #: src/bz-application.c:484 msgctxt "About Dialog Translator Credit" msgid "Shihfu Juan" msgstr "Shihfu Juan" #: src/bz-application.c:485 msgctxt "About Dialog Translator Credit" msgid "Shinsei" msgstr "Shinsei" #: src/bz-application.c:486 msgctxt "About Dialog Translator Credit" msgid "Vlastimil Dědek" msgstr "Vlastimil Dědek" #: src/bz-application.c:487 msgctxt "About Dialog Translator Credit" msgid "asen23" msgstr "asen23" #: src/bz-application.c:488 msgctxt "About Dialog Translator Credit" msgid "camegone" msgstr "camegone" #: src/bz-application.c:489 msgctxt "About Dialog Translator Credit" msgid "renner" msgstr "renner" #: src/bz-application.c:490 msgctxt "About Dialog Translator Credit" msgid "robotta" msgstr "robotta" #: src/bz-application.c:1033 msgid "Constructing Flatpak instance..." msgstr "Flatpak példány létrehozása…" #: src/bz-application.c:1050 msgid "Reusing last Flatpak instance..." msgstr "Legutóbbi Flatpak példány újrafelhasználása…" #: src/bz-application.c:1075 msgid "Flathub is not registered on this system" msgstr "A Flathub nincs beállítva ezen a rendszeren" #: src/bz-application.c:1078 msgid "" "Would you like to add Flathub as a remote? If you decline, the Flathub page " "will not be available. You can change this later." msgstr "" "Szeretnéd engedélyezni a Flathub távoli adattárat? Ha ezt nem teszed meg, a " "Flathub fül nem lesz elérhető. Később ezt bármikor megváltoztathatod." #: src/bz-application.c:1083 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Később" #: src/bz-application.c:1084 msgid "Add Flathub" msgstr "Flathub engedélyezése" #: src/bz-application.c:1116 #, c-format msgid "Identifying installed entries..." msgstr "Telepített tételek beazonosítása…" #: src/bz-application.c:1128 #, c-format msgid "Beginning remote entry retrieval while referencing %d blocklist(s)..." msgstr "Távoli tételek lekérésének megkezdése, %d tiltólista hivatkozásával…" #: src/bz-application.c:1276 #, c-format msgid "Receiving Entries" msgstr "Tételek fogadása" #: src/bz-application.c:1277 #, c-format msgid "%'d of %'d" msgstr "%'d/%'d" #: src/bz-application.c:1288 #, c-format msgid "Waiting for background indexing tasks to catch up..." msgstr "Várakozás a háttérben futó indexelési feladatok befejezésére…" #: src/bz-application.c:1329 #, c-format msgid "Completed initialization in %0.2f seconds" msgstr "Az indítás %0.2f másodperc alatt befejeződött" #: src/bz-application.c:1334 src/bz-application.c:1489 msgid "Checking for updates..." msgstr "Frissítések keresése…" #: src/bz-application.c:1373 msgid "Synchronizing..." msgstr "Szinkronizálás…" #: src/bz-browse-widget.blp:11 src/bz-flathub-page.blp:19 #: src/bz-full-view.blp:10 src/bz-installed-page.blp:15 src/bz-window.blp:161 msgid "Empty" msgstr "Üres" #: src/bz-browse-widget.blp:15 msgid "No Curated Applications" msgstr "Nincsenek válogatott alkalmazások" #: src/bz-browse-widget.blp:16 msgid "" "Bazaar was not provided a curated content configuration. Contact your " "operating system's support channels for assistance." msgstr "" "A Bazaar nem talál válogatott tartalomkonfigurációt. Segítségért fordulj az " "operációs rendszer támogatási csatornáihoz." #: src/bz-browse-widget.blp:22 src/bz-flathub-page.blp:30 msgid "Browser" msgstr "Böngésző" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Hiba történt" #: src/bz-error.c:89 msgid "Close" msgstr "Bezárás" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Másolás és bezárás" #: src/bz-featured-tile.blp:89 msgid "App of the Day" msgstr "A nap alkalmazása" #: src/bz-flathub-category.c:325 msgid "Audio & Video" msgstr "Hang és videó" #: src/bz-flathub-category.c:327 msgid "Developer Tools" msgstr "Fejlesztői eszközök" #: src/bz-flathub-category.c:329 msgid "Education" msgstr "Oktatás" #: src/bz-flathub-category.c:331 msgid "Gaming" msgstr "Játék" #: src/bz-flathub-category.c:333 msgid "Graphics & Photography" msgstr "Grafika és fényképezés" #: src/bz-flathub-category.c:335 msgid "Networking" msgstr "Hálózat" #: src/bz-flathub-category.c:337 msgid "Productivity" msgstr "Produktivitás" #: src/bz-flathub-category.c:339 msgid "Science" msgstr "Tudomány" #: src/bz-flathub-category.c:341 msgid "System" msgstr "Rendszer" #: src/bz-flathub-category.c:343 msgid "Utilities" msgstr "Segédprogramok" #: src/bz-flathub-category-section.c:137 #, c-format msgid "%d applications" msgstr "%d alkalmazás" #: src/bz-flathub-category-section.c:336 #, c-format msgid "More %s" msgstr "Még több %s" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "A Flathub nincs engedélyezve" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "A Flathub adattár nem található egyik Flatpak telepítéseden sem" #: src/bz-flathub-page.blp:80 src/bz-flathub-page.blp:109 #: src/bz-flathub-page.c:168 msgid "Trending" msgstr "Felkapott" #: src/bz-flathub-page.blp:85 src/bz-flathub-page.blp:235 #: src/bz-flathub-page.c:198 msgid "Popular" msgstr "Népszerű" #: src/bz-flathub-page.blp:90 msgid "New" msgstr "Új" #: src/bz-flathub-page.blp:95 msgid "Updated" msgstr "Frissített" #: src/bz-flathub-page.blp:141 msgid "More Trending" msgstr "Még több felkapott" #: src/bz-flathub-page.blp:151 src/bz-flathub-page.c:178 msgid "Recently Updated" msgstr "Nemrég frissített" #: src/bz-flathub-page.blp:183 msgid "More Updated" msgstr "Még több frissített" #: src/bz-flathub-page.blp:193 src/bz-flathub-page.c:188 msgid "Recently Added" msgstr "Nemrég hozzáadott" #: src/bz-flathub-page.blp:225 msgid "More New" msgstr "Még több új" #: src/bz-flathub-page.blp:267 msgid "More Popular" msgstr "Még több népszerű" #: src/bz-flathub-page.blp:356 msgid "On the go" msgstr "Útközben" #: src/bz-flathub-page.blp:368 msgid "Apps for your Linux phones and tablets" msgstr "Alkalmazások Linux telefonokra és táblagépekre" #: src/bz-flathub-page.blp:379 src/bz-flathub-page.blp:414 msgid "More Mobile apps" msgstr "Még több mobilapp" #: src/bz-flathub-page.c:208 msgid "Mobile Apps" msgstr "Mobilappok" #: src/bz-flatpak-entry.c:552 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub oldal" #: src/bz-flatpak-entry.c:573 msgctxt "Project URL Type" msgid "Project Website" msgstr "Projekt honlapja" #: src/bz-flatpak-entry.c:577 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Hiba bejelentése" #: src/bz-flatpak-entry.c:581 msgctxt "Project URL Type" msgid "FAQ" msgstr "GYIK" #: src/bz-flatpak-entry.c:585 msgctxt "Project URL Type" msgid "Help" msgstr "Segítség" #: src/bz-flatpak-entry.c:589 msgctxt "Project URL Type" msgid "Donate" msgstr "Adományozás" #: src/bz-flatpak-entry.c:595 msgctxt "Project URL Type" msgid "Translate" msgstr "Segítség a fordításban" #: src/bz-flatpak-entry.c:599 msgctxt "Project URL Type" msgid "Contact" msgstr "Kapcsolat" #: src/bz-flatpak-entry.c:603 msgctxt "Project URL Type" msgid "Source Code" msgstr "Forráskód" #: src/bz-flatpak-entry.c:609 msgctxt "Project URL Type" msgid "Contribute" msgstr "Hozzájárulás" #: src/bz-full-view.blp:14 msgid "No Results" msgstr "Nincs találat" #: src/bz-full-view.blp:15 msgid "Try a different search query" msgstr "Próbálkozz más keresőkifejezéssel" #: src/bz-full-view.blp:21 src/bz-window.blp:171 msgid "Content" msgstr "Tartalom" #: src/bz-full-view.blp:151 msgid "Verified by the original developers" msgstr "Az eredeti fejlesztők által hitelesítve" #: src/bz-full-view.blp:178 msgid "Support" msgstr "Támogatás" #: src/bz-full-view.blp:198 msgid "Repository Star Count" msgstr "Adattár csillagszámlálója" #: src/bz-full-view.blp:228 msgid "Open" msgstr "Megnyitás" #: src/bz-full-view.blp:241 msgid "Download & Install Application" msgstr "Alkalmazás letöltése és telepítése" #: src/bz-full-view.blp:256 msgid "Uninstall Application" msgstr "Alkalmazás eltávolítása" #: src/bz-full-view.blp:271 msgid "Install Other Version" msgstr "Másik verzió telepítése" #: src/bz-full-view.blp:295 msgid "Download" msgstr "Letöltés" #: src/bz-full-view.blp:411 msgid "Downloads/mo" msgstr "Letöltés/hó" #: src/bz-full-view.c:261 msgid "---" msgstr "---" #. Translators: M is the suffix for millions, \xC2\xA0 is a non-breaking space #: src/bz-full-view.c:265 #, c-format msgid "%.2f M" msgstr "%.2f m" #. Translators: K is the suffix for thousands, \xC2\xA0 is a non-breaking space #: src/bz-full-view.c:268 #, c-format msgid "%.2f K" msgstr "%.2f e" #: src/bz-full-view.c:277 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d letöltés az elmúlt 30 napban" #: src/bz-full-view.c:298 #, c-format msgid "Download size of %s" msgstr "Letöltés mérete: %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-full-view.c:308 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-full-view.c:316 msgid "All Ages" msgstr "Minden életkor" #: src/bz-full-view.c:318 msgid "Age Rating" msgstr "Korhatár" #: src/bz-full-view.c:326 msgid "Suitable for all ages" msgstr "Minden korosztály számára alkalmas" #: src/bz-full-view.c:328 #, c-format msgid "Suitable for ages %d and up" msgstr "%d éves kortól ajánlott" #: src/bz-full-view.c:348 msgid "Unknown" msgstr "Ismeretlen" #: src/bz-full-view.c:351 msgid "Proprietary Software" msgstr "Zárt forráskódú szoftver" #: src/bz-full-view.c:355 #, c-format msgid "Free software licensed under %s" msgstr "Szabad szoftver a(z) %s licenc alatt" #: src/bz-full-view.c:363 msgid "Free" msgstr "Szabad" #: src/bz-full-view.c:363 msgid "Proprietary" msgstr "Védett" #: src/bz-full-view.c:383 msgid "Adaptive" msgstr "Alkalmazkodó" #: src/bz-full-view.c:383 msgid "Desktop Only" msgstr "Csak asztali" #: src/bz-full-view.c:389 msgid "Works on desktop, tablets, and phones" msgstr "Működik asztali számítógépen, táblagépen és mobiltelefonon" #: src/bz-full-view.c:390 msgid "May not work on mobile devices" msgstr "Lehet, hogy nem működik mobileszközökön" #: src/bz-full-view.c:401 msgid "No URL" msgstr "Nincs URL" #: src/bz-full-view.c:419 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Ez az alkalmazás Szabad és Nyílt Forráskódú licenccel rendelkezik, ami azt " "jelenti, hogy által a forráskód biztonsági szempontból bárki által " "ellenőrizhető." #: src/bz-full-view.c:420 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Ez az alkalmazás kereskedelmi licenccel rendelkezik, ami azt jelenti, hogy a " "forráskód magántulajdonban van, és független harmadik fél nem ellenőrizheti." #: src/bz-full-view.c:676 msgid "Show Less" msgstr "Kevesebb mutatása" #: src/bz-full-view.c:676 msgid "Show More" msgstr "Több mutatása" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Billentyűzet támogatás" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Billentyűzet szükséges" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Billentyűzet ajánlott" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Billentyűzet használható" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Billentyűzet támogatás ismeretlen" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Egér támogatás" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Egér vagy mutatóeszköz szükséges" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Egér vagy mutatóeszköz ajánlott" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Egér vagy mutatóeszköz használható" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Egér vagy mutatóeszköz támogatás ismeretlen" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Érintőképernyő támogatás" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Érintőképernyő szükséges" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Érintőképernyő ajánlott" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Érintőképernyő használható" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Érintőképernyő támogatás ismeretlen" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Mobil támogatás" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Működik mobileszközökön" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Lehet, hogy nem működik jól mobileszközökön" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Asztali támogatás" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Jól működik nagy kijelzőkön" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s csak bizonyos eszközökön működik jól" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s a legtöbb eszközön működik" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Hardver támogatás" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "" #: src/bz-inspector.blp:22 msgid "Active Blocklists" msgstr "" #: src/bz-inspector.blp:44 msgid "Active Curated-Configs" msgstr "" #: src/bz-inspector.blp:66 msgid "All Entry Groups" msgstr "" #: src/bz-inspector.blp:69 msgid "Filter..." msgstr "" #: src/bz-inspector.blp:110 msgid "Decache and Inspect" msgstr "" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Nincs telepített Flatpak" #: src/bz-installed-page.blp:25 src/bz-window.blp:305 src/bz-window.blp:399 msgid "Installed" msgstr "Telepítve" #: src/bz-installed-page.blp:108 msgid "Support this application" msgstr "Alkalmazás támogatása" #: src/bz-installed-page.blp:185 msgid "More actions" msgstr "További lehetőségek" #: src/bz-installed-page.blp:204 msgid "Run this application" msgstr "Alkalmazás futtatása" #: src/bz-installed-page.blp:216 msgid "Run" msgstr "Futtatás" #: src/bz-installed-page.blp:228 src/bz-installed-page.blp:239 msgid "View Store Page" msgstr "Alkalmazásoldal megnyitása" #: src/bz-installed-page.c:649 msgid "Choose an Installation" msgstr "Telepítés kiválasztása" #: src/bz-installed-page.c:652 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "Ennek az alkalmazásnak több verziója is telepítve van. Melyikkel szeretnéd " "folytatni?" #: src/bz-installed-page.c:656 src/bz-window.c:1102 src/bz-window.c:1124 msgid "Cancel" msgstr "Mégse" #: src/bz-license-dialog.c:115 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may not be able to contribute to this app." msgstr "" "Ez az alkalmazás zárt fejlesztésű, ezért csak a fejlesztői ismerik a belső " "működését. Lehetnek olyan biztonsági hiányosságai, amelyek nehezen " "észlelhetők, illetve a működése észrevétlenül megváltozhat.\n" "\n" "Nem tudsz hozzájárulni az alkalmazás fejlesztéséhez." #: src/bz-license-dialog.c:124 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Ezt az alkalmazást egy nemzetközi közösség nyíltan fejleszti.\n" "\n" "Te is csatlakozhatsz és segíthetsz még jobbá tenni." #: src/bz-license-dialog.c:135 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Ezt az alkalmazást egy nemzetközi közösség nyíltan fejleszti, és a(z) %s teszi elérhetővé.\n" "\n" "Te is csatlakozhatsz és segíthetsz még jobbá tenni." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Beállítások" #: src/bz-preferences-dialog.blp:23 src/bz-window.blp:48 src/bz-window.blp:337 msgid "Search" msgstr "Keresés" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Csak szabad szoftver" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications from search results" msgstr "Zárt forráskódú alkalmazások elrejtése a keresési eredményekből" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Csak Flathub eredmények" #: src/bz-preferences-dialog.blp:32 msgid "Limit search results to applications only available on Flathub" msgstr "Keresés korlátozása a Flathubon elérhető alkalmazásokra" #: src/bz-preferences-dialog.blp:36 msgid "Delay Search Results" msgstr "Keresés késleltetése" #: src/bz-preferences-dialog.blp:37 msgid "Improve results performance by debouncing search terms" msgstr "" "Keresés teljesítményének javítása a keresőkifejezések pergésmentesítésével" #: src/bz-preferences-dialog.blp:42 msgid "Application Details" msgstr "Alkalmazás részletei" #: src/bz-preferences-dialog.blp:45 msgid "Display Star Count" msgstr "Csillagszámláló mutatása" #: src/bz-preferences-dialog.blp:46 msgid "Show the star count of an application's source code repository" msgstr "Az alkalmazás forráskód-adattára csillagszámának megjelenítése" #: src/bz-preferences-dialog.blp:71 msgid "Progress Bar" msgstr "Folyamatjelző" #: src/bz-preferences-dialog.blp:72 msgid "Choose a theme for the progress bar!" msgstr "Válassz témát a folyamatjelző sávoknak" #: src/bz-preferences-dialog.blp:107 msgid "" "Bazaar can fetch and display the star count from an application's source " "code repository on a remote Git forge. \n" " For projects on GitHub, rate limits may cause them not to appear." msgstr "" "A Bazár letölti és megjeleníti a csillagok számát egy alkalmazás forráskód-" "adattárából a távoli Git forge-on. \n" " A GitHubon található projektek esetében a használati korlát miatt " "előfordulhat, hogy nem mindig sikerül betölteni." #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Kiemelőszín" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Pride színek" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Lezbikus színek" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Transzgender színek" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Nonbináris színek" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Biszexuális színek" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Aszexuális színek" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "Pánszexuális színek" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Aromantikus színek" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Genderfluid színek" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Poliszexuális színek" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Omniszexuális színek" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "Verziótörténet" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "%s verzió" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "Nincsenek részletek ehhez a kiadáshoz" #: src/bz-search-widget.blp:69 msgid "Search Apps" msgstr "Alkalmazások keresése" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Másolva!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Hivatkozás másolása" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Hivatkozás megnyitása" #: src/bz-stats-dialog.blp:26 msgid "Timeline" msgstr "Idővonal" #: src/bz-stats-dialog.blp:31 msgid "Installs:" msgstr "Telepítés:" #: src/bz-stats-dialog.blp:37 msgid "World" msgstr "Térkép" #: src/bz-transaction-manager.c:1140 #, c-format msgid "Finished in %.02f seconds" msgstr "Befejezve %.02f másodperc alatt" #: src/bz-transaction-view.blp:94 msgid "App Add-on" msgstr "Alkalmazás kiegészítő" #: src/bz-transaction-view.blp:119 msgid "Runtime" msgstr "Futtatókörnyezet" #: src/bz-transaction-view.blp:145 src/bz-transaction-view.blp:171 msgid "Install Size" msgstr "Telepített méret" #: src/bz-transaction-view.blp:199 src/bz-window.blp:350 msgid "Update" msgstr "Frissítés" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Eddig átvíve: %s" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Függőben" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Telepítés most" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Frissítések elérhetők" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "A következő alkalmazások frissítésre várnak. Szeretnéd telepíteni őket?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d futtatókörnyezet és/vagy kiegészítőhöz érhető el frissítés. Szeretnéd " "telepíteni ezeket?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "További %d futtatókörnyezet és/vagy kiegészítő frissítve lesz." #: src/bz-window.blp:63 msgid "Go Home" msgstr "Vissza a kezdőoldalra" #: src/bz-window.blp:86 msgid "Tasks" msgstr "Feladatok" #: src/bz-window.blp:105 src/bz-window.blp:418 msgid "Toggle transaction sidebar" msgstr "Tranzakciók megjelenítése/elrejtése" #: src/bz-window.blp:141 msgid "Stop Active Tasks" msgstr "Futó feladatok leállítása" #: src/bz-window.blp:149 msgid "Clear History" msgstr "Előzmények törlése" #: src/bz-window.blp:165 msgid "No Tasks Yet" msgstr "Nincsenek feladatok" #: src/bz-window.blp:219 src/bz-window.blp:223 msgid "Offline" msgstr "Offline" #: src/bz-window.blp:229 msgid "Loading" msgstr "Betöltés" #: src/bz-window.blp:270 msgid "Browse" msgstr "Böngészés" #: src/bz-window.blp:280 msgid "App View" msgstr "Alkalmazás nézet" #: src/bz-window.blp:295 src/bz-window.blp:392 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:325 msgid "Go Back" msgstr "Vissza" #: src/bz-window.blp:381 msgid "View curated applications" msgstr "Válogatott alkalmazások megtekintése" #: src/bz-window.blp:385 msgid "Curated" msgstr "Válogatott" #: src/bz-window.blp:389 msgid "View the latest on Flathub" msgstr "Legújabb Flathub alkalmazások megtekintése" #: src/bz-window.blp:396 msgid "View installed applications" msgstr "Telepített alkalmazások megtekintése" #: src/bz-window.blp:441 msgid "Main Menu" msgstr "Főmenü" #: src/bz-window.blp:486 msgid "_Donate to Bazaar ❤️" msgstr "A Bazár _támogatása ❤️" #: src/bz-window.blp:491 msgid "_Refresh Content" msgstr "Ú_jratöltés" #: src/bz-window.blp:498 msgid "_Preferences" msgstr "_Beállítások" #: src/bz-window.blp:503 msgid "_Keyboard Shortcuts" msgstr "_Gyorsbillentyűk" #: src/bz-window.blp:508 msgid "_About Bazaar" msgstr "A Bazár _névjegye" #: src/bz-window.blp:515 msgid "_Quit Bazaar" msgstr "_Kilépés" #: src/bz-window.c:827 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Hamarosan elérhető lesz a helyi .flatpak csomagfájlok ellenőrzésének és " "telepítésének lehetősége! Addig is próbáld meg futtatni a\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "parancsot a parancssorban." #: src/bz-window.c:967 msgid "Can't do that right now!" msgstr "Ezt most nem lehetséges!" #: src/bz-window.c:1096 #, c-format msgid "Install %s?" msgstr "%s telepítése" #: src/bz-window.c:1099 msgid "May install additional shared components" msgstr "További megosztott összetevők telepíthetők" #: src/bz-window.c:1118 #, c-format msgid "Remove %s?" msgstr "Remove %s?" #: src/bz-window.c:1121 msgid "Settings & user data will be kept" msgstr "A beállítások és a felhasználói adatok megmaradnak" #: src/bz-window.c:1289 msgid "Resume Current Tasks" msgstr "Feladatok folytatása" #: src/bz-window.c:1295 msgid "Pause Current Tasks" msgstr "Feladatok szüneteltetése" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u downloads" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Általános" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Keresőablak megnyitása" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Beállítások megnyitása" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Újratöltés" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Tranzakciókezelő megjelenítése/elrejtése" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Gyorsbillentyűk" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Kilépés" kolunmi-bazaar-7b9c8e1/po/id.po000066400000000000000000002504101514314607700164360ustar00rootroot00000000000000# Indonesian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025 asen23 # KiKaraage , 2025-2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-08 02:49+0700\n" "PO-Revision-Date: 2026-02-09 12:35+0700\n" "Last-Translator: KiKaraage \n" "Language-Team: Indonesian\n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Tambah, hapus atau mutakhirkan perangkat lunak Flatpak pada komputer ini" # Added "Aplikasi" and "Pusat Aplikasi" (App Center) to search queries #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistem;PackageManager;Discover;Flatpak;Aplikasi;Toko;PerangkatLunak;PusatAplikasi;ManajerPaket;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Jendela Baru" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Temukan dan pasang aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Toko aplikasi baru untuk Linux yang menawarkan kemudahan menemukan dan " "memasang aplikasi serta modul tambahan dari server-server Flatpak, terutama " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Bazaar menekankan pentingnya mendukung para pengembang yang telah memajukan " "desktop Linux. Bazaar juga memberi ruang distributor untuk melakukan kurasi " "aplikasi \"pilihan\" untuk pengguna. " #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:701 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Tampilan muka dengan daftar aplikasi dari Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Tampilan halaman detail aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Tampilan pencarian aplikasi" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Tampilan kategori aplikasi" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "Kelola Modul Tambahan" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:227 msgid "Remove" msgstr "Hapus" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:198 msgid "Install" msgstr "Pasang" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "Peringkat Usia" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Kekerasan (Kartun)" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Tidak ada info mengenai penggambaran kekerasan berbentuk kartun" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Kekerasan (Fantasi)" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Tidak ada info mengenai penggambaran kekerasan berbentuk fantasi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Kekerasan (Nyata)" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Tidak ada info mengenai penggambaran kekerasan realistik" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Kekerasan Menggambarkan Pertumpahan Darah" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Tidak ada info mengenai penggambaran pertumpahan darah" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Kekerasan Seksual" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Tidak ada info mengenai penggambaran kekerasan seksual" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Minuman Keras" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "" "Tidak ada info mengenai penggambaran/penyebutan terkait minuman beralkohol" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Narkotika" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "" "Tidak ada info mengenai referensi terkait narkotika dan obat-obatan terlarang" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Rokok" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Tidak ada info mengenai referensi terkait rokok " #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Ketelanjangan" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Tidak ada info mengenai segala bentuk ketelanjangan" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Tema Seksual" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Tidak ada info mengenai segala bentuk referensi atau penggambaran seksual " #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Kata-Kata Kasar" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Tidak ada info mengenai segala penggunaan kata-kata kasar" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Humor Tidak Pantas" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Tidak ada info mengenai penggunaan humor yang tidak pantas" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Diskriminasi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Tidak ada info mengenai segala penggunaan bahasa yang diskriminatif" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Iklan" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Tidak ada info mengenai semua bentuk iklan" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Judi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "" "Tidak ada info mengenai segala penyebutan dan penggambaran terkait judi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Jual Beli" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Tidak ada info mengenai kemampuan transaksi atau pembelian" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Obrolan Antar Pengguna" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Tidak ada info mengenai cara melakukan obrolan dengan pengguna lain" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Panggilan Antar Pengguna" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "" "Tidak ada info mengenai cara melakukan panggilan suara dengan pengguna lain" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Rincian Kontak" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Tidak ada info terkait tindakan berbagi nama pengguna di media sosial atau " "alamat email" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Informasi Identifikasi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "" "Tidak ada info terkait tindakan membagikan info pengguna dengan pihak ketiga " #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Berbagi Lokasi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "Tidak ada info mengenai tindakan berbagi lokasi dengan pengguna lain" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostitusi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Tidak ada info mengenai penyebutan referensi terkait prostitusi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Zina" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Tidak ada info mengenai penyebutan referensi terkait perzinaan" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Karakter yang Diseksualisasi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Tidak ada info mengenai karakter yang diseksualisasikan" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Penistaan" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Tidak ada info mengenai penyebutan referensi terkait penistaan" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Jasad Manusia" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Tidak ada info mengenai terlihatnya sisa-sisa jasad manusia" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Perbudakan" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Tidak ada info mengenai penyebutan referensi terkait perbudakan" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Tidak memuat referensi terkait obat-obatan terlarang" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Tidak memuat penggunaan kata-kata kasar dan umpatan" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Tidak memuat iklan atau transaksi keuangan" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Tidak memuat konten seksual" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Tidak memuat kemampuan obrolan tanpa moderasi" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Tidak memuat konten kekerasan" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Obat Terlarang" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Kata-Kata Kasar" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Uang" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Sosial" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Kekerasan" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Semua" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "Peringkat usia untuk %s tidak diketahui" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s cocok untuk semua usia" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s diperbolehkan untuk usia balita" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s diperbolehkan untuk usia anak-anak" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s diperbolehkan untuk usia remaja" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s diperbolehkan untuk usia dewasa" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s diperbolehkan untuk usia %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "Menu Utama" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "_Donasi ke Bazaar ❤️" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "_Pengaturan" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "_Masuk dengan Flathub" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "_Kelola Sisa Data Pengguna" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "_Sinkronkan Dengan Server" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "_Pintasan Papan Tik" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "_Tentang Bazaar" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "_Tutup Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Folder sistem %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Subfolder beranda %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Folder sistem utama" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Konfigurasi sistem utama dari /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Subfolder desktop %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Folder desktop" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Subfolder dokumen %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Folder dokumen" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Subfolder musik %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Folder musik" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Subfolder gambar %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Folder gambar" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Subfolder Berkas Publik %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Folder Berkas Publik" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Subfolder video %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Folder video" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Subfolder templat %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Folder templat" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Subfolder cache pengguna %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Folder cache pengguna" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Subfolder konfigurasi pengguna %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Folder konfigurasi pengguna" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Subfolder data pengguna %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Folder data pengguna" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Subfolder tempokerja pengguna %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Folder tempokerja pengguna" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Akses sistem file ke %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Jalur sistem file tidak diketahui" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Ukuran Unduh" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Ukuran yang diunduh dari internet" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Ukuran Terpasang" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Ukuran Tersimpan" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Ukuran Data Pengguna" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Cache, konfigurasi, dan data aplikasi lainnya" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:178 msgid "Installed" msgstr "Terpasang" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "Tunjukkan Semua" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "Semua \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Aplikasi" #: src/bz-application.c:672 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:673 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:704 msgid "translator-credits" msgstr "KiKaraage , 2025" #: src/bz-application.c:715 msgid "Special Thanks" msgstr "Terima Kasih Khusus" #: src/bz-application.c:773 msgid "Logged Out Successfully!" msgstr "Akun Berhasil Dikeluarkan!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Melakukan pengaturan..." #: src/bz-application.c:979 src/bz-application.c:988 msgid "Set Up Flathub" msgstr "Atur Flathub" #: src/bz-application.c:982 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub belum diatur pada sistem ini. Anda tidak dapat mencari dan memasang " "aplikasi lewat Bazaar jika Flathub belum tersedia.\n" "\n" "Anda masih dapat menggunakan Bazaar untuk mencari dan menghapus aplikasi " "terpasang." #: src/bz-application.c:987 msgid "Later" msgstr "Nanti" #: src/bz-application.c:1397 src/bz-application.c:3087 msgid "Synchronizing..." msgstr "Mengsinkronkan..." #: src/bz-application.c:1544 src/bz-application.c:3083 #, c-format msgid "Receiving %d entries..." msgstr "%d entri tersisa..." #: src/bz-application.c:1549 msgid "Checking for updates" msgstr "Memeriksa pemutakhiran" #: src/bz-application.c:3089 msgid "Indexing Data..." msgstr "Mengindeks Data..." #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Halaman Flathub" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "Situs Web Proyek" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Pelacak Masalah" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "Pertanyaan Jamak" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "Bantuan" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "Sumbang" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "Terjemahkan" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "Kontak" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kode Sumber" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "Berkontribusi" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "Kosong" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Pilihan Belum Tersedia" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Info aplikasi pilihan tidak tersedia pada sistem ini. Anda masih dapat " "menjelajahi aplikasi dari Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Jelajah Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Tidak Ada Jaringan" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Peramban" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Informasi pengembang tidak tersedia." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Kepemilikan ID aplikasi %s belum diverifikasi, kemungkinan dikemas dalam " "skala komunitas." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Kepemilikan ID aplikasi %s telah diverifikasi secara manual \n" " tim Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Kepemilikan ID aplikasi %1$s telah diverifikasi oleh %2$s di %3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "Kepemilikan ID aplikasi %1$s telah diverifikasi menggunakan %2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Kepemilikan ID aplikasi %s telah diverifikasi." #: src/bz-donations-dialog.blp:58 msgid "This Bazaar Release Was Made Possible By Users Like You!" msgstr "Versi ini dapat rilis karena dukungan Anda!" #: src/bz-donations-dialog.blp:66 msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "Saya cinta Bazaar, namun saya tidak dapat mengembangkannya sendiri. Jika " "Anda ingin membantu pengembangan lebih lanjut, mari berdonasi lewat Ko-fi:" #: src/bz-donations-dialog.blp:76 msgid "Donate to Bazaar" msgstr "Donasi ke Bazaar" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Pilih Pemasangan" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Anda telah memasang beberapa versi aplikasi ini. Versi mana yang ingin Anda " "gunakan?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:197 #: src/bz-transaction-dialog.c:226 src/bz-transaction-dialog.c:271 #: src/bz-transaction-dialog.c:562 msgid "Cancel" msgstr "Batal" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Hanya untuk pengguna ini" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "pengguna ini" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "semua pengguna" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Telah Terjadi Kegagalan" #: src/bz-error.c:89 msgid "Close" msgstr "Tutup" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Salin dan Tutup" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Masuk dengan Flathub dan kelola aplikasi favorit" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Masuk" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Jumlah Favorit" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Bongkar" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "Dukung aplikasi ini" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Hapus dari Favorit" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "Aplikasi Favorit" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 msgid "Open App Library" msgstr "Buka Pustaka Aplikasi" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:563 msgid "Install All" msgstr "Pasang Semua" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "Memuat" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "Tidak Ada Favorit" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "Aplikasi yang Anda tandai sebagai favorit akan muncul di sini" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Sebelumnya" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Selanjutnya" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Aplikasi Hari Ini" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "Penyunting" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Mixer" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "Musik" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "Pemutar" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Perekam" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "Pengurut" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Pengontrol" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "Emulasi" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "Aksi" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Petualangan" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Arkade" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Blok" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Papan" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Kartu" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Anak-Anak" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "Logika" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "Bermain Peran" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Penembak" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "Simulasi" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "Olahraga" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "Strategi" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "Audio & Video" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "Putar Media" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Apl Audio & Video Lain" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Alat Pengembangan" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Kembangkan" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Apl Pengembangan Lain" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Edukasi" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Belajar" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "Apl Edukasi Lain" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Permainan" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Bermain" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "Permainan Lainnya" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "Grafis & Fotografi" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Berkreasi" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Apl Grafis & Foto Lain" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Jaringan" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Apl Jaringan Lain" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Produktivitas" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Bekerja" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Apl Produktivitas Lain" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "Ilmu Pengetahuan" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "Apl Ilmu Pengetahuan Lain" #: src/bz-flathub-category.c:128 msgid "System" msgstr "Sistem" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Apl Sistem Lain" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "Utilitas" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Alat" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "Apl Utilitas Lain" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Sedang Tren" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Aplikasi Tren Lainnya" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populer" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Apl Populer Lainnya" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Baru Saja Rilis" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Baru" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Apl Baru Lainnya" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Baru Dimutakhirkan" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Dimutakhirkan" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "Apl Mutakhir Lainnya" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Untuk Ponsel" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "Apl Ponsel Lainnya" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Apl Adwaita Lainnya" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "Aplikasi KDE" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "Apl KDE Lainnya" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub Belum Ditambahkan" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Remote Flathub tidak ditemukan pada seluruh pemasangan Flatpak Anda" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Terdapat kesalahan pada Flathub" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Hubungkan Kembali Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub Tidak Tersedia" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Bazaar tidak dapat terhubung ke Flathub. Anda masih dapat mencari dan " "mengelola aplikasi." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Cari Aplikasi" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Di Mana Saja" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Aplikasi untuk ponsel dan tablet Linux Anda" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Apl Ponsel Lainnya" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Kita ♥​ Main" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Permainan dan aplikasi untuk memainkan judul-judul favoritmu" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Permainan Lainnya" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "Tidak Ada Hasil" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "Coba gunakan kata kunci lainnya" #: src/bz-full-view.blp:59 msgid "Content" msgstr "Konten" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "Saat ini pemasangan bundel .flatpak belum didukung" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Dukung" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Buka" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Unduh & Pasang Aplikasi" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Hapus Pemasangan Aplikasi" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Pasang Versi Lain" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "Unduhan/Bulan" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Berhenti Menerima Pemutakhiran Utama" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Aplikasi ini menggunakan tempokerja (runtime) yang sudah tidak menerima " "pemutakhiran maupun perbaikan keamanan. Aplikasi ini mungkin tidak aman saat " "digunakan." #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "Buang Data" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "Label:" #: src/bz-full-view.c:220 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "%.*fjt" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "%.*frb" #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d unduhan dalam 30 hari terakhir" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "Nihil" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "Ukuran Unduh" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "Info ukuran apl tidak tersedia" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "Ukuran unduhan %s" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "Semua Usia" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "Info panduan usia tidak tersedia" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "Cocok untuk semua usia" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "Cocok untuk usia %d ke atas" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "Tidak Diketahui" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "Aplikasi bebas di bawah lisensi %s" #: src/bz-full-view.c:403 msgid "Free software" msgstr "Aplikasi bebas" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "Aplikasi dengan hak cipta khusus" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "Lisensi Khusus: %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "Bebas" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Proprietari" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Lisensi Khusus" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "Adaptif" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "Hanya Desktop" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "Bekerja di desktop, tablet dan ponsel" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "Mungkin tidak bekerja optimal di ponsel" #: src/bz-full-view.c:472 msgid "No URL" msgstr "Tidak ada URL" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Aplikasi ini memiliki lisensi FLOSS, sehingga kode sumbernya dapat diaudit " "secara bebas dan terbuka." #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Aplikasi ini memiliki lisensi proprietari, dikembangkan secara tertutup " "dengan kode sumber aplikasi yang tidak bisa diaudit secara independen." #: src/bz-full-view.c:498 msgid "More Apps" msgstr "Aplikasi Lainnya" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "Aplikasi Lain dari %s" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "Jelajah lebih dari pengembang ini" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "Jelajah lebih dari %s" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s sudah tidak terpasang, namun masih memiliki %s data tersimpan." #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Aman" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "Risiko Rendah" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "Risiko Sedang" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "Risiko Tinggi" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "Aplikasi Lain" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Aplikasi" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "Sembunyikan" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "Tampilkan Lebih Banyak" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Dukungan Perangkat" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Pintasan papan tik" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Membutuhkan papan tik" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Direkomendasikan menggunakan papan tik" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Mendukung papan tik" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Dukungan papan tik tidak diketahui" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Dukungan tetikus" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Membutuhkan tetikus atau alat penunjuk" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Direkomendasikan menggunakan tetikus atau alat penunjuk" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Mendukung tetikus atau alat penunjuk" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Dukungan untuk tetikus atau alat penunjuk tidak diketahui" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Dukungan layar sentuh" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Membutuhkan layar sentuh" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Direkomedasikan menggunakan layar sentuh" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Mendukung layar sentuh" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Dukungan untuk layar sentuh tidak diketahui" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Dukungan ponsel" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Bekerja di ponsel" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Mungkin tidak bekerja optimal di ponsel" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Dukungan desktop" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Bekerja optimal di layar lebar" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s bekerja optimal pada perangkat tertentu" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s bekerja baik pada sebagian besar perangkat" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Berhenti Menerima Pemutakhiran" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "Cari aplikasi terpasang" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "Tidak Ada Aplikasi Tersedia" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 msgid "Library" msgstr "Pustaka" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "Pemutakhiran Tertunda" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "Unduhan" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "Baru Dihapus" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "Bersihkan Transaksi Lama" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "Aplikasi Terpasang" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Tidak ada hasil yang cocok untuk \"%s\" dari aplikasi terpasang" #: src/bz-library-page.c:165 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u Pemutakhiran Tersedia" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Mari Berpartisipasi" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "Lisensi Tidak Diketahui" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "Dibangun Bersama" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Aplikasi ini dikembangkan secara terbuka oleh komunitas dari seluruh dunia.\n" "\n" "Anda dapat berpartisipasi dan ikut membuatnya lebih baik." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "Lisensi aplikasi ini tidak diketahui" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Aplikasi ini dikembangkan secara terbuka oleh komunitas dari seluruh dunia, " "dan dirilis di bawah lisensi %s.\n" "\n" "Anda dapat berpartisipasi membuat aplikasi ini lebih baik." #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Aplikasi ini tidak dikembangkan secara terbuka, sehingga hanya pihak " "pengembang yang memahami penuh cara kerjanya. Pengawasan keamanan aplikasi " "ini mungkin lebih sulit, dan statusnya dapat berubah sewaktu-waktu.\n" "\n" "Anda mungkin tidak dapat berkontribusi pada aplikasi ini." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Aplikasi ini dikembangkan di bawah lisensi khusus %s.\n" "\n" "Anda mungkin dapat atau tidak dapat berkontribusi pada aplikasi ini." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Hubungkan ke Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Terjadi Kesalahan" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Hubungkan akun Flatpak ke Bazaar untuk mengelola aplikasi favorit Anda." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Selesai" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Halo, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Preferensi" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "Koneksi jaringan dibatasi — sinkronisasi data otomatis sedang dijeda" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "Sinkronkan" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Saringan Konten" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Sembunyikan Aplikasi Sumber Tertutup" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Hanya tampilkan aplikasi bersumber terbuka pada hasil cari/jelajah" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Hanya Tampilkan Aplikasi Flathub" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "Batasi hasil cari/jelajah hanya pada aplikasi yang tersedia di Flathub" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Hanya Tampilkan Apl Terverifikasi" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Sembunyikan aplikasi tanpa verifikasi Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Sembunyikan Aplikasi Tanpa Dukungan" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Sembunyikan aplikasi yang sudah tidak didukung oleh para pengembangnya" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "Cari" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Tunda Hasil Pencarian" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "Tingkatkan performa pencarian dengan menunda pemuatan istilah pencarian" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Bilah Kemajuan" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Pilihlah tema favorit Anda!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Strip Vertikal" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Tampilkan warna bendera dari kiri ke kanan" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Warna Aksen" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Warna Kebanggaan" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Warna Bangga Lesbian" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Warna Bangga Homoseksual Pria" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Warna Bangga Transgender" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Warna Bangga Nonbiner" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Warna Bangga Biseksual" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Warna Bangga Aseksual" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Warna Bangga Panseksual" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Warna Bangga Aromantik" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Warna Bangga Fluiditas Gender " #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Warna Bangga Poliseksual" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Warna Bangga Omniseksual" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Warna Bangga Aromantik-Aseksual" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Warna Bangga Agender" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Warna Bangga Genderqueer" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Warna Bangga Interseks" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Warna Bangga Demigender" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Warna Bangga Biromantik" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Warna Bangga Disabilitas" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Warna Bangga Waria" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Warna Bangga Netrois" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:150 msgid "Version History" msgstr "Riwayat Versi" #: src/bz-releases-list.c:168 #, c-format msgid "Version %s" msgstr "Versi %s" #: src/bz-releases-list.c:220 msgid "No details for this release" msgstr "Tidak ada detail untuk rilisan ini" #: src/bz-releases-list.c:232 msgid "Get More Information" msgstr "Info Lebih Lanjut" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Pasang" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "Izin Tidak Jelas" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "Izin aplikasi ini tidak diketahui" #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Tidak Ada Izin" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "Aplikasi ini sepenuhnya terisolasi" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Akses Jaringan" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Dapat mengakses internet" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Tidak Ada Akses Jaringan" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Tidak dapat mengakses internet" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Akses Perangkat Pengguna" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "Dapat mengakses perangkat seperti kamera atau pengontrol mainan" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Tidak Ada Akses Perangkat Pengguna" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "Tidak dapat mengakses perangkat seperti kamera atau pengontrol mainan" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Akses Perangkat Masukan" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Dapat mengakses perangkat masukan" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Akses Mikrofon dan Pemutaran Suara" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "Dapat mengakses mikrofon dan memutar suara tanpa permintaan izin" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Akses Perangkat Sistem" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "Dapat mengakses perangkat sistem yang membutuhkan izin lebih lanjut" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Akses Konten Layar" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Dapat mengakses konten dari layar, termasuk jendela aplikasi lain" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Sistem Jendela Lawas" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Selalu menggunakan sistem jendela lawas X11" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "Izin Sewenang-wenang" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Dapat memperoleh izin sewenang-wenang" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Akses Konfigurasi Pengguna" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Dapat mengakses dan mengubah konfigurasi pengguna" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Akses Baca/Tulis Penuh pada Sistem Berkas" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "" "Memiliki akses baca dan tulis untuk semua data pada sistem perangkat ini" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Akses Baca/Tulis Direktori Rumah" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "" "Memiliki akses baca dan tulis untuk semua data pada direktori Rumah " "perangkat ini" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Akses Baca Penuh dalam Sistem Berkas" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "Memiliki akses baca untuk semua data pada sistem perangkat ini" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Akses Baca Direktori Rumah" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "" "Memiliki akses baca untuk semua data pada direktori Rumah perangkat ini" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Akses Baca/Tulis Folder Unduhan" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "" "Memiliki akses baca dan tulis untuk semua data pada direktori Unduhan " "perangkat ini" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Akses Baca Folder Unduhan" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "Memiliki akses baca untuk semua data di direktori Unduhan Anda" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "Memiliki akses baca dan tulis untuk semua data pada direktori ini" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "Memiliki akses baca untuk semua data pada direktori ini" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Tidak Ada Akses Sistem Berkas" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "Tidak dapat mengakses sistem berkas sama sekali" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Menggunakan Layanan Sistem" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Dapat meminta data dari layanan sistem di luar portal XDG" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Menggunakan Layanan Sesi" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Dapat meminta data dari layanan sesi di luar portal XDG" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Tidak Ada Akses Layanan" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "Tidak dapat mengakses layanan sistem atau sesi non-portal sama sekali" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Pengembang Terverifikasi" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "Pengembang aplikasi ini sudah terverifikasi oleh Flathub" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Kode Proprietari" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Kode sumber aplikasi ini tidak bersifat publik, sehingga aplikasi ini tidak " "dapat diaudit secara independen dan mungkin tidak aman" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Kode Dapat Diaudit" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Kode sumber aplikasi ini bersifat publik dan dapat diaudit secara " "independen, sehingga kemungkinan besar aplikasi ini aman" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Menggunakan Layanan Sistem %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Menggunakan Layanan Sesi %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Menggunakan Layanan %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Dapat melihat layanan di luar portal XDG" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Dapat berkomunikasi dengan layanan di luar portal XDG" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Dapat memiliki layanan di luar portal XDG" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Integrasi Menu Global" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Dapat menampilkan opsi aplikasi pada bilah menu global" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Integrasi Pengaturan KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Dapat mendeteksi ketika terdapat perubahan konfigurasi desktop KDE" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Pengaturan Global KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Dapat membaca preferensi desktop KDE, seperti font dan tema warna" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "Layanan Penyimpanan Sandi" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "Dapat menyimpan dan mengambil kata sandi menggunakan penyimpanan kunci sistem" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Layanan Notifikasi Desktop" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Dapat mengirim notifikasi desktop" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Integrasi Baki Sistem" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Dapat menampilkan ikon pada baki sistem" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Integrasi KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "" "Dapat berinteraksi dengan perangkat yang terkoneksi melalui KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Keamanan" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Rincian" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Lisensi" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "ID Aplikasi" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Aplikasi ini menggunakan versi platform aplikasi (SDK) usang dan mungkin " "memiliki gangguan atau kerentanan keamanan yang tak diperbaiki." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s aman untuk dipasang" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s tidak memiliki izin berbahaya" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s mungkin aman untuk dipasang" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s mungkin tidak aman untuk dipasang" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s tidak aman untuk dipasang" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Tangkapan Layar" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Tangkapan Layar Sebelumnya" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Tangkapan Layar Selanjutnya" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Salin Gambar" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Kembalikan Skala Tampilan" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Perkecil Tampilan" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Perbesar Tampilan" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Karosel Tangkapan Layar" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Tampilkan Tangkapan Layar" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Cari Aplikasi dan Permainan" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Kategori Tidak Tersedia" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Cari aplikasi menggunakan bilah pencarian di atas. " #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Tidak Ada Aplikasi Tersedia" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Tidak ada hasil untuk \"%s\" di Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Tersalin!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Salin Tautan" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Buka Tautan" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Linimasa" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Jumlah Pemasangan:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Dunia" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Pemasangan Total" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2frb Pemasangan Total" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d Pemasangan Total" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Tidak Ada Hasil" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikasi Berlabel \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Pencarian gagal" #: src/bz-transaction-dialog.c:151 msgid "Keep Data" msgstr "Simpan Data" #: src/bz-transaction-dialog.c:152 msgid "Allow restoring settings and content" msgstr "Izinkan pemulihan data dan pengaturan aplikasi" #: src/bz-transaction-dialog.c:161 msgid "Delete Data" msgstr "Hapus Data" #: src/bz-transaction-dialog.c:162 msgid "Permanently remove app data to save space" msgstr "Hapus permanen data aplikasi untuk menghemat ruang" #: src/bz-transaction-dialog.c:187 #, c-format msgid "Install %s?" msgstr "Pasang %s?" #: src/bz-transaction-dialog.c:192 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Pilih versi pemasangan. Mungkin membutuhkan pemasangan komponen tambahan" #: src/bz-transaction-dialog.c:194 msgid "May install additional shared components" msgstr "Mungkin membutuhkan pemasangan komponen tambahan" #: src/bz-transaction-dialog.c:215 #, c-format msgid "Remove %s?" msgstr "Hapus %s?" #: src/bz-transaction-dialog.c:218 msgid "Select which version to remove." msgstr "Pilih versi aplikasi yang akan dihapus." #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Setelah dihapus, aplikasi %s tidak akan bisa digunakan." #: src/bz-transaction-dialog.c:243 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" memiliki risiko tinggi" #: src/bz-transaction-dialog.c:247 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Aplikasi ini memiliki akses penuh pada sistem Anda, termasuk semua file, " "riwayat peramban, kata sandi tersimpan, dan data lainnya. Aplikasi ini " "juga memiliki akses internet, yang memungkinkannya mengirim data Anda ke " "pihak luar. \n" "\n" "Karena kode sumbernya tidak terbuka, aplikasi ini tidak dapat diaudit " "terkait penggunaan izin-izin tersebut." #: src/bz-transaction-dialog.c:256 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Aplikasi ini menggunakan sistem jendela lawas X11, yang memungkinkannya " "merekam semua penekanan tombol, mengambil tangkapan layar, dan memantau " "aplikasi lain. Aplikasi ini juga memiliki akses internet, yang " "memungkinkannya mengirim data Anda ke pihak luar.\n" "\n" "Karena kode sumbernya tidak terbuka, aplikasi ini tidak dapat diaudit " "terkait penggunaan izin-izin tersebut." #: src/bz-transaction-dialog.c:272 msgid "Install Anyway" msgstr "Tetap Pasang" #: src/bz-transaction-dialog.c:533 msgid "All apps are already installed" msgstr "Semua aplikasi sudah terpasang." #: src/bz-transaction-dialog.c:535 msgid "OK" msgstr "Ya" # %u is the number of apps to install, so the strings might have singular and plural versions depend on your language. #: src/bz-transaction-dialog.c:551 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Pasang %u Aplikasi?" #: src/bz-transaction-dialog.c:559 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Aplikasi berikut akan dipasang, termasuk komponen tambahan jika tersedia" #: src/bz-transaction-dialog.c:560 #, c-format msgid "%d addons will be installed." msgstr "%d komponen tambahan akan dipasang." #: src/bz-transaction-dialog.c:561 msgid "Additionally, addons will be installed." msgstr "Selain itu, komponen tambahan juga akan dipasang." #: src/bz-transaction-manager.c:1248 #, c-format msgid "Finished in %.02f seconds" msgstr "Selesai dalam %.02f detik" #: src/bz-transaction-tile.blp:125 msgid "App Add-on" msgstr "Modul Aplikasi" #: src/bz-transaction-tile.blp:154 msgid "Runtime" msgstr "Tempokerja (Runtime)" #: src/bz-transaction-tile.blp:178 msgid "In Queue" msgstr "Dalam Antrian" #: src/bz-transaction-tile.blp:202 msgid "Done" msgstr "Selesai" #: src/bz-transaction-tile.blp:243 msgid "Open App" msgstr "Buka Aplikasi" #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s Bebas" #: src/bz-transaction.c:342 msgid "Pending" msgstr "Ditunda" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "Mutakhirkan Semua" #: src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "Pemutakhiran" #: src/bz-updates-card.c:293 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u Tempokerja Baru" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Kelola Sisa Data Pengguna" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "Data Pengguna tidak ditemukan" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "Data Pengguna" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Data aplikasi %s telah dihapus." #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Hapus Data Pengguna" #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "Memuat Ulang Konten Bazaar" #: src/bz-window.blp:153 msgid "Curated" msgstr "Pilihan" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "Tidak ada proses latar belakang!" #: src/bz-window.blp:325 msgid "You are running a new version of Bazaar!" msgstr "Versi terbaru Bazaar telah terpasang!" #: src/bz-window.blp:326 msgid "See What's New" msgstr "Lihat Yang Baru" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "Saat ini Bazaar belum memuat halaman Flathub terbaru" #: src/bz-window.blp:449 msgid "Log Out" msgstr "Keluar" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "Anda tidak dapat menghapus Bazaar dari dalam Bazaar." #: src/bz-window.c:891 src/bz-window.c:925 msgid "Can't do that right now!" msgstr "Tunggu hingga Bazaar selesai memuat" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "Unduhan" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Umum" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Buka Dialog Pencarian" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Buka Pengaturan" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Sinkronkan Dengan Server" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Open Library" msgstr "Buka Pustaka" #: src/gtk/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Tampilkan Pintasan" #: src/gtk/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Quit" msgstr "Keluar" #~ msgid "Toggle transaction sidebar" #~ msgstr "Tampil/sembunyikan bilah samping transaksi" #~ msgid "Install Size" #~ msgstr "Ukuran Terpasang" #~ msgid "Ongoing" #~ msgstr "Saat Ini" #~ msgid "Finished" #~ msgstr "Selesai" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "Telah mentransfer %s sejauh ini" #, c-format #~ msgid "%d Update Available" #~ msgid_plural "%d Updates Available" #~ msgstr[0] "%d Pemutakhiran Tersedia" #~ msgid "Updates Are Available" #~ msgstr "Terdapat Pemutakhiran" #~ msgid "" #~ "The following applications are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "Aplikasi berikut memiliki pemutakhiran. Apakah anda ingin memasangnya?" #, c-format #~ msgid "" #~ "%d runtimes and/or addons are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "%d tempokerja dan/atau modul tambahan memiliki pemutakhiran. Apakah Anda " #~ "ingin memasangnya?" #, c-format #~ msgid "Additionally, %d runtimes and/or addons will be updated." #~ msgstr "" #~ "Selain itu, %d tempokerja dan/atau modul tambahan akan dimutakhirkan." #~ msgid "Update Now" #~ msgstr "Mutakhirkan Sekarang" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "Tampilkan/sembunyikan Manajer Transaksi" #~ msgid "Hide EOL Entries" #~ msgstr "Sembunyikan Aplikasi Tanpa Dukungan" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "Sembunyikan aplikasi dan dependensi tanpa dukungan mutakhir" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Tunjukkan Jumlah Bintang Repo" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "" #~ "Deteksi dan tampilkan data \"jumlah bintang\" repositori git saat memuat " #~ "halaman detail aplikasi" #~ msgid "Only Show Free Software" #~ msgstr "Sembunyikan Aplikasi Sumber Tertutup" #~ msgid "Hide proprietary software" #~ msgstr "Hanya tampilkan aplikasi dengan lisensi sumber terbuka" #~ msgid "Debounce Search Inputs" #~ msgstr "Tunda Masukan Pencarian" #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "" #~ "Tunda masukan saat mengetik untuk mencegah hasil pencarian muncul terlalu " #~ "cepat" #~ msgid "Global Progress Bar Theme" #~ msgstr "Tema Bilah Kemajuan" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Pilih tampilan bilah kemajuan Bazaar" #~ msgid "Saved Window Dimensions" #~ msgstr "Dimensi Jendela Tersimpan" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "Dimensi jendela saat membuka jendela Bazaar berikutnya" #~ msgid "?" #~ msgstr "?" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s cocok untuk usia batita" #~ msgid "--- MB" #~ msgstr "--- MB" #~ msgid "Of the size of human DNA" #~ msgstr "Dari ukuran DNA manusia" #~ msgid "3 billion base pairs" #~ msgstr "3 miliar pasangan basa" #~ msgid "Of the Linux Kernel" #~ msgstr "Dari ukuran kernel Linux" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "Dari ukuran RAM dan ROM komputer pemandu Apollo 11" #~ msgid "Total ROM and RAM" #~ msgstr "Pada misi pendaratan manusia pertama di Bulan" #~ msgid "Of the original Super Mario Bros" #~ msgstr "Dari ukuran gim Super Mario Bros asli" #~ msgid "On the NES" #~ msgstr "pada konsol NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "Dari ukuran seluruh artikel Wikipedia" #~ msgid "Without any media" #~ msgstr "Tanpa file media sama sekali" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "Fitur ini sedang dinonaktifkan. Silahkan unduh dan pasang Flatseal untuk " #~ "mengatur perizinan aplikasi. " #~ msgid "Entry Inspector" #~ msgstr "Periksa Masukan" #~ msgid "Serialize" #~ msgstr "Serialisasikan" #~ msgid "Convert to JSON" #~ msgstr "Ubah ke JSON" #~ msgid "More Mobile apps" #~ msgstr "Aplikasi Ponsel lainnya" #~ msgid "We ♥ Games" #~ msgstr "Kami ♥ Main" #~ msgid "Repository Star Count" #~ msgstr "Jumlah Bintang Repositori" #~ msgid "Size" #~ msgstr "Ukuran" #, c-format #~ msgid "%.2fM" #~ msgstr "%.2fM" #, c-format #~ msgid "%.2fK" #~ msgstr "%.2fK" #~ msgid "Bazaar Inspector" #~ msgstr "Pemeriksa Bazaar" #~ msgid "Enable Global Debug Mode" #~ msgstr "Nyalakan Mode Debug Global" #~ msgid "Active Blocklists" #~ msgstr "Daftar Blok Aktif" #~ msgid "Active Curated-Configs" #~ msgstr "Konfigurasi Kurasi Aktif" #~ msgid "All Entry Groups" #~ msgstr "Seluruh Grup Masukan" #~ msgid "Filter..." #~ msgstr "Saring..." #~ msgid "Decache and Inspect" #~ msgstr "Hapus Cache dan Periksa" #~ msgid "No Flatpaks Installed" #~ msgstr "Tidak Ada Flatpak Terpasang" #~ msgid "Application Details" #~ msgstr "Detail Aplikasi" #~ msgid "Display Star Count" #~ msgstr "Tunjukkan Jumlah Bintang Repo" #~ msgid "Show the star count of an application's source code repository" #~ msgstr "Tunjukkan jumlah bintang dari repositori sumber aplikasi" #~ msgid "" #~ "Bazaar can fetch and display the star count from an application's source " #~ "code repository on a remote Git forge. \n" #~ " For projects on GitHub, rate limits may cause them not to appear." #~ msgstr "" #~ "Bazaar dapat mengambil dan menampilkan jumlah bintang dari repositori Git " #~ "sumber kode aplikasi.\n" #~ "Untuk aplikasi dari GitHub, terdapat potensi terbatasnya muatan yang " #~ "mungkin menghambat munculnya data ini." #~ msgid "Inspect UI Entry" #~ msgstr "Periksa Masukan Antarmuka" #~ msgid "All Debug Actions" #~ msgstr "Semua Tindakan Debug" #~ msgid "Tasks" #~ msgstr "Proses" #~ msgid "Stop Active Tasks" #~ msgstr "Hentikan Proses Aktif" #~ msgid "Clear History" #~ msgstr "Hapus Riwayat" #~ msgid "No Tasks Yet" #~ msgstr "Tidak ada proses berlangsung" #~ msgid "Sync" #~ msgstr "Sinkronisasi" #~ msgid "Open Bazaar Inspector" #~ msgstr "Buka Pemeriksa Bazaar" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "Kemampuan membuka dan memasang file .flatpak secara lokal segera hadir! " #~ "Saat ini, coba jalankan\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "pada baris perintah." #~ msgid "Resume Current Tasks" #~ msgstr "Lanjutkan Proses Ini" #~ msgid "Pause Current Tasks" #~ msgstr "Jeda Proses Ini" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u unduhan" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Muat ulang" #~ msgid "Show Animated Background" #~ msgstr "Tampilkan Animasi Latar Belakang" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Tampilkan animasi ikon latar belakang pada halaman utama" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Buat ringkasan pendek berkisar antara 10-35 karakter" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Jendela utama Bazaar yang menampilkan Blender" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "Flatpak ini telah diverifikasi oleh pengembang perangkat lunak asli" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore" #~ msgstr "Jill Fiore" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Konfigurasi kurasi konten Bazaar saat ini belum tersedia. Hubungi sistem " #~ "operasi anda untuk mendukung fitur ini." #~ msgid "Apps Of The Week" #~ msgstr "Aplikasi Minggu Ini" #~ msgid "Run this application" #~ msgstr "Jalankan aplikasi ini" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "Jumlah unduhan pada 30 hari terakhir. Klik untuk melihat statistik " #~ "unduhan aplikasi ini." #~ msgid "Remote repo name" #~ msgstr "Nama repo remote" #, c-format #~ msgid "Released %x" #~ msgstr "Dirilis pada %x" #~ msgid "How the application looks" #~ msgstr "Tampilan aplikasi" #~ msgid "Appearance" #~ msgstr "Tampilan" #~ msgid "Show animated background" #~ msgstr "Tampilkan animasi latar belakang" #~ msgid "Type to filter" #~ msgstr "Ketik untuk mencari" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Sembunyikan aplikasi berlisensi proprietari" #~ msgid "Advanced" #~ msgstr "Opsi Lanjutan" #~ msgid "Match using regular expressions" #~ msgstr "Cocokkan dengan ekspresi reguler (regex)" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "Sembunyikan hasil pencarian dan sortir di balik transisi pemuatan" #~ msgid "Share" #~ msgstr "Bagikan" #~ msgid "Open this link externally" #~ msgstr "Buka tautan ini secara eksternal" #~ msgid "Downloads Over Time" #~ msgstr "Unduhan seiring waktu" #~ msgid "Minimize Lower Bound" #~ msgstr "Perkecil batas bawah" #~ msgid "Maximize Upper Bound" #~ msgstr "Perbesar batas atas" #~ msgid "Installing" #~ msgstr "Sedang dipasang" #~ msgid "Removing" #~ msgstr "Sedang dihapus" #~ msgid "Transactions Will Appear Here" #~ msgstr "Transaksi akan muncul di sini" #~ msgid "Halt the execution of transactions" #~ msgstr "Hentikan proses transaksi" #~ msgid "Browse" #~ msgstr "Telusuri" #~ msgid "App View" #~ msgstr "Tampilan Aplikasi" #~ msgid "Go Back" #~ msgstr "Kembali" #~ msgid "Refresh" #~ msgstr "Muat ulang" #~ msgid "View curated applications" #~ msgstr "Lihat aplikasi pilihan" #~ msgid "View the latest on Flathub" #~ msgstr "Lihat yang terbaru dari Flathub" #~ msgid "Up to date!" #~ msgstr "Versi terkini sudah dimuat!" #~ msgid "Confirm Action" #~ msgstr "Konfirmasi Aksi" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Anda akan menghapus Flatpak berikut:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Apakah Anda yakin?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Anda akan memasang Flatpak berikut:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Apakah Anda yakin?" #~ msgid "Resume the execution of transactions" #~ msgstr "Lanjutkan proses transaksi" #~ msgid "Pause the execution of transactions" #~ msgstr "Hentikan sementara proses transaksi" kolunmi-bazaar-7b9c8e1/po/it.po000066400000000000000000001317541514314607700164670ustar00rootroot00000000000000# Italian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Pietro F. , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-11-11 10:39+0100\n" "PO-Revision-Date: 2025-11-11 11:25+0100\n" "Last-Translator: Pietro F. \n" "Language-Team: Italian\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:225 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Aggiunge, rimuove o aggiorna le applicazioni flatpak su questo computer" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Nascondi voci EOL" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Nascondi voci EOL e voci che dipendono da esse" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Show Git Forge Star Counts" msgstr "Mostra il numero di stelle su Git Forge" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the " "full view" msgstr "" "Se tentare di rilevare e mostrare il “numero di stelle” per i progetti nella " "vista completa" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Only Show Free Software" msgstr "Mostra solo Free Software" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Hide proprietary software when searching" msgstr "nascondi software proprietario durante la ricerca" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Show Only Flathub Content" msgstr "Mostra solo i contenuti di Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Filter search results to only show applications available on Flathub" msgstr "" "Filtra i risultati della ricerca per mostrare solo le applicazioni " "disponibili su Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:26 msgid "Debounce Search Inputs" msgstr "Ricerca senza rimbalzo" #: data/io.github.kolunmi.Bazaar.gschema.xml:27 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "" "Aggiungere un ritardo nell'elaborazione dei dati per evitare risultati " "immediati" #: data/io.github.kolunmi.Bazaar.gschema.xml:45 msgid "Global Progress Bar Theme" msgstr "Tema barra di avanzamento globale" #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "Describes the look of the global progress bar" msgstr "Descrive l'aspetto della barra di avanzamento globale" #: data/io.github.kolunmi.Bazaar.gschema.xml:50 msgid "Saved Window Dimensions" msgstr "Dimensioni finestra salvate" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "The window dimensions to be used by the next Bazaar window" msgstr "" "Le dimensioni della finestra da utilizzare per la prossima finestra Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Scopri e installa applicazioni" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Un nuovo app store per GNOME incentrato sulla ricerca e l'installazione di " "applicazioni e componenti aggiuntivi dai repository remoti Flatpak, in " "particolare Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Sottolinea l'importanza di supportare gli sviluppatori che rendono possibile " "il desktop Linux. Bazaar presenta una scheda “Consigliate” che può essere " "configurata dai distributori per consentire un'esperienza più personalizzata." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:494 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "La schermata iniziale che mostra le app di Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Pagina dell'app Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Pagina di Ricerca" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Pagina delle Categorie" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:582 msgid "Manage Add-ons" msgstr "Gestisce estensioni" #: src/bz-addons-dialog.c:88 src/bz-transaction-view.blp:212 #: src/bz-window.c:1101 msgid "Remove" msgstr "Rimuovi" #: src/bz-addons-dialog.c:93 src/bz-full-view.blp:289 #: src/bz-transaction-view.blp:186 src/bz-window.c:1077 msgid "Install" msgstr "Installa" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Delle dimensioni del DNA umano" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 miliardi di coppie di basi" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "Del kernel Linux" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "Del computer di bordo dell'Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "ROM e RAM totali" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "Dell'originale Super Mario Bros." #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "Su NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "Delle dimensioni di Wikipedia" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Senza alcun media" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Dimensione Download" #: src/bz-application.c:416 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Questa funzionalità è attualmente disabilitata. Si consiglia di scaricare e " "installare Flatseal per gestire le autorizzazioni delle app." #: src/bz-application.c:479 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:480 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:497 msgid "translator-credits" msgstr "Pietro F. , 2025" #: src/bz-application.c:1069 msgid "Constructing Flatpak instance..." msgstr "Creazione dell'istanza Flatpak..." #: src/bz-application.c:1086 msgid "Reusing last Flatpak instance..." msgstr "Riutilizzo dell'ultima istanza Flatpak..." #: src/bz-application.c:1111 msgid "Flathub is not registered on this system" msgstr "Flathub non è registrato su questo sistema" #: src/bz-application.c:1114 msgid "" "Would you like to add Flathub as a remote? If you decline, the Flathub page " "will not be available. You can change this later." msgstr "" "Vuoi aggiungere Flathub come repository remoto? Se rifiuti, la pagina " "Flathub non sarà disponibile. Puoi cambiare questa impostazione in un " "secondo momento." #: src/bz-application.c:1119 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Dopo" #: src/bz-application.c:1120 msgid "Add Flathub" msgstr "Aggiungi Flathub" #: src/bz-application.c:1152 msgid "Identifying installed entries..." msgstr "Identificazione delle voci installate..." #: src/bz-application.c:1176 msgid "Receiving Entries" msgstr "Ricezione delle voci" #: src/bz-application.c:1333 #, c-format msgid "%'d of %'d" msgstr "%'d di %'d" #: src/bz-application.c:1346 #, c-format msgid "Waiting for background indexing tasks to catch up..." msgstr "" "In attesa che le attività di indicizzazione in background vengano " "completate..." #: src/bz-application.c:1388 #, c-format msgid "Completed initialization in %0.2f seconds" msgstr "Inizializzazione completata in %0.2f secondi" #: src/bz-application.c:1393 src/bz-application.c:1548 msgid "Checking for updates..." msgstr "Controllo degli aggiornamenti..." #: src/bz-application.c:1432 msgid "Synchronizing..." msgstr "Sincronizzazione..." #: src/bz-browse-widget.blp:11 src/bz-flathub-page.blp:19 #: src/bz-full-view.blp:53 src/bz-installed-page.blp:15 src/bz-window.blp:174 msgid "Empty" msgstr "Vuoto" #: src/bz-browse-widget.blp:15 msgid "No Curation" msgstr "Non ci sono Applicazioni Consigliate" #: src/bz-browse-widget.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Non sono disponibili informazioni sulle app consigliate per questo sistema. " "È comunque possibile sfogliare le applicazioni su Flathub" #: src/bz-browse-widget.blp:18 msgid "Browse Flathub" msgstr "Esplora Flathub" #: src/bz-browse-widget.blp:29 src/bz-browse-widget.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Nessuna connessione" #: src/bz-browse-widget.blp:39 src/bz-flathub-page.blp:40 msgid "Browser" msgstr "Browser" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Ispettore delle voci" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Serializza" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Converti in JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Si è verificato un errore" #: src/bz-error.c:89 msgid "Close" msgstr "Chiudi" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Copia e Chiudi" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "App del Giorno" #: src/bz-flathub-category.c:66 msgid "Audio & Video" msgstr "Audio & Video" #: src/bz-flathub-category.c:66 msgid "Media" msgstr "Media" #: src/bz-flathub-category.c:66 msgid "More Audio & Video" msgstr "Più Audio & Video" #: src/bz-flathub-category.c:67 msgid "Developer Tools" msgstr "Strumenti per Sviluppatori" #: src/bz-flathub-category.c:67 msgid "Develop" msgstr "Sviluppa" #: src/bz-flathub-category.c:67 msgid "More Developer Tools" msgstr "Più Strumenti per Sviluppatori" #: src/bz-flathub-category.c:68 msgid "Education" msgstr "Educazione" #: src/bz-flathub-category.c:68 msgid "Learn" msgstr "Impara" #: src/bz-flathub-category.c:68 msgid "More Education" msgstr "Più Educazione" #: src/bz-flathub-category.c:69 msgid "Gaming" msgstr "Gaming" #: src/bz-flathub-category.c:69 msgid "Play" msgstr "Gioca" #: src/bz-flathub-category.c:69 msgid "More Gaming" msgstr "Più Gaming" #: src/bz-flathub-category.c:70 msgid "Graphics & Photography" msgstr "Grafica & Fotografia" #: src/bz-flathub-category.c:70 msgid "Create" msgstr "Crea" #: src/bz-flathub-category.c:70 msgid "More Graphics & Photography" msgstr "Più Grafica & Fotografia" #: src/bz-flathub-category.c:71 msgid "Networking" msgstr "Networking" #: src/bz-flathub-category.c:71 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:71 msgid "More Networking" msgstr "Più Networking" #: src/bz-flathub-category.c:72 msgid "Productivity" msgstr "Produttività" #: src/bz-flathub-category.c:72 msgid "Work" msgstr "Lavoro" #: src/bz-flathub-category.c:72 msgid "More Productivity" msgstr "Più Produttività" #: src/bz-flathub-category.c:73 msgid "Science" msgstr "Scienza" #: src/bz-flathub-category.c:73 msgid "More Science" msgstr "Più Scienza" #: src/bz-flathub-category.c:74 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:74 msgid "More System" msgstr "Più Sistema" #: src/bz-flathub-category.c:75 msgid "Utilities" msgstr "Utilità" #: src/bz-flathub-category.c:75 msgid "Tools" msgstr "Strumenti" #: src/bz-flathub-category.c:75 msgid "More Utilities" msgstr "Più Utilità" #: src/bz-flathub-category.c:76 src/bz-flathub-page.blp:109 #: src/bz-flathub-page.blp:142 msgid "Trending" msgstr "In Tendenza" #: src/bz-flathub-category.c:76 msgid "More Trending" msgstr "Più In Tendenza" #: src/bz-flathub-category.c:77 src/bz-flathub-page.blp:115 #: src/bz-flathub-page.blp:175 msgid "Popular" msgstr "Popolari" #: src/bz-flathub-category.c:77 msgid "More Popular" msgstr "Più Popolari" #: src/bz-flathub-category.c:78 src/bz-flathub-page.blp:164 msgid "Recently Added" msgstr "Aggiunte Recentemente" #: src/bz-flathub-category.c:78 src/bz-flathub-page.blp:121 msgid "New" msgstr "Nuove" #: src/bz-flathub-category.c:78 msgid "More New" msgstr "Più Nuove" #: src/bz-flathub-category.c:79 src/bz-flathub-page.blp:153 msgid "Recently Updated" msgstr "Aggiornate Recentemente" #: src/bz-flathub-category.c:79 src/bz-flathub-page.blp:127 msgid "Updated" msgstr "Aggiornate" #: src/bz-flathub-category.c:79 msgid "More Updated" msgstr "Più Aggiornate Recentemente" #: src/bz-flathub-category.c:80 msgid "Mobile" msgstr "Mobile" #: src/bz-flathub-category.c:80 msgid "More Mobile" msgstr "Più Mobile" #: src/bz-flathub-category-section.c:132 src/bz-search-widget.c:314 #, c-format msgid "%d applications" msgstr "%d applicazioni" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub non aggiunto" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "Il repository remoto Flathub non è stato trovato in nessuna delle tue " "installazioni Flatpak" #: src/bz-flathub-page.blp:48 msgid "Flathub Unavailable" msgstr "Flathub non disponibile" #: src/bz-flathub-page.blp:49 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Impossibile connettersi a Flathub. È comunque possibile gestire e cercare le " "applicazioni." #: src/bz-flathub-page.blp:52 msgid "Search Apps" msgstr "Cerca Applicazioni" #: src/bz-flathub-page.blp:266 msgid "On the go" msgstr "On the go" #: src/bz-flathub-page.blp:278 msgid "Apps for your Linux phones and tablets" msgstr "App per il tuo telefono o tablet Linux" #: src/bz-flathub-page.blp:289 src/bz-flathub-page.blp:324 msgid "More Mobile apps" msgstr "Più App Mobile" #: src/bz-flathub-page.c:204 msgid "Mobile Apps" msgstr "App Mobile" #: src/bz-flatpak-entry.c:554 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Pagina Flathub" #: src/bz-flatpak-entry.c:575 msgctxt "Project URL Type" msgid "Project Website" msgstr "Sito del Progetto" #: src/bz-flatpak-entry.c:579 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Segnala un problema" #: src/bz-flatpak-entry.c:583 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:587 msgctxt "Project URL Type" msgid "Help" msgstr "Aiuto" #: src/bz-flatpak-entry.c:591 msgctxt "Project URL Type" msgid "Donate" msgstr "Dona" #: src/bz-flatpak-entry.c:597 msgctxt "Project URL Type" msgid "Translate" msgstr "Traduci" #: src/bz-flatpak-entry.c:601 msgctxt "Project URL Type" msgid "Contact" msgstr "Contatta" #: src/bz-flatpak-entry.c:605 msgctxt "Project URL Type" msgid "Source Code" msgstr "Codice Sorgente" #: src/bz-flatpak-entry.c:611 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuisci" #: src/bz-full-view.blp:20 src/bz-window.blp:117 src/bz-window.blp:394 msgid "Toggle transaction sidebar" msgstr "Mostra o Nasconde il menu delle operazioni" #: src/bz-full-view.blp:43 src/bz-window.blp:417 msgid "Main Menu" msgstr "Menu Principale" #: src/bz-full-view.blp:57 msgid "No Results" msgstr "Nessun risultato" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Prova con una ricerca diversa" #: src/bz-full-view.blp:64 src/bz-window.blp:184 msgid "Content" msgstr "Contenuto" #: src/bz-full-view.blp:196 msgid "Verified by the original developers" msgstr "Verificato dagli sviluppatori originali" #: src/bz-full-view.blp:223 msgid "Support" msgstr "Supporta" #: src/bz-full-view.blp:243 msgid "Repository Star Count" msgstr "Numero di stelle del repository" #: src/bz-full-view.blp:273 msgid "Open" msgstr "Apri" #: src/bz-full-view.blp:286 msgid "Download & Install Application" msgstr "Installa questa applicazione" #: src/bz-full-view.blp:301 msgid "Uninstall Application" msgstr "Disinstalla questa applicazione" #: src/bz-full-view.blp:316 msgid "Install Other Version" msgstr "Installa altra versione" #: src/bz-full-view.blp:340 msgid "Size" msgstr "Peso" #: src/bz-full-view.blp:456 msgid "Downloads /mo" msgstr "Download /mo" #: src/bz-full-view.c:284 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:288 #, c-format msgid "%.2fM" msgstr "%.2fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:291 #, c-format msgid "%.2fK" msgstr "%.2fK" #: src/bz-full-view.c:300 #, c-format msgid "%d downloads in the last 30 days" msgstr "%'d download negli ultimi 30 giorni" #: src/bz-full-view.c:321 #, c-format msgid "Download size of %s" msgstr "Dimensioni Download di %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-full-view.c:331 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-full-view.c:339 msgid "All Ages" msgstr "Tutte le Età" #: src/bz-full-view.c:341 msgid "Age Rating" msgstr "Fascia d'Età" #: src/bz-full-view.c:349 msgid "Suitable for all ages" msgstr "Adatto per tutte le età" #: src/bz-full-view.c:351 #, c-format msgid "Suitable for ages %d and up" msgstr "Adatto per %d anni in sù" #: src/bz-full-view.c:375 msgid "Unknown" msgstr "Sconosciuto" #: src/bz-full-view.c:378 msgid "Proprietary Software" msgstr "Software Propietario" #: src/bz-full-view.c:382 #, c-format msgid "Free software licensed under %s" msgstr "Free software sotto licenza %s" #: src/bz-full-view.c:390 msgid "Free" msgstr "Free" #: src/bz-full-view.c:390 msgid "Proprietary" msgstr "Propietario" #: src/bz-full-view.c:410 msgid "Adaptive" msgstr "Adattiva" #: src/bz-full-view.c:410 msgid "Desktop Only" msgstr "Solo Desktop" #: src/bz-full-view.c:416 msgid "Works on desktop, tablets, and phones" msgstr "Funziona su desktop, tablet e telefoni" #: src/bz-full-view.c:417 msgid "May not work on mobile devices" msgstr "Potrebbe non funzionare su dispositvi mobili" #: src/bz-full-view.c:428 msgid "No URL" msgstr "Nessun URL" #: src/bz-full-view.c:446 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Questa applicazione ha una licenza FLOSS, il che significa che il codice " "sorgente può essere controllato per sicurezza." #: src/bz-full-view.c:447 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Questa applicazione ha una licenza proprietaria, il che significa che il " "codice sorgente è sviluppato privatamente e non può essere verificato da una " "terza parte indipendente." #: src/bz-full-view.c:454 msgid "Other Apps by this Developer" msgstr "Altre App di questo Sviluppatore" #: src/bz-full-view.c:456 #, c-format msgid "Other Apps by %s" msgstr "Altre App di %s" #: src/bz-full-view.c:828 msgid "Show Less" msgstr "Mostra di meno" #: src/bz-full-view.c:828 msgid "Show More" msgstr "Mostra di più" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Supporto per le tastiere" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Richiede le tastiere" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Raccomanda le tastiere" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Supporto per le tastiere" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Supporto sconosciuto per le tastiere" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Supporto Mouse" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Richiede mouse o dispositivi di puntamento" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Raccomanda mouse o dispositivi di puntamento" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Supporto per mouse o dispositivi di puntamento" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Supporto sconosciuto per mouse o dispositivi di puntamento" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Supporto per schermi touchscreen" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Richiede schermi touchscreen" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Raccomanda schermi touchscreen" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Supporto touchscreen" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Supporto sconosciuto per schermi touchscreen" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Supporto per dispositivi mobili" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Funziona su dispositivi mobili" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Potrebbe non funzionare su dispositivi mobili" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Supporto Desktop" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Ottimizzato per grandi schermi" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s funziona al meglio su hardware specifico" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s funziona sulla maggior parte dei dispositivi" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Supporto Hardware" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Ispettore di Bazaar" #: src/bz-inspector.blp:22 msgid "Enable Global Debug Mode" msgstr "Abilita Modalità di Debug globale" #: src/bz-inspector.blp:29 msgid "Active Blocklists" msgstr "Blocklist attive" #: src/bz-inspector.blp:46 msgid "Active Curated-Configs" msgstr "Configurazioni attive per Consigliate" #: src/bz-inspector.blp:64 msgid "All Entry Groups" msgstr "Tutti i gruppi di voci" #: src/bz-inspector.blp:72 msgid "Filter..." msgstr "Filtra..." #: src/bz-inspector.blp:113 msgid "Decache and Inspect" msgstr "Elimina la cache ed Ispeziona" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Nessun Flatpak Installato" #: src/bz-installed-page.blp:25 src/bz-window.blp:319 msgid "Installed" msgstr "Installate" #: src/bz-installed-page.c:406 msgid "Choose an Installation" msgstr "Scegli un installazione" #: src/bz-installed-page.c:409 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "Hai installato più versioni di questa app. Con quale desideri procedere? " #: src/bz-installed-page.c:413 src/bz-window.c:1076 src/bz-window.c:1100 msgid "Cancel" msgstr "Annulla" #: src/bz-license-dialog.c:115 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may not be able to contribute to this app." msgstr "" "Questa app non è sviluppata in modo trasparente, quindi solo i suoi " "sviluppatori sanno come funziona. Potrebbe essere insicura in modi difficili " "da rilevare e potrebbe cambiare senza preavviso o supervisione." #: src/bz-license-dialog.c:124 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Questa app è sviluppata apertamente da una comunità internazionale.\n" "\n" "Puoi partecipare e contribuire a renderla ancora migliore." #: src/bz-license-dialog.c:135 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Questa applicazione è sviluppata apertamente da una comunità internazionale " "e rilasciata con licenza %s.\n" "\n" "Puoi partecipare e contribuire a migliorarla." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Preferenze" #: src/bz-preferences-dialog.blp:23 src/bz-window.blp:334 msgid "Search" msgstr "Cerca" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Solo Free Software" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications from search results" msgstr "Nascondi applicazioni proprietarie dai risultati di ricerca" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Solo risultati da Flathub" #: src/bz-preferences-dialog.blp:32 msgid "Limit search results to applications only available on Flathub" msgstr "" "Limita i risultati della ricerca alle applicazioni disponibili su Flathub" #: src/bz-preferences-dialog.blp:36 msgid "Delay Search Results" msgstr "Mostra Risultati di Ricerca" #: src/bz-preferences-dialog.blp:37 msgid "Improve results performance by debouncing search terms" msgstr "" "Migliorare le prestazioni dei risultati applicando il debouncing ai termini " "di ricerca" #: src/bz-preferences-dialog.blp:42 msgid "Application Details" msgstr "Dettagli dell'app" #: src/bz-preferences-dialog.blp:45 msgid "Display Star Count" msgstr "Mostra conteggio stelle" #: src/bz-preferences-dialog.blp:46 msgid "Show the star count of an application's source code repository" msgstr "" "Mostra il numero di stelle del repository del codice sorgente di " "un'applicazione" #: src/bz-preferences-dialog.blp:71 msgid "Progress Bar" msgstr "Barra di avanzamento" #: src/bz-preferences-dialog.blp:72 msgid "Choose a theme for the progress bar!" msgstr "Scegli un tema per la barra di avanzamento!" #: src/bz-preferences-dialog.blp:98 msgid "End of Life Apps" msgstr "App Obsolete" #: src/bz-preferences-dialog.blp:101 msgid "Hide EOL Apps" msgstr "Nascondi App obsolete" #: src/bz-preferences-dialog.blp:102 msgid "Hide apps which are no longer supported by their developers" msgstr "Nascondi le app non più supportate dagli sviluppatori" #: src/bz-preferences-dialog.blp:116 msgid "" "Bazaar can fetch and display the star count from an application's source " "code repository on a remote Git forge. \n" " For projects on GitHub, rate limits may cause them not to appear." msgstr "" "Bazaar può recuperare e visualizzare il numero di stelle dal repository del " "codice sorgente di un'applicazione su una piattaforma Git remota.\n" "Per i progetti su GitHub, i limiti di richieste potrebbero impedirne la " "visualizzazione." #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Colore d'accento" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Colori Pride" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Colori lesbian pride" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Colori transgender pride" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Colori nonbinary pride" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Colori bisexual pride" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Colori asexual pride" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "" "Non sono disponibili informazioni sulla curatela per questo sistema. È " "comunque possibile sfogliare le applicazioni su Flathub" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Colori aromantic pride" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Colori genderfluid pride" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Colori polysexual pride" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Colori omnisexual pride" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "Cronologia delle Versioni" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "Versione %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "Nessun dettaglio per questa versione" #: src/bz-rich-app-tile.blp:103 msgid "Get" msgstr "Ottieni" #: src/bz-search-widget.blp:105 msgid "Search Apps, Games, Software" msgstr "Cerca App, Giochi, Software" #: src/bz-search-widget.blp:149 msgid "Categories Unavailable" msgstr "Categorie non disponibili" #: src/bz-search-widget.blp:150 msgid "Search for apps using the search bar above." msgstr "Cerca le app digitando nella barra di ricerca superiore." #: src/bz-search-widget.blp:233 msgid "No Applications Found" msgstr "Nessuna Applicazione Trovata" #: src/bz-search-widget.c:225 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Nessun risultato per \"%s\" in Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Copiato!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Copia Link" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Apri Link" #: src/bz-stats-dialog.blp:26 msgid "Timeline" msgstr "Cronologia" #: src/bz-stats-dialog.blp:31 msgid "Installs:" msgstr "Installazioni:" #: src/bz-stats-dialog.blp:37 msgid "World" msgstr "Mondiale" #: src/bz-transaction-manager.c:1140 #, c-format msgid "Finished in %.02f seconds" msgstr "Finito in %.02f secondi" #: src/bz-transaction-view.blp:94 msgid "App Add-on" msgstr "Estensioni dell'App" #: src/bz-transaction-view.blp:119 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-view.blp:145 src/bz-transaction-view.blp:171 msgid "Install Size" msgstr "Dimensione di Installazione" #: src/bz-transaction-view.blp:199 src/bz-window.blp:355 msgid "Update" msgstr "Aggiorna" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Trasferito %s finora" #: src/bz-transaction.c:336 msgid "Pending" msgstr "In attesa" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Installa ora" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Sono disponibili aggiornamenti" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "Le seguenti applicazioni possono essere aggiornate. Vuoi installarle?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d I runtime e/o i componenti aggiuntivi possono essere aggiornati. Vuoi " "installarli?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Inoltre, verranno aggiornati %d runtime e/o componenti aggiuntivi." #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Ispeziona voci UI" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "Tutte le Azioni di Debug" #: src/bz-window.blp:98 msgid "Tasks" msgstr "Attività" #: src/bz-window.blp:154 msgid "Stop Active Tasks" msgstr "Interrompi attività attive" #: src/bz-window.blp:162 msgid "Clear History" msgstr "Cancella cronologia" #: src/bz-window.blp:178 msgid "No Tasks Yet" msgstr "Nessuna attività ancora" #: src/bz-window.blp:293 msgid "Curated" msgstr "Consigliate" #: src/bz-window.blp:306 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:481 msgid "_Donate to Bazaar ❤️" msgstr "_Dona a Bazaar ❤️" #: src/bz-window.blp:486 msgid "_Refresh Content" msgstr "_Ricarica Contenuto" #: src/bz-window.blp:493 msgid "_Preferences" msgstr "_Preferenze" #: src/bz-window.blp:498 msgid "_Keyboard Shortcuts" msgstr "_Scorciatoie da tastiera" #: src/bz-window.blp:503 msgid "_About Bazaar" msgstr "_Info su Bazaar" #: src/bz-window.blp:510 msgid "_Quit Bazaar" msgstr "_Chiude Bazaar" #: src/bz-window.blp:519 msgid "Open Bazaar Inspector" msgstr "Apri Ispettore di Bazaar" #: src/bz-window.c:819 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "La possibilità di ispezionare e installare i file bundle .flatpak locali è " "in arrivo! Nel frattempo, provate a eseguire\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "alla riga di comando." #: src/bz-window.c:941 msgid "Can't do that right now!" msgstr "Non posso farlo adesso!" #: src/bz-window.c:1070 #, c-format msgid "Install %s?" msgstr "Installare %s?" #: src/bz-window.c:1073 msgid "May install additional shared components" msgstr "È possibile installare componenti condivisi aggiuntivi" #: src/bz-window.c:1092 #, c-format msgid "Remove %s?" msgstr "Rimuovere %s?" #: src/bz-window.c:1096 #, c-format msgid "" "It will not be possible to use %s after it is uninstalled.\n" "\n" "Settings and user data will be kept." msgstr "" "Non sarà possibile usare %s dopo la disinstallazione.\n" "\n" "Le impostazioni e i dati utente verranno conservati." #: src/bz-window.c:1262 msgid "Resume Current Tasks" msgstr "Riprendi attività correnti" #: src/bz-window.c:1268 msgid "Pause Current Tasks" msgstr "Sospendi attività correnti" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u download" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Generali" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Apre la barra di ricerca" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Apri le Preferenze" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Ricarica" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Mostra o Nasconde menu delle operazioni" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Mostra scorciatoie da tastiera" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Esce" #~ msgid "Searching for Blender" #~ msgstr "Ricerca di Blender" #~ msgid "Manage Addons" #~ msgstr "Gestione delle estensioni" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "João Victor (Leal)" #~ msgstr "João Victor (Leal)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Léane GRASSER" #~ msgstr "Léane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel Mrówka (Microwave)" #~ msgstr "Marcel Mrówka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "camegone" #~ msgstr "camegone" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "Avvio recupero delle voci remote facendo riferimento a %d blocklist..." #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Non è stata fornita alcuna configurazione di contenuti consigliati per " #~ "Bazaar. Per assistenza, contattare il supporto del sistema operativo." #~ msgid "Games" #~ msgstr "Giochi" #~ msgid "Graphics" #~ msgstr "Grafica e Fotografia" #~ msgid "Office" #~ msgstr "Produttività" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "Sito del Progetto" #~ msgid "Share this application" #~ msgstr "Condividi questa applicazione" #~ msgid "Excludes shared components" #~ msgstr "Esclude componenti condivisi" #~ msgid "Source code may not be available" #~ msgstr "Il codice sorgente potrebbe non essere disponibile" #~ msgid "Click for details" #~ msgstr "Clicca per maggiori dettagli" #~ msgid "Repositories" #~ msgstr "Repository" #~ msgid "Open in browser" #~ msgstr "Apri nel browser" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "%'d Download Mensili" #~ msgid "%B %-d, %Y" #~ msgstr "%B %-d, %Y" #~ msgid "%B %-d" #~ msgstr "%B %-d" #~ msgid "Support this application" #~ msgstr "Supporta questa applicazione" #~ msgid "Run this application" #~ msgstr "Avvia questa applicazione" #~ msgid "Run" #~ msgstr "Avvia" #~ msgid "View Store Page" #~ msgstr "Mostra dettagli nello Store" #~ msgid "Git Forge Star Counts" #~ msgstr "Numero di stelle Git Forge" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "" #~ "La mancanza di un token di accesso GitHub può causare limiti di velocità" #~ msgid "Show Only Flathub Apps" #~ msgstr "Mostra solo applicazioni da Flathub" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "Attendere una breve pausa per ridurre il carico del sistema." #~ msgid "Theme" #~ msgstr "Tema" #~ msgid "Pride Rainbow Flag" #~ msgstr "Bandiera arcobaleno" #~ msgid "Bisexual Flag" #~ msgstr "Bandiera bisessuale" #~ msgid "Asexual Flag" #~ msgstr "Bandiera asessuale" #~ msgid "Share" #~ msgstr "Condividi" #~ msgid "Error Details" #~ msgstr "Dettagli dell'errore" #~ msgid "Transactions" #~ msgstr "Transazioni" #~ msgid "Loading" #~ msgstr "Caricamento" #~ msgid "Browse" #~ msgstr "Esplora" #~ msgid "App View" #~ msgstr "Vista dell'App" #~ msgid "Go Back" #~ msgstr "Vai indietro" #~ msgid "View curated applications" #~ msgstr "Visualizza applicazioni consigliate" #~ msgid "View the latest on Flathub" #~ msgstr "Visualizza le ultime novità di Flathub" #~ msgid "View installed applications" #~ msgstr "Visualizza applicazioni installate" #~ msgid "_Quit Service" #~ msgstr "_Esce dal servizio" #~ msgid "Up to date!" #~ msgstr "Aggiornato!" #~ msgid "Settings & user data will be kept" #~ msgstr "Le impostazioni e i dati utente saranno conservati" #~ msgid "Calligraphy application page" #~ msgstr "Pagina dell'applicazione Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "Grafico dei download di Blender" #~ msgid "Open this image in the default image viewer" #~ msgstr "Apri questa immagine nel visualizzatore di immagini di default" #~ msgid "Copy this image to the clipboard" #~ msgstr "Copia questa immagine negli appunti" #~ msgid "App Details" #~ msgstr "Dettagli dell'app" #~ msgid "License" #~ msgstr "Licenza" #~ msgid "Download Statistics" #~ msgstr "Statistiche di Download" #~ msgid "Show Downloads Over Time" #~ msgstr "Mostra download nel tempo" #~ msgid "Remote repo name" #~ msgstr "Nome del repository remoto" #~ msgid "Updated Size" #~ msgstr "Dimensione dell'aggiornamento" #~ msgid "Freed Space" #~ msgstr "Spazio liberato" #~ msgid "Transactions Will Appear Here" #~ msgstr "Le operazioni appariranno qui" #~ msgid "Halt the execution of transactions" #~ msgstr "Ferma l'esecuzione delle operazioni" #~ msgid "Clear all finished transactions" #~ msgstr "Cancella tutte le operazioni completate" #~ msgid "Resume the execution of transactions" #~ msgstr "Riprende l'esecuzione delle operazioni" #~ msgid "Pause the execution of transactions" #~ msgstr "Mette in pausa l'esecuzione delle operazioni" #~ msgid "Downloads Over Time" #~ msgstr "Download nel tempo" #~ msgid "Confirm Action" #~ msgstr "Conferma Azione" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Stai per disinstallare il seguente Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sei sicuro?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Stai per installare il seguente Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Sei sicuro?" #~ msgid "Apps Of The Week" #~ msgstr "Applicazioni della Settimana" #, c-format #~ msgid "Released %x" #~ msgstr "Rilasciata il %x" #~ msgid "Minimize Lower Bound" #~ msgstr "Minimizzare il limite inferiore" #~ msgid "Maximize Upper Bound" #~ msgstr "Massimizzare il limite superiore" #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "Sfoglia il codice sorgente" #~ msgid "Full Application View" #~ msgstr "Vista completa dell'applicazione" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "" #~ "Modifica i contenuti visualizzati durante la visualizzazione delle " #~ "applicazioni" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause " #~ "GitHub to eventually rate limit you." #~ msgstr "" #~ "Se non disponi di un token di accesso, attivando questa impostazione " #~ "GitHub potrebbe eventualmente limitare la tua velocità di accesso." #~ msgid "Type to filter" #~ msgstr "Digita per cercare" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Escludi risultati con licenza proprietaria" #~ msgid "Exclude results not originating from Flathub" #~ msgstr "Escludi risultati non provenienti da Flathub" #~ msgid "Advanced" #~ msgstr "Avanzate" #~ msgid "Open this link externally" #~ msgstr "Aprire questo link in un'applicazione esterna" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "Ricevute %'d voci su %'d (%.1f secondi trascorsi)" #~ msgid "Finished Tasks" #~ msgstr "Operazioni Completate" #, c-format #~ msgid "%s to install" #~ msgstr "%s da installare" #~ msgid "Open in Image Viewer" #~ msgstr "Apri nel Visualizzatore Immagini" #~ msgid "Installing" #~ msgstr "Installazione" #~ msgid "Updating" #~ msgstr "Aggiornamento" #~ msgid "Removing" #~ msgstr "Rimozione" #~ msgid "Show Animated Background" #~ msgstr "Mostra sfondo animato" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Mostrare o nascondere lo sfondo animato sulla pagina iniziale" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "Il numero di download negli ultimi 30 giorni. Clicca per vedere le " #~ "statistiche." #~ msgid "This application does not provide a donation link" #~ msgstr "Questa applicazione non fornisce un link per le donazioni" #~ msgid "Edit Permissions" #~ msgstr "Modifica le autorizzazioni" #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try looking at their project page for " #~ "more information." #~ msgstr "" #~ "“%s” non fornisce un link per le donazioni. Ciò non significa che non " #~ "puoi sostenerli! Prova a consultare la loro pagina del " #~ "progetto per ulteriori informazioni." #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try finding their project page for more information." #~ msgstr "" #~ "“%s” non fornisce un link per le donazioni. Ciò non significa che non " #~ "puoi sostenerli! Prova a cercare la pagina del loro progetto per " #~ "ulteriori informazioni." #~ msgid "How the application looks" #~ msgstr "Aspetto dell'applicazione" #~ msgid "Appearance" #~ msgstr "Aspetto" #~ msgid "Show animated background" #~ msgstr "Mostra sfondo animato" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Mantenere la descrizione breve, tra i 10 e i 35 caratteri." #~ msgid "No description" #~ msgstr "Nessuna descrizione" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Finestra principale di Bazaar nella pagina di Blender" #~ msgid "Match using regular expressions" #~ msgstr "Corrispondenza tramite espressioni regolari" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "" #~ "Nascondere il filtro e l'ordinamento con un effetto di dissolvenza " #~ "incrociata" kolunmi-bazaar-7b9c8e1/po/ja.po000066400000000000000000003436551514314607700164520ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2025 Japanese translations for bazaar package # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025 camegone msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-11 03:02+0900\n" "PO-Revision-Date: 2026-02-11 03:21+0900\n" "Last-Translator: camegone \n" "Language-Team: Japanese \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.8\n" #: data/io.github.kolunmi.Bazaar.desktop.in:3 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:4 msgid "Add, remove or update flatpak software on this computer" msgstr "flatpakのソフトウェアをこのコンピューターに追加、削除します" #: data/io.github.kolunmi.Bazaar.desktop.in:10 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" #: data/io.github.kolunmi.Bazaar.desktop.in:16 msgid "New Window" msgstr "新しいウィンドウ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "アプリケーションを検索、インストールする" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Flatpak のアプリケーションやアドオンをリモートリポジトリ (特に Flathub) から" "検索、インストールすることに特化した、Linux 用の新しいアプリストアです。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Linux のデスクトップを開発している開発者たちを支援することは重要です。Bazaar " "ではディストリビューターが管理できる「特選アプリ」タブによってユーザーの体験" "を最適化することを可能にします。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Flathub のアプリが表示されるホームページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Nucleus アプリページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "検索ページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "カテゴリーページ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:74 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:88 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:110 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:122 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:143 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:162 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:193 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:204 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:222 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:233 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:246 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:256 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:268 msgid "This release comes with the following improvements:" msgstr "このリリースには以下の改善点が含まれています:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:76 #, fuzzy msgid "Better track installed versions of apps" msgstr "インストール済みのアプリを検索" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:77 msgid "Add `enable-bulk-install` key to curated sections" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:78 msgid "Introduce the app library page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:79 #, fuzzy msgid "Add donations dialog" msgstr "年齢レーティングダイアログ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:80 msgid "Fix broken addon and runtime eol detection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:81 msgid "Add `override-eol-markings` main config string list" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:90 msgid "Improve context dialogs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:91 msgid "Fix leftover data bar being shown prematurely" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:92 msgid "Have a rotation toggle for flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:93 msgid "Add hard check to prevent removing Bazaar flatpak" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:94 #, fuzzy msgid "Improve download statistics tooltips" msgstr "ダウンロードの統計" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:95 msgid "Add read support for flatpak bundles" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:96 msgid "Fix critical output sometimes during transactions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:97 msgid "Fix error popover refusing to spawn in transaction sidebar" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:104 msgid "Minor bugfix release" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:112 msgid "Fix issue where installed page is empty on opening second window" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:113 msgid "Fix screenshot flickering in search results" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:114 msgid "Fix pride flags sometimes not showing on certain locales" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:115 msgid "Add \"Install all\" to favorites page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:124 msgid "Trash user data instead of deleting" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:125 msgid "Tweaks to permissions dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:126 msgid "Fix broken EOL filtering" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:127 msgid "Add text filter to installed page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:128 msgid "" "Add optional translations mappings for string properties in YAML configs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:129 msgid "Hide EOL apps by default" msgstr "更新終了のアプリをデフォルトで非表示" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:130 msgid "Many other minor bug fixes and improvements" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:137 msgid "" "This small release ensures the new icon is rendered correctly on KDE Plasma." msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:145 msgid "New market stall icon" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:146 msgid "Remove Flathub styling" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:147 msgid "Add horizontal versions of pride flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:148 msgid "Text selection in app descriptions can be made across paragraph breaks" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:149 msgid "Support YAML anchors and aliases in config parsing" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:150 msgid "" "Drastically reduce disk cache writes over time by skipping unchanged entries" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:151 msgid "Show background status in popover" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:152 msgid "Add app permission system" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:153 msgid "Add back release URLs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:154 msgid "Fix sync-remotes action in shortcut dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:155 msgid "Fix visual hiccups in comet animations" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:164 msgid "Flathub account support with the ability to manage bookmarks" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:165 msgid "" "Flathub bookmarks replace star count; you can add or remove bookmarks from " "app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:166 msgid "An \"Only Show Verified\" option" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:167 msgid "Exhaustive category pages for most categories" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:168 msgid "An \"Adwaita\" or \"KDE\" category shown based on desktop environment" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:169 msgid "Updated installed indicator for app tiles" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:170 msgid "3 new flag options" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:171 msgid "Fixed GNOME search provider to show the app page instead of search" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:172 msgid "" "Fixed issue where flatpakref URIs did not open when the app wasn't running " "in the background" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:173 msgid "" "Fixed issue where some proprietary apps were marked as \"Special License\"" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:174 msgid "Fixed issue where graphs did not work with touch" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:181 msgid "" "Another quick release to restore alphabetical sorting on the installed page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:187 msgid "Quick release to allow manual refresh if flathub is being flaky" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:195 msgid "" "Fix frequent disk writes; set refresh frequency to 1 day rather than 1 hour" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:196 msgid "Add \"Delete User Data\" option when uninstalling an application" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:197 msgid "Version cache to prevent incompatibility between Bazaar versions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:206 msgid "" "Reworked loading to be substantially faster after first start via async " "loading" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:207 msgid "A gaming section on the Flathub page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:208 msgid "Improved UI on mobile, especially on app pages" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:209 msgid "Verified badges next to most places where apps are shown" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:210 msgid "A popover that explains what verification and non-verification mean" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:211 msgid "An \"other apps by\" page for when a developer has more than 6 apps" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:212 msgid "Tags that show other apps with the same tag when pressed" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:213 msgid "An age rating dialog" msgstr "年齢レーティングダイアログ" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:214 msgid "Changed search filters into global content filters" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:215 msgid "5 new pride flags" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:224 msgid "" "Add \"hide-eol\" preferences option to prevent Bazaar from showing end-of-" "life applications or applications which depend on end-of-life runtimes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:225 msgid "Fix global progress bar theme sometimes not syncing with preferences" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:226 msgid "Show version next to addon name in the addons dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:235 msgid "Add \"On the go\" section and mobile cateogry" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:236 msgid "Greatly decrease reported memory usage" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:237 msgid "Rework search UI" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:238 msgid "Rework page stack navigation" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:239 msgid "Change screenshot dialog to page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:248 msgid "Fix slow/inconsistent image loading" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:249 msgid "Fix context row in full view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:258 msgid "Rework full view layout" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:259 msgid "Improve progress bar theme selection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:260 msgid "Reduce quantity and improve quality of search results" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:261 msgid "Allow the application window to fit on mobile screen sizes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:270 msgid "Add interactive screenshot dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:271 msgid "Fix empty update dialogs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:272 msgid "Greatly improve look of app description rendering" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:273 msgid "Add pending state to the global progress bar" msgstr "全体のプログレスバーに中止の状態を追加しました" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:274 msgid "Add featured apps carousel" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:281 msgid "More improvements:" msgstr "改善点:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:283 msgid "Improve design of transaction dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:284 msgid "Update remove button pulse effect and comet size curve" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:285 msgid "Reap and reload cached textures after a day" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:286 msgid "Eliminate some crashes caused by race conditions" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:287 msgid "Change preferences group to context bar in full view" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:288 msgid "Switch side panels to sidebars and use flat header bar designs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:289 msgid "Add really useful app size dialog :)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:296 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:308 msgid "Some improvements:" msgstr "改善点:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:298 msgid "" "Make the global progress bar customizable with pride flags! Check preferences" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:299 msgid "Add a new world map page to the download statistics dialog" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:300 msgid "" "Allow clicking on entries on transaction sidebar to navigate to the original " "store page" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:301 msgid "Add Alexander Vanhee to the developer credits" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:310 msgid "Overhaul download history graph; make it interactive" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:311 msgid "Smarter \"back\" functionality" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:312 msgid "Hide bottom bar more often on small window sizes" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:313 msgid "" "Make \"light-banner\" and \"dark-banner\" keys available to curated configs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:320 msgid "This release includes:" msgstr "今回のリリースに含まれる変更:" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:322 msgid "553d041 * chore(po): update Ukrainian translation (#408)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:323 msgid "711732a * Rework Version History (#407)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:324 msgid "" "d2d3771 * Calculate detailed app tiles text color based on luminance of " "background accent color (#405)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:325 msgid "3787e6e * Save window size in gsettings" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:326 msgid "18ba76c * AsyncTexture: increase HTTP timeout to 5 seconds" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:327 msgid "980f752 * SearchWidget: prevent invalid item selection" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:328 msgid "ab95593 * Add installed icons to app tiles (#404)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:329 msgid "203754b * (UI) Improve visiblility of add-on feature (#403)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:330 msgid "069ce61 * fix installed page list outline ring (#402)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:331 msgid "" "da9f7b8 * (UX) Refine the Flathub views to be denser and have less partial " "lines (#401)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:332 msgid "a6939ba * fix(po): fix Ukrainian translation (#400)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:333 msgid "35c9611 * decrease app-tile description width reqs" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:334 msgid "6098be7 * chore(po): update Polish translation (#397)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:335 msgid "2944d1e * change per section limit to 12 from 9 (#396)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:336 msgid "0b04284 * Update Japanese Translation (#394)" msgstr "" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:337 msgid "fa60f4f * Move to brand new shiny Adw.ShortcutsDialog (#395)" msgstr "" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "アドオンを管理する" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:231 msgid "Remove" msgstr "削除する" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:202 msgid "Install" msgstr "インストール" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "年齢レーティング" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "カートゥーン調の暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "カートゥーン調の暴力に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "ファンタジーの暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "ファンタジーの暴力に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "リアルな暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "リアルな暴力に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "流血表現を含む暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "流血表現に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "性的暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "性的暴力に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "アルコール" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "アルコールに関する描写の情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "麻薬" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "麻薬に関する描写の情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "タバコ" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "タバコに関する描写の情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "ヌード" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "あらゆるヌード描写に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "性的なテーマ" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "性的な要素や描写に関する情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "不適切な言葉" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "あらゆる不適切な言葉、行動に関する描写の情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "不適切なユーモア" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "不適切なユーモアに反する描写が含まれているかの情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "差別" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "あらゆる差別的な言葉に関する描写が含まれているかの情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "広告" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "あらゆる広告が含まれているかについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "ギャンブル" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "あらゆる種類のギャンブル描写が含まれているかの情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "購入" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "お金を使うことができるかについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "ユーザー同士のチャット" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "他のユーザーとチャットをする方法があるかについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "ユーザー同士のボイスチャット" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "他のユーザーと会話をする方法があるかについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "連絡先" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "SNS のユーザーネームや、e-メールアドレスを共有することについての情報はありま" "せん" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "特定可能な情報" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "ユーザーの情報を第三者と共有することに関しての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "位置情報の共有" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "他のユーザーと物理的な位置情報を共有することについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "売春" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "売春に関する描写についての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "姦通" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "姦通 (不倫) に関する描写の情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "性的特徴付けられたキャラクター" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "性的特徴付けられたキャラクターについての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "冒涜" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "" "冒涜的な描写が含まれているかの冒涜的な描写が含まれているかの情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "人の死体" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "人の死体に関する表示についての情報はありません" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "奴隷制度" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "奴隷に関する描写が含まれているかの情報はありません" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "ドラッグの描写は含まれていません" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "汚い言葉や不適切な言葉、乱暴な言葉は含まれていません" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "広告やアプリ内での取引は含まれていません" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "性的描写やヌードは含まれていません" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "無制限のチャット機能は含まれていません" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "暴力描写は含まれていません" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "ドラッグ" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "乱暴な言葉" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "お金" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "ソーシャル" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "暴力" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "全年齢" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s の年齢レーティングは不明です" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s は全ての年齢のユーザーに適している" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s は小さな子供のユーザーに適している" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s は子供のユーザーに適している" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s はティーンエイジのユーザーに適している" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s は大人のユーザーに適している" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s は %s のユーザーに適している" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "メインメニュー" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "Bazaar に寄付する❤️(_D)" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "設定(_P)" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "Flathub にログイン(_L)" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "残存しているユーザーデータを管理(_M)" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "リモートと同期(_S)" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "キーボードショートカット(_K)" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "Bazaar について(_A)" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "Bazaar を終了(_Q)" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "システムフォルダー %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "ホームのサブフォルダー %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "ホストシステムのフォルダー" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "/etc ディレクトリにあるホストシステムの設定" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "デスクトップ内のサブフォルダー %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "デスクトップのフォルダー" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "ドキュメント内のサブフォルダー %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "ドキュメントのフォルダー" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "ミュージック内のサブフォルダー %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "ミュージックのフォルダー" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "ピクチャ内のサブフォルダー %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "ピクチャのフォルダー" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "公開フォルダー内のサブフォルダー %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "公開フォルダー" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "ビデオ内のサブフォルダー %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "ビデオのフォルダー" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "テンプレート内のサブフォルダー %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "テンプレートのフォルダー" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "ユーザーキャッシュ内のサブフォルダー %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "ユーザーのキャッシュフォルダー" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "ユーザー設定内のサブフォルダー %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "ユーザー設定のフォルダー" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "ユーザーデータ内のサブフォルダー %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "ユーザーデータのフォルダー" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "ユーザーランタイム内のサブフォルダー %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "ユーザーランタイムのフォルダー" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "%s へのファイルシステム アクセス" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "不明なファイルシステムのパス" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "ダウンロードサイズ" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "インターネットからダウンロードするデータの量" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "インストール済みのサイズ" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "ディスク上のサイズ" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "ユーザーデータのサイズ" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "キャッシュや設定、その他のアプリデータ" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:178 msgid "Installed" msgstr "インストール済み" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "すべて表示" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "全ての「%s」" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "アプリケーション総数: %d" #: src/bz-application.c:674 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "" #: src/bz-application.c:675 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "" #: src/bz-application.c:703 msgid "Adam Masciola" msgstr "" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:706 msgid "translator-credits" msgstr "camegone, 2025" #: src/bz-application.c:717 msgid "Special Thanks" msgstr "スペシャルサンクス" #: src/bz-application.c:775 msgid "Logged Out Successfully!" msgstr "正常にログアウトされました!" #: src/bz-application.c:898 msgid "Performing setup..." msgstr "セットアップの実行中..." #: src/bz-application.c:981 src/bz-application.c:990 msgid "Set Up Flathub" msgstr "Flathub をセットアップする" #: src/bz-application.c:984 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub はあなたのシステムでセットアップされていません。Flathub が利用できな" "い場合、アプリを検索したりインストールすることができません。 あなたは引き続" "き Bazaar でインストール済みのアプリを検索したり削除することができます。" #: src/bz-application.c:989 msgid "Later" msgstr "後で" #: src/bz-application.c:1399 src/bz-application.c:3116 msgid "Synchronizing..." msgstr "同期中..." #: src/bz-application.c:1546 src/bz-application.c:3112 #, c-format msgid "Receiving %d entries..." msgstr "%d 件のエントリを受信中..." #: src/bz-application.c:1551 msgid "Checking for updates" msgstr "更新を確認中" #: src/bz-application.c:3118 msgid "Indexing Data..." msgstr "データをインデックス中..." #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub ページ" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "プロジェクトのウェブサイト" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "バグトラッカー" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "よくある質問" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "ヘルプ" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "寄付" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "翻訳" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "連絡先" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "ソースコード" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "貢献する" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "空" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "特選アプリなし" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "特選アプリの情報がこのシステム向けに提供されていません。ですが Flathub のアプ" "リを閲覧することはできます" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Flathub を閲覧" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "オフライン" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "ブラウザー" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "開発者に関する情報がありません。" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "このアプリ ID、%s の所有権は検証されておらず、コミュニティのパッケージである" "可能性があります。" #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "このアプリ ID、%s の所有権は Flathub のチームが手動で検証済みです。" #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "このアプリ ID、%1$s の所有権は %3$s に所属する %2$s によって検" "証済みです。" #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "このアプリ ID、%1$s の所有権は、%2$s を使って検証済みです。" #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "このアプリ ID、%s の所有権は検証済みです。" #: src/bz-donations-dialog.blp:47 msgid "View the Release Page" msgstr "リリースページを表示" #: src/bz-donations-dialog.blp:69 msgid "This Bazaar Release Was Made Possible By Users Like You!" msgstr "" "この Bazaar の新バージョンはあなたのようなユーザーに支えられて実現しました!" #: src/bz-donations-dialog.blp:77 msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "私は Bazaar の開発が好きですが、それは私一人だけではできません。もしあなたが" "将来的な開発の継続を支援したいなら、ko-fi でプロジェクトを支援することを検討" "してください:" #: src/bz-donations-dialog.blp:87 msgid "Donate to Bazaar" msgstr "Bazaar に寄付する" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:156 #, c-format msgid "What's New in Version %s?" msgstr "バージョン %s での変更点は何?" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "インストールの選択" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "あなたはこのアプリの複数のバージョンをインストールしています。どれを選択して" "続けますか?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:201 #: src/bz-transaction-dialog.c:230 src/bz-transaction-dialog.c:275 #: src/bz-transaction-dialog.c:578 msgid "Cancel" msgstr "キャンセル" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "このユーザーのみ" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "このユーザー" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "全てのユーザー" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "エラーが発生しました" #: src/bz-error.c:89 msgid "Close" msgstr "閉じる" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "コピーして閉じる" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Flathub にログインしてお気に入りを管理する" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "ログイン" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "お気に入りされた数" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "アンインストール" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "このアプリケーションを支援する" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "お気に入りから削除" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "お気に入り" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 msgid "Open App Library" msgstr "アプリ ライブラリを開く" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:579 msgid "Install All" msgstr "全てインストール" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "読み込み中" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "お気に入りがありません" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "あなたがお気に入りマークをつけたアプリがここに表示されます" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "前へ" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "次へ" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "今日のアプリ" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "編集" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "ミキサー" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "音楽" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "プレーヤー" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "レコーダー" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "シーケンサー" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "チューナー" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "テレビ" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "エミュレーター" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "アクション" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "アクション" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "アーケード" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "ブロック" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "ボードゲーム" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "カードゲーム" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "子供向け" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "論理" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "ロールプレイング" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "射撃系" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "シミュレーション" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "スポーツ" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "戦略" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "映像や音楽" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "メディア" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "映像や音楽をもっと見る" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "開発ツール" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "開発" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "開発ツールをもっと見る" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "教育" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "学ぶ" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "教育アプリをもっと見る" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "ゲーム" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "遊ぶ" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "ゲームをもっと見る" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "画像や写真" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "創作する" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "画像や写真関連のアプリをもっと見る" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "ネットワーク" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "インターネット" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "ネットワーク関連のアプリをもっと見る" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "生産性向上" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "働く" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "生産性向上アプリをもっと見る" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "科学" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "科学アプリをもっと見る" #: src/bz-flathub-category.c:128 msgid "System" msgstr "システム" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "システムアプリをもっと見る" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "便利ツール" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "ツール" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "便利ツールをもっと見る" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "話題のアプリ" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "話題のアプリをもっと見る" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "人気のアプリ" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "人気アプリをもっと見る" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "最近追加されたアプリ" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "新しいアプリ" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "新着アプリをもっと見る" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "最近更新されたアプリ" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "更新されたアプリ" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "更新されたものをもっと見る" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "モバイル" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "モバイル対応アプリをもっと見る" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Adwaita をもっと見る" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "KDE アプリ" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "KDE のアプリをもっと見る" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub が見つかりません" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "このコンピューター上のどの flatpak にも Flathub リモートレポジトリが見つかり" "ませんでした" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub がエラーを返しました" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Flathub への接続を再試行" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub が利用不可" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Flathub に接続できませんでした。アプリの管理と検索はすることができます。" #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "アプリ検索" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "どこでも一緒" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Linux フォンやタブレット向けのアプリ" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "モバイル対応アプリをもっと見る" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "ゲームやお気に入りのタイトルを遊ぶためのアプリ" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "ゲームをもっと見る" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "結果無し" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "別の語句で検索してみてください" #: src/bz-full-view.blp:59 msgid "Content" msgstr "内容" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "" ".flatpak 形式のバンドルをインストールする機能はまだサポートされていません" #: src/bz-full-view.blp:210 msgid "Support" msgstr "支援する" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "開く" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "アプリケーションをダウンロードしてインストールする" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "このアプリケーションをアンインストール" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "ほかのバージョンをインストール" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "月あたりのダウンロード数" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "アップデートの提供終了" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "このアプリは更新やセキュリティ修正の提供が終了したランタイムを使用していま" "す。 使用することが安全でなくなる可能性があります。" #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "データを捨てる" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "タグ:" #: src/bz-full-view.c:220 msgid "---" msgstr "" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "" #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "過去1ヶ月の間に %d ダウンロード" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "利用不能" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "ダウンロード" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "サイズの情報がありません" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "ダウンロードサイズ: %s" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "全年齢" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "年齢レーティングの情報がありません" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "全ての年齢のユーザーに適している" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "%d 歳以上のユーザーに適している" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "不明" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "%s ライセンスのもと公開されているフリーソフト" #: src/bz-full-view.c:403 msgid "Free software" msgstr "フリーのソフトウェア" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "プロプライエタリ ソフトウェア" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "特別なライセンス: %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "フリー" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "プロプライエタリ" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "特別なライセンス" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "幅広いデバイスに対応" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "デスクトップのみ" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "デスクトップ、タブレット、携帯電話で動きます" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "モバイル端末では動かない可能性があります" #: src/bz-full-view.c:472 msgid "No URL" msgstr "URL がありません" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "このアプリケーションはフリーのOSSライセンスで公開されており、安全のためにソー" "スコードを確認することができます。" #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "このアプリケーションはプロプライエタリなライセンスで公開されており、ソース" "コードはプライベートで開発されているため、独立した第三者による検査を受けるこ" "とができません。" #: src/bz-full-view.c:498 msgid "More Apps" msgstr "アプリをもっと見る" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "%s のアプリをもっと見る" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "この開発者の別のアプリ" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "%s の別のアプリ" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s はインストールされていませんが、%s のデータは残存しています。" #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "安全" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "低いリスク" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "中間のリスク" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "高いリスク" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "他のアプリ" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "アプリケーション総数: %d" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "折り畳む" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "もっと見る" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "ハードウェアのサポート" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "キーボードのサポート" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "キーボードの使用が必須" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "キーボードの使用を推奨" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "キーボードが使用可能" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "キーボードのサポート状況が不明" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "マウスのサポート" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "マウス等のポインティングデバイスの使用が必須" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "マウス等のポインティングデバイスの使用を推奨" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "マウス等のポインティングデバイスが使用可能" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "マウス等のポインティングデバイスのサポート状況が不明" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "タッチスクリーンのサポート" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "タッチスクリーンの使用が必須" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "タッチスクリーンの使用を推奨" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "タッチスクリーンが使用可能" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "タッチスクリーンのサポート状況が不明" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "モバイル端末のサポート" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "モバイル端末で使用可能" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "モバイル端末では動かない可能性があります" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "デスクトップのサポート" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "大きな画面で快適に動作します" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s は特定のデバイスが搭載された端末で快適に動作します" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s はほとんどのデバイスで動作します" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "更新の提供終了" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "インストール済みのアプリを検索" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "アプリケーションがありません" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 msgid "Library" msgstr "ライブラリ" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "実行待ちの更新" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "ダウンロード一覧" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "最近アンインストールされたアプリ" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "終了したタスクを削除" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "インストール済みのアプリ" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "インストール済みのアプリ一覧には、「%s」という単語は見つかりませんでした" #: src/bz-library-page.c:165 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u 件の利用可能なアップデート" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "参加する" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "不明なライセンス" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "コミュニティーによって作られました" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "このアプリは国際的なコミュニティによってオープンに開発されています。\n" "\n" "あなたは開発に参加して機能改善の手助けができます。" #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "このアプリのライセンスは不明です" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "このアプリは国際的なコミュニティによってオープンに開発されていて、%s ライセン" "スのもとで公開されています。\n" "\n" "あなたは開発に参加して機能改善の手助けができます。" #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "このアプリはオープンソースとして開発されていないため、開発者しかどんな処理を" "行っているかを知ることができません。これによってセキュリティ上の脅威を発見す" "ることが難しくなったり、外部の監視無しに悪意のあるコードに変更される可能性が" "あります。\n" "\n" "あなたはこのアプリに対しての貢献を行うことができないかもしれません。" #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "このアプリは特別なライセンス、%s の下開発されています。\n" "あなたはこのアプリに対して貢献を行うことができないかもしれません。" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Flathub に接続する" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "不明なエラーが発生しました" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "あなたの Flathub アカウントを Bazzar へ接続して、お気に入りのアプリを管理しよ" "う。" #: src/bz-login-page.blp:108 msgid "Finish" msgstr "完了" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "ようこそ、%s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "設定" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "従量課金のネットワークに接続しています — ストア情報の自動取得は一時停止されて" "います" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "手動で同期する" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "コンテンツフィルター" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "フリーのソフトウェアのみ表示" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "プロプライエタリのソフトウェアを検索結果から除外する" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Flathub からの検索結果のみ表示" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "検索結果を Flathub で利用可能なアプリのみに限定する" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "検証済みの検索結果のみ表示" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Flathub で検証されていないアプリケーションを非表示にする" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "更新終了のアプリを非表示" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "開発者によるサポートが終了したアプリを非表示にする" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "検索" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "検索の遅延" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "入力から検索までをわずかに遅延させることで検索のパフォーマンスを向上させる" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "プログレスバー" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "プログレスバーを好きなテーマで彩りましょう!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "垂直のストライプ" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "旗の色を左から右へと表示します" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "アクセントカラー" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "プライドカラー" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "レズビアン プライド カラー" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "男性 ホモセクシャル プライド カラー" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "トランスジェンダー プライド カラー" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "ノンバイナリー プライド カラー" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "バイセクシュアル プライド カラー" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "アセクシュアル プライド カラー" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "パンセクシュアル プライド カラー" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "アロマンティック プライド カラー" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "ジェンダーフルイド プライド カラー" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "ポリセクシュアル プライド カラー" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "オムニセクシュアル プライド カラー" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "アロエース プライド カラー" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "アジェンダー プライド カラー" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "ジェンダークィア プライド カラー" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "インターセックス プライド カラー" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "デミジェンダー プライド カラー" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "バイロマンティック プライド カラー" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "ディスアビリティー プライド カラー" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "フェムボーイ プライドカラー" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "ニュートロワ プライド カラー" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:150 msgid "Version History" msgstr "バージョン履歴" #: src/bz-releases-list.c:168 #, c-format msgid "Version %s" msgstr "バージョン %s" #: src/bz-releases-list.c:220 msgid "No details for this release" msgstr "このリリースの詳細情報がありません" #: src/bz-releases-list.c:232 msgid "Get More Information" msgstr "詳細情報を確認する" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "入手" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "不明な権限" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "このアプリの動作に必要な権限が許可されていません。" #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "使用する権限なし" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "アプリは完全にサンドボックス化 (隔離) されています" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "ネットワーク アクセス" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "インターネットに接続する" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "ネットワーク アクセスなし" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "インターネットに接続しない" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "ユーザーデバイスへのアクセス" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "ウェブカメラやゲーム用コントローラーのようなデバイスにアクセスできます" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "ユーザーデバイスへのアクセスなし" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "ウェブカメラやゲーム用コントローラーのようなデバイスにアクセスできません" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "入力デバイスへのアクセス" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "入力デバイスへアクセスできます" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "マイクへのアクセスと音声再生" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "マイクの入力へのアクセスと音声再生を許可なく行えます" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "システムデバイスへのアクセス" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "特権を要求されるシステムデバイスにアクセスすることができます" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "画面の内容へのアクセス" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "画面や他のウィンドウに表示されている内容へのアクセスができます" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "古いウィンドウシステム" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "常に古いウィンドウシステム (X11) を使用します" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "任意の権限" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "任意のあらゆる権限を取得することができます" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "ユーザー設定" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "ユーザーの設定へのアクセスと変更ができます" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "ファイルシステム全体の読み書きアクセス" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "ファイルシステム上全てのファイルの読み書きができます" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "ホームフォルダーの読み書きアクセス" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "あなたのホームディレクトリ内の全てのデータを読み書きできます" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "ファイルシステム全体の読み込みアクセス" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "ファイルシステム上全てのデータを読み込みできます" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "ホームフォルダーの読み込みアクセス" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "あなたのホームディレクトリ内の全てのデータの読み込みができます" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "ダウンロードフォルダーの読み書きアクセス" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "あなたのダウンロード ディレクトリ内の全てのデータを読み書きできます" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "ダウンロードフォルダーの読み込みアクセス" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "あなたのダウンロード ディレクトリ内の全てのデータを読みこみできます" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "このディレクトリ内の全てのデータを読み書きできます" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "このディレクトリ内の全てのデータの読み込みができます" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "ファイルシステムへのアクセスなし" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "ファイルシステムへのアクセスは全く行いません" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "システムサービスを使用" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Portal 以外のシステムサービスへデータをリクエストできます" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "セッション サービスを使用" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Portal 以外のセッション サービスへデータをリクエストできます" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "サービスへのアクセスなし" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "" "Portal 以外のシステムやセッションのサービスへのアクセスを全く行いません" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "検証済みアプリ開発者" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "このアプリの開発者はなりすましてはないことが確認されています" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "プロプライエタリなコード" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "ソースコードが公開されていないため、個別に監査することができず、脆弱である可" "能性があります" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "検査可能なコード" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "このアプリのソースコードは公開されており、自主的に検査可能なため、安全な可能" "性が高いです" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "システムサービス %s を使用" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "セッション サービス %s を使用" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "サービス %s を使用" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Portal 以外のサービスを見ることができます" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Portal 以外のサービスと通信できます" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Portal 以外のサービスを保有できます" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "グローバル メニュー統合" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "グローバルなメニューバーに追加のメニューを表示できます" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "KDE 設定統合" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "KDE デスクトップの設定が変更されたときに検知できます" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "KDE のグローバル設定" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "KDE デスクトップの設定 (フォントやカラーなど) を読み込むことができます" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "シークレット ストレージ サービス" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "スステムのキーリングを使用して、パスワードを保存または引き出すことができます" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "デスクトップ通知サービス" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "デスクトップに通知を送信できます" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "システムトレイ統合" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "システムトレイにアイコンを表示できます" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "KDE コネクト統合" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "KDE コネクトでペアリングされたデバイスと通信することができます" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "安全性" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "詳細" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "ライセンス" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "アプリ ID" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "このアプリは古いバージョンのソフトウェア開発キット (SDK) を使用しており、バグ" "や脆弱性などの修正が提供されないままになっている可能性があります。" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s は安全です" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s は危険な権限を使用していません" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s はおそらく安全です" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s はおそらく安全ではありません" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s は安全ではありません" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "スクリーンショット" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "前のスクリーンショット" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "次のスクリーンショット" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "画像をコピー" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "表示をリセット" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "ズームアウト" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "ズームイン" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "スクリーンショット カルーセル" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "スクリーンショットビューアを開く" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "アプリ、ゲーム、ソフトウェアを検索" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "カテゴリーが利用不能です" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "画面上側にある検索バーを使用してアプリを検索する。" #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "アプリケーションがありません" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "「%s」という検索語句に合致するアプリは、Flathub にありませんでした" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "コピーしました!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "リンクをコピーする" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "リンクを開く" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "時系列" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "インストール数:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "地域別" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "総ダウンロード回数: %.2fM 回" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "総ダウンロード回数: %.2fK 回" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "総ダウンロード回数: %'d 回" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "検索結果無し" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "\"%s\" タグのついたアプリ" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "検索に失敗しました" #: src/bz-transaction-dialog.c:155 msgid "Keep Data" msgstr "データを保持" #: src/bz-transaction-dialog.c:156 msgid "Allow restoring settings and content" msgstr "設定やコンテンツをまた使うことのできるように保持する" #: src/bz-transaction-dialog.c:165 msgid "Delete Data" msgstr "データを削除" #: src/bz-transaction-dialog.c:166 msgid "Permanently remove app data to save space" msgstr "アプリのデータを永久に削除して容量を確保する" #: src/bz-transaction-dialog.c:191 #, c-format msgid "Install %s?" msgstr "%s をインストールしますか?" #: src/bz-transaction-dialog.c:196 msgid "" "Select which version to install. May install additional shared components" msgstr "" "どのバージョンをインストールするかを選択してください。追加の共有のコンポーネ" "ントがインストールされることがあります" #: src/bz-transaction-dialog.c:198 msgid "May install additional shared components" msgstr "追加の共有コンポーネントがインストールされることがあります" #: src/bz-transaction-dialog.c:219 #, c-format msgid "Remove %s?" msgstr "%s を削除しますか?" #: src/bz-transaction-dialog.c:222 msgid "Select which version to remove." msgstr "削除するバージョンを選択してください。" #: src/bz-transaction-dialog.c:224 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "%s をアンインストールした後は、利用できなくなります。" #: src/bz-transaction-dialog.c:247 #, c-format msgid "“%s” is High Risk" msgstr "「%s」は高リスクです" #: src/bz-transaction-dialog.c:251 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "このアプリはあなたのシステムに完全なアクセスが可能であり、これはあなたの" "ファイル、ブラウザの閲覧履歴、保存したパスワード にアクセス可能なうえ、イ" "ンターネットに接続して第三者へあなたのデータを送信可能であることを意味しま" "す。\n" "\n" "このアプリはプロプライエタリであり、取得した権限で何を行っているかを検査する" "ことができません。" #: src/bz-transaction-dialog.c:260 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "このアプリは古い X11 ウィンドウシステムを使用しており、全てのキーストロー" "クを記録したり、スクリーンショットを撮ったり、他のアプリケーションを監視する" "ことができます。さらに、インターネットに接続可能なため、第三者にあなたの" "データを送信可能なことを意味します。\n" "\n" "このアプリはプロプライエタリであり、取得した権限で何を行っているかを検査する" "ことができません。" #: src/bz-transaction-dialog.c:276 msgid "Install Anyway" msgstr "それでもインストールする" #: src/bz-transaction-dialog.c:549 msgid "All apps are already installed" msgstr "全てのアプリがすでにインストール済みです" #: src/bz-transaction-dialog.c:551 msgid "OK" msgstr "OK" #: src/bz-transaction-dialog.c:567 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "%u 個のアプリをインストールしますか?" #: src/bz-transaction-dialog.c:575 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "以下のものがインストールされます。追加の共有コンポーネントがインストールされ" "ることがあります" #: src/bz-transaction-dialog.c:576 #, c-format msgid "%d addons will be installed." msgstr "%d 個のアドオンがインストールされます。" #: src/bz-transaction-dialog.c:577 msgid "Additionally, addons will be installed." msgstr "追加で、いくつかのアドオンがインストールされます。" #: src/bz-transaction-manager.c:1251 #, c-format msgid "Finished in %.02f seconds" msgstr "%.02f 秒で完了しました" #: src/bz-transaction-tile.blp:125 msgid "App Add-on" msgstr "アプリ アドオン" #: src/bz-transaction-tile.blp:154 msgid "Runtime" msgstr "ランタイム" #: src/bz-transaction-tile.blp:178 msgid "In Queue" msgstr "順番待ち" #: src/bz-transaction-tile.blp:202 msgid "Done" msgstr "完了" #: src/bz-transaction-tile.blp:243 msgid "Open App" msgstr "アプリを開く" #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s を解放しました" #: src/bz-transaction.c:342 msgid "Pending" msgstr "一時停止中" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "全て更新" #: src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "更新" #: src/bz-updates-card.c:293 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u 件のランタイムのアップデート" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "残存するユーザーデータを管理" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "ユーザーデータが見つかりませんでした" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "ユーザーデータ" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "%s のユーザーデータをゴミ箱に移す" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "ユーザーデータをゴミ箱に移動" #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "ストアの内容を再読み込み中" #: src/bz-window.blp:153 msgid "Curated" msgstr "特選アプリ" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "バックグラウンドタスクがありません!" #: src/bz-window.blp:325 msgid "You are running a new version of Bazaar!" msgstr "Bazaar の新しいバージョンを実行中です!" #: src/bz-window.blp:326 msgid "See What's New" msgstr "変更点を見る" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "ネットワークに接続されていますが、キャッシュされた Flathub を表示しています" #: src/bz-window.blp:449 msgid "Log Out" msgstr "ログアウト" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "Bazaar を使って Bazaar を削除することはできません!" #: src/bz-window.c:891 src/bz-window.c:925 msgid "Can't do that right now!" msgstr "今すぐにはできません!" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "ダウンロード" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "一般" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "検索ダイアログを表示" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "設定を開く" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "リモートと同期" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Open Library" msgstr "ライブラリを開く" #: src/gtk/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "ショートカットを表示" #: src/gtk/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Quit" msgstr "アプリを閉じる" #~ msgid "_Refresh Content" #~ msgstr "ストアの内容を再読み込み(_R)" #~ msgid "Toggle transaction sidebar" #~ msgstr "ダウンロードのサイドバーを表示/非表示" #~ msgid "Install Size" #~ msgstr "インストールサイズ" #~ msgid "Ongoing" #~ msgstr "進行中" #~ msgid "Finished" #~ msgstr "完了済み" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "%s 転送済み" #~ msgid "Tasks" #~ msgstr "タスク" #~ msgid "Stop Active Tasks" #~ msgstr "現在進行中のタスクを停止" #~ msgid "Clear History" #~ msgstr "履歴を削除" #~ msgid "No Tasks Yet" #~ msgstr "タスクがありません" #, c-format #~ msgid "%d Update Available" #~ msgid_plural "%d Updates Available" #~ msgstr[0] "%d 件の更新が利用可能です" #~ msgid "Updates Are Available" #~ msgstr "更新が利用可能です" #~ msgid "" #~ "The following applications are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "以下のアプリケーションが更新の対象になっています。インストールしてもよろし" #~ "いですか?" #, c-format #~ msgid "" #~ "%d runtimes and/or addons are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "%d 個のランタイムやアドオンが更新の対象になっています。インストールしても" #~ "よろしいですか?" #, c-format #~ msgid "Additionally, %d runtimes and/or addons will be updated." #~ msgstr "さらに %d 個のランタイムや、アドオンが更新されます。" #~ msgid "Update Now" #~ msgstr "今すぐ更新" #~ msgid "Resume Current Tasks" #~ msgstr "中止中のタスクを再開" #~ msgid "Pause Current Tasks" #~ msgstr "現在のタスクを一時停止" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "ダウンロードマネージャーの表示/非表示" #~ msgid "Pride Colors (Horizontal)" #~ msgstr "プライドカラー (水平)" #~ msgid "Lesbian Pride Colors (Horizontal)" #~ msgstr "レズビアン プライド カラー (水平)" #~ msgid "Male Homosexual Pride Colors (Horizontal)" #~ msgstr "男性 ホモセクシャル プライド カラー (水平)" #~ msgid "Transgender Pride Colors (Horizontal)" #~ msgstr "トランスジェンダー プライド カラー (水平)" #~ msgid "Nonbinary Pride Colors (Horizontal)" #~ msgstr "ノンバイナリー プライド カラー (水平)" #~ msgid "Bisexual Pride Colors (Horizontal)" #~ msgstr "バイセクシュアル プライド カラー (水平)" #~ msgid "Asexual Pride Colors (Horizontal)" #~ msgstr "アセクシュアル プライド カラー (水平)" #~ msgid "Pansexual Pride Colors (Horizontal)" #~ msgstr "パンセクシュアル プライド カラー (水平)" #~ msgid "Aromantic Pride Colors (Horizontal)" #~ msgstr "アロマンティック プライド カラー (水平)" #~ msgid "Genderfluid Pride Colors (Horizontal)" #~ msgstr "ジェンダーフルイド プライド カラー (水平)" #~ msgid "Polysexual Pride Colors (Horizontal)" #~ msgstr "ポリセクシュアル プライド カラー (水平)" #~ msgid "Omnisexual Pride Colors (Horizontal)" #~ msgstr "オムニセクシュアル プライド カラー (水平)" #~ msgid "Aroace Pride Colors (Horizontal)" #~ msgstr "アロエース プライド カラー (水平)" #~ msgid "Agender Pride Colors (Horizontal)" #~ msgstr "アジェンダー プライド カラー (水平)" #~ msgid "Genderqueer Pride Colors (Horizontal)" #~ msgstr "ジェンダークィア プライド カラー (水平)" #~ msgid "Intersex Pride Colors (Horizontal)" #~ msgstr "インターセックス プライド カラー (水平)" #~ msgid "Demigender Pride Colors (Horizontal)" #~ msgstr "デミジェンダー プライド カラー (水平)" #~ msgid "Biromantic Pride Colors (Horizontal)" #~ msgstr "バイロマンティック プライド カラー (水平)" #~ msgid "Disability Pride Colors (Horizontal)" #~ msgstr "ディスアビリティー プライド カラー (水平)" #~ msgid "Femboy Pride Colors (Horizontal)" #~ msgstr "フェムボーイ プライドカラー (水平)" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "ローカルの flatpak バンドルファイルを表示、インストールする機能は近日追加" #~ "予定です! しばらくの間は代わりに、\n" #~ "\n" #~ "flatpak install --bundle バンドルファイル名.flatpak\n" #~ "\n" #~ "をコマンドラインで実行してください。" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u ダウンロード" #~ msgid "Hide EOL Entries" #~ msgstr "更新終了のエントリを非表示" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "更新が終了したエントリや、それに依存しているエントリを非表示にする" #~ msgid "Only Show Free Software" #~ msgstr "フリーのソフトウェアのみ表示" #~ msgid "Hide proprietary software" #~ msgstr "プロプライエタリ ソフトウェアを非表示" #~ msgid "Show Only Flathub Content" #~ msgstr "Flathub の内容のみ表示" #~ msgid "Debounce Search Inputs" #~ msgstr "検索の遅延" #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "" #~ "入力してから検索されるまでに遅延を設け、即座に結果が表示されないようにする" #~ msgid "Global Progress Bar Theme" #~ msgstr "全体のプログレスバーのテーマ" #~ msgid "Describes the look of the global progress bar" #~ msgstr "全体のプログレスバーの見た目を変更する" #~ msgid "Saved Window Dimensions" #~ msgstr "保存したウィンドウサイズ" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "次回 Bazaar のウィンドウを表示する時に使用されるウィンドウの寸法" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s は幼児のユーザーに適している" #~ msgid "Of the size of human DNA" #~ msgstr "人間のDNAのサイズに対する割合" #~ msgid "3 billion base pairs" #~ msgstr "30億塩基対" #~ msgid "Of the Linux Kernel" #~ msgstr "linuxのカーネルに対する割合" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "アポロ11号のガイダンスコンピュータに対する割合" #~ msgid "Total ROM and RAM" #~ msgstr "ROMとRAMの合計" #~ msgid "Of the original Super Mario Bros" #~ msgstr "初代スーパーマリオブラザーズに対する割合" #~ msgid "On the NES" #~ msgstr "ファミコン版" #~ msgid "Of the size of Wikipedia" #~ msgstr "Wikipedia のサイズに対する割合" #~ msgid "Without any media" #~ msgstr "画像や音声などを除いたサイズ" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "この機能は現在無効になっています。アプリの権限を管理するためには、" #~ "Flatseal をインストールすることを推奨します。" #~ msgid "Entry Inspector" #~ msgstr "エントリのインスペクター" #~ msgid "Serialize" #~ msgstr "シリアライズ" #~ msgid "Convert to JSON" #~ msgstr "JSON に変換する" #~ msgid "More Mobile apps" #~ msgstr "モバイル対応アプリをもっと見る" #~ msgid "Size" #~ msgstr "サイズ" #~ msgid "Bazaar Inspector" #~ msgstr "Bazaar インスペクター" #~ msgid "Enable Global Debug Mode" #~ msgstr "全域のデバッグモードを有効化" #~ msgid "Active Blocklists" #~ msgstr "有効なブラックリスト" #~ msgid "Active Curated-Configs" #~ msgstr "有効な特選アプリの設定" #~ msgid "All Entry Groups" #~ msgstr "全てのエントリグループ" #~ msgid "Filter..." #~ msgstr "検索..." #~ msgid "No Flatpaks Installed" #~ msgstr "Flatpak がインストールされていません" #~ msgid "Remove User Data" #~ msgstr "ユーザーデータを削除" #~ msgid "Inspect UI Entry" #~ msgstr "UI エントリを検査" #~ msgid "All Debug Actions" #~ msgstr "すべてのデバッグオプション" #~ msgid "Open Bazaar Inspector" #~ msgstr "Bazaar インスペクターを開く" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "再読み込み" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Git Forge のスター数を表示" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "「スターの数」をプロジェクトの詳細画面で表示するかどうか" #~ msgid "Repository Star Count" #~ msgstr "リポジトリーのスター数" #~ msgid "Application Details" #~ msgstr "アプリケーションの詳細" #~ msgid "Display Star Count" #~ msgstr "スターの数を表示" #~ msgid "Show the star count of an application's source code repository" #~ msgstr "アプリのソースコードがあるリポジトリのスターの数を表示する" #~ msgid "" #~ "Bazaar can fetch and display the star count from an application's source " #~ "code repository on a remote Git forge. \n" #~ " For projects on GitHub, rate limits may cause them not to appear." #~ msgstr "" #~ "Bazzarは Git forge のリモートにあるアプリケーションのリポジトリに付けられ" #~ "たスターの数を取得して、表示できます。\n" #~ "GitHub のプロジェクトでは、レート制限により表示されないことがあります。" #~ msgid "Mobile Apps" #~ msgstr "モバイル対応アプリ" #~ msgid "Verified by the original developers" #~ msgstr "オリジナルの開発者によって検証済みです" #~ msgid "Hide proprietary software when searching" #~ msgstr "検索結果からプロプライエタリのソフトウェアを除外します" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "検索結果を Flathub で利用可能なアプリのみに限定する" #~ msgid "Constructing Flatpak instance..." #~ msgstr "Flatpak のインスタンスを生成中..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "Flatpak のインスタンスを再利用中..." #~ msgid "Flathub is not registered on this system" #~ msgstr "Flathub がシステムに登録されていません" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "Flathub をリモートのリポジトリに追加しますか? 拒否した場合、Flathub ページ" #~ "は利用できません。これは、あとから変更可能です。" #~ msgid "Add Flathub" #~ msgstr "Flathub を追加" #, c-format #~ msgid "Identifying installed entries..." #~ msgstr "インストール済みのエントリを特定中..." #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "%d 件のブロックリストを参照しながらリモートのエントリの取得開始中..." #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d / %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "バックグラウンドのインデックス処理が終了するのを待っています..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "%0.2f で初期化を完了しました" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Bazaar が読み込める特選アプリの情報がありませんでした。あなたが使用してい" #~ "る OS のサポートチャンネルに連絡してください。" #~ msgid "More actions" #~ msgstr "詳細コマンド" #~ msgid "Run this application" #~ msgstr "このアプリケーションを実行する" #~ msgid "Run" #~ msgstr "実行" #~ msgid "Git Forge Star Counts" #~ msgstr "Git Forge のスター数" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "" #~ "GitHub のアクセストークン無しではレート制限の原因となる可能性があります" #~ msgid "Show Only Flathub Apps" #~ msgstr "Flathub のアプリのみ表示" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "システムの負荷を減らすため、少しの待ち時間を追加する" #~ msgid "Go Home" #~ msgstr "ホームに戻る" #~ msgid "Browse" #~ msgstr "ブラウズ" #~ msgid "App View" #~ msgstr "アプリ表示" #~ msgid "Go Back" #~ msgstr "戻る" #~ msgid "View curated applications" #~ msgstr "厳選されたアプリケーションを表示する" #~ msgid "View the latest on Flathub" #~ msgstr "Flathub の最新のアプリを表示する" #~ msgid "Settings & user data will be kept" #~ msgstr "設定とユーザーデータは保持されます" #~ msgid "Pride Rainbow Flag" #~ msgstr "プライドレインボー フラッグ" #~ msgid "Bisexual Flag" #~ msgstr "バイセクシュアル フラッグ" #~ msgid "Asexual Flag" #~ msgstr "アセクシュアル フラッグ" #~ msgid "_Quit Service" #~ msgstr "_サービスの停止" #~ msgid "Games" #~ msgstr "ゲーム" #~ msgid "Graphics" #~ msgstr "グラフィック" #~ msgid "Office" #~ msgstr "オフィス" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "ホームページ" #~ msgid "Share this application" #~ msgstr "このアプリケーションを共有する" #~ msgid "Excludes shared components" #~ msgstr "共有のコンポーネントを除く" #~ msgid "Source code may not be available" #~ msgstr "ソースコードを入手できないことがあります" #~ msgid "Click for details" #~ msgstr "クリックで詳細を開く" #~ msgid "Repositories" #~ msgstr "リポジトリー" #~ msgid "Open in browser" #~ msgstr "ブラウザーで開く" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "月間 %'d ダウンロード" #~ msgid "Theme" #~ msgstr "テーマ" #~ msgid "Share" #~ msgstr "共有" #~ msgid "Manage Addons" #~ msgstr "アドオンを管理する" #~ msgid "%B %-d, %Y" #~ msgstr "%Y/%0m/%0d" #~ msgid "%B %-d" #~ msgstr "%0m/%0d" #~ msgid "Transactions" #~ msgstr "ファイル操作" #~ msgid "Up to date!" #~ msgstr "最新です!" #~ msgid "Calligraphy application page" #~ msgstr "カリグラフィーのアプリケーションページ" #~ msgid "Download graph for Blender" #~ msgstr "Blender のグラフをダウンロード" #~ msgid "Open this image in the default image viewer" #~ msgstr "この画像をデフォルトの画像ビューアーで開く" #~ msgid "Copy this image to the clipboard" #~ msgstr "この画像をクリップボードにコピーする" #~ msgid "Show Downloads Over Time" #~ msgstr "過去の期間に対するダウンロード数のグラフを表示する" #~ msgid "Remote repo name" #~ msgstr "リモートのリポジトリーの名前" #~ msgid "Updated Size" #~ msgstr "更新後のサイズ" #~ msgid "Freed Space" #~ msgstr "解放された容量" #~ msgid "Transactions Will Appear Here" #~ msgstr "ダウンロードはここに表示されます" #~ msgid "Halt the execution of transactions" #~ msgstr "現在進行中のダウンロードを停止" #~ msgid "Resume the execution of transactions" #~ msgstr "ダウンロードを再開する" #~ msgid "Pause the execution of transactions" #~ msgstr "実行中のダウンロードを一時停止する" #~ msgid "Downloads Over Time" #~ msgstr "ダウンロード数の推移" #~ msgid "Minimize Lower Bound" #~ msgstr "グラフの下限を最小化" #~ msgid "Maximize Upper Bound" #~ msgstr "グラフの上限を最大化" #~ msgid "Confirm Action" #~ msgstr "操作の確認" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "あなたは以下の Flatpak をアンインストールしようとしています:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "アンインストールしてもよろしいですか?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "あなたは以下の Flatpak をインストールしようとしています:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "インストールしてもよろしいですか?" #~ msgid "Apps Of The Week" #~ msgstr "今週のアプリ" #, c-format #~ msgid "Released %x" #~ msgstr "リリース日 %x" #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "VCS ブラウザー" #~ msgid "Full Application View" #~ msgstr "アプリケーションページの表示" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "アプリケーションを見ているときに表示される内容を変更します" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause " #~ "GitHub to eventually rate limit you." #~ msgstr "" #~ "あなたがアクセストークンを持っていない場合、この設定をオンにしていると " #~ "Github からレート制限をされる恐れがあります。" #~ msgid "Type to filter" #~ msgstr "入力して検索" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "プロプライエタリなライセンスの結果を除外" #~ msgid "Advanced" #~ msgstr "高度なオプション" #~ msgid "Open this link externally" #~ msgstr "このリンクを外部で開く" kolunmi-bazaar-7b9c8e1/po/kw.po000066400000000000000000002336611514314607700164740ustar00rootroot00000000000000# Cornish translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Flynn Peck , 2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-04 23:40+0000\n" "PO-Revision-Date: 2026-02-05 13:42+0000\n" "Last-Translator: Flynn Peck \n" "Language-Team: kw\n" "Language: kw\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Basar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Addya, remova, po nowedhi medhelweyth flatpak yn an amontyell ma" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;DyghtyerFardellow;Trovya;Flatpak;Medhelweyth;Gwerthji;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Fenester Nowydh" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Trovya ha lea appys" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Unn gwerthji appys nowydh rag Linux gans unn fog war ow trovya hag ow lea " "appys hag ystynansow dhyworth gwerthjiow Flatpak, dres oll Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Y posleva an skoodhyans rag an awtours neb a gul an ekokevreyth Linux. Basar " "omdhiskwedhes an \"dyghtys\" tabb dre konfigurys gans lesrenyadesow dhe " "alowa unn eksperyans leel." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:701 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "An folen chi ow displetya appys Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Folen app Nuklesen" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Folen hwithrans" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Folen klassys" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "Dyghtya Ystynansow" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:227 msgid "Remove" msgstr "Remova" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:198 msgid "Install" msgstr "Lea" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "Talvos Oos" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Garowder Komik" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Kedhlow vyth yn-kever garowder komik" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Garowder Fantasi" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Kedhlow vyth yn-kever garowder fantasi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Garowder Gwirvosek" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Kedhlow vyth yn-kever garowder gwirvosek" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Garowder rag Krow" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Kedhlow vyth yn-kever krow" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Garowder Reydhel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Kedhlow vyth yn-kever garowder reydhel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Las" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Kedhlow vyth yn-kever kampollans dhe las" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Droggya Anlaghel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Kedhlow vyth yn-kever kampollans dhe droggya anlaghel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tobacko" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Kedhlow vyth yn-kever kampollans dhe gwaren tobacko" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nothedh" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Kedhlow vyth yn-kever kampollans dhe nothedh" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Themow Reydhel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Kedhlow vyth yn-kever kampollans dhe po portrayansow a gnas reydhel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Koss" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Kedhlow vyth yn-kever kossya" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Hwarthuster na Gwiw" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Kedhlow vyth yn-kever hwarthuster na gwiw" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Disfaveryans" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Kedhlow vyth yn-kever keskows disfaveryans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Argemynnow" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Kedhlow vyth yn-kever argemynnow" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Hapwaryans" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Kedhlow vyth yn-kever hapwaryans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Prenyans" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Kedhlow vyth yn-kever prenyans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Keskows ynter Devnydhyoryon" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Kedhlow vyth yn-kever keskows ynter devnydhyoryon" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Galow Pellgows ynter Devnydhyoryon" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Kedhlow vyth yn-kever keskows ynter devnydhyoryon" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Kedhlow Kestav" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "Kedhlow vyth yn-kever kevrans a hanwyn usyer po ebost" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Kedhlow Privedh" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "Kedhlow vyth yn-kever kevrans a kedhlow privedh gans tressa partiow" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Kevrans Tyller" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "Kedhlow vyth yn-kever kevrans tyller gans devnydhyoryon erel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Horyans" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Kedhlow vyth yn-kever kampollans dhe horyans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Avoutri" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Kedhlow vyth yn-kever kampollans dhe avoutri" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Warioryon Reydhel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Kedhlow vyth yn-kever warioryon reydhel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Defolyans" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Kedhlow vyth yn-kever kampollans dhe defolyans" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Korf Marow" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Kedhlow vyth yn-kever korf marow a wel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Kethneth" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Kedhlow vyth yn-kever kampollans dhe kethneth" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Vyth komprehendya kampollans dhe droggys" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Vyth komprehendya kossya" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Vyth komprehendya argemynnow po treuswriansow monesek" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Vyth komprehendya kyjyans po nothedh" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Vyth komprehendya keskows heb musur" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Vyth komprehendya garowder" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Droggys" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Koss" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Mona" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Kowethasek" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Garowder" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Oll" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s re unn talvos oos ankoth" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s usi fytti rag oll" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s usi fytti rag fleghes yowynk" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s usi fytti rag fleghes" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s usi fytti rag degowogyon" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s usi fytti rag tevesigesow" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s usi fytti rag %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "Rol Chif" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "_Argevri dhe Basar ❤️" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "_Settyansow" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "_Omgelmi gans Flathub" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "_Dyghtya Data Usyer Remenant" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "_Kerghes Gwerthjiow" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "_Kesunyansow Bysowek" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "_A-dro Basar" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "_Kwytya Basar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Restrenva system %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Restrenva tre %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Restrenvaow system ost" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Settyansow system ost dhyworth /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Isrestrenva desktop %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Restrenva desktop" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Isrestrenva skrifow %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Restrenva skrifow" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Isrestrenva musik %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Restrenva musik" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Isrestrenva avenyow %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Restrenva avenyow" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Isrestrenva Kevren Poblek %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Restrenva Kevren Poblek" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Isrestrenva gwydhyowyow %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Restrenva gwydhyowyow" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Isrestrenva ensampelys %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Restrenva ensampelys" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Isrestrenva sorn usyer %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Restrenva sorn usyer" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Isrestrenva settyansow usyer %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Restrenva settyansow usyr" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Isrestrenva data usyer %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Restrenva Data Usyer" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Isrestrenva kerghynnedh usyer %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Restrenva kerghynnedh usyer" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Hedhas restrenva dhe %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Tyller restren ankoth" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Braster Iskarg" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Myns rag iskarga dhyworth an kesrosweyth" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Braster Leys" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Braster war Plasen" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Braster Data Usyer" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Cache, settyansow, ha data appys aral" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:175 msgid "Installed" msgstr "Leys" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "Diskwedhes Oll" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "Oll \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Appys" #: src/bz-application.c:672 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:673 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:704 msgid "translator-credits" msgstr "Flynn " #: src/bz-application.c:715 msgid "Special Thanks" msgstr "Grassow Arbennik" #: src/bz-application.c:773 msgid "Logged Out Successfully!" msgstr "Omdennys yn Sewen!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Ow gwruthyl selyans..." #: src/bz-application.c:975 src/bz-application.c:984 msgid "Set Up Flathub" msgstr "Selya Flathub" #: src/bz-application.c:978 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub yw na selys war an system ma. A Flathub yw ankavadow, ty na gallos " "peuri ha lea appys yn Basar." #: src/bz-application.c:983 msgid "Later" msgstr "Diwettha" #: src/bz-application.c:1393 src/bz-application.c:3087 msgid "Synchronizing..." msgstr "Ow Kettermynyegi..." #: src/bz-application.c:1540 src/bz-application.c:3083 #, c-format msgid "Receiving %d entries..." msgstr "Ow receva %d enworrans manylyon..." #: src/bz-application.c:1545 msgid "Checking for updates" msgstr "Ow checkya rag nowedhyansow" #: src/bz-application.c:3089 msgid "Indexing Data..." msgstr "Ow Kevernya Data..." #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Folen Flathub" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "Gwiasva Ragdres" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rol a Kudynnow" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "Govynnow Kemmyn" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "Gweres" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "Argevri" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "Treylya" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "Kestava" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kod" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "Kevri" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "Gwag" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Dyghtyans Vyth" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Yma kudhlow dyghtyans vyth provys war an system ma. Ty gallos hwath peuri " "appys war Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Peuri Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Dhywarlinen" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Peurell" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Kedhlow awtour ankavadow." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "An perghenogeth a an %s ID app na gwirys hag y yw unn fardel ansodhogel " "martesen." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "An perghenogeth a an %s ID app yw gwirys dre dhorn gans an bagas Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "An perghenogeth a an %1$s ID app yw gwirys gans %2$s war %3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "An perghenogeth a an %1s ID app yw gwirys ow devnydhya %1s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "An perghenogeth a an %s ID app yw gwirys." #: src/bz-donations-dialog.blp:22 msgid "Bazaar is a Passion Project" msgstr "Basar yw Ragdres Passyon" #: src/bz-donations-dialog.blp:23 src/bz-window.blp:325 msgid "Support the Future of Linux App Distribution" msgstr "Skoodhya an Termyn a Dheu a Lesrannans Appys Linux" #: src/bz-donations-dialog.blp:32 msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "My a gar ow gul Basar, mes ny allav gul yth yn unsel. Mar ty mynnes gweres " "skoodhya gwrians pella, mar pleg, prederi owth argevri dhe'n ragdres yn ow " "ko-fi:" #: src/bz-donations-dialog.blp:42 msgid "Donate to Bazaar" msgstr "Argevri dhe Basar" #: src/bz-donations-dialog.blp:48 msgid "Disable the donations banner on startup" msgstr "Ungallosegi an baner argevrohow dres dalleth" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Dewis unn Ynstallyans" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Ty kavos versyons liesek a an app ma leys. Pyneyl a vynn'ta y gavos procedya " "gans?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:197 #: src/bz-transaction-dialog.c:226 src/bz-transaction-dialog.c:271 #: src/bz-transaction-dialog.c:561 msgid "Cancel" msgstr "Hedhi" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Rag an usyer ma hepken" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "an usyer" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "oll usyoryon" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Unn Error Hwarvos" #: src/bz-error.c:89 msgid "Close" msgstr "Kwytya" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Dasskrifa ha Kwytya" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Omgelmi gans Flathub rag dyghtya drughyow" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Omgelmi" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Somm Drughyow" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Dislea" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "Skoodhya an app ma" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Dilea a Drudhyow" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "Drudhyow" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 msgid "Open App Library" msgstr "Ygeri Lyverva Appys" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:562 msgid "Install All" msgstr "Lea Oll" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "Ow Karga" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "Vyth Drudhyow" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "Appys ty merkya avel drudh a wra diskwedhes omma" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Kyns" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Nessa" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "App a'n Jydh" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "Pennskrifa" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Kemyskell" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "Ilow" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "Gwarier" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Rekordyer" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "Kevreser" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Tonyer" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "Pellwolok" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "Omhevelians" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "Gwrians" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Aventur" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Arkade" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Stockow" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Bordh" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Karten" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Fleghes" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "Lojyk" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "Rann" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Sether" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "Hevelebyans" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "Sportys" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "Strateji" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "Son & Gwydhyow" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "Media" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Moy Son & Gwydhyow" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Toulys Amontydh" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Displegya" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Moy Toulys Amontydh" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Adhyskans" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Dyski" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "Moy Adhyskans" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Gwariow" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Gwari" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "Moy Gwariow" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "Grafek & Skeusenieth" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Gul" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Moy Grafek & Skeusenieth" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Rosweythyans" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Kesrosweyth" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Moy Rosweythyans" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Askorruster" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Gonis" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Moy Askorruster" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "Godhonieth" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "Moy Godhonieth" #: src/bz-flathub-category.c:128 msgid "System" msgstr "Kevreyth" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Moy Kevreyth" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "Lesow" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Toulys" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "Moy Lesow" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Gerys-da Lemmyn" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Moy Gerys-da Lemmyn" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Gerys-da" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Moy Gerys-da" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Addya A-lergh" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nowydh" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Moy Nowydh" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Nowedhys A-lergh" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Nowedhys" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "Moy Nowedhys" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Gwayadow" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "Moy Gwayadow" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Moy Adwaita" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "Appys KDE" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "Moy Appys KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub heb Addya" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "An gwerthji Flathub na fonya war neb agas ynstalyansow Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub ri tre unn error" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Hwilewgh arta Junyans Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub Ankavadow" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Yma difygya dhe junya Flathub. Ty gallos hwath dyghtya ha hwilas rag appys." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Hwilas Appys" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Gwayadow" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Appys rag agas kellgowsoryon ha leghennow Linux" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Moy Appys Gwayadow" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Ni ♥ Gwariow​" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Gwariow hag appys rag eksekutya agas titlys drudh" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Moy Gwariow" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "Vyth Sewyansow" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "Assaya hwithrans erel" #: src/bz-full-view.blp:59 msgid "Content" msgstr "Dalgh" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "Ow lea fardellow .flatpal na hwath skoodhys" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Skoodhya" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Ygeri" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Iskarga & Lea App" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Dislea App" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Lea Versyon Erel" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "Iskargow/Mis" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Na Fella Ow Receva Nowedhyansow Kolonnen" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "An app ma devnydhya unn kerghynnedh may na fella receva nowedhyansow po " "ewnheans sawder. Y'n bos martesen diantel rag devnydh." #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "Data Atal" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "Taggys:" #: src/bz-full-view.c:220 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d iskargow y'n mis diwettha" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "Ankavadow" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "Iskarg" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "Kedhlow braster ankavadow" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "Braster iskarg a %s" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "Oll Osow" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "Kedhlow Talvos oos ankavadow" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "Fytti rag oll osow" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "Fytti rag osow %d ha war-vann" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "Ankoth" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "Medhelweyth dhe wari kummya a-woles dhe %s" #: src/bz-full-view.c:403 msgid "Free software" msgstr "Medhelweyth dhe wari" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "Medhelweyth Perghenogel" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "Kummyas Arbennik: %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "Dhe wari" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Perghenogel" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Kummyas Arbennik" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "Desedhadow" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "Amontyell Unnik" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "Gweythresek war amontyellow, leghennow, ha kellgowsoryon" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "Res angweythresek war kellgowsoryon" #: src/bz-full-view.c:472 msgid "No URL" msgstr "URL Vyth" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "An app ma re unn kummyas dhe wari, ytho an kod gallos arhwilas rag salowder." #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "An app ma re unn kummyas perghenogel, ytho an kod usi displegya privedh ha " "na gallos arhwilas gans unn parti tressa." #: src/bz-full-view.c:498 msgid "More Apps" msgstr "Moy Appys" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "Moy Appys gans %s" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "Appys Aral gans an Awtour ma" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "Appys Aral gans %s" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s usi na ynstallys, saw y hwath re %s a data remenant." #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Saw" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "Peryl Isel" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "Peryl Kresek" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "Peryl Ughel" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "Appys Aral" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d App" msgstr[1] "%d Appys" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "Diskwedhes Le" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "Diskwedhes Moy" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Skoodhyans kalesweyth" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Skoodhyans bysowek" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Rekwirya bysowegi" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Komendya bysowegi" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Skoodhya bysowegi" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Skoodhyans ankoth rag bysowegi" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Skoodhyans logosen" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Rekwirya logosen po devisyow poyntya" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Komendya logosen po devisyow poyntya" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Skoodhya logosen po devisyow poyntya" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Skoodhyans ankoth rag logosen po devisyow poyntya" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Skoodhyans tochskrin" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Rekwirya tochskrinyow" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Komendya tochskrinyow" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Skoodhya tochskrinyow" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Skoodhyans ankoth rag tochskrinyow" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Skoodhyans kellgowser" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Gweythresek war kellgowsoryon" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Res angweythresek war kellgowsoryon" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Skoodhyans amontyell" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Gweythresek war skrinyow bras" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s gweythresek gwella war kalesweyth komparek" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s gweythresek war rann vrassa a devisyow" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Nowedhys Namoy" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "Hwilas appys leys" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "Appys Kavosys Vyth" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 msgid "Library" msgstr "Lyverva" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "Nowedhys Ow Gortos" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "Iskargow" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "Disleys A-lergh" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "Dilea Oberennow Deu" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "Appys Leys" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Parow vyth kavosys rag \"%s\" y'n rol appys leys" #: src/bz-library-page.c:165 src/bz-updates-card.c:225 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u Nowedhyans Kavadow" msgstr[1] "%u Nowedhyansow Kavadow" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Bos Omvyskys" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "Kummyas Ankoth" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "Byldya gans an Kemeneth" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "An app ma usi gwrys y'n poblek gans unn kemeneth keswlasek.\n" "\n" "Ty gallos kemeres rann ha gweres gwellhe y." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "An kummyas rag an app ma usi ankoth" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "An app ma usi gwrys y'n poblek gans unn kemeneth keswlasek, hadyllo a-woles " "dhe an %s kummyas." #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "An app ma usi gwyrs na y'n poblek, ytho an awtours unnik aswon fatel y " "oberi. Y res usi andhiogel yn agwedhow dre kales dhe helergi, hag y res " "chanja heb ankov.\n" "\n" "Ty res po na res kevri dhe an app ma." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "An app ma usi gwyrs a-woles dhe an kummyas arbennik %s.\n" "\n" "Ty res po na res kevri dhe an app ma." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Junya dhe Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Yma Hager Vargen" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "Junya dha akont Flathub dhe Basar rag dyghtya dha appys drudh." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Finsya" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Dydh dha, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Settyansow" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Junyans kesrosweyth yw strothys — kerghow awtomatek synsas gwerthji yw " "powesys" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "Kerghes dre Dhorn" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Sidhlow Dalgh" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Medhelweyth dre wari Unnik" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Kudha appys perghenogel dres peuryans ha hwithrans" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Sewyasow a Flathub Unnik" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Finwetha sewyasow hwithrans ha peuryans dhe appys kavadow unnik war Flathub" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Sewyasow Gwirys Hepken" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Kudha sewyansow na gwirys war Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Kudha Appys Marow" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Kudha appys may na skoodhya gans y'ga awtours" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "Hwithrans" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Delatya Sewyasow Hwithrans" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "Gwellhe skavder sewyasow gans ow kesunya geryow hwithrans" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Barr Avonsyans" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Dewis unn thema rag an barr avonsyans!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Linennow Plommwedhek" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Diskwedhes kolors baner dhyworth kledh dhe dyghow" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Kolor Usyer" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Kolors Gooth" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Kolors Gooth Lesbian" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Kolors Gooth Gourkethreydhel" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Kolors Gooth Treusreydhek" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Kolors Gooth na Den na Ben" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Kolors Gooth Dewreydhel" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Kolors Gooth Anreydhel" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Kolors Gooth Pubreydhek" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Kolors Gooth Anromansek" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Kolors Gooth Reydh Chanjus" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Kolors Gooth Liesreydhek" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Kolors Gooth Ollreydhek" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Kolors Gooth Anromansek hag Anreydhel" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Kolors Gooth Anreydh" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Kolors Gooth na Den na Ben" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Kolors Gooth Hermaphroditek" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Kolors Gooth Hanterreydh" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Kolors Gooth Dewromansek" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Kolors Gooth Evredhyon" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Kolors Gooth Maw-Gwregel" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Kolors Gooth Newtroys" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:137 msgid "Version History" msgstr "Istori a Versyons" #: src/bz-releases-list.c:165 #, c-format msgid "Version %s" msgstr "Versyon %s" #: src/bz-releases-list.c:215 msgid "No details for this release" msgstr "Manylyon vyth rag an veryson ma" #: src/bz-releases-list.c:227 msgid "Get More Information" msgstr "Kerghes Moy Kudhlow" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Kerghes" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "Grontys Ankoth" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "Grontys fyllel rag an app ma." #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Grontys Vyth" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "App yw kontaynys yn leun" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Hedhas Kesrosweyth" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Gallos drehedhes an kesrosweyth" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Hedhas Kesrosweyth Vyth" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Na gallos drehedhes an kesrosweyth" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Hedhas Devis Usyer" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "Gallos drehedhes devisyow kepar ha kameras po konsolen wariow gwydhyow" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Hedhas Devis Usyer Vyth" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Na gallos drehedhes devisyow kepar ha kameras po konsolen wariow gwydhyow" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Hedhas Devis Ynworrans" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Gallos drehedhes devisyow ynworrans" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Hedhas Korrgewsell Ha Seni Son" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "Gallos goslowes gans korrgewsellow ha seni son neb ow peji gront" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Hedhas Devis System" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "Gallos drehedhes devisyow system may rekwirya grontys ughelhys" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Hedhas Dalgh Skrin" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Gallos drehedhes an dalgh skrin po fenestri aral" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "System Fenester Anterrus" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Devnydhya prest unn system fenester anterrus (X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "Grontys Siansek" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Gallos kavos grontys siansek" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Settyansow Usyer" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Gallos drehedhes ha chanjya settyansow usyer" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Hedhas rag Redya/Skrifa System Restrenva Leun" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "Gallos redya ha skrifa oll data yn an system restrenva" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Hedhas rag Redya/Skrifa Restrenva Tre" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "Gallos redya ha skrifa oll data yn dha restrenva tre" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Hedhas rag Redya System Restrenva Leun" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "Gallos redya oll data yn an system restrenva" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Hedhas rag Redya Restrenva Tre" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "Gallos redya oll data yn dha restrenva tre" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Hedhas rag Redya/Skrifa yn Restrenva Iskargow" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "Gallos redya ha skrifa oll data yn dha restrenva iskargow" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Hedhas rag Redya yn Restrenva Iskargow" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "Gallos redya oll data yn dha restrenva iskargow" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "Gallos redya ha skrifa oll data y'n restrenva" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "Gallos redya oll data y'n restrenva" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Hedhas System Restrenva Vyth" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "Na gallos an system restrenva banna" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Devnydhya Gonisyow System" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Gallos govyn data dhyworth gonisyow anportal system" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Devnydhya Gonisyow Esedhek" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Gallos govyn data dhyworth gonisyow anportal esedhek" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Hedhas Gonis Vyth" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "Na gallos drehedhes gonisyow anportal system po esedhek banna" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Awtour App Gwirys" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "An awtour a an app ma yw gwirys rag bos piw i onwul" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Kod Perghenogel" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "An kod na poblek, ytho y'n na gallos arhwilas yn anserghek ha bos martesen " "diantel" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Kod Arhwiladow" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "An kod yw poblek ha gallos arhwilas yn anserghek, ytho an app ma yw saw moy " "gwirhaval" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Devnydhya an Gonis System %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Devnydhya an Gonis Esedhek %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Devnydhya an Gonis %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Gallos gweles an gonis anportal" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Gallos kewsel dhe an gonis anportal" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Gallos perghenna an gonis anportal" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Oberyans Rol Olldalghus" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Gallos diskwedhes rolyow yn unn barr rol olldalghus" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Oberyans Settyansow KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Gallos helerghi pan settyansow KDE chanjya" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Settyansow Olldalghus KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Gallos redya settyansow desktop KDE kepar ha fontow ha kolors" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "Gonis Gwithyans Kevrinyow" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "Gallos gwitha ha kerghes y geryow-tremena ow devnydhya an alhwedhow-bysow " "system" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Gonis Gwarnyansow Desktop" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Gallos danvon gwarnyansow desktop" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Oberyans Tallyour System" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Gallos diskwedhes unn arwodhik y'n tallyour system" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Oberyans KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "Gallos keskomunya gans devisyow junys dre KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Sawder" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Manylyon" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Kummyas" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "ID App" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "An app ma devnydhya unn versyon anterrus a an kerghynnedh medhelweyth (SDK) " "ha kontaynya martesen kudynnow po goliadewderow sawder may na bos ewnhys." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s yw Saw" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s kavis Grontys Diantel Vyth" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s yw Saw Dell Hevel" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s yw Saw Martesen" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s yw Diantel" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Imajys" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Imach Kyns" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Imach Nessa" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Dasskrifa Imach" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Dasgorra Gwel" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Lehe" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Moghhe" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Res A-dro Imajys" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Ygeri Goloker Imajys" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Hwials Appys, Gwariow, Medhelweyth" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Kassys Ankavadow" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Hwilas rag appys gans an barr hwithrans a-ugh." #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Appys Kavos Vyth" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Sewyansow kavos vyth rag \"%s\" yn Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Dasskrifys" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Dasskrifa Gorgevren" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Ygeri Gorgevren" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Linen Dermyn" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Leyansow:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Nor" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Somm Leyansow" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fk Somm Leyansow" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d Somm Leyansow" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Sewyansow Kavos Vyth" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Appys Taggya avel \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Hwithrans fyllis" #: src/bz-transaction-dialog.c:151 msgid "Keep Data" msgstr "Synsi Data" #: src/bz-transaction-dialog.c:152 msgid "Allow restoring settings and content" msgstr "Alowa dasserghyans settyansow ha d" #: src/bz-transaction-dialog.c:161 msgid "Delete Data" msgstr "Dilea Data" #: src/bz-transaction-dialog.c:162 msgid "Permanently remove app data to save space" msgstr "Dilea yn fast data app dhe erbysi dalghuster" #: src/bz-transaction-dialog.c:187 #, c-format msgid "Install %s?" msgstr "Lea %s?" #: src/bz-transaction-dialog.c:192 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Dewis may versyon rag lea. Martesen a wra lea darnow kevrennys keworransel" #: src/bz-transaction-dialog.c:194 msgid "May install additional shared components" msgstr "Res lea darnow keworransel poblek" #: src/bz-transaction-dialog.c:215 #, c-format msgid "Remove %s?" msgstr "Dilea %s?" #: src/bz-transaction-dialog.c:218 msgid "Select which version to remove." msgstr "Dewis mar verson rag remova." #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Y yw angalladow dhe devnydhya %s wosa y yw dislea." #: src/bz-transaction-dialog.c:243 #, c-format msgid "“%s” is High Risk" msgstr "\"%s\" yw Peryl Ughel" #: src/bz-transaction-dialog.c:247 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "An app ma kavos hedhas leun dhe dha system, ow komprehendya oll dha " "restrennow, istori peurell, geryow-tremena sawys ha moy. Keffrys, y " "kavos hedhas kesrosweyth, ytho y gallos danvon dha data dhe partiow tressa." #: src/bz-transaction-dialog.c:256 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "An app ma devnydhys an system fenestri anterrus X11, ytho y'n gallos " "rekordya oll jynnskrifow, kemeres skrin-imajys, ha helerghi appys aral. Maga ta, y'n gallos drehedhes an kesrosweyth, ytho y'n gallos danvon dha " "data dhe partiow tressa.\n" "\n" "Rag an app yw perghenogel, y'n na gallos bos arhwilas rag py y'n gul gans an " "grontys ma." #: src/bz-transaction-dialog.c:272 msgid "Install Anyway" msgstr "Lea yn neb Kas" #: src/bz-transaction-dialog.c:532 msgid "All apps are already installed" msgstr "Oll appys yw leys seulabrys" #: src/bz-transaction-dialog.c:534 msgid "OK" msgstr "Da Lowr" #: src/bz-transaction-dialog.c:550 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Lea %u App?" msgstr[1] "Lea %u Appys?" #: src/bz-transaction-dialog.c:558 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "An taklow a sew a wra leys. Darnow kevrennys keworransel a wra leys maga ta " "martesen" #: src/bz-transaction-dialog.c:559 #, c-format msgid "%d addons will be installed." msgstr "%d ystynansow a wra leys." #: src/bz-transaction-dialog.c:560 msgid "Additionally, addons will be installed." msgstr "Maga ta, ystyanansow a wra leys." #: src/bz-transaction-manager.c:1246 #, c-format msgid "Finished in %.02f seconds" msgstr "Deu yn %.02f eylennow" #: src/bz-transaction-tile.blp:124 msgid "App Add-on" msgstr "Ystynnans rag App" #: src/bz-transaction-tile.blp:153 msgid "Runtime" msgstr "Kerghynnedh rag App" #: src/bz-transaction-tile.blp:177 msgid "In Queue" msgstr "Yn Lost" #: src/bz-transaction-tile.blp:201 msgid "Done" msgstr "Deu" #: src/bz-transaction-tile.blp:241 msgid "Open App" msgstr "Ygeri App" #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s Rythhys" #: src/bz-transaction.c:342 msgid "Pending" msgstr "Ow Gortos" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "Nowedhi Oll" #: src/bz-updates-card.blp:148 msgid "Update" msgstr "Nowedhyans" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Dyghtya Data Usyer Remenant" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "Data Usyer kavos vyth" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "Data Usyer" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Removys Data User rag %s" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Remova Data Usyer" #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "Ow Diseghow Dalgh Gwerthji" #: src/bz-window.blp:153 msgid "Curated" msgstr "Dyghtys" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "Oberennow vyth yn kilva!" #: src/bz-window.blp:326 msgid "See More" msgstr "Gweles Moy" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Ty re unn junyans kewrosweyth lemen yw ow gweles unn versyon koth a Flathub" #: src/bz-window.blp:449 msgid "Log Out" msgstr "Omdenna" #: src/bz-window.c:669 msgid "You can't remove Bazaar from Bazaar!" msgstr "Ty na gallos remova Basar dhyworth Basar!" #: src/bz-window.c:912 src/bz-window.c:946 msgid "Can't do that right now!" msgstr "Ny allav gul na y'n eur ma" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "Iskargow" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Ollgemmyn" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Ygeri Fenester Hwithrans" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Ygeri Settyansow" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "_Kettermynyegi Gwerthjiow" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Dewis Dyghtyer Treuswrians" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Diskwedhes Kesunyansow Bysowek" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Kwytya" #~ msgid "_Refresh Content" #~ msgstr "_Dishegha Dalgh" #~ msgid "Toggle transaction sidebar" #~ msgstr "Dewis bord lestri treuswrians" #~ msgid "Install Size" #~ msgstr "Braster Lea" #~ msgid "Ongoing" #~ msgstr "Didorr" #~ msgid "Finished" #~ msgstr "Deu" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "Treusperthi %s bys lemmyn" #~ msgid "Tasks" #~ msgstr "Oberennow" #~ msgid "Stop Active Tasks" #~ msgstr "Hedhi Oberennow Byw" #~ msgid "Clear History" #~ msgstr "Dilea Istori" #~ msgid "No Tasks Yet" #~ msgstr "Oberennow Vyth Hwath" #, c-format #~ msgid "%d Update Available" #~ msgid_plural "%d Updates Available" #~ msgstr[0] "%d Nowedh Kavadow" #~ msgstr[1] "%d Nowedhow Kavadow" #~ msgid "Updates Are Available" #~ msgstr "Nowedhow Kavadow" #~ msgid "" #~ "The following applications are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "An appys a sew yw dewisadow rag nowedhow. A vynnsowgh lea y's?" #, c-format #~ msgid "" #~ "%d runtimes and/or addons are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "%d kerghynnedhow ha/po ystynnans yw dewisadow rag nowedhow. A vynnsowgh " #~ "lea y's?" #, c-format #~ msgid "Additionally, %d runtimes and/or addons will be updated." #~ msgstr "Dres hemma, %d kerghynnedhow ha/po ystyannans yw nowedhys." #~ msgid "Update Now" #~ msgstr "Nowedhi Lemmyn" #~ msgid "Resume Current Tasks" #~ msgstr "Daskemeres Oberennow A-Lemmyn" #~ msgid "Pause Current Tasks" #~ msgstr "Powes Oberennow A-Lemmyn" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "An Gallos dhe hwithra ha lea restrennow .flatpak leel ow tos yn skon! Yn " #~ "kettermyn, tria owth eksekutya\n" #~ "\n" #~ "flatpak install --bundle agas-gronn.flatpak\n" #~ "\n" #~ "yn an linen arghadow." #~ msgid "Hide EOL Entries" #~ msgstr "Keles appys marow" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "Keles appys marow hag appys serghek" #~ msgid "Only Show Free Software" #~ msgstr "Diskwedhes appys dhe wari hepken" #~ msgid "Hide proprietary software" #~ msgstr "Keles appys perghenogel" #~ msgid "Show Only Flathub Content" #~ msgstr "Diskwedhes synsas Flathub hepken" #~ msgid "Hide applications which do not originate from Flathub" #~ msgstr "Kudha appys may na dalleth dhyworth Flathub" #~ msgid "Show Only Verified Content" #~ msgstr "Diskwedhes Dalgh Flathub Hepken" #~ msgid "Hide applications which are not verified on Flathub" #~ msgstr "Kudha appys may na gwirys war Flathub" #~ msgid "Debounce Search Inputs" #~ msgstr "Kesunya Ynworransow Hwithrans" #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "" #~ "Addya unn ardak dherag hwilas rag preventya gorthebow desempis dres " #~ "jynnskrifa" #~ msgid "Global Progress Bar Theme" #~ msgstr "Thema Barr Avonsyans Olldalghus" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Deskrifa an mir a an Barr Avonsyans Olldalghus" #~ msgid "Saved Window Dimensions" #~ msgstr "Sawys Braster Fenester" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "An braster fenester rag devnydh gans an fenester Basar nessa" #~ msgid "?" #~ msgstr "?" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "An nas ma usi evredhek y'n eur ma. Y usi komendya dhe iskarga ha lea " #~ "Flatseal dhe dyghtya grontow appys." #~ msgid "Entry Inspector" #~ msgstr "Hwithrer Enworrans Manylyon" #~ msgid "Serialize" #~ msgstr "Kedreylya yn Baytys" #~ msgid "Convert to JSON" #~ msgstr "Kedreylya yn JSON" #~ msgid "More Mobile apps" #~ msgstr "Moy Appys Gwayadow" #~ msgid "Bazaar Inspector" #~ msgstr "Hwithrer Basar" #~ msgid "Background Task Info:" #~ msgstr "Kedhlow Oberennow Kilva:" #~ msgid "Enable Global Debug Mode" #~ msgstr "Gallosegi Prevessa Olldalghus" #~ msgid "Active Blocklists" #~ msgstr "Rol a Lettys Byw" #~ msgid "Active Curated-Configs" #~ msgstr "Settyansow Dyghtys Byw" #~ msgid "All Entry Groups" #~ msgstr "Oll Bagasow Enworrans Manylyon" #~ msgid "Filter..." #~ msgstr "Sidhla..." #~ msgid "Decache and Inspect" #~ msgstr "Dissorn ha Hwithra" #~ msgid "No Flatpaks Installed" #~ msgstr "Vyth Flatpakow Ynstallys" #~ msgid "Connect with Flathub" #~ msgstr "_Junya dhe Flathub" #~ msgid "Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth (Gorwelyek)" #~ msgid "Lesbian Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Lesbian (Gorwelyek)" #~ msgid "Male Homosexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Gourkethreydhel (Gorwelyek)" #~ msgid "Transgender Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Treusreydhek (Gorwelyek)" #~ msgid "Nonbinary Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth na Den na Ben (Gorwelyek)" #~ msgid "Bisexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Dewreydhel (Gorwelyek)" #~ msgid "Asexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Anreydhel (Gorwelyek)" #~ msgid "Pansexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Pubreydhek (Gorwelyek)" #~ msgid "Aromantic Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Anromansek (Gorwelyek)" #~ msgid "Genderfluid Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Reydh Chanjus (Gorwelyek)" #~ msgid "Polysexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Liesreydhek (Gorwelyek)" #~ msgid "Omnisexual Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Ollreydhek (Gorwelyek)" #~ msgid "Aroace Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Anromansek hag Anreydhel (Gorwelyek)" #~ msgid "Agender Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Anreydh (Gorwelyek)" #~ msgid "Genderqueer Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth na Den na Ben (Gorwelyek)" #~ msgid "Intersex Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Hermaphroditek (Gorwelyek)" #~ msgid "Demigender Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Hanterreydh (Gorwelyek)" #~ msgid "Biromantic Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Dewromansek (Gorwelyek)" #~ msgid "Disability Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Evredhyon (Gorwelyek)" #~ msgid "Femboy Pride Colors (Horizontal)" #~ msgstr "Kolors Gooth Maw-Gwregel (Gorwelyek)" #~ msgid "Inspect UI Entry" #~ msgstr "Hwithra Elven Ynterfas" #~ msgid "All Debug Actions" #~ msgstr "Oll Gwriansow Prevessa" #~ msgid "Open Bazaar Inspector" #~ msgstr "Ygeri Hwithrer Basar" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u iskargow" #~ msgid "Size" #~ msgstr "Braster" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s usi fytti rag fleghes vyghan" #~ msgid "--- MB" #~ msgstr "--- MB" #~ msgid "Of the size of human DNA" #~ msgstr "a an braster a DNA den" #~ msgid "3 billion base pairs" #~ msgstr "3 bilvil koplow ben" #~ msgid "Of the Linux Kernel" #~ msgstr "a an Bewyn Linux" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "a an amontyell Apollo 11" #~ msgid "Total ROM and RAM" #~ msgstr "Somm rag ROM ha RAM" #~ msgid "Of the original Super Mario Bros" #~ msgstr "a Super Mario Bros" #~ msgid "On the NES" #~ msgstr "yn an NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "a an braster rag Wikipedya" #~ msgid "Without any media" #~ msgstr "Heb neb media" #~ msgid "Remove User Data" #~ msgstr "Remova Data Usyer" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Disegha" kolunmi-bazaar-7b9c8e1/po/meson.build000066400000000000000000000000471514314607700176430ustar00rootroot00000000000000i18n.gettext('bazaar', preset: 'glib') kolunmi-bazaar-7b9c8e1/po/nl.po000066400000000000000000002110501514314607700164500ustar00rootroot00000000000000# Dutch translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # #: src/bz-installed-page.blp:68 msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-10 20:06+0100\n" "PO-Revision-Date: 2025-07-15 07:56+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Voeg flatpak software toe, verwijder deze of update deze op deze computer" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Systeem;Pakketbeheer;Ontdekken;Flatpak;Software;Winkel;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Nieuw Venster" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Ontdek en installeer applicaties" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Een nieuwe appstore voor GNOME, gericht op het ontdekken en installeren van " "applicaties en add-ons van Flatpak bronnen, vooral Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Het legt de nadruk op het ondersteunen van de ontwikkelaars die de Linux " "desktop mogelijk maken. Bazaar heeft een \"gecureerde\" tab die door " "distributeurs kan worden aangepast voor een meer gelokaliseerde ervaring." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:697 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Het startscherm dat Flathub apps weergeeft" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Nucleus apppagina" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Zoekpagina" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Categoriepagina" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:694 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Beheer Addons" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:224 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "Verwijder" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:166 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:201 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Installeren" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:409 src/bz-full-view.c:416 msgid "Age Rating" msgstr "Leeftijdsadvies" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Stripgeweld" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Geen informatie over stripgeweld" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Fantasiegeweld" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Geen informatie over fantasiegeweld" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Realistisch geweld" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Geen informatie over realistisch geweld" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Geweld met bloedvergieten" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Geen informatie over geweld met bloedvergieten" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Seksueel geweld" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Geen informatie over seksueel geweld" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alcohol" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Geen informatie over verwijzingen naar alcohol" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Drugs" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Geen informatie over verwijzingen naar illegale drugs" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabak" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Geen informatie over verwijzingen naar tabaksproducten" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Naaktheid" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Geen informatie over enige naaktheid" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Seksuele thema’s" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Geen informatie over seksueel verwijzingen of afbeeldingen" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Grof Taalgebruik" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Geen informatie over grof taalgebruik" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Ongepaste humor" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Geen informatie over ongepaste humor" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Discriminatie" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Geen informatie over discriminerend taalgebruik" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Reclame" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Geen informatie over enige reclame" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Gokken" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Geen informatie over gokken" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Aankopen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Geen informatie over de mogelijkheid om echt geld uit te geven" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Gesprekken tussen gebruikers" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Geen informatie over mogelijkheden om met andere gebruikers te chatten" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Audiogesprekken tussen gebruikers" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Geen informatie over mogelijkheden om met andere gebruikers te praten" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Contactgegevens" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Geen informatie over het delen van gebruikersnamen van sociale netwerken of " "e-mailadressen" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Identificerende informatie" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "Geen informatie over het delen van gebruikersinformatie met derden" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Locatie delen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Geen informatie over het delen van de fysieke locatie met andere gebruikers" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostitutie" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Geen informatie over verwijzingen naar prostitutie" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Overspel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Geen informatie over verwijzingen naar overspel" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Geseksualiseerde personages" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Geen informatie over geseksualiseerde personages" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Heiligschennis" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Geen informatie over verwijzingen naar heiligschennis" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Menselijke overblijfselen" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Geen informatie over zichtbare overblijfselen van dode mensen" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Slavernij" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Geen informatie over verwijzingen naar slavernij" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Bevat geen verwijzingen naar drugs" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Bevat geen scheldwoorden of ander grof taalgebruik" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Bevat geen reclame of monetaire transacties" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Bevat geen seks of naaktheid" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "" "Bevat geen niet-gecontroleerde gespreksfunctionaliteit tussen gebruikers" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Bevat geen geweld" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drugs" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Grof taalgebruik" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Geld" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Sociaal" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Geweld" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:399 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Alle" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s heeft een onbekende leeftijdsclassificatie" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s is geschikt voor iedereen" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s is geschikt voor jonge kinderen" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s is geschikt voor kinderen" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s is geschikt voor tieners" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s is geschikt voor volwassenen" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s is geschikt voor %s" #: src/bz-age-rating-dialog.c:849 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:480 msgid "Main Menu" msgstr "Hoofdmenu" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:553 msgid "_Donate to Bazaar ❤️" msgstr "_Doneer aan Bazaar ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Inhoud verversen" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:560 msgid "_Preferences" msgstr "_Voorkeuren" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:581 msgid "_Keyboard Shortcuts" msgstr "_Snelkoppelingen Toetsenbord" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:586 msgid "_About Bazaar" msgstr "_Over Bazaar" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:593 msgid "_Quit Bazaar" msgstr "_Sluit Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Systeemmap %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Home submap %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Systeemmappen van host" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Systeemconfiguratie van host in /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Bureaublad-submap %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Bureaublad-map" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Bureaublad-submap %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Documenten-map" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Muziek-submap %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Muziek-map" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Afbeeldingen-submap %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Afbeeldingen-map" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Openbaar-submap %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Openbaar-map" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Video’s-submap %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Video’s-map" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Sjablonen-submap %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Sjablonen-map" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Cache-submap %s van gebruiker" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Cachemap van gebruiker" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Configuratie-submap %s van gebruiker" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Configuratiemap van gebruiker" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Gegevens-submap %s van gebruiker" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Gegevensmap van gebruiker" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Runtime-submap %s van gebruiker" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Runtime-map van gebruiker" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Toegang tot %s in bestandssysteem" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Onbekend bestandspad" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Download Grootte" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Te downloaden hoeveelheid van internet" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Geïnstalleerde Grootte" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Grootte op schijf" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Grootte Gebruikersgegevens" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Caches, instellingen en andere app-data" #: src/bz-app-tile.blp:85 src/bz-full-view.c:363 src/bz-installed-page.blp:85 #: src/bz-window.blp:296 msgid "Installed" msgstr "Geïnstalleerd" #: src/bz-apps-page.blp:103 msgid "Show All" msgstr "Toon Alle" #: src/bz-apps-page.c:232 #, c-format msgid "All \"%s\"" msgstr "Alle \"%s\"" #: src/bz-apps-page.c:506 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Applicaties" #: src/bz-application.c:668 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:669 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:700 msgid "translator-credits" msgstr "Alexander Vanhee, 2025" #: src/bz-application.c:711 msgid "Special Thanks" msgstr "Speciale Dank" #: src/bz-application.c:769 msgid "Logged Out Successfully!" msgstr "Succesvol Uitgelogd!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Setup aan het uitvoeren..." #: src/bz-application.c:975 src/bz-application.c:984 msgid "Set Up Flathub" msgstr "Flathub instellen" #: src/bz-application.c:978 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub is niet ingesteld op dit systeem. Je kunt geen applicaties in Bazaar " "browsen en installeren als het niet beschikbaar is.\n" "\n" "Je kunt Bazaar nog steeds gebruiken om reeds geïnstalleerde apps te bekijken " "en verwijderen." #: src/bz-application.c:983 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Later" #: src/bz-application.c:1385 src/bz-application.c:3059 msgid "Synchronizing..." msgstr "Synchroniseren..." #: src/bz-application.c:1524 src/bz-application.c:3055 #, c-format msgid "Receiving %d entries..." msgstr "%d items ontvangen..." #: src/bz-application.c:1529 msgid "Checking for updates" msgstr "Controleren op updates" #: src/bz-application.c:3061 msgid "Indexing Data..." msgstr "Gegevens aan het Indexeren..." #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:65 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Leeg" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Geen Gecureerde Apps" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Er is geen curatie-info beschikbaar op dit systeem. Je kan nog steeds apps " "op Flathub bekijken" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Naar Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Offline" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Browser" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Ontwikkelaarsinformatie niet beschikbaar." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Het eigendom van de %s app-ID is niet geverifieerd en het kan een " "communitypakket zijn." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Het eigendom van de %s app-ID is handmatig geverifieerd door het Flathub-" "team." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Het eigendom van de %1$s app-ID is geverifieerd door %2$s op %3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "Het eigendom van de %1$s app-ID is geverifieerd met %2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Het eigendom van de %s app-ID is geverifieerd." #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Kies een Installatie" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Je hebt meerdere versies van deze app geïnstalleerd. Welke wil je gebruiken?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:200 #: src/bz-transaction-dialog.c:223 src/bz-transaction-dialog.c:253 msgid "Cancel" msgstr "Annuleer" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Er is een fout opgetreden" #: src/bz-error.c:89 msgid "Close" msgstr "Sluiten" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Kopieren en Sluiten" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Log in met Flathub om favorieten te beheren" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Log In" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Aantal favorieten" #: src/bz-favorites-tile.c:164 msgid "Uninstall" msgstr "Verwijderen" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Ondersteun deze applicatie" #: src/bz-favorites-tile.blp:118 msgid "Remove from Favorites" msgstr "Verwijder van Favorieten" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:75 #: src/bz-window.blp:611 msgid "Favorites" msgstr "Favorieten" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:457 msgid "Toggle transaction sidebar" msgstr "Schakel Transactie-zijbalk" #: src/bz-favorites-page.blp:53 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Laden" #: src/bz-favorites-page.blp:68 msgid "No Favorites" msgstr "Geen Favorieten" #: src/bz-favorites-page.blp:69 msgid "Applications you mark as favorite will appear here" msgstr "Applicaties die je als favoriet markeert verschijnen hier" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Vorige" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Volgende" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "App van de Dag" #: src/bz-flathub-category.c:79 msgid "Audio & Video" msgstr "Audio & Video" #: src/bz-flathub-category.c:79 msgid "Media" msgstr "Media" #: src/bz-flathub-category.c:79 msgid "More Audio & Video" msgstr "Meer Audio & Video" #: src/bz-flathub-category.c:80 msgid "Developer Tools" msgstr "Ontwikkeltools" #: src/bz-flathub-category.c:80 msgid "Develop" msgstr "Ontwikkel" #: src/bz-flathub-category.c:80 msgid "More Developer Tools" msgstr "Meer Ontwikkeltools" #: src/bz-flathub-category.c:81 msgid "Education" msgstr "Educatie" #: src/bz-flathub-category.c:81 msgid "Learn" msgstr "Leren" #: src/bz-flathub-category.c:81 msgid "More Education" msgstr "Meer Educatie" #: src/bz-flathub-category.c:82 msgid "Gaming" msgstr "Gaming" #: src/bz-flathub-category.c:82 msgid "Play" msgstr "Spelen" #: src/bz-flathub-category.c:82 msgid "More Gaming" msgstr "Meer Gaming" #: src/bz-flathub-category.c:83 msgid "Graphics & Photography" msgstr "Grafisch & Fotografie" #: src/bz-flathub-category.c:83 msgid "Create" msgstr "Creëren" #: src/bz-flathub-category.c:83 msgid "More Graphics & Photography" msgstr "Meer Grafisch & Fotografie" #: src/bz-flathub-category.c:84 msgid "Networking" msgstr "Netwerken" #: src/bz-flathub-category.c:84 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:84 msgid "More Networking" msgstr "Meer Netwerken" #: src/bz-flathub-category.c:85 msgid "Productivity" msgstr "Productiviteit" #: src/bz-flathub-category.c:85 msgid "Work" msgstr "Werk" #: src/bz-flathub-category.c:85 msgid "More Productivity" msgstr "Meer Productiviteit" #: src/bz-flathub-category.c:86 msgid "Science" msgstr "Wetenschap" #: src/bz-flathub-category.c:86 msgid "More Science" msgstr "Meer Wetenschap" #: src/bz-flathub-category.c:87 msgid "System" msgstr "Systeem" #: src/bz-flathub-category.c:87 msgid "More System" msgstr "Meer Systeem" #: src/bz-flathub-category.c:88 msgid "Utilities" msgstr "Tools" #: src/bz-flathub-category.c:88 msgid "Tools" msgstr "Tools" #: src/bz-flathub-category.c:88 msgid "More Utilities" msgstr "Meer Tools" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Trending" #: src/bz-flathub-category.c:89 msgid "More Trending" msgstr "Meer Trending" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populair" #: src/bz-flathub-category.c:90 msgid "More Popular" msgstr "Meer Populair" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Recent Toegevoegd" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nieuw" #: src/bz-flathub-category.c:91 msgid "More New" msgstr "Meer Niewe" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Onlangs Bijgewerkt" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Bijgewerkt" #: src/bz-flathub-category.c:92 msgid "More Updated" msgstr "Meer Bijgewerkt" #: src/bz-flathub-category.c:93 msgid "Mobile" msgstr "Onderweg" #: src/bz-flathub-category.c:93 msgid "More Mobile" msgstr "Meer Onderweg" #: src/bz-flathub-category.c:94 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:94 msgid "More Adwaita" msgstr "Meer Adwaita" #: src/bz-flathub-category.c:95 msgid "KDE Apps" msgstr "KDE Apps" #: src/bz-flathub-category.c:95 msgid "More KDE Apps" msgstr "Meer KDE Apps" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub Niet Toegevoegd" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "De Flathub remote is op geen van je Flatpak installaties teruggevonden" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub gaf een foutmelding" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Flathub-verbinding opnieuw proberen" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub Onbeschikbaar" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "We konden geen verbinding maken met Flathub. Je kunt nog steeds applicaties " "beheren en zoeken." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Apps Zoeken" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Onderweg" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Apps voor je Linux telefoons en tablets" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Meer Mobiele Apps" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "We​ ♥​ Games" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Games en apps om je favoriete titels te spelen" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Meer Gaming" #: src/bz-flatpak-entry.c:608 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub Pagina" #: src/bz-flatpak-entry.c:629 msgctxt "Project URL Type" msgid "Project Website" msgstr "Projectwebsite" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Probleemtracker" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "FAQ" msgstr "Veelgestelde Vragen" #: src/bz-flatpak-entry.c:641 msgctxt "Project URL Type" msgid "Help" msgstr "Hulp" #: src/bz-flatpak-entry.c:645 msgctxt "Project URL Type" msgid "Donate" msgstr "Doneer" #: src/bz-flatpak-entry.c:651 msgctxt "Project URL Type" msgid "Translate" msgstr "Vertalen" #: src/bz-flatpak-entry.c:655 msgctxt "Project URL Type" msgid "Contact" msgstr "Contact" #: src/bz-flatpak-entry.c:659 msgctxt "Project URL Type" msgid "Source Code" msgstr "Broncode" #: src/bz-flatpak-entry.c:665 msgctxt "Project URL Type" msgid "Contribute" msgstr "Brijdragen" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Geen Resultaten" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Probeer een andere zoekterm" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Content" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Steunen" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Openen" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "App Downloaden & Uitvoeren" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Verwijder deze Applicatie" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Installeer Andere Versie" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "Downloads p/m" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Core-updates Gestopt" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Deze app gebruikt een runtime die geen updates of beveiligingsfixes meer " "ontvangt. Het kan onveilig worden om te gebruiken." #: src/bz-full-view.blp:627 msgid "Trash Data" msgstr "Naar Prullenbak" #: src/bz-full-view.blp:761 msgid "Tags:" msgstr "Tags:" #: src/bz-full-view.c:307 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:314 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:321 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:331 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d downloads in de afgelopen 30 dagen" #: src/bz-full-view.c:363 msgid "Download" msgstr "Download" #: src/bz-full-view.c:381 #, c-format msgid "Download size of %s" msgstr "Downloadgrootte van %s" #: src/bz-full-view.c:414 msgid "All Ages" msgstr "Iedereen" #: src/bz-full-view.c:426 msgid "Age rating information unavailable" msgstr "Leeftijdsclassificatie niet beschikbaar" #: src/bz-full-view.c:431 msgid "Suitable for all ages" msgstr "Geschikt voor alle leeftijden" #: src/bz-full-view.c:433 #, c-format msgid "Suitable for ages %d and up" msgstr "Geschikt voor %d jarigen en ouder" #: src/bz-full-view.c:466 src/bz-full-view.c:471 src/bz-full-view.c:499 #: src/bz-full-view.c:510 msgid "Unknown" msgstr "Onbekend" #: src/bz-full-view.c:476 #, c-format msgid "Free software licensed under %s" msgstr "Vrije software gelicentieerd onder %s" #: src/bz-full-view.c:481 msgid "Free software" msgstr "Alleen Vrije Software" #: src/bz-full-view.c:484 msgid "Proprietary Software" msgstr "Propriëtaire Software" #: src/bz-full-view.c:487 #, c-format msgid "Special License: %s" msgstr "Speciale licentie: %s" #: src/bz-full-view.c:504 msgid "Free" msgstr "Vrij" #: src/bz-full-view.c:507 src/bz-license-dialog.c:190 msgid "Proprietary" msgstr "Propriëtair" #: src/bz-full-view.c:512 src/bz-license-dialog.c:192 msgid "Special License" msgstr "Speciale licentie" #: src/bz-full-view.c:532 msgid "Adaptive" msgstr "Adaptief" #: src/bz-full-view.c:532 msgid "Desktop Only" msgstr "Alleen Desktop" #: src/bz-full-view.c:538 msgid "Works on desktop, tablets, and phones" msgstr "Werkt op desktop, tablets en telefoons" #: src/bz-full-view.c:539 msgid "May not work on mobile devices" msgstr "Werkt mogelijk niet op mobiele apparaten" #: src/bz-full-view.c:550 msgid "No URL" msgstr "Geen URL" #: src/bz-full-view.c:568 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Deze applicatie heeft een FLOSS licentie, wat betekent dat de broncode " "gecontroleerd kan worden op veiligheid" #: src/bz-full-view.c:569 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Deze applicatie heeft een proprietary-licentie, wat betekent dat de broncode " "privé wordt ontwikkeld en niet gecontroleerd kan worden door een derde " "partij." #: src/bz-full-view.c:576 msgid "More Apps" msgstr "Meer Apps" #: src/bz-full-view.c:577 #, c-format msgid "More Apps by %s" msgstr "Andere Apps van %s" #: src/bz-full-view.c:584 msgid "Other Apps by this Developer" msgstr "Andere Apps van deze Ontwikkelaar" #: src/bz-full-view.c:586 src/bz-full-view.c:786 #, c-format msgid "Other Apps by %s" msgstr "Andere Apps van %s" #: src/bz-full-view.c:595 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s is niet geïnstalleerd, maar heeft nog %s aan gegevens." #: src/bz-full-view.c:668 src/bz-full-view.c:685 msgid "N/A" msgstr "N.b." #: src/bz-full-view.c:675 src/bz-full-view.c:677 src/bz-full-view.c:679 msgid "Low Risk" msgstr "Laag risico" #: src/bz-full-view.c:681 msgid "Medium Risk" msgstr "Gemiddeld risico" #: src/bz-full-view.c:683 msgid "High Risk" msgstr "Hoog risico" #: src/bz-full-view.c:788 msgid "Other Apps" msgstr "Andere Apps" #: src/bz-full-view.c:790 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Applicatie" msgstr[1] "%d Applicaties" #: src/bz-full-view.c:1129 msgid "Show Less" msgstr "Minder Weergeven" #: src/bz-full-view.c:1129 msgid "Show More" msgstr "Meer Weergeven" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Hardwareondersteuning" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Toetsenbordondersteuning" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Vereist toetsenbord" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Toetsenbord aanbevolen" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Ondersteunt toetsenborden" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Onbekende ondersteuning voor toetsenborden" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Muisondersteuning" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Vereist muis of aanwijzingsapparaat" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Muis of aanwijzingsapparaat aanbevolen" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Ondersteunt muis of aanwijzingsapparaten" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Onbekende ondersteuning voor muis of aanwijzingsapparaten" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Touchscreen-ondersteuning" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Vereist touchscreen" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Touchscreens aanbevolen" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Ondersteunt touchscreens" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Onbekende ondersteuning voor touchscreens" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Mobiele ondersteuning" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Werkt op mobiele apparaten" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Werkt mogelijk niet goed op mobiele apparaten" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Desktopondersteuning" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Werkt goed op grote schermen" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s werkt het beste op specifieke hardware" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s werkt op de meeste apparaten" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "Doorzoek geïnstalleerde apps" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "Geen Applicaties Gevonden" #: src/bz-installed-page.c:154 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "Geen resultaten gevonden voor \"%s\" in de lijst met geïnstalleerde apps" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Gestopt met ontvangen van updates" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Doe mee" #: src/bz-license-dialog.c:184 msgid "Unknown License" msgstr "Onbekende licentie" #: src/bz-license-dialog.c:187 msgid "Community Built" msgstr "Door Community Gebouwd" #: src/bz-license-dialog.c:235 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Deze app wordt openbaar ontwikkeld door een internationale gemeenschap.\n" "\n" "Je kunt dus deelnemen en helpen om de app nog beter te maken." #: src/bz-license-dialog.c:238 msgid "The license of this app is not known" msgstr "De licentie van deze app is niet bekend" #: src/bz-license-dialog.c:244 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Deze app wordt openbaar ontwikkeld door een internationale community en " "uitgebracht onder de %s licentie.\n" "\n" "Je kunt deelnemen en helpen om de app nog beter te maken." #: src/bz-license-dialog.c:252 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Deze app wordt niet openbaar ontwikkeld, dus alleen de ontwikkelaars weten " "hoe het werkt. De app kan op moeilijk te detecteren manieren onveilig zijn " "en kan zonder toezicht veranderen.\n" "\n" "Je kunt mogelijk niet bijdragen aan deze app." #: src/bz-license-dialog.c:258 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Deze app is ontwikkeld onder de speciale licentie %s.\n" "\n" "Je kunt mogelijk niet bijdragen aan deze app." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Verbind met Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Er Ging Iets Mis" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "Verbind je Flathub-account met Bazaar om je favoriete apps te beheren." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Voltooi" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Hallo, %s!" #: src/bz-preferences-dialog.blp:20 msgid "Preferences" msgstr "Voorkeuren" #: src/bz-preferences-dialog.blp:26 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Netwerkverbinding is gemeten — automatische synchronisatie van " "winkelgegevens is gepauzeerd" #: src/bz-preferences-dialog.blp:27 src/bz-window.blp:491 msgid "Sync Manually" msgstr "Handmatig synchroniseren" #: src/bz-preferences-dialog.blp:32 msgid "Content Filters" msgstr "Content Filters" #: src/bz-preferences-dialog.blp:35 msgid "Free Software Only" msgstr "Alleen Vrije Software" #: src/bz-preferences-dialog.blp:36 msgid "Hide proprietary applications when browsing and searching" msgstr "Verberg propriëtaire applicaties bij browsen en zoeken" #: src/bz-preferences-dialog.blp:40 msgid "Flathub Results Only" msgstr "Alleen Flathub Resultaten" #: src/bz-preferences-dialog.blp:41 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Beperk zoek- en browseresultaten tot applicaties die alleen op Flathub " "beschikbaar zijn" #: src/bz-preferences-dialog.blp:45 msgid "Verified Results Only" msgstr "Alleen Geverifieerde Resultaten" #: src/bz-preferences-dialog.blp:46 msgid "Hide results that are not verified on Flathub" msgstr "Verberg resultaten die niet geverifieerd zijn op Flathub" #: src/bz-preferences-dialog.blp:50 msgid "Hide EOL Apps" msgstr "Verberg EOL-apps" #: src/bz-preferences-dialog.blp:51 msgid "Hide apps which are no longer supported by their developers" msgstr "Verberg apps die niet langer ondersteund worden door hun ontwikkelaars" #: src/bz-preferences-dialog.blp:56 src/bz-window.blp:311 msgid "Search" msgstr "Zoeken" #: src/bz-preferences-dialog.blp:59 msgid "Delay Search Results" msgstr "Vertraag Zoekresultaten" #: src/bz-preferences-dialog.blp:60 msgid "Improve results performance by debouncing search terms" msgstr "Verbeter zoekprestaties door zoektermen te debouncen" #: src/bz-preferences-dialog.blp:65 msgid "Progress Bar" msgstr "Voortgangsbalk" #: src/bz-preferences-dialog.blp:66 msgid "Choose a theme for the progress bar!" msgstr "Kies een thema voor de voortgangsbalk!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Accentkleur" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Pride kleuren" #: src/bz-preferences-dialog.c:34 msgid "Pride Colors (Horizontal)" msgstr "Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:35 msgid "Lesbian Pride Colors" msgstr "Lesbische Pride kleuren" #: src/bz-preferences-dialog.c:36 msgid "Lesbian Pride Colors (Horizontal)" msgstr "Lesbische Pride kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:37 msgid "Male Homosexual Pride Colors" msgstr "Mannelijke Homoseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:38 msgid "Male Homosexual Pride Colors (Horizontal)" msgstr "Mannelijke Homoseksuele Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:39 msgid "Transgender Pride Colors" msgstr "Transgender Pride Kleuren" #: src/bz-preferences-dialog.c:40 msgid "Transgender Pride Colors (Horizontal)" msgstr "Transgender Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:41 msgid "Nonbinary Pride Colors" msgstr "Nonbinaire Pride Kleuren" #: src/bz-preferences-dialog.c:42 msgid "Nonbinary Pride Colors (Horizontal)" msgstr "Nonbinaire Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:43 msgid "Bisexual Pride Colors" msgstr "Biseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:44 msgid "Bisexual Pride Colors (Horizontal)" msgstr "Biseksuele Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:45 msgid "Asexual Pride Colors" msgstr "Aseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:46 msgid "Asexual Pride Colors (Horizontal)" msgstr "Aseksuele Pride Kleuren (Horizontal)" #: src/bz-preferences-dialog.c:47 msgid "Pansexual Pride Colors" msgstr "Panseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:48 msgid "Pansexual Pride Colors (Horizontal)" msgstr "Panseksuele Pride Kleuren (Horizontal)" #: src/bz-preferences-dialog.c:49 msgid "Aromantic Pride Colors" msgstr "Aromantische Pride Kleuren" #: src/bz-preferences-dialog.c:50 msgid "Aromantic Pride Colors (Horizontal)" msgstr "Aromantische Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:51 msgid "Genderfluid Pride Colors" msgstr "Genderfluïde Pride Kleuren" #: src/bz-preferences-dialog.c:52 msgid "Genderfluid Pride Colors (Horizontal)" msgstr "Genderfluïde Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:53 msgid "Polysexual Pride Colors" msgstr "Polyseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:54 msgid "Polysexual Pride Colors (Horizontal)" msgstr "Polyseksuele Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:55 msgid "Omnisexual Pride Colors" msgstr "Omniseksuele Pride Kleuren" #: src/bz-preferences-dialog.c:56 msgid "Omnisexual Pride Colors (Horizontal)" msgstr "Omniseksuele Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:57 msgid "Aroace Pride Colors" msgstr "Aroace Pride Kleuren" #: src/bz-preferences-dialog.c:58 msgid "Aroace Pride Colors (Horizontal)" msgstr "Aroace Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:59 msgid "Agender Pride Colors" msgstr "Agender Pride Kleuren" #: src/bz-preferences-dialog.c:60 msgid "Agender Pride Colors (Horizontal)" msgstr "Agender Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:61 msgid "Genderqueer Pride Colors" msgstr "Genderqueer Pride Kleuren" #: src/bz-preferences-dialog.c:62 msgid "Genderqueer Pride Colors (Horizontal)" msgstr "Genderqueer Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:63 msgid "Intersex Pride Colors" msgstr "Intersekse Pride Kleuren" #: src/bz-preferences-dialog.c:64 msgid "Intersex Pride Colors (Horizontal)" msgstr "Intersekse Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:65 msgid "Demigender Pride Colors" msgstr "Demigender Pride Kleuren" #: src/bz-preferences-dialog.c:66 msgid "Demigender Pride Colors (Horizontal)" msgstr "Demigender Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:67 msgid "Biromantic Pride Colors" msgstr "Biromantische Pride Kleuren" #: src/bz-preferences-dialog.c:68 msgid "Biromantic Pride Colors (Horizontal)" msgstr "Biromantische Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:69 msgid "Disability Pride Colors" msgstr "Disability Pride Kleuren" #: src/bz-preferences-dialog.c:70 msgid "Disability Pride Colors (Horizontal)" msgstr "Disability Pride Kleuren (Horizontaal)" #: src/bz-preferences-dialog.c:71 msgid "Femboy Pride Colors" msgstr "Femboy Pride Kleuren" #: src/bz-preferences-dialog.c:72 msgid "Femboy Pride Colors (Horizontal)" msgstr "Femboy Pride Kleuren (Horizontaal)" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "Versie Geschiedenis" #: src/bz-releases-list.c:136 #, c-format msgid "Version %s" msgstr "Versie %s" #: src/bz-releases-list.c:174 msgid "No details for this release" msgstr "Geen details voor deze versie" #: src/bz-releases-list.c:186 msgid "Get More Information" msgstr "Meer Informatie" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Haal" #: src/bz-safety-calculator.c:77 msgid "Unknown Permissions" msgstr "Onbekende Machtigingen" #: src/bz-safety-calculator.c:78 msgid "Permissions are missing for this app." msgstr "Machtigingen ontbreken voor deze app." #: src/bz-safety-calculator.c:91 msgid "No Permissions" msgstr "Geen machtigingen" #: src/bz-safety-calculator.c:92 msgid "App is fully sandboxed" msgstr "Toepassing bevindt zich volledig in een zandbak" #: src/bz-safety-calculator.c:98 msgid "Network Access" msgstr "Netwerktoegang" #: src/bz-safety-calculator.c:99 msgid "Can access the internet" msgstr "Heeft toegang tot het internet" #: src/bz-safety-calculator.c:101 msgid "No Network Access" msgstr "Geen netwerktoegang" #: src/bz-safety-calculator.c:102 msgid "Cannot access the internet" msgstr "Heeft geen toegang tot het internet" #: src/bz-safety-calculator.c:107 msgid "User Device Access" msgstr "Gebruikerstoegang tot apparaat" #: src/bz-safety-calculator.c:108 msgid "Can access devices such as webcams or gaming controllers" msgstr "Kan toegang verkrijgen tot apparaten zoals webcams of spelcontrollers" #: src/bz-safety-calculator.c:110 msgid "No User Device Access" msgstr "Geen gebruikerstoegang tot apparaat" #: src/bz-safety-calculator.c:111 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Kan geen toegang verkrijgen tot apparaten zoals webcams of spelcontrollers" #: src/bz-safety-calculator.c:116 msgid "Input Device Access" msgstr "Toegang tot invoerapparaten" #: src/bz-safety-calculator.c:117 msgid "Can access input devices" msgstr "Heeft toegang tot invoerapparaten" #: src/bz-safety-calculator.c:123 msgid "Microphone Access and Audio Playback" msgstr "Toegang tot microfoon en audio afspelen" #: src/bz-safety-calculator.c:124 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "Kan naar microfoons luisteren en audio afspelen zonder toestemming te vragen" #: src/bz-safety-calculator.c:130 msgid "System Device Access" msgstr "Systeemtoegang tot apparaat" #: src/bz-safety-calculator.c:131 msgid "Can access system devices which require elevated permissions" msgstr "" "Kan naar microfoons luisteren en audio afspelen zonder toestemming te vragen" #: src/bz-safety-calculator.c:137 msgid "Screen Contents Access" msgstr "Toegang tot scherminhoud" #: src/bz-safety-calculator.c:138 msgid "Can access the contents of the screen or other windows" msgstr "Kan de inhoud van het scherm of andere vensters benaderen" #: src/bz-safety-calculator.c:144 msgid "Legacy Windowing System" msgstr "Verouderd venstersysteem" #: src/bz-safety-calculator.c:145 msgid "Uses a legacy windowing system" msgstr "Gebruikt een verouderd venstersysteem" #: src/bz-safety-calculator.c:151 msgid "Arbitrary Permissions" msgstr "Willekeurige toegangsrechten" #: src/bz-safety-calculator.c:152 msgid "Can acquire arbitrary permissions" msgstr "Kan willekeurige toegangsrechten verkrijgen" #: src/bz-safety-calculator.c:158 msgid "User Settings" msgstr "Gebruikersinstellingen" #: src/bz-safety-calculator.c:159 msgid "Can access and change user settings" msgstr "Heeft toegang tot gebruikersinstellingen en kan die wijzigen" #: src/bz-safety-calculator.c:165 msgid "Full File System Read/Write Access" msgstr "Lees- en schrijftoegang tot volledig bestandssysteem" #: src/bz-safety-calculator.c:166 msgid "Can read and write all data on the file system" msgstr "Kan alle gegevens op het bestandssysteem lezen en schrijven" #: src/bz-safety-calculator.c:173 msgid "Home Folder Read/Write Access" msgstr "Lees- en schrijftoegang tot home map" #: src/bz-safety-calculator.c:174 msgid "Can read and write all data in your home directory" msgstr "Kan alle gegevens in uw persoonlijke map lezen en schrijven" #: src/bz-safety-calculator.c:181 msgid "Full File System Read Access" msgstr "Leestoegang tot volledig bestandssysteem" #: src/bz-safety-calculator.c:182 msgid "Can read all data on the file system" msgstr "Kan alle gegevens op het bestandssysteem lezen" #: src/bz-safety-calculator.c:190 msgid "Home Folder Read Access" msgstr "Leestoegang tot home map" #: src/bz-safety-calculator.c:191 msgid "Can read all data in your home directory" msgstr "Kan alle gegevens in uw home map lezen" #: src/bz-safety-calculator.c:199 msgid "Download Folder Read/Write Access" msgstr "Lees- en schrijftoegang tot downloadmap" #: src/bz-safety-calculator.c:200 msgid "Can read and write all data in your downloads directory" msgstr "Kan alle gegevens in uw downloadmap lezen en schrijven" #: src/bz-safety-calculator.c:210 msgid "Download Folder Read Access" msgstr "Leestoegang tot downloadmap" #: src/bz-safety-calculator.c:211 msgid "Can read all data in your downloads directory" msgstr "Kan alle gegevens in uw downloadmap lezen" #: src/bz-safety-calculator.c:224 msgid "Can read and write all data in the directory" msgstr "Kan alle gegevens in de map lezen en schrijven" #: src/bz-safety-calculator.c:238 msgid "Can read all data in the directory" msgstr "Kan alle gegevens in de map lezen" #: src/bz-safety-calculator.c:253 msgid "No File System Access" msgstr "Geen toegang tot bestandssysteem" #: src/bz-safety-calculator.c:254 msgid "Cannot access the file system at all" msgstr "Heeft geen enkele toegang tot het bestandssysteem" #: src/bz-safety-calculator.c:261 msgid "Uses System Services" msgstr "Gebruikt systeemdiensten" #: src/bz-safety-calculator.c:262 msgid "Can request data from non-portal system services" msgstr "Kan gegevens opvragen van niet-portal-sessiediensten" #: src/bz-safety-calculator.c:268 msgid "Uses Session Services" msgstr "Gebruikt sessiediensten" #: src/bz-safety-calculator.c:269 msgid "Can request data from non-portal session services" msgstr "Kan gegevens opvragen van niet-portal-sessiediensten" #: src/bz-safety-calculator.c:294 msgid "No Service Access" msgstr "Geen diensttoegang" #: src/bz-safety-calculator.c:295 msgid "Cannot access non-portal session or system services at all" msgstr "Heeft geen enkele toegang tot niet-portal-sessie- of systeemdiensten" #: src/bz-safety-calculator.c:303 msgid "Verified App Developer" msgstr "Geverifieerde App-ontwikkelaar" #: src/bz-safety-calculator.c:304 msgid "The developer of this app has been verified to be who they say they are" msgstr "" "De ontwikkelaar van deze app is geverifieerd en is wie ze zeggen te zijn" #: src/bz-safety-calculator.c:313 msgid "Proprietary Code" msgstr "Propriëtaire Code" #: src/bz-safety-calculator.c:314 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "De broncode is niet publiek, dus kan niet onafhankelijk gecontroleerd worden " "en kan onveilig zijn" #: src/bz-safety-calculator.c:324 msgid "Auditable Code" msgstr "Controleerbare Code" #: src/bz-safety-calculator.c:325 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "De broncode is publiek en kan onafhankelijk gecontroleerd worden, wat de app " "waarschijnlijk veiliger maakt" #: src/bz-safety-calculator.c:435 #, c-format msgid "Use the %s System Service" msgstr "Gebruikt de %s-systeemdienst" #: src/bz-safety-calculator.c:439 #, c-format msgid "Use the %s Session Service" msgstr "Gebruikt de %s-sessiedienst" #: src/bz-safety-calculator.c:443 #, c-format msgid "Use the %s Service" msgstr "Gebruikt de %s-dienst" #: src/bz-safety-calculator.c:453 msgid "Can see the non-portal service" msgstr "Kan de niet-portal-dienst zien" #: src/bz-safety-calculator.c:455 msgid "Can talk to the non-portal service" msgstr "Kan praten met de niet-portal-dienst" #: src/bz-safety-calculator.c:457 msgid "Can own the non-portal service" msgstr "Kan eigenaar zijn van de niet-portal-dienst" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Veiligheid" #: src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Veilig" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Gegevens" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Licentie" #: src/bz-safety-dialog.blp:62 msgid "App ID" msgstr "App ID" #: src/bz-safety-dialog.blp:71 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:98 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Deze app gebruikt een verouderde versie van het softwareplatform (SDK) en " "kan bugs of beveiligingskwetsbaarheden bevatten die niet zullen worden " "opgelost." #: src/bz-safety-dialog.c:222 #, c-format msgid "%s is Safe" msgstr "%s is veilig" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s geeft geen onveilige permissies" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s is Probably Safe" msgstr "%s is waarschijnlijk veilig" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s is mogelijk onveilig" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Unsafe" msgstr "%s is onveilig" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Schermafbeeldingen" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Vorige schermafbeelding" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Volgende schermafbeelding" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Afbeelding kopiëren" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Weergave resetten" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Uitzoomen" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Inzoomen" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Schermafbeeldingen carrousel" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Schermafbeeldingsviewer openen" #: src/bz-search-widget.blp:107 msgid "Search Apps, Games, Software" msgstr "Zoek Apps, Games, Software" #: src/bz-search-widget.blp:146 msgid "Categories Unavailable" msgstr "Categorieën niet beschikbaar" #: src/bz-search-widget.blp:147 msgid "Search for apps using the search bar above." msgstr "Zoek naar apps met de zoekbalk hierboven." #: src/bz-search-widget.blp:231 msgid "No Applications Found" msgstr "Geen Applicaties Gevonden" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Geen resultaten voor \"%s\" op Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Gekopieerd!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Kopieer Link" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Open Link" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Tijdlijn" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Installaties:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Kaart" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Totale Installaties" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK Totale Installaties" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d Totale Installaties" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Geen Resultaten Gevonden" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Apps getagd met \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Zoeken mislukt" #: src/bz-transaction-dialog.c:159 msgid "Keep Data" msgstr "Gegevens behouden" #: src/bz-transaction-dialog.c:160 msgid "Allow restoring settings and content" msgstr "Herstel van instellingen en inhoud toestaan" #: src/bz-transaction-dialog.c:169 msgid "Delete Data" msgstr "Data Verwijderen" #: src/bz-transaction-dialog.c:170 msgid "Permanently remove app data to save space" msgstr "App-gegevens permanent verwijderen om ruimte te besparen" #: src/bz-transaction-dialog.c:194 #, c-format msgid "Install %s?" msgstr "%s Installeren?" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Kan extra gedeelde componenten installeren" #: src/bz-transaction-dialog.c:216 #, c-format msgid "Remove %s?" msgstr "%s Verwijderen?" #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Het zal niet mogelijk zijn om %s te gebruiken na deïnstallatie." #: src/bz-transaction-dialog.c:239 #, c-format msgid "“%s” is High Risk" msgstr "“%s” is Hoog Risico" #: src/bz-transaction-dialog.c:240 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Deze app heeft volledige toegang tot je systeem, inclusief al je " "bestanden, browsergeschiedenis, opgeslagen wachtwoorden en meer. Het " "heeft ook toegang tot internet, wat betekent dat het je gegevens naar " "externe partijen kan versturen.\n" "\n" "Omdat de app propriëtair is, kan het ook niet gecontroleerd worden wat het " "doet met deze machtigingen." #: src/bz-transaction-dialog.c:254 msgid "Install Anyway" msgstr "Installeer Toch" #: src/bz-transaction-manager.c:1148 #, c-format msgid "Finished in %.02f seconds" msgstr "Geslaagd in %.02f seconden" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "App Add-on" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Geïnstalleerde Grootte" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "In Afwachting" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "Bezig" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "Voltooid" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "Update" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "Tot nu toe %s overgedragen" #: src/bz-update-dialog.blp:7 msgid "Update Now" msgstr "Update Nu" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Er zijn Updates Beschikbaar" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "De volgende applicaties hebben updates beschikbaar. Wil je deze Installeren?" #: src/bz-update-dialog.c:135 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "%d runtimes en/of add-ons hebben updates. Wil je deze nu installeren?" #: src/bz-update-dialog.c:143 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Daarnaast zullen %d runtimes en/of add-ons worden bijgewerkt." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Restgebruikersgegevens Beheren" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Geen gebruikersgegevens gevonden" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Gebruikersgegevens" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Gebruikersgegevens verwijderd voor %s" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Gebruikersgegevens verwijderen" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Taken" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Stop Bezige Taken" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Geschiedenis Wissen" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Nog Geen Taken" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "Winkelinhoud aan het verversen" #: src/bz-window.blp:271 msgid "Curated" msgstr "Gecureerd" #: src/bz-window.blp:284 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:432 msgid "No background tasks!" msgstr "Geen achtergrondtaken!" #: src/bz-window.blp:490 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Je hebt een netwerkverbinding maar bekijkt een gecachte versie van Flathub" #: src/bz-window.blp:565 msgid "_Login with Flathub" msgstr "_Inloggen met Flathub" #: src/bz-window.blp:571 msgid "_Manage Leftover User Data" msgstr "Restgegevens _Beheren" #: src/bz-window.blp:576 msgid "_Synchronize Remotes" msgstr "Remotes _synchroniseren" #: src/bz-window.blp:617 msgid "Log Out" msgstr "Uitloggen" #: src/bz-window.c:435 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d update beschikbaar" msgstr[1] "%d updates beschikbaar" #: src/bz-window.c:872 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "De mogelijkheid om lokale .flatpak bestanden te inspecteren en te " "installeren komt er binnenkort aan\n" "Flatpak install -bundle jouw-bundle.flatpak\n" "\n" "in de command line" #: src/bz-window.c:1010 msgid "Can't do that right now!" msgstr "Dit is nu niet mogelijk!" #: src/bz-window.c:1080 msgid "Resume Current Tasks" msgstr "Huidige Taken Hervatten" #: src/bz-window.c:1086 msgid "Pause Current Tasks" msgstr "Huidige Taken Pauzeren" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u downloads" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Algemeen" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Open zoekdialoog" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Voorkeuren" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Remotes Synchroniseren" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Schakel Transactiebeheerder" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Toon Snelkoppelingen" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Sluit Af" kolunmi-bazaar-7b9c8e1/po/pl.po000066400000000000000000002737761514314607700165010ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2025 Polish translations for bazaar package # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025, 2026 Microwave msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-25 00:25+0100\n" "PO-Revision-Date: 2026-01-25 11:55+0100\n" "Last-Translator: Marcel Mrówka \n" "Language-Team: Polish <>\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 |" "| n%100>=20) ? 1 : 2);\n" "X-Generator: Lokalize 25.08.2\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Zarządzaj oprogramowaniem flatpak na tym komputerze" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;PackageManager;Discover;Flatpak;Software;Store;ZarządzanieOprogramo" "waniem;Odkrywaj;Odkrywca;Oprogramowanie;Sklep;Bazar;Sklepzaplikacjami;AppStore" ";" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Nowe okno" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Odkrywaj i instaluj aplikacje" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Nowy sklep z aplikacjami z naciskiem na odkrywanie i instalowanie aplikacji " "i dodatków z repozytoriów flatpak, głównie z Flathuba" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Podkreśla też potrzebę wspierania twórców aplikacji na Linuxa. Bazaar " "posiada stronę \"polecane\", która może być konfigurowana przez " "dystrybutorów pozwalając na bardziej lokalne doświadczenia." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:706 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Widok domowy pokazujący aplikacje z Flathuba" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Strona aplikacji Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Strona wyszukiwania" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Strona kategorii" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:696 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Zarządzaj dodatkami" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:483 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:242 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "Usuń" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:250 src/bz-full-view.blp:470 #: src/bz-transaction-dialog.c:213 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Zainstaluj" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:338 src/bz-full-view.c:345 msgid "Age Rating" msgstr "Próg wiekowy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Kreskówkowa przemoc" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Brak informacji o występowaniu kreskówkowej przemocy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Fantastyczna przemoc" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Brak informacji o występowaniu fantastycznej przemocy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Realistyczna przemoc" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Brak informacji o występowaniu realistycznej przemocy" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Przemoc z ukazaniem krwawienia" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Brak informacji o występowaniu przemocy z krwawieniem" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Przemoc seksualna" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Brak informacji o występowaniu przemocy seksualnej" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alkohol" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Brak informacji o występowaniu odniesień do alkoholu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Narkotyki" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Brak informacji o występowaniu odniesień do narkotyków" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tytoń" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Brak informacji o występowaniu odniesień do tytoniu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nagość" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Brak informacji o występowaniu nagości" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Motywy seksualne" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Brak informacji o występowaniu odniesień lub przedstawień natury seksualnej" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Wulgaryzmy" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Brak informacji o występowaniu wulgaryzmów" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Nieodpowiedni humor" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Brak informacji o występowaniu nieodpowiedniego humoru" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Dyskryminacja" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Brak informacji o występowaniu dyskryminacji" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Reklamy" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Brak informacji o występowaniu reklam" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Hazard" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Brak informacji o występowaniu hazardu" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Zakupy" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Brak informacji o możliwości robienia zakupów" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Rozmowy między użytkownikami" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Brak informacji o możliwości rozmawiania z innymi użytkownikami" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Rozmowy głosowe między użytkownikami" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "" "Brak informacji o możliwości prowadzenia rozmów głosowych z innymi " "użytkownikami" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Przekazywanie informacji kontaktowych" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Brak informacji o przekazywaniu nazw użytkowników na portalach " "społecznościowych, czy też adresów e-mail" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Przekazywanie danych osobowych" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "" "Brak informacji o wysyłaniu osobom trzecim danych osobowych użytkowników" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Udostępnianie lokalizacji" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "Brak informacji o udostępnianiu lokalizacji użytkownika z innymi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostytucja" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Brak informacji o występowaniu odniesień do prostytucji" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Cudzołóstwo" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Brak informacji o występowaniu odniesień do cudzołóstwa" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Seksualizowanie postacie" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Brak informacji o występowaniu seksualizowanych postaci" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Profanacja" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Brak informacji o występowaniu odniesień do profanacji" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Zwłoki" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Brak informacji o występowaniu zwłok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Niewolnictwo" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Brak informacji o występowaniu odniesień do niewolnictwa" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Nie zawiera odniesień do narkotyków" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Nie zawiera przekleństw, profanacji i innych rodzajów mocnego języka" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Nie zawiera reklam i możliwości wykonywania zakupów" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Nie zawiera seksu i nagości" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Nie zawiera niekontrolowanej funkcji chatu" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Nie zawiera przemocy" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Używki" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Mocny język" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Pieniądze" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Społeczność" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Przemoc" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:328 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "3+" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s nie posiada progu wiekowego" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s jest odpowiednie dla wszystkich" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s jest odpowiednie dla młodszych dzieci" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s jest odpowiednie dla dzieci" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s jest odpowiednie dla nastolatków" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s jest odpowiednie dla dorosłych" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s jest odpowiednie dla %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:483 msgid "Main Menu" msgstr "Menu główne" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:556 msgid "_Donate to Bazaar ❤️" msgstr "Przekaż _darowiznę ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Odśwież zawartość" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:563 msgid "_Preferences" msgstr "_Preferencje" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:584 msgid "_Keyboard Shortcuts" msgstr "Skróty _klawiszowe" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:589 msgid "_About Bazaar" msgstr "O _aplikacji Bazaar" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:596 msgid "_Quit Bazaar" msgstr "_Zamknij Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Folder systemu %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Podfolder katalogu domowego %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Foldery systemu hostowego" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Konfiguracja systemu hostowego z /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Podfolder pulpitu %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Folder pulpitu" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Podfolder dokumentów %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Folder dokumentów" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Podfolder muzyki %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Folder muzyki" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Podfolder obrazów %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Folder obrazów" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Podfolder publicznego udostępniania %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Folder publicznego udostępniania" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Podfolder filmów %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Folder filmów" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Podfolder szablonów %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Folder szablonów" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Podfolder pamięci podręcznej użytkownika %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Folder pamięci podręcznej" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Podfolder konfiguracji użytkownika %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Folder konfiguracji użytkownika" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Podfolder danych użytkownika %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Folder danych użytkownika" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Podfolder bibliotek użytkownika %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Folder bibliotek użytkownika" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Dostęp systemu plików do %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Nieznana ścieżka systemu plików" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Rozmiar do pobrania" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Ilość do pobrania z internetu" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Rozmiar po instalacji" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Rozmiar na dysku" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Rozmiar danych użytkownika" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Pamięć podręczna, ustawienia i inne dane aplikacji" #. Translators: As in 'The app is installed'. #. Translators: . #: src/bz-app-tile.blp:86 src/bz-full-view.c:292 src/bz-installed-page.blp:86 #: src/bz-window.blp:299 msgid "Installed" msgstr "Zainstalowane" #: src/bz-apps-page.blp:110 msgid "Show All" msgstr "Pokaż wszystkie" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "Wszystkie \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d aplikacji" #: src/bz-application.c:677 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:678 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:709 msgid "translator-credits" msgstr "Marcel Mrówka (Microwave) , 2025, 2026" #: src/bz-application.c:720 msgid "Special Thanks" msgstr "Specjalne podziękowania" #: src/bz-application.c:778 msgid "Logged Out Successfully!" msgstr "Wylogowano pomyślnie!" #: src/bz-application.c:906 msgid "Performing setup..." msgstr "Konfigurowanie..." #: src/bz-application.c:985 src/bz-application.c:994 msgid "Set Up Flathub" msgstr "Skonfiguruj Flathub" #: src/bz-application.c:988 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub nie jest skonfigurowany na tym urządzeniu. Nie będziesz mógł " "przeglądać i instalować aplikacji w Bazaarze, jeśli jest niedostępny.\n" "\n" "Nadal możesz używać Bazaaru do przeglądania i usuwanie już zainstalowanych " "aplikacji." #: src/bz-application.c:993 src/bz-window.c:875 msgid "Later" msgstr "Później" #: src/bz-application.c:1393 src/bz-application.c:3099 msgid "Synchronizing..." msgstr "Synchronizowanie..." #: src/bz-application.c:1534 src/bz-application.c:3095 #, c-format msgid "Receiving %d entries..." msgstr "Otrzymywanie %d wystąpień..." #: src/bz-application.c:1539 msgid "Checking for updates" msgstr "Sprawdzanie dostępności aktualizacji" #: src/bz-application.c:3101 msgid "Indexing Data..." msgstr "Indeksowanie danych..." #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:75 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Puste" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Brak polecanych" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Plik konfiguracji polecanych nie jest dostępny na tym systemie. Możesz nadal " "przeglądać aplikacje na Flathubie." #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Przeglądaj Flathub'a" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Offline" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Przeglądarka" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Informacja o twórcy jest nie dostępna" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Własność identyfikatora aplikacji %s nie została zweryfikowana i może być " "pakietem zbudowanym przez społeczność." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Własność identyfikatora aplikacji %s została zweryfikowana ręcznie przez " "zespół Flathub" #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Własność identyfikatora aplikacji %1$s została zweryfikowana przez %2$s na %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "" "Własność identyfikatora aplikacji %1$s została zweryfikowana przy użyciu " "%2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Własność identyfikatora aplikacji %s została zweryfikowana." #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Wybierz instalację" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Masz zainstalowanych kilka wersji tej aplikacji. Z którą chciałbyś " "kontynuować?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:212 #: src/bz-transaction-dialog.c:241 src/bz-transaction-dialog.c:286 #: src/bz-transaction-dialog.c:595 msgid "Cancel" msgstr "Anuluj" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Tylko dla tego użytkownika" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "ten użytkownik" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "wszyscy użytkownicy" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Wystąpił błąd" #: src/bz-error.c:89 msgid "Close" msgstr "Zamknij" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Kopiuj i zamknij" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Zaloguj się do konta Flathub, aby zarządzać ulubionymi" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Zaloguj" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Liczba polubień" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Odinstaluj" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Wesprzyj tą aplikację" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Usuń z ulubionych" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:85 #: src/bz-window.blp:614 msgid "Favorites" msgstr "Ulubione" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:460 msgid "Toggle transaction sidebar" msgstr "Włącz pasek boczny transakcji" #: src/bz-favorites-page.blp:46 src/bz-transaction-dialog.c:596 msgid "Install All" msgstr "Zainstaluj wszystkie" #: src/bz-favorites-page.blp:63 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Ładowanie" #: src/bz-favorites-page.blp:78 msgid "No Favorites" msgstr "Brak ulubionych" #: src/bz-favorites-page.blp:79 msgid "Applications you mark as favorite will appear here" msgstr "Aplikacje, które oznaczysz jako ulubione będą się tutaj ukazywać" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Wstecz" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Dalej" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Aplikacja dnia" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "Edytowanie" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Mikser" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "Muzyka" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "Gracz" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Nagrywarka" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "Sekwencer" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Tuner" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "Telewizja" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "Emulacja" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "Akcja" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Przygoda" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Automatowe" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Klocki" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Planszówki" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Karciane" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Dla dzieci" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "Logiczne" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "RPG" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Strzelanki" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "Symulacja" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "Sporty" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "Strategiczne" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "Audio i Wideo" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "Multimedia" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Więcej aplikacji multimedialnych" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Narzędzia programistyczne" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Programowanie" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Więcej narzędzi programistycznych" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Edukacja" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Ucz się" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "Więcej aplikacji dot. edukacji" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Gry" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Graj" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "Więcej gier" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "Grafika i fotografia" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Twórz" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Więcej aplikacji dot. grafiki i fotografii" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Narzędzia sieciowe" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Więcej narzędzi sieciowych" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Produktywność" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Pracuj" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Więcej aplikacji dot. produktywności" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "Nauka" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "Więcej aplikacji dot. nauki" #: src/bz-flathub-category.c:128 msgid "System" msgstr "System" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Więcej aplikacji dot. systemu" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "Narzędzia" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Narzędzia" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "Więcej narzędzi" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Trendujące" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Więcej trendujących" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Popularne" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Więcej popularnych" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Niedawno dodane" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Nowe" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Więcej nowych" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Niedawno zaktualizowane" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Zaktualizowane" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "Więcej zaktualizowanych" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Mobilne" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "Więcej mobilnych" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Więcej aplikacji Adwaita" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "Od KDE" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "Więcej aplikacji od KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub nie został dodany" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Nie znaleziono Flathuba na żadnej z twoich instalacji flatpaka." #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub zwrócił błąd" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Spróbuj ponownie połączyć się z Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub jest niedostępny" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Nie mogliśmy się połączyć z Flathub. Nadal możesz wyszukiwać i zarządzać " "aplikacjami." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Wyszukuj aplikacji" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "W biegu" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Aplikacje na twoje urządzenia mobilne z Linuxem" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Więcej aplikacji mobilnych" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "My ​ ♥ gry" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Gry i aplikacje do uruchamiania twoich ulubionych pozycji" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Więcej gier" #: src/bz-flatpak-entry.c:670 msgctxt "Project URL Type" msgid "Project Website" msgstr "Strona projektu" #: src/bz-flatpak-entry.c:674 src/bz-flatpak-entry.c:747 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Issue Tracker" #: src/bz-flatpak-entry.c:679 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:683 msgctxt "Project URL Type" msgid "Help" msgstr "Pomoc" #: src/bz-flatpak-entry.c:687 msgctxt "Project URL Type" msgid "Donate" msgstr "Przekaż darowiznę" #: src/bz-flatpak-entry.c:693 msgctxt "Project URL Type" msgid "Translate" msgstr "Tłumacz" #: src/bz-flatpak-entry.c:697 msgctxt "Project URL Type" msgid "Contact" msgstr "Skontaktuj się" #: src/bz-flatpak-entry.c:701 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kod ĹşrĂłdłowy" #: src/bz-flatpak-entry.c:707 msgctxt "Project URL Type" msgid "Contribute" msgstr "Miej wkład" #: src/bz-flatpak-entry.c:734 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Strona Flathub" #: src/bz-flatpak-entry.c:756 msgctxt "Project URL Type" msgid "Manifest" msgstr "Manifest" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Brak wynikĂłw" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "SprĂłbuj wyszukać coś innego" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Zawartość" #: src/bz-full-view.blp:211 msgid "Support" msgstr "Wesprzyj" #: src/bz-full-view.blp:234 src/bz-full-view.blp:494 msgid "Open" msgstr "OtwĂłrz" #: src/bz-full-view.blp:247 src/bz-full-view.blp:467 msgid "Download & Install Application" msgstr "Pobierz i zainstaluj aplikację" #: src/bz-full-view.blp:262 msgid "Uninstall Application" msgstr "Odinstaluj aplikację" #: src/bz-full-view.blp:277 src/bz-full-view.blp:509 msgid "Install Other Version" msgstr "Zainstaluj inną wersję" #: src/bz-full-view.blp:431 msgid "Downloads/Month" msgstr "Pobrań/miesiąc" #: src/bz-full-view.blp:528 msgid "Stopped Receiving Core Updates" msgstr "Nie otrzymuje podstawowych aktualizacji" #: src/bz-full-view.blp:542 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Ta aplikacja wykorzystuje bibliotekę, ktĂłra juĹź nie otrzymuje aktualizacji " "lub poprawek zabezpieczeń. MoĹźe się stać niebezpieczna." #: src/bz-full-view.blp:631 msgid "Trash Data" msgstr "Przenieś dane do kosza" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "Identyfikatory:" #: src/bz-full-view.c:235 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:242 #, c-format msgid "%.*fM" msgstr "%.*f mln" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:249 #, c-format msgid "%.*fK" msgstr "%.*f tys." #: src/bz-full-view.c:259 #, c-format msgid "%d downloads in the last 30 days" msgstr "%'d pobrań w ciągu ostatnich 30 dni" #. Translators: . #: src/bz-full-view.c:292 msgid "Download" msgstr "Rozmiar do pobrania" #: src/bz-full-view.c:310 #, c-format msgid "Download size of %s" msgstr "Rozmiar do pobrania %s" #: src/bz-full-view.c:343 msgid "All Ages" msgstr "PrĂłg wiekowy" #: src/bz-full-view.c:355 msgid "Age rating information unavailable" msgstr "Informacja o progu wiekowym jest nie dostępna" #: src/bz-full-view.c:360 msgid "Suitable for all ages" msgstr "Odpowiednie od 3 lat" #: src/bz-full-view.c:362 #, c-format msgid "Suitable for ages %d and up" msgstr "Odpowiednie od %d lat" #: src/bz-full-view.c:395 src/bz-full-view.c:400 src/bz-full-view.c:428 #: src/bz-full-view.c:439 msgid "Unknown" msgstr "Nieznane" #: src/bz-full-view.c:405 #, c-format msgid "Free software licensed under %s" msgstr "Wolne oprogramowanie pod licencją %s" #: src/bz-full-view.c:410 msgid "Free software" msgstr "Wolne oprogramowanie" #: src/bz-full-view.c:413 msgid "Proprietary Software" msgstr "Oprogramowanie własnościowe" #: src/bz-full-view.c:416 #, c-format msgid "Special License: %s" msgstr "Licencja specjalna: %s" #: src/bz-full-view.c:433 msgid "Free" msgstr "Wolne" #: src/bz-full-view.c:436 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Własnościowe" #: src/bz-full-view.c:441 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Licencja specjalna" #: src/bz-full-view.c:461 msgid "Adaptive" msgstr "Zmienne" #: src/bz-full-view.c:461 msgid "Desktop Only" msgstr "" "Tylko na\n" "komputery" #: src/bz-full-view.c:467 msgid "Works on desktop, tablets, and phones" msgstr "Działa na komputerach, tabletach i telefonach" #: src/bz-full-view.c:468 msgid "May not work on mobile devices" msgstr "MoĹźe nie działać na urządzeniach mobilnych" #: src/bz-full-view.c:479 msgid "No URL" msgstr "Brak adresu URL" #: src/bz-full-view.c:497 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Ta aplikacja ma licencję FLOSS — oznacza to, Ĺźe jej kod ĹşrĂłdłowy moĹźe być " "audytowany pod kątem bezpieczeństwa." #: src/bz-full-view.c:498 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Ta aplikacja ma licencję własnościową — oznacza to, Ĺźe jej kod ĹşrĂłdłowy jest " "tworzony prywatnie i niezaleĹźne osoby trzecie nie mogą go audytować." #: src/bz-full-view.c:505 msgid "More Apps" msgstr "Więcej aplikacji" #: src/bz-full-view.c:506 #, c-format msgid "More Apps by %s" msgstr "Więcej aplikacji od %s" #: src/bz-full-view.c:513 msgid "Other Apps by this Developer" msgstr "Inne aplikacje od tego twĂłrcy" #: src/bz-full-view.c:515 src/bz-full-view.c:715 #, c-format msgid "Other Apps by %s" msgstr "Inne aplikacje od %s" #: src/bz-full-view.c:524 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s nie jest zainstalowane, lecz nadal ma %s obecnych danych." #: src/bz-full-view.c:597 src/bz-full-view.c:614 msgid "N/A" msgstr "Niedostępne" #: src/bz-full-view.c:604 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Bezpieczna" #: src/bz-full-view.c:606 src/bz-full-view.c:608 msgid "Low Risk" msgstr "Niskie ryzyko" #: src/bz-full-view.c:610 msgid "Medium Risk" msgstr "Średni ryzyko" #: src/bz-full-view.c:612 msgid "High Risk" msgstr "Wysokie ryzyko" #: src/bz-full-view.c:717 msgid "Other Apps" msgstr "Inne aplikacje" #: src/bz-full-view.c:719 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d aplikacja" msgstr[1] "%d aplikacje" msgstr[2] "%d aplikacji" #: src/bz-full-view.c:1058 msgid "Show Less" msgstr "PokaĹź mniej" #: src/bz-full-view.c:1058 msgid "Show More" msgstr "PokaĹź więcej" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Wsparcie sprzętu" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Wsparcie klawiatury" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Wymaga posiadania klawiatury" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Zaleca posiadanie klawiatury" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Wspiera klawiaturę" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Wsparcie klawiatur jest nieznane" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Wsparcie myszki" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Wymaga myszki lub innego urządzenia wskazującego" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Zaleca korzystanie z myszki lub innego urządzenia wskazującego" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Wspiera myszki i inne urządzenia wskazujące" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Wsparcie myszek i innych urządzeń wskazujących jest nieznane" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Wsparcie ekranĂłw dotykowych" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Wymaga ekranu dotykowego" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Zaleca korzystanie z ekranu dotykowego" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Wspira ekrany dotykowe" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Wsparcie ekranĂłw dotykowych jest nieznane" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Wsparcie urządzeń mobilnych" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Działa na urządzeniach mobilnych" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "MoĹźe nie działać najlepiej na urządzeniach mobilnych" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Wspiera komputery" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Doskonale działa na duĹźych ekranach" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s działa najlepiej na konkretnym sprzęcie" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s działa na większości urządzeń" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "Wyszukuj zainstalowanych aplikacji" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "Nie znaleziono aplikacji" #: src/bz-installed-page.c:157 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Brak wynikĂłw dla \"%s\" na liście zainstalowanych aplikacji" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Zatrzymano otrzymywanie wystąpień" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Miej wkład" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "Nieznana licencja" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "Stworzone przez społeczność" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Ta aplikacja jest tworzona jako wolna przez międzynarodową społeczność.\n" "\n" "MoĹźesz mieć wkład w proces tworzenia i ulepszania jej." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "Licencja tej aplikacji jest nieznana." #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Ta aplikacja jest tworzona jako wolna przez międzynarodową społeczność i " "jest wydawana z licencją %s.\n" "\n" "MoĹźesz mieć wkład w ulepszaniu jej." #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Ta aplikacja nie jest tworzona jako wolna, zatem tylko jej twĂłrcy wiedzą jak " "działa. MoĹźe być niewykrywalnie niebezpieczna, oraz zmieniać się bez " "ostrzeĹźenia.\n" "\n" "Nie będziesz mĂłgł mieć wkładu w procesie tworzenia tej aplikacji." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Ta aplikacja jest tworzona i wydawana pod licencją specjalną %s\n" "\n" "Nie wiemy, czy będziesz mĂłgł mieć wkładu w procesie tworzenia jej." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Połącz z Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Coś poszło nie tak" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Zaloguj się swoim kontem Flathub w Bazaarze, aby zarządzać swoimi ulubionymi " "aplikacjami." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Zakończ" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Cześć, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Preferencje" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Wykryto taryfowe połączenie internetowe - zatrzymano automatyczną " "synchronizację danych sklepowych" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:494 msgid "Sync Manually" msgstr "Synchronizuj ręcznie" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Filtry zawartości" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Tylko wolne oprogramowanie" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Ukrywaj aplikacje własnościowe podczas przeglądania i wyszukiwania" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Tylko wyniki z Flathuba" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Limituj wyniki wyszukiwania i przeglądania, tak aby pokazywać tylko " "aplikacje dostępne na Flathubie" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Tylko zweryfikowane wyniki" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Ukrywaj niezweryfikowane aplikacje" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Ukrywaj aplikacje z brakiem wsparcia" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Ukrywaj aplikacje nie otrzymujące juĹź aktualizacji od swoich twĂłrcĂłw" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:314 msgid "Search" msgstr "Wyszukaj" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Opóźniaj wyniki wyszukiwania" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "Ulepsz wydajność wyszukiwania opóźniając wyniki" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Pasek postępu" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Wybierz motyw paska postępu!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Pionowe paski" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from top to bottom" msgstr "Wyświetlaj kolory flag od gĂłry do dołu" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Kolor akcentowy" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Kolory dumy" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Kolory dumy lesbijek" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Kolory dumy mężczyzn homoseksualnych" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Kolory dumy osĂłb transpłciowych" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Kolory dumy osĂłb niebinarnych" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Kolory dumy osĂłb biseksualnych" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Kolory dumy osĂłb aseksualnych" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Kolory dumy osĂłb panseksualnych" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Kolory dumy osĂłb aromantycznych" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Kolory dumy osĂłb genderfluidalnych" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Kolory dumy osĂłb polyseksualnych" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Kolory dumy osĂłb omniseksualnych" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Kolory dumy osĂłb aromantyczno-seksualnych" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Kolory dumy osĂłb bezpłciowych" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Kolory dumy osĂłb genderqueerowych" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Kolory dumy osĂłb interseksualnych" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Kolory dumy osĂłb półpłciowych" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Kolory dumy osĂłb biomantycznych" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Kolory dumy osĂłb niepełnosprawnych" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Kolory dumy fembojĂłw" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Kolory dumy osĂłb neutroidalnych" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "Historia wersji" #: src/bz-releases-list.c:135 #, c-format msgid "Version %s" msgstr "Wersja %s" #: src/bz-releases-list.c:172 msgid "No details for this release" msgstr "Brak szczegółów dla tego wydania" #: src/bz-releases-list.c:184 msgid "Get More Information" msgstr "Dowiedz się więcej" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Pobierz" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "Nieznane uprawnienia" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "Brakuje uprawnień tej aplikacji." #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Brak uprawnień" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "Aplikacja jest w pełni uruchamiana w środowisku piaskownicy" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Dostęp do sieci" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Ma dostęp do internetu" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Nie potrzebuje internetu" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Nie ma dostępu do internetu" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Dostęp do urządzeń uĹźytkownika" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "" "MoĹźe uzyskać dostęp do urządzeń takich jak kamerki internetowe i kontrolery " "do gier" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Brak dostępu do urządzeń uĹźytkownika" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Nie moĹźe uzyskać dostęp do urządzeń takich jak kamerki internetowe i " "kontrolery do gier" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Dostęp do urządzeń wprowadzania" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Ma dostęp do urządzeń wprowadzania" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Dostęp do mikrofonu i odtwarzania dĹşwięku" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "" "MoĹźe słuchać przy uĹźyciu mikrofonĂłw i odtwarzać dĹşwięk bez proszenia o " "pozwolenie" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Dostęp do urządzeń systemowych" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "" "MoĹźe uzyskać dostęp do urządzeń systemowych, ktĂłre wymagają wysokich " "uprawnień" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Dostęp do zawartości ekranu" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Ma dostęp do zawartości ekranu i innych okien" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Przestarzały system okien" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Zawsze wykorzystuje przestarzały system okien (X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "Samowolne uprawnienia" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "MoĹźe uzyskać samowolne uprawnienia" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Ustawienia uĹźytkownika" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Ma dostęp do ustawień uĹźytkownika i moĹźe je zmieniać" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Pełny dostęp do systemu plikĂłw" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "MoĹźe odczytywać i zapisywać wszystkie dane na systemie plikĂłw" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Dostęp do katalogu domowego" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "MoĹźe odczytywać i zapisywać wszystkie dane w twoim katalogu domowym" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Pełny dostęp do odczytu systemu plikĂłw" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "MoĹźe odczytywać wszystkie dane na systemie plikĂłw" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Dostęp do odczytu katalogu domowego" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "MoĹźe odczytywać dane w twoim katalogu domowym" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Dostęp do folderu pobranych" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "MoĹźe odczytywać i zapisywać wszystkie dane w twoim folderze pobranych" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Dostęp do odczytu folderu pobranych" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "MoĹźe odczytywać dane w twoim folderze pobranych" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "MoĹźe odczytywać i zapisywać wszystkie dane w katalogu" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "MoĹźe odczytywać wszystkie dane w katalogu" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Brak dostępu do systemu plikĂłw" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "Absolutnie nie ma dostępu do systemu plikĂłw" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Wykorzystuje usługi systemowe" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "MoĹźe prosić o dane z poza-portalowych usług systemowych" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Usługi sesji uĹźytkownika" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "MoĹźe prosić o dane z poza-portalowych usług" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Brak dostępu do usług" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "Absolutnie nie ma dostępu do usług systemowych, ani sesji" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Zweryfikowany twĂłrca aplikacji" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "" "TwĂłrca tej aplikacji został zweryfikowany pod względem czy są kim za kogo " "się uwaĹźają" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Własnościowy kod" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Kod ĹşrĂłdłowy nie jest publiczny, więc nie moĹźe być niezaleĹźnie audytowany, " "co sprawia, Ĺźe aplikacja moĹźe być niebezpieczna" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Audytowalny" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Kod ĹşrĂłdłowy jest publiczny i moĹźe być niezaleĹźnie audytowany, co sprawia, " "Ĺźe aplikacja jest raczej bardziej bezpieczna" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Korzystaj z usługi systemowej %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Korzystaj z usługi sesji %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Korzystaj z usługi %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "MoĹźe widzieć poza-portalowe usługi" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "MoĹźe rozmawiać z poza-portalowymi usługami" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "MoĹźe posiadać poza-portalowe usługi" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Integracja z globalnym menu" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "MoĹźe wyświetlać swoje menu w globalnym pasku menu" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Integracja z ustawieniami KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "MoĹźe wykryć kiedy ustawienia pulpitu KDE się zmieniają" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Globalne ustawienia KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "MoĹźe odczytywać preferencje pulpitu KDE, rzeczy jak czcionki i kolory" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "Usługa tajemnej pamięci" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "" "MoĹźe przechowywać i otrzymywać swoje hasła korzystając z systemowego pęku kluc" "zy" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Usługa powiadomień pulpitowych" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "MoĹźe wysyłać powiadomienia pulpitowe" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Integracja z zasobnikiem systemowym" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "MoĹźe wyświetlać ikonę w zasobniku systemowym" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Integracja z KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "MoĹźe komunikować się z urządzeniami połączonymi przez KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Bezpieczeństwo" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Szczegóły" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Licencja" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "Identyfikator aplikacji" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:100 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Ta aplikacja wykorzystuje przestarzałą wersję środowiska programowania (SDK) " "i moĹźe zawierać błędy i luki bezpieczeństwa, ktĂłre nie zostaną naprawione." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "Aplikacja %s jest bezpieczna" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "Aplikacja %s nie posiada niebezpiecznych uprawnień" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "Aplikacja %s jest prawdopodobnie bezpieczna" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "Aplikacja %s jest prawdopodobnie niebezpieczna" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "Aplikacja %s jest niebezpieczna" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Zrzuty ekranu" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Wstecz" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Dalej" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Kopiuj obraz" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Zresetuj widok" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Oddal" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "PrzybliĹź" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Karuzela zrzutĂłw ekranu" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "OtwĂłrz przeglądarkę zrzutĂłw ekranu" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Wyszukuj aplikacje, gry i oprogramowanie" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Kategorie są niedostępne" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Wyszukuj aplikacje korzystając z powyĹźszego paska wyszukiwania" #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Nie znaleziono aplikacji" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Brak wynikĂłw dotyczących \"%s\" na Flathubie" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Skopiowano!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Kopiuj łącze" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "OtwĂłrz łącze" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Oś czasowa" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Instaluje:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Świat" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "Całkowicie %.2f mln pobrań" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "Całkowicie %.2f tys. pobrań" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "Całkowicie zainstalowana %'d razy" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Brak wynikĂłw" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplikacje z identyfikatorem \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Wyszukiwanie nie powiodło się" #: src/bz-transaction-dialog.c:166 msgid "Keep Data" msgstr "Zachowaj dane" #: src/bz-transaction-dialog.c:167 msgid "Allow restoring settings and content" msgstr "PozwĂłl na przywracanie ustawień i zawartości" #: src/bz-transaction-dialog.c:176 msgid "Delete Data" msgstr "Usuń dane" #: src/bz-transaction-dialog.c:177 msgid "Permanently remove app data to save space" msgstr "Usuń dane aplikacji na zawsze, aby zaoszczędzić miejsce" #: src/bz-transaction-dialog.c:202 #, c-format msgid "Install %s?" msgstr "Zainstalować %s?" #: src/bz-transaction-dialog.c:207 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Wybierz wersję do zainstalowania. MoĹźe zainstalować dodatkowe współdzielone ko" "mponenty" #: src/bz-transaction-dialog.c:209 msgid "May install additional shared components" msgstr "MoĹźe zainstalować dodatkowe współdzielone komponenty" #: src/bz-transaction-dialog.c:230 #, c-format msgid "Remove %s?" msgstr "Usunąć %s?" #: src/bz-transaction-dialog.c:233 msgid "Select which version to remove." msgstr "Wybierz wersję do usunięcia." #: src/bz-transaction-dialog.c:235 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Nie będzie moĹźna korzystać z %s po odinstalowaniu." #: src/bz-transaction-dialog.c:258 #, c-format msgid "“%s” is High Risk" msgstr "Aplikacja %s jest wysokim zagroĹźeniem" #: src/bz-transaction-dialog.c:262 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Ta aplikacja ma pełny dostęp do twojego systemu, w tym twoich plikĂłw, " "historii przeglądania, zapisanych haseł i wielu innych. Posiada rĂłwnieĹź " "dostęp do internetu, co oznacza, Ĺźe moĹźe wysyłać twoje dane do osĂłb " "trzecich.\n" "\n" "PoniewaĹź ta aplikacja jest własnościowa, nie moĹźe być audytowana pod " "względem tego co robi z tymi uprawnieniami." #: src/bz-transaction-dialog.c:271 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Ta aplikacja wykorzystuje przestarzały system okien X11, ktĂłry pozwala jej " "na rejestrowanie wszystkich wciśnięć klawiszy, robienia zrzutĂłw ekranu i " "monitorowania innych aplikacji Posiada rĂłwnieĹź dostęp do internetu, co " "oznacza, Ĺźe moĹźe wysyłać twoje dane do osĂłb trzecich.\n" "\n" "PoniewaĹź ta aplikacja jest własnościowa, nie moĹźe być audytowana pod " "względem tego co robi z tymi uprawnieniami." #: src/bz-transaction-dialog.c:287 msgid "Install Anyway" msgstr "Zainstaluj mimo to" #: src/bz-transaction-dialog.c:566 msgid "All apps are already installed" msgstr "Wszystkie aplikacje są juĹź zainstalowane" #: src/bz-transaction-dialog.c:568 msgid "OK" msgstr "OK" #: src/bz-transaction-dialog.c:584 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Zainstalować %u aplikację?" msgstr[1] "Zainstalować %u aplikacje?" msgstr[2] "Zainstalować %u aplikacji?" #: src/bz-transaction-dialog.c:592 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Następujące zostanie zainstalowane. Dodatkowe współdzielone składniki mogą " "rĂłwnieĹź być zainstalowane." #: src/bz-transaction-dialog.c:593 #, c-format msgid "%d addons will be installed." msgstr "Dodatki do zainstalowania: %d" #: src/bz-transaction-dialog.c:594 msgid "Additionally, addons will be installed." msgstr "Dodatkowo, następująca liczba dodatkĂłw zostanie zainstalowana: %d." #: src/bz-transaction-manager.c:1150 #, c-format msgid "Finished in %.02f seconds" msgstr "Ukończono w %.02f sek." #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Dodatek aplikacji" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Biblioteka" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Rozmiar po instalacji" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "Oczekujące" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "Trwające" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "Zakończone" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "Aktualizuj" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "Do tej pory przeniesiono %s" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Zarządzaj pozostałymi danymi" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Nie znaleziono danych uĹźytkownika" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Dane uĹźytkownika" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Przeniesiono do kosza dane uĹźytkownika %s" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Przenieś do kosza dane uĹźytkownika" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Zadania" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Zatrzymaj aktywne zadania" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Wyczyść historię" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Brak zadań" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "OdświeĹźanie zawartości" #: src/bz-window.blp:273 msgid "Curated" msgstr "Polecane" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:435 msgid "No background tasks!" msgstr "Brak zadań w tle!" #: src/bz-window.blp:493 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Masz połączenie z internetem, ale przeglądasz wersję Flathuba, ktĂłra została " "zapisana w pamięci twojego komputera" #: src/bz-window.blp:568 msgid "_Login with Flathub" msgstr "Za_loguj się do Flathub" #: src/bz-window.blp:574 msgid "_Manage Leftover User Data" msgstr "Zarządzaj _pozostałymi danymi" #: src/bz-window.blp:579 msgid "_Synchronize Remotes" msgstr "Z_synchronizuj repozytoria" #: src/bz-window.blp:620 msgid "Log Out" msgstr "Wyloguj się" #: src/bz-window.c:440 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d aktualizacja dostepna" msgstr[1] "%d aktualizacje dostępne" msgstr[2] "%d aktualizacji dostępnych" #: src/bz-window.c:734 msgid "You can't remove Bazaar from Bazaar!" msgstr "Nie moĹźesz usunąć Bazaaru z poziomu Bazaaru!" #: src/bz-window.c:871 msgid "Updates Are Available" msgstr "Dostępne są aktualizacje" #: src/bz-window.c:872 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Następujące aplikacje mają dostępne aktualizacje. Czy chcesz je zainstalować?" #: src/bz-window.c:873 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "Jest dostępna następująca liczba aktualizacji dla bibliotek i/lub dodatkĂłw: " "%d. Czy chcesz je zainstalować?" #: src/bz-window.c:874 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "" "Dodatkowo, następująca liczba bibliotek i/lub dodatkĂłw zostanie " "zaktualizowana: %d." #: src/bz-window.c:876 msgid "Update Now" msgstr "Aktualizuj teraz" #: src/bz-window.c:891 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "MoĹźliwość wyświetlania i instalowania lokalnych plikĂłw .flatpak będzie " "niedługo dostępna! Tymczasem, moĹźesz uruchomić z poziomu terminala\n" "\n" "flatpak install --bundle twoj-pakiet.flatpak" #: src/bz-window.c:1030 src/bz-window.c:1080 msgid "Can't do that right now!" msgstr "Nie moĹźesz tego teraz zrobić!" #: src/bz-window.c:1155 msgid "Resume Current Tasks" msgstr "Kontynuuj wykonywanie zadań" #: src/bz-window.c:1161 msgid "Pause Current Tasks" msgstr "Zapauzuj wykonywanie zadań" #: src/bz-world-map.c:587 msgid "Downloads" msgstr "Pobrania" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "OgĂłlne" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "OtwĂłrz okno wyszukiwania" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "OtwĂłrz preferencje" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Zsynchronizuj repozytoria" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Włącz menedĹźera transakcji" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "PokaĹź skrĂłty" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "WyjdĹş" #~ msgid "Pride Colors (Horizontal)" #~ msgstr "Kolory dumy (poziome)" #~ msgid "Lesbian Pride Colors (Horizontal)" #~ msgstr "Kolory dumy lesbijek (poziome)" #~ msgid "Male Homosexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy mężczyzn homoseksualnych (poziome)" #~ msgid "Transgender Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb transpłciowych (poziome)" #~ msgid "Nonbinary Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb niebinarnych (poziome)" #~ msgid "Bisexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb biseksualnych (poziome)" #~ msgid "Asexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb aseksualnych (poziome)" #~ msgid "Pansexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb panseksualnych (poziome)" #~ msgid "Aromantic Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb aromantycznych (poziome)" #~ msgid "Genderfluid Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb genderfluidalnych (poziome)" #~ msgid "Polysexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb polyseksualnych (poziome)" #~ msgid "Omnisexual Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb omniseksualnych (poziome)" #~ msgid "Aroace Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb aromantyczno-seksualnych (poziome)" #~ msgid "Agender Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb bezpłciowych (poziome)" #~ msgid "Genderqueer Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb genderqueerowych (poziome)" #~ msgid "Intersex Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb interseksualnych (poziome)" #~ msgid "Demigender Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb półpłciowych (poziome)" #~ msgid "Biromantic Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb biomantycznych (poziome)" #~ msgid "Disability Pride Colors (Horizontal)" #~ msgstr "Kolory dumy osĂłb niepełnosprawnych (poziome)" #~ msgid "Femboy Pride Colors (Horizontal)" #~ msgstr "Kolory dumy fembojĂłw (poziome)" #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u pobrań" #~ msgid "Hide EOL Entries" #~ msgstr "Ukrywaj wystąpienia z brakiem wsparcia" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "Ukrywaj wystąpienia z brakiem wsparcia" #~ msgid "Only Show Free Software" #~ msgstr "Pokazuj tylko wolne oprogramowanie" #~ msgid "Hide proprietary software" #~ msgstr "Ukrywaj oprogramowanie własnościowe" #~ msgid "Show Only Flathub Content" #~ msgstr "Pokazuj tylko zawartość z Flathuba" #~ msgid "Hide applications which do not originate from Flathub" #~ msgstr "Ukrywaj aplikacje nie pochodzące z Flathuba" #~ msgid "Show Only Verified Content" #~ msgstr "Pokazuj tylko zawartość zweryfikowaną" #~ msgid "Hide applications which are not verified on Flathub" #~ msgstr "Ukrywaj aplikacje nie będące zweryfikowane na Flathubie" #~ msgid "Debounce Search Inputs" #~ msgstr "Opóźniaj wyszukiwanie podczas wpisywania" #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "" #~ "Dodaj opóźnienie przed wyszukiwaniem, aby zapobiec natychmiastowym " #~ "odpowiedziom podczas wpisywania" #~ msgid "Global Progress Bar Theme" #~ msgstr "Globalny motyw paska postępu" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Określa wygląd paska postępu w całej aplikacji" #~ msgid "Saved Window Dimensions" #~ msgstr "Zapisane wymiary okna" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "" #~ "Wymiary okna, ktĂłre zostaną uĹźyte przy następnym uruchomieniu Bazaaru" #~ msgid "?" #~ msgstr "?" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "Ta funkcja jest na ten moment wyłączona. Zalecamy, abyś zainstalował " #~ "Flatseal, aby zarządzać uprawnieniami twoich aplikacji." #~ msgid "Entry Inspector" #~ msgstr "Inspektor wystąpień" #~ msgid "Serialize" #~ msgstr "Serializuj" #~ msgid "Convert to JSON" #~ msgstr "Przekonwertuj na JSON" #~ msgid "More Mobile apps" #~ msgstr "Więcej aplikacji mobilnych" #~ msgid "Bazaar Inspector" #~ msgstr "Inspektor Bazaaru" #~ msgid "Background Task Info:" #~ msgstr "Informacje o zadaniu w tle:" #~ msgid "Enable Global Debug Mode" #~ msgstr "Włącz globalny tryb debugowania" #~ msgid "Active Blocklists" #~ msgstr "Aktywne listy blokowania" #~ msgid "Active Curated-Configs" #~ msgstr "Aktywne konfiguracje strony \"Polecane\"" #~ msgid "All Entry Groups" #~ msgstr "Wszystkie grupy wystąpień" #~ msgid "Filter..." #~ msgstr "Filtruj..." #~ msgid "Decache and Inspect" #~ msgstr "Wyczyść pamięć podręczną i inspektuj" #~ msgid "No Flatpaks Installed" #~ msgstr "Nie zainstalowano Ĺźadnych FlatpakĂłw" #~ msgid "Connect with Flathub" #~ msgstr "Połącz z Flathub" #~ msgid "Inspect UI Entry" #~ msgstr "Zbadaj element interfejsu" #~ msgid "All Debug Actions" #~ msgstr "Wszystkie działania debugowania" #~ msgid "Open Bazaar Inspector" #~ msgstr "OtwĂłrz inspektora Bazaaru" #, c-format #~ msgid "%s is suitable for toddlers" #~ msgstr "%s jest odpowiednie dla małych dzieci" #~ msgid "Size" #~ msgstr "Rozmiar" #~ msgid "Remove User Data" #~ msgstr "Usuń dane uĹźytkownika" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "OdświeĹź" #~ msgid "--- MB" #~ msgstr "--- MB" #~ msgid "Of the size of human DNA" #~ msgstr "rozmiaru DNA człowieka" #~ msgid "3 billion base pairs" #~ msgstr "3 miliardy par zasadowych" #~ msgid "Of the Linux Kernel" #~ msgstr "jądra Linuksa" #~ msgid "linux-6.17.tar.xz" #~ msgstr "linux-6.17.tar.xz" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "komputera naprowadzającego Apollo 11" #~ msgid "Total ROM and RAM" #~ msgstr "RAMu i ROMu razem" #~ msgid "Of the original Super Mario Bros" #~ msgstr "oryginalnej wersji Super Mario Bros" #~ msgid "On the NES" #~ msgstr "na konsoli NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "rozmiaru Wikipedii" #~ msgid "Without any media" #~ msgstr "bez Ĺźadnych multimediĂłw" #~ msgid "Show Git Forge Star Counts" #~ msgstr "PokaĹź ilość gwiazdek na git" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "" #~ "StwierdĹş, czy Bazaar ma prĂłbwać wykryć i pokazać \"ilość gwiazdek\" dla " #~ "projektĂłw w pełwnym widoku" #~ msgid "Mobile Apps" #~ msgstr "Aplikacje mobilne" #~ msgid "Repository Star Count" #~ msgstr "Liczba gwiazdek repozytorium" #, c-format #~ msgid "%.2fM" #~ msgstr "%.2f mln" #, c-format #~ msgid "%.2fK" #~ msgstr "%.2f tys." #~ msgid "Application Details" #~ msgstr "Szczegóły aplikacji" #~ msgid "Display Star Count" #~ msgstr "PokaĹź liczbę gwiazdek repozytorium" #~ msgid "Show the star count of an application's source code repository" #~ msgstr "PokaĹź licznik ukazujący liczbę gwiazdek repozytorium aplikacji" #~ msgid "" #~ "Bazaar can fetch and display the star count from an application's source " #~ "code repository on a remote Git forge. \n" #~ " For projects on GitHub, rate limits may cause them not to appear." #~ msgstr "" #~ "Bazaar moĹźe pokazywać ilość gwiazdek z repozytorium aplikacji na " #~ "serwisach Git. Projekty z repozytoriamu na GitHubie, mogą zostać " #~ "ograniczone,\n" #~ "więc licznik moĹźe się nie pokazać." #~ msgid "Hide proprietary software when searching" #~ msgstr "Ukrywaj oprogramowanie własnościowe podczas wyszukiwania" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "" #~ "Filtruj wyniki wyszukiwania, tak aby pokazywać tylko aplikacje dostępne " #~ "na Flathubie" #~ msgid "Verified by the original developers" #~ msgstr "Zweryfikowane przez oryginalnych twĂłrcĂłw " #~ msgid "End of Life Apps" #~ msgstr "Aplikacje z brakiem wsparcia" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "JoĂŁo Victor (Leal)" #~ msgstr "JoĂŁo Victor (Leal)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "LĂŠane GRASSER" #~ msgstr "LĂŠane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel MrĂłwka (Microwave)" #~ msgstr "Marcel MrĂłwka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Sabri Ünal" #~ msgstr "Sabri Ünal" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "camegone" #~ msgstr "camegone" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "Constructing Flatpak instance..." #~ msgstr "Przygotywywanie instancji Flatpaka..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "Ponowne wykorzystywanie ostatniej instancji Flatpaka..." #~ msgid "Flathub is not registered on this system" #~ msgstr "Flathub nie jest zarejestrwowany na tym komputerze" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "Czy chcesz dodać Flathub do listy repozytoriĂłw flatpak? Jeśli tego nie " #~ "zrobisz strona \"Flathub\" nie będzie dostępna. MoĹźesz to zmienić w " #~ "dowolnym momencie." #~ msgid "Add Flathub" #~ msgstr "Dodaj Flathub" #, c-format #~ msgid "Identifying installed entries..." #~ msgstr "Identyfikowanie zainstalowanych wystąpień..." #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "Rozpoczynanie otrzymywania zdalnych wystąpień odnosząc się do %d list(y) " #~ "blokowania..." #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d z %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "Oczekiwanie na zakończenie indeksowania w tle..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "Zakończono inicjalizację w %0.2f sek." #~ msgid "More actions" #~ msgstr "Więcej zadań" #~ msgid "Run this application" #~ msgstr "Uruchom tą aplikację" #~ msgid "Run" #~ msgstr "Uruchom" #~ msgid "View Store Page" #~ msgstr "PokaĹź stronę sklepową aplikacji" #~ msgid "Settings & user data will be kept" #~ msgstr "Ustawiania i dane uĹźytkownika zostaną zachowane" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "Nie dołączono konfiguracji polecanych aplikacji do Bazaaru. Skontakuj się " #~ "z kanałami pomocy swojej dystrybucji, aby uzyskać pomoc." #~ msgid "Game" #~ msgstr "Gry" #~ msgid "Visual" #~ msgstr "Grafika" #~ msgid "Office" #~ msgstr "Biuro" #~ msgid "Git Forge Star Counts" #~ msgstr "Licznik gwiazdek na git" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "" #~ "Nie posiadanie tokenu dostępu Githuba moĹźe spowodoać blokowanie próśb" #~ msgid "Show Only Flathub Apps" #~ msgstr "Pokazuj tylko aplikacje z Flathuba" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "Poczekaj przez chilkę, aby zmniejszyć obciążenie systemu" #~ msgid "Pride Rainbow Flag" #~ msgstr "Tęczowa flaga dumy" #~ msgid "Bisexual Flag" #~ msgstr "Flaga osĂłb biseksualnych" #~ msgid "Asexual Flag" #~ msgstr "Flaga osĂłb aseksualnych" #~ msgid "Go Home" #~ msgstr "Powróć do strony domowej" #~ msgid "Browse" #~ msgstr "Przeglądaj" #~ msgid "App View" #~ msgstr "Widok aplikacji" #~ msgid "Go Back" #~ msgstr "PowrĂłt" #~ msgid "View curated applications" #~ msgstr "Przeglądaj polecane aplikacje" #~ msgid "View the latest on Flathub" #~ msgstr "Przeglądaj najnowsze z Flathuba" #~ msgid "_Quit Service" #~ msgstr "_Zakończ usługę" #~ msgid "Graphics" #~ msgstr "Grafika" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "Strona domowa" #~ msgid "Share this application" #~ msgstr "Podziel się tą aplikacją" #~ msgid "Excludes shared components" #~ msgstr "Wyklucza współdzielone komponenty" #~ msgid "Source code may not be available" #~ msgstr "Kod ĹşrĂłdłowy, moĹźe nie być dostępny" #~ msgid "Click for details" #~ msgstr "Kliknij, aby uzyskać informacje" #~ msgid "Repositories" #~ msgstr "Repozytoria" #~ msgid "Open in browser" #~ msgstr "OtwĂłrz w przeglądarce" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "%'d miesięcznych pobrań" #~ msgid "Theme" #~ msgstr "Motyw" #~ msgid "Share" #~ msgstr "Podziel się" #~ msgid "Calligraphy application page" #~ msgstr "Strona aplikacji Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "Wykres pobrań Blendera" #~ msgid "Manage Addons" #~ msgstr "Zarządzaj dodatkami" #~ msgid "Open this image in the default image viewer" #~ msgstr "OtwĂłrz ten obraz w domyślnej przeglądarce zdjęć" #~ msgid "Copy this image to the clipboard" #~ msgstr "Skopiuj ten obraz do schowka" #~ msgid "Download Statistics" #~ msgstr "Statystyki pobrań" #~ msgid "Show Downloads Over Time" #~ msgstr "PokaĹź pobrania na przestrzeni czasu" #~ msgid "Remote repo name" #~ msgstr "Nazwa repozytorium" #~ msgid "%B %-d, %Y" #~ msgstr "%-d %B, %Y" #~ msgid "%B %-d" #~ msgstr "%-d %B" #~ msgid "Downloads Over Time" #~ msgstr "Pobrania na przestrzeni czasu" #~ msgid "Updated Size" #~ msgstr "Rozmiar po aktualizacji" #~ msgid "Freed Space" #~ msgstr "Zwolnione miejsce" #~ msgid "Transactions Will Appear Here" #~ msgstr "Tutaj pojawią się transakcje" #~ msgid "Halt the execution of transactions" #~ msgstr "Zatrzymaj wykonywanie transakcji" #~ msgid "Clear all finished transactions" #~ msgstr "Wyczyść wszystkie zakończone transakcje" #~ msgid "Up to date!" #~ msgstr "Wszystko zaktualizowane!" #~ msgid "Confirm Action" #~ msgstr "ZatwierdĹş zadanie" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Masz zamiar usunąć następujący Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Czy na pewno chcesz to zrobić?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "Masz zamiar zainstalować następujący Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Czy na pewno chcesz to zrobić?" #~ msgid "Resume the execution of transactions" #~ msgstr "WznĂłw wykonywanie transakcji" #~ msgid "Pause the execution of transactions" #~ msgstr "Zatrzymaj wykonywanie transakcji" #~ msgid "Apps Of The Week" #~ msgstr "Polecane w tym tygodniu" #, c-format #~ msgid "Released %x" #~ msgstr "Wydano %x" #~ msgid "Minimize Lower Bound" #~ msgstr "Zminimalizuj dolną granicę" #~ msgid "Maximize Upper Bound" #~ msgstr "Zmaksymalizuj gĂłrną granicę" #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "Przeglądarka VCS" #~ msgid "Full Application View" #~ msgstr "Pełny widok aplikacji" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "Zmień co się pokazuje podczas wyświetlania aplikacji" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause " #~ "GitHub to eventually rate limit you." #~ msgstr "" #~ "Jeśli nie posiadasz tokenu dostępu włączenie tego ustawienia moĹźe " #~ "sprawić, Ĺźe Github moĹźe zacząć blokować twoje żądania" #~ msgid "Type to filter" #~ msgstr "Pisz, aby filtrować" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Odrzuć wyniki z licencjami własnościowymi" #~ msgid "Advanced" #~ msgstr "Zaawansowane" #~ msgid "Open this link externally" #~ msgstr "OtwĂłrz to łącze w przeglądarce" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "Otrzymano %'d z %'d wystąpień (minęło %0.1f sek.)" #~ msgid "VCS Forge Star Count" #~ msgstr "Licznik gwiazdek na VCS" #~ msgid "This application does not provide a donation link" #~ msgstr "Ta aplikacja nie posiada łącza do strony przekazywania darowizny" #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try looking at their project page for " #~ "more information." #~ msgstr "" #~ "\"%s\" nie posiada łącza do strony przekazywaina darowizny. Oznacza to, " #~ "Ĺźe nie moĹźesz wesprzeć tej aplikacji. Zajrzyj do a href=\"%s\">strony " #~ "projektu, aby dowiedzieć się więcej." #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try finding their project page for more information." #~ msgstr "" #~ "\"%s\" nie posiada łącza do strony przekazywaina darowizny. Oznacza to, " #~ "Ĺźe nie moĹźesz wesprzeć tej aplikacji. SprĂłbĂłj znaleźć stronę projektu tej " #~ "aplikacji, aby dowiedzieć się więcej." #~ msgid "Installing" #~ msgstr "Instalowanie" #~ msgid "Removing" #~ msgstr "Usuwanie" #~ msgid "Show Animated Background" #~ msgstr "PokaĹź animowane tła" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "" #~ "Wybierz czy chcesz, aby pokazywać animowane tła ikon na stronie domowej" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "Jest to liczba pobrań z ostatnich 30 dni. Naciśnij, aby zobaczyć " #~ "statystyki pobrań tej aplikacji." #~ msgid "How the application looks" #~ msgstr "Jak aplikacja się prezentuje" #~ msgid "Appearance" #~ msgstr "Wygląd" #~ msgid "Show animated background" #~ msgstr "PokaĹź animowane tła" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Proszę skrĂłcić podsumowanie, powinno mieć między 10 a 35 znakĂłw." #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Główne okno Bazaaru pokazujące Blendera" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Microwave" #~ msgstr "Microwave" #~ msgid "Match using regular expressions" #~ msgstr "PorĂłwnywaj uĹźywając zwyczajnych wyraĹźeń" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "Ukryj filtrowanie i sortowanie za efektem przejścia" kolunmi-bazaar-7b9c8e1/po/pt_BR.po000066400000000000000000001773041514314607700170620ustar00rootroot00000000000000# Portuguese translations for bazaar package # Traduçþes em portuguĂŞs brasileiro para o pacote bazaar. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Rin Koito , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-12-12 22:31-0400\n" "PO-Revision-Date: 2025-12-12 22:42-0400\n" "Last-Translator: Rin Koito \n" "Language-Team: Brazilian Portuguese\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:234 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Adicione, remova ou atualize flatpaks neste computador" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistema;GerenciadorDePacotes;Discover;Flatpak;Aplicativos;Loja;" # https://pt.wikipedia.org/wiki/Fim_de_vida_(produto) #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Esconder entradas em fim de vida (EOL)" # https://pt.wikipedia.org/wiki/Fim_de_vida_(produto) #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Esconder entradas em fim de vida (EOL) e entradas dependentes delas" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Show Git Forge Star Counts" msgstr "Exibir a contagem de estrelas de plataformas Git" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the " "full view" msgstr "" "Se deve fazer a tentativa de detectar e mostrar a \"contagem de estrelas\" " "para projetos na visualização completa" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Only Show Free Software" msgstr "Mostrar apenas softwares livres" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Hide proprietary software" msgstr "Ocultar softwares proprietĂĄrios" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Show Only Flathub Content" msgstr "Mostrar Apenas ConteĂşdos do Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Hide applications which do not originate from Flathub" msgstr "Excluir aplicativos que nĂŁo sĂŁo originados do Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:26 msgid "Debounce Search Inputs" msgstr "Entrada de Pesquisa com Atraso" #: data/io.github.kolunmi.Bazaar.gschema.xml:27 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "" "Adiciona um delay antes de pesquisar para evitar mĂşltiplas respostas " "enquanto digita" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "Global Progress Bar Theme" msgstr "Tema da Barra de Progresso Global" #: data/io.github.kolunmi.Bazaar.gschema.xml:52 msgid "Describes the look of the global progress bar" msgstr "Descreve a aparĂŞncia da barra de progresso global" #: data/io.github.kolunmi.Bazaar.gschema.xml:56 msgid "Saved Window Dimensions" msgstr "DimensĂľes da Janela Salvas" #: data/io.github.kolunmi.Bazaar.gschema.xml:57 msgid "The window dimensions to be used by the next Bazaar window" msgstr "" "As dimensĂľes da janela a serem utilizadas pela prĂłxima janela do Bazaar" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Descobrir e instalar aplicativos" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Uma nova loja de aplicativos para o GNOME, focada em descobrir e instalar " "aplicativos e complementos de repositĂłrios de Flatpak, particularmente o " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Isso enfatiza o apoio aos desenvolvedores que tornam o desktop Linux " "possĂ­vel. Bazaar provĂŞ uma seção de \"recomendados\" que pode ser " "configurada por distribuidores para entregar uma experiĂŞncia mais localizada." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "A pĂĄgina inicial exibindo aplicativos do Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "PĂĄgina do aplicativo Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "PĂĄgina de pesquisa" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "PĂĄgina de catergorias" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:716 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Gerenciar ExtensĂľes" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:504 #: src/bz-installed-tile.blp:117 src/bz-transaction-view.blp:213 #: src/bz-window.c:1282 msgid "Remove" msgstr "Remover" #: src/bz-addons-dialog.c:95 src/bz-full-view.blp:276 src/bz-full-view.blp:491 #: src/bz-transaction-view.blp:187 src/bz-window.c:1259 msgid "Install" msgstr "Instalar" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:50 #: src/bz-full-view.c:385 src/bz-full-view.c:392 msgid "Age Rating" msgstr "Classificação Indicativa" #: src/bz-age-rating-dialog.blp:40 src/bz-age-rating-dialog.c:790 msgid "?" msgstr "?" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #: src/bz-age-rating-dialog.c:139 msgid "Cartoon Violence" msgstr "ViolĂŞncia Caricata" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #: src/bz-age-rating-dialog.c:140 msgid "No information regarding cartoon violence" msgstr "Sem informaçþes acerca de violĂŞncia caricata" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #: src/bz-age-rating-dialog.c:143 msgid "Fantasy Violence" msgstr "ViolĂŞncia Fantasiosa" # https://pt.wikipedia.org/wiki/Sistema_de_Classifica%C3%A7%C3%A3o_Indicativa_Brasileiro #: src/bz-age-rating-dialog.c:144 msgid "No information regarding fantasy violence" msgstr "Sem informaçþes acerca de violĂŞncia fantasiosa" #: src/bz-age-rating-dialog.c:147 msgid "Realistic Violence" msgstr "ViolĂŞncia Realista" #: src/bz-age-rating-dialog.c:148 msgid "No information regarding realistic violence" msgstr "Sem informaçþes acerca de violĂŞncia realista" #: src/bz-age-rating-dialog.c:151 msgid "Violence Depicting Bloodshed" msgstr "ViolĂŞncia com Presença de Sangue" #: src/bz-age-rating-dialog.c:152 msgid "No information regarding bloodshed" msgstr "Sem informaçþes acerca de violĂŞncia com presença de sangue" #: src/bz-age-rating-dialog.c:155 msgid "Sexual Violence" msgstr "ViolĂŞncia Sexual" #: src/bz-age-rating-dialog.c:156 msgid "No information regarding sexual violence" msgstr "Sem informaçþes acerca de violĂŞncia sexual" #: src/bz-age-rating-dialog.c:159 msgid "Alcohol" msgstr "Álcool" #: src/bz-age-rating-dialog.c:160 msgid "No information regarding references to alcohol" msgstr "Sem informaçþes acerca de referĂŞncias Ă  ĂĄlcool" #: src/bz-age-rating-dialog.c:163 msgid "Narcotics" msgstr "NarcĂłticos" #: src/bz-age-rating-dialog.c:164 msgid "No information regarding references to illicit drugs" msgstr "Sem informaçþes acerca de referĂŞncias a drogas ilĂ­citas" #: src/bz-age-rating-dialog.c:167 msgid "Tobacco" msgstr "Tabaco" #: src/bz-age-rating-dialog.c:168 msgid "No information regarding references to tobacco products" msgstr "Sem informaçþes acerca de referĂŞncias a produtos de tabaco" #: src/bz-age-rating-dialog.c:171 src/bz-age-rating-dialog.c:358 msgid "Nudity" msgstr "Nudez" #: src/bz-age-rating-dialog.c:172 msgid "No information regarding nudity of any sort" msgstr "Sem informaçþes acerca de nenhum tipo de nudez" #: src/bz-age-rating-dialog.c:175 msgid "Sexual Themes" msgstr "Temas Sexuais" #: src/bz-age-rating-dialog.c:176 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Sem informaçþes acerca de referĂŞncias ou retrataçþes a nenhum tipo de " "natureza sexual" #: src/bz-age-rating-dialog.c:179 msgid "Profanity" msgstr "Profanidade" #: src/bz-age-rating-dialog.c:180 msgid "No information regarding profanity of any kind" msgstr "Sem informaçþes acerca de nenhum tipo de profanidade" #: src/bz-age-rating-dialog.c:183 msgid "Inappropriate Humor" msgstr "Humor Inapropriado" #: src/bz-age-rating-dialog.c:184 msgid "No information regarding inappropriate humor" msgstr "Sem informaçþes acerca de humor inapropriado" #: src/bz-age-rating-dialog.c:187 msgid "Discrimination" msgstr "Discriminação" #: src/bz-age-rating-dialog.c:188 msgid "No information regarding discriminatory language of any kind" msgstr "Sem informaçþes acerca de nenhum tipo de linguagem discriminatĂłria" #: src/bz-age-rating-dialog.c:191 msgid "Advertising" msgstr "Propaganda" #: src/bz-age-rating-dialog.c:192 msgid "No information regarding advertising of any kind" msgstr "Sem informaçþes acerca de nenhum tipo de propaganda" #: src/bz-age-rating-dialog.c:195 msgid "Gambling" msgstr "Apostas ou Jogos de Azar" #: src/bz-age-rating-dialog.c:196 msgid "No information regarding gambling of any kind" msgstr "Sem informaçþes acerca de nenhum tipo de apostas ou jogos de azar" #: src/bz-age-rating-dialog.c:199 msgid "Purchasing" msgstr "Compras" #: src/bz-age-rating-dialog.c:200 msgid "No information regarding the ability to spend money" msgstr "Sem informaçþes acerca de possibilidades de gastar dinheiro" #: src/bz-age-rating-dialog.c:203 msgid "Chat Between Users" msgstr "Mensagens Entre UsuĂĄrios" #: src/bz-age-rating-dialog.c:204 msgid "No information regarding ways to chat with other users" msgstr "Sem informaçþes acerca de formas de se comunicar com outros usuĂĄrios" #: src/bz-age-rating-dialog.c:207 msgid "Audio Chat Between Users" msgstr "Comunicaçþes de Áudio Entre UsuĂĄrios" #: src/bz-age-rating-dialog.c:208 msgid "No information regarding ways to talk with other users" msgstr "" "Sem informaçþes acerca de formas de se comunicar por ĂĄudio com outros " "usuĂĄrios" #: src/bz-age-rating-dialog.c:211 msgid "Contact Details" msgstr "Detalhes de Contato" #: src/bz-age-rating-dialog.c:212 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Sem informaçþes acerca de compartilhamento de nomes de usuĂĄrio de redes " "sociais ou endereços de e-mail" #: src/bz-age-rating-dialog.c:215 msgid "Identifying Information" msgstr "Informaçþes de Identidade" #: src/bz-age-rating-dialog.c:216 msgid "No information regarding sharing of user information with third parties" msgstr "" "Sem informaçþes acerca de compartilhamento de informaçþes de usuĂĄrio com " "terceiros" #: src/bz-age-rating-dialog.c:219 msgid "Location Sharing" msgstr "Compartilhamento de Localização" #: src/bz-age-rating-dialog.c:220 msgid "No information regarding sharing of physical location with other users" msgstr "" "Sem informaçþes acerca de compartilhamento de localização com outros usuĂĄrios" #: src/bz-age-rating-dialog.c:223 msgid "Prostitution" msgstr "Prostituição" #: src/bz-age-rating-dialog.c:224 msgid "No information regarding references to prostitution" msgstr "Sem informaçþes acerca de referĂŞncias a prostituição" #: src/bz-age-rating-dialog.c:227 msgid "Adultery" msgstr "AdultĂŠrio" #: src/bz-age-rating-dialog.c:228 msgid "No information regarding references to adultery" msgstr "Sem informaçþes acerca de referĂŞncias a adultĂŠrio" #: src/bz-age-rating-dialog.c:231 msgid "Sexualized Characters" msgstr "Personagens Sexualizados" #: src/bz-age-rating-dialog.c:232 msgid "No information regarding sexualized characters" msgstr "Sem informaçþes acerca de personagens sexualizados" #: src/bz-age-rating-dialog.c:235 msgid "Desecration" msgstr "Profanação" #: src/bz-age-rating-dialog.c:236 msgid "No information regarding references to desecration" msgstr "Sem informaçþes acerca de referĂŞncias a profanação" #: src/bz-age-rating-dialog.c:239 msgid "Human Remains" msgstr "Restos Humanos" #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Sem informaçþes acerca de restos humanos mortos visĂ­veis" #: src/bz-age-rating-dialog.c:243 msgid "Slavery" msgstr "EscravidĂŁo" #: src/bz-age-rating-dialog.c:244 msgid "No information regarding references to slavery" msgstr "Sem informaçþes acerca de referĂŞncias a escravidĂŁo" #: src/bz-age-rating-dialog.c:307 msgid "Does not include references to drugs" msgstr "NĂŁo inclui referĂŞncias a drogas" #: src/bz-age-rating-dialog.c:309 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "NĂŁo inclui linguagem de teor ofensivo, profanidade e nenhum outro tipo de " "linguagem inapropriada" #: src/bz-age-rating-dialog.c:311 msgid "Does not include ads or monetary transactions" msgstr "NĂŁo inclui anĂşncios ou transaçþes monetĂĄrias" #: src/bz-age-rating-dialog.c:313 msgid "Does not include sex or nudity" msgstr "NĂŁo inclui sexo ou nudez" #: src/bz-age-rating-dialog.c:315 msgid "Does not include uncontrolled chat functionality" msgstr "NĂŁo inclui funcionalidade nĂŁo controlada de comunicação" #: src/bz-age-rating-dialog.c:317 msgid "Does not include violence" msgstr "NĂŁo inclui violĂŞncia" #: src/bz-age-rating-dialog.c:352 msgid "Drugs" msgstr "Drogas" #: src/bz-age-rating-dialog.c:354 msgid "Strong Language" msgstr "Linguagem ImprĂłpria" #: src/bz-age-rating-dialog.c:356 msgid "Money" msgstr "Dinheiro" #: src/bz-age-rating-dialog.c:360 msgid "Social" msgstr "Social" #: src/bz-age-rating-dialog.c:362 msgid "Violence" msgstr "ViolĂŞncia" #: src/bz-age-rating-dialog.c:564 #, c-format msgid "%s • %s" msgstr "%s • %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:752 src/bz-full-view.c:375 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:782 msgctxt "Age rating" msgid "All" msgstr "Livre" #: src/bz-age-rating-dialog.c:846 #, c-format msgid "%s has an unknown age rating" msgstr "%s possui classificação indicativa desconhecida" #: src/bz-age-rating-dialog.c:854 #, c-format msgid "%s is suitable for everyone" msgstr "%s ĂŠ adequado para todos" #: src/bz-age-rating-dialog.c:857 #, c-format msgid "%s is suitable for toddlers" msgstr "%s ĂŠ adequado para crianças de um a trĂŞs anos" #: src/bz-age-rating-dialog.c:860 #, c-format msgid "%s is suitable for young children" msgstr "%s ĂŠ adequado para crianças pequenas" #: src/bz-age-rating-dialog.c:863 #, c-format msgid "%s is suitable for children" msgstr "%s ĂŠ adequado para crianças" #: src/bz-age-rating-dialog.c:866 #, c-format msgid "%s is suitable for teenagers" msgstr "%s ĂŠ adequado para adolecentes" #: src/bz-age-rating-dialog.c:869 #, c-format msgid "%s is suitable for adults" msgstr "%s ĂŠ adequado para adultos" #: src/bz-age-rating-dialog.c:872 #, c-format msgid "%s is suitable for %s" msgstr "%s ĂŠ adequado para %s" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Tamanho do Download" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "Do tamanho do DNA humano" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 bilhĂľes de pares de bases" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "Do Kernel Linux" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "Do computador de orientação da Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "Total de ROM e RAM" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "Do Super Mario Bros original" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "No NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "Do tamanho da Wikipedia" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "Sem nenhuma mĂ­dia" #: src/bz-apps-page.blp:14 src/bz-full-view.blp:43 src/bz-user-data-page.blp:15 #: src/bz-window.blp:426 msgid "Main Menu" msgstr "Menu Principal" #: src/bz-apps-page.blp:17 src/bz-user-data-page.blp:18 src/bz-window.blp:506 msgid "_Donate to Bazaar ❤️" msgstr "_Doar para o Bazaar ❤️" #: src/bz-apps-page.blp:18 src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Recarregar ConteĂşdo" #: src/bz-apps-page.blp:22 src/bz-user-data-page.blp:22 src/bz-window.blp:513 msgid "_Preferences" msgstr "_PreferĂŞncias" #: src/bz-apps-page.blp:23 src/bz-user-data-page.blp:23 src/bz-window.blp:523 msgid "_Keyboard Shortcuts" msgstr "_Atalhos de Teclado" #: src/bz-apps-page.blp:24 src/bz-user-data-page.blp:24 src/bz-window.blp:528 msgid "_About Bazaar" msgstr "_Sobre o Bazaar" #: src/bz-apps-page.blp:28 src/bz-user-data-page.blp:27 src/bz-window.blp:535 msgid "_Quit Bazaar" msgstr "_Sair do Bazaar" #: src/bz-application.c:556 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Esta funcionalidade estĂĄ atualmente desativada. É recomendado baixar e " "instalar o Flatseal para gerenciar permissĂľes de aplicativos." #: src/bz-application.c:638 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:639 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #: src/bz-application.c:661 msgid "Adam Masciola" msgstr "Adam Masciola" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:664 msgid "translator-credits" msgstr "JoĂŁo Victor , 2025\n" "Rin Koito , 2025" #: src/bz-application.c:790 msgid "Performing setup..." msgstr "Realizando configuração" #: src/bz-application.c:869 src/bz-application.c:878 msgid "Set Up Flathub" msgstr "Configurando Flathub" #: src/bz-application.c:872 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub nĂŁo configurado neste sistema. VocĂŞ nĂŁo poderĂĄ navegar e instalar " "aplicativos no Bazaar se estiver indisponĂ­vel.\n" "\n" "VocĂŞ ainda pode utilizar o Bazaar para navegador e remover aplicativos jĂĄ " "instalados." #: src/bz-application.c:877 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Depois" #: src/bz-application.c:1277 msgid "Synchronizing..." msgstr "Sincronizando..." #: src/bz-application.c:1416 #, c-format msgid "Receiving %d entries..." msgstr "Obtendo %d entradas" #: src/bz-application.c:1421 msgid "Checking for updates" msgstr "Verificando atualizaçþes" #: src/bz-curated-view.blp:11 src/bz-flathub-page.blp:19 #: src/bz-full-view.blp:53 src/bz-installed-page.blp:15 #: src/bz-user-data-page.blp:41 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Vazio" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Sem Recomendaçþes" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "NĂŁo hĂĄ informação curada neste sistema. VocĂŞ ainda pode navegar por " "aplicaçþes no Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Navegar Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Offline" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Navegador" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Informaçþes sobre desenvolveres nĂŁo estĂĄ disponĂ­vel" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "A propriedade do ID do aplicativo %s nĂŁo foi verificada e talvez seja um " "pacote da comunidade." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "A propriedade do ID do aplicativo %s foi manualmente verificada pelo time do " "Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %s app ID has been verified by %s on %s." msgstr "" "A propriedade do ID do aplicativo %s foi verificada por %s em %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %s app ID has been verified using %s." msgstr "A propriedade do ID do aplicativo %s foi verificada utilizando %s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "A propriedade do ID do aplicativo %s foi verificada." #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Inspetor de entrada" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Serializar" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Converter para JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Um Erro Ocorreu" #: src/bz-error.c:89 msgid "Close" msgstr "Fechar" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Copiar e Fechar" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Anterior" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "PrĂłximo" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Aplicativo do Dia" #: src/bz-flathub-category.c:78 msgid "Audio & Video" msgstr "Áudio & VĂ­deo" #: src/bz-flathub-category.c:78 msgid "Media" msgstr "MĂ­dia" #: src/bz-flathub-category.c:78 msgid "More Audio & Video" msgstr "Mais Áudio e VĂ­deo" #: src/bz-flathub-category.c:79 msgid "Developer Tools" msgstr "Ferramentas de desenvolvedores" #: src/bz-flathub-category.c:79 msgid "Develop" msgstr "Desenvolver" #: src/bz-flathub-category.c:79 msgid "More Developer Tools" msgstr "Mais Ferramentas de desenvolvedores" #: src/bz-flathub-category.c:80 msgid "Education" msgstr "Educação" #: src/bz-flathub-category.c:80 msgid "Learn" msgstr "Aprender" #: src/bz-flathub-category.c:80 msgid "More Education" msgstr "Mais Educação" #: src/bz-flathub-category.c:81 msgid "Gaming" msgstr "Jogos" #: src/bz-flathub-category.c:81 msgid "Play" msgstr "Jogar" #: src/bz-flathub-category.c:81 msgid "More Gaming" msgstr "Mais Jogos" #: src/bz-flathub-category.c:82 msgid "Graphics & Photography" msgstr "GrĂĄficos e Fotografia" #: src/bz-flathub-category.c:82 msgid "Create" msgstr "Criar" #: src/bz-flathub-category.c:82 msgid "More Graphics & Photography" msgstr "Mais GrĂĄficos e Fotografia" #: src/bz-flathub-category.c:83 msgid "Networking" msgstr "Conectividade" #: src/bz-flathub-category.c:83 msgid "Internet" msgstr "Comunicação" #: src/bz-flathub-category.c:83 msgid "More Networking" msgstr "Mais Comunicação" #: src/bz-flathub-category.c:84 msgid "Productivity" msgstr "Produtividade" #: src/bz-flathub-category.c:84 msgid "Work" msgstr "Trabalho" #: src/bz-flathub-category.c:84 msgid "More Productivity" msgstr "Mais Produtividade" #: src/bz-flathub-category.c:85 msgid "Science" msgstr "CiĂŞncia" #: src/bz-flathub-category.c:85 msgid "More Science" msgstr "Mais CiĂŞncia" #: src/bz-flathub-category.c:86 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:86 msgid "More System" msgstr "Mais Sistema" #: src/bz-flathub-category.c:87 msgid "Utilities" msgstr "UtilitĂĄrios" #: src/bz-flathub-category.c:87 msgid "Tools" msgstr "Ferramentas" #: src/bz-flathub-category.c:87 msgid "More Utilities" msgstr "Mais UtilitĂĄrios" #: src/bz-flathub-category.c:88 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Em Alta" #: src/bz-flathub-category.c:88 msgid "More Trending" msgstr "Mais Em Alta" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populares" #: src/bz-flathub-category.c:89 msgid "More Popular" msgstr "Mais Populares" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Recentemente Adicionados" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:131 msgid "New" msgstr "Novos" #: src/bz-flathub-category.c:90 msgid "More New" msgstr "Mais Novos" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Recentemente Atualizados" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Atualizados" #: src/bz-flathub-category.c:91 msgid "More Updated" msgstr "Mais Atualizados" #: src/bz-flathub-category.c:92 msgid "Mobile" msgstr "Aplicativos MĂłveis" #: src/bz-flathub-category.c:92 msgid "More Mobile" msgstr "Mais Aplicativos MĂłveis" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub nĂŁo Adicionado" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "O repositĂłrio do Flathub nĂŁo foi encontrado por nenhuma de suas instalaçþes " "de Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub retornou um erro" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Tentar conexĂŁo ao Flathub novamente" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub IndisponĂ­vel" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "NĂŁo conseguimos conectar ao Flathub. VocĂŞ ainda pode gerenciar e pesquisar " "por aplicativos." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Procurar Apps" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Em movimento" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Aplicativos para seus telefones e tablets Linux" #: src/bz-flathub-page.blp:293 msgid "More Mobile Apps" msgstr "Mais Aplicativos MĂłveis" #: src/bz-flathub-page.blp:328 msgid "More Mobile apps" msgstr "Mais Aplicativos MĂłveis" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "NĂłs♥Jogos" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Jogos e aplicativos para rodar seus tĂ­tulos favoritos" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Mais Jogos" #: src/bz-flatpak-entry.c:600 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "PĂĄgina do Flathub" #: src/bz-flatpak-entry.c:621 msgctxt "Project URL Type" msgid "Project Website" msgstr "Site do Projeto" #: src/bz-flatpak-entry.c:625 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Rastreador de problemas" #: src/bz-flatpak-entry.c:629 msgctxt "Project URL Type" msgid "FAQ" msgstr "Perguntas Mais Frequentes" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Help" msgstr "Ajuda" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "Donate" msgstr "Doar" #: src/bz-flatpak-entry.c:643 msgctxt "Project URL Type" msgid "Translate" msgstr "Traduzir" #: src/bz-flatpak-entry.c:647 msgctxt "Project URL Type" msgid "Contact" msgstr "Contatar" #: src/bz-flatpak-entry.c:651 msgctxt "Project URL Type" msgid "Source Code" msgstr "CĂłdigo Fonte" #: src/bz-flatpak-entry.c:657 msgctxt "Project URL Type" msgid "Contribute" msgstr "Contribuir" #: src/bz-full-view.blp:20 src/bz-window.blp:126 src/bz-window.blp:403 msgid "Toggle transaction sidebar" msgstr "Alternar barra lateral de transaçþes" #: src/bz-full-view.blp:57 msgid "No Results" msgstr "Sem Resultados" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Tente outro termo de pesquisa" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "ConteĂşdo" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Apoiar" #: src/bz-full-view.blp:230 msgid "Repository Star Count" msgstr "Contagem de Estrelas do RepositĂłrio" #: src/bz-full-view.blp:260 src/bz-full-view.blp:515 msgid "Open" msgstr "Abrir" #: src/bz-full-view.blp:273 src/bz-full-view.blp:488 msgid "Download & Install Application" msgstr "Baixar & Instalar Aplicativo" #: src/bz-full-view.blp:288 msgid "Uninstall Application" msgstr "Desinstalar Aplicativo" #: src/bz-full-view.blp:303 src/bz-full-view.blp:530 msgid "Install Other Version" msgstr "Instalar Outra VersĂŁo" #: src/bz-full-view.blp:327 msgid "Size" msgstr "Tamanho" #: src/bz-full-view.blp:432 msgid "Downloads /mo" msgstr "Downloads /mo" #: src/bz-full-view.blp:549 msgid "Stopped Receiving Core Updates" msgstr "Parou de receber atualizaçþes crĂ­ticas" #: src/bz-full-view.blp:563 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Este aplicativo utiliza um runtime que nĂŁo recebe mais atualizaçþes ou " "atualizaçþes de segurança. Talvez se torne inseguro para uso." #: src/bz-full-view.blp:649 src/bz-window.c:1228 msgid "Delete Data" msgstr "Excluir Dados" #: src/bz-full-view.blp:783 msgid "Tags:" msgstr "Etiquetas:" #: src/bz-full-view.c:301 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:308 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:315 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:325 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d downloads nos Ăşltimos 30 dias" #: src/bz-full-view.c:357 #, c-format msgid "Download size of %s" msgstr "Tamanho do download de %s" #: src/bz-full-view.c:390 msgid "All Ages" msgstr "Todas as idades" #: src/bz-full-view.c:402 msgid "Age rating information unavailable" msgstr "Classificação indicativa indisponĂ­vel" #: src/bz-full-view.c:407 msgid "Suitable for all ages" msgstr "Adequado para todas as idades" #: src/bz-full-view.c:409 #, c-format msgid "Suitable for ages %d and up" msgstr "Adequado para idades de %d anos ou mais" #: src/bz-full-view.c:442 src/bz-full-view.c:447 src/bz-full-view.c:475 #: src/bz-full-view.c:486 msgid "Unknown" msgstr "Desconhecido" #: src/bz-full-view.c:452 #, c-format msgid "Free software licensed under %s" msgstr "Software livre sob a licença %s" #: src/bz-full-view.c:457 msgid "Free software" msgstr "Software Livre" #: src/bz-full-view.c:460 msgid "Proprietary Software" msgstr "Software ProprietĂĄrio" #: src/bz-full-view.c:463 #, c-format msgid "Special License: %s" msgstr "Licença Especial: %s" #: src/bz-full-view.c:480 msgid "Free" msgstr "Livre" #: src/bz-full-view.c:483 src/bz-license-dialog.c:118 msgid "Proprietary" msgstr "ProprietĂĄrio" #: src/bz-full-view.c:488 src/bz-license-dialog.c:120 msgid "Special License" msgstr "Licença Especial" #: src/bz-full-view.c:508 msgid "Adaptive" msgstr "Adaptativo" #: src/bz-full-view.c:508 msgid "Desktop Only" msgstr "Somente Desktop" #: src/bz-full-view.c:514 msgid "Works on desktop, tablets, and phones" msgstr "Funciona em desktops, tablets e celulares" #: src/bz-full-view.c:515 msgid "May not work on mobile devices" msgstr "Talvez nĂŁo funcione em dispositivos mĂłveis" #: src/bz-full-view.c:526 msgid "No URL" msgstr "Sem URL" #: src/bz-full-view.c:544 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Este aplicativo tem uma licença livre e de cĂłdigo aberto, o que significa " "que o cĂłdigo fonte pode ser auditĂĄvel por segurança." #: src/bz-full-view.c:545 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Este aplicativo tem uma licença proprietĂĄria, o que significa que o cĂłdigo " "fonte ĂŠ desenvolvido de maneira privada e nĂŁo pode ser auditĂĄvel por " "terceiros." #: src/bz-full-view.c:552 msgid "More Apps" msgstr "Mais Aplicativos" #: src/bz-full-view.c:553 #, c-format msgid "More Apps by %s" msgstr "Mais Aplicativos de %s" #: src/bz-full-view.c:560 msgid "Other Apps by this Developer" msgstr "Outros Aplicativos Deste Desenvolvedor" #: src/bz-full-view.c:562 src/bz-full-view.c:670 #, c-format msgid "Other Apps by %s" msgstr "Outros Aplicativos de %s" #: src/bz-full-view.c:570 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s nĂŁo estĂĄ instalado, mas ainda possui %s de dados presentes." #: src/bz-full-view.c:672 msgid "Other Apps" msgstr "Outros Aplicativos" #: src/bz-full-view.c:674 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Aplicativo" msgstr[1] "%d Aplicativos" #: src/bz-full-view.c:1036 msgid "Show Less" msgstr "Mostrar Menos" #: src/bz-full-view.c:1036 msgid "Show More" msgstr "Mostrar Mais" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Suporte a Hardware" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Suporte a Teclado" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Precisa de teclado" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Teclado recomendado" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Suporta teclados" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Suporte a teclado desconhecido" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Suporte a mouse" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Precisa de mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Recomenda mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Suporta mouse ou dispositivo de indicação" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Suporte para mouses ou dispositivos de indicação desconhecido" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Suporte a tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Precisa de tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Recomenda tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Suporta tela sensĂ­vel ao toque" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Suporte a telas sensĂ­veis ao toque desconhecido" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Suporte a dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Funciona em dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Talvez nĂŁo funcione bem em dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Suporte a Desktop" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Funciona bem em telas grandes" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s funciona melhor em hardwares especĂ­ficos" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s funciona na maioria dos dispositivos" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Inspetor do Bazaar" #: src/bz-inspector.blp:33 msgid "Background Task Info:" msgstr "Informaçþes de Tarefas em Segundo Plano" #: src/bz-inspector.blp:43 msgid "Enable Global Debug Mode" msgstr "Habilitar Modo de Depuração Global" #: src/bz-inspector.blp:50 msgid "Active Blocklists" msgstr "Listas de Bloqueio Ativas" #: src/bz-inspector.blp:67 msgid "Active Curated-Configs" msgstr "Configuraçþes de Listas Recomendadas Ativas" #: src/bz-inspector.blp:85 msgid "All Entry Groups" msgstr "Todos os Grupos de Entradas" #: src/bz-inspector.blp:93 msgid "Filter..." msgstr "Filtrar..." #: src/bz-inspector.blp:134 msgid "Decache and Inspect" msgstr "Limpar Cache e Inspecionar" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Sem Flatpaks Instalados" #: src/bz-installed-page.blp:25 src/bz-window.blp:298 msgid "Installed" msgstr "Instalados" #: src/bz-installed-page.c:395 msgid "Choose an Installation" msgstr "Escolha uma Instalação" #: src/bz-installed-page.c:398 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "VocĂŞ tem vĂĄrias versĂľes deste aplicativo instaladas. Com qual vocĂŞ gostaria " "de prosseguir? " #: src/bz-installed-page.c:402 src/bz-window.c:1258 src/bz-window.c:1281 msgid "Cancel" msgstr "Cancelar" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Parou de Receber Atualizaçþes" #: src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Apoiar este aplicativo" #: src/bz-license-dialog.blp:160 msgid "Get Involved" msgstr "Envolva-se" #: src/bz-license-dialog.c:107 src/bz-license-dialog.c:112 msgid "Unknown License" msgstr "Licença Desconhecida" #: src/bz-license-dialog.c:115 msgid "Community Built" msgstr "Feito pela Comunidade" #: src/bz-license-dialog.c:148 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Este aplicativo ĂŠ desenvolvido em aberto por uma comunidade internacional e " "ĂŠ distribuĂ­do sob a licença %s.\n" "\n" "VocĂŞ pode participar e ajudar a tornĂĄ-lo ainda melhor." #: src/bz-license-dialog.c:156 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Este aplicativo ĂŠ desenvolvido em aberto por uma comunidade internacional.\n" "\n" "VocĂŞ pode participar e ajudar a o tornar ainda melhor." #: src/bz-license-dialog.c:161 msgid "The license of this app is not known" msgstr "A licença deste aplicativo ĂŠ desconhecida" #: src/bz-license-dialog.c:165 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Este aplicativo nĂŁo ĂŠ desenvolvido em cĂłdigo aberto, entĂŁo somente os " "desenvolvedores sabem como ele funciona. Ele talvez seja inseguro de formas " "que sĂŁo difĂ­ceis de detectar e pode mudar sem supervisĂŁo.\n" "\n" "VocĂŞ talvez nĂŁo possa contribuir para este aplicativo." #: src/bz-license-dialog.c:174 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Este aplicativo ĂŠ desenvolvido sob a licença especial %s.\n" "\n" "VocĂŞ talvez nĂŁo possa contribuir para este aplicativo." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "PreferĂŞncias" #: src/bz-preferences-dialog.blp:23 msgid "Content Filters" msgstr "Filtros de ConteĂşdo" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Somente Software Livre" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications when browsing and searching" msgstr "" "Ocultar aplicativos proprietĂĄrios dos resultados de navegação e pesquisa" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Somente Resultados do Flathub" #: src/bz-preferences-dialog.blp:32 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Limitar resultados de navegação e pesquisa aos aplicativos disponĂ­veis no " "Flathub" #: src/bz-preferences-dialog.blp:36 msgid "Hide EOL Apps" msgstr "Ocultar Aplicativos em fim de vida (EOL)" #: src/bz-preferences-dialog.blp:37 msgid "Hide apps which are no longer supported by their developers" msgstr "" "Ocultar aplicativos que nĂŁo sĂŁo mais suportados por seus desenvolvedores" #: src/bz-preferences-dialog.blp:42 src/bz-window.blp:313 msgid "Search" msgstr "Pesquisar" #: src/bz-preferences-dialog.blp:45 msgid "Delay Search Results" msgstr "Atrasar Resultados de Pesquisa" #: src/bz-preferences-dialog.blp:46 msgid "Improve results performance by debouncing search terms" msgstr "" "Melhorar resultados de performance utilizando debouncing nos termos " "pesquisados" #: src/bz-preferences-dialog.blp:51 msgid "Application Details" msgstr "Detalhes do Aplicativo" #: src/bz-preferences-dialog.blp:54 msgid "Display Star Count" msgstr "Mostrar Contagem de Estrelas" #: src/bz-preferences-dialog.blp:55 msgid "Show the star count of an application's source code repository" msgstr "" "Mostrar a contagem de estrelas do repositĂłrio cĂłdigo fonte da aplicação" #: src/bz-preferences-dialog.blp:80 msgid "Progress Bar" msgstr "Barra de Progresso" #: src/bz-preferences-dialog.blp:81 msgid "Choose a theme for the progress bar!" msgstr "Escolha um tema para a barra de progresso!" #: src/bz-preferences-dialog.blp:116 msgid "" "Bazaar can fetch and display the star count from an application's source " "code repository on a remote Git forge. \n" " For projects on GitHub, rate limits may cause them not to appear." msgstr "" "Bazaar pode verificar e mostrar a contagem de estrelas do repositĂłrio cĂłdigo " "fonte da aplicação em uma forja git externa.\n" " Para projetos no GitHub, limites de taxa talvez façam com que elas nĂŁo " "apareçam." #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Cor de destaque" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Cores de Orgulho" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Cores do Orgulho LĂŠsbico" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Cores do Orgulho TransgĂŞnero" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Cores do Orgulho NĂŁo BinĂĄrio" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Cores do Orgulho Bisexual" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Cores do Orgulho Asexual" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "Cores do Orgulho Pansexual" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Cores do Orgulho Arromântico" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Cores do Orgulho GĂŞnero FluĂ­do" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Cores do Orgulho Polissexual" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Cores do Orgulho Omnissexual" #: src/bz-preferences-dialog.c:44 msgid "Aroace Pride Colors" msgstr "Cores do Orgulho Aroace" #: src/bz-preferences-dialog.c:45 msgid "Agender Pride Colors" msgstr "Cores do Orgulho AgĂŞnero" #: src/bz-preferences-dialog.c:46 msgid "Genderqueer Pride Colors" msgstr "Cores do Orgulho Genderqueer" #: src/bz-preferences-dialog.c:47 msgid "Intersex Pride Colors" msgstr "Cores do Orgulho Intersexo" #: src/bz-preferences-dialog.c:48 msgid "Demigender Pride Colors" msgstr "Cores do Orgulho DemigĂŞnero" #: src/bz-preferences-dialog.c:49 msgid "Biromantic Pride Colors" msgstr "Cores do Orgulho Birromântico" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "HistĂłrico de VersĂŁo" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "VersĂŁo %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "NĂŁo hĂĄ detalhes para este lançamento" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Obter" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Capturas de tela" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Captura de tela anterior" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "PrĂłxima captura de tela" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Copiar Image" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Redefinir Visualização" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Diminuir Zoom" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Aumentar Zoom" #: src/bz-screenshots-carousel.blp:6 msgid "Screenshots Carousel" msgstr "Carrossel de Capturas de Tela" #: src/bz-screenshots-carousel.blp:104 msgid "Open Screenshot Viewer" msgstr "Abrir Visualizador de Imagens" #: src/bz-search-widget.blp:105 msgid "Search Apps, Games, Software" msgstr "Pesquisar Aplicativos, Jogos e Softwares" #: src/bz-search-widget.blp:149 msgid "Categories Unavailable" msgstr "Atualizaçþes IndisponĂ­veis" #: src/bz-search-widget.blp:150 msgid "Search for apps using the search bar above." msgstr "Pesquisa por aplicativos utilizando a barra de pesquisa acima." #: src/bz-search-widget.blp:234 msgid "No Applications Found" msgstr "Nenhum Aplicativo Encontrado" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Sem resultados para \"%s\" no Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Copiado!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Copiar Link" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Abrir Link" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Linha do tempo" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Instalaçþes:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Mundo" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Nenhum Resultado Encontrado" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Aplicativos com a etiqueta \"%s\"" #: src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Aplicativos" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "A pesquisa falhou" #: src/bz-transaction-manager.c:1137 #, c-format msgid "Finished in %.02f seconds" msgstr "ConcluĂ­do em %.02f segundos" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "ExtensĂľes do aplicativo" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Tamanho da Instalação" #: src/bz-transaction-view.blp:200 msgid "Update" msgstr "Atualizar" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "%s transferidos atĂŠ agora" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Pendente" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "Instalar Agora" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Atualizaçþes EstĂŁo DisponĂ­veis" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Os seguintes aplicativos podem ser atualizados. VocĂŞ gostaria de instalĂĄ-los?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d runtimes e/ou extensĂľes podem ser atualizados. VocĂŞ gostaria de instalĂĄ-" "los?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Adicionalmente, %d runtimes e/ou extensĂľes serĂŁo atualizados." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Gerenciar Dados de UsuĂĄrio Restantes" #: src/bz-user-data-page.blp:55 msgid "No User Data" msgstr "Sem Dados de UsuĂĄrio" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Dados de UsuĂĄrio" #: src/bz-user-data-tile.c:144 #, c-format msgid "Removed User Data for %s" msgstr "Remover Dados de UsuĂĄrio para %s" #: src/bz-user-data-tile.blp:74 msgid "Remove User Data" msgstr "Remover Dados de UsuĂĄrio" #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Inspecionar Entrada de UI" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "Depurar todas as açþes" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Tarefas" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Parar Tarefas Ativas" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Limpar HistĂłrico" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Nenhuma Tarefa Ainda" #: src/bz-window.blp:258 msgid "Refreshing Store Content" msgstr "Recarregando o ConteĂşdo da Loja" #: src/bz-window.blp:273 msgid "Curated" msgstr "Recomendados" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:433 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Sua conexĂŁo ĂŠ limitada - sincronização de dados automĂĄtica da loja pausada" #: src/bz-window.blp:434 src/bz-window.blp:443 msgid "Sync Manually" msgstr "Sincronizar Manualmente" #: src/bz-window.blp:442 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "VocĂŞ possui conexĂŁo Ă  internet, mas estĂĄ vendo uma versĂŁo em cache do Flathub" #: src/bz-window.blp:518 msgid "_Manage Leftover User Data" msgstr "_Gerenciar Dados de UsuĂĄrio Restantes" #: src/bz-window.blp:544 msgid "Open Bazaar Inspector" msgstr "Abrir Inspetor do Bazaar" #: src/bz-window.c:475 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d Atualização DisponĂ­vel" msgstr[1] "%d Atualizaçþes DisponĂ­veis" #: src/bz-window.c:970 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "A funcionalidade de inspecionar e instalar pacotes .flatpak estĂĄ chegando em " "breve! Por enquanto, insira\n" "\n" "flatpak install --bundle seu-pacote.flatpak\n" "\n" "em seu terminal." #: src/bz-window.c:1088 msgid "Can't do that right now!" msgstr "NĂŁo consigo fazer isso agora!" #: src/bz-window.c:1219 msgid "Keep Data" msgstr "Manter Dados" #: src/bz-window.c:1220 msgid "Allow restoring settings and content" msgstr "Habilita restauração de configuração e conteĂşdo" #: src/bz-window.c:1229 msgid "Permanently remove app data to save space" msgstr "Remove permanentemente os dados do aplicativo para liberar espaço" #: src/bz-window.c:1252 #, c-format msgid "Install %s?" msgstr "Instalar %s?" #: src/bz-window.c:1255 msgid "May install additional shared components" msgstr "Pode instalar componentes compartilhados adicionais" #: src/bz-window.c:1274 #, c-format msgid "Remove %s?" msgstr "Remover %s?" #: src/bz-window.c:1278 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "NĂŁo serĂĄ possĂ­vel utilizar %s apĂłs ser desinstalado." #: src/bz-window.c:1341 msgid "Resume Current Tasks" msgstr "Retomar Tarefas Atuais" #: src/bz-window.c:1347 msgid "Pause Current Tasks" msgstr "Pausar Tarefas Atuais" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u downloads" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Geral" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Abrir DiĂĄlogo de Pesquisa" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Abrir PreferĂŞncias" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Recarregar" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Alternar Gerenciador de Transaçþes" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Mostrar Atalhos" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Sair" #~ msgid "We ♥ Games" #~ msgstr "NĂłs ♥ Jogos" #, c-format #~ msgid "%.2fM" #~ msgstr "%.2fM" #, c-format #~ msgid "%.2fK" #~ msgstr "%.2fK" #~ msgid "Sync" #~ msgstr "Sincronizar" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "" #~ "Filtra resultados de pesquisa para exibir apenas aplicativos disponĂ­veis " #~ "no Flathub" #~ msgid "Manage Addons" #~ msgstr "Gerenciar ExtensĂľes" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "JoĂŁo Victor (Leal)" #~ msgstr "JoĂŁo Victor (Leal)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "LĂŠane GRASSER" #~ msgstr "LĂŠane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel MrĂłwka (Microwave)" #~ msgstr "Marcel MrĂłwka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Sabri Ünal" #~ msgstr "Sabri Ünal" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "camegone" #~ msgstr "camegone" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "Constructing Flatpak instance..." #~ msgstr "Construindo instância de Flatpak..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "Reutilizando Ăşltima instância de Flatpak..." #~ msgid "Flathub is not registered on this system" #~ msgstr "Flathub nĂŁo estĂĄ registrado neste sistema" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "VocĂŞ gostaria de adicionar o repositĂłrio do Flathub? Se recusar, a pĂĄgina " #~ "do Flathub nĂŁo estarĂĄ disponĂ­vel. VocĂŞ pode alterar isso depois." #~ msgid "Add Flathub" #~ msgstr "Adicionar Flathub" #, c-format #~ msgid "Identifying installed entries..." #~ msgstr "Identificando entradas instaladas..." #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "Iniciando a obtenção de entradas remotas, consultando %d lista(s) de " #~ "bloqueio..." #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d de %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "Aguardando tarefas de indexação em segundo plano..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "Inicialização completada em %0.2f segundos" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "O Bazaar nĂŁo recebeu uma configuração de conteĂşdo recomendado. Contate os " #~ "canais de suporte do seu sistema operacional para receber assistĂŞncia." #~ msgid "Graphics" #~ msgstr "GrĂĄficos" #~ msgid "Office" #~ msgstr "Produtividade" #~ msgctxt "Project URL Type" #~ msgid "Homepage" #~ msgstr "PĂĄgina Inicial" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "" #~ "Este flatpak foi verificado pelos desenvolvedores originais do software." #~ msgid "Share this application" #~ msgstr "Compartilhar este aplicativo" #~ msgid "Excludes shared components" #~ msgstr "Exclui componentes compartilhados" #~ msgid "Source code may not be available" #~ msgstr "O cĂłdigo-fonte pode nĂŁo estar disponĂ­vel" #~ msgid "Click for details" #~ msgstr "Clique para mais detalhes" #~ msgid "Repositories" #~ msgstr "RepositĂłrios" #~ msgid "Open in browser" #~ msgstr "Abrir no navegador" #, c-format #~ msgid "%'d Monthly Downloads" #~ msgstr "%'d Downloads Mensais" #~ msgid "%B %-d, %Y" #~ msgstr "%-d de %B , %Y" #~ msgid "%B %-d" #~ msgstr "%-d de %B" #~ msgid "Run this application" #~ msgstr "Executar este aplicativo" #~ msgid "Run" #~ msgstr "Executar" #~ msgid "View Store Page" #~ msgstr "Visualizar PĂĄgina na Loja" #~ msgid "Git Forge Star Counts" #~ msgstr "Contagem de Estrelas de Plataformas Git" #~ msgid "Not having a GitHub access token may trigger rate limits" #~ msgstr "NĂŁo ter um token de acesso do GitHub pode acionar limites de taxa" #~ msgid "Show Only Flathub Apps" #~ msgstr "Mostrar Apenas Apps Flathub" #~ msgid "Wait for a brief pause to reduce system load" #~ msgstr "Aguarde uma breve pausa para reduzir a carga do sistema" #~ msgid "Theme" #~ msgstr "Tema" #~ msgid "Pride Rainbow Flag" #~ msgstr "Bandeira do Orgulho Arco-Íris" #~ msgid "Bisexual Flag" #~ msgstr "Bandeira Bissexual" #~ msgid "Asexual Flag" #~ msgstr "Bandeira Assexual" #~ msgid "Share" #~ msgstr "Compartilhar" #~ msgid "Loading" #~ msgstr "Carregando" #~ msgid "Browse" #~ msgstr "Navegar" #~ msgid "App View" #~ msgstr "Visualização de Aplicativo" #~ msgid "Go Back" #~ msgstr "Voltar" #~ msgid "View curated applications" #~ msgstr "Ver aplicativos recomendados" #~ msgid "View the latest on Flathub" #~ msgstr "Ver os Ăşltimos do Flathub" #~ msgid "View installed applications" #~ msgstr "Ver aplicativos instalados" #~ msgid "_Quit Service" #~ msgstr "_Sair do Serviço" #~ msgid "Settings & user data will be kept" #~ msgstr "As configuraçþes e os dados do usuĂĄrio serĂŁo mantidos" #~ msgid "Calligraphy application page" #~ msgstr "PĂĄgina de aplicativo de caligragia" #~ msgid "Download graph for Blender" #~ msgstr "GrĂĄfico de Downloads para o Blender" #~ msgid "Open this image in the default image viewer" #~ msgstr "Abra essa imagem no visualizador de imagens padrĂŁo" #~ msgid "Copy this image to the clipboard" #~ msgstr "Copiar para ĂĄrea de transferĂŞncia" #~ msgid "Apps Of The Week" #~ msgstr "Aplicativos da Semana" #~ msgid "App Details" #~ msgstr "Detalhes do App" #~ msgid "Download Statistics" #~ msgstr "EstatĂ­sticas de Download" #~ msgid "Show Downloads Over Time" #~ msgstr "Mostrar downloads ao longo do tempo" #~ msgid "Remote repo name" #~ msgstr "Nome do repositĂłrio remoto" #, c-format #~ msgid "Released %x" #~ msgstr "Lançado em %x" #~ msgid "Downloads Over Time" #~ msgstr "Downloads ao Longo do Tempo" #~ msgid "Minimize Lower Bound" #~ msgstr "Minimizar o Limite Inferior" #~ msgid "Maximize Upper Bound" #~ msgstr "Maximizar o Limite Superior" #~ msgid "Updated Size" #~ msgstr "Tamanho Atualizado" #~ msgid "Freed Space" #~ msgstr "Espaço Liberado" #~ msgid "Transactions Will Appear Here" #~ msgstr "As Transaçþes AparecerĂŁo Aqui" #~ msgid "Halt the execution of transactions" #~ msgstr "Interromper a execução das transaçþes" #~ msgid "Clear all finished transactions" #~ msgstr "Limpar todas as transaçþes finalizadas" #~ msgid "Up to date!" #~ msgstr "JĂĄ estĂĄ atualizado!" #~ msgid "Confirm Action" #~ msgstr "Confirmar Ação" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "VocĂŞ estĂĄ prestes a remover o seguinte Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "VocĂŞ tem certeza?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "VocĂŞ estĂĄ prestes a instalar o seguinte Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "VocĂŞ tem certeza?" #~ msgid "Resume the execution of transactions" #~ msgstr "Retomar a execução de transaçþes" #~ msgid "Pause the execution of transactions" #~ msgstr "Pausar a execução de transaçþes" #~ msgctxt "Project URL Type" #~ msgid "VCS Browser" #~ msgstr "Navegador" #~ msgid "Full Application View" #~ msgstr "Visualização Completa do Aplicativo" #~ msgid "Change what content is shown when viewing applications" #~ msgstr "Mudar qual conteĂşdo ĂŠ mostrado ao visualizar aplicativos" #~ msgid "" #~ "If you do not have an access token, turning this setting on may cause " #~ "GitHub to eventually rate limit you." #~ msgstr "" #~ "Se vocĂŞ nĂŁo tiver um token de acesso, ativar esta configuração pode fazer " #~ "com que o GitHub eventualmente limite suas requisiçþes." #~ msgid "Type to filter" #~ msgstr "Digite para filtrar" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Excluir resultados com licenças proprietĂĄrias" #~ msgid "Advanced" #~ msgstr "Avançado" #~ msgid "Open this link externally" #~ msgstr "Abrir este link externamente" #~ msgid "Finished Tasks" #~ msgstr "Tarefas finalizadas" #, c-format #~ msgid "%s to install" #~ msgstr "%s para instalar" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "" #~ "%'d entradas recebidas de um total de %'d (%0.1f segundos decorridos)" #~ msgid "VCS Forge Star Count" #~ msgstr "Contagem de Estrelas da Plataforma de VCS" #~ msgid "This application does not provide a donation link" #~ msgstr "Este aplicativo nĂŁo provĂŞ um link para doaçþes" #~ msgid "Edit Permissions" #~ msgstr "Editar PermissĂľes" #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try looking at their project page for " #~ "more information." #~ msgstr "" #~ "\"%s\" nĂŁo provĂŞ um link para doaçþes. Isso nĂŁo quer dizer que vocĂŞ nĂŁo " #~ "possĂĄ apoiĂĄ-lo! Tente procurar na pĂĄgina do projeto " #~ "para mais informaçþes." #, c-format #~ msgid "" #~ "\"%s\" does not provide a donations link. This does not mean you cannot " #~ "support them! Try finding their project page for more information." #~ msgstr "" #~ "\"%s\" nĂŁo provĂŞ um link para doaçþes. Isso nĂŁo quer dizer que vocĂŞ nĂŁo " #~ "possĂĄ apoiĂĄ-lo! Tente procurar na pĂĄgina do projeto para mais informaçþes." #~ msgid "Installing" #~ msgstr "Instalando" #~ msgid "Updating" #~ msgstr "Atualizando" #~ msgid "Removing" #~ msgstr "Removendo" #~ msgid "Show Animated Background" #~ msgstr "Mostrar Plano de Fundo Animado" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Se deseja mostrar Ă­cone de plano de fundo animado na pĂĄgina inicial" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Mantenha o resumo curto, entre 10 e 35 caracteres" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Janela principal do Bazaar mostrando o Blender" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "O nĂşmero de downloads dos Ăşltimos 30 dias. Clique para ver as " #~ "estatĂ­sticas de download deste aplicativo." #~ msgid "How the application looks" #~ msgstr "Como o aplicativo se parece" #~ msgid "Appearance" #~ msgstr "AparĂŞncia" #~ msgid "Show animated background" #~ msgstr "Mostrar plano de fundo animado" #~ msgid "Match using regular expressions" #~ msgstr "Corresponder utilizando expressĂľes regulares" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "" #~ "Ocultar filtragem e ordenação usando um efeito de transição crossfade" kolunmi-bazaar-7b9c8e1/po/pt_PT.po000066400000000000000000002564241514314607700171030ustar00rootroot00000000000000# Portuguese translations for bazaar package # Tradução portuguesa (Portugal) para o pacote bazaar. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-27 19:32+0000\n" "PO-Revision-Date: 2025-07-15 11:36+0100\n" "Last-Translator: Eduardo Correia (Azenyr)\n" "Language-Team: Portuguese (Portugal)\n" "Language: pt_PT\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Adicionar, remover ou atualizar software flatpak neste computador" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Sistema;GestorDePacotes;Discover;Flatpak;Aplicaçþes;Loja;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Nova Janela" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Descobrir e instalar aplicaçþes" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 #, fuzzy msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Uma nova loja de aplicaçþes para Linux com foco em descobrir e instalar " "aplicaçþes e extensĂľes (add-ons) a partir de repositĂłrios Flatpak, " "principalmente do Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 #, fuzzy msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Prioritiza o suporte aos desenvolvedores que juntos tornam o Linux em " "computadores possĂ­vel. O Bazaar apresenta a secção \"Recomendadas\" que pode " "ser configurada pelos distribuidores para permitir uma experiĂŞncia mais " "personalizada." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:706 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 #, fuzzy msgid "The home page displaying Flathub apps" msgstr "A vista inicial a demonstrar apps do Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "PĂĄgina da app Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 #, fuzzy msgid "Search page" msgstr "PĂĄgina de pesquisa" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "PĂĄgina das categorias" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:701 #: src/bz-installed-tile.blp:99 #, fuzzy msgid "Manage Add-ons" msgstr "Gerir ExtensĂľes" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:488 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:242 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "Remover" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:255 src/bz-full-view.blp:475 #: src/bz-transaction-dialog.c:213 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Instalar" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:346 src/bz-full-view.c:353 msgid "Age Rating" msgstr "classificação etĂĄria" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "ViolĂŞncia em desenhos animados" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Sem informação sobre violĂŞncia em desenhos animados" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "ViolĂŞncia em fantasia" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Sem informação sobre violĂŞncia em fantasia" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "ViolĂŞncia realista" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Sem informação sobre violĂŞncia realista" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "ViolĂŞncia que mostre sangue" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Sem informação sobre violĂŞncia que mostre sangue" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "ViolĂŞncia sexual" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Sem informação sobre violĂŞncia sexual" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Álcool" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Sem informação sobre referĂŞncias a ĂĄlcool" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "NarcĂłticos (Drogas)" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Sem informação sobre referĂŞncias a drogas" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Tabaco" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Sem informação sobre referĂŞncias a produtos de tabaco" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Nudez" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Sem informação sobre nudez de qualquer tipo" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Temas sexuais" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Sem informação sobre referĂŞncias ou representaçþes de temas sexuais" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Linguagem obscena" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Sem informação sobre uso de linguagem obscena de qualquer tipo" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Humor inapropriado" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Sem informação sobre uso de humor inapropriado" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Discriminação" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Sem informação sobre liguagem discriminatĂłria de qualquer tipo" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Publicidades" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Sem informação sobre publicidade de qualquer tipo" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Apostas (Jogos de azar)" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Sem informação sobre apostas ou jogos de azar de qualquer tipo" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Compras" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Sem informação sobre a possibilidade de gastar dinheiro" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Conversas entre utilizadores" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "" "Sem informação sobre a possibilidade de conversar com outros utilizadores" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Conversas por ĂĄudio entre utilizadores" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Sem informação sobre conversas por ĂĄudio entre utilizadores" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 #, fuzzy msgid "Contact Details" msgstr "Detalhes de contacto" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Sem informação sobre a partilha social de nomes de utilizador ou emails" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Informação pessoal identificĂĄvel" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "Sem informação sobre a partilha de informação pessoal com terceiros" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Partilha de localização" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Sem informação sobre a possibilidade de partilhar a localização fĂ­sica com " "outros utilizadores" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Prostituição" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Sem informação sobre referĂŞncias a prostituição" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "AdultĂŠrio" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Sem informação sobre referĂŞncias a adultĂŠrio" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "ConteĂşdos sexualizados" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Sem informação sobre referĂŞncias a conteĂşdos sexualizados" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 #, fuzzy msgid "Desecration" msgstr "Profanação" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Sem informação sobre referĂŞncias a profanação" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Visibilidade de restos humanos" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Sem informação sobre restos humanos visĂ­veis" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "EscravidĂŁo" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Sem informação sobre referĂŞncias a escravidĂŁo" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "NĂŁo inclui referĂŞncias a uso de drogas" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "NĂŁo inclui liguagem palavrĂľes, asneiras, ou qualquer outro tipo de liguagem " "obscena" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "NĂŁo inclui publicidade ou transaçþes monetĂĄrias" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "NĂŁo inclui sexo nem nudez" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "NĂŁo inclui capacidade de conversas por chat sem controlo" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "NĂŁo inclui violĂŞncia" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Drogas" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Linguagem obscena" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Dinheiro" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Social" #: src/bz-age-rating-dialog.c:479 #, fuzzy msgid "Violence" msgstr "ViolĂŞncia" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:336 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Todas as idades" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s tem uma classificação etĂĄria desconhecida" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s ĂŠ apropriado para todas as idades" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s ĂŠ apropriado para crianças pequenas" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s ĂŠ apropriado para crianças" #: src/bz-age-rating-dialog.c:752 #, fuzzy, c-format msgid "%s is suitable for teenagers" msgstr "%s ĂŠ apropriado para adolescentes" #: src/bz-age-rating-dialog.c:755 #, fuzzy, c-format msgid "%s is suitable for adults" msgstr "%s ĂŠ apropriado para adultos" #: src/bz-age-rating-dialog.c:758 #, fuzzy, c-format msgid "%s is suitable for %s" msgstr "%s ĂŠ apropriado para %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:483 msgid "Main Menu" msgstr "Menu Principal" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:556 msgid "_Donate to Bazaar ❤️" msgstr "_Efetuar uma doação para o Bazaar ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 #, fuzzy msgid "_Refresh Content" msgstr "_Recarregar conteĂşdo" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:563 #, fuzzy msgid "_Preferences" msgstr "_Definiçþes" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:584 msgid "_Keyboard Shortcuts" msgstr "_Atalhos de teclado" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:589 msgid "_About Bazaar" msgstr "_Acerca do bazaar" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:596 #, fuzzy msgid "_Quit Bazaar" msgstr "_Sair do bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Pasta do sistema %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Subpasta pessoal %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Pastas do sistema principal" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Definiçþes do sistema principal provenientes de /etc" #: src/bz-app-permissions.c:169 #, fuzzy, c-format msgid "Desktop subfolder %s" msgstr "Subpasta do ambiente de trabalho %s" #: src/bz-app-permissions.c:170 #, fuzzy msgid "Desktop folder" msgstr "Pasta do computador" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Subpasta documentos %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Pasta documentos" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Subpasta mĂşsica %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Pasta mĂşsica" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Subpasta imagens %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Pasta imagens" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Subpasta partilha %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Pasta partilha" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Subpasta vĂ­deos %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Pasta vĂ­deos" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Subpasta templates %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Pasta templates" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Subpasta cache do utilizador %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Pasta cache do utilizador" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Subpasta das definiçþes do utilizador %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Pasta das definiçþes do utilizador" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Subpasta dos dados do utilizador %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Pasta dos dados do utilizador" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Subpasta runtime do utilizador %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Pasta runtime do utilizador" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Acesso ao sistema de ficheiros para %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Caminho de localização desconhecido" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 #, fuzzy msgid "Download Size" msgstr "Tamanho da transferĂŞncia" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Tamanho para transferĂŞncia da internet" #: src/bz-app-size-dialog.blp:76 #, fuzzy msgid "Installed Size" msgstr "Tamanho da instalação" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Tamanho no disco" #: src/bz-app-size-dialog.blp:99 #, fuzzy msgid "User Data Size" msgstr "Dados de utilizador" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Ficheiros temporĂĄrios, definiçþes e outros dados da app" #. Translators: As in 'The app is installed'. #. Translators: . #: src/bz-app-tile.blp:86 src/bz-full-view.c:295 src/bz-installed-page.blp:86 #: src/bz-window.blp:299 msgid "Installed" msgstr "Instalado" #: src/bz-apps-page.blp:110 msgid "Show All" msgstr "Mostrar tudo" #: src/bz-apps-page.c:243 #, fuzzy, c-format msgid "All \"%s\"" msgstr "Todas de \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, fuzzy, c-format msgid "%d Applications" msgstr "%d aplicaçþes" #: src/bz-application.c:677 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:678 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:709 msgid "translator-credits" msgstr "" #: src/bz-application.c:720 msgid "Special Thanks" msgstr "Agradecimentos especiais" #: src/bz-application.c:778 msgid "Logged Out Successfully!" msgstr "SessĂŁo terminada com sucesso!" #: src/bz-application.c:906 msgid "Performing setup..." msgstr "A configurar..." #: src/bz-application.c:985 src/bz-application.c:994 #, fuzzy msgid "Set Up Flathub" msgstr "Adicionar o Flathub" #: src/bz-application.c:988 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "O Flathub nĂŁo estĂĄ configurado neste sistema. Pode ainda assim navegar e " "instalar apps no Bazaar.\n" "\n" "Pode mesmo assim utilizar o Bazzar para navegar e remover apps jĂĄ instaladas." #: src/bz-application.c:993 src/bz-window.c:875 msgid "Later" msgstr "Mais tarde" #: src/bz-application.c:1393 src/bz-application.c:3072 msgid "Synchronizing..." msgstr "A sincronizar..." #: src/bz-application.c:1534 src/bz-application.c:3068 #, fuzzy, c-format msgid "Receiving %d entries..." msgstr "A receber %d itens..." #: src/bz-application.c:1539 #, fuzzy msgid "Checking for updates" msgstr "A procurar atualizaçþes..." #: src/bz-application.c:3074 msgid "Indexing Data..." msgstr "A indexar dados..." #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:75 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Vazio" #: src/bz-curated-view.blp:15 #, fuzzy msgid "No Curation" msgstr "Sem Aplicaçþes Recomendadas" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "De momento, nĂŁo existe sistema de recomendaçþes configurado neste sistema. " "Pode mesmo assim navegar e instalar aplicaçþes na tab Flathub." #: src/bz-curated-view.blp:18 #, fuzzy msgid "Browse Flathub" msgstr "Navegar pelo Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Sem Ligação (Offline)" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Explorador" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Informaçþes de desenvolvedor nĂŁo disponĂ­veis." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "A propriedade do ID da app %s nĂŁo foi verificada pelo que poderĂĄ ser uma " "aplicação da comunidade." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "A propriedade do ID da app %s foi verificada manualmente pela equipa do " "Flathub." #: src/bz-developer-badge.c:161 #, fuzzy, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "A propriedade do ID da app %s foi verificada por %s em %s" #: src/bz-developer-badge.c:168 #, fuzzy, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "A propriedade do ID da app %s foi verificada usando %s" #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "A propriedade do ID da app %s foi verificado." #: src/bz-entry-group-util.c:73 #, fuzzy msgid "Choose an Installation" msgstr "Escolha uma instalação" #: src/bz-entry-group-util.c:76 #, fuzzy msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Parece que tem mĂşltiplas versĂľes desta app instaladas. Com qual delas " "gostaria de continuar? " #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:212 #: src/bz-transaction-dialog.c:241 src/bz-transaction-dialog.c:286 #: src/bz-transaction-dialog.c:595 msgid "Cancel" msgstr "Cancelar" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Apenas para este utilizador" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "este utilizador" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "todos os utilizadores" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Ocorreu Um Erro" #: src/bz-error.c:89 msgid "Close" msgstr "Fechar" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Copiar e Fechar" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Entre com a conta Flathub para gerir os seus favoritos" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Entrar" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Contagem de favoritos" #: src/bz-favorites-tile.c:172 #, fuzzy msgid "Uninstall" msgstr "Desinstalar" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 #, fuzzy msgid "Support this application" msgstr "Apoiar esta aplicação" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Remover dos favoritos" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:85 #: src/bz-window.blp:614 msgid "Favorites" msgstr "Favoritos" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:460 msgid "Toggle transaction sidebar" msgstr "Alternar a barra lateral de transaçþes" #: src/bz-favorites-page.blp:46 src/bz-transaction-dialog.c:596 #, fuzzy msgid "Install All" msgstr "Instalar" #: src/bz-favorites-page.blp:63 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "A carregar" #: src/bz-favorites-page.blp:78 msgid "No Favorites" msgstr "Sem favoritos" #: src/bz-favorites-page.blp:79 msgid "Applications you mark as favorite will appear here" msgstr "Aplicaçþes que marque como favoritas irĂŁo aparecer aqui" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Anterior" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Seguinte" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "App do Dia" #: src/bz-flathub-category.c:89 #, fuzzy msgid "Editing" msgstr "Edição" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "MIDI" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Mixagem" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "MĂşsica" #: src/bz-flathub-category.c:93 #, fuzzy msgid "Player" msgstr "Jogar" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Gravador" #: src/bz-flathub-category.c:95 #, fuzzy msgid "Sequencer" msgstr "Sequenciador" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Sintetizador" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "TV" #: src/bz-flathub-category.c:102 #, fuzzy msgid "Emulation" msgstr "Emulação" #: src/bz-flathub-category.c:103 #, fuzzy msgid "Action" msgstr "Ação" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Aventura" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Arcada" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Blocos" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Tabuleiro" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Cartas" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Crianças" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "LĂłgica" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "Atuação (Role Playing)" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Tiros" #: src/bz-flathub-category.c:113 #, fuzzy msgid "Simulation" msgstr "Simulação" #: src/bz-flathub-category.c:114 #, fuzzy msgid "Sports" msgstr "Desporto" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "EstratĂŠgia" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "Áudio e VĂ­deo" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "MultimĂŠdia" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Ver mais ĂĄudio e vĂ­deo" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Ferramentas para desenvolvedores" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Desenvolver" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Ver mais ferramentas para desenvolvedores" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Educação" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Aprender" #: src/bz-flathub-category.c:122 #, fuzzy msgid "More Education" msgstr "Ver mais educação" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Jogos" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Jogar" #: src/bz-flathub-category.c:123 #, fuzzy msgid "More Gaming" msgstr "Ver mais jogos" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "GrĂĄficos e fotografia" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Criar" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Ver mais grĂĄficos e fotografia" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Redes e comunicaçþes" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Ver mais redes e comunicaçþes" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Produtividade" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Trabalhar" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Ver mais produtividade" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "CiĂŞncia" #: src/bz-flathub-category.c:127 #, fuzzy msgid "More Science" msgstr "Ver mais ciĂŞncia" #: src/bz-flathub-category.c:128 msgid "System" msgstr "Sistema" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Mais sistema" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "UtilitĂĄrios" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Ferramentas" #: src/bz-flathub-category.c:129 #, fuzzy msgid "More Utilities" msgstr "Ver mais utilitĂĄrios" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "TendĂŞncias" #: src/bz-flathub-category.c:130 #, fuzzy msgid "More Trending" msgstr "Mais tendĂŞncias" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Populares" #: src/bz-flathub-category.c:131 #, fuzzy msgid "More Popular" msgstr "Mais Populares" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Adicionadas Recentemente" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Novas" #: src/bz-flathub-category.c:132 #, fuzzy msgid "More New" msgstr "Ver mais adicionadas recentemente" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Atualizadas Recentemente" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 #, fuzzy msgid "Updated" msgstr "Atualizadas" #: src/bz-flathub-category.c:133 #, fuzzy msgid "More Updated" msgstr "Ver mais atualizadas recentemente" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Mobile" #: src/bz-flathub-category.c:134 #, fuzzy msgid "More Mobile" msgstr "Ver mais mobile" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 #, fuzzy msgid "More Adwaita" msgstr "Ver mais adwaita" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "Apps KDE" #: src/bz-flathub-category.c:136 #, fuzzy msgid "More KDE Apps" msgstr "Ver mais apps KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "O repositĂłrio Flathub nĂŁo foi adicionado" #: src/bz-flathub-page.blp:24 #, fuzzy msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "" "O repositĂłrio Flathub nĂŁo foi encontrado em nenhuma das suas instalaçþes " "Flatpak" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "O Flathub devolveu um erro" #: src/bz-flathub-page.blp:41 #, fuzzy msgid "Retry Flathub Connection" msgstr "Tentar novamente a conexĂŁo com o Flathub" #: src/bz-flathub-page.blp:57 #, fuzzy msgid "Flathub Unavailable" msgstr "Flathub nĂŁo disponĂ­vel" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "NĂŁo foi possĂ­vel conectar com o Flathub. Pode ainda assim gerir e pesquisar " "por aplicaçþes." #: src/bz-flathub-page.blp:61 #, fuzzy msgid "Search Apps" msgstr "Pesquisar aplicaçþes" #: src/bz-flathub-page.blp:270 #, fuzzy msgid "On the Go" msgstr "Fora de casa" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Apps para o seu telemĂłvel e tablet Linux" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 #, fuzzy msgid "More Mobile Apps" msgstr "Mais apps mobile" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Todos ♥ Jogos" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Jogos e apps para gerir e correr os seus jogos favoritos" #: src/bz-flathub-page.blp:435 #, fuzzy msgid "More Games" msgstr "Ver mais jogos" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Sem Resultados" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Tente termos de pesquisa diferentes" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "ConteĂşdo" #: src/bz-full-view.blp:123 msgid "Installing .flatpak bundles is not yet supported" msgstr "A instalação de pacotes .flatpak ainda nĂŁo ĂŠ suportada." #: src/bz-full-view.blp:216 msgid "Support" msgstr "Apoiar" #: src/bz-full-view.blp:239 src/bz-full-view.blp:499 msgid "Open" msgstr "Abrir" #: src/bz-full-view.blp:252 src/bz-full-view.blp:472 #, fuzzy msgid "Download & Install Application" msgstr "Transferir e instalar a aplicação" #: src/bz-full-view.blp:267 #, fuzzy msgid "Uninstall Application" msgstr "Desinstalar a aplicação" #: src/bz-full-view.blp:282 src/bz-full-view.blp:514 msgid "Install Other Version" msgstr "Instalar outra versĂŁo" #: src/bz-full-view.blp:436 #, fuzzy msgid "Downloads/Month" msgstr "TransferĂŞncias/MĂŞs" #: src/bz-full-view.blp:533 msgid "Stopped Receiving Core Updates" msgstr "Deixou de receber atualizaçþes base" #: src/bz-full-view.blp:547 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Esta app usa um runtime (serviço de execução) que jĂĄ nĂŁo estĂĄ a receber " "atualizaçþes nem correçþes de segurança. Pode tornar-se perigoso a usar no " "futuro." #: src/bz-full-view.blp:636 #, fuzzy msgid "Trash Data" msgstr "Dados de utilizador" #: src/bz-full-view.blp:776 msgid "Tags:" msgstr "Etiquetas:" #: src/bz-full-view.c:235 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:242 #, c-format msgid "%.*fM" msgstr "%.*f M" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:249 #, c-format msgid "%.*fK" msgstr "%.*f mil" #: src/bz-full-view.c:259 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d transferĂŞncias nos Ăşltimos 30 dias" #: src/bz-full-view.c:271 src/bz-full-view.c:605 src/bz-full-view.c:622 msgid "N/A" msgstr "N/A" #. Translators: . #: src/bz-full-view.c:295 #, fuzzy msgid "Download" msgstr "Transferir" #: src/bz-full-view.c:315 #, fuzzy msgid "Size information unavailable" msgstr "Classificação etĂĄria nĂŁo disponĂ­vel" #: src/bz-full-view.c:318 #, fuzzy, c-format msgid "Download size of %s" msgstr "%s de tamanho da transferĂŞncia" #: src/bz-full-view.c:351 msgid "All Ages" msgstr "Todas as idades" #: src/bz-full-view.c:363 msgid "Age rating information unavailable" msgstr "Classificação etĂĄria nĂŁo disponĂ­vel" #: src/bz-full-view.c:368 msgid "Suitable for all ages" msgstr "Adequado a todas as idades" #: src/bz-full-view.c:370 #, c-format msgid "Suitable for ages %d and up" msgstr "Adequado a %d anos ou acima" #: src/bz-full-view.c:403 src/bz-full-view.c:408 src/bz-full-view.c:436 #: src/bz-full-view.c:447 msgid "Unknown" msgstr "Desconhecido" #: src/bz-full-view.c:413 #, c-format msgid "Free software licensed under %s" msgstr "Software livre licenciado sob %s" #: src/bz-full-view.c:418 #, fuzzy msgid "Free software" msgstr "Software livre" #: src/bz-full-view.c:421 msgid "Proprietary Software" msgstr "Software proprietĂĄrio" #: src/bz-full-view.c:424 #, c-format msgid "Special License: %s" msgstr "Licença Especial: %s" #: src/bz-full-view.c:441 msgid "Free" msgstr "Livre" #: src/bz-full-view.c:444 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "ProprietĂĄrio" #: src/bz-full-view.c:449 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Licença Especial" #: src/bz-full-view.c:469 msgid "Adaptive" msgstr "AdaptĂĄvel" #: src/bz-full-view.c:469 msgid "Desktop Only" msgstr "Apenas computador" #: src/bz-full-view.c:475 msgid "Works on desktop, tablets, and phones" msgstr "Funciona em computador, tablets e telemĂłveis" #: src/bz-full-view.c:476 msgid "May not work on mobile devices" msgstr "PoderĂĄ nĂŁo funcionar em telemĂłveis" #: src/bz-full-view.c:487 msgid "No URL" msgstr "Sem URL" #: src/bz-full-view.c:505 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Esta aplicação tem uma licença livre de cĂłdigo aberto (FOSS), o que " "significa que o cĂłdigo fonte pode ser auditĂĄvel para verificaçþes de " "segurança." #: src/bz-full-view.c:506 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Esta aplicação tem uma licença proprietĂĄria, o que significa que o cĂłdigo " "fonte ĂŠ privado e nĂŁo pode ser auditĂĄvel nem verificado por terceiros." #: src/bz-full-view.c:513 #, fuzzy msgid "More Apps" msgstr "Mais apps" #: src/bz-full-view.c:514 #, fuzzy, c-format msgid "More Apps by %s" msgstr "Mais apps de %s" #: src/bz-full-view.c:521 msgid "Other Apps by this Developer" msgstr "Outras apps deste desenvolvedor" #: src/bz-full-view.c:523 src/bz-full-view.c:723 #, c-format msgid "Other Apps by %s" msgstr "Outras apps de %s" #: src/bz-full-view.c:532 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s nĂŁo estĂĄ instalado(a), mais ainda tem %s de dados presentes." #: src/bz-full-view.c:612 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Seguro" #: src/bz-full-view.c:614 src/bz-full-view.c:616 msgid "Low Risk" msgstr "Baixo Risco" #: src/bz-full-view.c:618 msgid "Medium Risk" msgstr "MĂŠdio Risco" #: src/bz-full-view.c:620 msgid "High Risk" msgstr "Alto Risco" #: src/bz-full-view.c:725 msgid "Other Apps" msgstr "Outras apps" #: src/bz-full-view.c:727 #, fuzzy, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d aplicação" msgstr[1] "%d aplicaçþes" #: src/bz-full-view.c:1066 msgid "Show Less" msgstr "Mostrar menos" #: src/bz-full-view.c:1066 #, fuzzy msgid "Show More" msgstr "Mostrar mais" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 #, fuzzy msgid "Hardware Support" msgstr "Suporte de hardware" #: src/bz-hardware-support-dialog.c:62 #, fuzzy msgid "Keyboard support" msgstr "Suporte de teclado" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Requer um teclado" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Recomenda um teclado" #: src/bz-hardware-support-dialog.c:66 #, fuzzy msgid "Supports keyboards" msgstr "Suporta teclados" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Suporte a teclados desconhecido" #: src/bz-hardware-support-dialog.c:69 #, fuzzy msgid "Mouse support" msgstr "Suporte a rato" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Requer um rato ou dispositivo de apontar" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Recomenda um rato ou dispostivo de apontar" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Suporta ratos ou dispostivos de apontar" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Suporte a ratos ou dispostivos de apontar desconhecido" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Suporte a ecrĂŁ tĂĄctil" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Requer ecrĂŁ tĂĄctil" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Recomenda ecrĂŁ tĂĄctil" #: src/bz-hardware-support-dialog.c:80 #, fuzzy msgid "Supports touchscreens" msgstr "Suporta ecrĂŁs tĂĄcteis" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Suporte a ecrĂŁs tĂĄcteis desconhecido" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Suporte a dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Funciona em todos os dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Pode nĂŁo funcionar perfeitamente em alguns dispositivos mĂłveis" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Suporte a computador desktop" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Funciona bem em ecrĂŁs grandes" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s funciona melhor em hardware especĂ­fico" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s funciona bem na maior parte dos dispositivos" #: src/bz-installed-page.blp:28 #, fuzzy msgid "Search installed apps" msgstr "Ver as aplicaçþes instaladas" #: src/bz-installed-page.blp:67 #, fuzzy msgid "No Apps Found" msgstr "NĂŁo foram encontradas aplicaçþes" #: src/bz-installed-page.c:157 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Sem resultados para \"%s\" na lista de apps instaladas" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:136 #, fuzzy msgid "Stopped Receiving Updates" msgstr "A transferir itens" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Envolver-se" #: src/bz-license-dialog.c:126 #, fuzzy msgid "Unknown License" msgstr "Licença desconhecida" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "Feito pela comunidade" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Esta app ĂŠ desenvolvida em cĂłdigo aberto por uma comunidade internacional de " "desenvolvedores e apoiantes como vocĂŞ.\n" "\n" "PoderĂĄ participar e ajudar a tornar esta app ainda melhor." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "A licença desta app nĂŁo ĂŠ conhecida" #: src/bz-license-dialog.c:211 #, fuzzy, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Esta app ĂŠ desenvolvida em cĂłdigo aberto por uma comunidade internacional de " "desenvolvedores e apoiantes como vocĂŞ, e publicada sob a licença %s.\n" "\n" "PoderĂĄ participar e ajudar a tornar esta app ainda melhor." #: src/bz-license-dialog.c:219 #, fuzzy msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Esta app nĂŁo ĂŠ desenvolvida com o cĂłdigo aberto, pelo que apenas os seus " "desenvolvedores tĂŞm acesso Ă  forma como a mesma funciona. Isto pode ser " "inseguro em certas formas difĂ­ceis de detectar, e o funcionamento pode mudar " "sem aviso prĂŠvio.\n" "\n" "PoderĂĄ ou nĂŁo conseguir contribuir para o desenvolvimento desta app." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Esta app foi desenvolvida sub a licença especial %s.\n" "\n" "PoderĂĄ ou nĂŁo conseguir contribuir para o desenvolvimento desta app." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 #, fuzzy msgid "Connect to Flathub" msgstr "Navegar pelo Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Algo correu mal" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Conecte a sua conta Flathub ao Bazaar para gerir as suas apps favoritas." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Terminar" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "OlĂĄ, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Definiçþes" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "A conexĂŁo de internet atual estĂĄ definida como limitada - a sincronização " "automĂĄtica de dados da loja foi pausada" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:494 msgid "Sync Manually" msgstr "Sincronizar manualmente" #: src/bz-preferences-dialog.blp:31 #, fuzzy msgid "Content Filters" msgstr "Filtragem de ConteĂşdo" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Apenas software livre" #: src/bz-preferences-dialog.blp:35 #, fuzzy msgid "Hide proprietary applications when browsing and searching" msgstr "Ocultar software proprietĂĄrio dos resultados de pesquisa" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Apenas resultados do Flathub" #: src/bz-preferences-dialog.blp:40 #, fuzzy msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "Limitar a pesquisa e navegação apenas a apps disponĂ­veis no Flathub" #: src/bz-preferences-dialog.blp:44 #, fuzzy msgid "Verified Results Only" msgstr "Apenas apps verificadas do Flathub" #: src/bz-preferences-dialog.blp:45 #, fuzzy msgid "Hide results that are not verified on Flathub" msgstr "Excluir da pesquisa resultados que nĂŁo sejam do Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Ocultar apps em fim de vida (EOL)" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "" "Ocultar apps que jĂĄ nĂŁo estejam a receber suporte dos seus desenvolvedores" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:314 msgid "Search" msgstr "Pesquisar" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Atrasar resultados de pesquisa" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "Melhorar o desempenho da lista de resultados ao atrasar a entrada de texto " "da pesquisa" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Barra de progresso" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Escolha um tema para a barra de progresso" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Riscas Verticais" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Mostrar as cores das bandeiras da esquerda para a direita" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Cor de destaque" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 msgid "Version History" msgstr "HistĂłrico de versĂľes" #: src/bz-releases-list.c:136 #, c-format msgid "Version %s" msgstr "VersĂŁo %s" #: src/bz-releases-list.c:173 msgid "No details for this release" msgstr "Sem detalhes sobre esta versĂŁo" #: src/bz-releases-list.c:185 #, fuzzy msgid "Get More Information" msgstr "Obter mais informaçþes" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Obter" #: src/bz-safety-calculator.c:82 #, fuzzy msgid "Unknown Permissions" msgstr "PermissĂľes Desconhecidas" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "As permissĂľes estĂŁo em falta para esta app." #: src/bz-safety-calculator.c:96 #, fuzzy msgid "No Permissions" msgstr "Sem PermissĂľes" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "A app ĂŠ completamente sandboxed (isolada do sistema)" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Acesso Ă  internet" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Pode aceder Ă  internet" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Sem acesso Ă  internet" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "NĂŁo pode aceder Ă  internet" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Acesso a dispositivos do utilizador" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "Pode aceder a dispositivos como câmaras ou comandos de jogos" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Sem acesso a dispositivos do utilizador" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "NĂŁo pode aceder a dispositivos como câmaras ou comandos de jogos" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Acesso a dispositivos de introdução" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Pode aceder a dispositivos de introdução como rato e teclado" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Acesso a microfone e reprodução de ĂĄudio" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "Pode aceder a microfones e reproduzir som sem necessitar de permissĂŁo" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Acesso a dispositivos de sistema" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "" "Pode aceder a dispositivos de sistema que requeiram permissĂľes elevadas" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Acesso ao conteĂşdo do ecrĂŁ" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Pode aceder ao conteĂşdo do ecrĂŁ ou de outras janelas" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Sistema de janelas antigo (legacy)" #: src/bz-safety-calculator.c:150 #, fuzzy msgid "Always uses a legacy windowing system (X11)" msgstr "Usa um sistema de janelas antigo (legacy)" #: src/bz-safety-calculator.c:156 #, fuzzy msgid "Arbitrary Permissions" msgstr "PermissĂľes arbitrĂĄrias" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Pode obter permissĂľes arbitrĂĄrias" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Definiçþes do utilizador" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Pode aceder e alterar definiçþes do utilizador" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Acesso completo de leitura e escrita ao sistema de ficheiros" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "Pode aceder, alterar ou apagar quaisquer dados no sistema de ficheiros" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Acesso de leitura/escrita Ă  pasta pessoal (Home)" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "Pode aceder, alterar ou apagar quaisquer dados na pasta pessoal" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Acesso de leitura a todo o sistema" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "" "Pode ler e aceder (mas nĂŁo alterar/apagar) a quaisquer dados em qualquer " "parte do sistema de ficheiros" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Acesso de leitura Ă  pasta pessoal (Home)" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "" "Pode ler e aceder (mas nĂŁo alterar/apagar) a quaisquer dados na pasta " "pessoal do seu utilizador" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Acesso completo de leitura/escrita Ă  pasta TransferĂŞncias" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "" "Pode aceder, alterar ou apagar quaisquer dados na sua pasta TransferĂŞncias" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Acesso de leitura Ă  pasta TransferĂŞncias" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "" "Pode ler e aceder (mas nĂŁo alterar/apagar) a quaisquer dados na sua pasta " "TransferĂŞncias" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "" "Pode aceder, alterar ou apagar quaisquer dados nesta pasta ou diretĂłrio" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "" "Pode ler e aceder (mas nĂŁo alterar/apagar) a quaisquer dados nesta pasta ou " "diretĂłrio" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Sem acesso completo ao sistema de ficheiros" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "NĂŁo pode aceder de todo ao sistema de ficheiros" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Usa serviços de sistema" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Pode pedir dados para serviços de sistema fora do portal" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Usa serviços de sessĂŁo" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Pode pedir dados para serviços de sessĂŁo fora do portal" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Sem acesso a serviços" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "" "NĂŁo pode de todo aceder a serviços fora do portal sejam de sistema ou de " "sessĂŁo" #: src/bz-safety-calculator.c:331 #, fuzzy msgid "Verified App Developer" msgstr "" "Este flatpak foi verificado pelos desenvolvedores originais do software." #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "O desenvolvedor desta app foi verificado como sendo quem realmente diz" #: src/bz-safety-calculator.c:341 #, fuzzy msgid "Proprietary Code" msgstr "CĂłdigo ProprietĂĄrio" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "O cĂłdigo-fonte nĂŁo ĂŠ pĂşblico, pelo que nĂŁo pode ser verificado nem testado " "por terceiros e poderĂĄ ser inseguro" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "CĂłdigo-fonte auditĂĄvel" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Este cĂłdigo-fonte ĂŠ pĂşblico e pode ser testado e verificado de forma " "independente o que ajuda a verificar se esta app ĂŠ segura" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Usa o serviço de sistema %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Usa o serviço de sessĂŁo %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Usa o serviço %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Pode ver o serviço fora do portal" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Pode comunicar com o serviço fora do portal" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Pode ser proprietĂĄrio do serviço fora do portal" #: src/bz-safety-calculator.c:530 #, fuzzy msgid "Global Menu Integration" msgstr "Integração com o menu global" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Pode mostrar os seus prĂłprios menus na barra de menu global" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Integração com as definiçþes do KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Pode detectar quando definiçþes do KDE sĂŁo alteradas" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Definiçþes globais do KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Pode ler personalizaçþes do KDE como fontes ou tema de cores" #: src/bz-safety-calculator.c:548 #, fuzzy msgid "Secret Storage Service" msgstr "Serviço de armazenamento secreto" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "Pode guardar e obter as suas prĂłprias passwords atravĂŠs do chaveiro do sistema" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "Notificaçþes do ambiente de trabalho" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Pode enviar notificaçþes de ambiente de trabalho" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Integração com a barra de estado" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Pode mostrar um Ă­cone na barra de estado" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Integração KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "Pode interagir com dispositivos via KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Segurança" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Detalhes" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Licença" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "ID da app" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Esta app usa uma versĂŁo de software de desenvolvimento (SDK) desatualizada e " "pode por isso conter problemas ou vulnerabilidades de segurança que nunca " "serĂŁo resolvidas." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s ĂŠ seguro(a)" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s tem permissĂľes inseguras" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s ĂŠ provavelmente seguro(a)" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s poderĂĄ ser inseguro(a)" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s ĂŠ inseguro(a)" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Capturas de ecrĂŁ" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Captura anterior" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Captura seguinte" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Copiar imagem" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Redefinir vista" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Afastar o zoom" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Aproximar o zoom" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Carrossel de capturas de ecrĂŁ" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Abrir o visualizador de capturas de ecrĂŁ" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Procure apps, jogos e software" #: src/bz-search-widget.blp:96 #, fuzzy msgid "Categories Unavailable" msgstr "Categorias nĂŁo disponĂ­veis" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Pesquise por apps usando a barra de pesquisa acima." #: src/bz-search-widget.blp:181 #, fuzzy msgid "No Applications Found" msgstr "NĂŁo foram encontradas aplicaçþes" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Sem resultados para \"%s\" no Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Copiado!" #: src/bz-share-list.c:116 #, fuzzy msgid "Copy Link" msgstr "Copiar a ligação" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Abrir a ligação" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Linha do tempo" #: src/bz-stats-dialog.blp:46 #, fuzzy msgid "Installs:" msgstr "Instalaçþes:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Mundo" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f milhĂľes de instalaçþes totais" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f mil instalaçþes totais" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d instalaçþes totais" #: src/bz-tag-list.c:96 #, fuzzy msgid "No Results Found" msgstr "Sem Resultados" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Apps etiquetadas com \"%s\"" #: src/bz-tag-list.c:124 #, fuzzy msgid "Search failed" msgstr "A pesquisa falhou" #: src/bz-transaction-dialog.c:166 msgid "Keep Data" msgstr "Manter dados" #: src/bz-transaction-dialog.c:167 msgid "Allow restoring settings and content" msgstr "Permitir o restauro de definiçþes e conteĂşdo" #: src/bz-transaction-dialog.c:176 msgid "Delete Data" msgstr "Apagar dados" #: src/bz-transaction-dialog.c:177 msgid "Permanently remove app data to save space" msgstr "Remover permanentemente todos os dados da app para poupar espaço" #: src/bz-transaction-dialog.c:202 #, fuzzy, c-format msgid "Install %s?" msgstr "Instalar %s ?" #: src/bz-transaction-dialog.c:207 #, fuzzy msgid "" "Select which version to install. May install additional shared components" msgstr "PoderĂĄ instalar componentes adicionais" #: src/bz-transaction-dialog.c:209 msgid "May install additional shared components" msgstr "PoderĂĄ instalar componentes adicionais" #: src/bz-transaction-dialog.c:230 #, fuzzy, c-format msgid "Remove %s?" msgstr "Remover %s ?" #: src/bz-transaction-dialog.c:233 msgid "Select which version to remove." msgstr "Selecione qual versĂŁo a remover." #: src/bz-transaction-dialog.c:235 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "NĂŁo serĂĄ mais possĂ­vel usar %s apĂłs ser desinstalado(a)." #: src/bz-transaction-dialog.c:258 #, c-format msgid "“%s” is High Risk" msgstr "“%s” ĂŠ de alto risco" #: src/bz-transaction-dialog.c:262 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Esta app tem acesso completo de leitura e escrita ao sistema, incluindo " "todos os seus ficheiros, histĂłricos, passes guardadas, e muito mais. " "TambĂŠm tem acesso Ă  internet, pelo que poderĂĄ enviar estes e quaisquer dados " "para terceiros.\n" "\n" "Por a app ser proprietĂĄria de cĂłdigo fechado, nĂŁo se pode verificar o que ĂŠ " "que a mesma faz com estas permissĂľes e estes dados." #: src/bz-transaction-dialog.c:271 #, fuzzy msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Esta app tem acesso completo de leitura e escrita ao sistema, incluindo " "todos os seus ficheiros, histĂłricos, passes guardadas, e muito mais. " "TambĂŠm tem acesso Ă  internet, pelo que poderĂĄ enviar estes e quaisquer dados " "para terceiros.\n" "\n" "Por a app ser proprietĂĄria de cĂłdigo fechado, nĂŁo se pode verificar o que ĂŠ " "que a mesma faz com estas permissĂľes e estes dados." #: src/bz-transaction-dialog.c:287 #, fuzzy msgid "Install Anyway" msgstr "Instalar mesmo assim" #: src/bz-transaction-dialog.c:566 msgid "All apps are already installed" msgstr "As apps jĂĄ estĂŁo todas instaladas" #: src/bz-transaction-dialog.c:568 msgid "OK" msgstr "OK" #: src/bz-transaction-dialog.c:584 #, fuzzy, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Instalar %s ?" msgstr[1] "Instalar %s ?" #: src/bz-transaction-dialog.c:592 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "Os seguintes itens serĂŁo instalados. Componentes partilhados adicionais " "tambĂŠm poderĂŁo ser instalados, conforme necessĂĄrio." #: src/bz-transaction-dialog.c:593 #, c-format msgid "%d addons will be installed." msgstr "%d extensĂŁo(Ăľes) serĂĄ(ĂŁo) instalada(s)." #: src/bz-transaction-dialog.c:594 #, fuzzy msgid "Additionally, addons will be installed." msgstr "" "%d serviços de execução (runtimes) e/ou extensĂľes relacionados(as) tambĂŠm " "serĂŁo atualizados(as)." #: src/bz-transaction-manager.c:1150 #, c-format msgid "Finished in %.02f seconds" msgstr "ConcluĂ­do em %.02f segundos" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Extras da app" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Serviço de execução (Runtime)" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 #, fuzzy msgid "Install Size" msgstr "Tamanho da instalação" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "Pendente" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "Em andamento" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "Terminado" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "Atualizar" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "%s transferidos atĂŠ agora" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Gerir Dados Obsoletos(as)" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "NĂŁo foram encontrados dados de utilizador" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Dados de utilizador" #: src/bz-user-data-tile.c:144 #, fuzzy, c-format msgid "Trashed User Data for %s" msgstr "Removido os dados de utilizador de %s" #: src/bz-user-data-tile.blp:74 #, fuzzy msgid "Trash User Data" msgstr "Dados de utilizador" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Tarefas" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Parar as tarefas ativas" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Limpar o histĂłrico de tarefas" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Ainda sem tarefas" #: src/bz-window.blp:257 #, fuzzy msgid "Refreshing Store Content" msgstr "Recarregar o conteĂşdo da loja" #: src/bz-window.blp:273 msgid "Curated" msgstr "Recomendadas" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:435 msgid "No background tasks!" msgstr "Sem tarefas de fundo!" #: src/bz-window.blp:493 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Tem uma conexĂŁo Ă  internet ativa mas estĂĄ a ver uma versĂŁo anterior em cache " "do Flathub" #: src/bz-window.blp:568 #, fuzzy msgid "_Login with Flathub" msgstr "_Entrar com uma conta no Flathub" #: src/bz-window.blp:574 msgid "_Manage Leftover User Data" msgstr "_Gerir dados deixados para trĂĄs" #: src/bz-window.blp:579 msgid "_Synchronize Remotes" msgstr "_Sincronizar os repositĂłrios" #: src/bz-window.blp:620 msgid "Log Out" msgstr "Terminar sessĂŁo" #: src/bz-window.c:440 #, fuzzy, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d atualização disponĂ­vel" msgstr[1] "%d atualizaçþes disponĂ­veis" #: src/bz-window.c:734 msgid "You can't remove Bazaar from Bazaar!" msgstr "NĂŁo pode remover o Bazaar pelo Bazaar!" #: src/bz-window.c:871 msgid "Updates Are Available" msgstr "EstĂŁo DisponĂ­veis Atualizaçþes" #: src/bz-window.c:872 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "As seguintes aplicaçþes tĂŞm atualizaçþes disponĂ­veis. Deseja instalĂĄ-las " "agora?" #: src/bz-window.c:873 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "Existe(m) %d serviços de execução (runtimes) e/ou extensĂľes com atualizaçþes " "disponĂ­veis. Deseja atualizĂĄ-los(as) agora?" #: src/bz-window.c:874 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "" "%d serviços de execução (runtimes) e/ou extensĂľes relacionados(as) tambĂŠm " "serĂŁo atualizados(as)." #: src/bz-window.c:876 #, fuzzy msgid "Update Now" msgstr "Atualizar agora" #: src/bz-window.c:1036 src/bz-window.c:1086 msgid "Can't do that right now!" msgstr "NĂŁo ĂŠ possĂ­vel fazer isso neste momento!" #: src/bz-window.c:1161 msgid "Resume Current Tasks" msgstr "Retomar as tarefas atuais" #: src/bz-window.c:1167 msgid "Pause Current Tasks" msgstr "Pausar as tarefas atuais" #: src/bz-world-map.c:587 #, fuzzy msgid "Downloads" msgstr "Transferir" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Geral" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Abrir a Janela de Pesquisa" #: src/gtk/shortcuts-dialog.blp:14 #, fuzzy msgctxt "shortcut window" msgid "Open Preferences" msgstr "Abrir as definiçþes" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Sincronizar os repositĂłrios" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Alternar o Gestor de Transaçþes" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Mostrar os Atalhos" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Sair" #~ msgid "Hide EOL Entries" #~ msgstr "Ocultar apps em fim de vida (EOL)" #~ msgid "Hide EOL entries and entries depending on them" #~ msgstr "Ocultar apps em fim de vida (EOL) e items que dependam destas" #~ msgid "Only Show Free Software" #~ msgstr "Mostrar apenas software livre" #, fuzzy #~ msgid "Hide proprietary software" #~ msgstr "Ocultar software proprietĂĄrio" #~ msgid "Show Only Flathub Content" #~ msgstr "Mostrar apenas conteĂşdo do Flathub" #, fuzzy #~ msgid "Hide applications which do not originate from Flathub" #~ msgstr "Ocultar apps que nĂŁo sejam do Flathub" #, fuzzy #~ msgid "Show Only Verified Content" #~ msgstr "Mostrar apenas apps verificadas" #~ msgid "Hide applications which are not verified on Flathub" #~ msgstr "Ocultar apps que nĂŁo estejam verificadas no Flathub" #~ msgid "Debounce Search Inputs" #~ msgstr "Suavizar a entrar de texto na pesquisa" #, fuzzy #~ msgid "Add a delay before searching to prevent instant replies while typing" #~ msgstr "Atrasar a entrada de texto para evitar resultados instantâneos" #~ msgid "Global Progress Bar Theme" #~ msgstr "Tema da barra de progresso global" #~ msgid "Describes the look of the global progress bar" #~ msgstr "Descreve o aspeto da barra de progresso global" #~ msgid "Saved Window Dimensions" #~ msgstr "Guardar dimensĂľes da janela" #~ msgid "The window dimensions to be used by the next Bazaar window" #~ msgstr "As dimensĂľes a serem usadas por novas janelas do Bazaar" #~ msgid "?" #~ msgstr "?" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "" #~ "Esta funcionalidade estĂĄ atualmente desativada. É recomendado que " #~ "transfira e instale a aplicação Flatseal para gerir as permissĂľes das " #~ "aplicaçþes Flatpak." #~ msgid "Entry Inspector" #~ msgstr "Inspetor de Itens" #~ msgid "Serialize" #~ msgstr "Serializar" #~ msgid "Convert to JSON" #~ msgstr "Converter para JSON" #~ msgid "More Mobile apps" #~ msgstr "Mais apps mobile" #, fuzzy #~ msgctxt "Project URL Type" #~ msgid "Flathub Page" #~ msgstr "PĂĄgina do Flathub" #, fuzzy #~ msgctxt "Project URL Type" #~ msgid "Project Website" #~ msgstr "PĂĄgina do Projeto" #~ msgctxt "Project URL Type" #~ msgid "Issue Tracker" #~ msgstr "Issue Tracker" #~ msgctxt "Project URL Type" #~ msgid "FAQ" #~ msgstr "Perguntas Frequentes (FAQ)" #~ msgctxt "Project URL Type" #~ msgid "Help" #~ msgstr "Ajuda" #~ msgctxt "Project URL Type" #~ msgid "Donate" #~ msgstr "Donativos" #~ msgctxt "Project URL Type" #~ msgid "Translate" #~ msgstr "Traduçþes" #, fuzzy #~ msgctxt "Project URL Type" #~ msgid "Contact" #~ msgstr "Contacto" #~ msgctxt "Project URL Type" #~ msgid "Source Code" #~ msgstr "CĂłdigo-fonte" #~ msgctxt "Project URL Type" #~ msgid "Contribute" #~ msgstr "Contruibuir" #~ msgid "Size" #~ msgstr "Tamanho" #~ msgid "Bazaar Inspector" #~ msgstr "Inspector do Bazaar" #~ msgid "Background Task Info:" #~ msgstr "Info da tarefa em plano de fundo:" #~ msgid "Enable Global Debug Mode" #~ msgstr "Ligar o Modo de Depuração Global" #~ msgid "Active Blocklists" #~ msgstr "Listas de bloqueio ativas" #~ msgid "Active Curated-Configs" #~ msgstr "Configuraçþes ativas de recomendaçþes de apps" #~ msgid "All Entry Groups" #~ msgstr "Todos os grupos de itens" #~ msgid "Filter..." #~ msgstr "Filtrar..." #~ msgid "Decache and Inspect" #~ msgstr "Retirar da cache e inspeccionar" #~ msgid "No Flatpaks Installed" #~ msgstr "NĂŁo Existem Flatpaks Instalados" #~ msgid "Connect with Flathub" #~ msgstr "Conectar com o Flathub" #, fuzzy #~ msgid "Remove User Data" #~ msgstr "Remover os dados de utilizador" #~ msgid "Inspect UI Entry" #~ msgstr "Inspecionar o item de UI" #~ msgid "All Debug Actions" #~ msgstr "Todas as açþes de depuração" #, fuzzy #~ msgid "Open Bazaar Inspector" #~ msgstr "Abrir o inspector do Bazaar" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "A funcionalidade de verificar e instalar ficheiros/conjuntos .flatpak " #~ "estĂĄ a caminho! Enquanto nĂŁo estĂĄ disponĂ­vel, experimente executar o " #~ "comando\n" #~ "\n" #~ "flatpak install --bundle .flatpak\n" #~ "\n" #~ "a partir do terminal." #, c-format #~ msgid "%s: %'u downloads" #~ msgstr "%s: %'u transferĂŞncias" #~ msgid "Show Git Forge Star Counts" #~ msgstr "Ver o total de estrelas do Git Forge" #~ msgid "" #~ "Whether to attempt to detect and show \"star counts\" for projects in the " #~ "full view" #~ msgstr "" #~ "Tentar detectar e mostrar a contagem de estrelas para projetos na vista " #~ "completa" #~ msgid "Hide proprietary software when searching" #~ msgstr "Ocultar software proprietĂĄrio ao pesquisar" #~ msgid "Filter search results to only show applications available on Flathub" #~ msgstr "" #~ "Mostrar apenas resultados de pesquisa para aplicaçþes disponĂ­veis no " #~ "Flathub" #~ msgid "Of the size of human DNA" #~ msgstr "Do tamanho do ADN humano" #~ msgid "3 billion base pairs" #~ msgstr "3 mil milhĂľes de pares-base" #~ msgid "Of the Linux Kernel" #~ msgstr "Do Kernel do Linux" #~ msgid "Of the Apollo 11 guidance computer" #~ msgstr "Do computador guia Apollo 11" #~ msgid "Total ROM and RAM" #~ msgstr "MemĂłria ROM e RAM total" #~ msgid "Of the original Super Mario Bros" #~ msgstr "Do Super Mario Bros original" #~ msgid "On the NES" #~ msgstr "Na consola NES" #~ msgid "Of the size of Wikipedia" #~ msgstr "Do tamanho da Wikipedia" #~ msgid "Without any media" #~ msgstr "Sem nenhuma multimĂŠdia" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Eduardo Correia (Azenyr)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "Constructing Flatpak instance..." #~ msgstr "A construir a instância Flatpak..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "A reutilizar a Ăşltima instância Flatpak..." #~ msgid "Flathub is not registered on this system" #~ msgstr "O Flathub nĂŁo estĂĄ configurado neste sistema" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "Gostaria de adicionar o repositĂłrio Flathub a este sistema? Se recusar, a " #~ "pĂĄgina do Flathub ficarĂĄ indisponĂ­vel. Pode alterar esta escolha mais " #~ "tarde." #~ msgid "Add Flathub" #~ msgstr "Adicionar o Flathub" #, c-format #~ msgid "Identifying installed entries..." #~ msgstr "A identificar conteĂşdo instalado..." #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "" #~ "A iniciar a obtenção de dados dos repositĂłrios enquanto se referencia %d " #~ "lista(s) de bloqueio..." #, c-format #~ msgid "%'d of %'d" #~ msgstr "%'d de %'d" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "" #~ "A esperar que as tarefas de indexação a decorrer de fundo avancem..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "Inicialização terminada em %0.2f segundos" #~ msgid "Repository Star Count" #~ msgstr "Contagem de estrelas do repositĂłrio" #, c-format #~ msgid "%.2f M" #~ msgstr "%.2f M" #, c-format #~ msgid "%.2f K" #~ msgstr "%.2f K" #~ msgid "Run this application" #~ msgstr "Executar a aplicação" #~ msgid "Run" #~ msgstr "Executar" #~ msgid "View Store Page" #~ msgstr "Ver a pĂĄgina na loja" #~ msgid "Application Details" #~ msgstr "Detalhes da aplicação" #~ msgid "Display Star Count" #~ msgstr "Mostrar a contagem de estrelas" #~ msgid "Show the star count of an application's source code repository" #~ msgstr "Mostrar o total de estrelas do repositĂłrio do cĂłdigo da aplicação" #~ msgid "" #~ "Bazaar can fetch and display the star count from an application's source " #~ "code repository on a remote Git forge. \n" #~ " For projects on GitHub, rate limits may cause them not to appear." #~ msgstr "" #~ "O Bazaar pode obter e mostrar a contagem de estrelas do respetivo " #~ "repositĂłrio Git de cĂłdigo fonte de uma aplicação. \n" #~ "Para projetos do Github, poderĂŁo ser aplicados limites de pedidos pelo " #~ "mesmo que poderĂŁo fazer com que as estrelas deixem de aparecer " #~ "temporariamente." #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "Recarregar" #~ msgid "Show Animated Background" #~ msgstr "Mostrar Imagem de Fundo Animada" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "Mostrar o Ă­cone de imagem de fundo animada na pĂĄgina inicial" #~ msgid "Calligraphy application page" #~ msgstr "PĂĄgina da aplicação Calligraphy" #~ msgid "Download graph for Blender" #~ msgstr "GrĂĄfico de transferĂŞncias para o Blender" #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "" #~ "Foram recebidos %'d itens de um total de %'d (%0.1f segundos decorridos)" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "" #~ "O Bazaar nĂŁo tem uma definição para conteĂşdo recomendado. Contacte os " #~ "canais de suporte do seu sistema operativo para mais ajuda. " #~ msgid "Apps Of The Week" #~ msgstr "Aplicaçþes da Semana" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "" #~ "NĂşmero de transferĂŞncias dos Ăşltimos 30 dias. Clique para ver as " #~ "estatĂ­sticas desta aplicação." #~ msgid "Remote repo name" #~ msgstr "Nome do repositĂłrio remoto" #, c-format #~ msgid "Released %x" #~ msgstr "Lançado a %x" #~ msgid "How the application looks" #~ msgstr "A aparĂŞncia da aplicação" #~ msgid "Appearance" #~ msgstr "AparĂŞncia" #~ msgid "Show animated background" #~ msgstr "Mostrar imagem de fundo animada" #~ msgid "Type to filter" #~ msgstr "Escreva para procurar" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "Excluir da pesquisa resultados com licenças proprietĂĄrias" #~ msgid "Advanced" #~ msgstr "Avançado" #~ msgid "Share" #~ msgstr "Partilhar" #~ msgid "Open this link externally" #~ msgstr "Abrir a ligação externamente" #~ msgid "Downloads Over Time" #~ msgstr "TransferĂŞncias ao Longo do Tempo" #~ msgid "Minimize Lower Bound" #~ msgstr "Minimizar o limite inferior" #~ msgid "Maximize Upper Bound" #~ msgstr "Maximizar o limite superior" #~ msgid "Installing" #~ msgstr "A Instalar" #~ msgid "Removing" #~ msgstr "A Remover" #~ msgid "Transactions Will Appear Here" #~ msgstr "As Transaçþes IrĂŁo Aparecer Aqui" #~ msgid "Halt the execution of transactions" #~ msgstr "Interromper a execução das transaçþes" #~ msgid "Clear all finished transactions" #~ msgstr "Limpar as transaçþes finalizadas" #~ msgid "Browse" #~ msgstr "Explorar" #~ msgid "App View" #~ msgstr "Vista de Aplicação" #~ msgid "Go Back" #~ msgstr "Voltar" #~ msgid "View the latest on Flathub" #~ msgstr "Ver as novidades do Flathub" #~ msgid "Up to date!" #~ msgstr "Atualizado!" #~ msgid "Confirm Action" #~ msgstr "Confirmar Ação" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "IrĂĄ a remover a seguinte aplicação Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Deseja continuar?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "IrĂĄ instalar a seguinte aplicação Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Deseja continuar?" #~ msgid "Resume the execution of transactions" #~ msgstr "Retomar a execução das transaçþes" #~ msgid "Pause the execution of transactions" #~ msgstr "Colocar a execução das transaçþes em pausa" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "Mantenha o resumo curto, entre 10 e 35 caracteres" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Janela principal do Bazaar a mostrar o Blender" #~ msgid "Match using regular expressions" #~ msgstr "Corresponder atravĂŠs de expressĂľes regulares" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "" #~ "Ocultar filtragem e ordenação atravĂŠs de um efeito visual de transição " #~ "crossfade" kolunmi-bazaar-7b9c8e1/po/ru.po000066400000000000000000002720771514314607700165050ustar00rootroot00000000000000# Russian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025, 2026 Jill Fiore # Jill Fiore , 2025-2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-10 22:35+0700\n" "PO-Revision-Date: 2026-02-10 22:36+0700\n" "Last-Translator: Jill Fiore \n" "Language-Team: Russian\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "" "Установка, удаНонио иНи ОйнОвНонио Flatpak приложений на этом компьютере" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;Система;УправлениеПакетами;Discover;Flatpak;Приложения;Магазин;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Новое ОкнО" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Поиск и установка приложений" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Новый ПагаСин приложений для Linux с фокусом на пОиско, установке приложений " "и дОпОНнониК иС Flatpak репозиторий, в частности с Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Оно подчёркивает поддержку разработчиков, которые делают настольный Linux " "возможным. Bazaar внедряет вкНадку \"Курируемое\", которая настраивается " "дистрибьюторами для обеспечения йОНоо ориентированного опыта." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:703 msgid "Adam Masciola" msgstr "АдаП Масциола" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Главная страница, отображающая приложения Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Страница приложения Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Страница пОиска" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Страница категорий" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "Управление дополнениями" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:231 msgid "Remove" msgstr "Удалить" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:202 msgid "Install" msgstr "Установить" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "Возраст" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Мультипликационное насиНио" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Нет информации Đž мультипликационном насиНии" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Фэнтезийное насиНио" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Нет информации Đž фэнтезийном насиНии" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Реалистичное насиНио" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Нет информации Đž реалистичном насиНии" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Кровопролитие" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Нет информации Đž кровопролитии" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Сексуальное насиНио" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Нет информации Đž сексуальном насиНии" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Алкоголь" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Нет информации Đž упОПинании алкоголя" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Наркотики" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Нет информации Đž упОПинании наркотических средств" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "Тайак" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "Нет информации Đž упОПинании табачных иСдоНиК" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "Нагота" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Нет информации Đž наготе любого рода" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Сексуальные темы" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "" "Нет информации Đž упОПинании иНи пОкаСо изображений сексуального характера" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "Ненормативная Ноксика" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Нет информации Đž ненормативной Ноксико в любом видо" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Неприемлемый юмор" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Нет информации Đž неприемоемом юморе" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "Дискриминация" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Нет информации Đž дискриминации в любом видо" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "РокНаПа" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Нет информации Đž рекламе в любом видо" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Азартные игры" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Нет информации Đž азартных играх в любом видо" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "Покупка" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Нет информации Đž возможности тратить деньги" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "Общение ПоМду пользователями" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Нет инфорамции Đž возможностях общаться с другими пользователями" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "Аудиочат ПоМду пользователями" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Нет информации Đž возможности разговаривать с другими пользователями" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Контактная информация" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Нет информации Đž распространении имён пользователей иНи адресов электронной " "почты" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "Идентифицирующая информация" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "" "Нет информации Đž распространении пользовательских данных с другими лицами" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Распространение местоположения" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "" "Нет информации Đž распространении физического местоположения с другими " "пользователями" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Проституция" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Нет информации Đž упОПинании проституции" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Прелюбодеяние" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Нет информации Đž упОПинании прелюбодеяния" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Сексуализированные персонажи" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Нет информации Đž сексуализированных персонажей" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "Осквернение" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Нет информации Đž осквернении" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "Останки человека" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Нет информации Đž видимости останков человека" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "Рабство" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "Нет информации Đž упОПинании рабства" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Не содержит упоминания наркотических средств" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "" "Не содержит ругательство, ненормативную Ноксику, и любых видОв грубой речи" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Не содержит рекламу иНи денежные транзакции" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Не содержит сокс иНи наготу" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Не содержит функциональность немодерируемого чата" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Не содержит насиНио" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Наркотики" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Грубая речь" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Деньги" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Общение" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Насилие" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "Все" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s имеет неизвестное возрастное ограничение" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s предназначено для всех возрастов" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s предназначено для маленьких детей" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s предназначено для детей" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s предназначено для подростков" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s предназначено для взрослых" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s предназначено для %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "Главное меню" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "_Поддержать Bazaar ❤️" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "П_араметры" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "_Войти в Flathub" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "_Управлять оставшимися данными" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "ĐĄ_инхронизировать репозитории" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "_Сочетание кНавиш" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "О _Bazaar" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "_Завершить Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Системная папка %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Домашняя пОдпапка %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Системные папки хоста" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "Системная конфигурация хоста иС /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "Подпапка рабочего стола %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "Папка рабочего стола" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Подпапка документов %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Папка документов" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "Подпапка музыки %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "Папка музыки" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Подпапка изображений %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Папка изображений" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Подпапка общего доступа %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Папка общего доступа" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Подпапка с видоО %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Папка с видоО" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Подпапка шайНОнОв %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Папка шайНОнОв" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "Подпапка пользовательского кэша %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "Папка пользовательского кэша" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "Подпапка пользовательской конфигурации %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "Папка пользовательской конфигурации" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "Подпапка пользовательских данных %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "Папка пользовательских данных" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "Подпапка пользовательской среды выполнения %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "Папка пользовательской среды выполнения" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Доступ Đş файловой системе в %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Неизвестный путь файловой системы" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "Размер скачивания" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "Размер скачивания иС интернета" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Размер установки" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Размер на диско" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "Размер пользовательских данных" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Кэши, настройки и другие пользовательские данные" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:178 msgid "Installed" msgstr "Установлено" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "Показать всо" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "Все \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d приложений" #: src/bz-application.c:674 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "АдаП Масциола " #: src/bz-application.c:675 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Александр Фанхе" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:706 msgid "translator-credits" msgstr "Джилл Фиори , 2025, 2026" #: src/bz-application.c:717 msgid "Special Thanks" msgstr "Особая благодарность" #: src/bz-application.c:775 msgid "Logged Out Successfully!" msgstr "Выход иС аккаунта выполнен успошнО!" #: src/bz-application.c:898 msgid "Performing setup..." msgstr "Выполняется настройка..." #: src/bz-application.c:981 src/bz-application.c:990 msgid "Set Up Flathub" msgstr "Добавить Flathub" #: src/bz-application.c:984 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub но был дОйавНон в данную систему. Вы но сможете искать и " "устанавливать приложения в Bazaar пОка Он недоступен.\n" "\n" "Вы пО-прежнему можете использовать Bazaar для обзора и удаления уМо " "установленных приложений." #: src/bz-application.c:989 msgid "Later" msgstr "Позже" #: src/bz-application.c:1399 src/bz-application.c:3116 msgid "Synchronizing..." msgstr "Синхронизация..." #: src/bz-application.c:1546 src/bz-application.c:3112 #, c-format msgid "Receiving %d entries..." msgstr "Получение %d элементов" #: src/bz-application.c:1551 msgid "Checking for updates" msgstr "Проверка на наличие ОйнОвНониК" #: src/bz-application.c:3118 msgid "Indexing Data..." msgstr "Индексация данных..." #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Страница Flathub" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "Веб-сайт проекта" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Отслеживание ОшийОк" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "Часто задаваемые вопросы" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "Помощь" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "Пожертвовать" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "Перевод" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "Связаться" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "Исходный кОд" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "Сделать вкНад" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "Пусто" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Нет курации" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Отсутствует информация Đž курируемых приложениях в даннОК системе. Вы всё ещё " "можете поискать приложения вО вкНадко Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Открыть Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Нет интернета" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Обзор" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Информация Đž разработчике недоступна." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Право собственности на ID приложения %s но было подтверждено, это приложение " "может быть неофициальным." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Право собственности на ID приложения %s было подтверждено кОПандОК Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "Право собственности на ID приложения %1$s было подтверждено %2$s на " "%3$s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "" "Право собственности на ID приложения %1$s было подтверждено используя %2$s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Право собственности на ID приложения %s было подтверждено." #: src/bz-donations-dialog.blp:47 msgid "View the Release Page" msgstr "Открыть страницу выпуска" #: src/bz-donations-dialog.blp:69 msgid "This Bazaar Release Was Made Possible By Users Like You!" msgstr "Этот выпуск Bazaar был сдоНан благодаря таким пользователям, как Вы!" #: src/bz-donations-dialog.blp:77 msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "Мне нравится делать Bazaar, нО я но ПОгу это делать в одиночку. Если вы " "захотите поддержать дальнейшую разработку, пожалуйста пожертвуйте проекту в " "моём Ko-fi:" #: src/bz-donations-dialog.blp:87 msgid "Donate to Bazaar" msgstr "Поддержать Bazaar" #. Translators: the %s format specifier will be something along the lines of "0.7.6" etc #: src/bz-donations-dialog.c:156 #, c-format msgid "What's New in Version %s?" msgstr "Что нОвОгО в версии %s?" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Выбор установки" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Вы установили несколько версий даннОгО приложения. Какое вы хотите выбрать " "для продолжения?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:201 #: src/bz-transaction-dialog.c:230 src/bz-transaction-dialog.c:275 #: src/bz-transaction-dialog.c:578 msgid "Cancel" msgstr "Отмена" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "Только для этого пользователя" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "этот пользователь" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "всо пользователи" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Произошла Ошийка" #: src/bz-error.c:89 msgid "Close" msgstr "Закрыть" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Скопировать и закрыть" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Войдите в Flathub для управления избранными приложениями" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Войти" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "ЧисНО избранных" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "Удалить" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "Поддержать это приложение" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "Удалить иС избранных" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "Избранные" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 msgid "Open App Library" msgstr "Открыть библиотеку приложений" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:579 msgid "Install All" msgstr "Установить всо" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "Загрузка" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "Нет избранных" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "Приложения помеченные как избранные будут показаны здесь" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Предыдущий" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Следующий" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Приложение дня" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "Монтаж" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "Midi" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "Микшеры" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "Музыка" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "Проигрыватели" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "Звукозапись" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "Секвенсоры" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "Тюнеры" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "ТВ" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "Эмуляторы" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "Экшон" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "Приключения" #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "Аркады" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "Блоки" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "Настольные" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "Карточные" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "Для детей" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "Логические" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "Ролевые" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "Шутеры" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "Симуляторы" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "Спортивные" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "Стратегии" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "АудиО и видоО" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "Медиа" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "Больше приложений для аудиО и видоО" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "Инструменты разработчика" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "Разработчикам" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "Больше приложений для разработки" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "Образование" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "Обучение" #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "Больше образовательных приложений" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "Игры" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "Игры" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "Больше игр" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "Графика и фотография" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "Творите" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "Больше приложений для графики" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "Сеть" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "Сеть" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "Больше сетевых приложений" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "Продуктивность" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "Работа" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "Больше приложений для продуктивности" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "Наука" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "Больше научных приложений" #: src/bz-flathub-category.c:128 msgid "System" msgstr "Система" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "Больше системных приложений" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "Утилиты" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "Утилиты" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "Больше утилит" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "В тренде" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "Больше трендовых" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Популярное" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "Больше популярных" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Недавно добавленные" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "Новое" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "Больше нОвинОк" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Недавно обновленные" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Обновлённые" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "Больше обновленных" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "Мобильные" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "Больше мобильных приложений" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "Больше Adwaita" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "KDE приложения" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "Больше приложений Đş KDE" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub но дОйавНон" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Репозиторий Flathub но был наКдон среди ваших flatpak установок" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub вернул Ошийку" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Повторить подключение Đş Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub недоступен" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Мы но ПОМоП подключиться Đş Flathub. Вы всё ещё можете управлять приложениями " "и искать их." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Поиск приложений" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Всегда пОд рукой" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Приложения для ваших телефонов и планшетов на Linux" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Больше мобильных приложений" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Мы ♥ Игры" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Игры и приложения для Сапуска ваших любимых тайтлов" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Больше игр" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "Нет результатов" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "Попробуйте выполнить другой поисковый запрос" #: src/bz-full-view.blp:59 msgid "Content" msgstr "Содержимое" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "Установка пакетов .flatpak пОка но поддерживается" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Поддержать" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Открыть" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Скачать и установить приложение" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Удалить приложение" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Установить другую версию" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "Загрузок в месяц" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Прекращено получение основных ОйнОвНониК" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Это приложение использует среду выполнения, которая больше но получает " "обновления иНи исправления ОшийОк безопасности. Оно может стать небезопасным " "для использования." #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "Отправить в корзину" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "Метки:" #: src/bz-full-view.c:220 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "%.*f ПиН." #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "%.*f тыс." #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d загрузок Са пОсНоднио 30 дноК" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "Н/Д" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "Скачивание" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "Информация Đž размере недоступна" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "Размер скачивания %s" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "Для всех" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "Информация Đž возрастном ограничении недоступна" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "Предназначено для всех возрастов" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "Предназначено для лиц старше %d лет" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "Неизвестно" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "ХвОйОднОо программное обеспечение, лицензированное пОд %s" #: src/bz-full-view.c:403 msgid "Free software" msgstr "CвОйОднОо программное обеспечение" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "Проприетарное программное обеспечение" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "Специальная лицензия: %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "ХвОйОднОо" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "Проприетарное" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "Специальная лицензия" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "Адаптивное" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "Только для ПК" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "Работает на настольных компьютерах, планшетах и телефонах" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "Может но работать на мобильных устройствах" #: src/bz-full-view.c:472 msgid "No URL" msgstr "Нет URL" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Это приложение имеет лицензию FLOSS, что значит исходный кОд может быть " "проверен на безопасность." #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Это приложение имеет проприетарную лицензию, что значит исходный кОд " "разрабатывается в тайне и но может быть проверен ноСависиПОК третьей " "стороной." #: src/bz-full-view.c:498 msgid "More Apps" msgstr "Больше приложений" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "Больше приложений от %s" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "Другие приложения от этого разработчика" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "Другие приложения от %s" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "%s но установлено, нО пользовательские данные в размере %s ещё " "присутствуют." #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "Безопасно" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "Низкий риск" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "Средний риск" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "Высокий риск" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "Другие приложения" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d приложение" msgstr[1] "%d приложения" msgstr[2] "%d приложений" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "Показать меньше" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "Показать больше" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "Поддержка оборудования" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Поддержка клавиатуры" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Требуется использовать клавиатуру" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Рекомендуется использовать клавиатуру" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Поддерживает клавиатуру" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Неизвестная поддержка клавиатуры" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Поддержка мыши" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Требуется использовать мышь иНи указательные устройства" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Рекомендуется использовать мышь иНи указательные устройства" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Поддерживает мышь иНи указательные устройства" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Неизвестная поддержка мыши и указательных устройств" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Поддержка сенсорного экрана" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Требуется использовать сенсорный экран" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Рекомендуется использовать сенсорный экран" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Поддерживает сенсорные экраны" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Неизвестная поддержка сенсорных экран" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Поддержка мобильных устройств" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Работает на мобильных устройствах" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Может но работать хорошо на мобильных устройствах" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "Поддержка настольных компьютеров" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "Работает хорошо на больших экранах" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s работает лучше на определённых устройствах" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s работает на большинстве устройств" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "Прекращено получение ОйнОвНониК" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "Поиск установленных приложений" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "Приложение но наКдонО" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 msgid "Library" msgstr "Библиотека" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "Ожидают обновления" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "Загрузки" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "Недавно удалённые" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "Очистить выполненные задачи" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "Установленные приложения" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "Нет результатов пО запросу \"%s\" в списко установленных приложений" #: src/bz-library-page.c:165 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "Доступно %u ОйнОвНонио" msgstr[1] "Доступно %u обновления" msgstr[2] "Доступно %u ОйнОвНониК" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "Внести вкНад" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "Неизвестная лицензия" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "ХдоНанО сообществом" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Это приложение разрабатывается открыто международным сообществом.\n" "\n" "Вы можете внести свОК вкНад и сделать это приложение ещё лучше." #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "Лицензия этого приложения неизвестна" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Это приложение открыто разрабатывается международным сообществом и " "выпускается пОд лицензией %s.\n" "\n" "Вы можете внести свОК вкНад и сделать это приложение ещё лучше." #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Это приложение но разрабатывается открыто, поэтому только огО разработчики " "знают как ОнО работает. Оно может быть небезопасным в некоторых местах, " "которые сНОМнО опознать, и ОнО может измениться йоС предупреждения.\n" "\n" "Вы можете но иметь возможности внести вкНад в это приложение." #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Это приложение разрабатывается пОд специальной лицензией %s.\n" "\n" "Вы можете но иметь возможности внести вкНад в это приложение." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "Подключение Đş Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Что-то пОшНО но так" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "" "Подключитесь Đş свОоПу аккаунту Flathub в Bazaar для управления вашиПи " "избранными приложениями." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Завершить" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Приветствуем, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Параметры" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Сетевое сОодинонио ограничено — автоматическая синхронизация данных ПагаСина " "приостановлена" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "Синхронизировать вручную" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "Фильтры содержимого" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "Только свободные приложения" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "Скрыть проприетарные приложения при обзоре и пОиско" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "Только результаты иС Flathub" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "Ограничить обзор и результаты пОиска только приложениями иС Flathub" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "Только подтверждённые результаты" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "Скрыть приложения, которые но являются подтверждёнными на Flathub" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "Скрыть неподдерживаемые приложения" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Скрыть приложения, которые больше но поддерживаются разработчиками" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "Поиск" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Увеличить задержку результатов пОиска" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "" "Улучшить производительность пОкаСа результатов благодаря увеличению задержки " "ввОда запроса" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "Полоса прогресса" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "Выберите тему для полосы прогресса!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "Вертикальные полосы" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "Отображать цвета флагов сНова направо" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Цвет акцента" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Цвета гордости" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Цвета гордости лесбиянок" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "Цвета гордости мужчин гОПОсоксуаНОв" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "Цвета гордости трансгендеров" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "Цвета гордости небинарных" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "Цвета гордости йисоксуаНОв" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "Цвета гордости асоксуаНОв" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "Цвета гордости пансоксуаНОв" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "Цвета гордости аромантиков" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "Цвета гордости гендерфлюид" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "Цвета гордости пОНисоксуаНОв" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "Цвета гордости ОПнисоксуаНОв" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "Цвета гордости ароэйс" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "Цвета гордости агендеров" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "Цвета гордости гендерквиров" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "Цвета гордости интерсекс" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "Цвета гордости демигендеров" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "Цвета гордости биромантиков" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "Цвета гордости людей с ограниченными возможностями" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "Цвета гордости фембоев" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "Цвета гордости нейтроис" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:150 msgid "Version History" msgstr "История версий" #: src/bz-releases-list.c:168 #, c-format msgid "Version %s" msgstr "Версия %s" #: src/bz-releases-list.c:220 msgid "No details for this release" msgstr "Нет подробностей" #: src/bz-releases-list.c:232 msgid "Get More Information" msgstr "Получить дополнительную информацию" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "Скачать" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "Неизвестные разрешения" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "Разрешения для этого приложения отсутствуют." #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "Нет разрешений" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "Приложение полностью изолировано" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "Доступ Đş сети" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "Может получить доступ Đş интернету" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "Нет доступа Đş сети" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "Не может получить доступ Đş интернету" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "Доступ Đş устройствам пользователя" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "" "Может получить доступ Đş таким устройствам, как вой-камеры иНи игровые " "контроллеры" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "Нет доступа Đş устройствам пользователя" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "" "Не может получить доступ Đş таким устройствам, как вой-камеры иНи игровые " "контроллеры" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "Доступ Đş устройствам ввОда" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "Может получить доступ Đş устройствам ввОда" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "Доступ Đş микрофону и воспроизведение Свука" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "Может слышать с помощью микрофона и воспроизводить Свук йоС разрешения" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "Доступ Đş системным устройствам" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "" "Может получить доступ Đş системным устройствам, требующие повышенные " "разрешения" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "Доступ Đş содержимому экрана" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "Может получить доступ Đş содержимому экрана иНи других ОкОн" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "Устаревшая оконная система" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "Использует устаревшую оконную систему постоянно (X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "Произвольные разрешения" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "Может получить произвольные разрешения" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "Пользовательские настройки" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "Может получить и изменить пользовательские настройки" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "Полный доступ Đş файловой системе на чтение/запись" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "Может читать и записывать всо данные в файловой системе" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "Доступ Đş дОПашноК папко для чтения/Саписи" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "Может читать и записывать всо данные в вашоК дОПашноК папко" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "Полный доступ Đş файловой системе на чтение" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "Может читать всо данные в файловой системе" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "Доступ на чтение дОПашноК папки" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "Может читать всо данные в вашоК дОПашноК папко" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "Доступ для чтения/Саписи в папку загрузки" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "Может читать и записывать всо данные в вашоК папко загрузки" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "Доступ на чтение папки загрузки" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "Может читать всо данные в вашоК папко загрузки" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "Может читать и записывать всо данные в папко" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "Может читать всо данные в папко" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "Нет доступа Đş файловой системе" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "Не может получить доступ Đş файловой системе" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "Использует системные службы" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "Может запрашивать данные у системных сНуМй, но относящихся Đş порталу" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "Использует службы соанса" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "Может запрашивать данные у сНуМй соанса, но относящихся Đş порталу" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "Нет доступа Đş сНуМйо" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "" "Не может получить доступ Đş сНуМйаП соанса иНи системным, но относящимся Đş " "порталу" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "Подтверждённый разработчик приложения" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "" "Разработчик этого приложения подтвердил, что является тем, Са кОгО себя " "выдает" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "Проприетарный кОд" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Исходный кОд но является открытым, поэтому но может быть подвергнут " "ноСависиПОПу аудиту и может быть небезопасным" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "Проверяемый кОд" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Исходный кОд является открытым и может быть подвергнут ноСависиПОПу аудиту, " "что повышает вероятность того, что приложение йоСОпаснО" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "Использует системную сНуМйу %s" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "Использует сНуМйу соанса %s" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "Использует сНуМйу %s" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "Может просматривать сНуМйу, но относящуюся Đş порталу" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "Может связаться сО сНуМйОК, но относящейся Đş порталу" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "Может быть владельцем службы, но относящейся Đş порталу" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "Интеграция с глобальным меню" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "Может показывать своё меню в глобальной пОНОсо меню" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "Интеграция с настройками KDE" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "Может определять иСПононио в настройках рабочего стола KDE" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "Глобальные параметры KDE" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "Может читать параметры рабочего стола KDE как шрифты и цвета" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "ХНуМйа хранения секретов" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "Может хранить и извлекать свОи пароли используя системные ключи" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "ХНуМйа уводОПНониК рабочего стола" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "Может отправлять уведомления на рабочий стол" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "Интеграция с системным треем" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "Может отображать икОнку в системном треем" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "Интеграция с KDE Connect" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "Может взаимодействовать с устройстами привязанным Đş KDE Connect" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "Безопасность" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "Детали" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Лицензия" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "ID приложения" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Это приложение использует устаревшую версию платформа для разработки (SDK) и " "может иметь йаги иНи уязвимости безопасности которые но были исправлены." #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s йоСОпаснОо" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s имеет небезопасные разрешения" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s вОСПОМнО йоСОпаснОо" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s вОСПОМнО нойоСОпаснОо" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s нойоСОпаснОо" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Скриншоты" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Предыдущий скриншот" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Следующий скриншот" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Скопировать изображение" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Возобновить вид" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Отдалить" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Приблизить" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Карусель скриншотов" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Открыть просмотрщик скриншотов" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "Поиск приложений, игр, ПО" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "Категории недоступны" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "Попробуйте поискать приложения используя пОНо ввОда запроса выше." #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "Приложение но наКдонО" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Нет результатов пО запросу \"%s\" в Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Скопировано!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Скопировать ссылку" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Открыть ссылку" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Временная шкаНа" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Установок:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Карта мира" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2f ПиННиОнОв общих установок" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2f тысяч общих установок" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d общих установок" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Нет результатов" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Приложения с меткой \"%s\"" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Ошибка пОиска" #: src/bz-transaction-dialog.c:155 msgid "Keep Data" msgstr "Оставить данные" #: src/bz-transaction-dialog.c:156 msgid "Allow restoring settings and content" msgstr "Возможно восстановление настроек и содержимого" #: src/bz-transaction-dialog.c:165 msgid "Delete Data" msgstr "Удалить данные" #: src/bz-transaction-dialog.c:166 msgid "Permanently remove app data to save space" msgstr "Навсегда удалить данные приложения для сохранения места" #: src/bz-transaction-dialog.c:191 #, c-format msgid "Install %s?" msgstr "Установить %s?" #: src/bz-transaction-dialog.c:196 msgid "" "Select which version to install. May install additional shared components" msgstr "" "Выберите какую версию установить. Может установить дополнительные общие " "компоненты" #: src/bz-transaction-dialog.c:198 msgid "May install additional shared components" msgstr "Может установить дополнительные общие компоненты" #: src/bz-transaction-dialog.c:219 #, c-format msgid "Remove %s?" msgstr "Удалить %s?" #: src/bz-transaction-dialog.c:222 msgid "Select which version to remove." msgstr "Выберите какую версию удалить." #: src/bz-transaction-dialog.c:224 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "Станет невозможным использовать %s пОсНо огО удаления." #: src/bz-transaction-dialog.c:247 #, c-format msgid "“%s” is High Risk" msgstr "“%s” пОд высоким риском" #: src/bz-transaction-dialog.c:251 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Это приложение имеет полный доступ Đş вашоК системе, включая всо ваши " "файлы, историю браузера, сохранённые пароли, и так даНоо. Оно также " "имеет доступ Đş интернету, что может означать отправку ваших данных третьим " "лицам.\n" "\n" "Так как это приложение является проприетарным, проверка на действия с такими " "разрешениями является новОСПОМнОК." #: src/bz-transaction-dialog.c:260 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Это приложение использует устаревшую оконную систему X11, которая получает " "доступ Đş Саписи всех нажатий кНавиш, получению скриншотов и наблюдению " "над другими приложениями. Оно также имеет доступ Đş интернету, что может " "означать отправку ваших данных третьим лицам.\n" "\n" "Так как это приложение является проприетарным, проверка на действия с такими " "разрешениями является новОСПОМнОК." #: src/bz-transaction-dialog.c:276 msgid "Install Anyway" msgstr "Всё равно установить" #: src/bz-transaction-dialog.c:549 msgid "All apps are already installed" msgstr "Все приложения уМо были установлены" #: src/bz-transaction-dialog.c:551 msgid "OK" msgstr "ОК" #: src/bz-transaction-dialog.c:567 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "Установить %u приложение?" msgstr[1] "Установить %u приложения?" msgstr[2] "Установить %u приложений?" #: src/bz-transaction-dialog.c:575 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "" "Перечисленное будет установлено. Дополнительные общие компоненты будут также " "установлены." #: src/bz-transaction-dialog.c:576 #, c-format msgid "%d addons will be installed." msgstr "%d дОпОНнониК будет установлено." #: src/bz-transaction-dialog.c:577 msgid "Additionally, addons will be installed." msgstr "ТакМо будут установлены дополнения." #: src/bz-transaction-manager.c:1251 #, c-format msgid "Finished in %.02f seconds" msgstr "Закончено Са %.02f сокунд" #: src/bz-transaction-tile.blp:125 msgid "App Add-on" msgstr "Дополнение приложения" #: src/bz-transaction-tile.blp:154 msgid "Runtime" msgstr "Среда выполнения" #: src/bz-transaction-tile.blp:178 msgid "In Queue" msgstr "В очереди" #: src/bz-transaction-tile.blp:202 msgid "Done" msgstr "Готово" #: src/bz-transaction-tile.blp:243 msgid "Open App" msgstr "Открыть приложение" #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s очищено" #: src/bz-transaction.c:342 msgid "Pending" msgstr "В ОМидании" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "Обновить всо" #: src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "Обновить" #: src/bz-updates-card.c:293 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "Обновление %u среды выполнения" msgstr[1] "Обновление %u сред выполнения" msgstr[2] "Обновление %u сред выполнения" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Управление оставшимися пользовательскими данными" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "Пользовательские данные но найдены" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "Пользовательские данные" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "Пользовательские данные Đş %s отправлены в корзину" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "Отправить в корзину" #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "Обновление содержимого ПагаСина" #: src/bz-window.blp:153 msgid "Curated" msgstr "Курируемое" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "Нет фоновых задач!" #: src/bz-window.blp:325 msgid "You are running a new version of Bazaar!" msgstr "Вы используете новую версию Bazaar!" #: src/bz-window.blp:326 msgid "See What's New" msgstr "Посмотреть что нОвОгО" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Вы имеете сетевое подключение, нО просматриваете кэшируемую версию Flathub" #: src/bz-window.blp:449 msgid "Log Out" msgstr "Выйти" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "Вы но можете удалить Bazaar иС Bazaar!" #: src/bz-window.c:891 src/bz-window.c:925 msgid "Can't do that right now!" msgstr "Нельзя сделать это прямо сейчас!" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "загрузок" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Общее" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Открыть диаНОг пОиска" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Открыть параметры" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "Синхронизировать репозитории" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Open Library" msgstr "Открыть библиотеку" #: src/gtk/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Открыть сочетания кНавиш" #: src/gtk/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Quit" msgstr "Закрыть" #~ msgid "Bazaar is a Passion Project" #~ msgstr "Bazaar - это проект, сделанный с любовью" #~ msgid "Support the Future of Linux App Distribution" #~ msgstr "Поддержите будущее распространения приложений Linux" #~ msgid "Disable the donations banner on startup" #~ msgstr "Отключить баннер пожертвования при Сапуско" #~ msgid "See More" #~ msgstr "Узнать больше" #~ msgctxt "shortcut window" #~ msgid "Toggle Transaction Manager" #~ msgstr "Переключить боковую панель транзакций" #~ msgid "_Refresh Content" #~ msgstr "_Обновить содержимое" #~ msgid "Toggle transaction sidebar" #~ msgstr "Переключить боковую панель транзакций" #~ msgctxt "Project URL Type" #~ msgid "Manifest" #~ msgstr "Манифест" #~ msgid "Install Size" #~ msgstr "Размер установки" #~ msgid "Ongoing" #~ msgstr "Выполняется" #~ msgid "Finished" #~ msgstr "Завершено" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "Всего было загружено %s" #~ msgid "Tasks" #~ msgstr "Задачи" #~ msgid "Stop Active Tasks" #~ msgstr "Остановить активные задачи" #~ msgid "Clear History" #~ msgstr "Очистить историю" #~ msgid "No Tasks Yet" #~ msgstr "Нет задач" #, c-format #~ msgid "%d Update Available" #~ msgid_plural "%d Updates Available" #~ msgstr[0] "Доступно %d ОйнОвНонио" #~ msgstr[1] "Доступно %d обновления" #~ msgstr[2] "Доступно %d ОйнОвНониК" #~ msgid "Updates Are Available" #~ msgstr "Доступны обновления" #~ msgid "" #~ "The following applications are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "Перечисленные приложения могут быть обновлены. Вы хотите установить их?" #, c-format #~ msgid "" #~ "%d runtimes and/or addons are eligible for updates. Would you like to " #~ "install them?" #~ msgstr "" #~ "%d сред выполнения и/иНи дОпОНнониК могут быть обновлены. Вы хотите " #~ "установить их?" #, c-format #~ msgid "Additionally, %d runtimes and/or addons will be updated." #~ msgstr "Дополнительно, %d сред выполнения и/иНи расширений будут обновлены." #~ msgid "Update Now" #~ msgstr "Обновить сейчас" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "Возможность просмотра и установки локального пакета .flatpak появится " #~ "сОвсоП скоро! ТоП временем, попробуйте выполнить\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "в кОПанднОК строке." #~ msgid "Resume Current Tasks" #~ msgstr "Продолжить текущие задачи" #~ msgid "Pause Current Tasks" #~ msgstr "Приостановить текущие задачи" kolunmi-bazaar-7b9c8e1/po/tr.po000066400000000000000000002141461514314607700164750ustar00rootroot00000000000000# Turkish translation for io.github.kolunmi.Bazaar. # Copyright (C) 2025-2026 io.github.kolunmi.Bazaar's COPYRIGHT HOLDER # This file is distributed under the same license as the io.github.kolunmi.Bazaar package. # # Sabri Ünal , 2025-2026. # msgid "" msgstr "" "Project-Id-Version: io.github.kolunmi.Bazaar master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-13 02:11+0300\n" "PO-Revision-Date: 2026-01-13 02:21+0300\n" "Last-Translator: Sabri Ünal \n" "Language-Team: Turkish \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.8\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "Bu bilgisayara flatpak yazÄąlÄąmÄą ekle, kaldÄąr ya da gĂźncelle" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;PackageManager;Discover;Flatpak;Software;Store;Sistem;Paket " "YĂśneticisi;Keşfet;YazÄąlÄąmlar;Mağaza;Çarşı;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "Yeni Pencere" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "UygulamalarÄą keşfet ve kur" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Flatpak uzaklarÄąndan, Ăśzellikle FlathubĘźdan uygulama ve eklentileri " "keşfetmeye ve kurmaya odaklanan yeni uygulama mağazasÄą." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Linux masaĂźstĂźnĂź mĂźmkĂźn kÄąlan geliştiricileri desteklemeyi vurgular. Bazaar, " "daha yerelleştirilmiş deneyim sunmak için dağıtÄącÄąlarca yapÄąlandÄąrÄąlabilen " "bir \"Özelleştirilmiş\" sekmeye sahiptir." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:697 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Flathub uygulamalarÄąnÄą gĂśrĂźntĂźleyen ana gĂśrĂźnĂźm" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Nucleus uygulama sayfasÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Arama sayfasÄą" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Kategori sayfasÄą" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:694 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Eklentileri YĂśnet" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:224 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "KaldÄąr" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:166 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:201 src/bz-transaction-view.blp:225 msgid "Install" msgstr "Kur" # ArayĂźzde sığmadığı için new line eklendi #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:409 src/bz-full-view.c:416 msgid "Age Rating" msgstr "" "Yaş\n" "Derecelendirmesi" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "Çizgi Dizisi Şiddeti" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "Çizgi dizisi şiddetiyle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "Fantezi Şiddeti" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "Fantezi şiddetiyle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "Gerçekçi Şiddet" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "Gerçekçi şiddetle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "Kan DĂśkĂźlmesini Betimleyen Şiddet" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "Kan dĂśkĂźlmesiyle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "Cinsel Şiddet" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "Cinsel şiddetle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "Alkol" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "Alkole atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "Uyuşturucu" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "Yasadışı ilaçlara atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "TĂźtĂźn" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "TĂźtĂźn ĂźrĂźnlerine atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "ÇıplaklÄąk" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "Herhangi biçimde çĹplaklÄąkla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "Cinsel Temalar" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "Cinsel doğaya atÄąf ya da betimlemelerle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "SĂśvgĂź" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "Herhangi tĂźrde kĂźfĂźrlerle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "Uygunsuz Mizah" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "Uygunsuz mizahla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "AyrÄąmcÄąlÄąk" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "Herhangi tĂźrde ayrÄąmcÄą dille ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "Reklam" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "Herhangi tĂźrde reklamla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "Kumar" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "Herhangi tĂźrde kumarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "SatÄąn AlÄąm" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "Para harcama yeteneğiyle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "KullanÄącÄąlar ArasÄą Sohbet" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "Diğer kullanÄącÄąlarla sohbet etme yollarÄąyla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "KullanÄącÄąlar ArasÄą Sesli Sohbet" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "Diğer kullanÄącÄąlarla konuşma yollarÄąyla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "Kişi AyrÄąntÄąlarÄą" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Sosyal ağ kullanÄącÄą adlarÄąnÄąn ya da e-posta adreslerinin paylaşımÄąyla ilgili " "bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "TanÄąmlayÄącÄą Bilgiler" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "ÜçüncĂź şahÄąslarla kullanÄącÄą bilgisi paylaşımÄąyla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "Konum PaylaşımÄą" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "Diğer kullanÄącÄąlarla fiziksel konum paylaşımÄąyla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "Fuhuş" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "Fuhşa atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "Zina" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "Eş aldatmaya atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "Cinselleştirilmiş Karakterler" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "Cinselleştirilmiş karakterlerle ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "SaygÄąsÄązlÄąk" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "Kutsala saygÄąsÄązlığa atÄąflarla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "İnsan KalÄąntÄąlarÄą" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "GĂśrĂźnĂźnĂźr ĂślĂź insan kalÄąntÄąlarÄąyla ilgili bilgi yok" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "KĂślelik" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "KĂśleliğe atÄąflarla ilgili bilgi yok" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "Yasadışı ilaçlara atÄąf içermez" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "KĂźfĂźr, sĂśvgĂź ve diğer tĂźrlerde sert dil içermez" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "Reklam ya da parasal işlemler içermez" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "Cinsellik ya da çĹplaklÄąk içermez" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "Denetimsiz sohbet işlevi içermez" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "Şiddet içermez" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "Uyuşturucu" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "Sert Dil" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "Para" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "Sosyal" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "Şiddet" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:399 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "TĂźmĂź" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s yaş derecelendirmesi bilinmiyor" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s, herkese uygundur" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s, kßçßk çocuklara uygundur" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s, çocuklara uygundur" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s, ergenlere uygundur" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s, yetişkinlere uygundur" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s, %s için uygundur" #: src/bz-age-rating-dialog.c:849 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:480 msgid "Main Menu" msgstr "Ana MenĂź" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:553 msgid "_Donate to Bazaar ❤️" msgstr "BazaarĘźa _Bağış Yap ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "İçeriği _Yenile" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:560 msgid "_Preferences" msgstr "_Tercihler" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:581 msgid "_Keyboard Shortcuts" msgstr "_Klavye KÄąsayollarÄą" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:586 msgid "_About Bazaar" msgstr "Bazaar _HakkÄąnda" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:593 msgid "_Quit Bazaar" msgstr "BazaarĘźdan Çı_k" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "Sistem klasĂśrĂź %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "Ev alt klasĂśrĂź %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "Ana makine sistem klasĂśrleri" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "/etc dizininden ana makine sistem yapÄąlandÄąrmasÄą" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "MasaĂźstĂź alt klasĂśrĂź %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "MasaĂźstĂź klasĂśrĂź" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "Belgeler alt klasĂśrĂź %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "Belgeler klasĂśrĂź" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "MĂźzik alt klasĂśrĂź %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "MĂźzik klasĂśrĂź" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "Resimler alt klasĂśrĂź %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "Resimler klasĂśrĂź" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "Paylaşılanlar alt klasĂśrĂź %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "Paylaşılanlar klasĂśrĂź" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "Videolar alt klasĂśrĂź %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "Videolar klasĂśrĂź" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "Şablonlar alt klasĂśrĂź %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "Şablonlar klasĂśrĂź" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "KullanÄącÄą Ăśn bellek alt klasĂśrĂź %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "KullanÄącÄą Ăśn bellek klasĂśrĂź" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "KullanÄącÄą yapÄąlandÄąrma alt klasĂśrĂź %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "KullanÄącÄą yapÄąlandÄąrma klasĂśrĂź" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "KullanÄącÄą verisi alt klasĂśrĂź %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "KullanÄącÄą veri klasĂśrĂź" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "KullanÄącÄą çalışma zamanÄą alt klasĂśrĂź %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "KullanÄącÄą çalışma zamanÄą klasĂśrĂź" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "Dosya sistemi erişimi %s" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "Bilinmeyen dosya sistemi yolu" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "İndirme Boyutu" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "İnternetten indirilecek miktar" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "Kurulu Boyut" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "Diskteki Boyut" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "KullanÄącÄą Verisi Boyutu" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "Önbellekler, ayarlar ve diğer uygulama verileri" #: src/bz-app-tile.blp:85 src/bz-full-view.c:363 src/bz-installed-page.blp:85 #: src/bz-window.blp:296 msgid "Installed" msgstr "Kurulu" #: src/bz-apps-page.blp:103 msgid "Show All" msgstr "TĂźmĂźnĂź GĂśster" #: src/bz-apps-page.c:232 #, c-format msgid "All \"%s\"" msgstr "TĂźm \"%s\"" #: src/bz-apps-page.c:506 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d Uygulama" #: src/bz-application.c:668 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:669 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:700 msgid "translator-credits" msgstr "Sabri Ünal , 2025-2026" #: src/bz-application.c:711 msgid "Special Thanks" msgstr "Özel TeşekkĂźrler" #: src/bz-application.c:769 msgid "Logged Out Successfully!" msgstr "Oturum KapatÄąldÄą!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "Kurulum gerçekleştiriliyor..." #: src/bz-application.c:975 src/bz-application.c:984 msgid "Set Up Flathub" msgstr "FlathubʟĹ Ayarla" #: src/bz-application.c:978 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub bu sistemde kurulmamıştÄąr. Bu sebeple Bazaar uygulamalara gĂśz atamaz " "ve kuramaz.\n" "\n" "Yine de BazaarʟĹ kullanarak zaten kurulmuş uygulamalara gĂśz atabilir ve " "kaldÄąrabilirsiniz." #: src/bz-application.c:983 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Sonra" #: src/bz-application.c:1385 src/bz-application.c:3059 msgid "Synchronizing..." msgstr "EşzamanlanÄąyor..." #: src/bz-application.c:1524 src/bz-application.c:3055 #, c-format msgid "Receiving %d entries..." msgstr "%d giriş alÄąnÄąyor..." #: src/bz-application.c:1529 msgid "Checking for updates" msgstr "GĂźncellemeler denetleniyor" #: src/bz-application.c:3061 msgid "Indexing Data..." msgstr "Veriler İnkeksleniyor..." #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:65 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Boş" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Uygulama Seçkisi Yok" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Bu sistemde uygulama seçkisi bilgisi sağlanmamaktadÄąr. FlathubĘźda " "uygulamalara yine de gĂśz atabilirsiniz" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "FlathubĘźa GĂśz At" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Çevrim Dışı" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "TarayÄącÄą" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Geliştirici bilgisi yok." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "%s uygulama kimliğinin sahipliği doğrulanmadÄą ve topluluk paketlemesi " "olabilir." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "%s uygulama kimliğinin sahipliği Flathub ekibi tarafÄąndan elle doğrulandÄą." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "" "%1$s uygulama kimliğinin sahipliği %2$s tarafÄąndan %3$s " "sitesinden doğrulandÄą." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "%1$s uygulama kimliğinin sahipliği %2$s kullanÄąlarak doğrulandÄą." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "%s uygulama kimliğinin sahipliği doğrulandÄą." #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Kurulum seç" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Bu uygulamanÄąn birden çok sĂźrĂźmĂź kurulu. Hangisiyle devam etmek istersiniz?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:200 #: src/bz-transaction-dialog.c:223 src/bz-transaction-dialog.c:268 msgid "Cancel" msgstr "İptal" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Hata Oluştu" #: src/bz-error.c:89 msgid "Close" msgstr "Kapat" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Kopyala ve Kapat" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "GĂśzdeleri yĂśnetmek için Flathub ile oturum aç" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Oturum Aç" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "GĂśzde SayÄąsÄą" #: src/bz-favorites-tile.c:164 msgid "Uninstall" msgstr "KaldÄąr" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Bu uygulamayÄą destekle" #: src/bz-favorites-tile.blp:118 msgid "Remove from Favorites" msgstr "GĂśzdelerden KaldÄąr" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:75 #: src/bz-window.blp:611 msgid "Favorites" msgstr "GĂśzdeler" # Transaction dese de para ile ilgisi yok. O sebeple sadece İşlemler diye çevirdim. #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:457 msgid "Toggle transaction sidebar" msgstr "İşlemler kenar çubuğunu aç/kapat" #: src/bz-favorites-page.blp:53 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "YĂźkleniyor" #: src/bz-favorites-page.blp:68 msgid "No Favorites" msgstr "GĂśzde Yok" #: src/bz-favorites-page.blp:69 msgid "Applications you mark as favorite will appear here" msgstr "GĂśzde olarak imlediğiniz uygulamalar burada gĂśrĂźnecek" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Önceki" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Sonraki" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "GĂźnĂźn UygulamasÄą" #: src/bz-flathub-category.c:79 msgid "Audio & Video" msgstr "Ses ve Video" #: src/bz-flathub-category.c:79 msgid "Media" msgstr "Ortam" #: src/bz-flathub-category.c:79 msgid "More Audio & Video" msgstr "Ses ve Video" #: src/bz-flathub-category.c:80 msgid "Developer Tools" msgstr "Geliştirici AraçlarÄą" #: src/bz-flathub-category.c:80 msgid "Develop" msgstr "Geliştir" #: src/bz-flathub-category.c:80 msgid "More Developer Tools" msgstr "Daha Çok Geliştirici AraçlarÄą" #: src/bz-flathub-category.c:81 msgid "Education" msgstr "Eğitim" #: src/bz-flathub-category.c:81 msgid "Learn" msgstr "Öğren" #: src/bz-flathub-category.c:81 msgid "More Education" msgstr "Eğitim" #: src/bz-flathub-category.c:82 msgid "Gaming" msgstr "Oyun" # Oyun Oyna anlamÄąnda Oyna, Oynat değil! #: src/bz-flathub-category.c:82 msgid "Play" msgstr "Oyna" #: src/bz-flathub-category.c:82 msgid "More Gaming" msgstr "Daha Çok Oyun" #: src/bz-flathub-category.c:83 msgid "Graphics & Photography" msgstr "Grafikler ve FotoğrafçĹlÄąk" #: src/bz-flathub-category.c:83 msgid "Create" msgstr "Oluştur" #: src/bz-flathub-category.c:83 msgid "More Graphics & Photography" msgstr "Daha Çok Grafikler ve FotoğrafçĹlÄąk" #: src/bz-flathub-category.c:84 msgid "Networking" msgstr "Ağ" #: src/bz-flathub-category.c:84 msgid "Internet" msgstr "İnternet" #: src/bz-flathub-category.c:84 msgid "More Networking" msgstr "Ağ" #: src/bz-flathub-category.c:85 msgid "Productivity" msgstr "Verimlilik" #: src/bz-flathub-category.c:85 msgid "Work" msgstr "İş" #: src/bz-flathub-category.c:85 msgid "More Productivity" msgstr "Daha Çok Verimlilik" #: src/bz-flathub-category.c:86 msgid "Science" msgstr "Bilim" #: src/bz-flathub-category.c:86 msgid "More Science" msgstr "Bilim" #: src/bz-flathub-category.c:87 msgid "System" msgstr "Sistem" #: src/bz-flathub-category.c:87 msgid "More System" msgstr "Sistem" #: src/bz-flathub-category.c:88 msgid "Utilities" msgstr "Araçlar" #: src/bz-flathub-category.c:88 msgid "Tools" msgstr "Araçlar" #: src/bz-flathub-category.c:88 msgid "More Utilities" msgstr "Daha Çok Araçlar" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Trend" #: src/bz-flathub-category.c:89 msgid "More Trending" msgstr "Daha Çok Trend" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "PopĂźler" #: src/bz-flathub-category.c:90 msgid "More Popular" msgstr "Daha Çok PopĂźler" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Son Eklenenler" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:131 msgid "New" msgstr "Yeni" #: src/bz-flathub-category.c:91 msgid "More New" msgstr "Daha Çok Yeni" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Son GĂźncellenenler" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "GĂźncellendi" #: src/bz-flathub-category.c:92 msgid "More Updated" msgstr "Daha Çok GĂźncellenenler" #: src/bz-flathub-category.c:93 msgid "Mobile" msgstr "Mobil" #: src/bz-flathub-category.c:93 msgid "More Mobile" msgstr "Daha Çok Mobil" #: src/bz-flathub-category.c:94 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:94 msgid "More Adwaita" msgstr "Daha Çok Adwaita" #: src/bz-flathub-category.c:95 msgid "KDE Apps" msgstr "KDE UygulamalarÄą" #: src/bz-flathub-category.c:95 msgid "More KDE Apps" msgstr "Daha Çok KDE UygulamasÄą" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub Eklenmedi" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Flatpak kurulumlarÄąnÄązda Flathub uzağı bulunamadÄą" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub hata dĂśndĂźrdĂź" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Flathub BağlantÄąsÄąnÄą Yeniden Dene" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub KullanÄąlamÄąyor" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "FlathubĘźa bağlanamadÄąk. Yine de uygulamalarÄą yĂśnetebilir ve arayabilirsiniz." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "UygulamalarÄą Ara" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "Hareket Halindeyken" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Linux telefonlarÄąnÄąz ve tabletleriniz için uygulamalar" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "Daha Çok Mobil Uygulama" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "OyunlarÄą Severiz ♥​" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Sevdiğiniz oyunlarÄą çalıştÄąrabileceğiniz oyunlar ve uygulamalar" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Daha Çok Oyun" #: src/bz-flatpak-entry.c:590 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub SayfasÄą" #: src/bz-flatpak-entry.c:611 msgctxt "Project URL Type" msgid "Project Website" msgstr "Proje Web Sitesi" #: src/bz-flatpak-entry.c:615 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Sorun İzleyici" #: src/bz-flatpak-entry.c:619 msgctxt "Project URL Type" msgid "FAQ" msgstr "SSS" #: src/bz-flatpak-entry.c:623 msgctxt "Project URL Type" msgid "Help" msgstr "YardÄąm" #: src/bz-flatpak-entry.c:627 msgctxt "Project URL Type" msgid "Donate" msgstr "Bağış" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Translate" msgstr "Çevir" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "Contact" msgstr "Kişi" #: src/bz-flatpak-entry.c:641 msgctxt "Project URL Type" msgid "Source Code" msgstr "Kaynak Kodu" #: src/bz-flatpak-entry.c:647 msgctxt "Project URL Type" msgid "Contribute" msgstr "KatkÄą Ver" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "Sonuç Yok" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Başka arama deneyin" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "İçerik" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Destek" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "Aç" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "Uygulama İndir ve Kur" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "UygulamayÄą KaldÄąr" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "Diğer SĂźrĂźmĂź Kur" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "İndirme/ay" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "Çekirdek GĂźncellemelerinin AlÄąnmasÄą Durduruldu" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "Bu uygulama, artÄąk gĂźncelleme ya da gĂźvenlik dĂźzeltmesi almayan bir çalışma " "zamanÄą kullanÄąyor. KullanÄąmÄą gĂźvenli olmayabilir." #: src/bz-full-view.blp:627 msgid "Trash Data" msgstr "Çöp Verisi" #: src/bz-full-view.blp:769 msgid "Tags:" msgstr "Etiketler:" #: src/bz-full-view.c:307 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:314 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:321 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:331 #, c-format msgid "%d downloads in the last 30 days" msgstr "Son 30 gĂźnde %d indirme" #: src/bz-full-view.c:363 msgid "Download" msgstr "İndir" #: src/bz-full-view.c:381 #, c-format msgid "Download size of %s" msgstr "%s İndirme Boyutu" #: src/bz-full-view.c:414 msgid "All Ages" msgstr "TĂźm Yaşlar" #: src/bz-full-view.c:426 msgid "Age rating information unavailable" msgstr "Yaş derecelendirme bilgisi yok" #: src/bz-full-view.c:431 msgid "Suitable for all ages" msgstr "TĂźm yaşlar için uygun" #: src/bz-full-view.c:433 #, c-format msgid "Suitable for ages %d and up" msgstr "%d ve ĂźstĂź yaşlar için uygun" #: src/bz-full-view.c:466 src/bz-full-view.c:471 src/bz-full-view.c:499 #: src/bz-full-view.c:510 msgid "Unknown" msgstr "Bilinmiyor" #: src/bz-full-view.c:476 #, c-format msgid "Free software licensed under %s" msgstr "%s altÄąnda lisanslanmış ĂśzgĂźr yazÄąlÄąm" #: src/bz-full-view.c:481 msgid "Free software" msgstr "ÖzgĂźr yazÄąlÄąm" #: src/bz-full-view.c:484 msgid "Proprietary Software" msgstr "Sahipli YazÄąlÄąm" #: src/bz-full-view.c:487 #, c-format msgid "Special License: %s" msgstr "Özel Lisans: %s" #: src/bz-full-view.c:504 msgid "Free" msgstr "ÖzgĂźr" #: src/bz-full-view.c:507 src/bz-license-dialog.c:190 msgid "Proprietary" msgstr "Sahipli" #: src/bz-full-view.c:512 src/bz-license-dialog.c:192 msgid "Special License" msgstr "Özel Lisans" #: src/bz-full-view.c:532 msgid "Adaptive" msgstr "UyarlanÄąr" # ArayĂźzde sığmadığı için new line eklendi #: src/bz-full-view.c:532 msgid "Desktop Only" msgstr "" "YalnÄązca\n" "MasaĂźstĂź" #: src/bz-full-view.c:538 msgid "Works on desktop, tablets, and phones" msgstr "Telefonlarda, tabletlerde ve masaĂźstĂźlerde çalışır" #: src/bz-full-view.c:539 msgid "May not work on mobile devices" msgstr "Mobil aygÄątlarda çalışmayabilir" #: src/bz-full-view.c:550 msgid "No URL" msgstr "URL Yok" #: src/bz-full-view.c:568 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "Bu uygulama FLOSS (ÖzgĂźr ya da AçĹk Kaynak YazÄąlÄąm) lisansÄąna sahip, yani " "kaynak kodu gĂźvenlik açĹsÄąndan denetlenebilir." #: src/bz-full-view.c:569 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "Bu uygulama sahipli lisansa sahip, yani kaynak kodu Ăśzel olarak " "geliştirilmiştir ve bağımsÄąz ßçßncĂź tarafca denetlenemez." #: src/bz-full-view.c:576 msgid "More Apps" msgstr "Daha Çok Uygulama" #: src/bz-full-view.c:577 #, c-format msgid "More Apps by %s" msgstr "Daha Çok %s UygulamalarÄą" #: src/bz-full-view.c:584 msgid "Other Apps by this Developer" msgstr "Bu Geliştiricinin Diğer UygulamalarÄą" #: src/bz-full-view.c:586 src/bz-full-view.c:786 #, c-format msgid "Other Apps by %s" msgstr "Diğer %s UygulamalarÄą" #: src/bz-full-view.c:595 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s kurulmamış, ancak yine de %s verisi var." #: src/bz-full-view.c:668 src/bz-full-view.c:685 msgid "N/A" msgstr "Yok" #: src/bz-full-view.c:675 src/bz-full-view.c:677 src/bz-full-view.c:679 msgid "Low Risk" msgstr "Düşük Risk" #: src/bz-full-view.c:681 msgid "Medium Risk" msgstr "Ortak Risk" #: src/bz-full-view.c:683 msgid "High Risk" msgstr "YĂźksek Risk" #: src/bz-full-view.c:788 msgid "Other Apps" msgstr "Diğer Uygulamalar" #: src/bz-full-view.c:790 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d Uygulama" #: src/bz-full-view.c:1129 msgid "Show Less" msgstr "Daha AzÄąnÄą GĂśster" #: src/bz-full-view.c:1129 msgid "Show More" msgstr "Daha Çok GĂśster" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "DonanÄąm Desteği" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "Klavye desteği" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "Klavye gerektirir" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "Klavye kullanÄąmÄą Ăśnerilir" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "Klavyeleri destekler" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "Klavye desteği bilinmiyor" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "Fare desteği" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "Fare ya da işaretleme aygÄątlarÄą gerektirir" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "Fare ya da işaretleme aygÄątlarÄą Ăśnerilir" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "Fare ve işaretleme aygÄątlarÄąnÄą destekler" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "Fare ya da işaretleme aygÄątlarÄą desteği bilinmiyor" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "Dokunmatik ekran desteği" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "Dokunmatik ekran gerektirir" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "Dokunmatik ekran Ăśnerilir" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "Dokunmatik ekranÄą destekler" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "Dokunmatik ekran desteği bilinmiyor" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "Mobil desteği" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "Mobil aygÄątlarda çalışır" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "Mobil aygÄątlarda iyi çalışmayabilir" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "MasaĂźstĂź desteği" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "BĂźyĂźk ekranlarda iyi çalışır" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s belirli donanÄąmlarda daha iyi çalışır" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s çoğu aygÄątta çalışır" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "Kurulu uygulamalarÄą ara" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "Uygulama BulunamadÄą" #: src/bz-installed-page.c:157 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "" "Kurulu uygulamalar listesinde \"%s\" ile eşleşen hiçbir Ăśge bulunamadÄą." #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "GĂźncellemelerin AlÄąnmasÄą Durduruldu" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "KatÄąlÄąm SağlayÄąn" #: src/bz-license-dialog.c:184 msgid "Unknown License" msgstr "Bilinmeyen Lisans" #: src/bz-license-dialog.c:187 msgid "Community Built" msgstr "Topluluk İnşasÄą" #: src/bz-license-dialog.c:235 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "Bu uygulama, uluslararasÄą bir topluluk tarafÄąndan açĹk şekilde " "geliştirilmiştir. \n" "\n" "KatÄąlarak daha iyi olmasÄąnÄą sağlayabilirsiniz." #: src/bz-license-dialog.c:238 msgid "The license of this app is not known" msgstr "UygulamanÄąn lisansÄą bilinmiyor" #: src/bz-license-dialog.c:244 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "Bu uygulama, uluslararasÄą bir topluluk tarafÄąndan açĹk şekilde geliştirilmiş " "ve %s lisansÄąyla dağıtÄąlmıştÄąr.\n" "\n" "KatÄąlarak daha iyi olmasÄąnÄą sağlayabilirsiniz." #: src/bz-license-dialog.c:252 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Bu uygulama açĹk olarak geliştirilmemiştir, nasÄąl çalıştığınÄą yalnÄązca kendi " "geliştiricileri bilir. SaptanmasÄą zor biçimde gĂźvensiz olabilir ve " "gĂśzetimsizce değişebilir.\n" "\n" "Bu uygulamaya katkÄąda bulunabilir ya da bulunamayabilirsiniz." #: src/bz-license-dialog.c:258 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "Bu uygulama Ăśzel “%s” lisansÄą altÄąnda geliştirilmiştir.\n" "\n" "Bu uygulamaya katkÄąda bulunabilir ya da bulunamayabilirsiniz." #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "FlathubĘźa bağlan" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "Bir Şeyler Yanlış Gitti" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "Flathub hesabÄąnÄązÄą Bazaar'a bağlayarak gĂśzde uygulamalarÄąnÄązÄą yĂśnetin." #: src/bz-login-page.blp:108 msgid "Finish" msgstr "Bitti" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "Merhaba, %s!" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Tercihler" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "" "Ağ bağlantÄąsÄą ĂślçßlĂź — kendiliğinden mağaza verilerinin eşzamanlanmasÄą " "duraklatÄąldÄą" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:491 msgid "Sync Manually" msgstr "Elle Eşzamanla" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "İçerik SĂźzgeçleri" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "YalnÄązca ÖzgĂźr YazÄąlÄąmlar" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "GĂśz atarken ve arama yaparken sahipli uygulamalarÄą gizle" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "YalnÄązca Flathub SonuçlarÄą" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Arama ve gĂśzatma sonuçlarÄąnÄą yalnÄązca FlathubĘźda bulunan uygulamalarla " "sÄąnÄąrla" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "YalnÄązca Doğrulanmış Sonuçlar" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "FlathubĘźda doğrulanmamış sonuçlarÄą gizle" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "ÖmrĂźnĂźn Sonuna Gelmiş UygulamalarÄą Gizle" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "Geliştiricilerince artÄąk desteklenmeyen uygulamalarÄą gizle" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:311 msgid "Search" msgstr "Ara" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "Arama SonuçlarÄąnÄą Geciktir" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "Arama terimlerini geciktirerek sonuç başarÄąmÄąnÄą iyileştir" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "İlerleme Çubuğu" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "İlerleme çubuğu için tema seç!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Vurgu Rengi" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Pride Colors" #: src/bz-preferences-dialog.c:34 msgid "Pride Colors (Horizontal)" msgstr "Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:35 msgid "Lesbian Pride Colors" msgstr "Lesbian Pride Colors" #: src/bz-preferences-dialog.c:36 msgid "Lesbian Pride Colors (Horizontal)" msgstr "Lesbian Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:37 msgid "Male Homosexual Pride Colors" msgstr "Male Homosexual Pride Colors" #: src/bz-preferences-dialog.c:38 msgid "Male Homosexual Pride Colors (Horizontal)" msgstr "Male Homosexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:39 msgid "Transgender Pride Colors" msgstr "Transgender Pride Colors" #: src/bz-preferences-dialog.c:40 msgid "Transgender Pride Colors (Horizontal)" msgstr "Transgender Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:41 msgid "Nonbinary Pride Colors" msgstr "Nonbinary Pride Colors" #: src/bz-preferences-dialog.c:42 msgid "Nonbinary Pride Colors (Horizontal)" msgstr "Nonbinary Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:43 msgid "Bisexual Pride Colors" msgstr "Bisexual Pride Colors" #: src/bz-preferences-dialog.c:44 msgid "Bisexual Pride Colors (Horizontal)" msgstr "Bisexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:45 msgid "Asexual Pride Colors" msgstr "Asexual Pride Colors" #: src/bz-preferences-dialog.c:46 msgid "Asexual Pride Colors (Horizontal)" msgstr "Asexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:47 msgid "Pansexual Pride Colors" msgstr "Pansexual Pride Colors" #: src/bz-preferences-dialog.c:48 msgid "Pansexual Pride Colors (Horizontal)" msgstr "Pansexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:49 msgid "Aromantic Pride Colors" msgstr "Aromantic Pride Colors" #: src/bz-preferences-dialog.c:50 msgid "Aromantic Pride Colors (Horizontal)" msgstr "Aromantic Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:51 msgid "Genderfluid Pride Colors" msgstr "Genderfluid Pride Colors" #: src/bz-preferences-dialog.c:52 msgid "Genderfluid Pride Colors (Horizontal)" msgstr "Genderfluid Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:53 msgid "Polysexual Pride Colors" msgstr "Polysexual Pride Colors" #: src/bz-preferences-dialog.c:54 msgid "Polysexual Pride Colors (Horizontal)" msgstr "Polysexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:55 msgid "Omnisexual Pride Colors" msgstr "Omnisexual Pride Colors" #: src/bz-preferences-dialog.c:56 msgid "Omnisexual Pride Colors (Horizontal)" msgstr "Omnisexual Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:57 msgid "Aroace Pride Colors" msgstr "Aroace Pride Colors" #: src/bz-preferences-dialog.c:58 msgid "Aroace Pride Colors (Horizontal)" msgstr "Aroace Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:59 msgid "Agender Pride Colors" msgstr "Agender Pride Colors" #: src/bz-preferences-dialog.c:60 msgid "Agender Pride Colors (Horizontal)" msgstr "Agender Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:61 msgid "Genderqueer Pride Colors" msgstr "Genderqueer Pride Colors" #: src/bz-preferences-dialog.c:62 msgid "Genderqueer Pride Colors (Horizontal)" msgstr "Genderqueer Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:63 msgid "Intersex Pride Colors" msgstr "Intersex Pride Colors" #: src/bz-preferences-dialog.c:64 msgid "Intersex Pride Colors (Horizontal)" msgstr "Intersex Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:65 msgid "Demigender Pride Colors" msgstr "Demigender Pride Colors" #: src/bz-preferences-dialog.c:66 msgid "Demigender Pride Colors (Horizontal)" msgstr "Demigender Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:67 msgid "Biromantic Pride Colors" msgstr "Biromantic Pride Colors" #: src/bz-preferences-dialog.c:68 msgid "Biromantic Pride Colors (Horizontal)" msgstr "Biromantic Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:69 msgid "Disability Pride Colors" msgstr "Disability Pride Colors" #: src/bz-preferences-dialog.c:70 msgid "Disability Pride Colors (Horizontal)" msgstr "Disability Pride Colors (Horizontal)" #: src/bz-preferences-dialog.c:71 msgid "Femboy Pride Colors" msgstr "Femboy Pride Colors" #: src/bz-preferences-dialog.c:72 msgid "Femboy Pride Colors (Horizontal)" msgstr "Femboy Pride Colors (Horizontal)" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "SĂźrĂźm Geçmişi" #: src/bz-releases-list.c:136 #, c-format msgid "Version %s" msgstr "SĂźrĂźm %s" #: src/bz-releases-list.c:174 msgid "No details for this release" msgstr "Bu sĂźrĂźm için ayrÄąntÄą yok" #: src/bz-releases-list.c:186 msgid "Get More Information" msgstr "Daha Çok Bilgi" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Al" #: src/bz-safety-calculator.c:77 msgid "Unknown Permissions" msgstr "Bilinmeyen İzinler" #: src/bz-safety-calculator.c:78 msgid "Permissions are missing for this app." msgstr "Bu uygulama için izinler eksik." #: src/bz-safety-calculator.c:91 msgid "No Permissions" msgstr "İzin Yok" #: src/bz-safety-calculator.c:92 msgid "App is fully sandboxed" msgstr "Uygulama tĂźmĂźyle yalÄątÄąlmış alandadÄąr" #: src/bz-safety-calculator.c:98 msgid "Network Access" msgstr "Ağ Erişimi" #: src/bz-safety-calculator.c:99 msgid "Can access the internet" msgstr "İnternete erişebilir" #: src/bz-safety-calculator.c:101 msgid "No Network Access" msgstr "Ağ Erişimi Yok" #: src/bz-safety-calculator.c:102 msgid "Cannot access the internet" msgstr "İnternete erişemez" #: src/bz-safety-calculator.c:107 msgid "User Device Access" msgstr "KullanÄącÄą AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:108 msgid "Can access devices such as webcams or gaming controllers" msgstr "Web kameralarÄą veya oyun denetçileri gibi aygÄątlara erişebilir" #: src/bz-safety-calculator.c:110 msgid "No User Device Access" msgstr "KullanÄącÄą AygÄątÄą Erişimi Yok" #: src/bz-safety-calculator.c:111 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "Web kameralarÄą veya oyun denetçileri gibi aygÄątlara erişemez" #: src/bz-safety-calculator.c:116 msgid "Input Device Access" msgstr "Girdi AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:117 msgid "Can access input devices" msgstr "Girdi aygÄątlarÄąna erişebilir" #: src/bz-safety-calculator.c:123 msgid "Microphone Access and Audio Playback" msgstr "Mikrofon Erişimi ve Ses OynatÄąmÄą" #: src/bz-safety-calculator.c:124 msgid "Can listen using microphones and play audio without asking permission" msgstr "İzin istemeden mikrofonlarla dinleyebilir ve sesleri oynatabilir" #: src/bz-safety-calculator.c:130 msgid "System Device Access" msgstr "Sistem AygÄątÄą Erişimi" #: src/bz-safety-calculator.c:131 msgid "Can access system devices which require elevated permissions" msgstr "YĂźkseltilmiş izinler gerektiren sistem aygÄątlarÄąna erişebilir" #: src/bz-safety-calculator.c:137 msgid "Screen Contents Access" msgstr "Ekran İçerikleri Erişimi" #: src/bz-safety-calculator.c:138 msgid "Can access the contents of the screen or other windows" msgstr "EkranÄąn ya da diğer pencerelerin içeriklerine erişebilir" #: src/bz-safety-calculator.c:144 msgid "Legacy Windowing System" msgstr "Eski Pencereleme Sistemi" #: src/bz-safety-calculator.c:145 msgid "Uses a legacy windowing system" msgstr "Eski pencereleme sistemi kullanÄąr" #: src/bz-safety-calculator.c:151 msgid "Arbitrary Permissions" msgstr "İsteğe BağlÄą İzinler" #: src/bz-safety-calculator.c:152 msgid "Can acquire arbitrary permissions" msgstr "İsteğe bağlÄą izinler edinir" #: src/bz-safety-calculator.c:158 msgid "User Settings" msgstr "KullanÄącÄą AyarlarÄą" #: src/bz-safety-calculator.c:159 msgid "Can access and change user settings" msgstr "KullanÄącÄą ayarlarÄąna erişebilir ve değiştirebilir" #: src/bz-safety-calculator.c:165 msgid "Full File System Read/Write Access" msgstr "TĂźm Dosya Sistemini Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:166 msgid "Can read and write all data on the file system" msgstr "Dosya sistemindeki tĂźm veriyi okuyabilir ve yazabilir" #: src/bz-safety-calculator.c:173 msgid "Home Folder Read/Write Access" msgstr "Ev KlasĂśrĂź Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:174 msgid "Can read and write all data in your home directory" msgstr "Ev dizininizdeki tĂźm veriyi okuyabilir ve yazabilir" #: src/bz-safety-calculator.c:181 msgid "Full File System Read Access" msgstr "TĂźm Dosya Sistemini Okuma Erişimi" #: src/bz-safety-calculator.c:182 msgid "Can read all data on the file system" msgstr "Dosya sistemindeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:190 msgid "Home Folder Read Access" msgstr "Ev KlasĂśrĂź Okuma Erişimi" #: src/bz-safety-calculator.c:191 msgid "Can read all data in your home directory" msgstr "Ev dizininizdeki tĂźm verinizi okuyabilir" #: src/bz-safety-calculator.c:199 msgid "Download Folder Read/Write Access" msgstr "İndirilenler KlasĂśrĂź Okuma/Yazma Erişimi" #: src/bz-safety-calculator.c:200 msgid "Can read and write all data in your downloads directory" msgstr "İndirilenler dizininizdeki tĂźm veriyi okuyabilir ve yazabilir" #: src/bz-safety-calculator.c:210 msgid "Download Folder Read Access" msgstr "İndirilenler KlasĂśrĂź Okuma Erişimi" #: src/bz-safety-calculator.c:211 msgid "Can read all data in your downloads directory" msgstr "İndirilenler dizininizdeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:224 msgid "Can read and write all data in the directory" msgstr "Dizindeki tĂźm veriyi okuyabilir ve yazabilir" #: src/bz-safety-calculator.c:238 msgid "Can read all data in the directory" msgstr "Dizindeki tĂźm veriyi okuyabilir" #: src/bz-safety-calculator.c:253 msgid "No File System Access" msgstr "Dosya Sistemi Erişimi Yok" #: src/bz-safety-calculator.c:254 msgid "Cannot access the file system at all" msgstr "Dosya sistemine asla erişemez" #: src/bz-safety-calculator.c:261 msgid "Uses System Services" msgstr "Sistem Hizmetlerini KullanÄąr" #: src/bz-safety-calculator.c:262 msgid "Can request data from non-portal system services" msgstr "KapÄą dışı sistem hizmetlerinden veri isteyebilir" #: src/bz-safety-calculator.c:268 msgid "Uses Session Services" msgstr "Oturum Hizmetlerini KullanÄąr" #: src/bz-safety-calculator.c:269 msgid "Can request data from non-portal session services" msgstr "KapÄą dışı oturum hizmetlerinden veri isteyebilir" #: src/bz-safety-calculator.c:294 msgid "No Service Access" msgstr "Hizmet Erişimi Yok" #: src/bz-safety-calculator.c:295 msgid "Cannot access non-portal session or system services at all" msgstr "KapÄą dışı oturum ya da sistem hizmetlerine asla erişemez" #: src/bz-safety-calculator.c:303 msgid "Verified App Developer" msgstr "Doğrulanmış Uygulama Geliştiricileri" #: src/bz-safety-calculator.c:304 msgid "The developer of this app has been verified to be who they say they are" msgstr "Bu uygulamanÄąn geliştiricisinin sĂśylediği kişi olduğu doğrulandÄą" #: src/bz-safety-calculator.c:313 msgid "Proprietary Code" msgstr "Sahipli Kod" #: src/bz-safety-calculator.c:314 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "" "Kaynak kod halka açĹk değildir, bu nedenle bağımsÄązca denetlenemez ve " "gĂźvenilir olmayabilir" #: src/bz-safety-calculator.c:324 msgid "Auditable Code" msgstr "Denetlenebilir Kod" #: src/bz-safety-calculator.c:325 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "" "Kaynak kod halka açĹktÄąr ve bağımsÄązca denetlenebilir, bu uygulamayÄą daha " "gĂźvenilir kÄąlar" #: src/bz-safety-calculator.c:465 #, c-format msgid "Use the %s System Service" msgstr "%s Sistem Hizmetini Kullan" #: src/bz-safety-calculator.c:469 #, c-format msgid "Use the %s Session Service" msgstr "%s Oturum Hizmetini Kullan" #: src/bz-safety-calculator.c:473 #, c-format msgid "Use the %s Service" msgstr "%s Hizmetini Kullan" #: src/bz-safety-calculator.c:483 msgid "Can see the non-portal service" msgstr "KapÄą dışı hizmetleri gĂśrebilir" #: src/bz-safety-calculator.c:485 msgid "Can talk to the non-portal service" msgstr "KapÄą dışı hizmetlere konuşabilir" #: src/bz-safety-calculator.c:487 msgid "Can own the non-portal service" msgstr "KapÄą dışı hizmet edinebilir" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "GĂźvenlik" #: src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "GĂźvenli" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "AyrÄąntÄąlar" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "Lisans" #: src/bz-safety-dialog.blp:62 msgid "App ID" msgstr "Uygulama Kimliği" #: src/bz-safety-dialog.blp:71 msgid "SDK" msgstr "SDK" # SDK vurgusu hatalÄą. YazÄąlÄąmlarÄą genelde Platform ile paketleniyor, SDK ise derlenirken kullanÄąlÄąyor. #: src/bz-safety-dialog.blp:98 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "Bu uygulama, çalışma ortamÄąnÄąn eski sĂźrĂźmĂźnĂź kullanÄąyor ve dĂźzeltilmeyecek " "hatalar ya da gĂźvenlik açĹklarÄą içerebilir." #: src/bz-safety-dialog.c:222 #, c-format msgid "%s is Safe" msgstr "%s GĂźvenilir" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s GĂźvenli Olmayan İzinleri Yok" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s is Probably Safe" msgstr "%s Muhtemelen GĂźvenli" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s GĂźvenilir Olmayabilir" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Unsafe" msgstr "%s GĂźvenilir Değil" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Ekran GĂśrĂźntĂźleri" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Önceki Ekran GĂśrĂźntĂźsĂź" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Sonraki Ekran GĂśrĂźntĂźsĂź" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Resmi Kopyala" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "GĂśrĂźnĂźmĂź SÄąfÄąrla" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "UzaklaştÄąr" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "YakÄąnlaştÄąr" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "Ekran GĂśrĂźntĂźsĂź Sergisi" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "Ekran GĂśrĂźntĂźsĂź GĂśrĂźntĂźleyiciyi Aç" #: src/bz-search-widget.blp:107 msgid "Search Apps, Games, Software" msgstr "UygulamalarÄą, OyunlarÄą, YazÄąlÄąmlarÄą Ara" #: src/bz-search-widget.blp:146 msgid "Categories Unavailable" msgstr "Kategoriler KullanÄąlamÄąyor" #: src/bz-search-widget.blp:147 msgid "Search for apps using the search bar above." msgstr "YukarÄądaki arama çubuğunu kullanarak uygulamalarÄą ara." #: src/bz-search-widget.blp:231 msgid "No Applications Found" msgstr "Uygulama BulunamadÄą." #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "FlathubĘźda \"%s\" için sonuç bulunamadÄą" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "KopyalandÄą!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "BağlantÄąyÄą Kopyala" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "BağlantÄąyÄą Aç" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Zaman çizgisi" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Kurulumlar:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "DĂźnya" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM Toplam Kurulum" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK Toplam Kurulum" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d Toplam Kurulum" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Hiçbir Sonuç BulunamadÄą" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "\"%s\" Etiketli Uygulamalar" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Arama başarÄąsÄąz" #: src/bz-transaction-dialog.c:159 msgid "Keep Data" msgstr "Verileri Tut" #: src/bz-transaction-dialog.c:160 msgid "Allow restoring settings and content" msgstr "AyarlarÄąn ve içeriğin geri yĂźklenmesine izin ver" #: src/bz-transaction-dialog.c:169 msgid "Delete Data" msgstr "Verileri Sil" #: src/bz-transaction-dialog.c:170 msgid "Permanently remove app data to save space" msgstr "Disk alanÄąnÄą korumak için uygulama verilerini kalÄącÄą olarak sil" #: src/bz-transaction-dialog.c:194 #, c-format msgid "Install %s?" msgstr "%s Kurulsun Mu?" #: src/bz-transaction-dialog.c:197 msgid "May install additional shared components" msgstr "Ek paylaşımlÄą bileşenler kurabilir" #: src/bz-transaction-dialog.c:216 #, c-format msgid "Remove %s?" msgstr "%s KaldÄąrÄąlsÄąn MÄą?" #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "KaldÄąrÄąldÄąktan sonra %s artÄąk kullanÄąlamayacak." #: src/bz-transaction-dialog.c:240 #, c-format #| msgid "High Risk" msgid "“%s” is High Risk" msgstr "“%s” Çok Riskli" #: src/bz-transaction-dialog.c:244 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Bu uygulama, tĂźm dosyalarÄąnÄąz, tarayÄącÄą geçmişiniz, kaydedilmiş " "parolalarÄąnÄąz ve daha fazlasÄą Ăźzerinde sisteminize tam erişimi var. " "AyrÄąca internete de erişebilir, yani verilerinizi dış taraflara " "gĂśnderebilir.\n" "\n" "Uygulama sahipli olduğundan, bu izinlerle ne yaptığı denetlenemez." #: src/bz-transaction-dialog.c:253 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "Bu uygulama, tĂźm tuş darbelerini kaydetmeye, ekran gĂśrĂźntĂźlerini " "yakalamaya ve diğer uygulamalarÄą izlemeye izin veren eski X11 pencere " "sistemini kullanÄąr. AyrÄąca internete erişimi var, yani verilerinizi dış " "taraflara gĂśnderebilir.\n" "\n" "Uygulama sahipli olduğundan, bu izinlerle ne yaptığı denetlenemez." #: src/bz-transaction-dialog.c:269 msgid "Install Anyway" msgstr "Yine De Kur" #: src/bz-transaction-manager.c:1148 #, c-format msgid "Finished in %.02f seconds" msgstr "%.02f saniyede bitti" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Uygulama Eklentisi" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Çalışma ZamanÄą" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Kurulum Boyutu" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "Beklemede" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "SĂźren" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "TamamlandÄą" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "GĂźncelle" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "%s kÄąsmÄą aktarÄąldÄą" #: src/bz-update-dialog.blp:7 msgid "Update Now" msgstr "Şimdi GĂźncelle" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "GĂźncelleme Var" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "Aşağıdaki uygulamalar gĂźncelleme için uygun. GĂźncellemeler kurulsun mu?" #: src/bz-update-dialog.c:135 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d çalışma zamanÄą ve/ya da uzantÄą gĂźncelleme için uygun. GĂźncellemeler " "kurulsun mu??" #: src/bz-update-dialog.c:143 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "AyrÄąca, %d çalışma zamanÄą ve/ya da uzantÄą gĂźncellenecek.." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "ArtÄąk KullanÄącÄą Verisini YĂśnet" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "KullanÄącÄą Verisi bulunamadÄą" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "KullanÄącÄą Verisi" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "%s İçin KullanÄącÄą Verisi Çöpe TaşındÄą" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "KullanÄącÄą Verisini Çöpe Taşı" #: src/bz-window.blp:107 msgid "Tasks" msgstr "GĂśrevler" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Etkin GĂśrevleri Durdur" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Geçmişi Temizle" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "HenĂźz GĂśrev Yok" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "Mağaza İçeriği Yenileniyor" #: src/bz-window.blp:271 msgid "Curated" msgstr "Özelleştirilmiş" #: src/bz-window.blp:284 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:432 msgid "No background tasks!" msgstr "Arka plan gĂśrevi yok!" #: src/bz-window.blp:490 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "" "Ağ bağlantÄąnÄąz var ancak FlathubʟĹn Ăśnbelleklenmiş sĂźrĂźmĂźnĂź gĂśrĂźntĂźlĂźyorsunuz" #: src/bz-window.blp:565 msgid "_Login with Flathub" msgstr "Flathub İle _Oturum Aç" #: src/bz-window.blp:571 msgid "_Manage Leftover User Data" msgstr "ArtÄąk KullanÄącÄą Verisini _YĂśnet" #: src/bz-window.blp:576 msgid "_Synchronize Remotes" msgstr "UzaklarÄą _Eşzamanla" #: src/bz-window.blp:617 msgid "Log Out" msgstr "Oturumu Kapat" #: src/bz-window.c:435 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d GĂźncelleme Var" #: src/bz-window.c:872 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Yerel .flatpak paket dosyalarÄąnÄą inceleme ve kurma Ăśzelliği yakÄąnda " "kullanÄąma sunulacak! Bu Ăśzellik kullanÄąma sunulana kadar, komut satÄąrÄąnda şu " "komutu çalıştÄąrmayÄą deneyin:\n" "\n" "flatpak install --bundle your-bundle.flatpak" #: src/bz-window.c:1010 msgid "Can't do that right now!" msgstr "Şimdi yapma!" #: src/bz-window.c:1080 msgid "Resume Current Tasks" msgstr "Geçerli GĂśrevleri SĂźrdĂźr" #: src/bz-window.c:1086 msgid "Pause Current Tasks" msgstr "Geçerli GĂśrevleri Duraklat" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u indirme" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Genel" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Arama İletişim Kutusunu Aç" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Tercihleri Aç" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "UzaklarÄą Eşzamanla" # Transaction dese de para ile ilgisi yok. O sebeple sadece İşlemler diye çevirdim. #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "İşlemler YĂśneticisini Aç/Kapat" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "KÄąsayollarÄą GĂśster" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Çık" kolunmi-bazaar-7b9c8e1/po/uk.po000066400000000000000000001725401514314607700164700ustar00rootroot00000000000000# Ukrainian translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025 faoquad msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-06 19:57+0200\n" "PO-Revision-Date: 2025-12-21 15:55+0200\n" "Last-Translator: faoquad \n" "Language-Team: Ukrainian <>\n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" "4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Lokalize 25.12.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:3 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:234 msgid "Bazaar" msgstr "Базар" #: data/io.github.kolunmi.Bazaar.desktop.in:4 msgid "Add, remove or update flatpak software on this computer" msgstr "Встановлюйте, видаляйте та оновлюйте пакунки Flatpak на Ваш компʼютер" #: data/io.github.kolunmi.Bazaar.desktop.in:10 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;PackageManager;Discover;Flatpak;Software;Store;Магазин;Крамниця;" "Флатпак;Пакунки;Програми;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Сховати осиротілі надходження" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Сховати осиротілі надходження та надходження, котрі залежать від них" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Only Show Free Software" msgstr "Показувати Нишо вільні застосунки" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "Hide proprietary software" msgstr "Ховати власницькі застосунки" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Show Only Flathub Content" msgstr "Показувати Нишо вміст С Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Hide applications which do not originate from Flathub" msgstr "Ховати застосунки, що но походять із Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Debounce Search Inputs" msgstr "Чекати ввОду" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "Чекати на закінчення ввОду, айи попередити миттєві надходження." #: data/io.github.kolunmi.Bazaar.gschema.xml:46 msgid "Global Progress Bar Theme" msgstr "Загальний вигляд сПуМки поступу" #: data/io.github.kolunmi.Bazaar.gschema.xml:47 msgid "Describes the look of the global progress bar" msgstr "Описує вигляд загальної сПуМки поступу" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "Saved Window Dimensions" msgstr "Збережені розміри вікна" #: data/io.github.kolunmi.Bazaar.gschema.xml:52 msgid "The window dimensions to be used by the next Bazaar window" msgstr "Розміри, що їх користуватиме наступне вікно Базару" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "Знаходьте та встановлюйте застосунки" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Нова крамниця застосунків для Linux, зосереджена на знаходженні та " "встановленні застосунків і розширень С віддалених сховищ Flatpak, зокрема " "Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "Базар наголошує на підтримці розробників, що роблять ПОМНивиП Linux на " "стільничних компʼютерах. Він має вкНадку \"підібраних\" застосунків, котра " "ПОМо бути налаштована дистрибутивами, айи створити цілісніший досвід." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Домашня сторінка із застосунками С Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Сторінка застосунку Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Сторінка пОшуку" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Сторінка пОшуку С категоріями" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:686 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "Керувати розширеннями" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:477 #: src/bz-installed-tile.blp:117 src/bz-transaction-view.blp:213 #: src/bz-window.c:1314 msgid "Remove" msgstr "Видалити" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:166 #: src/bz-full-view.blp:249 src/bz-full-view.blp:464 #: src/bz-transaction-view.blp:187 src/bz-window.c:1291 msgid "Install" msgstr "Встановити" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:50 #: src/bz-full-view.c:374 src/bz-full-view.c:381 msgid "Age Rating" msgstr "Вікове обмеження" # хто я #: src/bz-age-rating-dialog.blp:40 src/bz-age-rating-dialog.c:790 msgid "?" msgstr "?" #: src/bz-age-rating-dialog.c:139 msgid "Cartoon Violence" msgstr "Анімована жорстокість" #: src/bz-age-rating-dialog.c:140 msgid "No information regarding cartoon violence" msgstr "Без даних щодо зображення анімованої жорстокости" #: src/bz-age-rating-dialog.c:143 msgid "Fantasy Violence" msgstr "Вигадана жорстокість" #: src/bz-age-rating-dialog.c:144 msgid "No information regarding fantasy violence" msgstr "Без даних щодо зображення вигаданої жорстокости" #: src/bz-age-rating-dialog.c:147 msgid "Realistic Violence" msgstr "Реалістична жорстокість" #: src/bz-age-rating-dialog.c:148 msgid "No information regarding realistic violence" msgstr "Без даних щодо зображення реалістичної жорстокости" #: src/bz-age-rating-dialog.c:151 msgid "Violence Depicting Bloodshed" msgstr "Жорстокість із зображенням кровопролиття" #: src/bz-age-rating-dialog.c:152 msgid "No information regarding bloodshed" msgstr "Без даних щодо зображення кровопролиття" #: src/bz-age-rating-dialog.c:155 msgid "Sexual Violence" msgstr "Сексуальне насильство" #: src/bz-age-rating-dialog.c:156 msgid "No information regarding sexual violence" msgstr "Без даних щодо СгадОк айО зображення сексуального насильства" #: src/bz-age-rating-dialog.c:159 msgid "Alcohol" msgstr "Алкоголь" #: src/bz-age-rating-dialog.c:160 msgid "No information regarding references to alcohol" msgstr "Без даних щодо СгадОк айО зображення алкоголю" #: src/bz-age-rating-dialog.c:163 msgid "Narcotics" msgstr "Заборонені речовини" # Тут поняття включає як заборонені, так і незаборонені речовини (алкоголь, тютюн тощо) #: src/bz-age-rating-dialog.c:164 msgid "No information regarding references to illicit drugs" msgstr "Без даних щодо СгадОк айО зображення пʼянких речовин" #: src/bz-age-rating-dialog.c:167 msgid "Tobacco" msgstr "Тютюн" #: src/bz-age-rating-dialog.c:168 msgid "No information regarding references to tobacco products" msgstr "Без даних щодо СгадОк айО зображення тютюнових виробів" #: src/bz-age-rating-dialog.c:171 src/bz-age-rating-dialog.c:358 msgid "Nudity" msgstr "Оголення" #: src/bz-age-rating-dialog.c:172 msgid "No information regarding nudity of any sort" msgstr "Без даних щодо зображення оголення" #: src/bz-age-rating-dialog.c:175 msgid "Sexual Themes" msgstr "Сексуальні теми" #: src/bz-age-rating-dialog.c:176 msgid "No information regarding references to or depictions of sexual nature" msgstr "Без даних щодо СгадОк айО зображення сексуального характеру" #: src/bz-age-rating-dialog.c:179 msgid "Profanity" msgstr "Лайка" #: src/bz-age-rating-dialog.c:180 msgid "No information regarding profanity of any kind" msgstr "Без даних щодо грубощів айО недоречного гумору" #: src/bz-age-rating-dialog.c:183 msgid "Inappropriate Humor" msgstr "Недоречний гумор" #: src/bz-age-rating-dialog.c:184 msgid "No information regarding inappropriate humor" msgstr "Без даних щодо використання недоречного гумору" #: src/bz-age-rating-dialog.c:187 msgid "Discrimination" msgstr "Дискримінація" #: src/bz-age-rating-dialog.c:188 msgid "No information regarding discriminatory language of any kind" msgstr "Без даних щодо використання дискримінаційної ПОви" #: src/bz-age-rating-dialog.c:191 msgid "Advertising" msgstr "РокНаПа" #: src/bz-age-rating-dialog.c:192 msgid "No information regarding advertising of any kind" msgstr "Без даних щодо рекламного вмісту" #: src/bz-age-rating-dialog.c:195 msgid "Gambling" msgstr "Азартний вміст" #: src/bz-age-rating-dialog.c:196 msgid "No information regarding gambling of any kind" msgstr "Без даних щодо азартного вмісту" #: src/bz-age-rating-dialog.c:199 msgid "Purchasing" msgstr "Покупки" #: src/bz-age-rating-dialog.c:200 msgid "No information regarding the ability to spend money" msgstr "Без даних щодо можливості витрачати гроші" #: src/bz-age-rating-dialog.c:203 msgid "Chat Between Users" msgstr "РОСПОви між користувачами" #: src/bz-age-rating-dialog.c:204 msgid "No information regarding ways to chat with other users" msgstr "Без даних щодо можливості спілкуватися С іншими користувачами" #: src/bz-age-rating-dialog.c:207 msgid "Audio Chat Between Users" msgstr "Голосові розмови між користувачами" #: src/bz-age-rating-dialog.c:208 msgid "No information regarding ways to talk with other users" msgstr "Без даних щодо гОНОсОвОгО звʼязку С іншими користувачами" #: src/bz-age-rating-dialog.c:211 msgid "Contact Details" msgstr "Контактні дані" #: src/bz-age-rating-dialog.c:212 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "Без даних щодо розголошення облікових даних соцмереж айО адрес електронної " "пошти" #: src/bz-age-rating-dialog.c:215 msgid "Identifying Information" msgstr "Виявні дані" #: src/bz-age-rating-dialog.c:216 msgid "No information regarding sharing of user information with third parties" msgstr "Без даних щодо розголошення користувацьких даних третім сторонам" #: src/bz-age-rating-dialog.c:219 msgid "Location Sharing" msgstr "Місцезнаходження" #: src/bz-age-rating-dialog.c:220 msgid "No information regarding sharing of physical location with other users" msgstr "Без даних щодо розголошення розташування іншим користувачам" #: src/bz-age-rating-dialog.c:223 msgid "Prostitution" msgstr "Проституція" #: src/bz-age-rating-dialog.c:224 msgid "No information regarding references to prostitution" msgstr "Без даних щодо СгадОк айО зображення проституції" #: src/bz-age-rating-dialog.c:227 msgid "Adultery" msgstr "Подружня зрада" #: src/bz-age-rating-dialog.c:228 msgid "No information regarding references to adultery" msgstr "Без даних щодо СгадОк айО зображення подружньої зради" #: src/bz-age-rating-dialog.c:231 msgid "Sexualized Characters" msgstr "Сексуалізовані персонажі" #: src/bz-age-rating-dialog.c:232 msgid "No information regarding sexualized characters" msgstr "Без даних щодо зображення сексуалізованих персонажів" # По-нашОПу но «кощунство». #: src/bz-age-rating-dialog.c:235 msgid "Desecration" msgstr "Блюзнірство" # По-нашОПу но «кощунство». #: src/bz-age-rating-dialog.c:236 msgid "No information regarding references to desecration" msgstr "Без даних щодо блюзнірства" #: src/bz-age-rating-dialog.c:239 msgid "Human Remains" msgstr "Людські рештки" #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "Без даних щодо зображення людських решток" #: src/bz-age-rating-dialog.c:243 msgid "Slavery" msgstr "Рабство" #: src/bz-age-rating-dialog.c:244 msgid "No information regarding references to slavery" msgstr "Без даних щодо СгадОк айО зображення рабства" # Тут поняття включає як заборонені, так і незаборонені речовини (алкоголь, тютюн тощо) #: src/bz-age-rating-dialog.c:307 msgid "Does not include references to drugs" msgstr "Не містить СгадОк айО зображення пʼянких речовин" #: src/bz-age-rating-dialog.c:309 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "Не містить грубощів айО недоречного гумору" #: src/bz-age-rating-dialog.c:311 msgid "Does not include ads or monetary transactions" msgstr "Не містить реклами айО грошових операцій" #: src/bz-age-rating-dialog.c:313 msgid "Does not include sex or nudity" msgstr "Не містить оголености айО соксу" #: src/bz-age-rating-dialog.c:315 msgid "Does not include uncontrolled chat functionality" msgstr "Не має можливості спілкуватися С іншими користувачами" #: src/bz-age-rating-dialog.c:317 msgid "Does not include violence" msgstr "Не містить жорстокости" # Тут поняття включає як заборонені, так і незаборонені речовини (алкоголь, тютюн тощо) #: src/bz-age-rating-dialog.c:352 msgid "Drugs" msgstr "Речовини" # ĐŻĐş розумію, це включає НаКНиву ПОву та інші форми міцної ПОви. #: src/bz-age-rating-dialog.c:354 msgid "Strong Language" msgstr "Грубощі" #: src/bz-age-rating-dialog.c:356 msgid "Money" msgstr "Гроші" # Тут мається на увазі чат та інші види звʼязку С іншими людьми. #: src/bz-age-rating-dialog.c:360 msgid "Social" msgstr "Спілкування" #: src/bz-age-rating-dialog.c:362 msgid "Violence" msgstr "Жорстокість" #: src/bz-age-rating-dialog.c:564 #, c-format msgid "%s • %s" msgstr "%s • %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:752 src/bz-full-view.c:364 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:782 msgctxt "Age rating" msgid "All" msgstr "Без обмежень" #: src/bz-age-rating-dialog.c:846 #, c-format msgid "%s has an unknown age rating" msgstr "%s но вказує вікове обмеження" #: src/bz-age-rating-dialog.c:854 #, c-format msgid "%s is suitable for everyone" msgstr "%s пасує всім" #: src/bz-age-rating-dialog.c:857 #, c-format msgid "%s is suitable for toddlers" msgstr "%s пасує немовлям" #: src/bz-age-rating-dialog.c:860 #, c-format msgid "%s is suitable for young children" msgstr "%s пасує ПаНиП дітям" #: src/bz-age-rating-dialog.c:863 #, c-format msgid "%s is suitable for children" msgstr "%s пасує дітям" #: src/bz-age-rating-dialog.c:866 #, c-format msgid "%s is suitable for teenagers" msgstr "%s пасує підліткам" #: src/bz-age-rating-dialog.c:869 #, c-format msgid "%s is suitable for adults" msgstr "%s пасує дорослим" #: src/bz-age-rating-dialog.c:872 #, c-format msgid "%s is suitable for %s" msgstr "%s пасує %s" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- МБ" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "Розмір завантаження" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "від людської ДНК" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 мільярди пар ОснОв" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "від ядра Linux" # Не потребує перекладу. #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "від бортового обчислювача Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "увесь простір ПЗП та ОЗП" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "від першого Super Mario Bros" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "на NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "від усієї Вікіпедії" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "йоС медіявмісту" #: src/bz-app-tile.blp:84 src/bz-installed-page.blp:25 src/bz-window.blp:298 msgid "Installed" msgstr "Встановлені" #: src/bz-apps-page.blp:14 src/bz-full-view.blp:43 src/bz-user-data-page.blp:15 #: src/bz-window.blp:443 msgid "Main Menu" msgstr "Головне меню" #: src/bz-apps-page.blp:17 src/bz-user-data-page.blp:18 src/bz-window.blp:522 msgid "_Donate to Bazaar ❤️" msgstr "_Пожертувати Базару ❤️" #: src/bz-apps-page.blp:18 src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "_Освіжити вміст" #: src/bz-apps-page.blp:22 src/bz-user-data-page.blp:22 src/bz-window.blp:529 msgid "_Preferences" msgstr "_Налаштування" #: src/bz-apps-page.blp:23 src/bz-user-data-page.blp:23 src/bz-window.blp:550 msgid "_Keyboard Shortcuts" msgstr "_Клавіатурні скорочення" #: src/bz-apps-page.blp:24 src/bz-user-data-page.blp:24 src/bz-window.blp:555 msgid "_About Bazaar" msgstr "_Про Базар" #: src/bz-apps-page.blp:28 src/bz-user-data-page.blp:27 src/bz-window.blp:562 msgid "_Quit Bazaar" msgstr "_Вийти" #: src/bz-application.c:578 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Цю можливість наразі виПкнонО. Для керування дОСвОНаПи застосунків радимо " "встановити Flatseal." #: src/bz-application.c:660 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "" #: src/bz-application.c:661 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "" #: src/bz-application.c:683 msgid "Adam Masciola" msgstr "" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:686 msgid "translator-credits" msgstr "faoquad , 2025" #: src/bz-application.c:750 msgid "Logged Out Successfully!" msgstr "Ви виКшНи С Flathub" #: src/bz-application.c:877 msgid "Performing setup..." msgstr "Налаштовуємо…" #: src/bz-application.c:956 src/bz-application.c:965 msgid "Set Up Flathub" msgstr "Налаштувати Flathub" #: src/bz-application.c:959 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub но налаштовано на цій системі. Ви но зможете шукати та встановлювати " "застосунки в Базарі. Проте, Ви зможете користати Базар для огляду та " "керування вМо встановленими застосунками." #: src/bz-application.c:964 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Пізніше" #: src/bz-application.c:1366 msgid "Synchronizing..." msgstr "Синхронізуємо…" #: src/bz-application.c:1505 #, c-format msgid "Receiving %d entries..." msgstr "Отримуємо %d надходжень…" #: src/bz-application.c:1510 msgid "Checking for updates" msgstr "Шукаємо оновлення" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:65 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:15 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "Порожньо" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "Жодного підібраного вмісту" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "Ваша операційна система но надає підібранoгО вмісту. Ви всо ще можете шукати " "застосунки на Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Оглянути Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Поза мережею" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "Оглядач" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "Відомості щодо розробників недоступні" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Володіння ідентифікатором цього застосунку но йуНО підтверджено. Можливо, " "цей пакунОк йуНО вивантажено спільнотою." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "" "Володіння ідентифікатором %s йуНО підтверджено власноруч командою Flathub." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %s app ID has been verified by %s on %s." msgstr "Володіння ідентифікатором %s йуНО підтверджено %s на %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %s app ID has been verified using %s." msgstr "Володіння ідентифікатором %s йуНО підтверджено С допомогою %s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Володіння ідентифікатором %s йуНО підтверджено." #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "Оберіть встановлення" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "" "Ви маєте декілька встановлених версій цього застосунку. З котрою С них Ви йаМа" "єте продовжити?" #: src/bz-entry-group-util.c:80 src/bz-window.c:1290 src/bz-window.c:1313 msgid "Cancel" msgstr "Скасувати" #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "Зневаджувач надходжень" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Серіалізувати" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Перетворити в JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Виникла пОПиНка" #: src/bz-error.c:89 msgid "Close" msgstr "Вийти" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Копіювати та вийти" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "Увійдіть із допомогою Flathub, айи керувати вподобаннями" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "Увійти" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "Кількість уподобань" #: src/bz-favorites-tile.c:164 msgid "Uninstall" msgstr "Видалити" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "Підтримати цей застосунок" #: src/bz-favorites-tile.blp:118 msgid "Remove from Favorites" msgstr "Прибрати С вподобаних" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:75 #: src/bz-window.blp:580 msgid "Favorites" msgstr "Вподобані" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:420 msgid "Toggle transaction sidebar" msgstr "Перемкнути віконце дій над застосунками" #: src/bz-favorites-page.blp:53 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "Шукаємо" #: src/bz-favorites-page.blp:68 msgid "No Favorites" msgstr "Нічого но впОдОйанО" #: src/bz-favorites-page.blp:69 msgid "Applications you mark as favorite will appear here" msgstr "Вподобані застосунки опинятимуться тут" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "Назад" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "Далі" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "Застосунок дня" #: src/bz-flathub-category.c:78 msgid "Audio & Video" msgstr "Звук та відео" #: src/bz-flathub-category.c:78 msgid "Media" msgstr "Медіа" #: src/bz-flathub-category.c:78 msgid "More Audio & Video" msgstr "Показати більше" #: src/bz-flathub-category.c:79 msgid "Developer Tools" msgstr "Розробка" #: src/bz-flathub-category.c:79 msgid "Develop" msgstr "Розробка" #: src/bz-flathub-category.c:79 msgid "More Developer Tools" msgstr "Показати більше" #: src/bz-flathub-category.c:80 msgid "Education" msgstr "Освіта" #: src/bz-flathub-category.c:80 msgid "Learn" msgstr "Освіта" #: src/bz-flathub-category.c:80 msgid "More Education" msgstr "Показати більше" #: src/bz-flathub-category.c:81 msgid "Gaming" msgstr "Ігри" #: src/bz-flathub-category.c:81 msgid "Play" msgstr "Ігри" #: src/bz-flathub-category.c:81 msgid "More Gaming" msgstr "Показати більше" #: src/bz-flathub-category.c:82 msgid "Graphics & Photography" msgstr "Графіка та фотографія" #: src/bz-flathub-category.c:82 msgid "Create" msgstr "Творчість" #: src/bz-flathub-category.c:82 msgid "More Graphics & Photography" msgstr "Показати більше" #: src/bz-flathub-category.c:83 msgid "Networking" msgstr "Мережа" #: src/bz-flathub-category.c:83 msgid "Internet" msgstr "Інтернет" #: src/bz-flathub-category.c:83 msgid "More Networking" msgstr "Показати більше" #: src/bz-flathub-category.c:84 msgid "Productivity" msgstr "Продуктивність" #: src/bz-flathub-category.c:84 msgid "Work" msgstr "Робота" #: src/bz-flathub-category.c:84 msgid "More Productivity" msgstr "Показати більше" #: src/bz-flathub-category.c:85 msgid "Science" msgstr "Наука" #: src/bz-flathub-category.c:85 msgid "More Science" msgstr "Показати більше" #: src/bz-flathub-category.c:86 msgid "System" msgstr "Система" #: src/bz-flathub-category.c:86 msgid "More System" msgstr "Показати більше" #: src/bz-flathub-category.c:87 msgid "Utilities" msgstr "Утиліти" #: src/bz-flathub-category.c:87 msgid "Tools" msgstr "Утиліти" #: src/bz-flathub-category.c:87 msgid "More Utilities" msgstr "Показати більше" #: src/bz-flathub-category.c:88 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "Набирають популярність" #: src/bz-flathub-category.c:88 msgid "More Trending" msgstr "Показати більше" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "Популярні" #: src/bz-flathub-category.c:89 msgid "More Popular" msgstr "Показати більше" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "Нещодавно додані" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:131 msgid "New" msgstr "Нові" #: src/bz-flathub-category.c:90 msgid "More New" msgstr "Показати більше" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "Нещодавно оновлені" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "Оновлені" #: src/bz-flathub-category.c:91 msgid "More Updated" msgstr "Показати більше" #: src/bz-flathub-category.c:92 msgid "Mobile" msgstr "Мобільні пристрої" #: src/bz-flathub-category.c:92 msgid "More Mobile" msgstr "Показати більше" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub но дОданО" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Сховище Flathub но йуНО СнаКдонО на МОднОПу С Ваших встановлень" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Помилка Flathub" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "Спробувати зʼєднатися С Flathub іще раз" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub недоступний" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "Не вдалося зʼєднатися С Flathub. Ви всо ще можете шукати застосунки та " "керувати ниПи." #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "Шукати застосунки" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "На ходу" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "Застосунки для Ваших смартфонів та планшетів на Linux" #: src/bz-flathub-page.blp:293 msgid "More Mobile Apps" msgstr "Показати більше" #: src/bz-flathub-page.blp:328 msgid "More Mobile apps" msgstr "Показати більше" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "Ми​ ♥​ ігри" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "Улюблені ігри та застосунки для них" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "Показати більше" #: src/bz-flatpak-entry.c:600 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Сторінка Flathub" #: src/bz-flatpak-entry.c:621 msgctxt "Project URL Type" msgid "Project Website" msgstr "URL проєкту" #: src/bz-flatpak-entry.c:625 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Відстеження пОПиНОк" #: src/bz-flatpak-entry.c:629 msgctxt "Project URL Type" msgid "FAQ" msgstr "ЧаПи" #: src/bz-flatpak-entry.c:633 msgctxt "Project URL Type" msgid "Help" msgstr "Допомога" #: src/bz-flatpak-entry.c:637 msgctxt "Project URL Type" msgid "Donate" msgstr "Пожертви" #: src/bz-flatpak-entry.c:643 msgctxt "Project URL Type" msgid "Translate" msgstr "Переклад" #: src/bz-flatpak-entry.c:647 msgctxt "Project URL Type" msgid "Contact" msgstr "Звʼязок" #: src/bz-flatpak-entry.c:651 msgctxt "Project URL Type" msgid "Source Code" msgstr "Початковий кОд" #: src/bz-flatpak-entry.c:657 msgctxt "Project URL Type" msgid "Contribute" msgstr "Долучитися" #: src/bz-full-view.blp:57 msgid "No Results" msgstr "Нічого но СнаКдонО" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "Спробуйте інший запит" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "Вміст" #: src/bz-full-view.blp:210 msgid "Support" msgstr "Підтримати" #: src/bz-full-view.blp:233 src/bz-full-view.blp:488 msgid "Open" msgstr "Запустити" #: src/bz-full-view.blp:246 src/bz-full-view.blp:461 msgid "Download & Install Application" msgstr "Завантажити Đš встановити цей застосунок" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "Видалити цей застосунок" #: src/bz-full-view.blp:276 src/bz-full-view.blp:503 msgid "Install Other Version" msgstr "Встановити іншу версію" #: src/bz-full-view.blp:300 msgid "Size" msgstr "Розмір" #: src/bz-full-view.blp:405 msgid "Downloads /mo" msgstr "Сав/міс" #: src/bz-full-view.blp:522 msgid "Stopped Receiving Core Updates" msgstr "Більше но отримує оновлень середовища виконання" #: src/bz-full-view.blp:536 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "ЌоК застосунок використовує середовище виконання, котре більше но отримує " "оновлень айО безпекових виправлень. Він ПОМо стати небезпечним Đ´Đž " "використання." #: src/bz-full-view.blp:619 src/bz-window.c:1260 msgid "Delete Data" msgstr "Видалити дані" #: src/bz-full-view.blp:753 msgid "Tags:" msgstr "Мітки:" #: src/bz-full-view.c:290 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:297 #, c-format msgid "%.*fM" msgstr "%.*f ПНн" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:304 #, c-format msgid "%.*fK" msgstr "%.*f тис." #: src/bz-full-view.c:314 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d завантажень протягом останніх 30 днів" #: src/bz-full-view.c:346 #, c-format msgid "Download size of %s" msgstr "Розмір завантаження" #: src/bz-full-view.c:379 msgid "All Ages" msgstr "Без обмежень" #: src/bz-full-view.c:391 msgid "Age rating information unavailable" msgstr "Дані щодо вікового обмеження недоступні" #: src/bz-full-view.c:396 msgid "Suitable for all ages" msgstr "Без обмежень Са віком" #: src/bz-full-view.c:398 #, c-format msgid "Suitable for ages %d and up" msgstr "%d та старше" #: src/bz-full-view.c:431 src/bz-full-view.c:436 src/bz-full-view.c:464 #: src/bz-full-view.c:475 msgid "Unknown" msgstr "Невідомо" #: src/bz-full-view.c:441 #, c-format msgid "Free software licensed under %s" msgstr "Вільне ПЗ Са ліцензією %s" #: src/bz-full-view.c:446 msgid "Free software" msgstr "Вільне ПЗ" #: src/bz-full-view.c:449 msgid "Proprietary Software" msgstr "Власницька ліцензія" #: src/bz-full-view.c:452 #, c-format msgid "Special License: %s" msgstr "Власна ліцензія: %s" #: src/bz-full-view.c:469 msgid "Free" msgstr "Вільна ліцензія" #: src/bz-full-view.c:472 src/bz-license-dialog.c:118 msgid "Proprietary" msgstr "Власницька ліцензія" #: src/bz-full-view.c:477 src/bz-license-dialog.c:120 msgid "Special License" msgstr "Власна ліцензія" #: src/bz-full-view.c:497 msgid "Adaptive" msgstr "Адаптивний" #: src/bz-full-view.c:497 msgid "Desktop Only" msgstr "Лише для стільниць" #: src/bz-full-view.c:503 msgid "Works on desktop, tablets, and phones" msgstr "Працює на стільницях, планшетах і смартфонах" #: src/bz-full-view.c:504 msgid "May not work on mobile devices" msgstr "Може но працювати на мобільних пристроях" #: src/bz-full-view.c:515 msgid "No URL" msgstr "Без URL" #: src/bz-full-view.c:533 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "ЌоК застосунок має вільну ліцензію. ĐŚĐľ означає, що початковий кОд ПОМо бути " "перевірено на безпечність." #: src/bz-full-view.c:534 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "ЌоК застосунок має невільну (власницьку) ліцензію. ĐŚĐľ означає, що початковий " "кОд но є публічно доступним і но ПОМо бути перевіреним на безпечність." #: src/bz-full-view.c:541 msgid "More Apps" msgstr "Більше застосунків" #: src/bz-full-view.c:542 #, c-format msgid "More Apps by %s" msgstr "Більше від %s" #: src/bz-full-view.c:549 msgid "Other Apps by this Developer" msgstr "Більше від розробників" #: src/bz-full-view.c:551 src/bz-full-view.c:659 #, c-format msgid "Other Apps by %s" msgstr "Більше від %s" # Трохи дОвшиК переклад, айи зберегти статеву нейтральність наСви саПОгО застосунку. #: src/bz-full-view.c:559 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "" "Застосунок %s но встановлено, проте він має %s залишкових даних." #: src/bz-full-view.c:661 msgid "Other Apps" msgstr "Інші застосунки" #: src/bz-full-view.c:663 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d застосунок" msgstr[1] "%d застосунки" msgstr[2] "%d застосунків" #: src/bz-full-view.c:1011 msgid "Show Less" msgstr "Згорнути" #: src/bz-full-view.c:1011 msgid "Show More" msgstr "Розгорнути" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Підтримка пристроїв" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Підтримка клавіатури" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "Вимагає клавіатуру" # Позначає, що застосунок ліпше працює С такими пристроями # Стан підтримки СагаНОП описується іншим рядком #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Бажана клавіатура" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Підтримує клавіатуру" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Сумісність із клавіатурами на вкаСана" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Підтримка миші" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "Вимагає Пишу айО вказівний пристрій" # Позначає, що застосунок ліпше працює С такими пристроями # Стан підтримки СагаНОП описується іншим рядком #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Бажані Пиша айО вказівний пристрій" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Підтримує Пишу айО вказівний пристрій" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Сумісність із ПишаПи айО вказівними пристроями но вкаСана" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Підтримка сенсорних екранів" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "Вимагає сенсорний екран" # Позначає, що застосунок ліпше працює С такими пристроями # Стан підтримки СагаНОП описується іншим рядком #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Бажаний сенсорний екран" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Підтримує сенсорний екран" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Сумісність із сенсорними екранами на вкаСана" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Підтримка мобільних пристроїв" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Працює на мобільних пристроях" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "Обмежена підтримка на мобільних пристроях" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Підтримка стільниць" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Працює добре на великих екранах" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s найліпше працює на певних пристроях" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s працює на більшості пристроїв" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "Зневаджувач" #: src/bz-inspector.blp:33 msgid "Background Task Info:" msgstr "Відомості про задачі у тлі:" #: src/bz-inspector.blp:43 msgid "Enable Global Debug Mode" msgstr "Увімкнути режим зневадження" #: src/bz-inspector.blp:50 msgid "Active Blocklists" msgstr "Задіяні чорні списки" #: src/bz-inspector.blp:67 msgid "Active Curated-Configs" msgstr "Задіяні налаштування підібраного вмісту" #: src/bz-inspector.blp:85 msgid "All Entry Groups" msgstr "Усі групи надходжень" #: src/bz-inspector.blp:93 msgid "Filter..." msgstr "Відсіяти…" #: src/bz-inspector.blp:134 msgid "Decache and Inspect" msgstr "Відкинути кош та дослідити" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Не встановлено МОднОгО пакунку Flatpak" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Більшe но отримує оновлень" #: src/bz-license-dialog.blp:160 msgid "Get Involved" msgstr "Долучитися" #: src/bz-license-dialog.c:107 src/bz-license-dialog.c:112 msgid "Unknown License" msgstr "Невідома ліцензія" #: src/bz-license-dialog.c:115 msgid "Community Built" msgstr "Розроблено спільнотою" # Згідно перекладу на Flathub #: src/bz-license-dialog.c:148 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "ЌоК застосунок розробляється у відкритому доступі міжнародною спільнотою та " "випускається під %s.\n" "\n" "Ви можете долучитися Đ´Đž проєкту та зробити КОгО ліпшим." # Згідно перекладу на Flathub #: src/bz-license-dialog.c:156 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "ЌоК застосунок розробляється у відкритому доступі міжнародною спільнотою.\n" "\n" "Ви можете долучитися Đ´Đž проєкту та зробити КОгО ліпшим." #: src/bz-license-dialog.c:161 msgid "The license of this app is not known" msgstr "Ліцензія цього застосунку невідома" # Згідно перекладу на Flathub #: src/bz-license-dialog.c:165 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "ЌоК застосунок но розробляється у відкритому доступі, тому Нишо КОгО " "розробники знають, як він працює. Він ПОМо мати вразливості, які ваМкО " "виявити, і ПОМо змінюватися йоС нагляду.\n" "\n" "Ви можете но мати можливості долучитися Đ´Đž проєкту." #: src/bz-license-dialog.c:174 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "ЌоК застосунок розробляється на умовах власної ліцензії %s.\n" "\n" "Ви можете но мати можливості долучитися Đ´Đž проєкту." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "Налаштування" #: src/bz-preferences-dialog.blp:23 msgid "Content Filters" msgstr "Відсіяти вміст" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Вільна ліцензія" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications when browsing and searching" msgstr "Ховати власницькі (пропрієтарні) застосунки С огляду та пОшуку" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Надходження Нишо С Flathub" #: src/bz-preferences-dialog.blp:32 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "" "Обмежити надходження у пОшуку та огляді Нишо Đ´Đž тих, що походять С Flathub" #: src/bz-preferences-dialog.blp:36 msgid "Hide EOL Apps" msgstr "Сховати осиротілі застосунки" #: src/bz-preferences-dialog.blp:37 msgid "Hide apps which are no longer supported by their developers" msgstr "" "Сховати застосунки, котрі більше но підтримуються вНасниПи розробниками" #: src/bz-preferences-dialog.blp:42 src/bz-window.blp:313 msgid "Search" msgstr "Пошук" #: src/bz-preferences-dialog.blp:45 msgid "Delay Search Results" msgstr "Чекати ввОду" #: src/bz-preferences-dialog.blp:46 msgid "Improve results performance by debouncing search terms" msgstr "Поліпшити швидкодію пОшуку, затримуючи відправлення пошукових запитів" #: src/bz-preferences-dialog.blp:51 msgid "Progress Bar" msgstr "ХПуМка поступу" #: src/bz-preferences-dialog.blp:52 msgid "Choose a theme for the progress bar!" msgstr "Оберіть цікавий зовнішній вигляд для сПуМки поступу!" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "Акцентний колір" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "Барви Гордості" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "Лесбійський прапор" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "Трансґендерний прапор" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "Небінарний прапор" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "Бісексуальні барви Гордості" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "Асексуальні барви Гордості" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "Пансексуальний прапор" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "Аромантичний прапор" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "Ґендерфлюїдний прапор" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "Полісексуальний прапор" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "Омнісексуальний прапор" #: src/bz-preferences-dialog.c:44 msgid "Aroace Pride Colors" msgstr "Прапор ароейс" #: src/bz-preferences-dialog.c:45 msgid "Agender Pride Colors" msgstr "Аґендерний прапор" #: src/bz-preferences-dialog.c:46 msgid "Genderqueer Pride Colors" msgstr "Ґендерквірний прапор" #: src/bz-preferences-dialog.c:47 msgid "Intersex Pride Colors" msgstr "Інтерсексуальний прапор" #: src/bz-preferences-dialog.c:48 msgid "Demigender Pride Colors" msgstr "Деміґендерний прапор" #: src/bz-preferences-dialog.c:49 msgid "Biromantic Pride Colors" msgstr "Біромантичний прапор" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "Історія версій" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "Версія %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "Без подробиць" # Сирець підказує, що це кнОпка завантаження #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Завантажити" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "Знімки" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "Попередній знімок" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "Наступний знімок" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "Копіювати знімок" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "Відновити масштаб" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "Віддалити" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "Наблизити" #: src/bz-screenshots-carousel.blp:6 msgid "Screenshots Carousel" msgstr "Карусель знімків" #: src/bz-screenshots-carousel.blp:104 msgid "Open Screenshot Viewer" msgstr "Відкрити переглядач знімків" #: src/bz-search-widget.blp:106 msgid "Search Apps, Games, Software" msgstr "Шукайте застосунки, ігри та програми" #: src/bz-search-widget.blp:150 msgid "Categories Unavailable" msgstr "Категорії недоступні" #: src/bz-search-widget.blp:151 msgid "Search for apps using the search bar above." msgstr "Шукайте застосунки Са допомогою рядка згори." #: src/bz-search-widget.blp:235 msgid "No Applications Found" msgstr "Жодного підібраного застосунку" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "Не СнаКдонО збігів для ÂŤ%sÂť на Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Скопійовано!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Копіювати посилання" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Відкрити посилання" # https://slovotvir.org.ua/words/taimlain #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Часоряд" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "Встановлень:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Світ" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "Нічого но СнаКдонО" # Буквальний переклад дещо СадОвгиК. #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "Мітка ÂŤ%sÂť" #: src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d застосунків" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "Пошук завершився новдаНО" #: src/bz-transaction-manager.c:1135 #, c-format msgid "Finished in %.02f seconds" msgstr "Завершено Са %.02f сок" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "Розширення" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "Середовище виконання" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "Розмір встановлення" #: src/bz-transaction-view.blp:200 msgid "Update" msgstr "Оновлення" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Наразі отримано %s" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Очікуємо" #: src/bz-update-dialog.blp:7 msgid "Update Now" msgstr "Оновити зараз" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "Доступні оновлення" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "Для цих застосунків доступні оновлення. Бажаєте встановити?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "Для %d середовищ виконання та/айО розширень доступні оновлення. Бажаєте " "встановити?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "Крім того, йудо ОнОвНонО %d середовищ виконання та/айО розширень." #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "Керувати СаНишкОвиПи даниПи" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "Користувацьких даних но СнаКдонО" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "Користувацькі дані" #: src/bz-user-data-tile.c:144 #, c-format msgid "Removed User Data for %s" msgstr "Користувацькі дані %s йуНО видаНонО" #: src/bz-user-data-tile.blp:74 msgid "Remove User Data" msgstr "Видалити користувацькі дані" #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Дослідити рядок інтерфейсу" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "Усі дії зневадження" #: src/bz-window.blp:107 msgid "Tasks" msgstr "Дії" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Зупинити активні дії" #: src/bz-window.blp:171 msgid "Clear History" msgstr "Очистити історію" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Жодних дій" #: src/bz-window.blp:258 msgid "Refreshing Store Content" msgstr "Оновлюємо вміст крамниці" #: src/bz-window.blp:273 msgid "Curated" msgstr "Підібрані" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:450 msgid "Network connection is metered — automatic store data sync is paused" msgstr "Платне зʼєднання — автоматичне освіження вмісту крамниці призупинено" #: src/bz-window.blp:451 src/bz-window.blp:460 msgid "Sync Manually" msgstr "Освіжити власноруч" #: src/bz-window.blp:459 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "Ви маєте зʼєднання С мережею, аНо переглядаєте кошОвану версію Flathub" #: src/bz-window.blp:534 msgid "_Login with Flathub" msgstr "_Увійти С допомогою Flathub" #: src/bz-window.blp:540 msgid "_Manage Leftover User Data" msgstr "_Керувати СаНишкОвиПи даниПи" #: src/bz-window.blp:545 msgid "_Synchronize Remotes" msgstr "_Освіжити віддалені сховища" #: src/bz-window.blp:571 msgid "Open Bazaar Inspector" msgstr "Відкрити зневаджувач" #: src/bz-window.blp:586 msgid "Log Out" msgstr "Вийти" #: src/bz-window.c:484 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "Доступне %s оновлення" msgstr[1] "Доступні %s оновлення" msgstr[2] "Доступні %s оновлень" #: src/bz-window.c:982 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Можливість оглянути та встановити локальні файл-пакунки .flatpak скоро йудо " "доступна! ТиП часом, спробуйте виконати кОПанду\n" "\n" "flatpak install --bundle ваш-файл-пакунОк.flatpak\n" "\n" "у терміналі." #: src/bz-window.c:1120 msgid "Can't do that right now!" msgstr "Наразі цього но ПОМна зробити!" # Виглядає як СагОНОвОк «пташечки» у діалозі при видаленні застосунку. #: src/bz-window.c:1251 msgid "Keep Data" msgstr "Залишити дані" #: src/bz-window.c:1252 msgid "Allow restoring settings and content" msgstr "Залишити можливість відновити налаштування та вміст у майбутньому" #: src/bz-window.c:1261 msgid "Permanently remove app data to save space" msgstr "Назавжди видалити дані застосунку" #: src/bz-window.c:1284 #, c-format msgid "Install %s?" msgstr "Встановити %s?" #: src/bz-window.c:1287 msgid "May install additional shared components" msgstr "Можуть бути встановлені додаткові компоненти" #: src/bz-window.c:1306 #, c-format msgid "Remove %s?" msgstr "Видалити %s?" #: src/bz-window.c:1310 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "%s но ПОМна йудо користати після видалення." #: src/bz-window.c:1373 msgid "Resume Current Tasks" msgstr "Відновити активні дії" #: src/bz-window.c:1379 msgid "Pause Current Tasks" msgstr "Призупинити активні дії" #: src/bz-world-map.c:572 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u завантажень" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Загальні" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Відкрити вікно пОшуку" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Налаштування" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "Освіжити" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Перемкнути віконце дій над застосунками" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Показати клавіатурні скорочення" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "Вийти" kolunmi-bazaar-7b9c8e1/po/vi.po000066400000000000000000001376061514314607700164730ustar00rootroot00000000000000# Vietnamese translations for bazaar package. # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # Loc Huynh , 2025. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-12-02 18:34+0700\n" "PO-Revision-Date: 2025-12-10 18:23+0700\n" "Last-Translator: Loc Huynh \n" "Language-Team: Vietnamese \n" "Language: vi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Gtranslator 49.0\n" #: data/io.github.kolunmi.Bazaar.desktop.in:3 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:234 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:4 msgid "Add, remove or update flatpak software on this computer" msgstr "ThĂŞm, xĂła hoạc cáş­p nháş­t pháş§n mᝁm Flatpak trĂŞn mĂĄy tĂ­nh nĂ y" #: data/io.github.kolunmi.Bazaar.desktop.in:10 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;PackageManager;Discover;Flatpak;Software;Store;TrĂŹnh quản lĂ˝ gĂłi; " "KhĂĄm phĂĄ; Pháş§n mᝁm; Cáť­a hĂ ng;" #: data/io.github.kolunmi.Bazaar.gschema.xml:6 msgid "Hide EOL Entries" msgstr "Ẩn cĂĄc m᝼c EOL" #: data/io.github.kolunmi.Bazaar.gschema.xml:7 msgid "Hide EOL entries and entries depending on them" msgstr "Ẩn cĂĄc m᝼c EOL vĂ  cĂĄc m᝼c ph᝼ thuộc vĂ o chĂşng" #: data/io.github.kolunmi.Bazaar.gschema.xml:11 msgid "Show Git Forge Star Counts" msgstr "Hiᝃn thị số sao trĂŞn Git Forge" #: data/io.github.kolunmi.Bazaar.gschema.xml:12 msgid "" "Whether to attempt to detect and show \"star counts\" for projects in the " "full view" msgstr "" "CĂł cố gắng phĂĄt hiện vĂ  hiᝃn thị \"số sao\" cho cĂĄc dáťą ĂĄn trong cháşż độ xem " "chi tiáşżt hay khĂ´ng" #: data/io.github.kolunmi.Bazaar.gschema.xml:16 msgid "Only Show Free Software" msgstr "Chỉ hiᝃn thị pháş§n mᝁm miễn phĂ­" #: data/io.github.kolunmi.Bazaar.gschema.xml:17 msgid "Hide proprietary software" msgstr "Ẩn pháş§n mᝁm độc quyᝁn" #: data/io.github.kolunmi.Bazaar.gschema.xml:21 msgid "Show Only Flathub Content" msgstr "Chỉ hiᝃn thị nội dung Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:22 msgid "Hide applications which do not originate from Flathub" msgstr "Ẩn cĂĄc ᝊng d᝼ng khĂ´ng cĂł nguồn gốc tᝍ Flathub" #: data/io.github.kolunmi.Bazaar.gschema.xml:26 msgid "Debounce Search Inputs" msgstr "TrĂŹ hoĂŁn tĂŹm kiáşżm" #: data/io.github.kolunmi.Bazaar.gschema.xml:27 msgid "Add a delay before searching to prevent instant replies while typing" msgstr "ThĂŞm độ trễ trước khi tĂŹm kiáşżm để trĂĄnh phản hồi tᝊc thĂŹ khi đang gĂľ" #: data/io.github.kolunmi.Bazaar.gschema.xml:51 msgid "Global Progress Bar Theme" msgstr "Cháť§ đề thanh tiáşżn trĂŹnh toĂ n c᝼c" #: data/io.github.kolunmi.Bazaar.gschema.xml:52 msgid "Describes the look of the global progress bar" msgstr "MĂ´ tả giao diện cáť§a thanh tiáşżn trĂŹnh toĂ n c᝼c" #: data/io.github.kolunmi.Bazaar.gschema.xml:56 msgid "Saved Window Dimensions" msgstr "KĂ­ch thước cáť­a sổ đã lưu" #: data/io.github.kolunmi.Bazaar.gschema.xml:57 msgid "The window dimensions to be used by the next Bazaar window" msgstr "KĂ­ch thước cáť­a sổ sáş˝ được sáť­ d᝼ng cho cáť­a sổ Bazaar tiáşżp theo" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "KhĂĄm phĂĄ vĂ  cĂ i đặt ᝊng d᝼ng" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for GNOME with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "Một cáť­a hĂ ng ᝊng d᝼ng mới cho GNOME táş­p trung vĂ o việc khĂĄm phĂĄ vĂ  cĂ i đặt " "ᝊng d᝼ng cĂšng tiện Ă­ch mở rộng tᝍ cĂĄc remote Flatpak, đặc biệt lĂ  Flathub." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "NĂł nhẼn mấnh việc hỗ trᝣ cĂĄc nhĂ  phĂĄt triᝃn lĂ m nĂŞn mĂ´i trường desktop " "Linux. Bazaar cĂł tab \"chọn lọc\" cĂł thᝃ được nhĂ  phân phối cẼu hĂŹnh để mang " "lấi trải nghiệm địa phưƥng hĂła tốt hĆĄn." #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:661 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "Trang cháť§ hiᝃn thị cĂĄc ᝊng d᝼ng Flathub" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Trang ᝊng d᝼ng Nucleus" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "Trang tĂŹm kiáşżm" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "Trang danh m᝼c" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:668 msgid "Manage Add-ons" msgstr "Quản lĂ˝ tiện Ă­ch mở rộng" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:505 #: src/bz-transaction-view.blp:212 src/bz-window.c:1125 msgid "Remove" msgstr "Gᝥ bỏ" #: src/bz-addons-dialog.c:95 src/bz-full-view.blp:277 src/bz-full-view.blp:492 #: src/bz-transaction-view.blp:186 src/bz-window.c:1102 msgid "Install" msgstr "CĂ i đặt" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:50 #: src/bz-full-view.c:385 src/bz-full-view.c:392 msgid "Age Rating" msgstr "Xáşżp hấng độ tuổi" #: src/bz-age-rating-dialog.blp:40 src/bz-age-rating-dialog.c:790 msgid "?" msgstr "?" #: src/bz-age-rating-dialog.c:139 msgid "Cartoon Violence" msgstr "Bấo láťąc hoất hĂŹnh" #: src/bz-age-rating-dialog.c:140 msgid "No information regarding cartoon violence" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ bấo láťąc hoất hĂŹnh" #: src/bz-age-rating-dialog.c:143 msgid "Fantasy Violence" msgstr "Bấo láťąc giả tưởng" #: src/bz-age-rating-dialog.c:144 msgid "No information regarding fantasy violence" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ bấo láťąc giả tưởng" #: src/bz-age-rating-dialog.c:147 msgid "Realistic Violence" msgstr "Bấo láťąc tháťąc táşż" #: src/bz-age-rating-dialog.c:148 msgid "No information regarding realistic violence" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ bấo láťąc tháťąc táşż" #: src/bz-age-rating-dialog.c:151 msgid "Violence Depicting Bloodshed" msgstr "Bấo láťąc cĂł mĂĄu" #: src/bz-age-rating-dialog.c:152 msgid "No information regarding bloodshed" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ cảnh đổ mĂĄu" #: src/bz-age-rating-dialog.c:155 msgid "Sexual Violence" msgstr "Bấo láťąc tĂŹnh d᝼c" #: src/bz-age-rating-dialog.c:156 msgid "No information regarding sexual violence" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ bấo láťąc tĂŹnh d᝼c" #: src/bz-age-rating-dialog.c:159 msgid "Alcohol" msgstr "Rưᝣu bia" #: src/bz-age-rating-dialog.c:160 msgid "No information regarding references to alcohol" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến rưᝣu bia" #: src/bz-age-rating-dialog.c:163 msgid "Narcotics" msgstr "Ma tĂşy" #: src/bz-age-rating-dialog.c:164 msgid "No information regarding references to illicit drugs" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến ma tĂşy" #: src/bz-age-rating-dialog.c:167 msgid "Tobacco" msgstr "Thuốc lĂĄ" #: src/bz-age-rating-dialog.c:168 msgid "No information regarding references to tobacco products" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến sản phẊm thuốc lĂĄ" #: src/bz-age-rating-dialog.c:171 src/bz-age-rating-dialog.c:358 msgid "Nudity" msgstr "Khỏa thân" #: src/bz-age-rating-dialog.c:172 msgid "No information regarding nudity of any sort" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ cảnh khỏa thân" #: src/bz-age-rating-dialog.c:175 msgid "Sexual Themes" msgstr "Cháť§ đề tĂŹnh d᝼c" #: src/bz-age-rating-dialog.c:176 msgid "No information regarding references to or depictions of sexual nature" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p hoạc mĂ´ tả tĂ­nh chẼt tĂŹnh d᝼c" #: src/bz-age-rating-dialog.c:179 msgid "Profanity" msgstr "NgĂ´n tᝍ thĂ´ t᝼c" #: src/bz-age-rating-dialog.c:180 msgid "No information regarding profanity of any kind" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ ngĂ´n tᝍ thĂ´ t᝼c" #: src/bz-age-rating-dialog.c:183 msgid "Inappropriate Humor" msgstr "HĂ i khĂ´ng phĂš hᝣp" #: src/bz-age-rating-dialog.c:184 msgid "No information regarding inappropriate humor" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ hĂ i khĂ´ng phĂš hᝣp" #: src/bz-age-rating-dialog.c:187 msgid "Discrimination" msgstr "Káťł thị" #: src/bz-age-rating-dialog.c:188 msgid "No information regarding discriminatory language of any kind" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ ngĂ´n ngᝯ káťł thị" #: src/bz-age-rating-dialog.c:191 msgid "Advertising" msgstr "Quảng cĂĄo" #: src/bz-age-rating-dialog.c:192 msgid "No information regarding advertising of any kind" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ quảng cĂĄo" #: src/bz-age-rating-dialog.c:195 msgid "Gambling" msgstr "Cờ bấc" #: src/bz-age-rating-dialog.c:196 msgid "No information regarding gambling of any kind" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ cờ bấc" #: src/bz-age-rating-dialog.c:199 msgid "Purchasing" msgstr "Mua hĂ ng" #: src/bz-age-rating-dialog.c:200 msgid "No information regarding the ability to spend money" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ khả năng chi tiĂŞu tiᝁn" #: src/bz-age-rating-dialog.c:203 msgid "Chat Between Users" msgstr "Trò chuyện giᝯa người dĂšng" #: src/bz-age-rating-dialog.c:204 msgid "No information regarding ways to chat with other users" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ cĂĄch trò chuyện với người dĂšng khĂĄc" #: src/bz-age-rating-dialog.c:207 msgid "Audio Chat Between Users" msgstr "Trò chuyện âm thanh giᝯa người dĂšng" #: src/bz-age-rating-dialog.c:208 msgid "No information regarding ways to talk with other users" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ cĂĄch nĂłi chuyện với người dĂšng khĂĄc" #: src/bz-age-rating-dialog.c:211 msgid "Contact Details" msgstr "ThĂ´ng tin liĂŞn hệ" #: src/bz-age-rating-dialog.c:212 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "" "KhĂ´ng cĂł thĂ´ng tin vᝁ việc chia sáşť tĂŞn người dĂšng mấng xĂŁ hội hoạc địa chỉ " "email" #: src/bz-age-rating-dialog.c:215 msgid "Identifying Information" msgstr "ThĂ´ng tin nháş­n dấng" #: src/bz-age-rating-dialog.c:216 msgid "No information regarding sharing of user information with third parties" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ việc chia sáşť thĂ´ng tin người dĂšng với bĂŞn thᝊ ba" #: src/bz-age-rating-dialog.c:219 msgid "Location Sharing" msgstr "Chia sáşť vị trĂ­" #: src/bz-age-rating-dialog.c:220 msgid "No information regarding sharing of physical location with other users" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ việc chia sáşť vị trĂ­ tháťąc với người dĂšng khĂĄc" #: src/bz-age-rating-dialog.c:223 msgid "Prostitution" msgstr "Mấi dâm" #: src/bz-age-rating-dialog.c:224 msgid "No information regarding references to prostitution" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến mấi dâm" #: src/bz-age-rating-dialog.c:227 msgid "Adultery" msgstr "Ngoấi tĂŹnh" #: src/bz-age-rating-dialog.c:228 msgid "No information regarding references to adultery" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến ngoấi tĂŹnh" #: src/bz-age-rating-dialog.c:231 msgid "Sexualized Characters" msgstr "Nhân váş­t tĂŹnh d᝼c hĂła" #: src/bz-age-rating-dialog.c:232 msgid "No information regarding sexualized characters" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ nhân váş­t tĂŹnh d᝼c hĂła" #: src/bz-age-rating-dialog.c:235 msgid "Desecration" msgstr "BĂĄng bổ" #: src/bz-age-rating-dialog.c:236 msgid "No information regarding references to desecration" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến bĂĄng bổ" #: src/bz-age-rating-dialog.c:239 msgid "Human Remains" msgstr "XĂĄc người" #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ hiᝃn thị xĂĄc người cháşżt" #: src/bz-age-rating-dialog.c:243 msgid "Slavery" msgstr "NĂ´ lệ" #: src/bz-age-rating-dialog.c:244 msgid "No information regarding references to slavery" msgstr "KhĂ´ng cĂł thĂ´ng tin vᝁ đề cáş­p đến cháşż độ nĂ´ lệ" #: src/bz-age-rating-dialog.c:307 msgid "Does not include references to drugs" msgstr "KhĂ´ng đề cáş­p đến ma tĂşy" #: src/bz-age-rating-dialog.c:309 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "KhĂ´ng chᝊa cháť­i thᝁ, ngĂ´n tᝍ thĂ´ t᝼c vĂ  cĂĄc loấi ngĂ´n ngᝯ mấnh khĂĄc" #: src/bz-age-rating-dialog.c:311 msgid "Does not include ads or monetary transactions" msgstr "KhĂ´ng chᝊa quảng cĂĄo hoạc giao dịch tiᝁn tệ" #: src/bz-age-rating-dialog.c:313 msgid "Does not include sex or nudity" msgstr "KhĂ´ng chᝊa tĂŹnh d᝼c hoạc khỏa thân" #: src/bz-age-rating-dialog.c:315 msgid "Does not include uncontrolled chat functionality" msgstr "KhĂ´ng cĂł chᝊc năng trò chuyện khĂ´ng kiᝃm soĂĄt" #: src/bz-age-rating-dialog.c:317 msgid "Does not include violence" msgstr "KhĂ´ng chᝊa bấo láťąc" #: src/bz-age-rating-dialog.c:352 msgid "Drugs" msgstr "Ma tĂşy" #: src/bz-age-rating-dialog.c:354 msgid "Strong Language" msgstr "NgĂ´n ngᝯ mấnh" #: src/bz-age-rating-dialog.c:356 msgid "Money" msgstr "Tiᝁn bấc" #: src/bz-age-rating-dialog.c:360 msgid "Social" msgstr "XĂŁ hội" #: src/bz-age-rating-dialog.c:362 msgid "Violence" msgstr "Bấo láťąc" #: src/bz-age-rating-dialog.c:564 #, c-format msgid "%s • %s" msgstr "%s • %s" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:752 src/bz-full-view.c:375 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:782 msgctxt "Age rating" msgid "All" msgstr "Mọi lᝊa tuổi" #: src/bz-age-rating-dialog.c:846 #, c-format msgid "%s has an unknown age rating" msgstr "%s cĂł xáşżp hấng độ tuổi khĂ´ng xĂĄc định" #: src/bz-age-rating-dialog.c:854 #, c-format msgid "%s is suitable for everyone" msgstr "%s phĂš hᝣp với mọi người" #: src/bz-age-rating-dialog.c:857 #, c-format msgid "%s is suitable for toddlers" msgstr "%s phĂš hᝣp với tráşť mẍu giĂĄo" #: src/bz-age-rating-dialog.c:860 #, c-format msgid "%s is suitable for young children" msgstr "%s phĂš hᝣp với tráşť nhỏ" #: src/bz-age-rating-dialog.c:863 #, c-format msgid "%s is suitable for children" msgstr "%s phĂš hᝣp với tráşť em" #: src/bz-age-rating-dialog.c:866 #, c-format msgid "%s is suitable for teenagers" msgstr "%s phĂš hᝣp với thiáşżu niĂŞn" #: src/bz-age-rating-dialog.c:869 #, c-format msgid "%s is suitable for adults" msgstr "%s phĂš hᝣp với người lớn" #: src/bz-age-rating-dialog.c:872 #, c-format msgid "%s is suitable for %s" msgstr "%s phĂš hᝣp với %s" #: src/bz-app-size-dialog.blp:43 msgid "--- MB" msgstr "--- MB" #: src/bz-app-size-dialog.blp:53 msgid "Download Size" msgstr "KĂ­ch thước tải vᝁ" #: src/bz-app-size-dialog.c:55 msgid "Of the size of human DNA" msgstr "KĂ­ch thước cáť§a DNA người" #: src/bz-app-size-dialog.c:55 msgid "3 billion base pairs" msgstr "3 tᝡ cạp base" #: src/bz-app-size-dialog.c:56 msgid "Of the Linux Kernel" msgstr "KĂ­ch thước cáť§a Linux Kernel" #: src/bz-app-size-dialog.c:56 msgid "linux-6.17.tar.xz" msgstr "linux-6.17.tar.xz" #: src/bz-app-size-dialog.c:57 msgid "Of the Apollo 11 guidance computer" msgstr "KĂ­ch thước cáť§a mĂĄy tĂ­nh dẍn đường Apollo 11" #: src/bz-app-size-dialog.c:57 msgid "Total ROM and RAM" msgstr "Tổng ROM vĂ  RAM" #: src/bz-app-size-dialog.c:58 msgid "Of the original Super Mario Bros" msgstr "KĂ­ch thước cáť§a Super Mario Bros gốc" #: src/bz-app-size-dialog.c:58 msgid "On the NES" msgstr "TrĂŞn NES" #: src/bz-app-size-dialog.c:59 msgid "Of the size of Wikipedia" msgstr "KĂ­ch thước cáť§a Wikipedia" #: src/bz-app-size-dialog.c:59 msgid "Without any media" msgstr "KhĂ´ng cĂł media" #: src/bz-application.c:556 msgid "" "This functionality is currently disabled. It is recommended you download and " "install Flatseal to manage app permissions." msgstr "" "Chᝊc năng nĂ y hiện bị tắt. Khuyáşżn nghị bấn tải vĂ  cĂ i Flatseal để quản lĂ˝ " "quyᝁn ᝊng d᝼ng." #: src/bz-application.c:638 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:639 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:664 msgid "translator-credits" msgstr "Loc Huynh , 2025" #: src/bz-application.c:788 msgid "Performing setup..." msgstr "Đang tháťąc hiện thiáşżt láş­p..." #: src/bz-application.c:817 src/bz-application.c:826 msgid "Set Up Flathub" msgstr "Thiáşżt láş­p Flathub" #: src/bz-application.c:820 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub chưa được thiáşżt láş­p trĂŞn hệ thống nĂ y. Bấn sáş˝ khĂ´ng thᝃ duyệt vĂ  cĂ i " "đặt ᝊng d᝼ng trong Bazaar náşżu nĂł khĂ´ng khả d᝼ng.\n" "\n" "Bấn vẍn cĂł thᝃ dĂšng Bazaar để duyệt vĂ  gᝥ bỏ cĂĄc ᝊng d᝼ng đã cĂ i." #: src/bz-application.c:825 src/bz-update-dialog.blp:6 msgid "Later" msgstr "Đᝃ sau" #: src/bz-application.c:1225 msgid "Synchronizing..." msgstr "Đang đồng bộ hĂła..." #: src/bz-application.c:1364 #, c-format msgid "Receiving %d entries..." msgstr "Đang nháş­n %d m᝼c..." #: src/bz-application.c:1369 msgid "Checking for updates..." msgstr "Đang kiᝃm tra cáş­p nháş­t..." #: src/bz-curated-view.blp:11 src/bz-flathub-page.blp:19 #: src/bz-full-view.blp:54 src/bz-installed-page.blp:15 src/bz-window.blp:183 msgid "Empty" msgstr "Trống" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "KhĂ´ng cĂł láťąa chọn" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "" "KhĂ´ng cĂł thĂ´ng tin chọn lọc trĂŞn hệ thống nĂ y. Bấn vẍn cĂł thᝃ duyệt ᝊng d᝼ng " "trĂŞn Flathub" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "Duyệt Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "Ngoấi tuyáşżn" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:40 msgid "Browser" msgstr "TrĂŹnh duyệt" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "ThĂ´ng tin nhĂ  phĂĄt triᝃn khĂ´ng khả d᝼ng." #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "" "Quyᝁn sở hᝯu ID ᝊng d᝼ng %s chưa được xĂĄc minh vĂ  cĂł thᝃ lĂ  gĂłi cộng đồng." #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "Quyᝁn sở hᝯu ID ᝊng d᝼ng %s đã được đội ngĹŠ Flathub xĂĄc minh tháť§ cĂ´ng." #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %s app ID has been verified by %s on %s." msgstr "Quyᝁn sở hᝯu ID ᝊng d᝼ng %s đã được %s xĂĄc minh trĂŞn %s." #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %s app ID has been verified using %s." msgstr "Quyᝁn sở hᝯu ID ᝊng d᝼ng %s đã được xĂĄc minh báşąng %s." #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "Quyᝁn sở hᝯu ID ᝊng d᝼ng %s đã được xĂĄc minh." #: src/bz-entry-inspector.blp:5 msgid "Entry Inspector" msgstr "TrĂŹnh kiᝃm tra m᝼c" #: src/bz-entry-inspector.blp:76 msgid "Serialize" msgstr "Chuyᝃn thĂ nh chuỗi" #: src/bz-entry-inspector.blp:80 msgid "Convert to JSON" msgstr "Chuyᝃn sang JSON" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "Đã xảy ra lỗi" #: src/bz-error.c:89 msgid "Close" msgstr "Đóng" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "Sao chĂŠp vĂ  đóng" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "ᝨng d᝼ng cáť§a ngĂ y" #: src/bz-flathub-category.c:78 msgid "Audio & Video" msgstr "Âm thanh & Video" #: src/bz-flathub-category.c:78 msgid "Media" msgstr "Đa phưƥng tiện" #: src/bz-flathub-category.c:78 msgid "More Audio & Video" msgstr "ThĂŞm Âm thanh & Video" #: src/bz-flathub-category.c:79 msgid "Developer Tools" msgstr "CĂ´ng c᝼ phĂĄt triᝃn" #: src/bz-flathub-category.c:79 msgid "Develop" msgstr "PhĂĄt triᝃn" #: src/bz-flathub-category.c:79 msgid "More Developer Tools" msgstr "ThĂŞm CĂ´ng c᝼ phĂĄt triᝃn" #: src/bz-flathub-category.c:80 msgid "Education" msgstr "GiĂĄo d᝼c" #: src/bz-flathub-category.c:80 msgid "Learn" msgstr "Học táş­p" #: src/bz-flathub-category.c:80 msgid "More Education" msgstr "ThĂŞm GiĂĄo d᝼c" #: src/bz-flathub-category.c:81 msgid "Gaming" msgstr "Trò chĆĄi" #: src/bz-flathub-category.c:81 msgid "Play" msgstr "ChĆĄi" #: src/bz-flathub-category.c:81 msgid "More Gaming" msgstr "ThĂŞm Trò chĆĄi" #: src/bz-flathub-category.c:82 msgid "Graphics & Photography" msgstr "Đồ họa & Nhiáşżp ảnh" #: src/bz-flathub-category.c:82 msgid "Create" msgstr "SĂĄng tấo" #: src/bz-flathub-category.c:82 msgid "More Graphics & Photography" msgstr "ThĂŞm Đồ họa & Nhiáşżp ảnh" #: src/bz-flathub-category.c:83 msgid "Networking" msgstr "Mấng" #: src/bz-flathub-category.c:83 msgid "Internet" msgstr "Internet" #: src/bz-flathub-category.c:83 msgid "More Networking" msgstr "ThĂŞm Mấng" #: src/bz-flathub-category.c:84 msgid "Productivity" msgstr "Năng suẼt" #: src/bz-flathub-category.c:84 msgid "Work" msgstr "CĂ´ng việc" #: src/bz-flathub-category.c:84 msgid "More Productivity" msgstr "ThĂŞm Năng suẼt" #: src/bz-flathub-category.c:85 msgid "Science" msgstr "Khoa học" #: src/bz-flathub-category.c:85 msgid "More Science" msgstr "ThĂŞm Khoa học" #: src/bz-flathub-category.c:86 msgid "System" msgstr "Hệ thống" #: src/bz-flathub-category.c:86 msgid "More System" msgstr "ThĂŞm Hệ thống" #: src/bz-flathub-category.c:87 msgid "Utilities" msgstr "Tiện Ă­ch" #: src/bz-flathub-category.c:87 msgid "Tools" msgstr "CĂ´ng c᝼" #: src/bz-flathub-category.c:87 msgid "More Utilities" msgstr "ThĂŞm Tiện Ă­ch" #: src/bz-flathub-category.c:88 src/bz-flathub-page.blp:110 #: src/bz-flathub-page.blp:143 msgid "Trending" msgstr "Thịnh hĂ nh" #: src/bz-flathub-category.c:88 msgid "More Trending" msgstr "ThĂŞm Thịnh hĂ nh" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:116 #: src/bz-flathub-page.blp:176 msgid "Popular" msgstr "Phổ biáşżn" #: src/bz-flathub-category.c:89 msgid "More Popular" msgstr "ThĂŞm Phổ biáşżn" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:165 msgid "Recently Added" msgstr "Mới thĂŞm gáş§n đây" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:122 msgid "New" msgstr "Mới" #: src/bz-flathub-category.c:90 msgid "More New" msgstr "ThĂŞm Mới" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:154 msgid "Recently Updated" msgstr "Mới cáş­p nháş­t gáş§n đây" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:128 msgid "Updated" msgstr "Đã cáş­p nháş­t" #: src/bz-flathub-category.c:91 msgid "More Updated" msgstr "ThĂŞm Đã cáş­p nháş­t" #: src/bz-flathub-category.c:92 msgid "Mobile" msgstr "Di động" #: src/bz-flathub-category.c:92 msgid "More Mobile" msgstr "ThĂŞm Di động" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub chưa được thĂŞm" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "Remote Flathub khĂ´ng được tĂŹm thẼy trong bẼt káťł cĂ i đặt Flatpak nĂ o" #: src/bz-flathub-page.blp:48 msgid "Flathub Unavailable" msgstr "Flathub khĂ´ng khả d᝼ng" #: src/bz-flathub-page.blp:49 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "" "KhĂ´ng thᝃ káşżt nối đến Flathub. Bấn vẍn cĂł thᝃ quản lĂ˝ vĂ  tĂŹm kiáşżm ᝊng d᝼ng." #: src/bz-flathub-page.blp:52 msgid "Search Apps" msgstr "TĂŹm kiáşżm ᝊng d᝼ng" #: src/bz-flathub-page.blp:261 msgid "On the Go" msgstr "Di động" #: src/bz-flathub-page.blp:273 msgid "Apps for your Linux phones and tablets" msgstr "ᝨng d᝼ng cho điện thoấi vĂ  mĂĄy tĂ­nh bảng Linux" #: src/bz-flathub-page.blp:284 msgid "More Mobile Apps" msgstr "ThĂŞm ᝨng d᝼ng di động" #: src/bz-flathub-page.blp:319 msgid "More Mobile apps" msgstr "ThĂŞm ᝊng d᝼ng di động" #: src/bz-flathub-page.blp:379 msgid "We ♥ Games" msgstr "We ♥ Games" #: src/bz-flathub-page.blp:392 msgid "Games and apps to run your favorite titles" msgstr "Trò chĆĄi vĂ  ᝊng d᝼ng để chấy cĂĄc táťąa game yĂŞu thĂ­ch" #: src/bz-flathub-page.blp:426 msgid "More Games" msgstr "ThĂŞm Trò chĆĄi" #: src/bz-flatpak-entry.c:574 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Trang Flathub" #: src/bz-flatpak-entry.c:595 msgctxt "Project URL Type" msgid "Project Website" msgstr "Trang web dáťą ĂĄn" #: src/bz-flatpak-entry.c:599 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "Theo dĂľi lỗi" #: src/bz-flatpak-entry.c:603 msgctxt "Project URL Type" msgid "FAQ" msgstr "Câu hỏi thường gạp" #: src/bz-flatpak-entry.c:607 msgctxt "Project URL Type" msgid "Help" msgstr "Trᝣ giĂşp" #: src/bz-flatpak-entry.c:611 msgctxt "Project URL Type" msgid "Donate" msgstr "QuyĂŞn gĂłp" #: src/bz-flatpak-entry.c:617 msgctxt "Project URL Type" msgid "Translate" msgstr "Dịch thuáş­t" #: src/bz-flatpak-entry.c:621 msgctxt "Project URL Type" msgid "Contact" msgstr "LiĂŞn hệ" #: src/bz-flatpak-entry.c:625 msgctxt "Project URL Type" msgid "Source Code" msgstr "MĂŁ nguồn" #: src/bz-flatpak-entry.c:631 msgctxt "Project URL Type" msgid "Contribute" msgstr "Đóng gĂłp" #: src/bz-full-view.blp:21 src/bz-window.blp:126 src/bz-window.blp:380 msgid "Toggle transaction sidebar" msgstr "Báş­t/tắt thanh bĂŞn giao dịch" #: src/bz-full-view.blp:44 src/bz-window.blp:403 msgid "Main Menu" msgstr "Menu chĂ­nh" #: src/bz-full-view.blp:58 msgid "No Results" msgstr "KhĂ´ng cĂł káşżt quả" #: src/bz-full-view.blp:59 msgid "Try a different search query" msgstr "Tháť­ truy vẼn tĂŹm kiáşżm khĂĄc" #: src/bz-full-view.blp:65 src/bz-window.blp:193 msgid "Content" msgstr "Nội dung" #: src/bz-full-view.blp:211 msgid "Support" msgstr "Hỗ trᝣ" #: src/bz-full-view.blp:231 msgid "Repository Star Count" msgstr "Số sao kho lưu trᝯ" #: src/bz-full-view.blp:261 src/bz-full-view.blp:516 msgid "Open" msgstr "Mở" #: src/bz-full-view.blp:274 src/bz-full-view.blp:489 msgid "Download & Install Application" msgstr "Tải xuống & cĂ i đặt ᝊng d᝼ng" #: src/bz-full-view.blp:289 msgid "Uninstall Application" msgstr "Gᝥ cĂ i đặt ᝊng d᝼ng" #: src/bz-full-view.blp:304 src/bz-full-view.blp:531 msgid "Install Other Version" msgstr "CĂ i đặt phiĂŞn bản khĂĄc" #: src/bz-full-view.blp:328 msgid "Size" msgstr "KĂ­ch thước" #: src/bz-full-view.blp:433 msgid "Downloads /mo" msgstr "Lưᝣt tải/thĂĄng" #: src/bz-full-view.blp:550 msgid "Stopped Receiving Core Updates" msgstr "Ngᝍng nháş­n cáş­p nháş­t lĂľi" #: src/bz-full-view.blp:564 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "ᝨng d᝼ng nĂ y dĂšng runtime khĂ´ng còn nháş­n cáş­p nháş­t hoạc vĂĄ bảo máş­t. CĂł thᝃ " "trở nĂŞn khĂ´ng an toĂ n khi sáť­ d᝼ng." #: src/bz-full-view.blp:735 msgid "Tags:" msgstr "Tháşť:" #: src/bz-full-view.c:301 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:308 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:315 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:325 #, c-format msgid "%d downloads in the last 30 days" msgstr "%d lưᝣt tải trong 30 ngĂ y qua" #: src/bz-full-view.c:357 #, c-format msgid "Download size of %s" msgstr "KĂ­ch thước tải vᝁ %s" #: src/bz-full-view.c:390 msgid "All Ages" msgstr "Mọi lᝊa tuổi" #: src/bz-full-view.c:402 msgid "Age rating information unavailable" msgstr "ThĂ´ng tin xáşżp hấng độ tuổi khĂ´ng khả d᝼ng" #: src/bz-full-view.c:407 msgid "Suitable for all ages" msgstr "PhĂš hᝣp với mọi lᝊa tuổi" #: src/bz-full-view.c:409 #, c-format msgid "Suitable for ages %d and up" msgstr "PhĂš hᝣp tᝍ %d tuổi trở lĂŞn" #: src/bz-full-view.c:440 msgid "Unknown" msgstr "KhĂ´ng xĂĄc định" #: src/bz-full-view.c:443 msgid "Proprietary Software" msgstr "Pháş§n mᝁm độc quyᝁn" #: src/bz-full-view.c:447 #, c-format msgid "Free software licensed under %s" msgstr "Pháş§n mᝁm miễn phĂ­ theo giẼy phĂŠp %s" #: src/bz-full-view.c:455 msgid "Free" msgstr "Miễn phĂ­" #: src/bz-full-view.c:455 src/bz-license-dialog.blp:135 msgid "Proprietary" msgstr "Độc quyᝁn" #: src/bz-full-view.c:475 msgid "Adaptive" msgstr "ThĂ­ch ᝊng" #: src/bz-full-view.c:475 msgid "Desktop Only" msgstr "Chỉ mĂĄy tĂ­nh để bĂ n" #: src/bz-full-view.c:481 msgid "Works on desktop, tablets, and phones" msgstr "Hoất động trĂŞn mĂĄy tĂ­nh để bĂ n, mĂĄy tĂ­nh bảng vĂ  điện thoấi" #: src/bz-full-view.c:482 msgid "May not work on mobile devices" msgstr "CĂł thᝃ khĂ´ng hoất động tốt trĂŞn thiáşżt bị di động" #: src/bz-full-view.c:493 msgid "No URL" msgstr "KhĂ´ng cĂł URL" #: src/bz-full-view.c:511 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "" "ᝨng d᝼ng nĂ y cĂł giẼy phĂŠp FLOSS, nghÄŠa lĂ  mĂŁ nguồn cĂł thᝃ được kiᝃm tra để " "đảm bảo an toĂ n." #: src/bz-full-view.c:512 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "ᝨng d᝼ng nĂ y cĂł giẼy phĂŠp độc quyᝁn, nghÄŠa lĂ  mĂŁ nguồn được phĂĄt triᝃn riĂŞng " "tư vĂ  khĂ´ng thᝃ được kiᝃm tra bởi bĂŞn thᝊ ba độc láş­p." #: src/bz-full-view.c:519 msgid "More Apps" msgstr "ThĂŞm ᝨng d᝼ng" #: src/bz-full-view.c:520 #, c-format msgid "More Apps by %s" msgstr "ThĂŞm ᝨng d᝼ng tᝍ %s" #: src/bz-full-view.c:527 msgid "Other Apps by this Developer" msgstr "ᝨng d᝼ng khĂĄc tᝍ nhĂ  phĂĄt triᝃn nĂ y" #: src/bz-full-view.c:529 src/bz-full-view.c:629 #, c-format msgid "Other Apps by %s" msgstr "ᝨng d᝼ng khĂĄc tᝍ %s" #: src/bz-full-view.c:631 msgid "Other Apps" msgstr "ᝨng d᝼ng khĂĄc" #: src/bz-full-view.c:633 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d ᝊng d᝼ng" #: src/bz-full-view.c:972 msgid "Show Less" msgstr "Thu gọn" #: src/bz-full-view.c:972 msgid "Show More" msgstr "Hiện thĂŞm" #: src/bz-hardware-support-dialog.blp:6 src/bz-hardware-support-dialog.blp:47 msgid "Hardware Support" msgstr "Hỗ trᝣ pháş§n cᝊng" #: src/bz-hardware-support-dialog.c:69 msgid "Keyboard support" msgstr "Hỗ trᝣ bĂ n phĂ­m" #: src/bz-hardware-support-dialog.c:71 msgid "Requires keyboards" msgstr "YĂŞu cáş§u bĂ n phĂ­m" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends keyboards" msgstr "Khuyáşżn nghị bĂ n phĂ­m" #: src/bz-hardware-support-dialog.c:73 msgid "Supports keyboards" msgstr "Hỗ trᝣ bĂ n phĂ­m" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for keyboards" msgstr "Hỗ trᝣ bĂ n phĂ­m khĂ´ng xĂĄc định" #: src/bz-hardware-support-dialog.c:76 msgid "Mouse support" msgstr "Hỗ trᝣ chuột" #: src/bz-hardware-support-dialog.c:78 msgid "Requires mice or pointing devices" msgstr "YĂŞu cáş§u chuột hoạc thiáşżt bị trỏ" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends mice or pointing devices" msgstr "Khuyáşżn nghị chuột hoạc thiáşżt bị trỏ" #: src/bz-hardware-support-dialog.c:80 msgid "Supports mice or pointing devices" msgstr "Hỗ trᝣ chuột hoạc thiáşżt bị trỏ" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for mice or pointing devices" msgstr "Hỗ trᝣ chuột hoạc thiáşżt bị trỏ khĂ´ng xĂĄc định" #: src/bz-hardware-support-dialog.c:83 msgid "Touchscreen support" msgstr "Hỗ trᝣ mĂ n hĂŹnh cảm ᝊng" #: src/bz-hardware-support-dialog.c:85 msgid "Requires touchscreens" msgstr "YĂŞu cáş§u mĂ n hĂŹnh cảm ᝊng" #: src/bz-hardware-support-dialog.c:86 msgid "Recommends touchscreens" msgstr "Khuyáşżn nghị mĂ n hĂŹnh cảm ᝊng" #: src/bz-hardware-support-dialog.c:87 msgid "Supports touchscreens" msgstr "Hỗ trᝣ mĂ n hĂŹnh cảm ᝊng" #: src/bz-hardware-support-dialog.c:88 msgid "Unknown support for touchscreens" msgstr "Hỗ trᝣ mĂ n hĂŹnh cảm ᝊng khĂ´ng xĂĄc định" #: src/bz-hardware-support-dialog.c:192 msgid "Mobile support" msgstr "Hỗ trᝣ di động" #: src/bz-hardware-support-dialog.c:193 msgid "Works on mobile devices" msgstr "Hoất động trĂŞn thiáşżt bị di động" #: src/bz-hardware-support-dialog.c:193 msgid "May not work well on mobile devices" msgstr "CĂł thᝃ khĂ´ng hoất động tốt trĂŞn thiáşżt bị di động" #: src/bz-hardware-support-dialog.c:198 msgid "Desktop support" msgstr "Hỗ trᝣ mĂĄy tĂ­nh để bĂ n" #: src/bz-hardware-support-dialog.c:199 msgid "Works well on large screens" msgstr "Hoất động tốt trĂŞn mĂ n hĂŹnh lớn" #: src/bz-hardware-support-dialog.c:233 #, c-format msgid "%s works best on specific hardware" msgstr "%s hoất động tốt nhẼt trĂŞn pháş§n cᝊng c᝼ thᝃ" #: src/bz-hardware-support-dialog.c:240 #, c-format msgid "%s works on most devices" msgstr "%s hoất động trĂŞn háş§u háşżt thiáşżt bị" #: src/bz-inspector.blp:5 msgid "Bazaar Inspector" msgstr "TrĂŹnh kiᝃm tra Bazaar" #: src/bz-inspector.blp:33 msgid "Background Task Info:" msgstr "ThĂ´ng tin tĂĄc v᝼ nᝁn:" #: src/bz-inspector.blp:43 msgid "Enable Global Debug Mode" msgstr "Báş­t cháşż độ gᝥ lỗi toĂ n c᝼c" #: src/bz-inspector.blp:50 msgid "Active Blocklists" msgstr "Danh sĂĄch chạn hoất động" #: src/bz-inspector.blp:67 msgid "Active Curated-Configs" msgstr "CẼu hĂŹnh chọn lọc hoất động" #: src/bz-inspector.blp:85 msgid "All Entry Groups" msgstr "TẼt cả nhĂłm m᝼c" #: src/bz-inspector.blp:93 msgid "Filter..." msgstr "Lọc..." #: src/bz-inspector.blp:134 msgid "Decache and Inspect" msgstr "XĂła bộ đệm vĂ  kiᝃm tra" #: src/bz-installed-page.blp:19 msgid "No Flatpaks Installed" msgstr "Chưa cĂ i Flatpak nĂ o" #: src/bz-installed-page.blp:25 src/bz-window.blp:298 msgid "Installed" msgstr "Đã cĂ i đặt" #: src/bz-installed-page.c:395 msgid "Choose an Installation" msgstr "Chọn cĂ i đặt" #: src/bz-installed-page.c:398 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with? " msgstr "" "Bấn đã cĂ i nhiᝁu phiĂŞn bản cáť§a ᝊng d᝼ng nĂ y. Bấn muốn tiáşżp t᝼c với phiĂŞn bản " "nĂ o? " #: src/bz-installed-page.c:402 src/bz-window.c:1101 src/bz-window.c:1124 msgid "Cancel" msgstr "Háť§y" #: src/bz-license-dialog.blp:77 msgid "Community Built" msgstr "Do cộng đồng xây dáťąng" #: src/bz-license-dialog.blp:176 msgid "Get Involved" msgstr "Tham gia" #: src/bz-license-dialog.c:115 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may not be able to contribute to this app." msgstr "" "ᝨng d᝼ng nĂ y khĂ´ng được phĂĄt triᝃn cĂ´ng khai, chỉ nhĂ  phĂĄt triᝃn biáşżt cĂĄch " "nĂł hoất động. CĂł thᝃ khĂ´ng an toĂ n theo cĂĄch khĂł phĂĄt hiện vĂ  cĂł thᝃ thay " "đổi mĂ  khĂ´ng được giĂĄm sĂĄt.\n" "\n" "Bấn cĂł thᝃ khĂ´ng đóng gĂłp được cho ᝊng d᝼ng nĂ y." #: src/bz-license-dialog.c:124 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "ᝨng d᝼ng nĂ y được cộng đồng quốc táşż phĂĄt triᝃn cĂ´ng khai.\n" "\n" "Bấn cĂł thᝃ tham gia vĂ  giĂşp nĂł tốt hĆĄn." #: src/bz-license-dialog.c:135 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "ᝨng d᝼ng nĂ y được cộng đồng quốc táşż phĂĄt triᝃn cĂ´ng khai vĂ  phĂĄt hĂ nh theo " "giẼy phĂŠp %s.\n" "\n" "Bấn cĂł thᝃ tham gia vĂ  giĂşp nĂł tốt hĆĄn." #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "TĂšy chỉnh" #: src/bz-preferences-dialog.blp:23 msgid "Content Filters" msgstr "Bộ lọc nội dung" #: src/bz-preferences-dialog.blp:26 msgid "Free Software Only" msgstr "Chỉ pháş§n mᝁm miễn phĂ­" #: src/bz-preferences-dialog.blp:27 msgid "Hide proprietary applications when browsing and searching" msgstr "Ẩn ᝊng d᝼ng độc quyᝁn khi duyệt vĂ  tĂŹm kiáşżm" #: src/bz-preferences-dialog.blp:31 msgid "Flathub Results Only" msgstr "Chỉ káşżt quả Flathub" #: src/bz-preferences-dialog.blp:32 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "Giới hấn káşżt quả tĂŹm kiáşżm vĂ  duyệt chỉ ở ᝊng d᝼ng cĂł trĂŞn Flathub" #: src/bz-preferences-dialog.blp:36 msgid "Hide EOL Apps" msgstr "Ẩn ᝊng d᝼ng EOL" #: src/bz-preferences-dialog.blp:37 msgid "Hide apps which are no longer supported by their developers" msgstr "Ẩn ᝊng d᝼ng khĂ´ng còn được nhĂ  phĂĄt triᝃn hỗ trᝣ" #: src/bz-preferences-dialog.blp:42 src/bz-window.blp:313 msgid "Search" msgstr "TĂŹm kiáşżm" #: src/bz-preferences-dialog.blp:45 msgid "Delay Search Results" msgstr "TrĂŹ hoĂŁn káşżt quả tĂŹm kiáşżm" #: src/bz-preferences-dialog.blp:46 msgid "Improve results performance by debouncing search terms" msgstr "Cải thiện hiệu suẼt káşżt quả báşąng cĂĄch trĂŹ hoĂŁn tᝍ khĂła tĂŹm kiáşżm" #: src/bz-preferences-dialog.blp:51 msgid "Application Details" msgstr "Chi tiáşżt ᝊng d᝼ng" #: src/bz-preferences-dialog.blp:54 msgid "Display Star Count" msgstr "Hiᝃn thị số sao" #: src/bz-preferences-dialog.blp:55 msgid "Show the star count of an application's source code repository" msgstr "Hiᝃn thị số sao cáť§a kho mĂŁ nguồn ᝊng d᝼ng" #: src/bz-preferences-dialog.blp:80 msgid "Progress Bar" msgstr "Thanh tiáşżn trĂŹnh" #: src/bz-preferences-dialog.blp:81 msgid "Choose a theme for the progress bar!" msgstr "Chọn cháť§ đề cho thanh tiáşżn trĂŹnh!" #: src/bz-preferences-dialog.blp:116 msgid "" "Bazaar can fetch and display the star count from an application's source " "code repository on a remote Git forge. \n" " For projects on GitHub, rate limits may cause them not to appear." msgstr "" "Bazaar cĂł thᝃ lẼy vĂ  hiᝃn thị số sao tᝍ kho mĂŁ nguồn ᝊng d᝼ng trĂŞn git forge " "tᝍ xa.\n" "Đối với dáťą ĂĄn trĂŞn GitHub, giới hấn tốc độ cĂł thᝃ khiáşżn chĂşng khĂ´ng xuẼt " "hiện." #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "MĂ u nổi báş­t" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "MĂ u cờ LGBT+" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "MĂ u cờ Lesbian" #: src/bz-preferences-dialog.c:35 msgid "Transgender Pride Colors" msgstr "MĂ u cờ Transgender" #: src/bz-preferences-dialog.c:36 msgid "Nonbinary Pride Colors" msgstr "MĂ u cờ Nonbinary" #: src/bz-preferences-dialog.c:37 msgid "Bisexual Pride Colors" msgstr "MĂ u cờ Bisexual" #: src/bz-preferences-dialog.c:38 msgid "Asexual Pride Colors" msgstr "MĂ u cờ Asexual" #: src/bz-preferences-dialog.c:39 msgid "Pansexual Pride Colors" msgstr "MĂ u cờ Pansexual" #: src/bz-preferences-dialog.c:40 msgid "Aromantic Pride Colors" msgstr "MĂ u cờ Aromantic" #: src/bz-preferences-dialog.c:41 msgid "Genderfluid Pride Colors" msgstr "MĂ u cờ Genderfluid" #: src/bz-preferences-dialog.c:42 msgid "Polysexual Pride Colors" msgstr "MĂ u cờ Polysexual" #: src/bz-preferences-dialog.c:43 msgid "Omnisexual Pride Colors" msgstr "MĂ u cờ Omnisexual" #: src/bz-preferences-dialog.c:44 msgid "Aroace Pride Colors" msgstr "MĂ u cờ Aroace" #: src/bz-preferences-dialog.c:45 msgid "Agender Pride Colors" msgstr "MĂ u cờ Agender" #: src/bz-preferences-dialog.c:46 msgid "Genderqueer Pride Colors" msgstr "MĂ u cờ Genderqueer" #: src/bz-preferences-dialog.c:47 msgid "Intersex Pride Colors" msgstr "MĂ u cờ Intersex" #: src/bz-preferences-dialog.c:48 msgid "Demigender Pride Colors" msgstr "MĂ u cờ Demigender" #: src/bz-preferences-dialog.c:49 msgid "Biromantic Pride Colors" msgstr "MĂ u cờ Biromantic" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:26 msgid "Version History" msgstr "Lịch sáť­ phiĂŞn bản" #: src/bz-releases-list.c:128 #, c-format msgid "Version %s" msgstr "PhiĂŞn bản %s" #: src/bz-releases-list.c:153 msgid "No details for this release" msgstr "KhĂ´ng cĂł chi tiáşżt cho bản phĂĄt hĂ nh nĂ y" #: src/bz-rich-app-tile.blp:137 msgid "Stopped Receiving Updates" msgstr "Ngᝍng nháş­n cáş­p nháş­t" #: src/bz-rich-app-tile.blp:154 msgid "Get" msgstr "Tải" #: src/bz-search-widget.blp:105 msgid "Search Apps, Games, Software" msgstr "TĂŹm kiáşżm ᝊng d᝼ng, trò chĆĄi, pháş§n mᝁm" #: src/bz-search-widget.blp:149 msgid "Categories Unavailable" msgstr "Danh m᝼c khĂ´ng khả d᝼ng" #: src/bz-search-widget.blp:150 msgid "Search for apps using the search bar above." msgstr "TĂŹm kiáşżm ᝊng d᝼ng báşąng thanh tĂŹm kiáşżm phĂ­a trĂŞn." #: src/bz-search-widget.blp:234 msgid "No Applications Found" msgstr "KhĂ´ng tĂŹm thẼy ᝊng d᝼ng" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "KhĂ´ng tĂŹm thẼy káşżt quả cho \"%s\" trĂŞn Flathub" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "Đã sao chĂŠp!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "Sao chĂŠp liĂŞn káşżt" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "Mở liĂŞn káşżt" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "Dòng thời gian" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "CĂ i đặt:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "Tháşż giới" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "KhĂ´ng tĂŹm thẼy káşżt quả" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "ᝨng d᝼ng cĂł tháşť \"%s\"" #: src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d ᝊng d᝼ng" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "TĂŹm kiáşżm thẼt bấi" #: src/bz-transaction-manager.c:1132 #, c-format msgid "Finished in %.02f seconds" msgstr "HoĂ n thĂ nh trong %.02f giây" #: src/bz-transaction-view.blp:94 msgid "App Add-on" msgstr "Tiện Ă­ch mở rộng ᝊng d᝼ng" #: src/bz-transaction-view.blp:119 msgid "Runtime" msgstr "Runtime" #: src/bz-transaction-view.blp:145 src/bz-transaction-view.blp:171 msgid "Install Size" msgstr "KĂ­ch thước cĂ i đặt" #: src/bz-transaction-view.blp:199 src/bz-window.blp:346 msgid "Update" msgstr "Cáş­p nháş­t" #: src/bz-transaction-view.c:139 #, c-format msgid "Transferred %s so far" msgstr "Đã truyᝁn %s" #: src/bz-transaction.c:336 msgid "Pending" msgstr "Đang chờ" #: src/bz-update-dialog.blp:7 msgid "Install Now" msgstr "CĂ i đặt ngay" #: src/bz-update-dialog.blp:10 msgid "Updates Are Available" msgstr "CĂł bản cáş­p nháş­t" #: src/bz-update-dialog.blp:11 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "" "CĂĄc ᝊng d᝼ng sau đủ điᝁu kiện cáş­p nháş­t. Bấn cĂł muốn cĂ i đặt chĂşng khĂ´ng?" #: src/bz-update-dialog.c:134 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "" "%d runtime vĂ /hoạc tiện Ă­ch mở rộng đủ điᝁu kiện cáş­p nháş­t. Bấn cĂł muốn cĂ i " "đặt chĂşng khĂ´ng?" #: src/bz-update-dialog.c:142 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "NgoĂ i ra, %d runtime vĂ /hoạc tiện Ă­ch mở rộng sáş˝ được cáş­p nháş­t." #: src/bz-window.blp:66 msgid "Inspect UI Entry" msgstr "Kiᝃm tra m᝼c giao diện" #: src/bz-window.blp:73 msgid "All Debug Actions" msgstr "TẼt cả hĂ nh động gᝥ lỗi" #: src/bz-window.blp:107 msgid "Tasks" msgstr "TĂĄc v᝼" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "Dᝍng tĂĄc v᝼ đang chấy" #: src/bz-window.blp:171 msgid "Clear History" msgstr "XĂła lịch sáť­" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "Chưa cĂł tĂĄc v᝼" #: src/bz-window.blp:258 msgid "Refreshing Store Content" msgstr "Đang lĂ m mới nội dung cáť­a hĂ ng" #: src/bz-window.blp:273 msgid "Curated" msgstr "Chọn lọc" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:330 msgid "Sync" msgstr "Đồng bộ" #: src/bz-window.blp:466 msgid "_Donate to Bazaar ❤️" msgstr "_QuyĂŞn gĂłp cho Bazaar ❤️" #: src/bz-window.blp:473 msgid "_Preferences" msgstr "_TĂšy chỉnh" #: src/bz-window.blp:478 msgid "_Keyboard Shortcuts" msgstr "_PhĂ­m tắt" #: src/bz-window.blp:483 msgid "_About Bazaar" msgstr "_Giới thiệu Bazaar" #: src/bz-window.blp:490 msgid "_Quit Bazaar" msgstr "ThoĂĄt _Bazaar" #: src/bz-window.blp:499 msgid "Open Bazaar Inspector" msgstr "Mở TrĂŹnh kiᝃm tra Bazaar" #: src/bz-window.c:844 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "Khả năng kiᝃm tra vĂ  cĂ i đặt táş­p tin .flatpak bundle c᝼c bộ sáş˝ sớm cĂł! Trong " "lĂşc chờ đợi, hĂŁy tháť­ chấy\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "trĂŞn dòng lệnh." #: src/bz-window.c:966 msgid "Can't do that right now!" msgstr "Hiện khĂ´ng thᝃ tháťąc hiện!" #: src/bz-window.c:1095 #, c-format msgid "Install %s?" msgstr "CĂ i đặt %s?" #: src/bz-window.c:1098 msgid "May install additional shared components" msgstr "CĂł thᝃ cĂ i đặt thĂŞm thĂ nh pháş§n chia sáşť" #: src/bz-window.c:1117 #, c-format msgid "Remove %s?" msgstr "Gᝥ bỏ %s?" #: src/bz-window.c:1121 #, c-format msgid "" "It will not be possible to use %s after it is uninstalled.\n" "\n" "Settings and user data will be kept." msgstr "" "Sáş˝ khĂ´ng thᝃ sáť­ d᝼ng %s sau khi gᝥ bỏ.\n" "\n" "CĂ i đặt vĂ  dᝯ liệu người dĂšng sáş˝ được giᝯ lấi." #: src/bz-window.c:1286 msgid "Resume Current Tasks" msgstr "Tiáşżp t᝼c tĂĄc v᝼ hiện tấi" #: src/bz-window.c:1292 msgid "Pause Current Tasks" msgstr "Tấm dᝍng tĂĄc v᝼ hiện tấi" #: src/bz-world-map.c:523 #, c-format msgid "%s: %'u downloads" msgstr "%s: %'u lưᝣt tải" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "Chung" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "Mở hộp thoấi tĂŹm kiáşżm" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "Mở tĂšy chỉnh" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Refresh" msgstr "LĂ m mới" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "Báş­t/tắt quản lĂ˝ giao dịch" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "Hiᝃn thị phĂ­m tắt" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "ThoĂĄt" kolunmi-bazaar-7b9c8e1/po/zh_CN.po000066400000000000000000002265711514314607700170560ustar00rootroot00000000000000# Chinese translations for bazaar package # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Shinsei , 2025. # jiesou , 2026. # Mikosh <>, 2026. # msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-02-09 15:07+0000\n" "PO-Revision-Date: 2026-02-10 01:09+0800\n" "Last-Translator: jiesou \n" "Language-Team: Chinese (China)\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Gtranslator 49.0\n" "Plural-Forms: nplurals=1; plural=0;\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:6 #: src/bz-window.blp:111 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "添加、卸载和更新此电脑上的 Flatpak 软䝜" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "新窗口" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "发现和安装应用" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "一款专为 Linux 设计的新应用商店,致力于从 Flatpak 远程仓库(特别是 Flathub)" "中发现并安装应用程序及插件。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "其强调支持那些使 Linux 桌面成为可能的开发者。Bazaar 设有一个\"精选\"标签,可" "由发行商配置,以提供更本地化的体验。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:701 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "展示 Flathub 应用程序的主页" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Nucleus 应用页" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "搜索页" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "分类页" #: src/bz-addons-dialog.blp:16 src/bz-full-view.blp:695 #: src/bz-installed-tile.blp:101 msgid "Manage Add-ons" msgstr "管理附加组件" #: src/bz-addons-dialog.c:94 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:119 src/bz-transaction-dialog.c:227 msgid "Remove" msgstr "卸载" #: src/bz-addons-dialog.c:99 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:198 msgid "Install" msgstr "安装" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:331 src/bz-full-view.c:338 msgid "Age Rating" msgstr "年龄分级" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "卡通暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "无卡通暴力相关信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "幻想暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "无关于幻想暴力的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "写实暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "无关于写实暴力的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "暴力描绘流血场面" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "无关于血腥的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "性暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "无关于性暴力的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "酒精" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "无关于酒精的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "毒品" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "无使用非法药物的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "烟草" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "无关于烟草产品的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "裸露" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "无任何种类的裸体信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "性主题" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "无关于提及和描绘性的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "脏话" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "不含任何种类的脏话信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "不适当幽默" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "无关于不当幽默的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "歧视" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "无关于歧视语言的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "广告" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "无任任何广告信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "赌博" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "无任何赌博内容" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "č´­äš°" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "无关于花钱能力的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "用户间交流" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "无关于与其他用户文字交流方式的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "用户见语音交流" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "无关于与其他用户语音交流方式的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "联系详情" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "未提供有关分享社交媒体用户名或电子邮件地址的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "识别信息" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "未提供与第三方共享用户信息的相关信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "位置共享" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "未提供与其他用户共享物理位置的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "卖淫" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "未提及有关卖淫的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "通奸" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "没有关于通奸相关信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "性化角色" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "未提供有关性化角色的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "亵渎" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "没有关于亵渎行为的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "人类遗骸" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "没有关于可见的人类遗骸的信息" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "奴隶制" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "不含提及奴隶制的信息" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "不包括对毒品的提及" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "不包括咒骂、脏话及其他类型的强烈言辞" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "不包括广告或货币交易" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "不包含性内容或裸露镜头" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "不包含不受控制的聊天功能" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "不包含暴力" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "药品" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "粗俗语言" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "金钱" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "礞交" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "暴力" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:321 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "所有" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s 的年龄分级未知" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s 适合所有人" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s 适合幼儿使用" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s 适合儿童" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s 适合青少年" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s 适合成人用户" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s 适合 %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:16 #: src/bz-user-data-page.blp:15 src/bz-window.blp:292 msgid "Main Menu" msgstr "主菜单" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 src/bz-window.blp:384 msgid "_Donate to Bazaar ❤️" msgstr "_向 Bazaar 捐助 ❤️" #: src/bz-all-apps-page.blp:25 src/bz-apps-page.blp:25 #: src/bz-user-data-page.blp:26 src/bz-window.blp:391 msgid "_Preferences" msgstr "_首选项" #: src/bz-all-apps-page.blp:30 src/bz-apps-page.blp:30 #: src/bz-user-data-page.blp:31 src/bz-window.blp:396 msgid "_Login with Flathub" msgstr "_用 Flathub 登录" #: src/bz-all-apps-page.blp:36 src/bz-apps-page.blp:36 #: src/bz-user-data-page.blp:37 src/bz-window.blp:402 msgid "_Manage Leftover User Data" msgstr "_管理遗留用户数据" #: src/bz-all-apps-page.blp:41 src/bz-apps-page.blp:41 #: src/bz-user-data-page.blp:42 src/bz-window.blp:407 msgid "_Synchronize Remotes" msgstr "_同步远程" #: src/bz-all-apps-page.blp:46 src/bz-apps-page.blp:46 #: src/bz-user-data-page.blp:47 src/bz-window.blp:412 msgid "_Keyboard Shortcuts" msgstr "_键盘快捷键" #: src/bz-all-apps-page.blp:51 src/bz-apps-page.blp:51 #: src/bz-user-data-page.blp:52 src/bz-window.blp:417 msgid "_About Bazaar" msgstr "_关于 Bazaar" #: src/bz-all-apps-page.blp:58 src/bz-apps-page.blp:58 #: src/bz-user-data-page.blp:59 src/bz-window.blp:424 msgid "_Quit Bazaar" msgstr "_退出 Bazaar" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "系统文件夹 %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "用户主文件夹 %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "主机系统文件夹" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "主机系统配置来自 /etc" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "桌面子文件夹 %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "桌面文件夹" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "文档子文件夹 %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "文档文件夹" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "音乐子文件夹 %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "音乐文件夹" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "图片子文件夹 %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "图片文件夹" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "公共共享子文件夹 %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "公共共享文件夹" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "视频子文件夹 %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "视频文件夹" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "模板子文件夹 %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "模板文件夹" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "用户缓存子文件夹 %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "用户缓存文件夹" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "用户配置子文件夹 %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "用户配置文件夹" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "用户数据子文件夹 %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "用户数据文件夹" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "用户运行时子文件夹 %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "用户运行时文件夹" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "寚 %s 的文件系统访问" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "未知文件系统路径" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "下载大小" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "从互联网下载的大小" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "已安装占用" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "硬盘占用" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "用户数据大小" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "缓存、设置和其他应用数据" #. Translators: As in 'The app is installed'. #: src/bz-app-tile.blp:86 src/bz-full-view.c:280 src/bz-releases-list.c:178 msgid "Installed" msgstr "已安装" #: src/bz-apps-page.blp:142 msgid "Show All" msgstr "展示所有" #: src/bz-apps-page.c:243 #, c-format msgid "All \"%s\"" msgstr "所有 \"%s\"" #: src/bz-apps-page.c:530 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d 个应用" #: src/bz-application.c:672 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:673 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:704 msgid "translator-credits" msgstr "Shinsei , 2025" #: src/bz-application.c:715 msgid "Special Thanks" msgstr "特别感谢" #: src/bz-application.c:773 msgid "Logged Out Successfully!" msgstr "登出成功!" #: src/bz-application.c:896 msgid "Performing setup..." msgstr "正在执行设置..." #: src/bz-application.c:979 src/bz-application.c:988 msgid "Set Up Flathub" msgstr "注册 Flathub" #: src/bz-application.c:982 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "此系统未设置 Flathub。如果 Flathub 不可用,您将无法在 Bazaar 中浏览和安装应用" "程序。\n" "\n" "您仍可使用 Bazaar 浏览和卸载已安装的应用程序。" #: src/bz-application.c:987 msgid "Later" msgstr "稍后" #: src/bz-application.c:1397 src/bz-application.c:3087 msgid "Synchronizing..." msgstr "同步中……" #: src/bz-application.c:1544 src/bz-application.c:3083 #, c-format msgid "Receiving %d entries..." msgstr "正在接收 %d 个条目..." #: src/bz-application.c:1549 msgid "Checking for updates" msgstr "正在检查更新" #: src/bz-application.c:3089 msgid "Indexing Data..." msgstr "正在索引数据……" #: src/bz-appstream-parser.c:265 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub 页面" #: src/bz-appstream-parser.c:286 msgctxt "Project URL Type" msgid "Project Website" msgstr "项目网站" #: src/bz-appstream-parser.c:290 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "问题追踪器" #: src/bz-appstream-parser.c:294 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-appstream-parser.c:298 msgctxt "Project URL Type" msgid "Help" msgstr "帮助" #: src/bz-appstream-parser.c:302 msgctxt "Project URL Type" msgid "Donate" msgstr "捐助" #: src/bz-appstream-parser.c:308 msgctxt "Project URL Type" msgid "Translate" msgstr "翻译" #: src/bz-appstream-parser.c:312 msgctxt "Project URL Type" msgid "Contact" msgstr "联系" #: src/bz-appstream-parser.c:316 msgctxt "Project URL Type" msgid "Source Code" msgstr "源䝣码" #: src/bz-appstream-parser.c:322 msgctxt "Project URL Type" msgid "Contribute" msgstr "贡献" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:68 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:48 #: src/bz-library-page.blp:59 src/bz-user-data-page.blp:86 msgid "Empty" msgstr "犺" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "无精选应用程序" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "该系统未提供策展信息。您仍可在 Flathub 上浏览应用程序。" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "浏览 Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "猝线" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "浏览器" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "无法获取开发者信息" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "诼 %s 应用 ID 的所有权尚未验证,可能是一个社区包。" #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "诼 %s 应用 ID 的所有权已由 Flathub 团队手动验证。" #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "%1$s 应用 ID 的所有权已验证为是 %3$s 上的 %2$s。" #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "%1$s 应用 ID 的所有权已通过 %2$s 验证。" #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "诼 %s 应用 ID 的所有权已通过验证。" #: src/bz-donations-dialog.blp:58 #, fuzzy msgid "This Bazaar Release Was Made Possible By Users Like You!" msgstr "正是有了像您这样的用户,Bazaar 才能顺利发行!" #: src/bz-donations-dialog.blp:66 #, fuzzy msgid "" "I love making Bazaar, but I cannot do it alone. If you would like to help " "support further development, please consider donating to the project at my " "ko-fi:" msgstr "" "我热爱开发 Bazaar,但我一个人的力量有限。如果您愿意支持后续的开发工作,请考虑" "在 ko-fi 捐助我:" #: src/bz-donations-dialog.blp:76 #, fuzzy msgid "Donate to Bazaar" msgstr "_向 Bazaar 捐助 ❤️" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "选择和安装" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "您已安装此应用的多个版本。您希望用哪一个继续?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:197 #: src/bz-transaction-dialog.c:226 src/bz-transaction-dialog.c:271 #: src/bz-transaction-dialog.c:562 msgid "Cancel" msgstr "取消" #: src/bz-entry-selection-row.blp:17 msgid "For this user only" msgstr "仅适用于当前用户" #: src/bz-entry-selection-row.c:112 msgid "this user" msgstr "当前用户" #: src/bz-entry-selection-row.c:112 msgid "all users" msgstr "所有用户" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "一个错误发生了" #: src/bz-error.c:89 msgid "Close" msgstr "关闭" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "复制并关闭" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "登录 Flathub 以管理收藏项目" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "登录" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "收藏数" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "卸载" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:77 msgid "Support this application" msgstr "支持此应用程序" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "从收藏中移除" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:78 #: src/bz-window.blp:442 msgid "Favorites" msgstr "收藏" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:31 src/bz-window.blp:307 #, fuzzy msgid "Open App Library" msgstr "打开应用库" #: src/bz-favorites-page.blp:39 src/bz-section-view.blp:144 #: src/bz-transaction-dialog.c:563 msgid "Install All" msgstr "安装全部" #: src/bz-favorites-page.blp:56 src/bz-user-data-page.blp:75 msgid "Loading" msgstr "加载中" #: src/bz-favorites-page.blp:71 msgid "No Favorites" msgstr "无收藏" #: src/bz-favorites-page.blp:72 msgid "Applications you mark as favorite will appear here" msgstr "您标记为收藏的应用程序将在此处显示" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "上一页" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "下一页" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "每日应用" #: src/bz-flathub-category.c:89 msgid "Editing" msgstr "编辑" #: src/bz-flathub-category.c:90 msgid "Midi" msgstr "MIDI" #: src/bz-flathub-category.c:91 msgid "Mixer" msgstr "调音" #: src/bz-flathub-category.c:92 msgid "Music" msgstr "音乐" #: src/bz-flathub-category.c:93 msgid "Player" msgstr "播放器" #: src/bz-flathub-category.c:94 msgid "Recorder" msgstr "录音" #: src/bz-flathub-category.c:95 msgid "Sequencer" msgstr "科学" #: src/bz-flathub-category.c:96 msgid "Tuner" msgstr "调谐器" #: src/bz-flathub-category.c:97 msgid "TV" msgstr "电视" #: src/bz-flathub-category.c:102 msgid "Emulation" msgstr "模拟器" #: src/bz-flathub-category.c:103 msgid "Action" msgstr "动作" #: src/bz-flathub-category.c:104 msgid "Adventure" msgstr "冒险" # 不用“街机“遵从 https://flathub.org/zh-Hans/apps/category/game/subcategories/ArcadeGame 的翻译 #: src/bz-flathub-category.c:105 msgid "Arcade" msgstr "游䚐中心" #: src/bz-flathub-category.c:106 msgid "Blocks" msgstr "方块" #: src/bz-flathub-category.c:107 msgid "Board" msgstr "图板" #: src/bz-flathub-category.c:108 msgid "Card" msgstr "卡片" #: src/bz-flathub-category.c:109 msgid "Kids" msgstr "儿童" #: src/bz-flathub-category.c:110 msgid "Logic" msgstr "逻辑" #: src/bz-flathub-category.c:111 msgid "Role Playing" msgstr "角色扮演" #: src/bz-flathub-category.c:112 msgid "Shooter" msgstr "射手" #: src/bz-flathub-category.c:113 msgid "Simulation" msgstr "模拟" #: src/bz-flathub-category.c:114 msgid "Sports" msgstr "体育" #: src/bz-flathub-category.c:115 msgid "Strategy" msgstr "战略" #: src/bz-flathub-category.c:120 msgid "Audio & Video" msgstr "音频与视频" #: src/bz-flathub-category.c:120 msgid "Media" msgstr "媒体" #: src/bz-flathub-category.c:120 msgid "More Audio & Video" msgstr "更多音频与视频" #: src/bz-flathub-category.c:121 msgid "Developer Tools" msgstr "开发者工具" #: src/bz-flathub-category.c:121 msgid "Develop" msgstr "开发" #: src/bz-flathub-category.c:121 msgid "More Developer Tools" msgstr "更多开发者工具" #: src/bz-flathub-category.c:122 msgid "Education" msgstr "教育" #: src/bz-flathub-category.c:122 msgid "Learn" msgstr "ĺ­Śäš " #: src/bz-flathub-category.c:122 msgid "More Education" msgstr "更多教育" #: src/bz-flathub-category.c:123 msgid "Gaming" msgstr "游戏" #: src/bz-flathub-category.c:123 msgid "Play" msgstr "游玩" #: src/bz-flathub-category.c:123 msgid "More Gaming" msgstr "更多游戏" #: src/bz-flathub-category.c:124 msgid "Graphics & Photography" msgstr "图形与摄影" #: src/bz-flathub-category.c:124 msgid "Create" msgstr "创造" #: src/bz-flathub-category.c:124 msgid "More Graphics & Photography" msgstr "更多图形与摄影" #: src/bz-flathub-category.c:125 msgid "Networking" msgstr "网络" #: src/bz-flathub-category.c:125 msgid "Internet" msgstr "互联网" #: src/bz-flathub-category.c:125 msgid "More Networking" msgstr "更多网络应用" #: src/bz-flathub-category.c:126 msgid "Productivity" msgstr "生产力" #: src/bz-flathub-category.c:126 msgid "Work" msgstr "工作" #: src/bz-flathub-category.c:126 msgid "More Productivity" msgstr "更多生产力" #: src/bz-flathub-category.c:127 msgid "Science" msgstr "科学" #: src/bz-flathub-category.c:127 msgid "More Science" msgstr "更多科学" #: src/bz-flathub-category.c:128 msgid "System" msgstr "系统" #: src/bz-flathub-category.c:128 msgid "More System" msgstr "更多系统" #: src/bz-flathub-category.c:129 msgid "Utilities" msgstr "实用工具" #: src/bz-flathub-category.c:129 msgid "Tools" msgstr "工具" #: src/bz-flathub-category.c:129 msgid "More Utilities" msgstr "更多实用工具" #: src/bz-flathub-category.c:130 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "飙升" #: src/bz-flathub-category.c:130 msgid "More Trending" msgstr "更多飙升应用" #: src/bz-flathub-category.c:131 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "人气" #: src/bz-flathub-category.c:131 msgid "More Popular" msgstr "更多人气应用" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "最近添加" #: src/bz-flathub-category.c:132 src/bz-flathub-page.blp:131 msgid "New" msgstr "新应用" #: src/bz-flathub-category.c:132 msgid "More New" msgstr "更多新应用" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "最近更新" #: src/bz-flathub-category.c:133 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "最近更新" #: src/bz-flathub-category.c:133 msgid "More Updated" msgstr "更多最近更新应用" #: src/bz-flathub-category.c:134 msgid "Mobile" msgstr "移动应用" #: src/bz-flathub-category.c:134 msgid "More Mobile" msgstr "更多移动应用" #: src/bz-flathub-category.c:135 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:135 msgid "More Adwaita" msgstr "更多 Adwaita 应用" #: src/bz-flathub-category.c:136 msgid "KDE Apps" msgstr "KDE 应用" #: src/bz-flathub-category.c:136 msgid "More KDE Apps" msgstr "更多 KDE 应用" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "Flathub 未添加" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "您的 Flatpak 安装中未找到 Flathub 远程仓库" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub 返回错误" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "重试 Flathub 连接" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub 不可用" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "我们无法连接到 Flathub。您仍然可以管理和搜索应用程序。" #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "搜索应用程序" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "随时随地" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "适用于您的 Linux 手机和平板电脑的应用" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "更多移动应用" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "我们 ♥ 游戏" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "运行您喜爱的游戏和应用" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "更多游戏" #: src/bz-full-view.blp:52 src/bz-library-page.blp:70 #: src/bz-library-page.blp:74 msgid "No Results" msgstr "无结果" #: src/bz-full-view.blp:53 msgid "Try a different search query" msgstr "尝试不同的搜索关键字" #: src/bz-full-view.blp:59 msgid "Content" msgstr "内容" #: src/bz-full-view.blp:117 msgid "Installing .flatpak bundles is not yet supported" msgstr "安装 .flatpak 包暂不支持" #: src/bz-full-view.blp:210 msgid "Support" msgstr "支持" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "打开" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "下载并安装应用程序" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "卸载此应用程序" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "安装其他版本" #: src/bz-full-view.blp:430 msgid "Downloads/Month" msgstr "次下载/㜈" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "停止接收核心更新" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "此应用使用的运行时环境已不再接收更新或安全修复,继续使用可能存在安全隐患" #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "垃圾数据" #: src/bz-full-view.blp:771 msgid "Tags:" msgstr "标签:" #: src/bz-full-view.c:220 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:227 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:234 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:244 #, c-format msgid "%d downloads in the last 30 days" msgstr "过去 30 天内下载 %d 揥" #: src/bz-full-view.c:256 src/bz-full-view.c:590 src/bz-full-view.c:607 msgid "N/A" msgstr "N/A" #. Translators: . #: src/bz-full-view.c:280 msgid "Download" msgstr "下载" #: src/bz-full-view.c:300 msgid "Size information unavailable" msgstr "大小信息不可用" #: src/bz-full-view.c:303 #, c-format msgid "Download size of %s" msgstr "%s 的下载大小" #: src/bz-full-view.c:336 msgid "All Ages" msgstr "全年龄" #: src/bz-full-view.c:348 msgid "Age rating information unavailable" msgstr "年龄分级信息不可用" #: src/bz-full-view.c:353 msgid "Suitable for all ages" msgstr "适合全年龄段" #: src/bz-full-view.c:355 #, c-format msgid "Suitable for ages %d and up" msgstr "适合年龄为 %d 岁及以上" #: src/bz-full-view.c:388 src/bz-full-view.c:393 src/bz-full-view.c:421 #: src/bz-full-view.c:432 msgid "Unknown" msgstr "未知" #: src/bz-full-view.c:398 #, c-format msgid "Free software licensed under %s" msgstr "根据 %s 许可证授权的自由软件" #: src/bz-full-view.c:403 msgid "Free software" msgstr "自由软件" #: src/bz-full-view.c:406 msgid "Proprietary Software" msgstr "专有软件" #: src/bz-full-view.c:409 #, c-format msgid "Special License: %s" msgstr "特殊许可证: %s" #: src/bz-full-view.c:426 msgid "Free" msgstr "自由" #: src/bz-full-view.c:429 src/bz-license-dialog.c:132 msgid "Proprietary" msgstr "专有" #: src/bz-full-view.c:434 src/bz-license-dialog.c:134 msgid "Special License" msgstr "特殊许可" #: src/bz-full-view.c:454 msgid "Adaptive" msgstr "自适应" #: src/bz-full-view.c:454 msgid "Desktop Only" msgstr "仅桌面端" #: src/bz-full-view.c:460 msgid "Works on desktop, tablets, and phones" msgstr "适用于台式机、平板电脑和手机" #: src/bz-full-view.c:461 msgid "May not work on mobile devices" msgstr "可能无法在移动设备上使用" #: src/bz-full-view.c:472 msgid "No URL" msgstr "无链接" #: src/bz-full-view.c:490 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "该应用程序具有 FLOSS 许可证,这意味着可以审核源代码的安全性。" #: src/bz-full-view.c:491 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "" "该应用程序具有专有许可证,这意味着源代码是私人开发的,不能由独立的第三方审" "核。" #: src/bz-full-view.c:498 msgid "More Apps" msgstr "更多应用" #: src/bz-full-view.c:499 #, c-format msgid "More Apps by %s" msgstr "来自 %s 的更多应用" #: src/bz-full-view.c:506 msgid "Other Apps by this Developer" msgstr "该开发者的其他应用" #: src/bz-full-view.c:508 src/bz-full-view.c:708 #, c-format msgid "Other Apps by %s" msgstr "来自 %s 的其他应用" #: src/bz-full-view.c:517 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s 未安装,但仍存在 %s 的数据。" #: src/bz-full-view.c:597 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "安全" #: src/bz-full-view.c:599 src/bz-full-view.c:601 msgid "Low Risk" msgstr "低风险" #: src/bz-full-view.c:603 msgid "Medium Risk" msgstr "中等风险" #: src/bz-full-view.c:605 msgid "High Risk" msgstr "高风险" #: src/bz-full-view.c:710 msgid "Other Apps" msgstr "其他应用" #: src/bz-full-view.c:712 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d 个应用" #: src/bz-full-view.c:1051 msgid "Show Less" msgstr "显示更少" #: src/bz-full-view.c:1051 msgid "Show More" msgstr "显示更多" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "硬件支持情况" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "键盘支持情况" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "需要键盘" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "推荐键盘" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "支持键盘" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "键盘支持情况未知" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "鼠标支持情况" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "需要鼠标或指针设备" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "推荐鼠标或指针设备" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "支持鼠标或指针设备" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "鼠标或指针设备支持情况未知" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "触控支持情况" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "需要触控" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "推荐触控" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "支持触控" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "触控支持情况未知" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "移动设备支持情况" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "可运行于移动设备" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "可能不支持移动设备" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "桌面端支持情况" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "大屏上运行良好" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s 在特定硬件上运行最佳" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s 在大多数设备正常工作" #: src/bz-installed-tile.blp:63 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "停止接收更新" #: src/bz-library-page.blp:29 msgid "Search installed apps" msgstr "搜索已安装的应用程序" #: src/bz-library-page.blp:63 msgid "No Apps Found" msgstr "未找到应用程序" #. Translators: . #: src/bz-library-page.blp:82 src/bz-window.blp:179 #, fuzzy msgid "Library" msgstr "库" #: src/bz-library-page.blp:110 msgid "Pending Updates" msgstr "等待更新" #: src/bz-library-page.blp:137 msgid "Downloads" msgstr "下载" #: src/bz-library-page.blp:180 msgid "Recently Uninstalled" msgstr "最近卸载" #: src/bz-library-page.blp:231 msgid "Clear Finished Tasks" msgstr "清除所有已完成的事务" #: src/bz-library-page.blp:242 msgid "Installed Apps" msgstr "已安装" #: src/bz-library-page.c:152 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "在已安装应用列表中未找到与 “%s” 匹配的项目" #: src/bz-library-page.c:165 src/bz-updates-card.c:257 #, c-format msgid "%u Available Update" msgid_plural "%u Available Updates" msgstr[0] "%u 个可用更新" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "参与进来" #: src/bz-license-dialog.c:126 msgid "Unknown License" msgstr "未知许可证" #: src/bz-license-dialog.c:129 msgid "Community Built" msgstr "社区共建" #: src/bz-license-dialog.c:202 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "此应用由一个国际社区以开源方式开发而成。\n" "\n" "您可以参与进来,帮助它变得更好。" #: src/bz-license-dialog.c:205 msgid "The license of this app is not known" msgstr "此应用的许可证未知" #: src/bz-license-dialog.c:211 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "此应用由国际社区开放开发,并根据 %s 许可证发布。\n" "\n" "您可以参与进来,帮助它变得更好。" #: src/bz-license-dialog.c:219 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "此应用未采用开放开发,因此只有开发者知道其运作机制。它可能存在难以察觉的安全" "漏洞,且可能在缺乏监管的情况下进行更改。\n" "\n" "您可能无法为本应用做出贡献。" #: src/bz-license-dialog.c:225 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "本应用基于特殊许可证 %s 开发。\n" "\n" "您可能无法为本应用做出贡献。" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "连接到 Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "发生错误" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "将您的 Flathub 账户连接到 Bazaar,以便管理您收藏的应用程序。" #: src/bz-login-page.blp:108 msgid "Finish" msgstr "完成" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "你好,%s" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "偏好设置" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "正在使用计费网络 - 自动储存数据同步已暂停" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:334 msgid "Sync Manually" msgstr "手动同步" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "内容筛选" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "仅自由软件" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "浏览和搜索时隐藏专有软件" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "仅包含 Flathub 结果" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "限制搜索和浏览的应用仅可从 Flathub 获取" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "仅显示已验证结果" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "隐藏未在 Flathub 上验证的结果" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "隐藏终止支持的应用" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "隐藏开发者不再支持的应用" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:197 msgid "Search" msgstr "搜索" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "延迟搜索结果" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "通过防抖搜索词提升结果性能" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "进度条" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "为进度条选择主题!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "竖条纹" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from left to right" msgstr "从左至右显示旗帜颜色" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "强调色" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "骄傲色" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "女同性恋骄傲色彩" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "男同性恋骄傲色彩" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "跨性别骄傲色" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "非二元性别骄傲色彩" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "双性恋骄傲色彩" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "无性恋骄傲色" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "泛性恋骄傲色" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "无浪漫倾向骄傲色" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "性别流动骄傲色" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "多性恋骄傲色" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "全性恋骄傲色彩" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "无浪漫无性恋者骄傲色" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "无性别骄傲色" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "性别酷儿骄傲色" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "双性恋骄傲色" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "半性别骄傲色" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "双浪漫骄傲色" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "残疾人骄傲色" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "伪娘骄傲色" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "中性骄傲色" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:28 #: src/bz-updates-card.blp:150 msgid "Version History" msgstr "版本历史" #: src/bz-releases-list.c:168 #, c-format msgid "Version %s" msgstr "版本 %s" #: src/bz-releases-list.c:220 msgid "No details for this release" msgstr "未提供变更日志" #: src/bz-releases-list.c:232 msgid "Get More Information" msgstr "获得更多信息" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "获取" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "未知权限" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "此应用缺少必要的权限。" #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "没有权限" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "应用已完全沙盒化" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "网络访问" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "可访问网络" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "无网络访问" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "不能访问互联网" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "用户设备访问" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "可以访问网络摄像头或游戏控制器等硬件设备" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "无用户设备访问" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "应用不能访问网络摄像头或游戏控制器等任何用户设备" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "输入设备访问" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "可以访问输入设备" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "麦克风访问和音频播放" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "无需请求权限即可使用麦克风收听和播放音频" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "系统设备访问" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "可以访问需要提升权限的系统设备" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "屏幕内容访问" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "可以访问屏幕或其他窗口的内容" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "过时窗口系统" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "始终使用过时的窗口系统(X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "任意权限" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "可以获取任意权限" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "用户设置" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "可以访问和更改用户设置" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "完全的文件系统读写权限" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "可以读取和写入文件系统上的所有数据" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "主文件夹读写权限" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "可以读取和写入您主目录中的所有数据" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "完整文件系统读取访问" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "可以读取文件系统上的所有数据" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "主文件夹读取权限" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "可以读取您主目录中的所有数据" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "下载文件夹读写权限" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "可以读写下载文件夹中的所有数据" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "下载文件夹读取权限" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "可以读取您下载目录中的所有数据" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "可以读写目录中的所有数据" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "可以读取目录中的所有数据" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "无文件系统访问权限" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "完全无法访问文件系统" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "使用系统服务" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "可从非门户系统服务请求数据" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "使用会话服务" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "可从非门户会话服务请求数据" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "无服务访问" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "完全无法访问非门户会话或系统服务" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "软件开发者已验证" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "软件开发者的身份已通过验证,使应用更安全" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "专有代码" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "源代码未公开,因此无法进行独立审计,可能存在安全隐患" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "可审计代码" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "源代码公开且可独立审计,这使得此应用更可能安全可靠" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "使用 %s 系统服务" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "使用 %s 会话服务" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "使用 %s 服务" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "可以看到非门户服务" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "可与非门户服务进行对话" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "可以拥有非门户服务" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "全局菜单集成" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "可在全局菜单栏中显示其菜单" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "KDE 设置集成" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "可检测 KDE 桌面设置何时发生变化" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "KDE 全局设置" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "可读取 KDE 桌面偏好设置,如字体和颜色" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "秘密存储服务" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "可使用系统密钥管理器存储和检索自身密码" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "桌面通知服务" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "可以发送桌面通知" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "系统托盘集成" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "可在系统托盘中显示图标" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "KDE Connect 集成" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "可与通过 KDE Connect 配对的设备进行交互" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "安全性" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "详细信息" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "许可证" #: src/bz-safety-dialog.blp:63 msgid "App ID" msgstr "App ID" #: src/bz-safety-dialog.blp:73 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:101 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "此应用使用了过时的软件平台(SDK)版本,可能包含无法修复的错误或安全漏洞。" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s 是安全的" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s 没有不安全权限" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s 很可能安全" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s 可能不安全" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s 是不安全的" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "屏幕截图" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "上一个截图" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "下一个截图" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "复制图片" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "重置视图" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "缩小" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "放大" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "截图轮播" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "打开截图查看器" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "搜索应用、游戏、软件" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "分类不可用" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "使用上方搜索栏搜索应用。" #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "未找到应用" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "在 Flathub 中未找到 “%s” 的结果" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "已复制!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "复制链接" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "打开链接" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "时间线" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "安装:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "世界" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "%.2fM 总安装量" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "%.2fK 总安装量" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "%'d 总安装量" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "无结果" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "标记为 “%s” 的应用" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "搜索失败" #: src/bz-transaction-dialog.c:151 msgid "Keep Data" msgstr "保留数据" #: src/bz-transaction-dialog.c:152 msgid "Allow restoring settings and content" msgstr "允许恢复设置和内容" #: src/bz-transaction-dialog.c:161 msgid "Delete Data" msgstr "删除数据" #: src/bz-transaction-dialog.c:162 msgid "Permanently remove app data to save space" msgstr "永久删除应用数据以节省空间" #: src/bz-transaction-dialog.c:187 #, c-format msgid "Install %s?" msgstr "安装 %s ?" #: src/bz-transaction-dialog.c:192 msgid "" "Select which version to install. May install additional shared components" msgstr "选择你要安装的版本。可能还要安装共享组件" #: src/bz-transaction-dialog.c:194 msgid "May install additional shared components" msgstr "可能还要安装额外的共享组件" #: src/bz-transaction-dialog.c:215 #, c-format msgid "Remove %s?" msgstr "卸载 %s ?" #: src/bz-transaction-dialog.c:218 msgid "Select which version to remove." msgstr "选择你要卸载的版本" #: src/bz-transaction-dialog.c:220 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "卸载后将无法使用 %s" #: src/bz-transaction-dialog.c:243 #, c-format msgid "“%s” is High Risk" msgstr "“%s” 是高风险的" #: src/bz-transaction-dialog.c:247 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "此应用拥有对您系统的完全访问权限,包括您的所有文件、浏览历史、已保存密码等。它还能访问互联网,这意味着它可能将您的数据发送给第三方。\n" "\n" "由于该应用是专有的,其如何利用权限也无法审查。\t" #: src/bz-transaction-dialog.c:256 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "此应用使用传统的 X11 窗口系统,这使其能够记录所有按键、截取屏幕截图并监控" "其他应用程序。同时,该应用具备网络访问权限,这意味着它可能将您的数据发送" "给外部。\n" "\n" "由于该应用是专有的,其如何利用权限也无法审查。" #: src/bz-transaction-dialog.c:272 msgid "Install Anyway" msgstr "坚持安装" #: src/bz-transaction-dialog.c:533 msgid "All apps are already installed" msgstr "所有应用都已经被安装" #: src/bz-transaction-dialog.c:535 msgid "OK" msgstr "好的" #: src/bz-transaction-dialog.c:551 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "安装 %u 应用?" #: src/bz-transaction-dialog.c:559 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "下列组件会被安装。可能还要安装共享组件" #: src/bz-transaction-dialog.c:560 #, c-format msgid "%d addons will be installed." msgstr "%d 附加组件将被安装" #: src/bz-transaction-dialog.c:561 msgid "Additionally, addons will be installed." msgstr "此外,附加组件将被安装" #: src/bz-transaction-manager.c:1248 #, c-format msgid "Finished in %.02f seconds" msgstr "在 %.02f 秒内完成" #: src/bz-transaction-tile.blp:125 msgid "App Add-on" msgstr "应用附加组件" #: src/bz-transaction-tile.blp:154 msgid "Runtime" msgstr "运行时" #: src/bz-transaction-tile.blp:178 msgid "In Queue" msgstr "队列中" #: src/bz-transaction-tile.blp:202 msgid "Done" msgstr "已完成" #: src/bz-transaction-tile.blp:243 msgid "Open App" msgstr "打开" #: src/bz-transaction-tile.c:110 #, c-format msgid "%s Freed" msgstr "%s 已释放" #: src/bz-transaction.c:342 msgid "Pending" msgstr "等待中" #: src/bz-updates-card.blp:36 msgid "Update All" msgstr "更新全部" #: src/bz-updates-card.blp:161 src/bz-updates-card.blp:186 msgid "Update" msgstr "更新" #: src/bz-updates-card.c:293 #, c-format msgid "%u Runtime Update" msgid_plural "%u Runtime Updates" msgstr[0] "%u 个运行时环境更新" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "管理遗留用户数据" #: src/bz-user-data-page.blp:89 msgid "No User Data found" msgstr "未找到用户数据" #: src/bz-user-data-page.blp:94 msgid "User Data" msgstr "用户数据" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "已删除 %s 的用户数据" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "清除用户数据" #: src/bz-window.blp:135 msgid "Refreshing Store Content" msgstr "正在刷新商店内容" #: src/bz-window.blp:153 msgid "Curated" msgstr "精选" #: src/bz-window.blp:166 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:273 msgid "No background tasks!" msgstr "无后台任务!" #: src/bz-window.blp:325 msgid "You are running a new version of Bazaar!" msgstr "你正在运行新版本的 Bazaar" #: src/bz-window.blp:326 msgid "See What's New" msgstr "看看更新了啥" #: src/bz-window.blp:333 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "您已连接网络,但正在查看 Flathub 的缓存版本" #: src/bz-window.blp:449 msgid "Log Out" msgstr "登出" #: src/bz-window.c:683 msgid "You can't remove Bazaar from Bazaar!" msgstr "你无法用 Bazaar 卸载 Bazaar" #: src/bz-window.c:891 src/bz-window.c:925 msgid "Can't do that right now!" msgstr "现在还不能这么做!" #: src/bz-world-map.c:587 msgctxt "As in, \"100 Downloads\"" msgid "Downloads" msgstr "次下载" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "一般" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "打开搜索对话框" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "打开偏好设置" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "从远程端同步" #: src/gtk/shortcuts-dialog.blp:24 #, fuzzy msgctxt "shortcut window" msgid "Open Library" msgstr "打开链接" #: src/gtk/shortcuts-dialog.blp:30 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "展示快捷键" #: src/gtk/shortcuts-dialog.blp:35 msgctxt "shortcut window" msgid "Quit" msgstr "退出" #~ msgid "_Refresh Content" #~ msgstr "_刷新内容" msgid "Toggle transaction sidebar" msgstr "切换事务侧面板" msgid "Install Size" msgstr "安装大小" msgid "Ongoing" msgstr "进行中" msgid "Finished" msgstr "已完成" #, c-format #~ msgid "Transferred %s so far" #~ msgstr "目前已传输 %s" msgid "Tasks" msgstr "任务" msgid "Stop Active Tasks" msgstr "停止当前任务" msgid "Clear History" msgstr "清除历史" msgid "No Tasks Yet" msgstr "当前无任务" #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "%d 个更新" msgid "Updates Are Available" msgstr "有可用更新" msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "以下应用可进行更新。您想要安装它们吗?" #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "%d 个运行时和/或插件可进行更新。您要安装它们吗?" #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "此外,%d 个运行时和/或插件也将被更新" msgid "Update Now" msgstr "立即更新" #~ msgid "" #~ "The ability to inspect and install local .flatpak bundle files is coming " #~ "soon! In the meantime, try running\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "on the command line." #~ msgstr "" #~ "检查和安装本地 .flatpak 包文件的功能即将推出!在此期间,请尝试在命令行运" #~ "行\n" #~ "\n" #~ "flatpak install --bundle your-bundle.flatpak\n" #~ "\n" #~ "以上命令。" msgid "Resume Current Tasks" msgstr "恢复当前任务" msgid "Pause Current Tasks" msgstr "暂停当前任务" msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "切换事务管理器" #~ msgid "Show Animated Background" #~ msgstr "展示动画背景" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "是否在首页展示动画图标背景" #~ msgid "Keep the summary shorter, between 10 and 35 characters" #~ msgstr "保持摘要简短,在 10 至 35 字之间" #~ msgid "Main Bazaar window showing Blender" #~ msgstr "Bazaar 主窗口正在展示 Blender" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "ć­¤ Flatpak 已由软件原开发者认证。" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore" #~ msgstr "Jill Fiore" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "Bazaar 未被提供精选内容配置。联系您的操作系统的支持频道寻求协助。" #~ msgid "Apps Of The Week" #~ msgstr "本周热门应用程序" #~ msgid "Run this application" #~ msgstr "运行此应用程序" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "过去 30 天的下载次数。点击查看此应用程序的下载统计信息。" #~ msgid "Remote repo name" #~ msgstr "远程仓库名" #, c-format #~ msgid "Released %x" #~ msgstr "发布于 %x" #~ msgid "No Flatpaks Installed" #~ msgstr "没有已安装的 Flatpak" #~ msgid "How the application looks" #~ msgstr "这个应用程序看起来怎么样" #~ msgid "Appearance" #~ msgstr "外观" #~ msgid "Show animated background" #~ msgstr "展示动画背景" #~ msgid "Type to filter" #~ msgstr "输入以筛选" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "排除有专有许可证的结果" #~ msgid "Advanced" #~ msgstr "鍘级" #~ msgid "Match using regular expressions" #~ msgstr "使用正则表达式匹配" #~ msgid "Hide filtering and sorting behind a crossfade effect" #~ msgstr "隐藏交叉淡入淡出效果背后的过滤和排序" #~ msgid "Debounce input to prevent instant replies" #~ msgstr "消除输入抖动以防止立即回复" #~ msgid "Share" #~ msgstr "分享" #~ msgid "Open this link externally" #~ msgstr "在外部打开链接" #~ msgid "Downloads Over Time" #~ msgstr "下载趋势" #~ msgid "Minimize Lower Bound" #~ msgstr "调低下限" #~ msgid "Maximize Upper Bound" #~ msgstr "调低上限" msgid "Installing" msgstr "正在安装" msgid "Removing" msgstr "正在卸载" #~ msgid "Transactions Will Appear Here" #~ msgstr "事务会在此显示" #~ msgid "Halt the execution of transactions" #~ msgstr "停止执行事务" #~ msgid "Browse" #~ msgstr "浏览" #~ msgid "App View" #~ msgstr "App View" #~ msgid "Go Back" #~ msgstr "返回" #~ msgid "Refresh" #~ msgstr "刷新" #~ msgid "View curated applications" #~ msgstr "查看精选的应用程序" #~ msgid "View the latest on Flathub" #~ msgstr "在 Flathub 查看最新的" #~ msgid "Up to date!" #~ msgstr "最新!" #~ msgid "Confirm Action" #~ msgstr "确认操作" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "您将要卸载以下 Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "您确定吗?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "您将安装以下 Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "您确定吗?" #~ msgid "Resume the execution of transactions" #~ msgstr "恢复事务执行" #~ msgid "Pause the execution of transactions" #~ msgstr "暂停事务执行" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "刷新" kolunmi-bazaar-7b9c8e1/po/zh_TW.po000066400000000000000000002261021514314607700170760ustar00rootroot00000000000000# Traditional Chinese translations for bazaar package # Copyright (C) 2025 THE bazaar'S COPYRIGHT HOLDER # This file is distributed under the same license as the bazaar package. # Automatically generated, 2025. # # SPDX-FileCopyrightText: 2025–2026 Shihfu Juan # SPDX-FileCopyrightText: 2025 Peter Dave Hello msgid "" msgstr "" "Project-Id-Version: bazaar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-01-24 01:17+0800\n" "PO-Revision-Date: 2026-01-24 21:23+0800\n" "Last-Translator: Shihfu Juan \n" "Language-Team: none\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.8\n" #: data/io.github.kolunmi.Bazaar.desktop.in:2 #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:7 src/bz-window.blp:5 #: src/bz-window.blp:233 msgid "Bazaar" msgstr "Bazaar" #: data/io.github.kolunmi.Bazaar.desktop.in:3 msgid "Add, remove or update flatpak software on this computer" msgstr "新增、移除或更新此電腦上的 Flatpak 軟體" #: data/io.github.kolunmi.Bazaar.desktop.in:9 msgid "GTK;System;PackageManager;Discover;Flatpak;Software;Store;" msgstr "" "GTK;System;PackageManager;Discover;Flatpak;Software;Store;套件管理;探索;軟體;" "商店;" #: data/io.github.kolunmi.Bazaar.desktop.in:15 msgid "New Window" msgstr "新視窗" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:8 msgid "Discover and install applications" msgstr "探索與安裝應用程式" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:10 msgid "" "A new app store for Linux with a focus on discovering and installing " "applications and addons from Flatpak remotes, particularly Flathub." msgstr "" "為 Linux 打造的新應用程式商店,著重探索與安裝來自 Flatpak 遠端(特別是 " "Flathub)的應用程式與附加元件。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:14 msgid "" "It emphasizes supporting the developers who make the Linux desktop possible. " "Bazaar features a \"curated\" tab that can be configured by distributors to " "allow for a more localized experience." msgstr "" "著重支援讓 Linux 桌面成真的開發者。Bazaar 提供「精選」分頁,發行商可設定以提" "供更在地化的體驗。" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:29 src/bz-application.c:706 msgid "Adam Masciola" msgstr "Adam Masciola" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:54 msgid "The home page displaying Flathub apps" msgstr "展示 Flathub 應用程式的首頁" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:58 msgid "Nucleus app page" msgstr "Nucleus 應用程式頁面" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:62 msgid "Search page" msgstr "搜尋頁面" #: data/io.github.kolunmi.Bazaar.metainfo.xml.in:66 msgid "Category page" msgstr "類別頁面" #: src/bz-addons-dialog.blp:14 src/bz-full-view.blp:697 #: src/bz-installed-tile.blp:99 msgid "Manage Add-ons" msgstr "管理附加元件" #: src/bz-addons-dialog.c:90 src/bz-full-view.blp:482 #: src/bz-installed-tile.blp:117 src/bz-transaction-dialog.c:225 #: src/bz-transaction-view.blp:277 msgid "Remove" msgstr "移除" #: src/bz-addons-dialog.c:95 src/bz-favorites-tile.c:174 #: src/bz-full-view.blp:249 src/bz-full-view.blp:469 #: src/bz-transaction-dialog.c:202 src/bz-transaction-view.blp:225 msgid "Install" msgstr "安裝" #: src/bz-age-rating-dialog.blp:7 src/bz-age-rating-dialog.blp:31 #: src/bz-age-rating-dialog.c:726 src/bz-full-view.c:338 src/bz-full-view.c:345 msgid "Age Rating" msgstr "年齡分級" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:88 msgid "Cartoon Violence" msgstr "卡通暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:90 msgid "No information regarding cartoon violence" msgstr "未提供任何關於卡通暴力的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:94 msgid "Fantasy Violence" msgstr "幻想暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:96 msgid "No information regarding fantasy violence" msgstr "未提供任何關於幻想暴力的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:100 msgid "Realistic Violence" msgstr "寫實暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:102 msgid "No information regarding realistic violence" msgstr "未提供任何關於寫實暴力的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:106 msgid "Violence Depicting Bloodshed" msgstr "含流血描寫的暴力內容" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:108 msgid "No information regarding bloodshed" msgstr "未提供任何關於流血場面的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:112 msgid "Sexual Violence" msgstr "性暴力" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:114 msgid "No information regarding sexual violence" msgstr "未提供任何關於性暴力的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:118 msgid "Alcohol" msgstr "酒精" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:120 msgid "No information regarding references to alcohol" msgstr "未提供任何關於酒精相關內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:124 msgid "Narcotics" msgstr "毒品" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:126 msgid "No information regarding references to illicit drugs" msgstr "未提供任何關於非法藥物的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:130 msgid "Tobacco" msgstr "菸草" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:132 msgid "No information regarding references to tobacco products" msgstr "未提供任何關於菸草製品的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:136 src/bz-age-rating-dialog.c:475 msgid "Nudity" msgstr "裸露" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:138 msgid "No information regarding nudity of any sort" msgstr "未提供任何關於裸露內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:142 msgid "Sexual Themes" msgstr "性相關主題" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:144 msgid "No information regarding references to or depictions of sexual nature" msgstr "未提供任何關於性相關描寫或暗示的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:148 msgid "Profanity" msgstr "粗俗用語" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:150 msgid "No information regarding profanity of any kind" msgstr "未提供任何關於粗俗用語的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:154 msgid "Inappropriate Humor" msgstr "不當幽默" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:156 msgid "No information regarding inappropriate humor" msgstr "未提供任何關於不當幽默的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:160 msgid "Discrimination" msgstr "歧視" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:162 msgid "No information regarding discriminatory language of any kind" msgstr "未提供任何關於歧視性言語的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:166 msgid "Advertising" msgstr "廣告" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:168 msgid "No information regarding advertising of any kind" msgstr "未提供任何關於廣告內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:172 msgid "Gambling" msgstr "賭博" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:174 msgid "No information regarding gambling of any kind" msgstr "未提供任何關於賭博內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:178 msgid "Purchasing" msgstr "䝘貝賟財" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:180 msgid "No information regarding the ability to spend money" msgstr "未提供任何關於金錢花費功能的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:184 msgid "Chat Between Users" msgstr "使用者之間的文字聊天" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:186 msgid "No information regarding ways to chat with other users" msgstr "未提供任何關於與其他使用者聊天方式的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:190 msgid "Audio Chat Between Users" msgstr "使用者之間的語音聊天" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:192 msgid "No information regarding ways to talk with other users" msgstr "未提供任何關於與其他使用者語音交談方式的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:196 msgid "Contact Details" msgstr "聯絡資訊" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:198 msgid "" "No information regarding sharing of social network usernames or email " "addresses" msgstr "未提供任何關於分享社群帳號或電子郵件地址的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:202 msgid "Identifying Information" msgstr "可識別個人身分的資訊" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:204 msgid "No information regarding sharing of user information with third parties" msgstr "未提供任何關於與第三方分享使用者資訊的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:208 msgid "Location Sharing" msgstr "位置分享" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:210 msgid "No information regarding sharing of physical location with other users" msgstr "未提供任何關於與其他使用者分享實際位置的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:214 msgid "Prostitution" msgstr "性交易" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:216 msgid "No information regarding references to prostitution" msgstr "未提供任何關於性交易相關內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:220 msgid "Adultery" msgstr "通姦" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:222 msgid "No information regarding references to adultery" msgstr "未提供任何關於通姦相關內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:226 msgid "Sexualized Characters" msgstr "性化角色" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:228 msgid "No information regarding sexualized characters" msgstr "未提供任何關於性化角色的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:232 msgid "Desecration" msgstr "褻瀆" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:234 msgid "No information regarding references to desecration" msgstr "未提供任何關於褻瀆相關內容的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:238 msgid "Human Remains" msgstr "人類遺骸" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:240 msgid "No information regarding visible dead human remains" msgstr "未提供任何關於可見人類遺骸的資訊" #. TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:244 msgid "Slavery" msgstr "弴彚" #. TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ #: src/bz-age-rating-dialog.c:246 msgid "No information regarding references to slavery" msgstr "未提供任何關於奴役相關內容的資訊" #: src/bz-age-rating-dialog.c:424 msgid "Does not include references to drugs" msgstr "不包含任何與毒品相關的內容" #: src/bz-age-rating-dialog.c:426 msgid "" "Does not include swearing, profanity, and other kinds of strong language" msgstr "不包含髒話、粗俗用語或其他強烈語言" #: src/bz-age-rating-dialog.c:428 msgid "Does not include ads or monetary transactions" msgstr "不包含廣告或金錢交易" #: src/bz-age-rating-dialog.c:430 msgid "Does not include sex or nudity" msgstr "不包含性內容或裸露描寫" #: src/bz-age-rating-dialog.c:432 msgid "Does not include uncontrolled chat functionality" msgstr "不包含未受控管的通訊功能" #: src/bz-age-rating-dialog.c:434 msgid "Does not include violence" msgstr "不包含暴力內容" #: src/bz-age-rating-dialog.c:469 msgid "Drugs" msgstr "毒品" #: src/bz-age-rating-dialog.c:471 msgid "Strong Language" msgstr "強烈語言" #: src/bz-age-rating-dialog.c:473 msgid "Money" msgstr "金錢" #: src/bz-age-rating-dialog.c:477 msgid "Social" msgstr "礞交" #: src/bz-age-rating-dialog.c:479 msgid "Violence" msgstr "暴力" #. Translators: Age rating format, e.g. "12+" for ages 12 and up #: src/bz-age-rating-dialog.c:676 src/bz-full-view.c:328 #, c-format msgid "%d+" msgstr "%d+" #: src/bz-age-rating-dialog.c:701 msgctxt "Age rating" msgid "All" msgstr "所有年齡層" #: src/bz-age-rating-dialog.c:737 #, c-format msgid "%s has an unknown age rating" msgstr "%s 的年齡分級未知" #: src/bz-age-rating-dialog.c:743 #, c-format msgid "%s is suitable for everyone" msgstr "%s 適合所有年齡層" #: src/bz-age-rating-dialog.c:746 #, c-format msgid "%s is suitable for young children" msgstr "%s 遊合嚟獼" #: src/bz-age-rating-dialog.c:749 #, c-format msgid "%s is suitable for children" msgstr "%s 適合兒童" #: src/bz-age-rating-dialog.c:752 #, c-format msgid "%s is suitable for teenagers" msgstr "%s 適合青少年" #: src/bz-age-rating-dialog.c:755 #, c-format msgid "%s is suitable for adults" msgstr "%s 遊合成人" #: src/bz-age-rating-dialog.c:758 #, c-format msgid "%s is suitable for %s" msgstr "%s 遊合 %s" #: src/bz-age-rating-dialog.c:852 #, c-format msgid "%s • %s" msgstr "%s • %s" #: src/bz-all-apps-page.blp:13 src/bz-apps-page.blp:14 src/bz-full-view.blp:43 #: src/bz-user-data-page.blp:15 src/bz-window.blp:483 msgid "Main Menu" msgstr "主選單" #: src/bz-all-apps-page.blp:17 src/bz-apps-page.blp:17 #: src/bz-user-data-page.blp:18 src/bz-window.blp:556 msgid "_Donate to Bazaar ❤️" msgstr "捐款給 Bazaar(&D) ❤️" #: src/bz-all-apps-page.blp:18 src/bz-apps-page.blp:18 #: src/bz-user-data-page.blp:19 msgid "_Refresh Content" msgstr "重新整理內容(&R)" #: src/bz-all-apps-page.blp:22 src/bz-apps-page.blp:22 #: src/bz-user-data-page.blp:22 src/bz-window.blp:563 msgid "_Preferences" msgstr "偏好設定(_P)" #: src/bz-all-apps-page.blp:23 src/bz-apps-page.blp:23 #: src/bz-user-data-page.blp:23 src/bz-window.blp:584 msgid "_Keyboard Shortcuts" msgstr "鍵盤快捷鍵(&K)" #: src/bz-all-apps-page.blp:24 src/bz-apps-page.blp:24 #: src/bz-user-data-page.blp:24 src/bz-window.blp:589 msgid "_About Bazaar" msgstr "關於 Bazaar(&A)" #: src/bz-all-apps-page.blp:28 src/bz-apps-page.blp:28 #: src/bz-user-data-page.blp:27 src/bz-window.blp:596 msgid "_Quit Bazaar" msgstr "退出 Bazaar(&Q)" #: src/bz-app-permissions.c:160 #, c-format msgid "System folder %s" msgstr "系統資料夾 %s" #: src/bz-app-permissions.c:162 #, c-format msgid "Home subfolder %s" msgstr "家目錄子目錄 %s" #: src/bz-app-permissions.c:164 msgid "Host system folders" msgstr "主機系統資料夾" #: src/bz-app-permissions.c:166 msgid "Host system configuration from /etc" msgstr "來自主機系統 /etc 中的系統設定" #: src/bz-app-permissions.c:169 #, c-format msgid "Desktop subfolder %s" msgstr "桌面子目錄 %s" #: src/bz-app-permissions.c:170 msgid "Desktop folder" msgstr "桌面資料夾" #: src/bz-app-permissions.c:173 #, c-format msgid "Documents subfolder %s" msgstr "文件子目錄 %s" #: src/bz-app-permissions.c:174 msgid "Documents folder" msgstr "文件資料夾" #: src/bz-app-permissions.c:177 #, c-format msgid "Music subfolder %s" msgstr "音樂子目錄 %s" #: src/bz-app-permissions.c:178 msgid "Music folder" msgstr "音樂資料夾" #: src/bz-app-permissions.c:181 #, c-format msgid "Pictures subfolder %s" msgstr "圖片子目錄 %s" #: src/bz-app-permissions.c:182 msgid "Pictures folder" msgstr "圖片資料夾" #: src/bz-app-permissions.c:185 #, c-format msgid "Public Share subfolder %s" msgstr "公開資料夾子目錄 %s" #: src/bz-app-permissions.c:186 msgid "Public Share folder" msgstr "公開資料夾" #: src/bz-app-permissions.c:189 #, c-format msgid "Videos subfolder %s" msgstr "影片子目錄 %s" #: src/bz-app-permissions.c:190 msgid "Videos folder" msgstr "影片資料夾" #: src/bz-app-permissions.c:193 #, c-format msgid "Templates subfolder %s" msgstr "模版子目錄 %s" #: src/bz-app-permissions.c:194 msgid "Templates folder" msgstr "模版資料夾" #: src/bz-app-permissions.c:197 #, c-format msgid "User cache subfolder %s" msgstr "使用者快取子目錄 %s" #: src/bz-app-permissions.c:198 msgid "User cache folder" msgstr "使用者快取資料夾" #: src/bz-app-permissions.c:201 #, c-format msgid "User configuration subfolder %s" msgstr "使用者設定子目錄 %s" #: src/bz-app-permissions.c:202 msgid "User configuration folder" msgstr "使用者設定資料夾" #: src/bz-app-permissions.c:205 #, c-format msgid "User data subfolder %s" msgstr "使用者資料子目錄 %s" #: src/bz-app-permissions.c:206 msgid "User data folder" msgstr "使用者資料資料夾" #: src/bz-app-permissions.c:209 #, c-format msgid "User runtime subfolder %s" msgstr "使用者執行環境子目錄 %s" #: src/bz-app-permissions.c:210 msgid "User runtime folder" msgstr "使用者執行環境資料夾" #: src/bz-app-permissions.c:212 #, c-format msgid "Filesystem access to %s" msgstr "對 %s 的檔案系統存取" #: src/bz-app-permissions.c:214 msgid "Unknown filesystem path" msgstr "未知的檔案系統目錄" #: src/bz-app-size-dialog.blp:29 src/bz-app-size-dialog.blp:55 msgid "Download Size" msgstr "下載大小" #: src/bz-app-size-dialog.blp:56 msgid "Amount to download from the internet" msgstr "從網際網路下載的大小" #: src/bz-app-size-dialog.blp:76 msgid "Installed Size" msgstr "安裝大小" #: src/bz-app-size-dialog.blp:77 msgid "Size on Disk" msgstr "磁碟上的大小" #: src/bz-app-size-dialog.blp:99 msgid "User Data Size" msgstr "使用者資料大小" #: src/bz-app-size-dialog.blp:100 msgid "Caches, settings, and other app data" msgstr "快取、設定以及其他應用程式資料" #. Translators: As in 'The app is installed'. #. Translators: . #: src/bz-app-tile.blp:86 src/bz-full-view.c:292 src/bz-installed-page.blp:86 #: src/bz-window.blp:299 msgid "Installed" msgstr "已安裝" #: src/bz-apps-page.blp:103 msgid "Show All" msgstr "顯示全部" #: src/bz-apps-page.c:232 #, c-format msgid "All \"%s\"" msgstr "全部 「%s」" #: src/bz-apps-page.c:506 src/bz-tag-list.c:109 #, c-format msgid "%d Applications" msgstr "%d 個應用程式" #: src/bz-application.c:677 msgctxt "About Dialog Developer Credit" msgid "Adam Masciola " msgstr "Adam Masciola " #: src/bz-application.c:678 msgctxt "About Dialog Developer Credit" msgid "Alexander Vanhee" msgstr "Alexander Vanhee" #. Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 #: src/bz-application.c:709 msgid "translator-credits" msgstr "" "Shihfu Juan , 2025,2026\n" "Peter Dave Hello , 2025" #: src/bz-application.c:720 msgid "Special Thanks" msgstr "特別感謝" #: src/bz-application.c:778 msgid "Logged Out Successfully!" msgstr "已成功登出!" #: src/bz-application.c:905 msgid "Performing setup..." msgstr "正在進行設定..." #: src/bz-application.c:984 src/bz-application.c:993 msgid "Set Up Flathub" msgstr "設定 Flathub" #: src/bz-application.c:987 msgid "" "Flathub is not set up on this system. You will not be able to browse and " "install applications in Bazaar if its unavailable.\n" "\n" "You can still use Bazaar to browse and remove already installed apps." msgstr "" "Flathub 未在此系統上設定完成。若無法使用 Flathub,您將無法在 Bazaar 中瀏覽與" "安裝應用程式。\n" "\n" "您仍可使用 Bazaar 來瀏覽並移除已安裝的應用程式。" #: src/bz-application.c:992 src/bz-window.c:875 msgid "Later" msgstr "稍後" #: src/bz-application.c:1380 src/bz-application.c:3086 msgid "Synchronizing..." msgstr "同步中..." #: src/bz-application.c:1521 src/bz-application.c:3082 #, c-format msgid "Receiving %d entries..." msgstr "正在接收 %d 筆項目…" #: src/bz-application.c:1526 msgid "Checking for updates" msgstr "正在檢查更新" #: src/bz-application.c:3088 msgid "Indexing Data..." msgstr "正在索引資料…" #: src/bz-curated-view.blp:11 src/bz-favorites-page.blp:75 #: src/bz-flathub-page.blp:19 src/bz-full-view.blp:53 #: src/bz-installed-page.blp:63 src/bz-user-data-page.blp:52 #: src/bz-window.blp:183 msgid "Empty" msgstr "無內容" #: src/bz-curated-view.blp:15 msgid "No Curation" msgstr "未經人工策選" #: src/bz-curated-view.blp:16 msgid "" "There is no curation information provided on this system. You can still " "browse applications on Flathub" msgstr "此系統未提供平台審核資訊。你仍可在 Flathub 上瀏覽應用程式" #: src/bz-curated-view.blp:18 msgid "Browse Flathub" msgstr "瀏覽 Flathub" #: src/bz-curated-view.blp:29 src/bz-curated-view.blp:33 #: src/bz-flathub-page.blp:30 src/bz-flathub-page.blp:34 msgid "Offline" msgstr "離線" #: src/bz-curated-view.blp:39 src/bz-flathub-page.blp:49 msgid "Browser" msgstr "瀏覽" #: src/bz-developer-badge.c:131 msgid "Developer information not available." msgstr "無法取得開發者資訊。" #: src/bz-developer-badge.c:137 src/bz-developer-badge.c:151 #, c-format msgid "" "The ownership of the %s app ID has not been verified and it may be a " "community package." msgstr "應用程式 ID %s 的所有權尚未經過驗證,可能為社群提供的套件。" #: src/bz-developer-badge.c:155 #, c-format msgid "" "The ownership of the %s app ID has been manually verified by the Flathub " "team." msgstr "應用程式 ID %s 的所有權已由 Flathub 團隊人工驗證。" #: src/bz-developer-badge.c:161 #, c-format msgid "" "The ownership of the %1$s app ID has been verified by %2$s on " "%3$s." msgstr "應用程式 ID %1$s 的所有權已由 %2$s 於 %3$s 驗證。" #: src/bz-developer-badge.c:168 #, c-format msgid "The ownership of the %1$s app ID has been verified using %2$s." msgstr "應用程式 ID %1$s 的所有權已透過 %2$s 驗證。" #: src/bz-developer-badge.c:172 #, c-format msgid "The ownership of the %s app ID has been verified." msgstr "應用程式 ID %s 的所有權已完成驗證。" #: src/bz-entry-group-util.c:73 msgid "Choose an Installation" msgstr "選擇要使用的安裝項目" #: src/bz-entry-group-util.c:76 msgid "" "You have multiple versions of this app installed. Which one would you like " "to proceed with?" msgstr "您已安裝此應用程式的多個版本。要繼續使用哪一個版本?" #: src/bz-entry-group-util.c:80 src/bz-transaction-dialog.c:201 #: src/bz-transaction-dialog.c:224 src/bz-transaction-dialog.c:269 #: src/bz-transaction-dialog.c:576 msgid "Cancel" msgstr "取消" #: src/bz-error.c:68 msgid "An Error Occurred" msgstr "發生錯誤" #: src/bz-error.c:89 msgid "Close" msgstr "關閉" #: src/bz-error.c:90 msgid "Copy and Close" msgstr "複製並關閉" #: src/bz-favorite-button.c:434 msgid "Log in with Flathub to manage favorites" msgstr "登入至 Flathub 以管理最愛" #: src/bz-favorite-button.c:440 msgid "Log In" msgstr "登入" #: src/bz-favorite-button.blp:14 msgid "Favorite Count" msgstr "收藏數量" #: src/bz-favorites-tile.c:172 msgid "Uninstall" msgstr "解除安裝" #: src/bz-favorites-tile.blp:70 src/bz-installed-tile.blp:75 msgid "Support this application" msgstr "支援此應用程式" #: src/bz-favorites-tile.blp:119 msgid "Remove from Favorites" msgstr "從收藏中移除" #: src/bz-favorites-page.blp:5 src/bz-favorites-page.blp:85 #: src/bz-window.blp:614 msgid "Favorites" msgstr "收藏" #: src/bz-favorites-page.blp:22 src/bz-full-view.blp:20 src/bz-window.blp:126 #: src/bz-window.blp:460 msgid "Toggle transaction sidebar" msgstr "切換作業側邊欄" #: src/bz-favorites-page.blp:46 src/bz-transaction-dialog.c:577 msgid "Install All" msgstr "安裝全部" #: src/bz-favorites-page.blp:63 src/bz-user-data-page.blp:41 msgid "Loading" msgstr "載入中" #: src/bz-favorites-page.blp:78 msgid "No Favorites" msgstr "沒有收藏" #: src/bz-favorites-page.blp:79 msgid "Applications you mark as favorite will appear here" msgstr "您所收藏的應用程式將會顯示在這裡" #: src/bz-featured-carousel.blp:31 msgid "Previous" msgstr "上一個" #: src/bz-featured-carousel.blp:53 msgid "Next" msgstr "下一個" #: src/bz-featured-tile.blp:88 msgid "App of the Day" msgstr "今日精選應用程式" #: src/bz-flathub-category.c:79 msgid "Audio & Video" msgstr "影音" #: src/bz-flathub-category.c:79 msgid "Media" msgstr "媒體" #: src/bz-flathub-category.c:79 msgid "More Audio & Video" msgstr "更多影音" #: src/bz-flathub-category.c:80 msgid "Developer Tools" msgstr "開發者工具" #: src/bz-flathub-category.c:80 msgid "Develop" msgstr "開發" #: src/bz-flathub-category.c:80 msgid "More Developer Tools" msgstr "更多開發者工具" #: src/bz-flathub-category.c:81 msgid "Education" msgstr "教育" #: src/bz-flathub-category.c:81 msgid "Learn" msgstr "學習" #: src/bz-flathub-category.c:81 msgid "More Education" msgstr "更多教育" #: src/bz-flathub-category.c:82 msgid "Gaming" msgstr "遊㈞" #: src/bz-flathub-category.c:82 msgid "Play" msgstr "遊玩" #: src/bz-flathub-category.c:82 msgid "More Gaming" msgstr "更多遊戲" #: src/bz-flathub-category.c:83 msgid "Graphics & Photography" msgstr "圖像與攝影" #: src/bz-flathub-category.c:83 msgid "Create" msgstr "創作" #: src/bz-flathub-category.c:83 msgid "More Graphics & Photography" msgstr "更多圖像與攝影" #: src/bz-flathub-category.c:84 msgid "Networking" msgstr "眲衯" #: src/bz-flathub-category.c:84 msgid "Internet" msgstr "網際網路" #: src/bz-flathub-category.c:84 msgid "More Networking" msgstr "更多網路" #: src/bz-flathub-category.c:85 msgid "Productivity" msgstr "生產力" #: src/bz-flathub-category.c:85 msgid "Work" msgstr "工作" #: src/bz-flathub-category.c:85 msgid "More Productivity" msgstr "更多生產力" #: src/bz-flathub-category.c:86 msgid "Science" msgstr "科學" #: src/bz-flathub-category.c:86 msgid "More Science" msgstr "更多科學" #: src/bz-flathub-category.c:87 msgid "System" msgstr "çłťçľą" #: src/bz-flathub-category.c:87 msgid "More System" msgstr "更多系統" #: src/bz-flathub-category.c:88 msgid "Utilities" msgstr "工具程式" #: src/bz-flathub-category.c:88 msgid "Tools" msgstr "工具" #: src/bz-flathub-category.c:88 msgid "More Utilities" msgstr "更多工具程式" #: src/bz-flathub-category.c:89 src/bz-flathub-page.blp:119 #: src/bz-flathub-page.blp:152 msgid "Trending" msgstr "近期熱門" #: src/bz-flathub-category.c:89 msgid "More Trending" msgstr "更多近期熱門" #: src/bz-flathub-category.c:90 src/bz-flathub-page.blp:125 #: src/bz-flathub-page.blp:185 msgid "Popular" msgstr "最受歡迎" #: src/bz-flathub-category.c:90 msgid "More Popular" msgstr "更多最受歡迎" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:174 msgid "Recently Added" msgstr "最近新增" #: src/bz-flathub-category.c:91 src/bz-flathub-page.blp:131 msgid "New" msgstr "最新" #: src/bz-flathub-category.c:91 msgid "More New" msgstr "更多最新" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:163 msgid "Recently Updated" msgstr "最近更新" #: src/bz-flathub-category.c:92 src/bz-flathub-page.blp:137 msgid "Updated" msgstr "已更新" #: src/bz-flathub-category.c:92 msgid "More Updated" msgstr "更多更新" #: src/bz-flathub-category.c:93 msgid "Mobile" msgstr "行動裝置" #: src/bz-flathub-category.c:93 msgid "More Mobile" msgstr "更多行動裝置" #: src/bz-flathub-category.c:94 msgid "Adwaita" msgstr "Adwaita" #: src/bz-flathub-category.c:94 msgid "More Adwaita" msgstr "更多 Adwaita" #: src/bz-flathub-category.c:95 msgid "KDE Apps" msgstr "KDE 應用程式" #: src/bz-flathub-category.c:95 msgid "More KDE Apps" msgstr "更多 KDE 應用程式" #: src/bz-flathub-page.blp:23 msgid "Flathub Not Added" msgstr "尚未加入 Flathub" #: src/bz-flathub-page.blp:24 msgid "The Flathub remote was not found on any of your Flatpak installations" msgstr "在您的任何 Flatpak 安裝中都找不到 Flathub 遠獯" #: src/bz-flathub-page.blp:35 msgid "Flathub returned an error" msgstr "Flathub 回傳了錯誤" #: src/bz-flathub-page.blp:41 msgid "Retry Flathub Connection" msgstr "重新嘗試連線至 Flathub" #: src/bz-flathub-page.blp:57 msgid "Flathub Unavailable" msgstr "Flathub 無法使用" #: src/bz-flathub-page.blp:58 msgid "" "We could not connect to Flathub. You can still manage and search for " "applications." msgstr "無法連線至 Flathub。您仍可管理並搜尋已安裝的應用程式。" #: src/bz-flathub-page.blp:61 msgid "Search Apps" msgstr "搜尋應用程式" #: src/bz-flathub-page.blp:270 msgid "On the Go" msgstr "隨時隨地" #: src/bz-flathub-page.blp:282 msgid "Apps for your Linux phones and tablets" msgstr "適用於您的 Linux 手機與平板的應用程式" #: src/bz-flathub-page.blp:293 src/bz-flathub-page.blp:328 msgid "More Mobile Apps" msgstr "更多行動應用程式" #: src/bz-flathub-page.blp:388 msgid "We​ ♥​ Games" msgstr "我們 ♥ 遊㈞" #: src/bz-flathub-page.blp:401 msgid "Games and apps to run your favorite titles" msgstr "用來執行您最愛作品的遊戲與應用程式" #: src/bz-flathub-page.blp:435 msgid "More Games" msgstr "更多遊戲" #: src/bz-flatpak-entry.c:663 msgctxt "Project URL Type" msgid "Flathub Page" msgstr "Flathub 頁面" #: src/bz-flatpak-entry.c:684 msgctxt "Project URL Type" msgid "Project Website" msgstr "專案網址" #: src/bz-flatpak-entry.c:688 msgctxt "Project URL Type" msgid "Issue Tracker" msgstr "問題追蹤器" #: src/bz-flatpak-entry.c:692 msgctxt "Project URL Type" msgid "FAQ" msgstr "FAQ" #: src/bz-flatpak-entry.c:696 msgctxt "Project URL Type" msgid "Help" msgstr "幫助" #: src/bz-flatpak-entry.c:700 msgctxt "Project URL Type" msgid "Donate" msgstr "捐贈" #: src/bz-flatpak-entry.c:706 msgctxt "Project URL Type" msgid "Translate" msgstr "çżťč­Ż" #: src/bz-flatpak-entry.c:710 msgctxt "Project URL Type" msgid "Contact" msgstr "聯絡方式" #: src/bz-flatpak-entry.c:714 msgctxt "Project URL Type" msgid "Source Code" msgstr "原始碼" #: src/bz-flatpak-entry.c:720 msgctxt "Project URL Type" msgid "Contribute" msgstr "貢獻" #: src/bz-full-view.blp:57 src/bz-installed-page.blp:74 #: src/bz-installed-page.blp:78 msgid "No Results" msgstr "沒有結果" #: src/bz-full-view.blp:58 msgid "Try a different search query" msgstr "請嘗試不同的搜尋關鍵字" #: src/bz-full-view.blp:64 src/bz-window.blp:193 msgid "Content" msgstr "內容" #: src/bz-full-view.blp:210 msgid "Support" msgstr "贊助" #: src/bz-full-view.blp:233 src/bz-full-view.blp:493 msgid "Open" msgstr "打開" #: src/bz-full-view.blp:246 src/bz-full-view.blp:466 msgid "Download & Install Application" msgstr "下載並安裝應用程式" #: src/bz-full-view.blp:261 msgid "Uninstall Application" msgstr "移除應用程式" #: src/bz-full-view.blp:276 src/bz-full-view.blp:508 msgid "Install Other Version" msgstr "安裝其他版本" #: src/bz-full-view.blp:430 msgid "Downloads /mo" msgstr "每月下載次數" #: src/bz-full-view.blp:527 msgid "Stopped Receiving Core Updates" msgstr "已停止接收核心更新" #: src/bz-full-view.blp:541 msgid "" "This app uses a runtime that no longer receives updates or security fixes. " "It may become unsafe to use." msgstr "" "此應用程式使用的執行環境已不再接收更新或安全修補,使用上可能存在安全風險。" #: src/bz-full-view.blp:630 msgid "Trash Data" msgstr "清除資料" #: src/bz-full-view.blp:772 msgid "Tags:" msgstr "標籤:" #: src/bz-full-view.c:235 msgid "---" msgstr "---" #. Translators: M is the suffix for millions #: src/bz-full-view.c:242 #, c-format msgid "%.*fM" msgstr "%.*fM" #. Translators: K is the suffix for thousands #: src/bz-full-view.c:249 #, c-format msgid "%.*fK" msgstr "%.*fK" #: src/bz-full-view.c:259 #, c-format msgid "%d downloads in the last 30 days" msgstr "在過去 30 天內有 %d 次下載" #. Translators: . #: src/bz-full-view.c:292 msgid "Download" msgstr "下載" #: src/bz-full-view.c:310 #, c-format msgid "Download size of %s" msgstr "下載 %s 的大小" #: src/bz-full-view.c:343 msgid "All Ages" msgstr "所有年齡層" #: src/bz-full-view.c:355 msgid "Age rating information unavailable" msgstr "年齡分級資訊未知" #: src/bz-full-view.c:360 msgid "Suitable for all ages" msgstr "適合所有年齡層" #: src/bz-full-view.c:362 #, c-format msgid "Suitable for ages %d and up" msgstr "遊合 %d 歲以上" #: src/bz-full-view.c:395 src/bz-full-view.c:400 src/bz-full-view.c:428 #: src/bz-full-view.c:439 msgid "Unknown" msgstr "未知" #: src/bz-full-view.c:405 #, c-format msgid "Free software licensed under %s" msgstr "䞝 %s 授權的自由軟體" #: src/bz-full-view.c:410 msgid "Free software" msgstr "自由軟體" #: src/bz-full-view.c:413 msgid "Proprietary Software" msgstr "專有軟體" #: src/bz-full-view.c:416 #, c-format msgid "Special License: %s" msgstr "特殊授權:%s" #: src/bz-full-view.c:433 msgid "Free" msgstr "自由" #: src/bz-full-view.c:436 src/bz-license-dialog.c:190 msgid "Proprietary" msgstr "專有" #: src/bz-full-view.c:441 src/bz-license-dialog.c:192 msgid "Special License" msgstr "特殊授權" #: src/bz-full-view.c:461 msgid "Adaptive" msgstr "支援多裝置" #: src/bz-full-view.c:461 msgid "Desktop Only" msgstr "僅限桌面" #: src/bz-full-view.c:467 msgid "Works on desktop, tablets, and phones" msgstr "可在電腦、平板與手機上使用" #: src/bz-full-view.c:468 msgid "May not work on mobile devices" msgstr "可能無法在行動裝置上使用" #: src/bz-full-view.c:479 msgid "No URL" msgstr "沒有網址" #: src/bz-full-view.c:497 msgid "" "This application has a FLOSS license, meaning the source code can be audited " "for safety." msgstr "此應用程式具有 FLOSS 授權,這意味著其原始碼可供審查以確保安全性。" #: src/bz-full-view.c:498 msgid "" "This application has a proprietary license, meaning the source code is " "developed privately and cannot be audited by an independent third party." msgstr "此應用程式採用專有授權,表示其原始碼為私有,無法由第三方獨立審查。" #: src/bz-full-view.c:505 msgid "More Apps" msgstr "更多應用程式" #: src/bz-full-view.c:506 #, c-format msgid "More Apps by %s" msgstr "更多由 %s 製作的應用程式" #: src/bz-full-view.c:513 msgid "Other Apps by this Developer" msgstr "其他由此開發者製作的應用程式" #: src/bz-full-view.c:515 src/bz-full-view.c:715 #, c-format msgid "Other Apps by %s" msgstr "其他由 %s 製作的應用程式" #: src/bz-full-view.c:524 #, c-format msgid "%s is not installed, but it still has %s of data present." msgstr "%s 並未安裝,但仍保留 %s 的資料。" #: src/bz-full-view.c:597 src/bz-full-view.c:614 msgid "N/A" msgstr "N/A" #: src/bz-full-view.c:604 src/bz-safety-dialog.blp:31 msgid "Safe" msgstr "安全" #: src/bz-full-view.c:606 src/bz-full-view.c:608 msgid "Low Risk" msgstr "低風險" #: src/bz-full-view.c:610 msgid "Medium Risk" msgstr "中度風險" #: src/bz-full-view.c:612 msgid "High Risk" msgstr "高風險" #: src/bz-full-view.c:717 msgid "Other Apps" msgstr "其他應用程式" #: src/bz-full-view.c:719 #, c-format msgid "%d Application" msgid_plural "%d Applications" msgstr[0] "%d 個應用程式" #: src/bz-full-view.c:1058 msgid "Show Less" msgstr "顯示更少" #: src/bz-full-view.c:1058 msgid "Show More" msgstr "顯示更多" #: src/bz-hardware-support-dialog.blp:7 src/bz-hardware-support-dialog.blp:31 msgid "Hardware Support" msgstr "硬體支援" #: src/bz-hardware-support-dialog.c:62 msgid "Keyboard support" msgstr "鍵盤支援" #: src/bz-hardware-support-dialog.c:64 msgid "Requires keyboards" msgstr "需要鍵盤" #: src/bz-hardware-support-dialog.c:65 msgid "Recommends keyboards" msgstr "建議搭配鍵盤使用" #: src/bz-hardware-support-dialog.c:66 msgid "Supports keyboards" msgstr "支援鍵盤" #: src/bz-hardware-support-dialog.c:67 msgid "Unknown support for keyboards" msgstr "鍵盤支援情況未知" #: src/bz-hardware-support-dialog.c:69 msgid "Mouse support" msgstr "滑鼠支援" #: src/bz-hardware-support-dialog.c:71 msgid "Requires mice or pointing devices" msgstr "需要滑鼠或指向性裝置" #: src/bz-hardware-support-dialog.c:72 msgid "Recommends mice or pointing devices" msgstr "建議搭配滑鼠或指向性裝置" #: src/bz-hardware-support-dialog.c:73 msgid "Supports mice or pointing devices" msgstr "支援滑鼠或指向性裝置" #: src/bz-hardware-support-dialog.c:74 msgid "Unknown support for mice or pointing devices" msgstr "滑鼠或指向性裝置支援情況未知" #: src/bz-hardware-support-dialog.c:76 msgid "Touchscreen support" msgstr "觸控螢幕支援" #: src/bz-hardware-support-dialog.c:78 msgid "Requires touchscreens" msgstr "需要觸控螢幕" #: src/bz-hardware-support-dialog.c:79 msgid "Recommends touchscreens" msgstr "建議搭配觸控螢幕" #: src/bz-hardware-support-dialog.c:80 msgid "Supports touchscreens" msgstr "支援觸控螢幕" #: src/bz-hardware-support-dialog.c:81 msgid "Unknown support for touchscreens" msgstr "觸控螢幕支援情況未知" #: src/bz-hardware-support-dialog.c:160 msgid "Mobile support" msgstr "行動裝置支援" #: src/bz-hardware-support-dialog.c:161 msgid "Works on mobile devices" msgstr "可在行動裝置上使用" #: src/bz-hardware-support-dialog.c:161 msgid "May not work well on mobile devices" msgstr "在行動裝置上的使用體驗可能不佳" #: src/bz-hardware-support-dialog.c:166 msgid "Desktop support" msgstr "桌面電腦支援" #: src/bz-hardware-support-dialog.c:167 msgid "Works well on large screens" msgstr "在大螢幕上運作良好" #: src/bz-hardware-support-dialog.c:201 #, c-format msgid "%s works best on specific hardware" msgstr "%s 在特定硬體上可發揮最佳效能" #: src/bz-hardware-support-dialog.c:209 #, c-format msgid "%s works on most devices" msgstr "%s 可在多數裝置上使用" #: src/bz-installed-page.blp:28 msgid "Search installed apps" msgstr "搜尋已安裝的應用程式" #: src/bz-installed-page.blp:67 msgid "No Apps Found" msgstr "找不到任何應用程式" #: src/bz-installed-page.c:157 #, c-format msgid "No matches found for \"%s\" in the list of installed apps" msgstr "在已安裝的應用程式清單中找不到符合「%s」的項目" #: src/bz-installed-tile.blp:61 src/bz-rich-app-tile.blp:136 msgid "Stopped Receiving Updates" msgstr "已停止接收更新" #: src/bz-license-dialog.blp:95 msgid "Get Involved" msgstr "參與貢獻" #: src/bz-license-dialog.c:184 msgid "Unknown License" msgstr "未知授權" #: src/bz-license-dialog.c:187 msgid "Community Built" msgstr "社群打造" #: src/bz-license-dialog.c:235 msgid "" "This app is developed in the open by an international community.\n" "\n" "You can participate and help make it even better." msgstr "" "此應用程式由國際社群以開放方式開發。\n" "\n" "您可以參與貢獻,協助讓它變得更好。" #: src/bz-license-dialog.c:238 msgid "The license of this app is not known" msgstr "此應用程式的授權資訊未知" #: src/bz-license-dialog.c:244 #, c-format msgid "" "This app is developed in the open by an international community, and " "released under the %s license.\n" "\n" "You can participate and help make it even better." msgstr "" "此應用程式由國際社群以開放方式開發,並以 %s 授權釋出。\n" "\n" "您可以參與貢獻,協助讓它變得更好。" #: src/bz-license-dialog.c:252 msgid "" "This app is not developed in the open, so only its developers know how it " "works. It may be insecure in ways that are hard to detect, and it may change " "without oversight.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "此應用程式並非以開放方式開發,因此只有開發者知道其運作方式。它可能存在難以察" "覺的安全風險,且可能在缺乏監督的情況下變更。\n" "\n" "您可能可以,也可能無法對此應用程式做出貢獻。" #: src/bz-license-dialog.c:258 #, c-format msgid "" "This app is developed under the special license %s.\n" "\n" "You may or may not be able to contribute to this app." msgstr "" "此應用程式採用特殊授權 %s 開發。\n" "\n" "您可能可以,也可能無法對此應用程式做出貢獻。" #: src/bz-login-page.blp:5 src/bz-login-page.blp:42 msgid "Connect to Flathub" msgstr "連結至 Flathub" #: src/bz-login-page.blp:32 msgid "Something Went Wrong" msgstr "發生問題" #: src/bz-login-page.blp:43 msgid "Connect your Flathub account to Bazaar to manage your favorited apps." msgstr "將您的 Flathub 帳號連結至 Bazaar,以管理您加入收藏的應用程式。" #: src/bz-login-page.blp:108 msgid "Finish" msgstr "完成" #: src/bz-login-page.c:663 #, c-format msgid "Hello, %s!" msgstr "您好,%s" #: src/bz-preferences-dialog.blp:19 msgid "Preferences" msgstr "偏好設定" #: src/bz-preferences-dialog.blp:25 msgid "Network connection is metered — automatic store data sync is paused" msgstr "目前的網路連線為計量連線,已暫停商店資料的自動同步" #: src/bz-preferences-dialog.blp:26 src/bz-window.blp:494 msgid "Sync Manually" msgstr "手動同步" #: src/bz-preferences-dialog.blp:31 msgid "Content Filters" msgstr "內容篩選" #: src/bz-preferences-dialog.blp:34 msgid "Free Software Only" msgstr "僅顯示自由軟體" #: src/bz-preferences-dialog.blp:35 msgid "Hide proprietary applications when browsing and searching" msgstr "在瀏覽與搜尋時隱藏專有軟體應用程式" #: src/bz-preferences-dialog.blp:39 msgid "Flathub Results Only" msgstr "僅顯示 Flathub 結果" #: src/bz-preferences-dialog.blp:40 msgid "" "Limit search and browse results to applications only available on Flathub" msgstr "將搜尋與瀏覽結果限制為僅在 Flathub 上提供的應用程式" #: src/bz-preferences-dialog.blp:44 msgid "Verified Results Only" msgstr "僅顯示已驗證的結果" #: src/bz-preferences-dialog.blp:45 msgid "Hide results that are not verified on Flathub" msgstr "隱藏未經 Flathub 驗證的結果" #: src/bz-preferences-dialog.blp:49 msgid "Hide EOL Apps" msgstr "隱藏已終止支援的應用程式" #: src/bz-preferences-dialog.blp:50 msgid "Hide apps which are no longer supported by their developers" msgstr "隱藏已不再由開發者支援的應用程式" #: src/bz-preferences-dialog.blp:55 src/bz-window.blp:314 msgid "Search" msgstr "搜尋" #: src/bz-preferences-dialog.blp:58 msgid "Delay Search Results" msgstr "延遲顯示搜尋結果" #: src/bz-preferences-dialog.blp:59 msgid "Improve results performance by debouncing search terms" msgstr "透過延遲處理搜尋輸入以提升結果效能" #: src/bz-preferences-dialog.blp:64 msgid "Progress Bar" msgstr "進度列" #: src/bz-preferences-dialog.blp:65 msgid "Choose a theme for the progress bar!" msgstr "選擇進度列的主題!" #: src/bz-preferences-dialog.blp:89 msgid "Vertical Stripes" msgstr "垂直條紋" #: src/bz-preferences-dialog.blp:90 msgid "Display flag colors from top to bottom" msgstr "由上而下顯示旗幟配色" #: src/bz-preferences-dialog.c:32 msgid "Accent Color" msgstr "強調色" #: src/bz-preferences-dialog.c:33 msgid "Pride Colors" msgstr "驕傲旗配色" #: src/bz-preferences-dialog.c:34 msgid "Lesbian Pride Colors" msgstr "女同志驕傲旗配色" #: src/bz-preferences-dialog.c:35 msgid "Male Homosexual Pride Colors" msgstr "男同志驕傲旗配色" #: src/bz-preferences-dialog.c:36 msgid "Transgender Pride Colors" msgstr "跨性別驕傲旗配色" #: src/bz-preferences-dialog.c:37 msgid "Nonbinary Pride Colors" msgstr "非二元性別驕傲旗配色" #: src/bz-preferences-dialog.c:38 msgid "Bisexual Pride Colors" msgstr "雙性戀驕傲旗配色" #: src/bz-preferences-dialog.c:39 msgid "Asexual Pride Colors" msgstr "無性戀驕傲旗配色" #: src/bz-preferences-dialog.c:40 msgid "Pansexual Pride Colors" msgstr "泛性戀驕傲旗配色" #: src/bz-preferences-dialog.c:41 msgid "Aromantic Pride Colors" msgstr "無浪漫傾向驕傲旗配色" #: src/bz-preferences-dialog.c:42 msgid "Genderfluid Pride Colors" msgstr "性別流動驕傲旗配色" #: src/bz-preferences-dialog.c:43 msgid "Polysexual Pride Colors" msgstr "多元性向驕傲旗配色" #: src/bz-preferences-dialog.c:44 msgid "Omnisexual Pride Colors" msgstr "全性向驕傲旗配色" #: src/bz-preferences-dialog.c:45 msgid "Aroace Pride Colors" msgstr "無浪漫/無性戀驕傲旗配色" #: src/bz-preferences-dialog.c:46 msgid "Agender Pride Colors" msgstr "無性別驕傲旗配色" #: src/bz-preferences-dialog.c:47 msgid "Genderqueer Pride Colors" msgstr "性別酷兒驕傲旗配色" #: src/bz-preferences-dialog.c:48 msgid "Intersex Pride Colors" msgstr "雙性人驕傲旗配色" #: src/bz-preferences-dialog.c:49 msgid "Demigender Pride Colors" msgstr "半性別驕傲旗配色" #: src/bz-preferences-dialog.c:50 msgid "Biromantic Pride Colors" msgstr "雙浪漫傾向驕傲旗配色" #: src/bz-preferences-dialog.c:51 msgid "Disability Pride Colors" msgstr "身心障礙驕傲旗配色" #: src/bz-preferences-dialog.c:52 msgid "Femboy Pride Colors" msgstr "女性氣質男性驕傲旗配色" #: src/bz-preferences-dialog.c:53 msgid "Neutrois Pride Colors" msgstr "中性性別驕傲旗配色" #: src/bz-releases-dialog.blp:5 src/bz-releases-list.blp:27 msgid "Version History" msgstr "版本紀錄" #: src/bz-releases-list.c:135 #, c-format msgid "Version %s" msgstr "版本 %s" #: src/bz-releases-list.c:173 msgid "No details for this release" msgstr "此版本沒有詳細資訊" #: src/bz-releases-list.c:185 msgid "Get More Information" msgstr "取得更多資訊" #: src/bz-rich-app-tile.blp:153 msgid "Get" msgstr "取得" #: src/bz-safety-calculator.c:82 msgid "Unknown Permissions" msgstr "未知的權限" #: src/bz-safety-calculator.c:83 msgid "Permissions are missing for this app." msgstr "此應用程式缺少權限資訊。" #: src/bz-safety-calculator.c:96 msgid "No Permissions" msgstr "無權限需求" #: src/bz-safety-calculator.c:97 msgid "App is fully sandboxed" msgstr "此應用程式已完全沙箱化" #: src/bz-safety-calculator.c:103 msgid "Network Access" msgstr "網路存取" #: src/bz-safety-calculator.c:104 msgid "Can access the internet" msgstr "可存取網際網路" #: src/bz-safety-calculator.c:106 msgid "No Network Access" msgstr "無網路存取" #: src/bz-safety-calculator.c:107 msgid "Cannot access the internet" msgstr "無法存取網際網路" #: src/bz-safety-calculator.c:112 msgid "User Device Access" msgstr "使用者裝置存取" #: src/bz-safety-calculator.c:113 msgid "Can access devices such as webcams or gaming controllers" msgstr "可存取如網路攝影機或遊戲控制器等裝置" #: src/bz-safety-calculator.c:115 msgid "No User Device Access" msgstr "無使用者裝置存取" #: src/bz-safety-calculator.c:116 msgid "Cannot access devices such as webcams or gaming controllers" msgstr "無法存取如網路攝影機或遊戲控制器等裝置" #: src/bz-safety-calculator.c:121 msgid "Input Device Access" msgstr "輸入裝置存取" #: src/bz-safety-calculator.c:122 msgid "Can access input devices" msgstr "可存取輸入裝置" #: src/bz-safety-calculator.c:128 msgid "Microphone Access and Audio Playback" msgstr "麥克風存取與音訊播放" #: src/bz-safety-calculator.c:129 msgid "Can listen using microphones and play audio without asking permission" msgstr "可在未詢問權限的情況下使用麥克風收音並播放音訊" #: src/bz-safety-calculator.c:135 msgid "System Device Access" msgstr "系統裝置存取" #: src/bz-safety-calculator.c:136 msgid "Can access system devices which require elevated permissions" msgstr "可存取需要較高權限的系統裝置" #: src/bz-safety-calculator.c:142 msgid "Screen Contents Access" msgstr "螢幕內容存取" #: src/bz-safety-calculator.c:143 msgid "Can access the contents of the screen or other windows" msgstr "可存取螢幕或其他視窗的內容" #: src/bz-safety-calculator.c:149 msgid "Legacy Windowing System" msgstr "舊式視窗系統" #: src/bz-safety-calculator.c:150 msgid "Always uses a legacy windowing system (X11)" msgstr "一律使用舊式視窗系統(X11)" #: src/bz-safety-calculator.c:156 msgid "Arbitrary Permissions" msgstr "任意權限" #: src/bz-safety-calculator.c:157 msgid "Can acquire arbitrary permissions" msgstr "可取得任意權限" #: src/bz-safety-calculator.c:163 msgid "User Settings" msgstr "使用者設定" #: src/bz-safety-calculator.c:164 msgid "Can access and change user settings" msgstr "可存取並變更使用者設定" #: src/bz-safety-calculator.c:170 msgid "Full File System Read/Write Access" msgstr "完整檔案系統讀取/寫入權限" #: src/bz-safety-calculator.c:171 msgid "Can read and write all data on the file system" msgstr "可讀取與寫入檔案系統中的所有資料" #: src/bz-safety-calculator.c:178 msgid "Home Folder Read/Write Access" msgstr "家目錄讀取/寫入權限" #: src/bz-safety-calculator.c:179 msgid "Can read and write all data in your home directory" msgstr "可讀取與寫入您家目錄中的所有資料" #: src/bz-safety-calculator.c:186 msgid "Full File System Read Access" msgstr "完整檔案系統讀取權限" #: src/bz-safety-calculator.c:187 msgid "Can read all data on the file system" msgstr "可讀取檔案系統中的所有資料" #: src/bz-safety-calculator.c:195 msgid "Home Folder Read Access" msgstr "家目錄讀取權限" #: src/bz-safety-calculator.c:196 msgid "Can read all data in your home directory" msgstr "可讀取您家目錄中的所有資料" #: src/bz-safety-calculator.c:204 msgid "Download Folder Read/Write Access" msgstr "下載資料夾讀取/寫入權限" #: src/bz-safety-calculator.c:205 msgid "Can read and write all data in your downloads directory" msgstr "可讀取與寫入您下載資料夾中的所有資料" #: src/bz-safety-calculator.c:215 msgid "Download Folder Read Access" msgstr "下載資料夾讀取權限" #: src/bz-safety-calculator.c:216 msgid "Can read all data in your downloads directory" msgstr "可讀取您下載資料夾中的所有資料" #: src/bz-safety-calculator.c:229 msgid "Can read and write all data in the directory" msgstr "可讀取與寫入該目錄中的所有資料" #: src/bz-safety-calculator.c:243 msgid "Can read all data in the directory" msgstr "可讀取該目錄中的所有資料" #: src/bz-safety-calculator.c:258 msgid "No File System Access" msgstr "無檔案系統存取權限" #: src/bz-safety-calculator.c:259 msgid "Cannot access the file system at all" msgstr "完全無法存取檔案系統" #: src/bz-safety-calculator.c:266 msgid "Uses System Services" msgstr "使用系統服務" #: src/bz-safety-calculator.c:267 msgid "Can request data from non-portal system services" msgstr "可向非入口(non-portal)的系統服務請求資料" #: src/bz-safety-calculator.c:273 msgid "Uses Session Services" msgstr "使用工作階段服務" #: src/bz-safety-calculator.c:274 msgid "Can request data from non-portal session services" msgstr "可向非入口(non-portal)的工作階段服務請求資料" #: src/bz-safety-calculator.c:322 msgid "No Service Access" msgstr "無服務存取權限" #: src/bz-safety-calculator.c:323 msgid "Cannot access non-portal session or system services at all" msgstr "完全無法存取非入口(non-portal)的工作階段或系統服務" #: src/bz-safety-calculator.c:331 msgid "Verified App Developer" msgstr "已驗證的應用程式開發者" #: src/bz-safety-calculator.c:332 msgid "The developer of this app has been verified to be who they say they are" msgstr "此應用程式的開發者身分已通過驗證,確認與其所聲稱的身分相符" #: src/bz-safety-calculator.c:341 msgid "Proprietary Code" msgstr "專有程式碼" #: src/bz-safety-calculator.c:342 msgid "" "The source code is not public, so it cannot be independently audited and " "might be unsafe" msgstr "原始碼未公開,無法進行獨立稽核,可能存在安全風險" #: src/bz-safety-calculator.c:352 msgid "Auditable Code" msgstr "可稽核的程式碼" #: src/bz-safety-calculator.c:353 msgid "" "The source code is public and can be independently audited, which makes the " "app more likely to be safe" msgstr "原始碼已公開,且可進行獨立稽核,使此應用程式更可能是安全的" #: src/bz-safety-calculator.c:493 #, c-format msgid "Use the %s System Service" msgstr "使用 %s 系統服務" #: src/bz-safety-calculator.c:497 #, c-format msgid "Use the %s Session Service" msgstr "使用 %s 工作階段服務" #: src/bz-safety-calculator.c:501 #, c-format msgid "Use the %s Service" msgstr "使用 %s 服務" #: src/bz-safety-calculator.c:511 msgid "Can see the non-portal service" msgstr "可查看非入口(non-portal)服務" #: src/bz-safety-calculator.c:513 msgid "Can talk to the non-portal service" msgstr "可與非入口(non-portal)服務通訊" #: src/bz-safety-calculator.c:515 msgid "Can own the non-portal service" msgstr "可擁有非入口(non-portal)服務" #: src/bz-safety-calculator.c:530 msgid "Global Menu Integration" msgstr "全域選單整合" #: src/bz-safety-calculator.c:531 msgid "Can display its menus in a global menu bar" msgstr "可將選單顯示於全域選單列" #: src/bz-safety-calculator.c:536 msgid "KDE Settings Integration" msgstr "KDE 設定整合" #: src/bz-safety-calculator.c:537 msgid "Can detect when KDE desktop settings change" msgstr "可偵測 KDE 桌面設定的變更" #: src/bz-safety-calculator.c:542 msgid "KDE Global Settings" msgstr "KDE 全域設定" #: src/bz-safety-calculator.c:543 msgid "Can read KDE desktop preferences like fonts and colors" msgstr "可讀取 KDE 桌面偏好設定(如字型與色彩)" #: src/bz-safety-calculator.c:548 msgid "Secret Storage Service" msgstr "祕密儲存服務" #: src/bz-safety-calculator.c:549 msgid "Can store and retrieve its own passwords using the system keyring" msgstr "可使用系統鑰匙圈儲存並取回自身的密碼" #: src/bz-safety-calculator.c:554 msgid "Desktop Notifications Service" msgstr "桌面通知服務" #: src/bz-safety-calculator.c:555 msgid "Can send desktop notifications" msgstr "可傳送桌面通知" #: src/bz-safety-calculator.c:561 msgid "System Tray Integration" msgstr "系統匣整合" #: src/bz-safety-calculator.c:562 msgid "Can display an icon in the system tray" msgstr "可在系統匣中顯示圖示" #: src/bz-safety-calculator.c:567 msgid "KDE Connect Integration" msgstr "KDE Connect 整合" #: src/bz-safety-calculator.c:568 msgid "Can interact with devices paired via KDE Connect" msgstr "可與透過 KDE Connect 配對的裝置互動" #: src/bz-safety-dialog.blp:7 msgid "Safety" msgstr "安全性" #: src/bz-safety-dialog.blp:50 msgid "Details" msgstr "詳細資訊" #: src/bz-safety-dialog.blp:53 msgid "License" msgstr "授權" #: src/bz-safety-dialog.blp:62 msgid "App ID" msgstr "應用程式 ID" #: src/bz-safety-dialog.blp:71 msgid "SDK" msgstr "SDK" #: src/bz-safety-dialog.blp:98 msgid "" "This app uses an outdated version of the software platform (SDK) and might " "contain bugs or security vulnerabilities which will not be fixed." msgstr "" "此應用程式使用過時的軟體平台(SDK),可能包含不會再修復的錯誤或安全漏洞。" #: src/bz-safety-dialog.c:227 #, c-format msgid "%s is Safe" msgstr "%s 是安全的" #: src/bz-safety-dialog.c:232 #, c-format msgid "%s has no Unsafe Permissions" msgstr "%s 沒有不安全的權限" #: src/bz-safety-dialog.c:237 #, c-format msgid "%s is Probably Safe" msgstr "%s 可能是安全的" #: src/bz-safety-dialog.c:242 #, c-format msgid "%s is Possibly Unsafe" msgstr "%s 可能不安全" #: src/bz-safety-dialog.c:247 #, c-format msgid "%s is Unsafe" msgstr "%s 不安全" #: src/bz-screenshot-page.blp:5 msgid "Screenshots" msgstr "螢幕截圖" #: src/bz-screenshot-page.blp:61 msgid "Previous Screenshot" msgstr "上一張截圖" #: src/bz-screenshot-page.blp:71 msgid "Next Screenshot" msgstr "下一張截圖" #: src/bz-screenshot-page.blp:87 msgid "Copy Image" msgstr "複製圖片" #: src/bz-screenshot-page.blp:147 msgid "Reset View" msgstr "重設檢視" #: src/bz-screenshot-page.blp:158 msgid "Zoom Out" msgstr "縮小" #: src/bz-screenshot-page.blp:168 msgid "Zoom In" msgstr "放大" #: src/bz-screenshots-carousel.blp:5 msgid "Screenshots Carousel" msgstr "螢幕截圖輪播" #: src/bz-screenshots-carousel.blp:103 msgid "Open Screenshot Viewer" msgstr "開啟截圖檢視器" #: src/bz-search-widget.blp:57 msgid "Search Apps, Games, Software" msgstr "搜尋應用程式、遊戲與軟體" #: src/bz-search-widget.blp:96 msgid "Categories Unavailable" msgstr "分類無法使用" #: src/bz-search-widget.blp:97 msgid "Search for apps using the search bar above." msgstr "請使用上方的搜尋列搜尋應用程式。" #: src/bz-search-widget.blp:181 msgid "No Applications Found" msgstr "找不到任何應用程式" #: src/bz-search-widget.c:241 #, c-format msgid "No results found for \"%s\" in Flathub" msgstr "在 Flathub 中找不到符合「%s」的結果" #: src/bz-share-list.c:64 msgid "Copied!" msgstr "已複製!" #: src/bz-share-list.c:116 msgid "Copy Link" msgstr "複製連結" #: src/bz-share-list.c:127 msgid "Open Link" msgstr "開啟連結" #: src/bz-stats-dialog.blp:28 msgid "Timeline" msgstr "時間軸" #: src/bz-stats-dialog.blp:46 msgid "Installs:" msgstr "安裝次數:" #: src/bz-stats-dialog.blp:55 msgid "World" msgstr "全球" #. Translators: M is the suffix for millions #: src/bz-stats-dialog.c:124 #, c-format msgid "%.2fM Total Installs" msgstr "總安裝次數 %.2fM" #. Translators: K is the suffix for thousands #: src/bz-stats-dialog.c:127 #, c-format msgid "%.2fK Total Installs" msgstr "總安裝次數 %.2fK" #: src/bz-stats-dialog.c:129 #, c-format msgid "%'d Total Installs" msgstr "總安裝次數 %'d" #: src/bz-tag-list.c:96 msgid "No Results Found" msgstr "沒有找到結果" #: src/bz-tag-list.c:108 #, c-format msgid "Apps Tagged \"%s\"" msgstr "標記為「%s」的應用程式" #: src/bz-tag-list.c:124 msgid "Search failed" msgstr "搜尋失敗" #: src/bz-transaction-dialog.c:160 msgid "Keep Data" msgstr "保留資料" #: src/bz-transaction-dialog.c:161 msgid "Allow restoring settings and content" msgstr "允許還原設定與內容" #: src/bz-transaction-dialog.c:170 msgid "Delete Data" msgstr "刪除資料" #: src/bz-transaction-dialog.c:171 msgid "Permanently remove app data to save space" msgstr "永久移除應用程式資料以節省空間" #: src/bz-transaction-dialog.c:195 #, c-format msgid "Install %s?" msgstr "要安裝 %s 嗎?" #: src/bz-transaction-dialog.c:198 msgid "May install additional shared components" msgstr "可能會安裝額外的共用元件" #: src/bz-transaction-dialog.c:217 #, c-format msgid "Remove %s?" msgstr "要移除 %s 嗎?" #: src/bz-transaction-dialog.c:221 #, c-format msgid "It will not be possible to use %s after it is uninstalled." msgstr "解除安裝後將無法再使用 %s。" #: src/bz-transaction-dialog.c:241 #, c-format msgid "“%s” is High Risk" msgstr "「%s」屬於高風險應用程式" #: src/bz-transaction-dialog.c:245 msgid "" "This app has full access to your system, including all your files, " "browser history, saved passwords, and more. It also has access to the " "internet, meaning it could send your data to outside parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "此應用程式對您的系統具有完整存取權限,包括所有檔案、瀏覽紀錄、已儲存的密碼" "等。同時也可存取網際網路,代表可能會將您的資料傳送給第三方。\n" "\n" "由於此應用程式為專有軟體,無法對其如何使用這些權限進行獨立審核。" #: src/bz-transaction-dialog.c:254 msgid "" "This app uses the legacy X11 windowing system, which allows it to record " "all keystrokes, capture screenshots, and monitor other applications. It " "also has access to the internet, meaning it could send your data to outside " "parties.\n" "\n" "Because the app is proprietary, it can not be audited for what it does with " "these permissions." msgstr "" "此應用程式使用舊式的 X11 視窗系統,這使其能夠記錄所有鍵盤輸入、擷取螢幕畫" "面,並監控其他應用程式。同時也可存取網際網路,代表可能會將您的資料傳送給" "第三方。\n" "\n" "由於此應用程式為專有軟體,無法對其如何使用這些權限進行獨立審核。" #: src/bz-transaction-dialog.c:270 msgid "Install Anyway" msgstr "仍要安裝" #: src/bz-transaction-dialog.c:547 msgid "All apps are already installed" msgstr "所有應用程式皆已安裝" #: src/bz-transaction-dialog.c:549 msgid "OK" msgstr "OK" #: src/bz-transaction-dialog.c:565 #, c-format msgid "Install %u App?" msgid_plural "Install %u Apps?" msgstr[0] "要安裝 %u 個應用程式嗎?" #: src/bz-transaction-dialog.c:573 msgid "" "The following will be installed. Additional shared components may also be " "installed" msgstr "將會安裝以下項目,並且可能同時安裝額外的共用元件" #: src/bz-transaction-dialog.c:574 #, c-format msgid "%d addons will be installed." msgstr "將會安裝 %d 個附加元件。" #: src/bz-transaction-dialog.c:575 msgid "Additionally, addons will be installed." msgstr "此外,還會安裝附加元件。" #: src/bz-transaction-manager.c:1150 #, c-format msgid "Finished in %.02f seconds" msgstr "於 %.02f 秒完成" #: src/bz-transaction-view.blp:95 msgid "App Add-on" msgstr "應用程式附加元件" #: src/bz-transaction-view.blp:120 msgid "Runtime" msgstr "執行環境" #: src/bz-transaction-view.blp:146 src/bz-transaction-view.blp:172 msgid "Install Size" msgstr "安裝大小" #: src/bz-transaction-view.blp:187 src/bz-transaction-view.blp:238 #: src/bz-transaction-view.blp:264 src/bz-transaction.c:342 msgid "Pending" msgstr "等待中" #: src/bz-transaction-view.blp:199 msgid "Ongoing" msgstr "進行中" #: src/bz-transaction-view.blp:212 msgid "Finished" msgstr "已完成" #: src/bz-transaction-view.blp:251 msgid "Update" msgstr "更新" #: src/bz-transaction-view.c:135 #, c-format msgid "Transferred %s so far" msgstr "目前已傳輸 %s" #: src/bz-user-data-page.blp:5 msgid "Manage Leftover User Data" msgstr "管理殘留的使用者資料" #: src/bz-user-data-page.blp:55 msgid "No User Data found" msgstr "找不到使用者資料" #: src/bz-user-data-page.blp:60 msgid "User Data" msgstr "使用者資料" #: src/bz-user-data-tile.c:144 #, c-format msgid "Trashed User Data for %s" msgstr "已將 %s 的使用者資料移至垃圾桶" #: src/bz-user-data-tile.blp:74 msgid "Trash User Data" msgstr "將使用者資料移至垃圾桶" #: src/bz-window.blp:107 msgid "Tasks" msgstr "工作" #: src/bz-window.blp:163 msgid "Stop Active Tasks" msgstr "停止進行中的工作" #: src/bz-window.blp:171 msgid "Clear History" msgstr "清除歷史紀錄" #: src/bz-window.blp:187 msgid "No Tasks Yet" msgstr "目前尚無工作" #: src/bz-window.blp:257 msgid "Refreshing Store Content" msgstr "正在重新整理商店內容" #: src/bz-window.blp:273 msgid "Curated" msgstr "粞選" #: src/bz-window.blp:286 msgid "Flathub" msgstr "Flathub" #: src/bz-window.blp:435 msgid "No background tasks!" msgstr "沒有背景工作!" #: src/bz-window.blp:493 msgid "" "You have a network connection but are viewing a cached version of Flathub" msgstr "您目前有網路連線,但正在檢視 Flathub 的快取版本" #: src/bz-window.blp:568 msgid "_Login with Flathub" msgstr "使用 Flathub 登入(_L)" #: src/bz-window.blp:574 msgid "_Manage Leftover User Data" msgstr "管理殘留的使用者資料(_M)" #: src/bz-window.blp:579 msgid "_Synchronize Remotes" msgstr "同步遠端(_S)" #: src/bz-window.blp:620 msgid "Log Out" msgstr "登出" #: src/bz-window.c:440 #, c-format msgid "%d Update Available" msgid_plural "%d Updates Available" msgstr[0] "有 %d 項更新可用" #: src/bz-window.c:734 msgid "You can't remove Bazaar from Bazaar!" msgstr "您無法在 Bazaar 中移除 Bazaar 本身!" #: src/bz-window.c:871 msgid "Updates Are Available" msgstr "有可用的更新" #: src/bz-window.c:872 msgid "" "The following applications are eligible for updates. Would you like to " "install them?" msgstr "下列應用程式可更新。是否要安裝?" #: src/bz-window.c:873 #, c-format msgid "" "%d runtimes and/or addons are eligible for updates. Would you like to " "install them?" msgstr "%d 個執行環境與/或附加元件可更新。是否要安裝?" #: src/bz-window.c:874 #, c-format msgid "Additionally, %d runtimes and/or addons will be updated." msgstr "此外,還有 %d 個執行環境與/或附加元件將會更新。" #: src/bz-window.c:876 msgid "Update Now" msgstr "現在更新" #: src/bz-window.c:891 msgid "" "The ability to inspect and install local .flatpak bundle files is coming " "soon! In the meantime, try running\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "on the command line." msgstr "" "檢視與安裝本機 .flatpak 封裝檔的功能即將推出!在此之前,請於命令列執行下列指" "令:\n" "\n" "flatpak install --bundle your-bundle.flatpak\n" "\n" "。" #: src/bz-window.c:1030 src/bz-window.c:1080 msgid "Can't do that right now!" msgstr "目前無法執行此動作!" #: src/bz-window.c:1155 msgid "Resume Current Tasks" msgstr "繼續目前的工作" #: src/bz-window.c:1161 msgid "Pause Current Tasks" msgstr "暫停目前的工作" #: src/bz-world-map.c:587 msgid "Downloads" msgstr "下載次數" #: src/gtk/shortcuts-dialog.blp:6 msgctxt "shortcut window" msgid "General" msgstr "一般" #: src/gtk/shortcuts-dialog.blp:9 msgctxt "shortcut window" msgid "Open Search Dialog" msgstr "開啟搜尋對話方塊" #: src/gtk/shortcuts-dialog.blp:14 msgctxt "shortcut window" msgid "Open Preferences" msgstr "打開偏好設定" #: src/gtk/shortcuts-dialog.blp:19 msgctxt "shortcut window" msgid "Synchronize Remotes" msgstr "同步遠端" #: src/gtk/shortcuts-dialog.blp:24 msgctxt "shortcut window" msgid "Toggle Transaction Manager" msgstr "切換作業管理器" #: src/gtk/shortcuts-dialog.blp:29 msgctxt "shortcut window" msgid "Show Shortcuts" msgstr "顯示快捷鍵" #: src/gtk/shortcuts-dialog.blp:34 msgctxt "shortcut window" msgid "Quit" msgstr "離開" #~ msgid "Show Animated Background" #~ msgstr "顯示動畫背景" #~ msgid "Whether to show the animated icon background on the home page" #~ msgstr "是否在首頁顯示動態圖示背景" #~ msgid "Calligraphy application page" #~ msgstr "書法應用程式頁面" #~ msgid "Download graph for Blender" #~ msgstr "Blender 的下載圖表" #~ msgid "This flatpak is verified by the original developers of the software." #~ msgstr "ć­¤ Flatpak 已由該軟體原始開發者驗證。" #~ msgid "" #~ "This functionality is currently disabled. It is recommended you download " #~ "and install Flatseal to manage app permissions." #~ msgstr "此功能目前停用。建議下載並安裝 Flatseal 以管理應用程式權限。" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Ahmed Najmawi" #~ msgstr "Ahmed Najmawi" #~ msgctxt "About Dialog Translator Credit" #~ msgid "AtomHare" #~ msgstr "AtomHare" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Azenyr" #~ msgstr "Azenyr" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Goudarz Jafari" #~ msgstr "Goudarz Jafari" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Jill Fiore (Lumaeris)" #~ msgstr "Jill Fiore (Lumaeris)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "KiKaraage" #~ msgstr "KiKaraage" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Lucosec" #~ msgstr "Lucosec" #~ msgctxt "About Dialog Translator Credit" #~ msgid "LĂŠane GRASSER" #~ msgstr "LĂŠane GRASSER" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Marcel MrĂłwka (Microwave)" #~ msgstr "Marcel MrĂłwka (Microwave)" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Pietro F." #~ msgstr "Pietro F." #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shihfu Juan" #~ msgstr "Shihfu Juan" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Shinsei" #~ msgstr "Shinsei" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Vlastimil Dědek" #~ msgstr "Vlastimil Dědek" #~ msgctxt "About Dialog Translator Credit" #~ msgid "asen23" #~ msgstr "asen23" #~ msgctxt "About Dialog Translator Credit" #~ msgid "renner" #~ msgstr "renner" #~ msgctxt "About Dialog Translator Credit" #~ msgid "robotta" #~ msgstr "robotta" #~ msgctxt "About Dialog Translator Credit" #~ msgid "Peter Dave Hello" #~ msgstr "Peter Dave Hello" #~ msgid "Constructing Flatpak instance..." #~ msgstr "正在建立 Flatpak 執行個體..." #~ msgid "Reusing last Flatpak instance..." #~ msgstr "正在沿用上一個 Flatpak 執行個體..." #~ msgid "Flathub is not registered on this system" #~ msgstr "此系統未註冊 Flathub" #~ msgid "" #~ "Would you like to add Flathub as a remote? If you decline, the Flathub " #~ "page will not be available. You can change this later." #~ msgstr "" #~ "是否要加入 Flathub 作為遠端?若選擇略過,將無法使用 Flathub 頁面。之後仍可" #~ "變更。" #~ msgid "Add Flathub" #~ msgstr "加入 Flathub" #, c-format #~ msgid "" #~ "Beginning remote entry retrieval while referencing %d blocklist(s)..." #~ msgstr "開始擷取遠端項目,並參考 %d 份封鎖清單..." #, c-format #~ msgid "Received %'d entries out of %'d (%0.1f seconds elapsed)" #~ msgstr "已接收 %'d 個項目,共 %'d 個(耗時 %0.1f 秒)" #, c-format #~ msgid "Waiting for background indexing tasks to catch up..." #~ msgstr "正在等待背景索引作業追上進度..." #, c-format #~ msgid "Completed initialization in %0.2f seconds" #~ msgstr "初始化完成(%0.2f 秒)" #~ msgid "" #~ "Bazaar was not provided a curated content configuration. Contact your " #~ "operating system's support channels for assistance." #~ msgstr "未提供 Bazaar 的精選內容設定。請聯絡作業系統的支援管道以取得協助。" #~ msgid "Apps Of The Week" #~ msgstr "本週精選應用程式" #~ msgid "Run this application" #~ msgstr "執行應用程式" #~ msgid "" #~ "The number of downloads in the last 30 days. Click to view this " #~ "application's download statistics." #~ msgstr "過去 30 天的下載次數。請點選以檢視此應用程式的下載統計資料。" #~ msgid "VCS Forge Star Count" #~ msgstr "VCS 平台星星數" #~ msgid "Remote repo name" #~ msgstr "遠端儲存庫名稱" #, c-format #~ msgid "Released %x" #~ msgstr "於 %x 釋出" #~ msgid "No Flatpaks Installed" #~ msgstr "未安裝任何 Flatpak" #~ msgid "How the application looks" #~ msgstr "應用程式的外觀" #~ msgid "Appearance" #~ msgstr "外觀" #~ msgid "Show animated background" #~ msgstr "顯示動畫背景" #~ msgid "Type to filter" #~ msgstr "輸入以篩選" #~ msgid "Exclude results with proprietary licenses" #~ msgstr "排除具有專有授權的結果" #~ msgid "Advanced" #~ msgstr "進階" #~ msgid "Debounce input to prevent instant replies" #~ msgstr "對輸入套用去抖動,避免立即回應" #~ msgid "Share" #~ msgstr "分享" #~ msgid "Open this link externally" #~ msgstr "在外部開啟此連結" #~ msgid "Downloads Over Time" #~ msgstr "下載趨勢" #~ msgid "Minimize Lower Bound" #~ msgstr "降低下限" #~ msgid "Maximize Upper Bound" #~ msgstr "提高上限" #~ msgid "Installing" #~ msgstr "正在安裝" #~ msgid "Updating" #~ msgstr "正在更新" #~ msgid "Removing" #~ msgstr "正在移除" #~ msgid "Transactions Will Appear Here" #~ msgstr "作業佇列將顯示在這裡" #~ msgid "Halt the execution of transactions" #~ msgstr "停止執行中的作業" #~ msgid "Clear all finished transactions" #~ msgstr "清除所有已完成的作業" #~ msgid "Browse" #~ msgstr "瀏覽" #~ msgid "App View" #~ msgstr "應用程式檢視" #~ msgid "Go Back" #~ msgstr "上一頁" #~ msgid "View curated applications" #~ msgstr "檢視精選應用程式" #~ msgid "View the latest on Flathub" #~ msgstr "檢視 Flathub 最新內容" #~ msgid "Up to date!" #~ msgstr "已是最新!" #~ msgid "Confirm Action" #~ msgstr "確認動作" #, c-format #~ msgid "" #~ "You are about to remove the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "即將移除下列 Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "是否確定?" #, c-format #~ msgid "" #~ "You are about to install the following Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "Are you sure?" #~ msgstr "" #~ "即將安裝下列 Flatpak:\n" #~ "\n" #~ "%s\n" #~ "%s\n" #~ "\n" #~ "是否確定?" #~ msgid "Resume the execution of transactions" #~ msgstr "恢復執行中的作業" #~ msgid "Pause the execution of transactions" #~ msgstr "暫停執行中的作業" #~ msgctxt "shortcut window" #~ msgid "Refresh" #~ msgstr "重新整理" kolunmi-bazaar-7b9c8e1/screenshots/000077500000000000000000000000001514314607700174225ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/screenshots/categories.png000066400000000000000000005111411514314607700222600ustar00rootroot00000000000000‰PNG  IHDR@ #Ź›-tEXtCreation TimeTue 10 Feb 2026 07:49:47 PM CET˜tEXtSoftwaregnome-screenshotďż>‘ĘIDATxœě€Ǖ÷˙=°źŤÝ3Z`Yś,ƒĚC;qě03^ř’\.Éw—ť0;x‡cŠCŽŘ‰™-3ɲŔb–VZިŻ_ÍôLwMuwőěŒô~öhg^Aż‚ŚWU'Ŕ0 Ă0 Ă0 Ă0 3ĆI€a†a†a†afŒĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘g4 †a†a†a†éŒ`F˘¸Ŕ‚Ă0 Ă0 Ă0 Ì~F” 2RÄ=†a†a†afě2ěbČp QśĎ" Ă0 Ă0 Ă0 Ì<˘ˆĂ&„ —¨` 1źŇŰc†a†a†a˜Ă™J bˆáçP V†a†a†a†^DÂ*ĘĄŹö(q†a†a†a†D{”¸çP &"GŘo?Ă0 Ă0 Ă0 Ă0ÉĐöŰĎVQ… Eč°"¤ ŰĂ0 Ă0 Ă0 Ă0C'ęzÂŕťÉďŠRmŃŔDě0@x4Ă0 Ă0 Ă0 Ì ÂFp„}"ŠTŒjŠabF-Šdg†a†a†af蘏ß$vDBŞ"‚TC8ˆ2ę#ę_żm„نa†a†a†‰ŽéÂĽbˆƒňŹ• ü„ Ýߥˆ üĘ\†a†a†a†Š.ŚŻŻ-Gô0DtżË&Ę4m%LŃ}iŇčň‡a†a†a†a˜čD™úâüÍş~Óǂ™áÄuçeš6”J&Ł>Ôď~a1=ŚŮ/ŠĘ0 Ă0 Ă0 Ă0‡ÓEOUáĂąůü0Ÿß‘ęÓQ~żŐ[ěˆů¤WˇĽűÍ0 Ă0 Ă0 Ă0Lĺ{Ő-}œűxˇčaÁ+v%­ßŠ)W)wԇŸčáţîT˜ú× Ů6Ă0 Ă0 Ă0 Ă0Ő#láÓŹćŻ[É"X ńŰŚ[řPEcĘLĹáĂůXĘw TËîç Ă0 Ă0 Ă0 Ă0ŐĂ-Üë‚řěpŚČ8)éĺŽ5´žëF…Ô&“É×°řÁ0 Ă0 sřB#ƍk36 ś¤6e†)—ü˘¨ŻążÖ˘8˜B]kÔ!˛ŕĄ2Ôɖ~SbÜo‚I.ZtäÉétz<+Ä Ă0 Ă0‡/4ߛ[p›2 3H# ­€4äf8"ˆ{–‰şGŮD‘lƒ^‰ë.§ÄÔÔԜ@ó†a†a˜ĂšúRS“3ś 6Ľśĺ…QfěAÓÝrÇîĎzMŮŹëŃč Ú÷‡:Ёň"ÍŔţz'JG}^ÍÁýv(öPü(o‡q~ŤS_ H2™XÚßĎE†a†a˜ĂşˆfĆ&,€0Ě؂„ĆĆFščąBHü¤OSS#č^ż§§§l!„úúÚĽ(žTEŐĘ=´á&#@tk|čÂT[AšūD3 Ă0 ÞЍn™ą ˇ-ÌhăććhSŰH(ĄOWW7úúúŇ H3€WüőĄ„ M˜–JźpÝo4HAšą,´ńŤo†a†a_âńJ\v2#n[†444D?ÜPZĘ#*¤f€Ň5?üŚÂ”MĽŽV~Vz; Ă0UDzŔż˙ýođťßýZ~gĆ˗#ŰőÉ'Ĺ-ˇÜŒwźămôúľBřk_ű<účĂř÷˙¸úÉ0Ěčă˜cŽĆ˙üĎăĆ˙ŒťďžýëŸđ…/üŽ>z†a=4ňƒŚł ʃň*?Í Lk¨ČFL0Y'„ď†u{ěrŹ\y"N:iĽźfĆ$~\wÝŐ˛]é­ ĚÇg>ói|öł˙QˆsĘ)'ĄľuŢűŢwă_˙ş—_ţJ@ŒMÎ;ďüć7żÄ˛eGĄRP{ó›ß(Žc 4gýŸř8~üăÚmz.&L˜ §fLœ8/yÉyřż˙ű>ţńĘx Ă0L:.eä‡ ĺ5„c­‰ŽPśÎP­ŤşŠ˝Ś†aćPóҗ^Tř~á…çŁ\ęńą}XŢH?ű쓸óÎŰđo| łfÍÂhäsŸűOŹ_ż˙ő_ŸÇh„FučNĆozÓ1}ú´ű¤IńľŻ}7Üp]ŕ1-ţGő˘űźđÂs2ŐýŚ: mmm…ź‡z÷üMćC7†cŃCĺ|ôч|ăŹXąÂżNöěűA¸Ű|ţüyÚ8W^ůüż˙÷9;Ď ĺďĂĽž‡“~ô#śhyúűűńӟţ W\ńjœqĆŮöß×ČßdżâŠËń‘|QyŮË.ĆUWý wÜń/yL˙ţ÷ŻÄńLJ‘Âď~÷<đŔ˝8á„ăÁ0ĚČÇďş!ěS-Ş1ęľĚ<ŐőD+ÎPËĐĆ0 3* )/\đ’Âď /ź°Źi0---řăŻÇ>đ~̝;GÎmœ9s.ťěĺ¸éŚż`ńâE8|řĂ˙&O˜ßúÖ7p¸sÔQKľváądÉßt4lţŞŤ~ VŻ~O<ń¤ç3œ žŮłgƒ)ѓűŰZFâ #÷Ýwżü}ęŠ'ŁR|ë[ßĆŐW_c ŸwƒŠ>4ZĎ?>řÁŮűě/ąmŰv¤R)űď6ůűßţíĂy䕑ŚĂźóoÇţçŘljĹ8xđ |ŰÉqÇ­ŔwżűmŹ\š Ă0Łz â÷ś—Ą@yV`Ä]Ĺő“ˇŔDĹ†aF54ýeÚ´âh-Ž<ňH<ű쳈M­8âˆ#°sçNűbü#xüńÇĺpěŻ|ĺ‹8űěłđío]ô2” ‰2ź¸t4vî܅ ôĂ;wíÚ囎^éöűß_>üáÚ‚Ĺ0#=hřăŽ[YGyäQycLBX{{;öďߏĄňç?˙U~†JšűúávŒ éjÄo~ó[űxýœ6Î3υOú38pŕ€´7_úŇ˙bŊcqňɧćÝŰۋ!RQĄÜ şWá˛řÁ0̨âWżşŞdháőחŢčţőŻ,‰G‹¤úAëK\ziNÜřÜçţKŠÄŢ˝{í§ˆŸĂÓO?ƒÁÁALž<ÉA.ůýío)¤?ňČ%ŇśzuîâÜ=íáâ‹/ƒއŸüäG2ŒN<ä MąyěąUřůĎ"âË_ţ">ôĄĘď/ů%ž‘4ĽƒĘ˙ÔSÉüh8÷œ9ĹQššôĂŞUŕá‡ď—ÓGF;×]w˝ÖNíńÜsŤľa÷ß˙.šäś`ő]TZ ŒÖ#¸ďžťd[ßvŰ­rčH™2eŠg¨ëíˇßZ2ŠçÜsĎÁ­ˇţ]ŚýóŸo(´;Ą›nń˙÷CiŁőMܐđĂ~O. KCű/˝ôŒe¨źęhz˘˙裏ɺ?ůä“P üŚźŐˇ3Uę?ţăSrÔMĄ˘‘KA}…pŽ#t,řÔ§ţÝžŃBŽZřß˙ýoi§é8:ßčć}Ź@â5qË-ˇĆťőÖzâ‡AďÎ:.==š‹x$~řĂă ox3žöľŻâŇBíóˇżý_üâ˙HÝÄ šfuőŐż•‹łŢxă_d[;ý‘úÝhЇöoĘăë_˙Ş ŁQƒßůÎ7ńĎţC.ŕLö#ŽXPâďŹY3ńŁý@Nšźá†ëqţů/Ă0LakUmŘđ˘e÷ýďWŻčXő˝ď}G^ƒnÚ´iHyG@§9”Ľ?Tň-0 Ă0ي2W¨– é[¸đyŃLCŻďşË;ü}׎ÝxĹ+.ˇ‰WĘďQůŸ˙ů:::°yóyÍ5ż“' ţó_Rh9ëŹ3ńŰßţJŽ6Ą:7üăŸĐÝݍE‹âÚk/×< 'ßkÖŹ‘7Pd#ą… ńă}ď{<Ńщ”‹/~)F3żřĹŻlŃç×ň]ó$~|čC•Ł<ˆŽŽÜ“Í›7Űĺ˙ ýä÷­výź€j@ď˙{ŃŮم?ýé/ňľq´fĚG?úaôőőĘör ś|řáUžôßţö7䍕‡­˙ře-ŘJâÖ̙3ąuë69]‹ň=ýôÓp¸Qœs މI}żúŐWČý›F(ô÷ö7tţśˇ˝k׎ł×}řĂţ(í4ꏎŽN~_°`F˘Ď7ţ czIěŢ˝'0ž3ÚK7%JGOO-.çDl¨h§WżúUůcălٲU†ÍŸ?_.žJë‚Đ“Ňőë×ăœsΖ6g¤Ńë_˙:šůJBMGÇ~)€ŃZC*$dţńIq˝ŻŻÓŚMĹç?˙ŮQťîĂ0‡éÄG?úqyܡ㝏ž÷˝+ĺydǎvŘ'†”wD*˘9Tz Ă0̨nn?őŠOŕÍo~“ń:tĂyíľ×ŮOVżěÇ:;; 7֕âŰßţŽÂMČńţ÷]]Ýx衇Ľíž{îSxHůĂn‹{Ň(żüĺFűĆëÓ2]ē@C‚Ŕ•W~_ÚčI%-ÖřÖˇžŮ>ąýŔžP­´ůË_•sçiM“ż˙ýFŒfH(řžˆŸýěr” ÝŃČw}ýëßÄwÜ)G~Đ(¨ĐÍQ___á÷Ÿ˙ü\wÝ´qż˙ýŮuz‹ý”÷ŚÂâŒ_ýę—äMÓ7żůmŮ^Ż|ĺe2.}§§,Nß">űŮϲa* ˝î“Úš.NÖŽ]‹(ĐÍÝ{ßűůF‘ˆöŚ7˝ÁîK÷âpâŢ{ďÇ'? ycYMLę›DΗżür{ßĂúŠ-8w饗áů狣‡Ö­[/ßxtć™gț,'d’hzđ`'Ć ´6'Mš$×üđcňäɅřŚüç~V.œJőM}H|ú׿nĂWžň5)’źýío•O:éüđłŸ]%ÓŃčJóŞW˝J.ÂJmź{÷nť}ž— 4Jcٲehnnöló'?ůiAŔ˘ă3ĺ}÷Ý÷ŘçŹÜ[Ťhš%-ŔKšjépÓM7Űńż,~ČŠ>N<ńx)ę2 3r(wAÓjL‰Ĺ‚݁é¸ő|?řÁ•ň:ƒ k(ZW‰DĄä=°Â0Ěa =Ľâ;î¸Ëž™ř˛|jÄž}űđéO˙'nżýŽŔxÎüHş Ľ‘"•Anşéď…ď4Ľ†žň^tхrN;MoqÖ/ rčźš€žÓÇÍźyó0uę9Ç˝=sîšç>űBţrŒfčŠ:€Ą‡tłDOOIđH§Ó2œFČÜyç]RđĄ×gҍMԅi„/źđ‚-^,–77$^,]š[¤Őt¸¨ł¸&‰8ä'Ýü65E_qÝݧţöˇ›ĺ šnhýXgőęŐríj ڗ†ő–‹I}Óžćˆ„i_yńĹ=âqĂ ”Ł h” ÎHŽëŻżc‰ÇBN7˘EŹI´ő゠roöО@ńmář śŔů-[L8AŽžŁŠ%ôŞÝT*mŸGţÇŢ÷sŻLÍk^-?nœé…š'¨óäHéÓ§Ëă­CMMŇsŽř׿n/|§‘=9Űmۗžô­Ż<đ üKBě /Ź•b† 4Ş™Ž›ĺg4ÂĂ0‡=ôTîUŻz îşëvߑ 4zŕݏۡo͏.:iôݜĐ[%îžťřd—^­ú“ŸüXnÇy L¸§. tnÔ š–BëBĐM;ÝŘĐ(š=oŢ\‘N§äßď|çʒiôäٍŰ/k”Ov¤EuCÍiMšîↆ“¨đ˙ţß# 矑Ń"¨$ŽÜpĂľr)ݸQ;аyZˇÁ÷͒{ZÓ~Ľr8.şHuřŔÉuvN;픪 :ÔúvďçQú ݌ŤĐ($šŇF#@HüŁăÇh”ÓX‚Fź‘B –Rт§*Gu”mCőMńM˜3gŽ<Žďß߁ż˙ýR§ożđ…˙’}…Čdru˙ӟţÜWžđäA ńÉO~Â>n_j×˙ťţďˇĎ wË)+:Ü} ît~dža†Ÿ‘´j6+GjŒß.§˝Ě;§pn¤4ćř7űáţŔźG•Z„afTł|ůňŔi0t#š|ůŃ0žÜ:OyiÍZŸ é ´b6ýŚ‘!4lĐYTŽ#q„ !Ó&\rÉËňŰř’}aýrJ‹:ŒÚšv?)Śu/Z€.âéCŁ!h* 7;v씢 á,ćJ#"Fűşô¤]‡ŽžŠn*ůJ8ç×Y;†4¤Zş˝âŠ×ŘÂĚ7äM‘_ş¨‹ˆ9ýĘíC}oůňc´q_ö˛‹ĺ_ę˙N{“ˆw8rß}÷ÉżŐ\$j}›ö?hM š:Aű0­ëCÜpßĆÜÍ1­—rýőűî÷ž÷]źýío“Ł,H@š1cŢńŽˇË‹ušţGSœľ; QUüŕäkp^ÔvΨ gĘ˝› üiš}čBÔvŠTî)éůççFŸüŰż}HN]2…âäM#N>˙ůĎÉ).´ž Ă0ĚP\éaŰÜš9ńƒúĐwA譆CÉ{8ŕ Ă0(ŢčA‚ĂÍ7˙&üď˙~Q^,ÓpgzCGooęëëä…3,řČGroUĄ `z= QŚ•ýiže"‘4چłŘßťßýNyb˘›6u „3ďűœsΒo}ůä'?ýč˙äM?˝ déŇ#ĺö kzÂźqă&üöˇż—áôä˜.°g̘nű>ş5óDBżp­#JТ†ůȇ쌄|ó ÷üâż EĄŻý[Cz›3G–<¤ŮoźIހN:Už­‡FĺźôĽĽ‹ĚRűŃĆ÷ž÷můúÍkŻ˝Ţh{´ ' ´.Á駟*×= Ń=ş…iewz ‰|šéAô†¤ßŕpäŢ{s˝ Ćtú˝őĂ=,˜ÖwřĎ˙üźoü¨őMÓÜLúJ4 †öc:†Eý0Úřîwż'ą´F M ¤*;í$Ň\všÓöĘcIBSŮHL¤…HéM" JÄŐW_+˙ţú׿‘Çŕ7żů˛]I9ăŒÓóyäDç}űöJ1ćSŸú¤\›…FĺPۆ-^üË_ţJŽMCůŃہ¨ôÖ'Şq„aŚ\rŁ–ýŻ=.\(ףĹPŃ$‚řA"oXŢ# ÓŤY~Ë Ă0cşu.T ş¸źćšëäPf÷  p.zĂ !ϗ]v…|U" tóMkƒĐMě\l_üŽ“ńhm :‰Đ´ zrHĂŹé­$&ĐĽ´(" M¤ľ9hXśó& Zc€nvčt Ç˛iňş×˝QĆĽĹRé"œ„Wżúu…'’ßúÖwđă˙DúL (҈J?–Ą'Zű¤ĽeœAhÔ}§ľ5Ź!Î˙Ą…é)<]`Đ$ˆ|đƒ–í~É%ŰOůË5T>ó™ĎÉž2wî\Ź\y˘éćdżŁ›^mč)ô÷ż˙Ò79|ůË_‘‹FŇë:ŠŻ’8çŹ#p¸ąmŰvůT‹ösgäV4€Ä&çv1ľžMűJ´ž„ł6у>$ß,2Ąă5Źx÷ťß'§śŃ›śHČÜłg\ôő˝ď}ż|u-˝˝…ŚśBűGŸüä§äş"ÎBÄ4Ş„„‘/|áísEN!!‚Ľ^ľęŮwHDŁcíťßý^<űěsů|>-§/Q8¨ťňĘď ŤôVš2IS{čNo˘ă7mĎ˝*Ă0ŁZľœO5p‹ř:N>ů4[Ü}›gŞ }'… %ď ctąfŘ-xßťKŸ˜ëŻó‰ç?‰ü‡Ć뒔ԺbĹ :ó†aF—]ö |ă_•ßé—n:é& E3żň•/I€řÄ'>…?ýéĎ`FW^ůšžƒ ‰CK–x/ýţ÷ŻDOOˇý¤ö3`F7î FšsíüVż;ĐşoxĂë¤řƒücđîžűvšHňÇ>ö ůV¨áŔ™ć7ܐˆAÓahRzÍő[ßjžöăOŘ+ˆ†)2’ŢCđ_ÉŠż˝Ćô™BŻ ěąU'Ů_Ią§ëhřH:˙Éä?Y×G¸ţ:‹¸żCů.á)0 Ăöаdz:JoE !ÔîטŇČz­$M¸âŠWĘ7Ż0Ł“[nšEž Cnî~+‡=ą­Ť›3^hߌŠ?ÎçŻú݁޴qá…çGşhÉĐ4.q@âNj/nÔö÷Ă šCŁjžůÍŻÉQ" Ă0‡š‘´*AÓł+-€D}“ŢĄ‚G€0 Ă0‡ ´&Ë…GŚ´ĐN˛Ž.I7Ě4œŢý*R†mĐ´:zťUCC˝œŢöŮĎţżÂş@ĂÁHÂTÂ0Ł›úúz477Ątuu{(šŔ#@†aŚÂĐ: &ŻŠŐ `˜Ńd:é¤SÁ0 Ă0a`‘[­CĄťť'˛řq(á×ŕ2 Ă0 Ă0U'“[ŻŢeŠpŰ2Ě؀fŚŃĺBi‡ňÖźCa†a†aŞ˝‘%Żěsfd@mË0Ě؀FoĐńô<ÓuAhÁSZóĂäőńĂ Ă0 Ă0LŐĄ)9•^dâW]2 SeHČ ĹŔ{zâr=Кš$ Äbš5Ô˛Yt:-…Ú˙GƒđáŔĂ0 Ă0 Suč"yp0e_H'ÁŒ¨MYa˜ą 4Ľe¤Ok‰ŻÂ0 Ă0 ĂşťËŸ[ΌL¸M†M°Â0 Ă0 ĂhČôÁƒ`ĆԖԦ Ă0Ł@†a†a˜CM—ŘżżCN`F'ÔvԆ<ő…a˜ŃŻÂ0 Ă0 ĂRhÔŔäâzôI&“ˆÇůšÜH†^uKo{!у…†aF+,€0 Ă0 Ă0ĂßL3 Ă0‡@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ća„a†a†a†a˜1 Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ća„a†a†a†a˜1 Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0Ě('‘H ™L"ŰŸ,‹>†a˜ňB؟,2údJĽN§Á0 ÌnXa†…ŘQ[[ƒšš)x0 Ă0•ƒDdˊ#‹KšŽŽN "ƒƒƒ”˘Ă0 3ú`„af‹Ĺä…xmm-†a˜C‰Íľľuň300€ţţ~dłY0 Ă0Ł@†aF $zÔ××óô†a˜a†ŽÇ4ŻŻŻOŠ! Ă0Ě耆a˜Q@CCú`†AMÇfš’ŘŰŰ †afäĂĂ0Ě§ŠŠIÎAg†aF$NÓôÄîîn0 Ă0#^9afĂâĂ0ĚȇŽÓtźf†aF6,€0 ÌPhh5‹ Ă0Ł:^Óq›a†š°Â0 3Ą!ŐźćĂ0Ěč‚Ý Ă0#@†aF4—œŢöÂ0 Ì>čřMÇq†afäÁGg†a˜F]]żę–af”BÇo:Ž3 Ă0#@†aFô:E>Í0 3şĄă8φa˜‘ż—afQ[[ƒrXžüźúŐŻÂąÇ.Gkë8ttŔO<kŻ˝O>ů†a˜C Ď{{űŔ0 ÌXa†AÔÔD@č ă'>ń1źęU—{ě“&MÄůçżD~Žťîz|ó›ßA&“Ă0 sh ă9 Ă0# @†aF‰D–mf˘#~ô÷÷㗿ü5ţţ÷[°{÷nLž< ^xŢúÖ7ˑ!€…Ż}í(‡E‹â¸ăŽĂřńíHĽRŘźy3î˝÷~tvvb¸yűŰߊG}ŹŹQ.&LŔßřzlŰś ×_F2´ âńLJ%KŁĽĽĹžŠęĹsĎ­ĆŞU Nc´Cĺ;ńÄdůš››ĐÓӋ^X‹|Hö9SH<űěłpÄ °wďŢߎĚ؆Žçt\ ű(Ă0ĚX†a˜B2™ŒŸŚ˝8âÇ{ßű<óĚł…°­[ˇág?ť =ô0~ôŁďŰ"ȸĺ–[# Gy$Î;ďl<üđ#¸ëŽťĺîă?ŻyÍŤđë_˙­,^źHŠEÓ§Oˇoş›ŃŐՅ‘‰Ż|ĺ+¤`CbÝءľľIAdΜٸîş?ŒúŃ=/yÉy˜={xŕAěۡ­­m8ůä•RtűóŸ˙jœĎQG-Ĺ…Gŕć›˙ŽƒJŰťßýNÜ˙žýƒat\g„afäŔ‹ 2 Ì˘.˜G˘A#?ünîž~úüęWż‘ßŐi2&,_~4žxâ)ů$žFJlŘđ˘}Cúg9aúôiÍЍ2 Bű÷\F*´ŽËäɓqíľ×É/ž¸=ö8Žżţhoo—BČhŚŚ&)G~üë_ˇÉţş}ű<÷Üsr4vihh0ÎŤŠŠI (7n’ëŕ0ĚpĂ Ą2 Ì,xĂ0Ě!ŚI{ěąň/Ý(ń܂÷źç]Xąb˘’ÍfKn@SřÝďŽöŘčFüĚ3OÇ´iÓ䨐őë7ȧîÎş‘=唓ĺS~z"JbĘÝwß+oV ZŤ„F:ГR™Aié&ߝ/M…xńĹe:÷ČʛFHPœÁÁA9J‚>AP\őAbBkkŤźä‘G=qœé5S§NłóeŢĎ>űœĽ@őb§ĽĽgu&fΜ)SÝÜqǝƣg–.]*…ő†ž~“ BuäŽ “zŚŃG˝LÖ÷?˙y„ČâôÓOˇójĂîÝ{äh!gA" ĹŻŻŻ—#P~x•Ź; ;î¸rúJWWˇÜćúőëa‚ô%ýlűöír”‘ǏĆĆF)\‘k׎“ÂÇ;ßůöBź|äCrűóçϗżĎ;ď\ůůŢ÷~ §ČP9iä AŻ+}ď{ߍ§žz ˇß~§´Íœ9—_ţJüô§?GOOě/'Ÿ|’œZFíJyßu×=˛˝ ę$BΚ5SĆ˝úęk°gĎ^̛7't’܍0˘v|üń'dy™Ăƒ¨Çu†aŚşřÉҖňÝRžë>1ĺĎęŚNţÎţţŃ;LšaćP@7—–eÇ˙ŕß'Ÿ.^yĺ÷ 7Ű:úűűđŽwź].Č÷óŸ˙Q é5tă7cĆ ű—@oo-Dx‡sӍëë^÷yĂG7Ó6l7ŠGq„č†űľŻ}ľŒ{ŰmˇŰ7šOcúô8ć˜e…)9tŁJë6Đԝ;ďźŰžqß.ý}ýë_kßčvČŃ$~,^ź .”ů4:bîÜ9xâ‰'ńŕƒĘzślŮ8Ľĺ„Ž“uFéHˆXšňDŹ[ˇ^Žlq źiŠ ­ľA~oٲMÖÝloÚ´É8ÝHÓ•żýí&y“LÓ4&Nœ GӄAí{ÖYgHĄC7˘ę‰ü&Lë™nŇ׎]/Eރ3Î8Músë­˙’bÎźyóě:‹ŐŤŸ—iN9ĺ$)ś‘8°jŐ*iŁ)+;vě”" Ő˙źÄÎď.)|ôőőŮBËyvú5F"ů@Ż Ľv7ŽEÖUwwOIŸŚđ+Žľˇqœ’Em}Î9gۂĚ>9•‰ĘKűőN¨^Hl a†5 Á‚Ä@ Łm‘H1ţ<ť7JAý—Ön Ž˛×˝îŐrT •‘úwîmK­˛O:ý€ŚRQüűďżßŽ—NšĎźüĺ—ÚśÇpĎ=÷JáčĚ3ϐÂőOćpÁ’ÇQ†a&z ącÇöŸŮ_é I™ü_úÍŽżĆđ†a˜Bńƒ8pŕ źqĽ§Ň$řAÓ'œřQĄ›ČkŽšÎža\.o6錐něiTşĄ#čf‘D˝őÖžl˙ăˇâMozƒ| (¸úękĺ ­ł %˝˘÷•ŻźLŢ°Ň 3AOôď˝÷žÂśIH VÁâÜ ßxăM˜:uŠźŮwltÓęܸҜH Ą'ř4úAĽ%q†ŚőäŇěśëć€yrď˝{=qŠ^éÚčí݆űîťçž{ŽźĄvʇFe<˙ü)äřÍ×젋ÂŠŁ ¨>Lę™ÚŠŚ˜tĂ~ꊧHąƒęŸ Q çwŽüN7ë$КŽ`ł˙٘2eŠœE âŽ7ôƒ„%(ýš5/ÄHÔŘąc–-[†K/˝DÖůD#iČďœÇÚâŘ]2o‚úŐíʕ'Č$^чPu YŽÝąmÚ´YÖ AÔżi´ ţĄ…~Š,$ꐨE#KęW]ő+[”é.äšfÍ,X°ŔS†ŐŤW„9‚üzüńÇeçę­CŽ\!!‡ĘĹŁ@˘×†a˜ęÂĂ0Ě(…nŽhJ˝í…<ő㢋.ĚÇĺ°k×.ůôœF#ĐM#=Q§őGŽšćZyS7iŇ$)˛źď}ď)IK7”$JĐ͉SŚL–OÎI¸!Üóă;;˝#6&Nœ(oŠÝ#č&Ôš1u T74eÖ•đƒnxIXpçC7ŐK—é`GÜěÜšSŠ@­­ă䈓84Mă´ÓN•Ł H,!!ęÔçÉ1 4ÂA­ëď˙‡R40Šg(>}ÜO¨)'>-śJe!QÂ-hŽ`ň /ŕ˜cŽ–Ó@h”ÄÖ­[ ŁR˘@íA B#UN:éDL›6UŠ:ŽިE#`H€Ł›LSAĘGÂÍěŮłĽŸ45‰D6šşB}ƒŚ(тł4 ȁD3`¨ORŸ&aú™őá†F„Đ稣Ž*؜×\SyTĂ0 ĂzXa†!Đ \”§…×^{˝@čUˇôśzňŽB7‡oy˛dŢ×]w=†Ý8ŇşôĄ<—,Y"G;Κ*ôôžĄĄŻ}íkä #ÝŕnܸQŠŻxĹˡW­'§4҃ň~םŢQ˛­3Ś{FÓĐŻ›XŹtćhX°nÝ:9­„nˆ_ýęă¤ÍŠť ¨ÎId˘éÎ ÝńŰßţ^~§uGčőąŻÜz6á÷żżŚä†ÝŚz{űđ›ßüNŠc$&Đ[‚hT őĎr^•LÓfh„ ‰´ŽŐYĽß6D"Ç '/E"ĂvîÜ%ĹjŞ_š>ĺ\´ýË.{šáBSWh¤€!Á,jjcet 3şá‘> Ă0# ^™‰af„@ QFÖu ›LşŁWÝŇ =ÝŔŃčšBŻ˙$;=mŚaý›7o‰”?ĺűo˙öš@¨şá§) Î4‹={öČŠtłë|č~¤›@ç5ł7Üđ'yăO7ňŞh ƒFVĐâ˘î¸´śĆ˛eG•ýfE@k\ĐÚ$"8ş§)´Ćˆšnă†Ţ|CÓ<ÜëqĹ!ß)œÖ´ ö˘Š$4݃֌0ĺŮgŸ•eŚú$膊5Ľm‹Ţš’Űnyőā˛,´Ťť}éw,–hZĐ Öşřío'%zˎ ÔÔĎČw7Îh Ú>6Ąż4JĂ •Ÿ„Ѝ7™´vä ˇ˙Đ~AbůOůS=:k{Tęă7ßü)2R|gjR4ĘGÝ/hżĄŃ’0D˘˝†Śˆ\ý 2^šő˝ń‡śIëżPßtDZ̓ZĽĹ_IœĄ‘F˙üçżät¤Yłfɛ|Ó2Қ24ââňË/“Ó…h*ÉřńíraZ*+Mƒ˘~Lőpúé§ÉEx)ošŽ˛lŮR)LAâŐ˝UĆY‡…Úžú3Mk!ц 5ErSˆxň¤ý…D@j::öËŠ34ú#l ËC­ÂË_ţ29"‡FM9o˘)BˇŢj6ŠýĐqa†9đ[`†aF4ށnÎŁ@7l÷Ý÷€\ГnŠé):ýݡoż~˙ĺ/W]ő šđ"ÝŔŃZtăj˛¨&A7näÝđѢ—tsK7Ÿ´&ˆł¨*Ąé”?­Ű@ScčF‘n"iꍬ ›HšŞA jŇSqşŃĽĹJéćšF‹Đš´ růž(§yœtŇJů—nbošĺŸ‚FRĐ ˛{M ň•n:iąK'hgŃR7ôúV@či?Ý(SŢšˇ€ŒËżĆv†\ä’ęŐq‡„ňƒFĐ =0Ą ôĆ*7ľ÷‡>ôA9:Ŕ™rĄkcZD•Ä ş'ąŚšPR;8‹Ń–[ĎÎpaŒD(-AÓ>ČŞ›ă_!×Ç ň9 ~ŇÄ(œŢŽCŁAh-g´ č[ßú)–čڞPŢ$ľľľÚe;Úţ%וĄi*$Ş8m˝eËY´ Z‡ŚŠŠwÝuˇgŠ őOÚ܋‘vttآĐ1Ň?÷›iH¤!a‰ŢnăLIĄ˛Óú)´8mL" •ö!{ČšŇD‹“ŕç×iÔ­CíEuLő@k͐ŕÂ#@č8ćL†a=‡ę-0–]'€ÄP*z8‚G"˙ĄąŤ´ ]ëŠ'(—t֌`†-A#8ĆŞřAPuŁqfŹCÇs?†aFźĂ0Ě‚†â×ֆ/°X$‚źůÍo3r8Ä}ôČ#‚a7řm? Ă0#žĂ0 3‚ őhí†aftCkű8 *3 Ă0Áđ†a˜ĂşXÖ-É0 Ìč8ÎâĂ0Ěȃ†a˜˝^ÓyĂ0 3ş ăwŘk’†a˜á†a˜˝"Óô5ľ Ă0ĚȂŽßüŞc†a˜‘ Ă0#>ÍSa†aF|ěf†ٰÂ0 3BéííE*•Ă0 3ňĄă5ˇ†a˜‘ Ă0#˜îînA†aF8tœŚă5Ă0 3˛a„af„CŐ<¤šafdBÇg?†aF 0 Ă0#VMŻTŹŻŻ‡eY`†a†zŰ -xĘ5Ă0Ě聆a˜Q]dÓ0ëşş:ÔÖւa†čxLŻşĺˇ˝0 Ì.Xa†EĐĹ6Ą‹ďÚÚÔÔÔŔ˛x6#Ă0Lľ"‹ÁÁAűř;(Gä1 Ă0Ł@†aF!tńÝŰŰ'?‰DÉdńxÜţĤ ÂÓd†aƇڎŕ‘Édĺń–F߼Ói0 Ă0Ł@†aF9tQÎć Ă0 Ă0  Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ća„a†a†a†a˜1 Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ća„a†a†a†a˜1 Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ća„a†a†a†a˜1 Ă0 Ă0 Ă0 ÌyXa†a†a†afĚĂĂ0 Ă0 Ă0 Ă0c@†a†a†a†ó°Â0 Ă0 Ă0 Ă0̘‡†a†a†a†aĆ<,€0 Ă0 Ă0 Ă0 3ćadBČĂ0fX–%?‡ ŢGĆŢ?fäÂű'Ì\őţÉä`ä’ÍfŃ>e6p.f->ă§ÍGCKŹX,AČ˙=ˆÂ?J˜W(_JňqE(7ő|&|ň(„ Íö”|ˇ§Â}Ńüö ­CĽT‡ ň1ňۛHďˇáö4yD÷EřćCűKާ˝{^āMaďsw o˙fĜýĽ Đ6çĚnÂçMĂĘă'bÁźŒoŻąˇésrĽ&+ Źŕ–va>ááţ˘âŰԇ ŁtCöw(i‡Ł~ĂúKĂŹi3Y}ąvszz/ţ~ßꏭťęűgűřYX´ôl̚{&Lœ‡†ĆVűâ1ćvMŢđ9ęl%E÷؄Aœź)ŕ8ígóţţq\_"—Iëżő_g óMg'+ŃNBs2RKUŃ2éÎgCđßźLŢÜtţ {_8€îƒ/bßî'°sË]čéÚrύ8˙źI8á¸v̟߄śśdáü)\ž ˇŻ&6á ×ÚňżmŽ|}mJžZ[5Ë1–ËfRŽá.›I9"–MÝVÖ>öwŚpŔ>gîZ˝›WíF×ΞŞîŸŒËŔnš~;ßcŽżÎ'ž˙$ňŸű“´?­+Vœđŕq¸â§žâÝX˛ňBO˜űB@(éDá%L‰+”/%ůˆ’­E·Ĺw<ŻcŐŽCŁ|Œüö&Ňűm¸=MŃ}‰Ţ÷÷<űOlžëŞŠ !ŽđńÁ÷,ĆĹÎ(ݰMřa'~ %­0ůęn6”´󭜿˘ź´ĂŕďwmÕ׼Pq!Ä>N;űX˛ěü˘Ę×kCđšŃÇŚë–Ţ8"<0˘ĹŇ8,~¸’™•Iw>‚˙ćeňćĽŸíŘ|Ö=űŤŠ !ŽđńţwĎĂK/œ"ˇ'<ţćţŽńŁÜ˛™”c¸Ë6Üm4Üe3)GIJ™nӃ;ń̟7öBHkë8<öŘŞ“ěŻěOĘţ ڟtţ“É˛Žpý-éŽßâ>Ű@tŸô‚HÝÔŠÓßŮß?€Ă:1sćexŐÇŻÄÄ =a,~řlO1„ű"˘ůíZ‡JŠAĺcäˇ7‘ŢoĂíiňˆîKy}żaâ|L9î2 vďC÷Žç+2löŃW]6?ůŢÉX´pœfĂ4á,~ %LŚcń#bÚáđ×[4ťo¸höt ŕ™u*śsÜËńŞ7} “&álŞä€ëľ!řÜčcÓuKo?ŰS ឈh~ű……ÖĄRŞCP‡FůůíM¤÷Űp{š<˘ű2´žOĂÝŰž‘Íŕŕć'†t’ }ô=ďX„˙řIJâ4’HÎâÇPÂD`:?"Ś]a1{<÷ÄÉHg~vߐ÷ĎSÎx νč#…i.îc„çˆbxŽ ;žřÚXüđfŕ›ÎĆâ`ÔĎŕW&onĺö3ڏ&M=ĹNŸÁţ=Oy˙|÷;ćâS_$÷{áÚŚpm“Ĺƒr wنť†ťl&ĺˆX6ÓíťÓĐţ8uůDűüšgMÇa)‚*„'U gäÇ—@s˘*ö|ľĹDá%L‰+”/%ůˆ’­E·Ĺw<ŻcŐŽCŁ|Œüö&Ňűm¸=MŃ}Š\ߟućť1iůĽr_+gäÇG>°¤4s?4á,~ %LŚcń#bÚáđ×'ěco\Œ×œ?{Hű'ü8ýÜ÷z7Ľp˝6Ÿ Ž/Z‹ŢŹ|ÓŮXüŒúüĘäÍ­ě~ćúrÄQďŔŒš/ŇţI#?>ôţ…l…ÇßźMŠ c›’Ö&\ŰőłšňőľŠ>›Ú*UŽá.ŰpˇŃp—ͤËfş}żr,}ĺĚ=cFŮű' U€VżŚ5?Î˰ř!ôyx~Ă[v3_D4żýÂBëP)Ő!¨CŁ|Œüö&Ňűm¸=MŃ}Š|ߟwá'P×> QWœ§ř´ćÇ˙űĚ1šĚý•šXüJ˜LÇâGÄ´ĂáoČ6żđŢe˜;­ŠŹý“Öü8˙’÷nJ9xm>7_´6?źYřŚłąřő3ř•É›[%Äçë’ACóĚ2ϟřÜgňó6Ľ.ŒmJ>Z›pm×ĎćĘ×׌úljŤT9†ťlĂÝFĂ]6“rD,›éöĂĘąü͋Ń4ĽüFĽęŔH…ĄŽJŠ-xjYŢF,~řlO1„ű"˘ůíZ‡JŠAĺcäˇ7‘ŢoĂíiňˆîKuúž‹cćéo“űœéIÂŮGiÁÓxœ§˝„Ľ3&Óąř1ípřk°Íẋ^ˇ°Źý“<ĺĎĄîc„çˆbxŽ19žhm,~xł đMgcń0ęgđ+“7ˇJŠ]Ł.8ň-eퟴŕ)íßÂľMáƟĹƒr wنť†ťl&ĺˆX6Ó훔ò÷Ż%/Ÿi˙dĚa¤ Đč~ۋ>ĎoxËn拈ćˇ_Xh*Ľ:uh”‘ßŢDzż ˇ§É#ş/Őíű㗞/GDFđŰ^ÂÓ‡G éXüˆ˜v8ü°ÍKNŸ.GDFđŰ^ź_"—I‡ĹW2ł2éÎgCđßźLŢÜ*-~8_&Ď< M3ýÁo{b9†ťlĂÝFĂ]6“rD,›éöËafœ8EŽa* †”şĹ'žçąąřáł=Ĺćˇ_Xh*Ľ:uh”‘ßŢDzż ˇ§É#ş/ŐíűN–œmęœbVĘŔk >>˜_´6?źYřŚłąřő3ř•É›[ľÄç÷”™gEÚ?/xÉd™VxüÍýeńĂ Ă]śánŁá.›I9"–ÍtűĆĺpŮfœ0™×Š,€TgˆŇŹĹÇm(ö|ĄĆ/üŁ„)q…ňĽ$Q˛ľČů”{ăîďKČöC¸/"šß~aĄu¨”ęÔĄQ>F~{éý6ܞ&čžTˇďťóh™˝"%ŐÇ\řĘă'–:UšÔÄâÇPÂD`:?"ŚËŹű•GĎćçŮż=GĂsŒÉńEkcńÛU€o:‹€Q?ƒ_™źšU[ü  ´O\ž˙ŞŠ@żšđŽk/lS¸˛eńĂ Ă]śánŁá.›I9"–ÍtűĆĺPlăľç}r,L%`¤‚8sü´ůšß(ö|ľŰŠÂ?J˜W(_JňqE(7?ÜńźŽUťň1ňۛHďˇáö4yD÷Ľş}_(ę'ĚËűĄnMő3ž`^ ‚#–šXüJ˜LÇâGÄ´Ăáďę~áĚÜţfşN˜8ŻäŕÝ烏&Ç­ĹoVžél,~Fý ~eňćv(ĢąeNţ§ŚÝŰʇϟ×ä)“(f݌䣾ĺÚ\ůúÚTŸMm•*Çp—m¸Űh¸ËfRŽˆe3Ýžq94śćüR@*KLĹihi‹>ŰS ឈh~ű……ÖĄRŞCP‡FůůíM¤÷Űp{š<˘űRÝž/”ô5ŃЊ(ŒoŻńĽ&?†&Óąř1ípř;Äş?.‰(44śz2öîóÁÇ“ă‹ÖĆâ‡7Ťßt6?Ł~ż2ys;Tâý›ŹvţlkOňĹŹ˘Ű„7\kË˙´šňőľ)ůŰ*UŽá.ŰpˇŃp—ͤËfş}ărhlôOMs´ó'cŠ8V,ć|-täb( FĄ5ž_\€ĹDČ'´•R‚:4ĘÇČoo"˝ß†ŰÓäÝ=Ÿ(ő­Dpžćö9u‹~Äb–_P ,~ %LŚcń#bÚáđˇu‹¸ZV1žwŸ>>˜_´6?źYřŚłąřő3ř•ɛۥ?÷ţNńü)ŠYRۄ7\kË˙´šňőľ)ůŰ*UŽá.ŰpˇŃp—ͤËfş}ărhl…ßrsB˜JÁ#@Ş…(펢đŚÄʗ’|\ĘͧÜw_Bś§Â}Ńüö ­CĽT‡ ň1ňۛHďˇáö4yD÷EDĎ'J}+‚ĘTš||09žhm,~xł đMgcń0ęgđ+“7ˇC-~”ţ0Cł*$7ś o¸Ö–˙hsĺëkSň5śUŞĂ]śánŁá.›I9"–ÍtűĆĺĐŘÔí3•‡j J;­(üŁ„)q…ňĽ$W„ró)÷ĆÝߗí)†p_D4żýÂBëP)Ő!¨CŁ|Œüö&Ňűm¸=MŃ}Ńó‰RßJ„ 2•…&?†&Óąř1ípř[­ş7ÄťĎLŽ/Z‹ŢŹ|ÓŮXüŒúüĘä͍ŏbůBlŽ|}mJžĆśJ•c¸Ë6Üm4Üe3)GIJ™n߸›vűLĹa¤ ÝoĄ ŢßBůR’+Bšů”{ăîďKČöC¸/"šß~aĄu¨”ęÔĄQ>F~{éý6ܞ&čžˆčůDŠo%BP™ĘB“‹C éXüˆ˜v8ü­VÝâÝ烏&Ç­ĹoVžél,~Fý ~eňć6œâ‡Ś:ańĂ Ă]śánŁá.›I9"–ÍtűĆĺĐŘüśĎT@ŞŒťó %@¨ńüâ,~ B>Ąu¨”ęÔĄQ>F~{éý6ܞ&čžˆčůDŠo%BP™ĘB“‹C éXüˆ˜v8ü­VÝGÁđcr|ŃÚXüđfŕ›ÎĆâ`ÔĎŕW&onŁIüPˇ%ŠŮۄ7\kË˙´šňőľ)ůŰ*UŽá.›I9Ę-›I9†ťl&ĺˆX6Óí—Cc Ű>SYXŠ"˘đŇ•-”/jggń#B>Ąu¨”ęÔĄQ>F~{éý6ܞ&čžˆčůDŠo%‚iż0F“ˆĹĄ„‰ŔtCš9Jǰ,ó´Fašp?*œś ‚Ž&Ç­ĹoVžél,~Fý ~eňćĆâGą|!6Wžž6%_c[ĽĘ1Üe3)Gše3)Çp—ͤËfş}ărhl&őČT@Ş„(üŁt^áý-”/jGgń#B>Ąu¨”ŞÜ:t_l†Ô!ÝŠUĆoř-č7LŰŢÄ=Ÿ(ő­D0­Cc4ńYüJ˜Lgzs.˛Ćé+BV–0˘ gń㌠Kâs,ŃŮtÝ҇ĹOVžél,~Fý ~eňć6bÄM݆!ŠŮ’kmÂŽľĺÚ\ůúڔ|m•*Çp—M”nߤljxŮĺ¨rـCßFŚŰ7.‡ĆfRLĺa¤ ˆÂ?JçĐp´q?!ŸĐ:TJľ]™Öa.m> !eű ż´~kăům⋈žO”úV"˜śýP`ńc(a"0]ŘÍšţaÁŰ- s÷‚1_?aÚ°$>ǝM×-˝qXüđdŕ›ÎĆâ`ÔĎŕW&on#IüĐTo ˘˜=DMxĂľśüď@›+__›’Żą­RĺƲe…a9 ˆ0ŸaنłLˇo\-J=2•…j ě,ÎÝÁE`ńň ­CĽTQę0+Jˇ§ÉĂë‹đĎ'Wfî7 üÖlŻŹś7ńEDĎ'J}+Ęmű(°ř1”0˜.čć\ŚÍĹ n`‹ö'ß´štžŁB4ů˛řqӆás,ŃŮtÝ҇ĹOVžél,~Fý ~eňć6šĹWö…´BgŢp­-˙;ĐćĘ×׌äklŤT9†ĄlYąe–Í‚A9*\ś‘ĐFŚŰ7.‡ĆĽ™ĘĂH•ĘĄ š¸‹ˆOh*Ľ2­Cş¸ôńEč.<˝˙äOV‰/ŋVËť˝bpÉö‚ý%qËk{_Dô|˘ôY%Bšm?†&Óůݜ mçq„Áv]AŠ@išŐáÝ^‰˘äËâÇ!L†ĎąDgÓuKo?góß ĎŞXś‘ŇFŚŰ7.‡Ćľ™ĘĂHĘĄ óéŘ,~DČ'´•R™ÔĄsń dšuE ŞCwž´mĘÇrÝŞxę[š#cńŁřŤÜś‹C é˘Š:áĂÁć“GóČçcÁŇćç7-†ĹęŚľĘŘS…ćGĐńEkcńÛU€o:‹€Q?ƒ_™źšąřQ,Ÿ@ˆÍ•ŻŻMÉ×ŘŚú\n9aٲ" ŽvWˑŐŘ +Gś¸ŠźÚáöĎŮ>ŹĘ—m$ľ‘éöËĄą•ŰG˜ĘÂH5ގ+”/j§fń#B>Ąu¨”ʤ5⇀fÁSWáýGنĽřa•nϲ4ۄßší•ŐöaučhœI}kňPűb”ś‹C é˘ˆŞđ!„OZeC–°´iŹüxÝÂ8+Čhú[BhýŠňŇFl7? ß=U‹ŢŹ|ÓŮXüŒúüĘäÍm$‹A‡.?„+pĺ#bË˙´šňőľ)ůŰTŸË-Ç!,›VüȊ’rd‡P6¸my1D(Sśü|GƒTŞÝ†ŠLˇo\­Ü>ÂT@Ş…đv\Ą|Q;5‹ň ­CĽT&u&~d•ól™lŮtĆN“AáÂÔ>3ÄăöneĹ‹çw/çM0BČ'ÓFőčˇ(‰[^ŰĂŔ=Ÿ(}V‰P‰ś7F„ĺ'Şć>ÚĹí͌şśŽ'k‡gě}LţÍ{÷sMIł˙Ćě}Š.Ââq ‰x ą˜•Űˇňo‘qtÂˆ‚Ąč6™Xü¨nÚrÄ]~AÇ­ĹoVžél,~Fý ~eňć6ćÄW>"Š-˙;ĐćňŰ׌äklSęDkAeË M9„(IŁ–Ă™ŚuΝd˟éف<ćĎĄ2ßÚt˘8eŰí3ůe…•eśŰ0ľ‘éöËĄą ľ0•…jŕęôůŸž/j_fń#B>Ąu¨”ʤńC=.A ">R@×>,^÷ŽŘřŚtŒÇŃŻÁÚ łń̂ąnái¨mh)œ@šJă™#Ď$šő@|ý%qËkű°:ôF4Î'JŸU"T˘íaů‰*„ů„uńCÝoә,úű2賐ęl@źfęĆ/„Ř•ÂŔú¨›7 ܇îľĎ!ŃGrfu jP?Ť ľ $q)Ž8ůş…’i1ÂĺôęW”—6bťjńcűhĐńEkcńÛU€o:›ąřĄÜ)ř–I3ĘąGúŻł—Iw>+ˇM|l‡ŁřáÎW¸ň ľĺÚ\~űڔ|m˘Ô÷Ń,~d•rP=0H§łňĄA:•EC\ %a?”łcŐ&-ŘAöG` cĄ3 Úżc ű=D°˙Ę=Ő˛4ýŚř€ĎńÉł6HĽÚm˜ÚČtűĆĺĐ؆ÚG˜ĘĂHşď˘4LţvE(=č˜ĺĂâ‡;ž×ąĐ:4?čä’čCýŽőxÉ#Ć ›ŸB2›ńř‘ĚŚŃh‹#ăˇ>ƒ“ěĎsĎމkÎz;Äԅ°bq×pÂüHŸ:ô÷[”Ä-ŻíĂęĐŃ8Ÿ(}V‰P‰ś:šÂj˘T<Ě'|,L{)ÉE#~8ÂǁƒŘ܀Ú}3Ń~ň…hXy¤|Rľó—żÇž?ވĸĚzĎŰ1éü—`p×něýËÍčźőv¤@W[ Kâ¨[‘Ŕ¸ńu¨­‰{ö1+żg$ˆĺňÁBĄőTX”Ś gńúÝSľąřáÍ*Ŕ7m(â‡ČŸ-+ŽńżT|dń#Čß`›P6PN™†zîŽ|D˜-˙;ĐćîK~6%_c›R'Z›I9QŮJďü1@'~HŃ#ERh´Cڎ$P_Ÿ„° ŘœËT{Ź ößş˜…Ć„@ŇčëĎ`gç 6°”d‰ş„Q ×: (ř,P2$[œ3¤vŚ62Ýžq94śJôŚň°RE„ňEíÄ,~DČ'´•R™ÔĄř!‡fŇHulÇyü§Ż EřđăČ=đÎ[ŽÄ_úďHNž›3ęÖüwaĽCôó?=zۇա7˘q>QúŹĄ2m?TDx&˘ a>ácq͏œe—öŻŽýčŰPƒĆľ30ů oBÍÜŮšxé4ś|ý{čzhâö*ŃÝm $[Q;{&j&O´wż.>{~ö+ >żąÇ썝gv݃ú’hoŤC<+4mîI•#D<ţZŚő †D¨`ťvâ‡.ŠĐwKo?ráŚJú?¤2éÎg嶉Ĺb>"̖˙hsůíkSň5ś)u˘ľ™”ă•-HüpçAçÎA[áčŔ´Ć8'ŐaO:†­iűĆnˆÚ+÷I؟l,'VdóçAýAçÇx"†‰ă“˜?čHáÉ-ýؗŁĄ1i?¸ł<ë€X"ˇď ĺ:VžÚ­đ˛´62Ýžq94śŠőŚâÄŔTĄ|Q;0‹ň ­CĽT&uh(~¤úĐşć>|čO˙‹ł×Ţg,~8Ěę܍WÝňôuď/8-„˛˝PżKă–×öaučhœO”>ŤD¨LŰž‰¨B˜Ořá ~P˧ŇlŰ҃ô_’˜ŇxŚţÇgŠâGĆűú•čYő¨}3/|zŸyΓoÍôi˜ţůOŁý5—#f‡'2q4=Qƒě˛ŘśŚÇž K÷5‘ ˘\íhoBë7 BۍĹčwOŐĆâ‡7ŤßtśĄˆÄŕ@7Nžs5NŸ˙sůÝϡÜZZ"Н͸LşóYšmâc‹âG9‚‹•/›‰řAűa&“ĹÁ}ýhƒ˜6šcőxś;†}śđ‘ś#Ľ˛ĘGg“Qř~ e˙ľ…Ë šqÁ\[Ŕě´LôŚ >Đ?Y¸ür-ÂZđąœvŚ62Ýžq94śŠőŚ*đ* ”/jfń#B>Ąu¨”ʤýÄ×Q‡ÄžŽ}8ĺ…;pÉ˝×ÁĘD> ›ľ%÷EkFëŽőčkg+ꉢRž×âý%qËkű°:ôF4Î'JŸU"TŚí‡ŠĎDT!Ě'üp?ú2Řšf-ˇŐaüťŢ…şĺË<ěřîŃűčăRôČíš­őż°¸řĹ ă^q1jgMÇÁŸü"•FM‡mž1ƒgô`âŃőhŹO"–Ÿ#Bg…ç 1Ž]-‹?´á•?Ômˆ0‹ŢŹ|ÓنşŕŠ3ű1ćˆţƒś°9€:YHżi/Ţý•*“î|Vn›řŘXü(Ś)śż-˙;ĐćňŰ׌äkl+é§âǀ-ę§öcŚ-|<ח@śÓ*Œô Q"?ĘĂůÍ3"Dä~Ű'@iKÓȐ$ÎXÇžŽ~ÜżľM­ő°âĹŃ …ţ&źŁAŤD¨LŰĂç‡)"<¨B˜OřX^óĂ˝ż ÚÂÄsýhź9މůWü°Ů˙翡灇䈚ú/ü!łc—ďśęV,GŰűߍx"!‡îĆŇę˙ea÷Ł˝čďwqVĂ×Ţ ?´á,~(żláqFɚů˙˛é4ŚŽ[‡š†8ję&4nśŸP§ áN‚âwď1Ą"eҝĎĘm‹%›,ţŠM8}$ŔćéK>6%_c›(ős,ˆ]ś¸80€l{#ěL˘×>Džň0"ŠŁAhąÔžt Măpé’:¤:şma3›óËí“R6í­Ymdş}ărhlë#J٘ĘÂH5PvŹ‚Y#%ž(MŽÍ‡Ĺw<ŻcĄuh ~Сţîœ˝°ǜ0H mTşż_ţ˝ĺydŇ)Żo~‹’¸ĺľ}Xz#çĽĎ**Óöţž˜aHT!Ě'|ʈB 0--vş}Mj˙’AűŰ߂š#xÂ{ŸY}×܀ÍMŽĺW§/ˆ qdwď†ČdáGÍŃKŃüĆ×˝´ŁÖÜnoóš ҕ]@=˙l5…SĂP^˜&œĹčwOŐĆâ‡7ŤßtśĄŠΏÁœšř&ů“ÖxÉâßap ÇĺŤ-’ŔťsŠŻÁvoĆă‚I™tçłrŰÄÇĆâ‡&˝+áś §Ř<}ÉÇŚäklSęDkS}6ľОůˆúŃĎ`ľŐ„ľÝ‰˛…Žŕ)2˘8-FäŢÓcŐŕÂŁšPÓÝmďי‚……XŐŠ0ّŰFŚŰmŁ[ĹúˆR6Śň°R%ÔNËâG„|4y¨qŤ%~ ôŔióbxĺÉӑ¸řBÔ~çk°ÚZQôd,38(ż7Đa6+G—„ű-źżQnۇա7˘q>QúŹĄ2mďď‹1báĺ†ů„Ĺ‘˛]”}Žúţöm݈ýšMgœ†ŚSVz“d2ŘsŐŻĺ6Hɉ q× ś^C˝g/‚¨;ýԝx\ţęÁţ¤mż˙>ˆ[ť ű_á8 |:\IyD`YË Ó„Yń#âNŞë–ŢýžĹOVžélĺŠY(Ł:˝˘‹gŻ-äłxĆóšWĹçŻŢ‹ë]y÷=wAXüĐۄ˛rĘd܇"ŕnBáśĺÚ\~űڔ|mJhmŞĎŚś*•-+ôĺ…ď÷÷Ł­6ƒ‡›°o0ć+`¤CGy˜ "Âóť+›Ä‹šQßŰ#Eçźéč˜Bo}ˆ‘×FŚŰ׌1´UŹ@_^ڞ°RÔÎĘâG„|4y¨q#‹JĹ ˛üďźř‘ěĂźś^yŇ´BšŘ˛#QűŁď 6g˘2ŘÓWřž°oîŤD¨LŰř2TDÂ|ÂÇęČĎĎüošúŇąÉ~*üL ÍŻ¸ɖfOźl?öýá/š…II)ˆ V~L~ˆ-†dvďAąĆ´\rQî5ÖůžMa˙†~鋟żĽĺĆe5ӄłřáŸŢťßłřáÉ*Ŕ7-PüČ:çĘŇŔń#˙up°§/ş nč+ˇM|l,~řĂâGĘŚ?2°ěëČťűšŃ‘ňŽüH—%j„ŘTŃÄBňqťł58oI-:w÷äwYá[ś’Š0ĂÔFŚŰ7j#[ĹúH@٘ĘĂHań#B>š<Ô¸›öâň7HÄöá˝/™ŽşÚ8´45˘ć_DâŠWŔ„žóľö ]<ŔoáýrŰ>Ź˝ó‰Ňg••i{_†Š¨B˜Ořá ~Í]])ôßكXCšN?Ĺóâŕ÷"ŰÓ[؞ĺȅR ‰ÄJ–íę‚ Í睫ŽÖŢÇłš 5űBŽ÷ž^t÷¤r˝2´~E䲆†iÂYüđIŤ6‹ŢŹ|ÓŮ´âG^x€kż;šČŠŰęyĘk߼úąlŽ÷ŐÔÄňُ˩1žŃVŃ_”Œ)”É-†¨ţę~ť*:r›řŘ?ńC“ Ąä!Âl.ż}m›‡ąM”ú4ď  7şJ g_^´ęąk VĄ#"~ř§/Žé˛pÎ\Îý˝…˛ÖńD†ŠLˇď×F&śŠő‘€˛1Ձ*ÁâG„|4y¨q#‰ÎE*~ĐY(Őšďńúş¤óžKźrˇ­ČŸg;ÍŤŚ'ŻĚ˝ŮÉIż~÷Řű¨ęŁpů°řĄ?d#?Ô,Xüđfŕ›ÎV"~h†R˙…÷řš-ž˝Lţ—Í ľn'Ćľ–ž%­Ľąő‰} )0ň!Cńäœßś×/ß2ĺGĽřÇ巉Ĺ3„kű"ČćňŰ×&źyŰÔn­ł)iŒm‡˛lŽé$Ží`G?bunŇh‹›||ҧ5ŁAâÍ­˜–@Ę˝ˆS6—HęÚ}yůn •ëë#eƒ+SYXŠ,~DČG“‡×Xü˘ôFƕ^8FáĚEčë܇WŸÔŠÓÇÁ”Ä+/EÍ×˙WŽ Ń1`?ĄVËóđ“Ż) ,Ĺ÷Šť|Sü.üv}ńoű°:ôF4Î'JŸU"TŚíM|Qsˆˆ¨B˜Ořá4ň#$ä+hűŸí•WhľG..3˜BďskdÜÜý‘(ěË4•,K ŸÚ7[™LVŽćČtwĂ”Ś•ÇËôt#Fy‰4Đ÷|Ÿ|ŻđsœĹm8‹Ęď[xœa?Jâă áHĹřňœ ݐ18Ћ• nƒ:˝śđf Ň4P—Î>î.XÖľMř•IMEůmâc;\ŏ¨§PáÚž˛šüöľ oĆś’ž‹Q#~d…żĎtmšĚ"‘Ä?ť›4kyˆŠ éБ:AÄ>§g-=Ť]ý#˛LˇÔFaśŠő‘€˛Šń˜ĘÂHŐ`ń#4L“‡7TüČ?™R/(s×EUţŚ*wňÉRú{ŕÜ%u8iŃD…ÖŠýżď#6s†ÇžDşŔc¨­CÇźă‹'‹~;N˘mV‡ŢˆĆůDéłJ„Ę´˝‰/B›1˘ a>ᇛřá„Ó<ćî5}ňF§nÉ’(ý›6Ë7&D‘ŸšAâG6'~ĐBÂôw Sę.yeQ ö§kMNŃű+ËRV˜&œĹC‹žŹ|ÓŮLŏ¹ŇÝ}Îôl$'b öá؏ÁsîC*Őëݖpű$J„Źâ‡+)SyXŠ ,~„†iňP㊎‹35ϐ['.ý͊‚ř‘˛Ÿ^91ƒKN˜ ´Ţ@2YƒšÚZ$kj'Jă̜†Ú}ąĺËňŰɢ˙ŕÁ’xONœ‹úćńđÜF°řaÖg}Ú|ŒUó ?ěF~ˆb8-:šŮe  ˆĺßĚâfpĎ^8sž‹âGÖ%~dňŸÜďlţŐŇ&ÄꑜÎČ?<6çܚ˙ž-ČÝĐdł´ÔďƄv˙}q|K’ńƒňź˜›2ăő-ëT˜%ž•ŒA1|ŽAŒÚÄÇĆâG4ň­wž›ĐÄSm›‡ąMíÖ:›’ĆŘ&aŮ4ĺ s çŹĚ îęj*˛"t”ÇP‘@›ý™;1‰ŢžÓFŚŰ7n#­b}$ l~Űg* U@(?„.L”ĆeńĂĎë˜pEň›ť\˛°š+ŽČ/ОéA´Ç;ńćłf@YŠ@Rc ľuőH$“čď°Ĺ¸BęęëĽ0⥼ľßţ*âŻx:ťä›§LönXń2ÔÔ7ÉíËľXü0볁žm>ƈ*„ů„V žŠŇ&ÄęĘĘ7ł8#<Ü"HŚŻż(~¸…úžÉ}Ü"Hz`Q°š ůŇÇęLŰyŤSD.kh˜&ü°?˘î¨BßuƒŽů(%‘´ç9ĺ Śăú"J2 >Néă Łř}™´âŠß…ăPŢîě6ŠÁ>?˙‹ ʜw‹ˇޑ(¤şéŠYĽś 1Ëm‹ŃJžÂmóô/›đćalĽŰmâ‡g] gżrĺÓەÂ~[`ܟŠëōaBČi)5b5čkŸŽ‰ ŃÝ2ݎ ÜvW˛bƒH“!ź`ńCÉ#ŔXĹĆTž˜ęĄt^Ą|ń„‰’¤Ú< aůJ„>ĎoOŚžˆh~ű…iňPăŠžĚœ…đćẘp†ć9Z¸-1¸ďżdęjJť?‰ńD˙ú׸ĺď˙ÄîÝ{¤rü +đĆ7˝ÍÍMčďó\(҂¨ą˝ąľëŰîôäˇfâL$ž`_ ĆK|s^‹+M.%ĆŹíĂęĐŃ8Ÿ(}V‰P™ś7ńE@ëK%e†ů„ŽÓ^Üńě%¨ĎđňçkűŤČď Ž˘`Ł8Îţn˙ÇkňÓGEůmâccńĂm†pů$”mڄ+,ŠÍ•ŻMIclSËQͲů”ĂiaŃ'ús Ÿfi7 O ňœEż[Öe“ż-űźł[1^áwŢ&›¨ˇPĚ<Ňž+Ź‘~e0éúv4ďz&wît|ńlŰÂÜś ďLĄa\­ˇ_‰ÜšZž^­ęśQXÝFn#­b}$ lŰg* ŐBx;­Pž(Ç 5Š6BXţŸ’0ĄĎĂóۓ‡Š/"šß~aš<Ô¸QÄ÷"!źĺ~Š|ůRŘGěÎÝřĐSĐÖ\•˜}CFâÇ?láăęß_W°Ó“ç‡\…mŰśăżţű?‘´oä]OĄéćj0•B͡žŒřO‰Ţţ$ˇś-z\uüĺh7ů;,y&pßŔ•×öaučhœO”>ŤD¨Lۛř"ěËe†ů„łř‘ĎŰÎJI$íyN9¨i㸞ˆ’ ƒSú8#@üp]qŚú°¤ţ÷8uńßĐ>šńúzRň>˜Š‹ęëěýÔŞwYěô5MžXłŚ÷ă›ďüW˛Ň‚ӍXVŮ.EËŚp`ű îZóRĎoOŚžˆh~ű…iňPăVJüČşŽ:îEPűşöâ-§NŔźŠ-Бˆ'08˜ÂŸţřWmřÖ-Űđč#ă¤“O´ ň,ÜŕÄßőV41˝˙ţYÜ6{j–‹FäŸ.˝íĂęĐŃ8Ÿ(}V‰P™ś7ńE ؗ! Ę ó gńŁHŒ€Ôd‘8ĐY!l$™Ě]lŐϚ™Űg Ă2rOb1Ť0"Ă5s,’BŰě8˜Űn~:Í`ƒ°Ĺ'C+RYBĂ4á,~ |ÜČG)‰¤=Ď)5m×Q’ađqJgäM{I&ëńŕö“Đ’˝'eŸGӔf[‡X}^Źm´÷;˙Wź˛Ë¤IŐ,ą[ńš[m˝młÂ/5é`٢‡ ‘)śHÓąy?xęHÜží,Lœäˆn' ľéĄm <˝BǸŸ…Ř‚ÎgŚeNńĂí“Pśhs•#’MŠ­MIclSËQͲů”Ý/˝1mĎ@Š)ćDŔüH UüĄ‚Héh‚௠łĹş9Kí]Ô+~8¤bľ°˛ţÂK-z&2]ňŐňVÜň–—G~”ŘËP6Śň°R„îťĐ„ ŸtÂŻ–˙§$Lčóđüöäaꋈćˇ_˜&5ŽŻřŇ2yÄšv@ţ ŮL>_â…gnmÁţœł°ÇŃ?,ű„ąw÷ű$Ôďgí ë¤bŮ7a´Í ˘:vÖé¸ćmĹS0ąe˘ˇü…×ßşÇţZ†mV‡ŢˆĆůˆ}V‰P™ś7ńE ؗ! Ę ó ?œĹ)ň)!™ˆc°ÝBíÖ^ ě܍äĚéR˜H§ÓH$ˆ75˘nöLôo܌Üţ“ëäF€Čů/ĹÝFäFV™2°żýŰwxÖI!/> Ó_|u‘¨íĆâÇÁǍ|”’HÚóœrPÓĆq}%§ôqFžřá0~ÂܸńăXˇçźę؛Ń>Ăńűe‡Őˇ Ţ0ÎŢq›KęoŠl•ƤStĐg“ľ…”ě -xŘçŃü”œto?v­íĆďV˝kz_‰ÉS—řoÔ&>6?tq˘!PLĘâG™ĺȊMŮ>XŇ>SWĚ‘˙m•ŒţpċxCZć-EĚGü /˛˝]šé8žŰ‰cbÍ ö§2¨ą":ĺľÔ:łBÚŃÚ(°n+Ô˙*ÖGĘč“R6ڞ°RE„ňĹ݉YüpÇó:ćÍӛ*~°Ń^;€…SăhЎŸ6Ů76 ű \c˙ˇo˘ę’qű ´…ŚúvLhm@ …§Ň~Ô7Ô JĽJnöˆ{[‡ű&c҂Ĺ#ż2íĹňnV[öB˜Qz#ç#4ýÄ'ŽP"TŚíM|öĺŸ D™a>á<ňŁ4ŹśĆŢçÖ ťšÝO?‡şŠ“ â}ˆćÇ wýF)zĐGüČÍ~ąŠO´­¸ŮY<ń´*3.$ą°ÁöŠxęł´;Łž,(á,~ |ÜČG)‰¤=.(5ßc‡ĎńQg 3rĹůĂîôSg.NjűÚđ˝{'á]'ü “gől¨łox:ĺG’ŹłuVXöS^Ť–Î}9AĘb߁H‘C䆂Q˝Đo[ě@ş/÷ÝĺXßîƒŘńb?|đmčoźÄ?ŚçC<Ń´6Ýá/´ „§Whă÷ł[ĐůĚ´L#Aüp'eń#Z9?ÔrČ7Ÿ‰ÜnrĘ4”ź=h-ˇ(‘͏ş(ţůŠ+Ţ!I[ü˜°`ŠżČi“Ţł čë Ýv)šŞ}¸đ–MsgUJéęV[ßş4†śŠő‘€˛ú¤”Š<,€T Ą|qwb?ÜńźŽ•ř퓉]{đňŁkqÜü 0Y‘n„Ăí#üĉ0sć lٲUgŮŃGĺF” Ę,•u[öŕgˇnŔ”%§ç-.ńĂYĘuk$\OýŰ>Ź˝ó‰RßJ„Ę´˝‰/Áž ü„(3Ě'œĹWţt‘•żGŞŤM uĹ8ôÜӋîǟBë9§K„ÄÜ릓hYą;Žý“Ü7h˙ŠYšýĆĘĎ'.8Lý$n6„śąďÎ{Šo“ą˙Śěk˝‰ÇśŘ>ōËŚ gńch7 á!6ő˜ĺÇőE”d|œŇÇáâ‡ËÖÖ> }ľoŔWď[ůCLŸÚ† ĹsVŞŠŽšď‰8uśRß Kîƒ']@ž~鞜B‡(O˛Š4n܋-Ű[đÝ?ŠqSĎE‹˝-ÇW+¤LşĂ_hOŻĐĆ1îg!ś ó™i™Ş)~h˛…ŏ •Ămł˙îϔN#Łŕ´ş–G~: ýŽ%ßÖ"GAwvvĘëcýˆKţŽmlŔ´EK?ölEj×fůźÁ?tŰŚďôĐ1“Ξ÷ĺ˙äęžG~—ðlLĺa¤ 勻ó˛řáŽçuŹÄo%÷Ű^úî›NjÄâúőÎč?œu m˜8ű2|ýqxë1?ÁâލhŢX:,>Aş{Ÿ}ňí”o5‹ŐÖ!^c?ňMÔŮ组R>ş[KŃŞŽöTnD—ß{°gC'žŢ~~ýÔ;1cîöššn­čmâccńCÇß‹*‡Ű–˙ۗő?żŃHzýŹ{:ËÄńăpćŠĹ¨ÉO3ëěîÁ#O<'ҕŽRü˜˝dŠźÖőŁg÷Vôí(Š%‹ň/ĺô9Q¸ŢUëZŐ#"´‘ĆVą>Pś@ŸĘĆT@Ş…Ň‰ĺwĄâŮĎoOŚžˆh~ű…iňPă‰ĘI'ţî\dßČD?ˆdMđô9˛c`sçÍÁżô_ř×?ďŔŽ;ĐÜ܌N8GsRöIĽˇˇˇä^Šo …Żüú4Î^iŸXę ~;ë 8e/źúVţ°BÚ>Ź˝óńŤďĐ>4Fď Dôp?üĂäˆűżqÍľh9ťƒë÷˘ăˇŁćő—Káƒöú[SSƒśÓNž[nύú PQ\Ő-€ |Ú"ńƒ.ţvţńoČĐE`^ü¨˜xV;šk žŠţ•Ĺ$œĹ2Ň% 8ĆřŮÔc–o×Q’ađqJgô‰"żş0łfq~ýl;Nß5θmӒ¨mŽGɛaʏL›íď—i˛oŚâ5 °Do^ô𮮴œ ´Üőľo˛:°gë n|ţBŹÚsfÍ_aG‰…řď?jR{~q„oă~b :Ÿő3”Ó‡„A›)Ť,~”QŸ˛ő‹`ŸâŚE~T†}ž<嘅ńƒhijÄĘGáGŸÁ`jĐ#TÔ55`ŃŇĽS˝î܊ŽíśřaL {‹Œ|&!JëL-[č: m˜ŐŁqilë#e ô) lLĺa¤(X~Ú(žŔ–˙§$Lčóđüöäaꋈćˇ_˜&5nŮÓ^č o_\ľ%zqę∉–ţä8“Ic`@ ­­Żyí垍“řŃŐÝU"~Đűď^}ú[DSŁ3lˇxó&ň)<âGţ‹ۇա7˘q>Qę[‰P™ś7ńE ؗ`żËFDgń#Ÿˇ•o6Q\Őýćzëʲĺ“q×1HÜx Ć]p6Ź ăóë|ä<îYŘů÷ĺlÂ@\Ű”™ŸgRü OÇěúăůWî )‚ôœÔ€“—N€{I1{ËSżrŐ‹e¤ JpŒńłŠÇ,ß8Ž/˘$Ăŕă”>ÎČ_óĂ˝^í_ُc˜9w%ŮՊ­OLĹł×cÂř¨™0Žxîô9‡ {ŸË`ńt—Ct䜘KŸíˇĎĽ›va_G~üđŰŃYs1ŚÍœ÷ŐëÉy3˙Cwř máéÚ8Ćý,Ät>3ęg(§ ƒ8ţ6Sň‡zĎś„+O2lJhmJc›P|ÖŮÔr”[6“r”-łőučů`C]ëJ§Ě46Ôă¤ăŽÂýś’ʏi°ĹeËlńŁŚĆ7Ď};śb˙ÖÍHX(yÝmĐkuĹ đ–ĂŇŻůĄłę  łz4n#­b}$ l>…”Š<ćďd"áî°,~¸ăy+ńŰ''ZÇŁ)Ţo´ć‡›DÜüÍňí.ý}čˇ?ýň;M{éîî†îŠäw7?‚ }ŃÔ65ďˇkE.)ŚśÚ>Ź˝ó‰RßJ„Ę´˝‰/Ážű]6"z8‹faVţŽŚĽŠł/œŒŽć>ěúŐ5…‘ôĄˇ)Őľ‰öśüëjiáҌ02™lţoîťnT8ÜymýÍľěěÎ/|šA÷ě8Ž:o˛}Á˜đřľ,~á,~”‘6(iŔ1ĆĎŚł|㸞ˆ’ ƒSú8Łpäü}›0i!ö'ނoŢ÷AlŰŐ€Ž­űĺËç<OČuA˛ƒ)ű‰łţÎYđt`ďAě[ł›vľăKw}ƒ-ŻC[űě!ůV&oáǸŸ…Ř‚Îg崉ŸMŰç‡R&C„âpĺ)P†MŠ­MIclŽíúŮÔr”[6“r„”­Î2ĂRŸá¨o˝&[9ĹAÉÔ54`ĹňĽr¤ĽťśmĹöM›ĺ_h6‹ü›˙¤56wźţÁLN¸ŹB9żYü`* UŔÝaYüpÇó:VâˇO>î<âöÁ|ő–Ř˝żŚtu÷˘ŚśQYçőşYyS%4‹ˇÝąj îx!öiGä_g›íĄŹůayn9XüĐű"ěK°ße#˘‡łř㌍°\|čű˛Ĺż¸{ť{˛ ZĐ'•NĄíœ3 BGśDüČ}čfËA.lj )´:ŸŽ7a÷Ÿo–ÂĽh˛//lĹÜ­žŃĹľ‰-óręĘjšv8úŠ&|¤‹ÚŹD°M=fůĆq}%§ôqF‘řá;ĺŇ;B‘"4ˇLFÓÔËńľ{>…őť§ŁcÓA vőŘ"Gé aJËOű$hZŒđŠ„žMť°çĹ.<žužzď§Ń6óRÔ7´*ůň)“Ľ=ü…śđô mă~b :Ÿő3”Ó‡„A˝Mł)#Xü(Łek´Jחóc •ÁÓ/n÷ 'äÔăÂIÇ.Em€řą}ëVl޸I+~˜"ş2ůëßŕ˛immäü>ÜĹÝń€:,€T?ÜńźŽ•ří“OɎoĹĐ2u>˙łťđť›ĹŁĎmFOßüxfÝvÜűÄßpşPëîîŇ.ję@7XYÍS­ç_܉_Ţś“ç+'A–ˆVńÂŇŹíĂęĐŃ8Ÿ(ő­D¨Lۛř"싁ßĺ ˘‡łřĄӎĘrÂPDÎ8c&ú/jÂś˙ű úöěőˆ­œ#‡özG~äßâ’˙MŻósD~űf‹>î<śüđ*deşTŔ€˝­“VN/ ÂřXčŔ2żbmZ˝´,~(żláqF÷ȏÜ—PâœcJÖ4b꼋đƒUŸÄ#[FwW ‰ćF[ěđމŐԗä‘Đ2ń:ÜôüKđťŐ˙ŽóÎE<^čż'Ą?ü…śđô mă~b :Ÿő3”Ó‡„A˝MW&Xü(ŁeŁî^˘đŔsąfËnßpAęjýŏ­[ˇaýGü9q#@üĐŮöˆĹcĄecńch}„Š,źH•`ńĂĎëX‰ß>ůřů’ŹmĤ%gᑝ[p× [Đßő&ľ$0Ú8̛юćúZěíǓkwcÍΜtätřŃŐՉŢŢ$IűSş;0˘GvíëÂׯY…I‹Î”k8ž…Š–fJŒQz#ú÷!%,J}+*Óö&žű­ď#˘‡łřać,€ę^ „ž×Ú7Pgž;ˇ܀mWţÓ˙ăcůŠ*Y$Ć5Łé„cqđUů]Čű\Ę'm˙C˘ĹĎäGh9űiÇ}áŕŞÇĽ°™ľďÓşĎkÁšç̖ŰTGŁäţzo°Ą–Ď? •ŤpZ?”ßśđ8ŁTüpíŒßȞšmš÷“Xłćë_¨ĹŇcžg˙H46Úă2ý¤~Ř6Ís4ű.*;8h‹%Ţő@bMőxp÷ë0ućň˘Sęl4Q\óĂňř_:R+´ „§Whă÷ł[Đų̊ŸĄœ>$ âčmş2EA ˜§(Ǧԉ֦¤1ś ×výlBńOgŤT9LĘfĺÎGÖ`Ö@‰/BůÜńÄZů}ŃĚIˆÂ†M[Ľř÷,nęźB×Ň.xšÍďŻÎwű‰öő&0ľ6^8ĆčŽYüZa* U€Ĺw<Żc%~űäS\š'VBЉÚz´ÍXˆqŮÜ PŞŻ/ôŔS@&݉DM-Z`ú‘íXłőQ¤ě'RÉď4>čÓP߀şş:¨ĐäAűIłz.ęíė~uĆÍ= ńDmŢo‹Ĺ€Ĺ2ň-/LŚ.ńĂ˝jŠOEA¤Ľą§˝tîúëFÄ~ý;Lyó BFËgc˙˝§ŃţÉĺë@„>ƒ˝˝Řţ“_猭Ĺ,<Ťg]4-MľńĂňť˛^WH¨eńC%Â*œvŘŏˆű¨nżÖ”ƒC”c‡É1SgěŹůá쓹˙Eń7Üţ[h?ÓgĐÚ9ą#^[k‹5ČŚčœçłćÇ@ ‚Ö‰÷–ŚF`âűœ)2vŽqŻ–ĺöR'…ţđÚÂÓ+´qŒűYˆ-č|ľM‚lÚ>_2i6ˆpĺ)Ęą)ŰŐڔ4Ć6áÚŽŸM(ţél•*G„˛%la V,E$ĘAÖmچçÖn*Y𴸸)-nÉßşWŕ:żíëíńíőĹ ů˛YJŮ\3ěŰČůÍâGia* OŠ2ÂőEčÂň˙”„ }žßž<4aBç‹Đ磍ŚÉC[鑞<œ›ŁX1ű)Umă8Œ›4 ç…) –cÂŹ#Q?núťöáí{Ž‚X{Ż'Ď[ĄŃ´(TsË8¨Đ›](ŽzO”śŸl}ó7w!3~jZň˘†î7‹_‚}‰âwŃäÉâGyažľ@P\|”~O߀3.ƒmx{oýga*KbńÔ̙•ÝQ˜ SüĐx,gę‹űłóę?a`Çn¤­,žÝ€S.™… m %âGÉ菈őŔâGĂ Óh ĘÁ!ĘąĂ䘊3ÄíH Qâżłżd2)̟¸ľőîËE;´Ś‰&űĆÇďľÔVn=Ďćě§Ĺu R=ůßĘ,řů<†Ĺ]˝-°âä)\żmĘvľ6%ąM¸śëgŠ:[ĽĘĄŘ´Ó@$šŁtŇ@ŚŰşŕÄx˘âˆ AÓažŰ°=żŃqÓÂGä?ţÓaěëDs[:KÄˊÔF€Y=ˇ‘ĆVą>°ř1Ęa¤Š×Ą Ë˙S&ôyx~{ňЄ /BŸ6n@˜&5nľÄËó†Ď?špŽ›_Œ)“ÄÜ}`rĎzô>rÄ`î˘+Iă@Ç~Ämń¤­mźg<0‘‹2 hŸ˙ňĆą-; MmSQŁpWĺýM~łřĄńE ؗ(~—úS6šŒXüˆŚŽ¤PDuďÓläŹKć`óîżăŕÖńhžř<Í`rŸ”‘[ř řݛś`˙Ÿn˛ĹŽ3šqňĽł1mRSѧńĂwô‡RV?*fˆv_WQŽ&ÇL}œ1ôśřgš„|WG´Ď›ç,ůŤ7ŁxMţŐ¸âőuˆÓJÝNDu6č]ÓŕŘš!đńßŮO-—˙,~hű|ʤٴŽrˇjSśŤľ)iŒmÂľ]?›PüÓŮ*U„”Íľż96E1ł˝Źčˆ“W˜ňěű‘Ăó žjí˘`K+ńžY7ˆÚ†dIŮKʛ˙ÇŻœß,~č둩<,€T áú"taůJ„>ĎoOš0ĄóEčóŃĆ ÓäĄĆ­¨řášRóÉÝQY–ĺú]ü›îďÁ ëoF_oýűvŁ˙‰?"5؏ŽýűdœÖśöźąJĽĐgßPÉ7M¸ˆĺ‡đţíî§qߌZ§.půc•^T˛řâ‹@°/ĺ÷ý!ĄÉˆĹňÂüDuqFĆOhoŔ™ĎĆŚçŻĹŔśÍrZKÝ Ç"6ib‰ř‘@„Gü i3{ŽşZîżÝg6bĺËgaúäŚüvJĹŐ_?)ߊ„˘ÝוƒC”c‡É1Sgl˝ęśG”Äq ”ô=Ŕ‚Yۊ‘ě4ňŇM,™ë}čŢČŠžˇš9e?|čVŢČd…úo^ŚüŸ8j›člfíäÝ@EÚaţ ƒ8z›I2E¸ţ:Ű ľ MZŐŚ¤1ś ×výlBńOgŤT9"” Š­Š­}čć́ äÉőŰpßł}G|żîśt4HÝŔA4ĆHÔ&†ÔFÎo?XLea¤ ץ Ë˙S&ôyx~{ňЄ /BŸ6n@˜&5nUF~”ÜĄXE‡ňNVAM/^UŐt Žă úkĐł}'zWߋť7Ęʆ†¤ě§Ţž>ôŮőA7Rž1öZÜ>¸×ÖÖĄˇ?kî݁Is—ç6íRď=#H|Ę^3ŞCoDă|˘ÔˇĄ2moâ‹@°/Qü.ő§l4ąřQĄ0(7UVQ˜pF…ĐT•ł.ž…u˙ƒťaŮOÂZ/˝Ŕ5 ¤řA")÷aÚďbąş~]<Ţłš°ň˛Ů˜9­9żM˝řá^kŔ´<,~T0Ě힎˘;LŽ™ú8‡řáÁ˘)Ÿ)Ěnu‰|2KŽţPIwuăŕłOŁwçAdŇĽ•ă~5Že ˜ç/ýiŒĄ˙ćeňćĆâ‡;%űPTŠŰa6eťZ›’ĆŘ&\Űőł Ĺ?­Rĺ(łlΚqľ ĚľR˜›ěDščD?îˇĹŒ0ťK:d4Čşľ˜9ŤąD~ýͨ–\ŮüŰ0ŤGă6ŇŘ*ÖG?Ć,€T MÇŽJ„ĎőEhóЄ Íö\Ž„Ç ÓäĄĆ=k~8žXî¸ęČ :‘d3hÚť ]Šzô ÔŁ{ }3ÎD&тş}O#‘é‘ö{řłŸpŐÖÔ˘Ś&7´o\K#ĆĎ\칓ÂsWU8‰üśtÓuÂęĐŃż)aQę[‰P™ś7ńE ؗ(~÷ĄHhҲř1ô0Ëň†ť5uż’V "ö§˝ľçźt&ÖŢű}¤z őÜÓko+ŤŤ•‡\1?Áޟ˙˝gśŕ[ü˜5­Ľ¸ ÍŢ­Š~#UíÇ @Ş€ĐýÎ˙S&4éDi>ęN |ň(† }>Ú¸aš<Ô¸‡DüpţąźátŁ“U3˘ąý¤¸ŠcúˇhÚ.~ zW?‰×˙u5hhoFíÚuśÂ~î꜆kĎA2.đßď˝3&ëßA6ĄA`coFžuĆ}kä űłÜkʈ×můźýűĽž••i{_‚}‰âwp2Ć'‹ s…;+ßĆgŃţ™żč+†šDŚZœ~ĆděÚűÄr;půJžŰíśçžg_,6ĎĹÄö?Bú‹QŘPҖť/†eŠ˘;LŽ™ú8‡Żřáز™4ŚľŽG]-,ł˙Ż)ä3Řсîukq°§˙\w6îÜrŚÍ>Ô öÔTÝţw\ąěf[đč@ÝÄ$ëóŻź-ź8ɟpۆˇŁśśIëży™ň_|â¨m˘ł™ľ“wi„ů+ âčm‘úĆŻ@\e(nŰcSśĄľ)iŒmÂľ]?›PüÓŮ*UŽrËŚřŒź BSJŽœŰˆőŰ,´ŮbaGŚĺvDÁ韨!\âG‰ ’?…Ňßş[œéÄÄ哋KŢĺË"OĂŽľű 6Wyí˛řaŢG˜ĘĂH•ŽÔNĚâ‡>nÉöź˙䎢sóçérî+íđÚ)S°äoAώ]X÷ƒŤĐ`5!c?JőőĄ6օÇ㦙ŻEĂřŮX>yĐ?ÚáÇxű:mCwś0oĚłp[ ßaučhœO”úV"TŚíM|ö%ŠßÁ}h¨°řQĄ0MxĚrľ—@a¤áADNijH˘iVńőÔ˘pĺŕ¤ń*~Żş-ÄJÜYü¨`˜I¸_ĺŕĺŘarĚÔÇańƒěĆyË˙8ë~Đnd?XčٸÝ;÷á@_ ~đŔ;0PwfΙ[H7}ö‰Řxpžr÷|pĺU˜˜Ú‹ŚÖ$ęŰęĺ@1ĐÔ×á¤#nÇ-k^‡Úš&íáĎŹLů/>qÔ6ŃŮĚÚÉťŠ´ ÂüqôśH}H—aŽCy!šÇ&4ńT›’ĆŘ&\Űőł Ĺ?MT¨e”Mž`˛ů´ŽëŮBš:šÇlىUév$,´ď„íĘP bIן‚ˆkDH3zđüó˝8÷Čvű°6áL/mÂé7bݡ‘ĆVą>ŒńŁĐo˜ŠÂHŽÔĚâ‡>nÉöź˙¸N ŧČň'q‚cö×AűÉRŞ!ƒ=k7áš_üVĎ8¤c1¤}ś„݆żĎ<ť&‚ łŽÄ@o'ŽšʞOlJÚ€i8ˇGŞß–Ű7Ŕ°˝ýËŻ„EŠo%BeÚŢā`_˘řևToŁÁâG…Â4áőPť*‚d˝#AdV˘7§’h„ü6YüŔ¨č&¨ÇŹR[đąĂ䘊Ă⇣HҨKćlśĹz9ő%ÝӃŽÖ˘ó đÜî#ń›'߂ɳÎ@C˛É˝)ůosË4¤ë_‰/ß7/?âœ4ű Œë?ˆĆI͈%c°RiŒoďąĎ§ÚßY™Š[ÔĹQŰDg3k'ď*Ň&óWÄŃŰ"őĄ|b{Ąˇ-Ü6eZ›’ĆŘ&\Űőł Ĺ?MőšÜr”[ś r8ç:űŠÁ⼹{Ő^l›1űŇĽ‹WÚ>­aŹ›CśĆŘ VŻ=ˆăZăhÖRxxAq=⇥/›ó›Ĺč}„Š<,€T áúGíŔ,~čă–lĎűO$żiń¨T]#öwŔ?ţ+šIÔ6´`O|<žœľ{ĆOG˔hkl•i˛"ƒĆšŕĚäqôö‰TaůŰ­üwË×řří)U`ů•°(ő­D¨Lۛř˘i3Ĺ`îwXŰŤŢFƒĹ …iÂUÝťd¸2jË3˘ EÁB(ď×ô‚ŏд#¤?Ł˘;LŽ™ú8,~8dlĄrӋ¨oIJńŁoÇôn܄ƒýMřÝă—c}Ďů˜9˙h;,îŢTŽ?ćď†5 ˜5ďÜş}Ű~ŢuÂo‘Iu˘Ą˝5-öCŠxg,ş n~’ÉƢż–I™œ-ęă¨m˘ł™ľ“wi„ů+ âčm‘úP>ąĆ˝PŠŰn›˛ ­MIclŽíúلâŸÎŚú\n9Ę-›ŽŽsžcŁÝ€ŢłbQ:7t">­ ťęp( Ó--vę?jcilŢx 0÷„é.ńĂ;Ý[¸GF+SÖMęѸ4śŠő`D‰ŞÁT@Ş€pýŁv\?ôqKśçýGŸOţěD+Ž!˛HقGËâ‡>nÉöź˙磏˘-/â蘜lŔśy+˛ŸPec1ÄkëQ—Źłä‰ü6…'ÄöČó›đŇSϖ†šâ‚ŤA~[auXü7¸üđ=™xÂBűĐŘ?TżM`ńŁBašđJůŰӓ˛÷šŹ6Œnn,ŽÚRG…R ŤU÷šđŃ&~Dż\wG &ÇL}?\Éä?ŮlS›6ŕŕSĎŁŤ§÷o>7Ž}=ŚĎ> ńD­Ćčm}ŚĚž?yb2N˜ô7\˛ä´ĽöŁś9^&OĘkxKËäÝ‹î”0ëCůÄş8QŽż,~T ůѐôöčÜĹ'3ŽhÇĘŐ{ńȁžíSčĹŃWŐdźŐƒmť°đ@ŽY1 őăj‹ţç˙ZJŮŕ sţ˛ř1´>ÂT@Ş‹FžŸŚË!#ż]k r$H< Ťm ęhˆ˛Č”{­GÁNÔÔáů­ťöubňxýkÇúR2oËšýpŢţËë‹ZŚ’ö,úâ_~%,J}+*Óö&žhÚL1˜űÖöţuh‹ ӄ›řşˆýuמġ]mç—ń¤mގ bÇÎqoŔ”‰ ŢŠ/đY'dţ)ŹÂiÇžřáĘĆđŘarĚÔÇańÕ,÷G'âť×`o~ňđ[љ8 sć/‚pZÓ*ŚqO{PŽ­.[Ü>'Ϙ˝Ť;ŚaÍ} đţ•żŔ$Z 5žĂ~ŇÜîNŁ-SÁË`˙lfíäÝ@EÚaţ ƒ8z[¤>”OŹ‹áúËâGů倥ć§N…ÉĎ!ą˙ĚZ2‰őxdÓl\8°÷ĎňßFĚŢî8tc—-~,ëꑜřŃŘZ_ô5­[?JFƒž˛ř1„>âś1•%Śâ¨•Ĺ}ܒíy˙’ß4Ľ….¸Dń=˜…mZ…9‹ôˇ¸¸bӔ9řŰ=ĎÁg^܃Xź&Ŕo“ś/F4Î'J}+*Óö&žhÚL1˜űÖöţu QfŘPҊƒ&ÝXůĄ î§żň2PĐ *”E>{ű,~„† %íPúC˘;LŽ™ú8,~¸’ĺöIűżtfG´=Чw-Ĺ˙Üý9ˆńŻÇ„I‹!”ÖŠSŚţk›‰şIŻĆďú,îÝt2Ž˙ŇéâyY[&on,~¸SÂŹ ň‰CËdĽańcčĺPߒRŇŚŽĐ`Ǜ:Ż §LŤÁŃO­EWs3ŚÖ˘9‘FĽďEß`?wőâ„T/Ž>q‹:[HŮ´ůeőuŚňđ*Ăâ‡>nÉöź˙D÷ŰYDŠĂÂúÂuÎ R[§ ŽůۊںÜóüóxS*š¤w×ČŘńn^ľ ‰ÖيŰsśaT‡^§ýËŻ„EŠo%BeÚŢÄM›)sżĂÚŢż#!Ę JZ`Ф;\§˝Ŕ5$żűR2íĹ2ß.‹ ӄ×oH^AÇ“cŚ>‹×"ÄńX[ťŽÄCű>ƒés—"Kř”[žTĄůŸLŇŠçáo›fa|S Ɇzż–+ĐűŇ6ŃŮĚÚÉťŠ´ ÂüqôśH}(Ÿ8´L†P?*TŐŚźáĐmŁó]ű´FœŘZƒńO­ÇÚÖVl^2 }¨ŰՉŽţ$Ę%n_ČśĹű°]Ô`_gKöŔÜIő˜źpş} °źž€ĹCŢG˜ŠĂHańCˇd{ŢĘ÷Ű.¨„ŃZnkaJŒšĄ÷ů YńŹ–Y¸óŃu8˙$ďZ żţŰc8›‚†xŇ㋥ťXü¨JߊĂJ †)LŚ;\ďŇQ•>`YđËP(ɲFTČ_ă° §=ŹÄ]RŸăŁÎ‡ĹW˛ߏXƒń#0uZ-œEQĄ;Ÿ Á˙œÍ„I‹ä›ŐbV̧LŢÜXüp§„Y䇖),~T¨Î?îŠ0ňwN˜Ě喹sÄJ‹ÖÔIbń‰Ó1i{7fŢó6ȌGÎŔ`m &ěًš}=ččŠ#˛Xj},Śš4:â58HďN< pÄŢ]˜‘˜zěDÔ5§ŘH÷TńÝŮXü¨^a* U‚Ĺ}ܒíy˙şß.ACÝŚ÷-1<ëX2ICË$üůŢU8ăŘů¨ŤÍ‰ż˙yÜúü ĆϞŞlCńE3„×SŞŔňŁôd˘Ćó‰+”•i{_4mŚĚýk{ł:bá‘ÂD`şĂ}ä‡C, djPĐfu /‰Řx żŐŞ{M8‹Ęď[x?\Ér˙¸ßŚ–ˇ%΍O~RYk~|łJű„ۧiĽ%eň>´ô?ŔfÖNŢ T¤MćŻ0ˆŁˇEęCůÄ&eŠŠpýeńٌr(6šžÖľ]רf)‚8ślÎ@ƒ2Ú§7aܔLßރ˝ˇ=Ž]M Ř9g"ö/š†žq@ˇ}îěJ!>Bíŕ€żŔ€HŘůděô}Š4R{ťĐşˇ‹ô`BKăś˘ą˝ŽCƒçUˇńĂ*˘ÔŁqilë#Ŕ¨?œßLea¤ °řĄ[˛=ď?ň;OaÍá łPźŘsŔ!‡ńšZôś,Ä{żúgœłb.śîé“;,Lœ\!_Ç źŕŠż/Qük{ł:bá‘ÂD`:?PXľm\îî^Ž)É ˆ!UČdO/ ™5ŘÚÎ]ZWHsČü­VÝkÂYüP~ŘÂă°řáJćő­p§ŁÄQÓ¸œ*Çł2ąřágóő_gË'.ŤBŽż,~”QŸ˛9úF1^n¤ťM bD^‰ŮO ĆĎh–ŸéúŃšszžßbkt7ÖŁ§ą);M:‡H§‘H Ôö˘ĄoM™ [jĐŘVŚS¨ÍßćJˇř!͎Ď괗|“z4n#­b}UâGĄý™ŠÂHĘĄ† M\€Ĺ˛ýö&Ę”]' OŤpjq†:ԏ›ˆÁÚSđĎuť‘¨›a‹Sŕ^ó‚ĹúĹď°ś/ŁŁ"†)LŚ;\Ĺ B%™ˆář‹ą~ó4¤RŢĹP“É8N=ş‰¸~oÝĚ?*Ś Ż”řĄć! láqXüp%ó9駐Âm‚˙febńĂĎćëżÎ–O\V;BéXü(Ł!esvÂMY§Ç3„lVqňwƒýЀ>ô=›É˘ż7Áž42é,2™4ŹűĘľ.†řřzÔ4´HÁĂ­}d•ůYĘ4RálWąąřá“/*×G˜ĘĂH•ĘĄ† M\€Ĺ˛ýö&*ńŰ5žĐ×{§$żŮŠzMý8$í4žhĹ×ĺż§Tĺ7đŰ'ŽP"’:t%đ÷%Šßam_FFE !m܀0Ÿč°?Saőja跏/,~(qa¨˜řĄĆ˘Ra"0‹ći-÷Ł,Ă´,~T0L^-ńC—6p×ĆańÕ̬L%qĐü7/“77?Ü)aÖůĕ*S•V”cË˙´šü÷ľ)ůjmJ=Ű*UŽ ”Í4ˆćí8îQYŸräł-ÄJŢŞĎN,~ä‹ęöڞ°R%„ú]ř„ ]şâ7 L“‡÷°?Üż!$+ü֕Éâi/%qa`ń# Ü(l(i#ć{(Ä÷SŹčůćó°ŠyĽŽş×„łřáŸ6p×ĆańÕ̬L%qĐü7/“77?Ü)aÖůĕ*“),~”Ł‚e+ âöŮYDé ~BÜţ9eSúwűWˆĎâǰőŚň°R„ú]ř„ ]şâ7 L“‡÷°?Üy¸F„řúRŽŻć!´žřćčwi\ĄDÖ:T ć~‡ľĹĐëpȈJ…‰Ŕt,~ř§UvCOXPZžö‚Ń× ś¸żkă°řáJfV&Ýůlţ›—É›‹î”0kƒ|âJ•É? ĘQĽ˛šŸhËáşN ›ö˘ľ)>ĂBäş5n#­bőč”M“O O!eÓć‹CÓG˜ĘÂH…\żďB׾'†Ç ÓäĄĆeńCŸGqĄTxćPúű"ôů  LQę[‰0Źu¨Ěýk‹ ÖašˆJ…‰Ŕt,~˜Ľľ\C~ƒóeńcHi‡Ť?´żë ,~¸’™•Iw>‚˙ćeňćĆâ‡;%ĚÚ Ÿ¸ReŠ‚P˙ [ţw Í忯MÉWkĽ~ŽńĂíł{AS‘um×´esçľnËĄąUŹƒĘ†đş‰}„Š<,€T QřÇőŰů.4q]{bx܀0Mj\?ôyD÷EDĎ'J}+†ľƒšßamQÁ:,QŠ0˜ŽĹhi­Â?iYü}ýÁ€ ý]L`ńÕ̬LşóŮü7/“77?Ü)aÖůÄŐ*“ •V„Ůňżm.˙}mJžZ›RĆśJ•cĘć^"+›5(‡b“‚ýöžĺÖxű‘ËĄąUʁ1'~ډŠ(,€TQřÇőŰů.4q]{bx܀0Ÿ…Ĺ]Ü żM|Ńó‰RßJ„a­CĹ`îwX[Tž##*&Óąř1ípř[­ş×„łřaˆ(Ý˙]ň?Xüp%3+“î|6˙ÍËä͍ĹwJ˜ľA>qľĘd‚pĽaśüď@›Ë_›’ŻÖŚÔƒą­Rĺî˛ŃÍŤnĂlAĺ0Ýžq94śŠŐ#0&ĹÇĆT@ށĐ~eńŁlż˝‰ô~nO“Gt_Dô|˘ÔˇaXëP1˜űÖ•ŻĂHˆ!„‹ƒ&‹Ó‡żŐŞ{M8‹†ˆŇýßő'˙ƒĹW2ł2éÎgCđßźLŢÜXüp§„YäWŤLQ`ńc„•ͤËfş}ărhlŤÇ€˛úR6mž8ô}„Š<,€TwŸeńĂ/n˜ßŢDzż ˇ§É#ş/"z>Qę[‰0Źu¨Ěýk‹ęÖáQÂD`:?"ŚŤU÷šđĂVüˆşƒŠŇýßő'˙ƒĹW2ł2éÎgCđßźLŢÜXüp§„YäWŤLQ`ńc„•ͤËfş}ărhlŤÇ€˛úR6mžž>ÂT@Ş„ťĂ˛řá7Ěoo"˝ß†ŰÓäÝ=Ÿ(ő­DÖ:T ć~‡ľEuëpȈ(a"0‹Ó‡żŐŞ{M8‹ćÍŻĹW2ł2éÎgCđßźLŢÜXüp§„YäW­Lš8AőŻPlů߁6—˙ž6%_­M”úÄâÇĐĘfş}ărhlŤÇ€˛úR6mžž>ÂT@Ş€ťĂ˛řá7Ěoo"˝ß†ŰÓäÝ=Ÿ(ő­DÖ:T ć~‡ľEuëpȈ(a"0‹Ó‡żŐŞ{M8‹e˘=&°řáJfV&Ýůlţ›—É›‹î”0kƒ|⪕IÇáJ/Üśüď@›Ë_›’ŻÖŚÔƒąMőšÜr wŮLĘąlŚŰ7.‡ĆVąz ([ O!e“‡X•î#Lĺa¤Š°řá7Ěoo"˝ß†ŰÓäÝœO6Ëň.Ąm\ßJ„a­CĹ`îwX[„ÔĄŽLQëp(ˆ(a"0‹Ó‡żŐŞ{M8‹e˘=&°řáJfV&Ýůlţ›—É›‹î”0kƒ|⪕IÇáJ/Üśüď@›Ë_›’ŻÖŚÔƒąMőšÜr wŮLĘąlŚŰ7.‡ĆVąz ([ O!eÓć‹ĐG˜ŠSXüđ‹ë|ˇ=YůÉfłĹď˘ř]Hť@ɅÍp‰yŸ‘÷‰~ĎiłđsZpܜd.LłÍŔúV"TŚí˝‰ôžhęP1˜űÖŽ:„ŚĎżü:,%LŚcń#bÚáđˇZuŻ gńŁL´Ç?\ÉĚʤ;Ÿ•ř*ňçÚ,ô× ůó„Y¸Ň™úďď/ĚÚ@s>+ťMćŻ0ˆŁˇEęCůÄU+“&Ž1šŽPŘŽpůhsůďkSňŐڔz0śŠ>ŁĚr wŮLĘąlŚŰ7.‡ĆVąz ([ O!eÓ拑ŃG˜ĘĂ#@Ş‹~qďÇۂÁ[OmE}ƒY|ôš=Z|ŮšáöBýŤCoDf.:ŞŻ[9Nš>řť8ГÁǡăč™őX6ŁoŘaťhyF‚ÖˇĄ2mďM¤o{M*sżĂÚBh}Qó1ó[ł˝’ÄQÂD`şĂAü¸üÁÖÝžŕ†şćLoÁ-ÄĹgÍóM”ŻIxTŻżĺ|ýČďţŢĽ˜6ąŠzuŻ gńŁ|Jw=?\ÉĚʤ;Ÿ ďo6>ű‘Š˜Đž”–Ÿýnž~žßî 1‡ÂŻxY+Î8ŠY†˙űś``žYđ/“wă,~¸SúűVçЉĽ{W0Ĺí —6ĄIŤÚ„7­MŠc›’ÖfRŽˆeűĘgîž=˝X¸tŢţá<ńűÓřŻýSÚN{É\\půbŻe–cÇćƒřĺW/}Űr,>nj`9|ˇ…2ŰHcŁnůůŁŘşz7ĆMjÄeŸ<Łź>vâ‡cc* Š2ÂůWŮŃäwĄ‹ŚÉC;ZF~d3˜’Éf<™Ýď°:ôF̍BąŸŽe҅8ŮtZ>5{pmúSYÜťŚÓţ-Ěë[‰P™ś÷&Ňű˘ŠCĹ`îwX[¸ęj˜>˙H}V! "J˜Lw،üH´ńϧ7•Äs/öâ ?X…üö‰ňň­†żÉXśôUS˝ş×„łřQAXüp'3+“î|Śń•ÎĂÂľ‘Wž´ń˜3$?J3›vůSŒĎâ‡.ŽŢŠĺW­L%žj2 A¸˙ć“Ú\ţűڄ7­M”n¤ßŘ&bľň{]˘ą¤l–ëŹ>Ń\ÜĆPĘaSŤ+ć›l ,‡ş­”}=űÝ˙]~îżim‰ĎĄm¤ą9ż“š:¨‰×–×G?˜ŠÁ#@ވpţUv4ů]čâ„iňP㎦5?žÝ҇/˙yłčrëŒ%öSŚ#Ç˰oţuúRtr°Ĺí 0űi”•ɍq]ŞËí9Ł-ěYĎĆŹb˜ ÎMYą\ˇ&ŋÝbÜb›ĺ ďäéLÓ)äg‹2Â>yÝţ\ţőtbśŸąd˝ĚÓʧŁm9›(ü–›ł<•\¸ ”ŰušrŔíźĺ/ą燾í5mŚű‰_\`ŘĹuĄˆ(a"0Ýá8íeْřčť/’ížqËüčW˙ÂŢýÝřÍ_×á’sçc֔ć˛ň­–żUŤ{M8‹e¤őMÇâ‡+™Y™Jâý14ëšÚ’§˝-‰óÎhÂ?îčąO‰ąœâr$+čaDĚĺ[ţü•ßDî4ęŒQĘX8ćĎĹV~O‘çźüy6o÷ž˝_‚Îgeˇ Âę[ÄŃŰ"ő!§~‚âä”UŚ_5"\~ˆ ›Ë_›đ楾)ő`lSňŃÚLĘQnŮ\čĘŚ†ŠŠ !ĺĐm+fE™Śds´6ŇŘÔíCóz<\Ĺľî˜ĘŔH•οʎ&ż ]܀0MjÜQ#~ĐE}qӓŠĄk_ĆH\Čŕ¨î∐{3v¸}d‹ –­&œť´Ż?šM†ýןvá-§ľaö„|óűđÂî´­œ/=şÇĎŠCkc\NMYőb?n|ރiKŠç,ŞĂO'ý|߯ˇăM§´bůʜJţđ‹}¸ćĄn dŹÜľ›izk Ż=ą §ÔĘi8XŐá@(#ť,ťh Nœßˆ=]i|řwť@#E~üć)hŞ‹áú‡;ąqß œ63y\Ű:ŇřýCxjkJ^\"?çúâe ¸ŕ¨F´Ůž?ˇ}?źm?ţ÷ňI˜ŘœŔmĎőŕÇwuÚŰňÖňś˝ˇâőmŻi3ĹŘOüâŁOüB4:\×ühޏcéĚ^ů}ٜńhŹżŸţŇ ö}K÷=śł^š@6ďčÂĎŻŤžŢ‰ŽžA9 ĺ˘3ćâ/_‚D<×§7l9€×}üfůý‹9›śuâşź€ÁTÇ/Œźĺ8̘œ{Šľžâ~"÷óď; /ËOš9Đ9€óßuƒüţ×ƒˇź|ŠŻďýiüň/Ďâ_lƎ˝=×Tƒĺ‹&ám—…#fĺŚĺÉí|ęfšÍŻ~ätÜöĐfÜůČźĺŇĽx×ĺË|ë‰Ĺ2ŇúŚcńÕ̬L%qD°˙Ž íŮ׏‰ăëpţ™íxřń^ě?Í%÷œlr§>ÚŕÂł›qě˛FŒk‰ă`g>ՋÜ~ĐŢǀ㏩ÇŰ_7Q&űŢUťđܚšáwžaŽłĎ×:3řô˙nőÂć& _˙üL÷Ž{;qÍ_äŐ_—žeRlCďC ŽŢŠĺW­Lşó´& Â凲šü÷ľ oZ›RĆ6%­Í¤C(€Ŕ˛ŠěÚօüĎ˝ňűď<{wuăá;6"ÎbÎÂńxÉKĐ6ĄĄPŽţŢnűăźđÔ.d2,[9ÇŽœWş]›ƒűűp˙ß×aăs{dşĆquXpôdœpŢ<ÔŮçÁľOěÄÍżxźöΛˇ?ŔËŢsůaţěܔ€V[4iłw'ZćÎŹ-äóÔs2^aħę/‹Ţ횔IwžÖ¤3&Ÿ\–Ú\ţűڄ7­MŠc›’ÖfRŽ ”­€ŽźŢ`űZ´¸/Źşc 6­ß[řýÂSöľăƃx×gOC}c-x\ý˝Ur͇Gďڄ};zŐ-Łó@~÷ĐŰ5 Óőuçž^öŠ×bŸ˛P9eťeőÔŐÔ ąŠŸůďˇâ'żů ŢüŽ—ĘđÝ[býS{°hůLüŕŞOŇ]pÉ)řŃoţs—L•#FîýăjéăQÇ,Ŕ×ô1|ő‡â#çČétţi5ҊܤńGţö‚ÜhM2‰7żçř̗ߋ'.ĹöÍ{JĘjRˇşöđÄ+§ßŒ >bjc* Ő@ŮŃäwĄâŚÉC;ZĹĄ$Ňîܞ bŒ_Ţš męNjű3öÍU'ÍĎ)Ó÷ŽîŔcűľoŽŢЋG×wJűŠ9uň˝Çďîم {ÓXż7‹ż=–S×i”Ćř†Ü˘pÇĚŞ—śťűpő{ąĂÎęÖ§ťđŕ 5~+ľî*čę­=¸ńąŘŮmášű÷â`onĘäqq9"eůŒdatČUwlÇÓŰąnOß˙Ç6T ÂęPhëĐŚËG×Oüâ,~„… %mÄ|Ť!~Źß´6Ŕ:[P¸íÍřöUÂNY1;÷öŕéČ­_ţŇăqúŃ5˜RżŰńö“â&)lÜz˙Ž’M\zÁq8n~ľĎâm/?S'ˇĘ<î{r/"áS–Ĺ Śáú˝÷ü᳸äÔńHö<Éőťm‘ŚVngWGś$ퟄWŸ;GNíÌöŹŚ~EčvCƒvŘúC™aańĂő[g+‰#"ůďPSÇÚ ýxň™ÜyîU—LD<î]„ĘAŁO8&'r>đČ><ůlˇ-n$ńȓ]xüéŇžü¨Fů‚FófÓ݌Bˆí;űäßöů™Y7;7uÍşn z× :Ÿ•Ý&ŤoaGo‹Ô‡ň‰ŤV&ÝyÚ La%­pŰ\ţűڄ7­M”nk4ŢŘŞč|VËäpö9ËŃ4sşŸĆ)ÎĂÄüŠŸÝ'ăm~>ˇŻZöuä›Ţs.RăöŁmđňËO/ŮčŠgŻ\ů~|óG&öŕš}#ŢZ\ŕ8e瞧ƒxv˙S[śĎě}]ŠƒŘ´zRšř—źń ź8°×Ἧ=MÚzť°Űž8°ŤűrŁCO9w&,kBGÝnźä +ŃŇÚTZ~ő°ř!u×d"ŔS`Ş„çŔ&"†‰ŇxjÜĂGüđ˛ŐžAIÔÔŰ|ZC#‰-šŠ/g.m—ZGYďSŹ==‰d˝\¤łżhYYű㠃–ú܈”÷ô#ž¨CĚ~ZœÍ¤°a÷NŃ?Öw”i­XY+&q $c–)2ĄŠ¨?nܗAź–.-l=Џ”ýd-W|Őlơí5mŚű‰_\€Ĺ€pٰĄ¤˜oľF~ěŢ߃×}ěďů Đ+Ş“rTכŽ8 sŚÄąęŠ~)r IPLĺnŒŹÁíX8wččƖ]}%Ű]8ÓŢŇ]šMöďĂٰc×ěŢׇАéĂŚ5áOˇ­łš=Řj_ŹíˇVœDĎÜúD*ҧü“Ť’ú î/FaCI;lý!jXy;*‹Žß:[IQś˙4-fŸŤŽýËv,]Ü"_{öŠăJg=i,‘Ĺ„ńš§­œ ?*Úkä˘ßĎŹîśEM]ĂäI )x˙źs'ŢňÚš˜7§^ž çä:<ľşKŽuގt>+ťMVß ŽŢŠĺW­Lşó´A™L.߄˛Í@›Ë _›RĆ6%­MőŮÔVnŮ\č|VĂ݌ŸÚ€îTNDÜÓłÓgNŔžÝśČ°?7˛Şë€|'5&L‡}Ůíňa)[Ś&KňÝßżÇ7×็śa÷ÖNÜ×+_ĂëC\ëłóN¨ţ}Š‚íË˙~t¤fí\ŠÇ‹Ű˙ý}yąŚs ŚÍœ„ÎÝĹşpüóŠ[]{xâ•ÓoFb1°1•‡*ŕîŹ,~(ń|śŠŰžĽŰž-|XńDî QÚű*Ýh„†|r$äG´S(ŚÖ@Ž?"rBŠÇ ˇXb_†Ĺ“ů 2J>`ĘSŰ+–°ó 7ŮÄ]q„œ.sݍ¤˛19ˆś™ÍÄĺĐbGá‘%[Óú`ĐäÍ⇒{óAÇuĹßŕţb6”´ĂÖ˘†•ˇŁ˛řáú­ł•ÄCňŸ :×íëřÇíťđ˛ó§ŕüłĆăŢ÷yó˛ź)zŹš7œ‰ByűűsŁ8^Ü<ˆžž ęí‡ ł§×`ţœÜ1ăáÇââó1cjć̨Am~Ęé3Ď÷Ř7b Żż,~xˇkR&ÝyÚ LŚ—oBŮf Í冯MŠc›’ÖŚúljBْ5škżŢžŸűúŠD"™đäKô§č|X_(G*Uź %›ĺ%E⇳ݾTq 'ťg؊[Ż~Z~×Ö„Ł–-°•I¸ńw—ř M9âVńœ~üÉKĄë›­íś`š-ú8hŸűę ǧt&]â‹ćec* U„Ĺ%žĎ6ľŰ×ä!ĄľCňŻ‘MŰ7={ťR˜ĐœÄíOďĂĎîؙ[OÄOŘiŠ,­s˜‚‰Ç&ňkŤYʖӶđŕŒÔ˜7‰ܝ…8 &×ůúŠű›Om•ŢXuôO3Ç×âٝšÖĽQ-u5Ľ7|Fux˜Š%u†0h2cńĂËÉÇ-Ŕw˙çÍů_ś™ą/Ô÷äÄ›SŠ‹…ŽÝ¸œœ{JLBĹşťĺvgMo/ń÷ů {€3'âžđânů}ňÄ\~ÉxQHÜš‡ž$ĺVŚß¸í BąˇyĂmí‹Ă8ÚڛpíޏÖ!G…ÜńŔ3Ąiݰřa&ÂÓéR‰p[ŘqMgcńZ˙8rý-ťˇüýöý8éř6LhŻĹąGóÄÉd˛śH2ˆńm5¸óžÝřŐľŰäÂćt^śOľH űaA|x@bçł/tářcZą`n=ŚŰ‚ÇöýčîVŰöÓOSVć†ő﷟foߙA"a§Cńőö喉Ĺ'aîż)ů,…˛Í@›Ë _›RĆ6%­MőŮÔ6IJMšÔŠ­[öâĹ ťąeĂ̘×Zˆ÷Ř}ĹéÎ&5y|&śÚçÎE'śIM)Űş97tÂřikŸĐŒ ë€}{ÚË ęs#łśmꀚ­;rë†,=zŢ˙‰+ПíĹî={mÄą¤/äm틯ś?÷•' Ľ-7…ü˘ $’qěé݃Ž]…xť7ďǤešăG&-°cëoÖ>uŤkOźrúÍî#&ec* U‚Ĺ%žĎ6ƒömߟň"F ŽíÄËVŒÇéGśăÉÍxjŰ Śś&äëikn}Ś yŹł4/šŰ żŘ…ł–śaöÄ:źve î[×ŁŚ5ŕřyÍjřźŠÄö˙‰ME•ţ §´ă[ˇîÇ ­‰źăĚvM.Ţúś×´™bě'~qą%~”ŕ×Ys°řĄ!;Ńů˜ožSÇ'qô’™xjőÜpËj˝ GĚiĂďo|{;ú¤—œą¸$éßn{KfŐaé‚ ňU¸űňqO;~žĚwR[˝\Ť`p0ƒko~3&XöÓă8~|Ýł%y%Eqőú˝ß<)‘[ëƒĘfuŻąoĐb¸ĺžŘş}č(?LĂDx:CXüŠ#†äżů†śXB.fx͟śăƒď˜k‹uj,Źzě.ß-SO̝ďžzÎśÓ>h^Vv™Xüp˛ćţG@ ˜ŽĹŕ˛zĆB<öč:9ę÷WWŽÂ‰gβŃ:l^wO?˛]ĆĄ5¨–Ž˜†^x…üU÷ŽGűôZL›ÓŠUwnÂÁšľ5–.Ď˝ćvńŃ3ńȃkä"¤7˙úiœň˛č>0€űn^]ČĂŠ3‘v~gąf˙ÓČŘţÜű×<ŰŁ¸ń¸eďĂq¤R˙Ÿ˝ďÜ¨Ň~ęîÉł3ł9{wÖq×8gŒą“1˜œš#pG>8üé¸#ܑs<‚É`Œ'lŻsöڛź9O؉ŢŻ’ZݒşrK=˝łďł{§U/V•Ş%}*•аcó^X¸Ż:{Ú`ŮńsÝco‹{ěÍĂOż÷'8ű%ÇAŽ= ܰ¸q=ôšÎĹo9Śť7+fÎîƒ}{úá[ž€Žy­0}~ĘJä‡yÝɂ@äGLOEÎËEœIţtÝ üöî°zY,œŃďy΂ˆę¸{wĎĆňŤkžŸX‘7ƒäŞ;Ŕi+Üýś,eőˆüЕĄÚND~Čt°ŽüůýĂýlu ‰Q÷3'ŽŞÎaÇd6Kä×텏› ću¸$É҈őřD xč`ůؗ‡÷‰ţś6ŸŘx˜=ć⠏ŹőÚĄŁ|œ{đ‘ƒŢşANđ+$Ô' joÔĐá—íCeăÔęÄ;N[ěg:ŔXL”•…Ň–ĹÚAť,ć‡[†ąütËŞŰ‘'ôÂłžu*üéOka|Ź7˙9ôö3Txűť^cÎAˆwي• áęŸDg'öövĂ9—ƒ°Ž9e,;b>lÚ¸6<˛Űű0â‘đĐŃ8ŤN\7˙ĺ^xäM°ţƒŰźYÓz;Ąľ­&Ć'Ş9ťĂoůŃKే6Âmń>ĎzÓÓ\¤ ^ňŞgÂ˙}÷jŘüđ.ďƲ#A›{l粗]?řňoĄP(­?őUmko…e+ÁŚ'ˇVlâmËëi{O‘}D§n„äAoI᝗Č^.ľĂťv!ÂĐb ĄGJ؉ŘśŔÇńüáî=ŢŤdŮ#,Cُý‰řČĎ7ĂSűóĺ瓝7‡űŁ<˝×=_űčĎ7Áý›†<Ľß˝ĐúĆuŰŕŽ'˘99NmnáܝxŢNČ6ă-8÷•ëwĂOoŰĺ=ĘĂrhË0üÇ/7zqkšGц52^_đö‘.Ŕ!C~đúSŽđ! ¸ˆü0DĚlůź1řŢŢ —ş„ĹŒ3 ľ˝–-™o}íEđ…˝2…5.žwŃ*xÇ.ƒžž™ŢësĎ=ýhřÖg^=­ĺY\.‰ňŢ7œá­72mZ§űé…ç<ătřđ[ŸîÝ]cŐ=đÎ×=ćĚęqďhuŔÎ~€gœąŢóŚKaţÜéîľV'̛ż>ű‘×ŔŠ%3A"?te¨śÓ‘2Ź+ŻĚ ‚Ç6ŮkčłŮřéŻv¸1ŃEÄpť…üÇÖßnŘ {öŽűÇ݃¸óŢpĺ= [vLřÇS÷8w ż;vůŤłľ­ÖmóŽ}ÝăěSŰü;ÂěqˇGžőŽżD~ÄâęԉwœśŘĎL@ä‡^ÝNôĂ ^ąţőý/ƒ“O^îł: —ËÂěŮ˝pÁÓWĂ'?ó&˜ľÜkşâĚ󎅗˝âéžM{G+Ź>e%|čß_Ù~/Ŕ€ëűŸ>đ"8炓ĄťťÓ%Zŕé? žóŇ3#~˜ßK._ç?c tOóü>ú˜ĽđÎ÷˝Ě=6ć"zlŃÓ˝ţB8aőJ7f›GĐG2ŢúKž6Ţţž—ĂŃǝ]íŢc/ ́˝âbxŢk/„|1ďůč;şŢřO/…Kćz:ŝˇź÷e0mFW$–ŞßTm 0öÍş’‡ŁQťró>™Đßŕ“-rĺ{­šÓˇfÍŠˇ÷÷k<Ł}ˆƒMqC÷ýŐ_Xëm‡wZ"?xš ÷a‹7óăîgÂ# ˛îĹJśĹ_EžX*şĺcPœđeě 0&sOŹŘëůJîrŠŕ’…qŔbŃk/đpď$1=vÇâ]y‰-¨čžŕe™œż ó]pc{ĺ-mž ›Nčéťů”ÜřŮâdÁ`Éűžmi÷HŒ’ç7ď-ŞšÍu”}ŽzyąŹ.îí4ᄀ…‰QďŻĂĘsíž_ŚÇęÎŢ2ăM˙uëőłwăÍ@ů՝űŕˇ{ĎTc„P‰6: ú(Ş úş‡ůńÔWÎ-OáóşÁ]wÓ 8ÎŞ ňƒoëtçîĎm…AŔ‘'#2.\]§}ž;>ŚycŇ[Ptbż{›xWĹh˝{ôŠ÷ţŮűţѡ —]t<8ms}1ďŢIuď•ĆŤ>Ůzí ÝŁËtđjžď÷tœžă˝Ţ:$cť|÷ís]_łý™'űܜˇ¸ˇ˘ć”ËÜ߀ҘkťœV—iuýĺ‡>áćÝîú[ĺWmd38ă{ŐuUÉ걝´ýÁT†BŮŻú˝öř|ăťn%ňCރuĺä[t;ďxĺŢ(Č´zoGËfƒĹ¸ ŢqľPőú„ÍÚČĺ:˝uľŘąˇXœđ>LĎ ŕř3(Ůě‘lŚ5¤—÷|” ŕČšÇ>Ç[¤čÇf‹"ťűE.×áŻýc­yˆüÜ qţ ÷Ţx‘öřü֟/Иc, ĹCP”ĹÚAť,ć‡[†ąütËâőH¨n]­}Đç{ÚŮr÷qśXčđÄ ěÝ ĹąŠŢ—<üň•7xß/ĂYpĆšÇŔĚöšŢaú;†ˇ¸äx%nÖ=śÍë^äŢ$đ‡ĆöÁžąÝ°rúqžÍƒ lż×ˇóťCoŰtďű°{lÝ:ô”ŤwŹë# ۇˇÁÎážÓœ;†—L[ -ݞî–Á§Ü<ýő;ŚľöÂÜÎyĐŃŇé=˛6Vƒ˝nĚÝwUŢĂĐŰÖ ťşőmwuĆaÓŕ&˜Ý1f´O‡ąâ8ÜżçAiż™´í!ťÔmçű˙ŹŸS}}˝pĎ=kĎpż˛•éŮĹ[‰žPţ˟R胥ż5Mڎ€I ‘VGŽ kő⺇ĂĚ,ĎäČćZ˝‹§źíÍŇpüÇ\˛9÷"ʛ:’y֎˙ć”÷ä)ëżîÖ')üişŢ^ŘŒ[–u\rĂőÁ|˛ˇ˛8ĺçŒ7nÎń‡ă•ł7Ä [ÖE÷.UĆ#<˜‡đ˘lާëýe9ĺZ˝ŠžţeXđޞ]Ö#?,”qá8ź)R¤Ě×%Gp|—ŘŻ;†<"śD‹îŻőë!8Ş îÉ!ŽíŽÚ˛W oŹÚ˛Ň÷”óý¸Ĺó9šýÁT†j;Mů!ÓÁşň—ą™Ţ+áłmѓëň1”—™ťč…ňqË_đÔÝtüă2fKŐʕ_aËl|FÄ_ˆ<€™˘Üe ­2ŸŽ0ç^Dą› žO˙“HŸ€Ş˝QC‡_f´•SŤď8mťŸĄjG䇺CăýŢGU8Řëow3bBs °Ő%6Eâ?°űވF^mÚ [ÜOŘσ{î­ŠGŢ%6Ÿě‚[ˇÁńp?Şvěëwɘh}Ç“ îˇJ=4ŰvŞ“„t@H ďŻD~đr‰ĆóOŠZÜťFĺŮLVžíŔNŚŘűb3‘Ȃ\Ęł3˛ěÄ)‹•\ĹWô‰ŠR‹żÂ}9¨'a¤•ܘ?ômłšňŹßƒ~ ]bd3ţët+Ż˙ľˇž˛Sy Ć;MU—鍌`zGftĺŕ̆ם7ËË?W~ýí}›†ŕÎő#îÝéNeVžóú‚ˇŸˆtˆüČľdőŘúm$ůa,ăČÉ7­śçȉüЕĄÚÎŞß5^‘ŔÍ?Zć;éá8ţkkĄrœóáî‡=˘â8ՉŔţQ0ë˝CǢđăŚÄô2šĘńýŮ"ďUń•Wއ÷`Ű>U{نżĚh*'˛Ÿqʈü”a,?ݲx=ŇŹ›˘`Q7ÝřÚőŕ”%֎’şIsRԍëšpąŹ!Y’"ˆüŕĺ"ˆç8U‚#î#.ăĺâřëoTÎŻ ވ!?ŽĂĎ;t˛çTt€ăĂqň#|ňć@íšœSžM•vřÔďˇĂsOšçŰ f´y'“Oíƒż=ŇżťgĐ%uÚ}‚(œ'‘ŇýP }"? m'#ߴڞ#'ňCW†–vj¨~×xeD~7qœ*šĄXŕ˰rŒNnŐcš#­“ąƒső˜W­ŃQĺ//‹cÔ:ü2Ł}¨lœZjrEăüEe:ŔXЇ (‹ľƒvY̡ CqMĘâőHłn:őˆAUÝřÚőŕ”%֎D~Xԍ<ˆI D~đrьÇńaž šű1iq–ď)–ZŕWwŔUwî,•›ËřŻ"t˛mč´`"?¤}o "? mĚwůâépç?á‹F6{kučř4’ç‹zśSn0•ĄĽŞß5^‘ŔÍ_żNQoIź2ŮńĚşO@•/jčđ˄ůóĘĘĆŠŐŠ&WL¤OLAäG:ő˜ł°~řłzߡm‚ýc{ĽőЍŻ]NYbí@ä‡eÝɃ@ä/Íxćš š“öŽ)Řś!{°&S^ôÍÉCĆţ"ŽN&Cä(ö‹ÚF5‘†śIçËÖ۸grڞ#'ňCW†–vj¨~×xeD~7ý:E˝ůś˝>(§V§š\1Ů>Ń‘)ŐĂĹXaÚs—V=tăk׃S–X;ůQgÝɂ”•jwb"?xş˛źurAs?&íS¨Ť Ë뗰ľA˛îPŹžĚD×) ;çb’ˇŞ/šŹ 9ţăşq™.ˆü0´Œ|Ój{ŽœČ]ZÚiBňťĆ+#ň¸ůë×)ęČ°%čőAŮ8ľ:ŐäŠÉö‰!ŞńPU‹Ľ]óĂ-ĂP\“2ŒĺĚ+KŞn:ő0Ź›n|ízpĘkGIݤ9)ęĆő M¸$P7Bň $E`ĺŸÚ˜ČžŽ,o\Đ܏I{ÇkĂ`ĄToń՘,d ÎĹ$oU_4YrüÇuă2]ůah;ůŚŐö9‘ş2´´3Ö|áýž †N­SŮo˜WÄů$ňC–/čő‘Ѹ:uŞÉ“íC T㥪,Kť,ć‡[†Ą¸&e˙W–TÝtęaX7ÝřÚőŕ”%֎’şIsRԍëšpI°n„dAHJŔĘ?ľ;/‘<]YŢ:š š“öŽ)LjĆ ôóVőE“ľ!Ç\7.łZĘęą5ôKäGşśD~čĘĐĘÎs`ÍŢď jčÔ:•ý†yEœ@"?dů‚^ůŤS§š\1Ů>ŠŮP#ˆ‡ĄmnY,–vY̡ CqMĘ0–3Ż,ŠşéÔðnşńľëÁ)KŹ%u“椨×/4á>’`ÝɃ€•jw^"?xş˛źurAs?&íS˜Ô6Œčç­ę‹&kCŽ˙¸.rôŕčŘŠ|b 2ŽœČtm‰üЕĄ•‘Ąm^ďxVGţúuŠz#ň#l z}P6N­N5šb˛}RłĄ‰PŐ"eąXÚe1?Ü2 Ĺ5)ĂXÎź˛¤ęŚSĂşéĆ׎§,ąv”ÔMš“˘n\żĐ„űHÂu#$"@Ň@l‡ŽcX%˛ŃE‰"?â>Đ܏I{Ç&ľ cúyŤú˘Éڐă?Ž+ËEh)ŤÇÖĐ/‘éÚůĄ+C+;ňƒçŻö÷5tj}Š~7ˆüŕĺ&Îôú€s<łîPĺ‹:ü2aţꞞqjuŞÉ“íQ™0ô7Č!R†=˛˜n†âš”a,g^&T7zÖM7žv=8e‰ľŁ¤nҜuăú…&ÜGRŞ!Y’â;,‘<]YŢ:š š“öŽ)LjĆ ôóVőE“ľ!Ç\W–‹6ĐRV­Ą_"?Ňľ%ňCW†VvÚů*üŐţž †N­/ŐÜÄů‚^pŽgÖ}Ş|QC‡_&̟WV6N­N5šb˛}"*3B5 —Ĺüj—ĹüpË0פ c9óĘâő°­›N= ëŚ_ťœ˛ÄÚQR7iNŠşqýBî#)Ս<ˆIń–ČžŽ,o\Đ܏I{Ç&ľ cúyŤú˘Éڐă?Ž+Ë%`r[GNäGşśD~čĘĐĘŽ.ňƒgZIŁ6ŸZZŞß "?xš‰ó˝>ŕĎŹűTů˘†żL˜?ŻŹlœZjrĹdűDTf„j.‹ůŐ.‹ůá–a(ŽIĆrć•Ĺëa[7zÖM7žv=8e‰ľŁ¤nҜuăú…&ÜGŇŹ!q’2ˆüŕéĘňÖÉÍý˜´wLaRŰ0V ŸˇŞ/šŹ 9ţ㺲\Ö!ˇ•qäD~¤kK䇮 ­ěˆümóĘxÇł:ňׯSÔ‘aKĐ냲qjuŞÉ“íE™.‚0´Mä‡F= ëŚ_ťœ˛ÄÚQR7iNŠşqýBî#)׍<ˆID~đteyëä‚ć~LÚ;Ś0Šm+ĐĎ[ŐMֆ˙q]Y.5r`r[GNäGşśD~čĘĐʎȏĐ6݌w<Ť#ý:E˝ůś˝>(§V§š\1Ů>‘”qғ#dĂţůĄQĂşéĆ׎§,ąv”ÔMš“˘n\żĐ„űHęFHD€¤"?xş˛źurAs?&íS˜Ô6Œčç­ę‹&kCŽ˙¸Ž,—jĚxаš­Œ#'ň#]["?tehe—ůˇ'ň¸ůë×)ęČ°%čőAŮ8ľ:ŐäŠÉö‰¤Œ“žúKä‡F= ëŚ_ťœ˛ÄÚQR7iNŠşqýBî# Ź!Y’ˆüŕéĘňÖÉÍý˜´wLaRŰ0V ŸˇŞ/šŹ 9ţ㺲\Ş1ăĽŔ:äś2ŽœČtm‰üЕĄ•]˘äGÄUm>˛ß ß0݈óCBä‡,_ĐëÎńĚşO@•/jčđ˄ůóĘĘĆŠŐŠ&WLśO$eGš`D~hÔðnşńľëÁ)KŹ%u“椨×/4á>ŇŔş’G‰KE˙ox×Ĺ莌ą/YlGŠŹúÚ'^\cFüź5ăq|˜ç‚ć~LÚ;Ś0Šm+ĐĎ[ŐMֆ˙q]Y.՘ĺ6Ę Xä8^€„e9‘éÚůĄ+C+;|‹%U˛Q”°D~7ý:E˝ůś˝>(§V§š\1Ů>‘”a8jÉüřIä‡F= ëŚ_ťœ˛ÄÚQR7iNŠşqýBî#Ź›áń“ "@RŔŘÁ@ä߇y.hîǤ˝c “Ú†ąýźU}ŃdmČńוĺRYmĂŇh?˜`_˙„\SqäD~¤kK䇮 ­ětóÝ7¨o1Œô×ř”ýéü†yEœ"?dů‚^pŽgÖ}Ş|QC‡_&̟WV6N­N5šb˛}")ĂŘF!?&ČGü˛żD~ÔW7ÝřÚőŕ”%֎’şIsRԍëšpipÝJó@HD€$wm¨n†vîňfäKD†QO(đQ‘U˙Qűáċëb̈Ÿˇf<Žó\Đ܏I{Ç&ľ cúyŤú˘Éڐă?Ž+ËĽ3چ…!v9&On‹’—qäD~¤kK䇮 ­ěLň]ˇmLĆçϚż‡:ża^燄ČYž ×œă™uŸ€*_ÔĐᗠó畕SŤSMޘlŸHĘ0śÁśÇG6ÉřÜšů`ĹűKäG}uӍŻ]NYbí(Š›4'Eݸ~Ą ÷‘I¨[i÷AĐŸ]’v?yˇ˙%´s—7#_"2ŒúëĆD•AH”~8ńâş3â筏ăĂ<4÷cŇŢ1…ImĂX~ŢŞžh˛6äřëĘrŠĆŹmÉí÷‚ î¸w/_€#[GNäGşśD~čĘĐĘÎ4ßŰÝ&عힸ áďŻLöSŐAš‘‚2ŮńĚşO@•/jčđ˄ůóĘĘĆŠŐŠ&WLśO$eŰś‡î<ńŕţŠ"?ꫛn|ízpĘkGIݤ9)ęĆő M¸LR݊÷!y’0ǁ§îż!2H0ö%"菰nLTDé‡/Ž‹1#~ޚń8>ĚsAs?&íS˜Ô6Œčç­ę‹&kCŽ˙¸Ž,—jĚÚ6dYŁ7ötŔôţô×­ľ”ŮĘ8r"?Ňľ%ňCW†Vv6ůţńÎíFăsӓ7F]~Żxe˛ß˜ŞĘuˆü”ÉŽgÖ}Ş|QC‡_&̟WV6N­N5šb˛}")ĂŘFXŢżçoFăóޛwzöD~ÔW7ÝřÚőŕ”%֎’şIsRԍëšp™ÄşM<¸S{|ôAH‚vĐÁݛáŠűŽ­”cě †lˆüˆű@s?Âźku1Ś0Šm+ĐĎ[ŐMֆ˙q]Y.՘ľmČ0öä Pčßâ}W$ů†-á7l‹ŔVƑů‘Ž-‘ş2´˛łÉ÷wˇo‡ ;úöšăsŕŔS°ń‰ë#žâżź2ŮoLUĺ:D~ĘdÇ3ë>Už¨ĄĂ/ćĎ++§V§š\1Ů>‘”al#,Řs#Œ˜?wo†{ţś3‹ý%ňCżşńľëÁ)KŹ%u“椨×/4á>2‰u+>°J{†=‘ ɂ윙Lúó7ĄT*Uvjˆ ď;FíĂş1QePĽNź¸.Ì82"?ŇiĂX~ŢŞžh˛6äřëĘrŠĆŹmCoŰcƒw}Çs ş'pL˙Kß{Tý6[GNäGşśD~čĘĐĘÎ&_öö—Ď˙úqŤńy˙ÚďTŢN˙Ęß Î ‘˛|Aď˜DäG4ŽNjrĹdűDR†ą ŒäU‚]›`5>Żůń“•ˇ;!‘uӍŻ]NYbí(Š›4'Eݸ~Ą ÷‘IŹ{űËŘ OjO‚ˆI lČ=żúŒżŢwŒęcčKLTDé‡/Ž‹1#ŽŒČtÚ0V ŸˇŞ/šŹ 9ţ㺲\Ş1kŰ0(źĺż*ł?LÁf|ě ’gŸěd9‘éÚůĄ+C+;Ű|?ňý+ł?LÁfÜqÓçj~#B*˛ß˜ŞĘuˆü”ÉŽgÖ}Ş|QC‡_&̟WV6N­N5šb˛}")ĂŘF<ÝO~ą2űĂlČ/żü¨ç“ČýzčĆ׎§,ąv”ÔMš“˘n\żĐ„űČ$×mâwVf’GVPîÄž;ąďźO&öɖ?íóç/|ÓŘŘ8` ş{:űťËŁîž\„9+žVŮĄˆüˆű@s?Âźku1Ś0Šm+ĐĎ[ŐMֆ˙q]Y.՘ľmźë[pđ_TŘń௠á1úŕăÜťXgŽžĹ .€LƑů‘Ž-‘ş2´˛łÍ÷sż|ž}͆şĆçŢݏyÇĐy OŃú óŠ8?$D~Čň˝c‘Ѹ:uŞÉ“íIĆ6âéîŢü]Řłő—uĎ-O ¸wŠVœ8ŁâŸČq=tăk׃S–X;Ję&ÍIQ7Ž_hÂ}d’ë6qݓ0që&ăń9ĐŢŢ;vl˙–űuĚý°i Ĺň_öAÎBľAHŠ`ˆÝëÁ˝0Üí ‘5š šaŢľşS˜Ô6Œčç­ę‹&kCŽ˙¸Ž,—jĚÚ6ôśŮc/ˇ|.B~°ąf3=ŮÜy˙Ř˝o Î?}ŽëĎŠ X“˜žœČtm‰üЕĄ•íc/ţރňŁžńšsŰ}06˛,9“DbĘ~cŞ:(× ňCP&;žé։ȏŔ &Ű'’2Œm`$Żěxň ňŁžńšţÁý0¸Ž9e–7>1š‘†ńľëÁ)KŹ%u“椨×/4á>2‰uc˝LüöŃůa;>Ur#źŁ3AśÜ=´uőAϟ冞Ä{Ł˙DäD~Äýđu1Ś0Šm+ĐĎ[ŐMֆ˙q]Y.՘ľmČŔ<=pÝżÁř–ľuâc”ÍšúĆm0˝ˇ Ž:˘‡o„ §19‘éÚůĄ+C+;ŰOßöżwĂMîIt|˛™ ›ÝąßŢŃ }3ŽTţĆyů!ËôŽID~DăęԉwœN˛O$eŰËق§O=ú :pw˘ă“Íš˙–ĐŐÓ ó–vWbůa_ťœ˛ÄÚQR7iNŠşqýBî#“X7śŕéč˙Ý…'öśäCŁGٜG€d –ô\ůÓę~ZÜOߚ5§ŢŢß?‡Ř4AÄjߔ\foڜĽ°čċ`ö‘k`ÚÜĺĐÖÝçśd”‡Âč?‘^%ň#‹1…ImĂX~ŢŞžh˛6äřëĘrŠĆ,ˇĄ{§Ş4Ú…abű˝ŢŤnŮzŢ,ňOR˝Ţ=rq7<ëüEpúÉ3aĺŇ˜Ń× ŮŒ"FŹ"D~¤kK䇮 ­ětňe3=ö NŔşmCpűŁűźWݲő>ŇŸ=}K`éň aî‚ŐĐ3ýhkďscdkęDä‡,_Đ;&ůŤS'Ţq:É>‘”a8jŠ…üŒl‚áűĄĎ_Ýď[SŸłuÁ gσ#Ÿł—tCWo 8噕Ő1”ł´,TWaF}pËbmĆ-‹Ůh—IęĄ_ťœ˛ÄÚQR7iNŠşqý‚Y;6didÝÜąR:˜‡ŇîƒPܸß{Ő-[ď#Éńy¨˘ŻŻîšgíî×~÷“w?î§Pţ!Jˆ¤H˜Řwˆ}÷@Hʈ |”Ę+Ű}ğLęŕ@c”@¨4> „ćOĄy‘Öř<Ń($„TěÄáƒ1@üßôĆ(` ŸBó‚Ć'ĐźhÜř$ˆAHƒŢŠyŒšl@‡;qP 1J ؁Ć'Đź ńI 4/ˆô˜2 ˆďěˆÄŒqLćĆ( OĄyAă“@h^á1ů ¤ @@hnĐ%š4> „ćOĐl „@ @ ” @ @ Ś<ˆ!@ 0ĺA@ @ „)"@@ @ Ly2 ŕż#@ ˆĐč÷¤Ó%ôAă“@h^Đř$šŸD€4ĽR ć/Y§_t1Ź:ĺTXtäJč™12™ŒŔ˘|q$2!ĐRfhë˜ŘęűĆ:l+pę°­'ŽŽÜŠĂV)ŤÓÖiŽś*•Š0¸śŽß Üu?ÜyÝ-°cóVÉxŠlŒą Ď>ŁÎ8ŽŽZ”ƒ™=d3Ž8Őxľ0TȕZ––Žą ňŁ!KKלĆ1áňSżŹXBŘ7‚°n_nߒ‡Ť×ĂĆĹÔÇgKK+L›Ö î÷6Čf3tňŘT@°ťöm¤]č\ĂČ6ŞŹo[Ť¨śœiÚ1=6^ňů<ŒÁČČ( ůÔÇgf^´žśrÇÎga8=mŕdh|N:P¸!,Ćř–îţnŤVŽjuTčĺŹTÂv‘…~Ɗîń‡& ´cJëöBţžm€ť‡RŸ„(r'´|τţŸlů“+ZÝO‹űé[łćÔŰűűŕpE@|źřÍo…ł.yvH"1D~ŘŘV@䇝m“"Ům×ü~őľ'N„ÄÇť/ď†çÝ. _ť-# ŒíRÖľ­GÝ~’ĘÇÖ&äÇB–¨nő0ŃľýîńqřÂßG'BâcćĚĐÝ= Í ť;˙öä‡ÓÜŚ;3ŰƓ"ŰŃŃLœ ˆöš3—ĄÉů!1­7V­Őę“D~T‹PŞĂ7’+×nń?>vŘ!}}˝pĎ=kĎpżöťŸźű™p?…ň§Xţ”B ý 9ü€ÓřYA|Âűd€Oˆ´ĎŸżđMccăp8‚.|ÁKŕý_ü ,YytH"e‘FśůagŰääĂâËŕ/}ôď=y"‘;żlŒ^qQ'|ďĂ}pě’Yx}ŇŔŘ.e]ŰzÔí'Š|lý`B~,d‰ę&P]KŮŃłrđŞŰa÷0ƒťň‰Ďžž^X°`´ľľĄyAä‡ÜNĎVpdiśmiiq Ä.(K011žŘřlš`tž÷Č.™„&ƒ!ÁĽtöy‹XľrTŤŁ˛@3_…’Đ-JuřFęX™˝;ďŔÁq(>uఝŮŘŢŢ;vl˙–űu |b#Lx ç ×’"؁áŻ3źćŸßďîČa6OÖOe‘Fśůag{Ü6t\f|Íů§CąP„Çî~°ŽƒŁoQ7üŰë§š?Z’Ç\âŰ2ŇŔŘ.e]ŰzÔí'Š|lý`B~,d‰ę&PÝ:cdÜńřŒ#[ĄŕžŞÜšu˘îń9cĆ ˜5k6=ćŇä ňCn§g+8 ˛´ăŰ:Ţăc cccuĎśçíŻ<…Ćg3‚@ޖÎ>oŤVŽjuThćŤ&$řE(ŐáéÇbă(wÂ|6¸ řÄŢĂr\5ŠĄ‡RB0óăĽoý§˜DÖGe‘Fśůag{‘aůKßń¸đE—zcÍÁ̏÷žź;‹G´´KYלuűI*[?˜ Y˘ş ÔĂD7Áď=łŽ8ž˝ŽńÉf~̘1Í "?ävzś‚ł K;•mOOtuu×5>Ů̏ś—œ„& 7„ĹČŰŇŮç-bŐĘQ­ŽĘÍ|JBˇ(Őá™Çbh}î*ȝ}„őř$¨AH `'l͏7~ŕ#q‰ĚĘ˙C䇑mD~Ř٢äG€7|ř0é"ăpŚĎÖüřo™–ŔĹ#ZÚĽŹk[şý$•­Lȏ…,QÝęa˘›BŒ˙waїľŸl͏ٳgĄšAä‡ÜNĎVpdi§śő…}}}ËľXOo͏ם „& 7„ĹČŰŇŮ-,bŐĘQ­ŽĘÍ|JBˇ(Őá™Ç ZŻ8 œ9Ӏި”ˆIlGeŒ[đ4“ ?a$ہË2"?Œl+ ňĂÎö'?2Ů źč_á9݃D0Fق§Y‡{Š9P'cŇü`B~,d‰ę&PݔbdÝáőî3:­Ć'[đ”ŚŐ77ˆüŰé٠΂,íÔśU!^˝˝=Vă“-xJowiB pCXŒź-ÝÁ"V­Őę¨,ĐĚWĄ$t‹Rž‘yʏ€˙ڞsŒŃř$čƒŔfĐŰ^Ô2TČľdD~ŘŮNň#ŔYĎşŔ›b6űƒŢöľę$bLšLȏ…,QÝęa˘›r=žwTŤ7 Älö˝íĽšAä‡ÜNĎVpdi§ś­˛ő@Ř,°Ůôś—&„!ź-}Ţ"V­Őę¨,ĐĚלŔ¸@ť]Ěc Vö”EŢ,Bň $a0ŚîŒg<3T"e‘Fśůag;…ȏ@vú3ĎŃ~V’é=ç̎¸ ńśŒ40śKYלuűI*[?˜ Y˘ş ÔĂDˇőpńœŁÚĆgOđ53ˆüŰé٠΂,íÔśbagg§Ńřl=} š „—~ĐŮç-bŐĘQ­ŽĘÍ|Í Œ ´ŰĹ<(bľŹYHk¤"@DpR°ę”ŕšHŮ@(ˈü0˛­€Č;Ű)H~0Źzډţ–â@ČĎ8ŽUě^—40śKYלuűI*[?˜ Y˘ş ÔĂDˇő(ËĎ\ŘRéĎŕ-„ć‘r;=[ÁYĽÚVnź^Zw|掝 „& 7„ĹČŰŇŮç-bŐĘQ­ŽĘÍ|JBˇ(Őá™ÇE,ś™=j–˙ƒID€$ˆ`ç\täJ„˛ŒČ#Ű ˆü°ł˘äĂÂKý͸Łĺřhi—˛Žm=ęö“T>ś~0!?˛Du¨‡‰n#ę’Żœ‘-‹őĆgKKšD~ČíôlgA–vj[ľ]K‹Aé,ěB“…Âbäméěóąjĺ¨VGefž %Ą[”ęđĚc"V°éĚëńˇ‰I9 $ŽžÓ%ŇňL䇑mD~ŘŮNaňƒĄgz/˜`fcqˆ¨eiéÚÖŁn?Iĺcëňc!KT7z˜č6˘1ů̳ųYş7Ól ňCn§g+8 ˛´SŰęŮe 3uzˆ l  pCXŒź-}Ţ"V­Őę¨,ĐĚWĄ$t‹Rž‘y,PÄ o:ÓZ<č,#q {0Éeˆü0˛­€Č;Ű)N~0řLşgŽٌäí/2Ҁ+ľ,-]c&ä'Š|lý`B~,d‰ę&PÝFÔƒŁ›Őú}ŹĐŰ_š D~ČíôlgA–vj[;ŒĆ'˝ýeňÂ a1ňśtşÝ"V­Őę¨,ĐĚWĄ$t‹Rž‘y,PÄŞž&çˇ]Đ †Ąźóůad[‘vś‡ůQ7”(‘Z––Žą ň“T>ś~0!?˛Du¨‡‰n#ęĄŇ%r ňCn§g+8 ˛´SŰÚÚ  pCXŒź-}Á"V­Őę¨,ĐĚWĄ$t‹Rž‘y,PÄŇiB2 ¤!(ďÁD~ŮV@䇝-‘jč’hj—˛Žą ň“T>ś~0!?˛Du¨‡‰n#ęĄŇ%r ňCn§g+8 ˛´SŰÚÚ  pCXŒź-}Á"V­Őę:WýZů*”„nQŞĂ72ŠX:Í@HD€¤ŽňL䇑mD~ŘŮvä‡Ĺ‘B—4@Sť”ue˜Ÿ¤ňąőƒ ůą%Ş›@=LtQSż„Ś‘r;=[ÁYĽÚ6y;B…ÂbämétˇEŹZ9ŞŐQY ™ŻBIčĽ:|#óX ˆ%oŸi€TQŢi‰ü0˛­€Č;["?ÔĐ% ĐÔ.e]c&ä'Š|lý`B~,d‰ę&PÝFÔĂÔ/ĄéAä‡ÜNĎVpdi§śMގĐDĐš FŮ&JMëU+Gľ:* 4óU( ݢT‡od ąäÍ@ă3-’Ę;-‘FśůagKä‡d¤Jte˛´te˜Ÿ¤ňąőƒ ůą%Ş›@=LtQSż„Ś‘r;=[ÁYĽÚ6y;BAç‚e›(5­7V­Őę¨,ĐĚWĄ$t‹Rž‘y,PĒ7Ď4AH*(ď´D~ŮVÂĹqíIe}˝ĹŇUo)hPĆAä‡d¤lwIęŐD×X† ůI*[?˜ Y˘ş ÔĂDˇő¨'&Ą)Aä‡ÜNĎVpdi§śMގĐDĐš FŮ&JMëU+Gľ:* 4óU( ݢT‡od ąäÍ@ă3m’ˆü0˛­ Ą‹cĒľ-ČȏĘI[T§Jˆ4¨ă ňĂ 2Ň%ş2YZşĆ2LČORůŘúÁ„üXČŐM &ş¨G=1 M "?ävzś‚ł K;ľmňv„&‚Î1Ę6QjZoŹZ9ŞŐQY ™ŻBIčĽ:|#óX ˆ%oŸ i€Č#Ű ¸8öOâRhKĹc/A\ń̐űŸČú>Ŕ5Ĺs=2LČORůŘúÁ„üXČŐM &ş¨G=1 M "?ävzś‚ł K;ľmňv„&‚Î1Ę6QjZoŹZ9ŞŐQY ™ŻBIčĽ:|#óX ˆ%oŸ A=t ÚNaňŁz'“[ÖˇüŘK¤¨†čŔPœ¸<Ĺţ'ňŁ>„pMqÁ\ ň“T>ś~0!?˛Du¨‡‰n#ęQOLBS‚Čšž­čźŹěÔśÉŰš:Ä(ŰDŠi˝ąjĺ¨VGefž %Ą[”ęđĚc"–ź,۟`"@RG=t Ú†äGôĎ÷Ť¨×äĆ÷͛ô•uBRě"? lE&‚…Ä.-ue˜Ÿ¤ňąőƒ ůą%Ş›@=LtQ$cšD~ČíôlEç%`e§śm´ĄĄ°¸ FޖNŸZÄŞ•ŁZ•šů*”„nQŞĂ72ŠXňf°l‚5ˆIi^ĐŘfäwÁS´hëŕąž8´ćGŕ:>+„­C’ÚbŠD~؊L' i\ ščË0!?Iĺ#ÖrޞzpuődŽnn&1”ş ÔĂDˇőH2&Ą)@ä‡ÜNĎVt^VvjŰFŰ ‹ bäméôŠEŹZ9ŞŐQY ™ŻBIčĽ:|#óX ˆ%oËö'Ô"@Rƒň—ĂRfh{8“œÇ^´ßĂyěĹ+Ŕwˆŕ¨Îú¨ú–iÄUʀČ#[…]#.PMte˜Ÿ¤ň‰n &gqü Ô­ C߼OĽ%Ö> ÔĂDˇőH2&Ą) C~đŽ•iŞă#‘“eGh(L/ˆąfo—š‚m,á˛vÜč /D u,hˇ‹y,PĒ7ƒF_R Š Í :ŰĂřUˇĹ| …<`ŠĽ’˙F˜ŕDKľ^ˆč?8O+•ЁÉd “ÍBKk+8î÷Ŕˇt҇,ŽRD~Ůş6škŠ‹YLČORů„6K&~0ţU˘[ťíhÚaX_ĄŤľ]#CK;KÝÔb`úů& "ňł$ӚůQűFľ° Œc™ŰÖ*ůAh(dÄ(/ŽléôŠ,ݘ§ÂvGŽ˘¸ę—rbIĺ˘"”ęđĚc"–ź4ڟˆi8ĐRfh{˜˝íĽrĺţ}›ž‚ƒ[wÂÄđ0,]źňyxüÉÍP(\bÄýä žMÖ%0‘‘Í22#ăm{ßš‘aߝň_żŹłŁ֜t<ěÚľśíŢšîh]0f̛ٖNĹĚÓúz ňĂŔÖĐu¨&şĆ2LČORů„6%äGí#0őĆMę#AQÍ=uľOýő0ŇM-ڟaŇŔ#9ÔłAűŘKU_y'!bŮҎÉks›zěÔśś#4ź bŐ14ltcIuxrŹ Ë'€Ź@3_…’Đ-JuřFćą@KŢ –íOH D€4h)3´=Œg~LŒĂîő›ŕŕ›`tt ěď‡Y}˝0>6{wěrɏ"]„Íâ`ł7˛'BtdĘŰ’ÉTɑŒOŒˇwŔˆK° ôÁŕžý0ۙ¸y'ěsS˜ľpŽç3ČIôŚU}¸ ňĂŔÖi\ ščË0!?IĺÚä(ô\ a"ůxă-Ü4ađsň’Fů ĽĽnj10ý|“†8ŃĄˇČdŽůáo;Ę)•ńzq<}[ÁYĽÚśŃv„†‚wAŹ:Ƣĺ, 7”Ĺ>>ö‚P=÷C §Z?= %Ą[”ęđĚc"–źlڟ4ˆiĐRfh{šĘŠ`äŕ oŢ ‡†ášŤo€ąŃqřËu7C’řů˙ýśňý˜cWŔeĎż ƒ0>Ł:şşř݅Ч˙‰ü0°5D¨&şĆ2LČORů„65ȏ*فt>XŠúŒÎÂň˙:ĎGă'SšOő0ŃM-ڟaŇ "?ŘvŁÖüŮřp$3(ev@äG]v„†"~AŒÄZ“Xn(‹ŤňđŢá_ŕ#¨ĎuŇ&ňĂDH° ZĘ mł™ŢVčŃ&+ä‹Pƒ;wyä‡ÚŰŰŕ¤5ÇVś‡]ňäĄŸ¨lϙ7Î9ďipÍţ##cŰuođfGF˝Çj⹯?#ŞO ˆü0°5D¨&şĆ2LČORů„6cäGÍš]dÚ,,Žj.ŤÜˆ ĹŹŹ˙ą!?a3Љ–v–şŠĹŔĆçChTä{$ô¸ăކE‹şC!he´r °BÉ5ܲe<üđِËUOOufTů‘Ž!Ô :X{Žá-nCᆲ¸*Žm‡ÎB •c*šÇ)ǒËEE(Őá™ÇE,”ú°i›iÔ–2CŰÐüÉňů‚÷¨‹.&&ň°iăVȔáÇĆ˘Ä ›MňÔĆm0>žŻąe ʞuC°8%chÍCżiÚ*ԓş@5Ń5–aB~’Ę'´)[óŁ„0:Q‚BËz(v•@>Žägą§#W9× ŸŸU†ŤQLÔĘgňö]]l|>„†Aő˜K>Ÿ‡ˇźůupöŮg@3á–[ţ_űúw Ĺ[W‹‡Řďˆö>VŤHä І"~Đă5)ZXâ9`ŒČ‹‹o§úŘKř†S3•2v›ZŠł›ůÁŇMD€¤ ´”ÚFäGř„ŽJ8”"ŰěŽVЍO€0c׎˝BůČđÜľö!Ąœ­Ľđ[`Âä‡ŢÔÝů‘­ĄiS^ĚbB~’ĘGŽ1ňc÷PśĚ~%ěÉ,…˙üÔ×aŰśžlŢź9đýŸ~ÚÚZ+柾ňżŕšŤŻ¸˙ô}Î8ëÔĘö˝wßďyÇ":>ă\řؕŞlłń˙ş—˙#lÝş­RÖŐŐ xó8,˜î_PĹĎĎ"ëęUÝF‰ ôd&şŠĹŔĆçChT ž˛ăŢŞUÇxäÇwžőpŐĎ˙ŕÉ›őqů˞ Żăpó-ˇÁc=á_"3*Ă ň#;B Đš .…ĎqÝÍbŠŞÜmĐů­çâť:2Ş^™I逓̀“Đ9ŠäڟÎnFä_HC45’ĐRfhK3?˘[î(›ýQ0 @ꅷHŞK€D׌*8D~¨eiÚš6ĺĹěĄI~°/#ă%ŘŰyŒöÝnŃťţĺM. ňŘłg?ěÜš~úŁ_ŔkßřƊ‹ˇźý póßnƒáá‘JŮ˙|ţkpĘŠ'WîŻ>ĺ$8ďÂsŕŚoŠčÜxýÍđ‚='­>ÁŰfQo{כáCďűxEÇ÷™ő/˘ ô8 €a Dz2ÝÔb`ăó!4 : œ2%Kzߛü``9°\˛tébxôŃu1řń4A䇉!đ.ˆă]"?ńŃy`V ŒAűxAŕÇ8°˛XŠŕž×Žśfá‘im0Ü×™œŕąšŕŤ“/‘|! ŃTAH*@K™Ą-‘ŐoĄPHíBŠóނ֙‹alÇc0ž[DÖëú:˝T€ČŔÚL62ĺÝu:éäă`úô^¸ďž‡˝7˄Á ćUY ö%D~$dkhڔłÍO~”—ŢŠ‘ą}},_‚ž“*Ĺ3fôÂű>ř6řĎOöěŢ?ůáĎáŇ˞ sçÎ.˧Ă+^óRřćWżWąŮśu;ü旀˯xaĽěíďz Üů÷ľ‘GŐţçó_‡Ż÷KÉpÖ9§Ăig< îźýŽhĘ,7ÍŇ 71*vk"?ědźmBj‘źENłĺˇ–ä‡ú+é‚ĺČËa`oc‹I#kiů‘Ž!č\‡ÉB ćm;˙¸}:kţO6FöŒŔ×ćNŔŽÓ!ÓR™ ÜuAd ňƒ/¤!š:ˆi(ź$ňC(a'sĹRô¨1}őó`Öé/ő-KEŘqÝaxă=Ţö<××ćGaZŮçZĚÂ'łí•˙řś×Âg=ÍűÎ^­{ĺÇ˙Űť0Ťdâţ€+„ ł’Íüœ`ů‘­!šňbśůɏř÷ ÁP>ĄÉĆą/ra$Č{ŢűFx÷{ţśěÜcŁ‘ˇˇ ÜOnž7n÷Ţ­b!ś<ཎ:€Ó6ě=ö– ]Ŕíޡ)ę ŸVYď#˜ ‘á iДű‹Ž.‘SzŻś­"LxL6ůäÔ!xôĹG´^D~¤cGH˘ bÉq´8</Řu°iɆNw'{ÁŢařro'8˝í \ŁXöłBä_HC´! ¤aHđbČ~ipᕏŽÂNŞfŹy^uŰ˝ł4ăäçUK‹ů ůÁpŞK‘)Á'łçĚŹ ípÉĽŔwžő“JYэU*UŸÓÔYąžD~$dkˆŚź˜UŸ$É&Éăů\ÍAfΜŮđĚg>úŚĎ‚ĹK—TĘ÷îÝ _üŇ"şK–.…7żĺÜ1[Ýńţă˙}"B~0|üß?-­Őošĺf¸ţúë¸éUfz„&ĂŻfHPwü: e&şD~,`J~0ýŽÎÎH;n˝ó¸íZöwě™wîžI"\‡N77˙•÷™˜h‚Č;B Đ˝  >ů,ÉWĎawî€fÂź™˝Ţ߼îM,Ď n.ř 2•Čž†hĂ@HCŕĹ ‘ąMŒm˘?7ĹťYńßmśćHŠTŞČÓ>"ňŁn[´é˜:亝RtLww7źíí}ö3Ÿ†ĄÁÁHŮż}ěăĐÚZ](uíÚ;áwżűmDç’K.…óĎż ˛ÍĆ˙ż}äÝÎň…žGviDeź^‘ĹPýߞ´ýEWw’É:ŠK*ňC´ j6Wű–•wż´đ$N€„ŃҒÔ+>HA +ą$1ˆü XÁâ‚8ź~ěo]ĺ›jd2Ny+§rŽ~ĚÚ˙Ë|•ĘÇaßsđ7Ar| çŰą^ÁÉQÇOČĄB.*ŇË7Şc ąPęCŻŻšB˘  Š#Á‹A"?@ǖ 2Ą;ĆěÇűŔ}€™§žÄß.˝íÎäŕX€îňňÝN6:ţ]'śVÁˇß§ŸąĆۇëŻűk$*#@ŠĹ’$'zě%M[tÄ2mWMq1‹ ůI*š.VϢŞ'TŢŁ*ĺq˜A¸ţŞaŔÉĂŢý{"îfϜ_˙ĎďUśÇ'Ća`÷8\öŒË+eíííđčÝĎW*e›ˇm„ç\ô’ˆŻe „Ď˙{Ug`¨ŽZr’÷ Đ×;ÝMëžĘp F%ËכvąY N¸‚Фű‹Ž.6W>„Da:óŁlĹ_żÇĹŃ?;tŔƈ“Ŕ^ąa­˝űh‘ƒŕŘbi§śm;ľ-ÁŞ âđŘ Íţ¨nGměœŮLĆýd!WţËś3NĆ{ě3XŘť„%ϒ=^tĎsŮ6ű^bi{ŁoLÄŕw ü˝šVôŞiVszÄ^2PyśřuÝT>ˇĽ:|#óX ˆ…Rh'$¤1Řp’*ě.č¸2"?˘[œÝxoeq˘Óf÷ßýÝń8´ÍX #Ű…‰ý[*˛Žî;sŢ"¨ƒîřN.ík_ţ.Ü~Ű]0}FÜwĎC°oßţˆďbąŕÍAĺUA D~ÔmkE~Č\×uĄY ň“T>ś~BăĐKůÝ#=ćÁ˘¨Ý KTD Úa>ŹŽŐŮ-ęƒc!Ž1÷NôX¤dž÷_Ü#@‚ŸšˇiĘHƒÉb`sĺCHu‘°qńĘן˜+űń~ 60™Œ)ʋ{IÇNmK0†Ĺ1‚üʜ‘9—ôhÉćźO.ë~wˇŮ:9Y÷ü5<Ä';А/ůoCdÄGÁ=ˇeDI 3>I‚P&?°ú(¨Gv`%—đśŸeR“.BY/(ä |"?řBƒ“"@RC‚ƒD~€‰-;(„× 0ęěĂá"×dZ¸˛’{—řžťź ĽRmNŐŁA-ˆü¨Ű–ȏ´ňąőS>U Íy'n12r˛0<^„ą|ÚZ\‚´|~V3 „)VNř`ňű ŽŘ\ůEňä‡˙c˙ŞWż„+ˇ%@L^5‘éŘŠm ư¸ Žš”¸:ŢĚ—řhÍľ@k™iÍĺ*3BF‚xä#8 îůhŢ˝1—/äÝżEpŠŽK€Ëł@œ2ÁŻËÄ3HüăŸ÷ Ę˘áęzٜí$ňƒ/ÔŽ!i’ ź$ňLmŮŤý˘+ȧ ˙˜b,'zě%M["?ŇĘÇÖż.ŐŕŢĄâ>)\ƒîž8Ř?ŞÔËćŠpúi÷ÁęŐĂüůƒĐÖœ&•Ę'ĽňÉVuťXĚB):``wôd: Ť-Sťč)Íü°“™ęęBŇäGĎşřĺü ™4߃śDDEÓÂÖ6fňd‘SÄČŰ☲YšĐ,6F„ä|"„‘ oTf€0ň#—)?ă=’Ř2ňcäŔ ”Š%PćLäGÝśD~¤•­ŸÚz%ěÄK—Yśj><ú÷ÍRYłöÁë_˙S˜š¸2mËÝî! '\žc œŇ„{Î6ć~÷ţ‚ű˳٢űh™Ŕýôoꃹ˝3ać4˙čż×Ďť˛=„ŽůšbŃŐ%ňc*#)ňƒë'Fr´|آ4źňOüEOŮŠĚÏ ěŽˆüW„ȏ„aqA,$?¸ĂŇńÎiýu@‚ľ@ʏĂxëdˈ? $XÄ ţs|ö¸6f ňř @…aäˆ÷RŃ?Mő&Łř$;*úk–Ź„S_ţ>˜poüš÷ýćuôÁžbœŹ€ ­šË o—jJuřF¨ĄŁ ÂÄ˘ŻšBťŸ6B‚ ¤Ą@}‘`eë°G`˛‘EP&^ľ gĎňž.˜­?Űšżěňś—ŻXůŘ?WfœzújřŘG>ăÍě`EŸţh{”˙x #B>pe?ÜűŕDĹ7Ó…RŠR8ţÄ¨>Zň„m§:ů! Ó°‹YLČORůŘúAĄ.ť‰Äf€d4 ď.—DwZĎźő­?€i‹O§eşËkl]ď2ĂĚöđgýd‚Ů œýĽoY? ¸ĺýłĄŻ# Őž×v2Ľ.6Y>@HiÎüŕĄmľ=RÜů0ž¸1œ$"?LěÄś4P­aqA'?PáÇńfr8!"ÄńÎWýďŮ 1âń'ngŠNČwŐ›R ŻWW&?˜M1Sň÷f‡ÁBŠlďMŚŹP °zń řÚŤŢٖ6ÚżĂ=ÔćaÇŔ^héěŤfŽáŠýŠČĽŞžÁD€4 ¨/#ňŹlËÇŢ 0â~/ž>3˘Z8kf…9óěS#Ě,Zź–-[O>š-ČUČϕŤöĚ Ú#[5ú /ˇ&k+‘ŒČţv˘2LČORůŘú‰Ö9ř÷ ôďq‰î‹_ř+č^p<8­sĄ8p+ŕŘf¨˝K`ׁiĐU쀖 Ÿü` wˆj{Rú§‰É‡íáŠFNěäcčť/„¤ŕ€úIš¸"ňĂČNlKƒÓÄČŰŇčŃč fwłžŃń ćłţ#1ÝmpƑŤ`ńô9đŕö đ×Çď­žý%üć§X_ŲŹěĎýď¤E+]ňă˝ĐŐÖťwď„áĄ~¸é۟çřYüĈüŕ ľëTÝ šˆiP_FäXن,dˆ~†˝šs´ŕŢB-rz°Pýzp¸ĆÝÁażlč cĹ}â#ŔŕÁhlHIř\ ň#["?ŇĘÇÖjéúŔč­ÇĂČ‘nOď,?n8mŤĄtđţ ůQ(A~–_ż+ńÝá@ë‚LtšŽűľ}Ö^Ü˝fvĺ8‹ĄˇNĘíIél˛|$2‚1=ó#Ŕ+_ý"Šüúën‚];÷BăA䇉Ř–§5,.ˆkČƒęvą˛†bŠüš[öřŠ_,děw3l=,œľüh¸đč5ޛc˜“#g/€'wm…}3a,?ěŘ\&@Ř[cœŠ˙÷Ă÷ťzáJřĘ+˙Ů#?ö¸äÇÁýů1§;Ëgf*őr$•áĄTGĐ(: *L,úš+ÔŽSuƒFhz $u žŒČ°˛-żŞ+ď˜ÖŸm…‰×-Ěš?đ.ůŃú›mŮőţœvÚjX¸hžˇ}Í˙;wřďß<Đ_‚_5 ŻşźËcơď*ÂĎ%LüEP=öRˇ­ůQÇa˘ał‡ůÁžłYńÇZ­š íÝ­GgosúŕᘼżvɏůŢÚĽŃ'˝˛‰%xňÁKaűŘ)PÄöPX„˝O ÂŘĐxĽŹˇcœ}ŇOaţů!A:gŒÁĐŕ,†*řŽQçÄeJ]"?Ś2E~Ä×8eBŻ|ő‹Ľ6=đěŢľęA¸~zëŹÖS‰üW„ȏ„aqAŒ a# ĺENŮ[^˛%Fx”źˇťă&xL†Š–l <˙¤s`ŜEźĺ%8}ӹυžÎn`S?ţ‡ď{Dˆˇ`jy\ůŻŇ-y났^źžtĹť<ňcďŢݰˇ˙Üń2ůÁO–Öüŕ ľëTÝ š.ˆI¨/#ňŹl9Çţ#0Ń;ÉŮľű }Ý ŕÜvpśŒ‚3ňoţ ,;b Îíť"ś?řů0\Ó̘ž…'Öça|"=ţR*q"?ęś%ň#­|lý ‘Ÿ gԏîSœ0ďQ÷ÄŽ°0ŕ-jĘpÇ_.€ż?rąŔ˘+˛ľxŒŻż^|ô^čZyŹťĎg 4üäÚ°ňćÁxî•ďŽ@ĆÓMZŚÔ%ňc*ŁŃ3?œńœK^i#ӆ ňƒČ†ÂₘK~t÷(Jy6†÷*[ö¸JŠč͘ô[ńɋL™élmƒŽ>ćöĚđ_s‹ĺٍčSÓ;§y~ÇG=Ÿšňů˛ˇf\rĹ__äąËáó/}tşäÇţ}{aĎţ}đŞoţ?¸˛WB~H+"*BŠßČ<(bůqxÔ€ú2"?ŔĘ66ó#@&{&PČ{ …<ůÄaű΢÷áŰúďWk˛śɈüŕoůQ7ůÁŕźW†ś– ×Y›Ë6Ub<°ţFžW/é‚ţţ~čňlĘż™čOHä1˜ŕÜËwŚśżčęBäGĂôpĹd=ö"Â+bĂčLÖxđÇŕŃáyŕtĎćĘ'îűčƒČ;ą- FkX\×K~00’" AŘÁś÷˛•×ß2°™/}څ0ŁŤ×Ű~|×SpÍĂw‘3çĂӏ]-Őْí|ĘË%Lžx‰ű˙ń €Ďžř­™Ň`?ěŢż×#?ĆťŘecSo”Oá"ňCŠlČs!$"@Ręˈü+[ÉĹq6[űLš`‹ b˜Ą™uŰů‘V>ś~PŠëąľ8ŘIU.ÄŁ+Đ%/ązâUČ÷şžľ]¸ż ěc<ŘĆĂF÷‘&‹üp$0Ż|•|=~ňŁ_Á{Ö@vŢ*Ž<˙ĎAD~˜Ř‰mi0ZĂâ‚ŘšüŕřńI,“ UňŁT&?2îvkKźxőyňcíŚÇŕÚGîô^mťlÖü2ůQuţĐöMň¤Tń°jŢ2řžŮ#?úŔνťáŐßú2ůÁËéąžĐ¸Ż‰üh$ˆi(ˆüHÄV0ó#ď˜iŽŻ—'`™k÷@& żtZ ŞcĎŃçBĎQçBa|öŻýL¨Ž‚łŰ ˙ź…PękÜ]ű!÷ˇ=ߑ5@”3? Z2 ŰÙüšJô˘ďđ!?x2֍˛…MMĽ<„w\cżčżâ/îǗ žێn˝2Ľ.‘SÍ6ó#Ŕe—žěđk¨D~˜Ř‰mi0ZĂâ‚8)ňĂ+*ĹʨÁ§T^ÄńÖúŃöŘËtď2úĆÇî[ž|Л|Ίŕ¸ËźňáńQčjë€Ń‰qXż{Ť˙Zܲoöý˜šKŕĎŁG~ xäÇkżý)Ÿüŕ=ę­sŞĆ=ÜJÎ+D~ˆü $"@ÎՁLޞČ ňCaë=›ňžâ8Ź)ů°Ź*Ą%ƒđĂŹżc÷Ň50÷¨čvĚ=6˙ô˝PʏťĹ<öŽŁ<„aâ¨ic%ČÝQ]řÍŚH˝$`KäGZůŘúA+?ÁP`˘%ńŒ7-'"eÖ~c~Âç+5“ˇŇ胺úç%?˛S%?⃖OÎĹkŢ|ˆ°ăîmpÜĚ#aö\ţ+1÷ěÚ ×_ws4:J‚‰rŮ)lęąSŰ6Ř– 5,.ˆ“$?źâéáŻ˙á’ôŢĂBexÚ˛c`Q߯˙oßđ0ümÝýŢ,‘Łç.† >Ů+żkóc.ąŃÇÎ_ OěÚă…|uF‰ësůěpĽK~t0ňchśďÝ oüîg`‚‘ĺˇĚýFĄ¨Ľ:|#ÔĐQPabŃ×\Ąq_ů1 ¤!ˆŸh(ä*{ r-Ů!<ó#°őŠŢf—I'—˘ëwœŠEřaů{璓"˛\W´ÎZ c;‡Ň܎ ů xBo„.‚ĘI•sĂl‰üŕťJô˘ň“T>ś~°n?lHŔxSóKŃő{Źý–řë5¤抁M–ĽŒŔŤ’eČá_óćӅ˛{ŕ¸hĹypü‰Çpĺěm1qDď/Q¨– ňĂÜFlG˜<ň#jPÂęëoK•×ßËëv¸ç¸îůîy+Nô~Cvîƒ?=tť÷ŘËňŮ áEkÎw˝9pďSĂ˙Ýy=|đŮŻôô6ěŰyöř6ú—ߏěŘ9‹ĄŐ=쇝{÷Ŕ[žű9oć‡ĂŢăú(˘Á¸%ňCŠlČs!¤"@R‘‰Ř\{Ŕ„~ĽőąËݞ:Ęoƒ*A21°3ęĽT€Â ˙˜‹łß˝[œwɍ–Ş~f×XDŸ­R˝×ˉ{QÉë'? Š]źaŹžZ[Zŕ}?˙*äÝăt†=" őL JĆő ĄT‡o„: *L,úš+´čky.„4AHވíÉD~€•­áĹq&“'śČłmđžÂĚtÜÂwłŐ °‡ŽƒŽůGC÷˛S]Ýˇý ĂţŤ:ŮërŰžżĆ_ľÄ˝ ËBöáAČ]}M.[˙ŁÄ=‹@ ňC-o8ů!3­ë˘ň“T>ś~PKˇćĹ(œţ QdďăC`ŠUóó.I]źtűÝň×銑‰űŃj;GC7ľţÁäc6bżŤcXNhVňƒkŢTűŘËş?>Żé}Di˙•ÇUüH3ŇH†ČyEˆüH›¸8-ň#@uć#?Šĺˇ••@uĎiƒqôü“΁–5ěŘ珻Çw>ßšĺj˜(ú ˆćÇĄ5× ',\7?ń ? „Ĺu˙x˙6řĚ ?‡žönČöuAfbźňÂ4ďńPvŁ@‡ 5?4üů1Ů $5Äöd"?ŔĘÖââŘ_5ÚŕšCojéööóÁ¸ľËŠďřó ÓÚĺ ăŢvÄßÚ}Đé^lať{97Rű*Ü"wöÇ$´•HF䇞i]}˜Ÿ¤ňąőƒV~,Ÿ÷„Ţă A'ďdę_Ő_$öŒßź;ŚGň%ča˜+ĆOޒ胺ú“ŮˆýNU‚‡f#?âdĹjÎş;îŮo]şTÔ (€‰ÚŠm›ÇNlŤŢAhH `qAŒź-‹ bńá¸'KŒüČ0ňŁ|*•2ތöŞŰ=Cý0łťrٜç‰]^ßšářŮ]7zĂ00Ť‡ˇo†ł–+ć,‚?÷u°ißNČš7 Ůşs{f@gK›gߖuđ•żţÖ[`Őń ţ–ÄŠ˘¨Ľ:|#ÔĐQPabŃ×\ĄE_Ës!4D€¤"?ąľź8ć˝&Đ;‚ŇİDˆ\ňĂ lg"?ôLëşčÄü$•­Lȏ˙8IKցlűfȨŤ0ů˜ŘďTő x8{ůöé˙[ůĂ'Ţ{ŚŇV4äMęM䇼"D~$ ‹ bämY\KU*‹ ˝őćücaŃq ‘’ăÍâřŤ§.;z;ť`˙Á!o‘Ó}#ƒŢě­ŸŔ`ëƒ,ž>–Ě˜ ˝ÝpҢ5Y°Ąť}`´ćreŇĽä˝fˇČš) ŇE ™ Ő`Cž‹Ň!!’6ˆü+Ű:.ŽŮ#0›Öç(P#ˇ‘YŘůĄ‡ş.ú0!?IĺcëňSEgKŽ;r\së˝°Śgň­-]˝{ŕÜWýôąœÖŁÜ“˝#]âqrÓśCiä1oúm"ĚĎ9W|zgÁi[ Nf`ară[Ą}b?x|آ ,dJ]´ó;ŮűŞÍH~w•_ţĘZřé&ˆ“ĄáśpŔä¸-8śÔq1qř’4Nm.ˆA~„ÁwqźO %đÎsKebă {Źźńń{ŔEŽ˙šxv#éxkqąˇ#şß' yřÚMż…cç-ƒŁć.ňŢ ĂfLLŒĂĐŘlďß ›÷í„ÝCýŢĚÇłw}–Ş9ďĹ@ä‡R5ؐç˘t@HD€¤ "?Ŕʶ΋cŢ Ĺ ˛đĎ˙Ř˖eážóđß_‚ĄĄňݏŤšŃb(œ9œƒEhýĹČ<4Pą=Ţ˝óüćâĚpřovßÉśAÁ0§ŞÜ‘ČTś2"?ôP×E‘áďÁš Ác0šŹg•ƒÇwţŽâqp&\bĂá/~ÚŐ9ço oĹyŕäfşc˛Ĺ=ásď6šƒłuŽ{–…ŇÁ!üřĘuťoćúůŘŰ~ć’('BŚĂ˝łĺäŘÔ.÷H×ë~˜Ýěr*ëŐuŚ5?%8N§š}ćG…ŃÄOň[ž@3h@ˆ˜ľ ‘Ś6őŘMyX\§J~ÔÄ*ż×)ż —‘ n[ô”Pył;Ęł<ĘËÄűä2Œ)ß,ˇGwl‚‡ˇoôŻ |ąźuEô˝açťo­Ź˝šˆ˘ôCRívA …&íĎZôľ<—:cŒAHZ ňŹl¸8fH|ÔźŤŽZîďîçœŢĂĂŸűŠ˙@LáĚYżxŽoÝÝăo9Ú?ôK†ä˝÷ý…q˜VŽůěRvš†ßfĚŢbŃĐv&ňCu]ôaB~’ĘÇÖÖĺÇ{R„s7Č#AÜŚžö,źćěŹ^z/ ŽŢíÉWÁ›b†F‹pĆšý0}áqî¸írĎ´ZÁÉvťrć˜ÍňpÇrŚ œ–Y€;*aÎ?é0˝3ëŸĎšÎ†ĆŠpćyŽŸĹi?Ň5ívýu‡Ü“¸‚ťďš„Jëlp \ĽúëřěŽĘęIéL>f#ö;“zĆhvňƒíűĎÎke `ଶL’ŒÎcrNĺřᘸ4ĝ ž&°ŰŞ;™Č,.ˆ‘ˇeqAŹÖ ÇH÷?'4ó—íq Žénل[8⿊ĹýŽlËëd;C.:vĚëÍyNŮşŤ;‡]?Gîuš’Ež>#=J#ž˝7g—-ŢVňfƒ@@€dœşëœ\˙`ň1ąß™Ôă0Fł/x wâĺy çÎŽŚâޑÎnőžďpî§7tń¨cňV fG˝¤O~X)Œ/úĐ@WC6i~0!?•OŐmđˇƒ;JÁ,§,ôdĺ;KŁů"äşüłRŢĺ*†Ü35—ô`ë{0â˘4ćÚşcą4Ŕ#ËărdÂőÓ=čűaSwKĂఇ¤=?Žßbŕ#ö Üp]d˝ÔűHŒRíüNö~gRĂ‡Â‚§r'ž”[^Úő—)(g_,[t/&Œm›ÇNlŤnC"?°¸ FޖĹąZ'&B_\J{Ś”çY„GŸ?ˇŢ˛e"Ă÷‡ŢŰ\JĽ’÷—-tZ ÉŞśŐ…WK%ŒčńӗœWPCG!Pvęl˙zúZžKąuTQĎE*´ôl+8LČŢkp?őĹAř§ˇtÑKZŕž&ŕ[?Źžń%{Ç>h™Ó…3g‚s°-WmöWůw“űdśŢX÷Öš%“ƒk´‰žâ2•­ŒČs_ôĄŽ†lŇü`B~Ô˛`=ŕz'Ě#°¸|Á=Aȍůeyś@iœRkĺŮd¤…ˇˆ;^‹Ńw8y‹Á•ż‹ŽŸěhŮπ'Ă ó뒕Ţlq÷ψŤ8ęű ů`É8ŃĔő2’)uŃÎďdďwőÔă0ÂĄD~0Œý(6dŇCplŃ˝˜0śm;ą­ş“‰üŔâ‚y[Ä<85Î#^€•ăf0 $đˆe^‰šľÁŽ`f{•n _&5ŠĽb…áÍÁňů‚O|”‰’R‰“[đoy–‰vť †ŽB€ ‹žć -úZžKąuƒÔ€uČQĄĽg[Á$?ŞĎ+ÖĘ2啫ĂŘąŤźr@čžĺwŰźťw”˙5×f@ɉcÂíLä‡9Œ/úĐ@WC6i~0!?Ńmî,ŠL0„Gš;H1ďŸPářvW‡-źÖRU`ł7<d°P%@0ś 1‹]̗OĂ&ś—ç*DЎx*›MÂŻ )˜ŻgRú“ŮˆýŽžzFhvňŁXôR.—ó.lňů‚–cHŠčśËĄĽĽĽœ[đÚkÁąE÷bÂŘśyěÄśęö$ňC‹ bämY\Ťu@pόý&8e˛Ă7`¤d x!KÉýžńž{¤>řo‰aş%ěp*cś<΂1bƒs>íßŔĐă2Ľňkxcé;’ó ~uԊ¨!@…‰Műó„}-ĎĽÎX„D@H*Ŕ:ä¨ĐŇł­ŕ0šůŔ[uRďZ5°‰ü¨ʋ>4ĐՐMšLČ;~ă'źHÍLô rĆŘa(ď-V ă. ™í){cgplýöhĚAż&ßďű vöƙŃţ˛öŞ[öčKŚŁš¤÷8Íxy&ÉhŐĎ ęŐŮfVˆR tĽĂ ‡šÁS€­[ˇ{ß/Ůsá?ű= zHZ`DĚĺ/ťĚűžeË6á="? ť)‹ bämY\Ťu$Ž‚ŢzW>ńáŻâÓ"~‰ˇâ‡ŤPňŢţâ•ĹKË7"JĄ5=üOľ,ţ›…Ąß•RůÔRĺ.† >´ŕŠ"—:c jÉP!ג†äĂčč8t÷tC#ĐÖŢęýeÓýuGdGŐŃaęô/‘ č&ęň#—iÍ ™vľg`pk7”FG\žÂńgy0’Â)šźÇWŠ5Á÷>•Îlu’UW›ëg{Wُ{wk|‡ˇhŞ“ió f’„H†}ŽŸŽŹş^Ć2ĽŽiĐLű]=ő8ŒĐŒ žFsňßú°nÝzŘľs7źţWxŸfËé‰'ÖGndT×OŐşÂâKt.xšŔNlŤŢAˆüŔâ‚y[Äj2Bk㰙ŮňZvŸÍÄ> ťvÖň“ łwfmčLv8ş{÷BçŠ,ČPqI‹żgaÁĚ>hĎe"1Ooƒż>lŕçś,,šŮ mšLőg‰GvġëęKŇ`˛÷ť¤ę1Ĺq(‘lgňďöŽŽÁž}ű`˙ţý0™˜1c̜éߝŠÜP ňRąŰNX\§N~Dî85şN6 ÁY.ž ÂĂŘř8ě8¨Ő‡cűô,]Ů\ŤwăŻT^ÔÔÄƁ˝[ž„Ý`fo7tľˇ ý9=<<ęćĘc>œč×řš¨!@…‰E_s…}-ĎĽŽX‡ŃńłŃ ¤!@-*äZ˛Ă–üpźtF`ěÚš 6Žß š–xäáuŢÁPŐĚţ(/ţ„ĄŮ˛“X6äşkor÷<80螰ő¸¤HŤwŔçL˝¨lŐ˛zm5Íâęfş5öƒ ůąAě´C7Š‚ő@ĘŰ­9V9nżłOÜÝÇf˝Çaâž'ś—`Ë}YŘ56Î;ş˝şÚ|YľŐ=;yŮt¸ýö‚ëç€ÚĎč¸`e{ĺgŠB`ŚÖ?–¤ÁdďwIŐcŠăPXó#ĐgŮ#›ƒƒƒđČŁÁňĺKĄ™Ŕr쇎Žřpó–D~ŘŘNX\#oËâ‚X­Ă“ű ™Ž6¸ĄˇNvˇ÷ěÚýG¸ęŤŽ\č2˛"ŠQxčG“j,™;Ë×toŽ{j'W§Żťfϝ ×Ok‡Lg›Ô_ÍšˆPG!@…IÝíoß×ň\ęˆu?'D€¤ԒĄBŽ%;LÉ‘|xdFGűaÎ\„bąűöŠďníŮ˝&Ü|†žé=ĐĺţŔóÍfĄť§Ëó=>^.ě˝}=̂—ŻÎ˘Ď0;ƜĽ2"?,m5Íâęfş5öƒ ůą…śƒ—°f‚„×aşszrpŇʙpűă9X´y·Ö^đÖv+!ôďĚÂĆÝĐŇŃçÝ•ĺvbń˜Ÿpý<âúŮäúY0Qëg_7´ś÷Áy+şj_ŮŤ‡ŁQGîvR¤ÁdďwIŐcŠăzě%d×ŃŃ ýëM°yÓSîqrŚwó'ńŠ˜Ý`Ř˝klظŚM›ć•ůż2+qžD~ŘŘNX\#oËâ‚X­‡ Ź,ޒ…ţ“Ăż?´–u´Ať÷&ł¨vaţČLkmą‰ź7{9 °Í­-9ŘšînuoîeœHúŢ#ßm­°ą0…“Cś%[.ŐĽ’$pî(ĀT˜ÔÝţö}-ĎĽŽX‡Ńńs˛@HŞ@-*äZ˛Ă„ü/ćVůşˆÉşwł-âÝúŔţ~čžÖ ‡†˝ˇĹ°g[Üů O>UYĐill–Ż\ęę@Kv t­ŢTÁž˝\żí]ÉfC„Ű™ČK[M3i€[™lŇü`B~,dÝČłÍX;„•Íďi…§?ßŮkŸš€ć]˘ŁĹ´ľćŕčŰpzKÍ̏Čw z[ĄoŐLxĚősç† hq q\?Ľ´ťăý¨EޟŢȄ~7œňű5ĂLç‘NŁ24ĐM@–Z Ëzđś§ľÇ^â1mZěŘšślÝŠ b ’‚nžlćrYůÁcAĐ2fó؉mՍFä‡(Ü#oK§,byĹČ:vţ›^˛=PzÚRXw`JŁůGč’¸ĺ\–/Ŕ`˙AKfýžůłú Ë=—˝%×÷52m-ÁŻc0ÓŢšžNČść*9×ŔSW4 jPabŰţqĄE_ËsŠ#–šc‚ˆI ¨%C…\KF3?üPîŻpk{;tϝ!Ԟ>ŁĎ;ɛΈ ĘwĄ3pާzëƒ+916}†ŤSňtű¤wĄX‹=Ú*ÓŤ UÎZ2"?,m5!# &ű"ÔŘ&äÇB&ѕÍńTˏÄtľf`ő’N8qa;ŒL” ŕ–wä2.q‘ŠńËŰő‚óČN×Ď×Oqa×Ot‘S‡[‡ČĐśe=xŰS‡ę̏8Z\‚żĽ…o§˛ĹÓˇ[f~¤aǡBƒ…Âbämé4‰EŹZy ŕ3"ŢŮc0Ä%ZćLŤúŔ°S„‡ŚuŔÝOí옥OśŁ†odZ[ Ýs߈ ú¸kŢŻjPV5¨0ŠťýíűÚ|iÚĘcłÉ@H*@-*äZ2"?Ęąü#FgwsÎj8¸aŤĐŞň( o}@Ÿŕ0ě!]ቘ[>ڑƒÎ:Z<6Cł;V‡Z˙ů‘€n˘~0!?2 ]ŃL_šŮĺţÍečiϚLjmËü„ꏚ1ôóAÝdŠĹ°Źo{ áP%?j_‰+ś‹ŰęĆÓˇ[PpaĽ° lMăM†ŘVÝŕD~€Â a1ňśtšÄ"–J!L6T—NčŽAŮŚ\Ţ2§ÇűTÝHŞcEěĊ06Ű2üXwŘAŒü°ş(>‡‘ďś6íoß×ćCH3ÖT›M"@ ä|ăËľdD~Ԝ̱…ÝVr<ŮŢî­0Ú?c#PĎC缙 ~ł—,ŽżĐę°S„V÷ łhĹ˜6ŤVœp ̞7GjëÔ,6 —ČK[M`ĺŸĐ6绉lŇü`B~,dučF^‘[šíUÓťĘŒ '& ?z\ˇ‡œP†}ÖĀ:ëŒş ČR‹aY•î!ŽC}懘‰–MůÁ@äGňv|Ű)40Q¸!,FޖN“XÄŞ•Ł@=D‚„˃ƒďŘąŒœüĆs­LŠÄha|™ť°Ź˘Ž¨8jPaRwűŰ÷ľůҌ5•Çf“‚†9ßřr-ŮaL~Dî$×JÍĺŕ¨WÁÇŹ€Ńá8°gż÷ÚŽśś6×sÉ:Ž‹ŢbŠlŚÉ´ŢiŢßl. Ń+' O'-gMÄÔI\‘ŮŽ8WŢ0#ň#ŘśŹ‡J÷ÇTyěĽňřYxZV؋vĚZESňŁ2\•sbÇD~˜ÚNĄ‰Â a1ňśtšÄ"V­<¤Ŕ=Ÿ­VÇFřŽƒ ŸmĄ’C!( ľá+š†só—5‰Ďaäť­MűŰ÷ľůҌ5•Çfƒ†9ßřr-ŮaL~đäŐťYXaGźő@\ƒ-pÚ3˝Żl™L\§f `ôŔ'?ŒŸc&ňĂŇÖ‚îd_„űÁ„üXČ,uăëxe‘ĹAĂQÄ@‰Ě‹ňÜęŤ3č& K-†e=Tş‡8Ś ůF0;1ŽŻž-ŽkłvG5žńŐ‘ĆśSh`˘pCXŒź-&ąˆU+çDw*…ÁFy éË›j0"đɏŘy߇ˆ‰s˨0ŠťýíűÚ|iĆŇq<…†k3Ôœo|š–ŒČ?Tl odVˆfĎËwš $ţ]œÍ8‘UE¤†âĂ;ÂDdń  š–,ŰŚ&?TŤë¸ě‹Pc?˜ YşŃő@b'[;ŽJWdGäGy۲*ÝCS‘üŰUg„TËtě"%ş5v*śEě˜ČSŰ)40Q¸!,FޖńVŽbőŕřĂő=8…'gChŻůQöYy˛4v^!šńńƒ\QTG!@…IÝíoß×ćCH3–Žă)4\› D€¤ ä|ăËľdD~DC†g~@Œ ĎŠu°źŘiČ[„‚ž:ŞuTT˜ÔÝţö}m>„4cé8žBĂľYAH*@Î7ž\KFä‡P&ZÍŢ#œŘI¨#ZU‘ď[g>ŸčUˇD~čČę´ľ%?d!}jěňc!KT—_.1!śąÂ!ްć­ÔEÝdŠĹ°Ź‡Šî!"?ävzś‚c‹ĽÚśyěÄśę'ňCn‹‘ˇĽÓ$ąjĺ¨VőWř˜%[ż_ŤĆ ŠBŁT§Ćwä‡Ý~Ű` pCXŒź-şZÄŞ•ŁZ]§żdqœPŹ$Öüů¨¨Ł†ŽB€ “şŰßžŻÍ‡f,‹ž>†ĺĄ "@R” eD~Řن<­=‰M>Ž#\AQaK䇝mä‡,dZ}uůÁ„üXČŐM &ş¨GSäc+łŹG=1ů!ˇÓł[,íÔśÍc'śU78‘ pCXŒź-şZÄŞ•ŁZ]§ż´ňU( ݢT‡od ąäÍ`Óţö}m>„4cYôőĄ0,uŇ ™ŒČ;ŰŘĹą#X€‚ŤŽkôh‹LF䇝­SO\ łF\„űÁ„üXČŐM &ş¨GSäc+łŹG=1ů!ˇÓł[,íÔśÍc'śU78‘ pCXŒź-şZÄŞ•ŁZ]§ż´ňU( ݢT‡od ąäÍ`Óţö}m>„4cYôőĄ0,§ˆIh&#ňĂÎÖŕâ˜÷ĆůŁ+Şš…2"?ěl‰ü¨Ă…,QÝęa˘Űˆz4E>ś2Ëz$•O“‚Čšž­ŕŘbi§śm;ą­şÁ'ŸühŇŞ“#Ę6QjZoŹZ9ŞŐuúK+_…’Đ-JuřFćą@KŢ 6íoß×ćCH3–E_×ńS@0 ŠÍdD~ŘŮ:MÖV"‘vśD~ÔáÇB–¨nő0ŃmD=š"[™e=’ʧIAä‡ÜNĎVplą´SŰ6ŘVÝŕD~ “#Ę6QjZoŹZ9ŞŐuúK+_…’Đ-JuřFćą@KŢ 6íoß×ćCH3–E_‹÷™&ه8ˆI h&#ňĂΖȏşm;ňCć"­‹>#?˜ Y˘ş ÔĂDˇőhŠ|le–őH*Ÿ&‘r;=[ÁąĹŇNmŰc?˜ YBşěü,|QÉş1ţ"Ś@\!% úWC?.+ľ÷‚sö;ˇƒsçw!ăčĆŔşó1’ĽòiĺÓ$˜ŠäÖ GϘÓQé’ěăڊ…D~˜Ř5ë n‹‘ˇĽS=‹XľrTŤëô÷÷ł<>~,uœĘŻŽT‡od ąäÍ`Óţö}m>„4cYôľxŸiŇ1:Ĺ@HCŔٙ‰üВ}ŕUo†ÝŰwTś˙ůł˙ǟş&˘Ăäxĺ["eßşţאÉfĽžĂŘśq3|ô ďôžżńý˙g_z‘Đvý#ĂŐ?şĘkŚ…Ë–ŔĹ/š ţňëŤáG_úŚ'˙ě˙}f͟Łw2ڙȉË$.úŒý`B~,d č˛sł’űO漿€LϢЏpőť!łíŸtŔ˛Ţ´}ů/#?…ŻŸ Y,UÉ‹zyžgŮ+žëm˙ôQŔu׎z´w™W–_ 8űž¨ Rľb&&K-†e=ŇʧI0ŐČVŸŸüäű°`Á‚JYŠ„pŕŔ~Ř´i3\sÍľpĂ 7¸eęxúqÇŐľ“;Î˙đ‡ßBooüéO×Ŕ§>ő¨žž^j)ń ľŰŞ;‹ČtrDŮŚćEŞeŹZ9ŞŐuú+ö{ÉĆňŸÎ}/,îœ ˇîY˙pĎwÁQq˜Bˇ(Őኰ†&uˇż}_›!ÍXŚ} ˛}ŚIÇčD)ƒł3ůĄ-ku2 }îúËÍ5:wÝxKD‡}LăfÝŁLÎÉzŸ''ľ]vä°â¨•0kÎlXý4ŸŒiÍd+ąłŽŁWŽäm§.ůaqĐhŠ‹YLȏ…,AÝBąT{˝}äĹPt/İ|áĹH’â˛g@…"jŐÉŘ_>ä‡}g~ó›î€Ňđ~(l{ňű6מ_ÔÄ@혓łżčĘ,ë‘Z>Đ˜Ş3?âş—uœ9s&œrĘřđ‡?ŕ Ÿ„ŽŽi<ý¸‚c‹†]¸ýĂ3ƈü0ľľąk’A‡NŽ(ŰÔźHľŒU+GľşNń ÝăhĽ:,Ną(ĎGčĽ:|#ÔĐQPaRwűŰ÷ľůҌeŃ×â}ŚIÇč Š‚ł3ůaeŰé=fpď-ˇC~"‘Ýő×[źżÓzz,|›çÜŇŃŸţÎ˙Â×ő#˜wÄ"#[=Y:śD~HL’ş°3ňƒ ůą%¨ËNÔŘÝĺŕź°4>ěýÍq>ĄĽŹăŸËeWúHqt b_9竜řçŻ„ţ‡÷hKE/¤[(U•JĺdJ;…_ş†~řČĆ"ś‹%ÔŽóäě/ş2Ëz¤–4—Ç^Ţ˙ţÁ‡>ôQřâ˙Ö­{Â+;ýôSá]ďz{Ź âßQă"ßšü täl‡ËąL‚ČlQ˜OŐÁd§#ňى “#Ę6QjZoŹZ9ŞŐuúK`ȎA•1œ„š„?ţ@Âŕ{ˆ †ŞźlÚßžŻuşÄ*–E_‹÷™&ŁSôLjŕěĚD~XÚuÜ*¸íÝ0:<Ýy7Ź>ç Ż|疭°uýF`8úřcáŽŰî¨ń=6: ż˙ÁĎிÝý{÷CwoœtćÓŕůŻ{9ôÎčăĆťćgż†k~úk˜Ÿ€cVWźý0gÁ‚ŢwŚÔ7˝ć,\Pă{Ü= űÔ;ŢŰ7Ńr`hß~¸ů÷סßýęç wćôˆŐÍ×\Ţ÷ {!äđďwĂĆGŸ€+żű%<ń—ń'Oľ8Yiúßűě—áÖ?ÝXń5:Q€;ŻżźýřđW?sŐć,†];ůĄé˘ał˜ Y˘şüz”ĆÂÄî' uÎQ]ńL(mžŮSp–—g ď‡üţ-[oIKd^ř —”X^9=ó!{ĘŤĄ´řT(ţň Sœ€’;ć2/ř_ČĚ9ş˘×˛úĽ€3–G}Bô{BĆq œłŢ š3^[QtZÚÁY´Ú˝[ ů?ţŔc×VKě>°í?ŠĺMĂăm/ŐŒŒ{l͍Ż}í›Âpţů繄ÂOźďď˙űŕŮĎž´b×ÖÖĎ|ć3ŕĚ3O‡ř‡ˇĂ÷ćÂÚľwÁgœî•9ĺăËńŹłÎ,űG—x¸Áűűźžóœg ü˝ÍóÉ>¸Îpż,_~|ůË˙Ýîq>ŔŇĽKŕÍo~œ|ňÉđ/˙ňŻŢcnážüčG?'œpź÷˝˝˝.żüE°lŮx÷ť˙ĽR^x˙Ď|╗/CYZôľůҌeŃ×â} c’=Óůagş8ÎňpbyńÓűoťĂ%6F˝ďÁă/'Ÿq*Š…ßW˙ř*Řąń)ď‡ů•˙đFřĆ/ ďřŕ{!—ËÂŕŢýđ‹ŻŻ&,[äô]ůWřâż —źŕ2݉†űáĎ?ű-ps,RőČ]÷Ăm×řäÇĺŻ}üäşßŔçż÷U˜1cŒ_|ő ßvíLä‡Ä|R.f1!?˛DuĹőČd[`lĂß˝ďš#΅BśÝ›u‘[yąW6şá֚Š˝ÇPN~­G~`ŠűŽúŘńŸgÂţ_żŘ4Ű̜c t܋}ěüÜŐ߽ŢÓɞőÝ„ÉďŰţ0ń“Z>ŠíápyŐměڟ­â2ŢB¨ĂĂţci ݛŹMŘÚ ůÁf|<ýéĂŤ^ő:ŘçŢ˜6mźýí˙čé]{íőžÎôéÓaŐŞU•u;Î9ç,Żüžűî‡={öxł6ňƒůťđÂg¸ţ^ëúŰWö÷VIÎď}ď?{äÇČČ(źď}ď‡ç?˙EđóŸ_ĺIO=ői^ŽńľN::ÚáĹ/~™K˛<ţúכ*ş§Ÿ~Zm ,‘ÍmęąăŰÚŘMŇ SÁâ‚y[:ŐłˆU+GľşĹąN,Ž÷3-Ó:îůůqÓöGŕě_}ĐűÜąkwžůĄă_­˜t‰‹§ĎYCůQxpßf¸č7ƒŐ?űgří†;=w/Yz:Ěić“edé´ŮđřmđšëžŻ˝ńźr ­ ź¤k&źôš˙„+Žů<5´Ç+{ś{ó Űi­Mżîöˇďkó!¤ˢŻĹűŒFR iƒČ;ŰŘĹqŠX„“Ďň{aĽ;°â˜ŁŕYŻxdftÂi—\§ŸwŽW~ďMń5E.žěYpęĹçA÷˘Ůđęwý̜=˓A1žţ—ÉEÜąKłG=ÓŰyčOPtíŰ …u7Ŕč:ßWćČóa‚݉Zrfٰżű(d÷?¸ńVşůľÉ„Se+ç'ŕŕŢ{?s.Œţé“ĐV…–Â0wű1zçyk‰ŕd÷m˜řŠ+ŚŚŒˇÝ Žä‡'ňaä˙Áƒ= {ű k—‹.ňŰÜąc|ă߆q÷8´aĂFřţ÷č•3Ą­­nžůfW6}öYžíŹY3áčŁ}2 H.žř˘ŠżŻý[žÍúő"ţZ[[šu™3gNe&ÇŻ~ő+7ć­°{÷nřžč(ž˙gx3@Âug3[śmŰƒƒCđůĎĄR~–{ž_lŐś-ňĂnŸˇ€Ĺ1—~°¸ Vëđä¨Vˇ¸ ։%ňÁöí f š6oűăwýöGźĎ'ďţĽW6Ł­Nî]ęůüř}ż€3ó!xů_žŰówĎ˝â‚aA[_dŞ$ťQđŽ›ž kl„ľű7¸w˘'š˙yďŻáÁ-p˙fřŢ#ńĘrî1^{/ˆĎqlÚßžŻÍ‡f,‹žď3zýMHôLš ňĂΖsqĚN~–ťŇ##öíŮ ë|†™2´ş'jŤN[ ŢuoÔĆ%Möíň/l–Ž\#EŸl`Ď*.9ęH¸íƛ\ňcúÝť^áź­<ĆJ>)2%XćÚ˛˜vďěÝşÓűťkÇN¸âÜçTĘ3ě?÷¤´X(ząg/˜+ńb×ÎD~h˘ał˜ Y˘ş’z”á¸wK;‚âĐnČN›΂ՀmţZ;X‡Âćż,;-â˛äž@ezýÇÁşN|Ž÷‰ƒÉó…´vűݘ. 쀶´ˇdźóˇ‰]‹ëřpÇEkg´đ|Č-;2.)“qďxAĺÍQ"?’’ńś„Ă—üˆ"x¤ťťŰű;00ŕľÍâĹ ˝íůóçĂß˙~S].—s‰Ž°uëv¸őÖżĂӟ~÷ [cƒ=ţÂH•‚{ĂáĆ˙ʢxëwţnżýfŽ?öVć/R„Š-ĂO<éÍZń×0)yŰĚnѢE5ug ÓeĺťÜă<#yX=Ąö/†ź-‰üHÄ\úÁâ‚X­Ă“ŁZÝâ‚X'–ĐűË΅;gTDyŢ'¸& ;üGťłîŘ{öâSŕóO€•=óa~g´e[*zŢéX(ţŽ‘~čÇ1Č´ş—‡ŮLÍBŹ[F÷ƒĂdŽÍžüÁJy+{œŠĆ×Đ"ňƒS¨Ů߄TAHZ ňĂÎVrq\tJpć…çÁ~ţ+X˙đc02ä˙řžrĆiik­ńí˙ŚűżĆ%,E}UŚô9î%KFDdŘntť¨,˝ŕOçę´qďŠÉý*ăůĄ‡¤.ě”2Lȏ…,Q]˝z°Ý/çöóŘşëĄë”W@vŢ îŮŃ4O6žáČćG#Ď-3”˘ĂF˝ś˘œ9Ă~ NÇqď<9ĐâŢĄböŌzB#śvBŰ+ž™YG2†ňŰróź2ÓCűňÓkŞI䇥LĽ›"ňCǖéyä2čęň×Ö¨ŽĂQl ęvŐi>_đˆˆëŻżŢ#@–-[ę‘ gœáĎÄd œ A0Ë$ę/šOÄŢŢ–‡‘ÉDgŻxŮ:ľş­­-•u˝ÂH–ŞĎĐ?*Čpř‘)P‹ bämé¤iŤVŽju‹ bX\ńë Ź\˝ůîЁʀŰ9zŔűţŤŻ€çšÓîMƒ?oš& yxɊłáĐ˝ŕúËeËDdôü—ÝŕpĘÄcd­ôǝƒN,ynE…Ałí –šL^G,‹žď3ý­WH¨D€¤"?ělő ?őÂs<dÓşő0ÔďżJó´ ĎeGnÖýŸ3oŽ7cÓë#˛Íĺm6{dş{§k÷śŮĆuOÂĎö ‹’{‘´Ů{Ë Ŕěšĺ;K˛óŞć-œë|ć/Zo˙Řű*ĺ÷Ä2ă2ëěDo¸4^CÎř°kç×ü0<@4ěbV4HE–¨Žf=ĘČšçGůÇŻuŮÉW@ËÜc Óéߍězv^5k– PÜ ŮžypđŢ_ĂÁkţĂťůÄHdwŤ Ńá͜Ř - O„lďRkĐč>°í?Šĺc ›"ˆüt}…Ź;fŢň–7U$l­ fËŢsâ‰'ŔÖ­[áŁýxůBĆ%[rŢWX;31nťíöĘěŠSO=VŻö@źîşë+o› ü1‚ĺ#ůX娼ĽĹóÇfpf2ü'Ë!ŔQG­„nđ§Őłř˗ű ÇPe8účŁ\[˙6Œœa Ą2ěÜšŤBşˆŰGŇz– D~ˆ 7„ĹČŰŇIÓ"V­ŐęÄ:ątŔLś ď­löž_ĂΉAĚĄż0Ţ˝Yč¸áŮîń1 ?žt˙ŕ+üŮű~ْS„ˆ‡Œ?ą~Ň=ŮÄřŤťýíűÚ|iƲčkń>ƒ†ą4lÖ 5@RZĘR˛=ÄɆĹÇŹđÖÔ`Žěܺݭě§őĎšřďďĆǟ€?ţř*Řż{/Üň§ëaíMˇyĺgždZ˘ 2ŢtőőpÓ݃-.ńńŁ/|ěń}Y}ÖŠBň#×RRČbĺÇÇጧŸëmďpóüᡞ ű†űaëžđÉ~ ^{éKŕ?Ţ˙1"?tlë–˜'zń¨I¤!KTWłe°Ý0Ë.vv=ě’ŰÜą6ČM_â-źôĽ/ŻýŤŢÚ W_ý'lđguÜ蕱GK؛V:;;aÖŹYđ™Ď|Ę%6ţäţý¤w<ęňˇżůľ\~ůKźĹJŮl­Ž`–Ćő×ű¤Ĺâŋ<ÂĽłłfϞŸýě§\Ů5Ţßŕŕ™Ďű3A–,Y 3gNw ‹đŔţ+ŘknĎ>űl˜ëŢlř§z§ˇŢß˙ě˙6„IwźămpÚi§z‹ł~đƒďŻ”ßzëmܡŔđÚ˛FjyBä‡(pCXĚĽ,.ˆŐ:<9ŞŐ-.ˆubĹŃÓŇkú–ÂęŢ%°şÇ˙œě~oĎćŕƝĂXŃG?ý ˜ÝݝíđŽ“.ƒ{^ňŸđ›gţ+ĚîęóK)ĂĽ5ÁqĎuűşŚÁŤÝăŤ^žâĺÍ`Óţö}m>„4cYôľxŸAĂX6„ş@3@RZĘR˛äCÁ% Î|úyđ›˙ÜŰ~[ľ5+ŒűœWźîşővŘź~üú[?‚_}ë‡Ţ]ĺŒ{ń4söL¸â­ŻŻą:aőIđƒĎ}ĹűY͔OđŚĎ˜Ďşâ…ÂźŻXVůţ•ý'źä_ ĎscŸ˙̧Ăߎý üáWÁďżĎröďbł˙Î:÷,nÎrůa&70OôâQ“4HC–¨Ž]=źqă˹ǎ‡ŽÓ_ë•ŻżrĽńĘ+Ą°Ýƒ&cˇZ—Ÿ -łŽ€i/ü\4T~ OŢě­á‘ěČ?í h™w ´y&Ŕ‘ţ˘¨ăOŢmÁ]-Án‘߸°0á’2­0ýußé§käw? ™Î>e˝ŇŰ_tehç'ľ| tS‘UÁ•W~źFzÇwÂ˙÷—ÜcYĆ#nżýT¸ä’gÂŢđZď#‚GLŘlö–—+üˇÜr+ŒUÖŕřűßoů{÷‰úťľň­ëÁČśđéĎţpńŗş„ËşdÍWźY&Œ| ăÎ;×Âţđ'ˆß}Řž}|ţ󟫩'ű°WËڈ"?†Ĺ1—~°¸ Vëđä¨Vˇ¸ ։ĹÉ3—ÂĎ}GMůe7~6 ě„OŢ}üűiWŔ އ›Ńy|`;ě§č?ö˛˘w>źç¤çÂkŽžúÚş<{užLŕpu#ɨ8"´čkó!¤ˢŻĹű ĆҰ!Ô š’ ĐR–’íť8>Í%@*ß/ünxó{ŢËW.‡ÎŽNčîę‚ăO>>üŮOŔ9Ďšˆ›łi{ůa‰Ô.íHƒDd‰ęę×#~Õ]ąŮ…u×VĘňëŽ÷Ęâ3á™-+o-ÁŔ^o˙!úˇşw¸J.A1účőĐ˙ý×î}Ň#JZÝ}jŕ'oƒáű~%÷$'F`äŽ_ŔŔ _ŠřŒßfq3wA˙Oß;sý ”ƒĄë˙†×ţ2bŤSgĄĚDל?Lü¤–Oş ‚ȏ`NzĽRÉ{ĽíÚľwÁż˙ű•đ/˙ň~°`d>ű0ââĘ+? ˙ő__€uëžđdŁŁŁpď˝÷Á{ßűŻđűß˙Ńó‰čëßu×=pŕŔŠ˙kŻ˝Ąě ËŻÝÍŔ'>ń˙\˙ńwĎ=÷şą˙~÷ť?Vf”|ţó_týÝí˝ň–=3wî\ď 4oxÛ<e˙ţý011὞÷Ť_ýźç=ďóÚ">Ťă3Ÿů,\}ő5^ŹýűxŻÍ}ßű>X&y¤sók[Úň„ČQ ᆰ˜K?X\ŤuxrTŤ[\ëĊBăůjś(–;Ţ~ąĺNxó_ż ßů8 şÇ@vžšŽ;|úž_Áďú‰˙řháíˇ|ţśí!eÄż;.~˝ářŘ˙'_Ć#şÔ_Qv*műž6Bšą,úZźĎ a,]ç„záh”‡ŽÁ÷Lčođɖ?šň‡Í5fĎô­YsęíýĺőŚ2ŘI[šü'÷Ü.Đ0uőŰâÇ3Z:˝;ĆĽ" Ćź˛œ{‚Ó×Ňá}rËĆKţëoťłmĐî­n°w˘ş:5;tşĺm™œ÷–’ű;XŒ”&źu˛ŽĎén,ß稷ݑń§ËçĄĂĹq(zŤ Ż›ó‰“ƒĹąĘc:2-Бmőî~ł2&óË[ÝŘ-nގWŤaԍ=Q*ÔÔWŐ5ĽD~TđĘ.÷N~3’Ĺ0ƒ1şé‹óÄŽęş@Ô' —%ŞŤ_Ś:Q,ÁČD „Ö\Ú[ü™NăůŒĺŃ;UiĎfź7ś0ýQˇ|˘Pň‡élÍ@Ť++ş'vě5ˇăßOpŢĹtÚrŽç—%l=ń‚Ż—wővÍS,úJíŽ~.ëxoaşL‡Ĺfoô›(۲GbY§ěłŕůCoĽqÇ_ŕ”ydÇJWÇiÉyvžNĄč•eÚZü̞őůDŮűĚ…—ëDŃËÓqo6fĘžâő’VZŠĂósř‘Ł˙úĺřœ*čëëuÉóľlľí~`—`îi›ű)”?Ĺň§ú`čoЀáďœÖŚG`ăQWżí¸8ޟŠ‘2!Lp8č’éő†.1á}Dy1rcďÄP¤Ě{m.gA[O7?T…‘ě‡_>bŘľ3‘ ыGLȏ…,Q]ózxÄ{můü‡mł˙éËř4Ź,[>9ę@FzřkřşP™ÂÎRޜúoâcvÁÚ!>ÁÁô3•ˇÇdüë4ώ]ű0]÷’ ˛9?ž7ˤlŸuÉť|~é_$˘/SÖÓŠłIűÔ'C;?ŠĺS‡n‚ ňÇáĎ vqš •CeGđ(K؆-’Š˜ Ĺ “N¨ŒézNy6püc2ęŻß_\1š “—JN™ ÁHÜđßh˝3^Náö!ňCe›â€Źq:5{ťÔ´ŢXľrTŤëô—VžĂlq|—`Ŕ–2ů5XQńöílů-,vcdD•Ŕ„`˙‘“Ž‚GX`ů`›É 2ŸŔ`7čZ2•ĺŕ>aŇâż×Ó÷V'÷É'—ŤźŚRŻ“´Â`Ő×ćCH3–E_‹÷ţśrNH D€4ĆŁŽ~ŰĂňâ8a[G!גĽcKäGHôâňc!KTןŢůťÓ›u‚sŚđĽ“w‘ÖeJě.9&ĹP9Dý1Â$E%žăżž:¸Ţs¸őđ Fž„ă¸×‰ŢěĘeVčÜ(žO*}`Ű&~RËÇÖO‚ăÖsgăojžęśJ0djlŋBĹƉKnĚ*ą€Pš2âč0bĂżAYőʈă+˜A•GdjmQ’ż#|ťŒČŽ"ŐšIЎokcgśů!ňjuţŇĘWĄT ŢţďxGÁrQüxţ?Ţ,˜ÚŽ<~Âä¤G–x#%¤ř)˛œÇéĘ\?Vě‘Çť;-‹ć+Ť0XőľůҌeŃ×â}FŁż­œ’ ŠĂxÔŐoKäGýśD~ŘŮNůax´Hôâ t–%Ş[_=*ën„ä57nĂşh. oGâ9ąz„ĎÉÂrŹ’q[iĚD÷]ÚůI-[?†cS"?Dvށm\ÁŃ´ŤęÖxD™ ýÔĆÔťŠ’ç*Ż‘ C'G”m˘Ô´ŢXľrTŤëô—Vž %ÎPDˆ„áŻqݐ˙üŤF§F‘ß^?…äašcÓţö}m>„4cYôľxŸ1ěom焤AHŞ0uőŰůQż-‘vś‡ ůĄ27ş@ĄüXČŐM &ş¨GSäc+łŹGjůŘúŠslĆ]ů!ľÓł[,íÔśÉŮ]uŐŻźĹNüÇ~2Zvę˜ę'ňCH¸!,FޖNšąjĺ¨V×é/­|JBˇ(Őá™ÇE,y3Ř´ż}_›!ÍX}-Ţglú@Ç9! ’ŒG]ýśD~ÔoK䇝-‘uřą%Ş›@=LtQŚČÇVfYÔňąőSç،ť&ňCj§g+8śXÚŠm“ł 9 ŇüÇ{ä!ň#ač䈲M”šÖŤVŽjuţŇĘWĄ$t‹Rž‘y,PĒ7ƒMűŰ÷ľůҌeŃ×â}ĆŚtœŇ ŠŔxÔŐoKäGýśD~ŘŮůQ‡ Y˘ş ÔĂDˇőhŠ|le–őH-[?’zX€Čšž­ŕŘbi§śMގÖü0ą­sĐ) 7„ĹČŰŇIÓ"V­Őę:ýĽ•ŻBIčĽ:|#óX ˆ%o›öˇďkó!¤ˢŻĹűŒMč8'¤ "@´”IäD~ÔoK䇝-‘uřą%Ş›@=LtQŚČÇVfYÔňąő#ЇˆüŰéŮ Ž-–vjŰćąŰŞüp!?ŒÇŠNŽŇŸ”šÖŤVŽjuţŇĘWĄ$t‹Rž‘y,PĒ7ƒMűŰ÷ľůҌeŃ×â}ĆŚtœČ V ¤Ą@K™DNäGýśD~ŘŮŞä‡Ěň˘ t–%Ş›@=LtQŚČÇVfYÔňąő#ЇˆüŰéŮ Ž-–vjŰćąŰŞœČ-k­bäméÄŐi努ŐuúK+_…’Đ-JuřFćą@KŢ 6íoß×ćCH3–E_‹÷›>Đqn 'Xƒ†-e9‘őŰůagKäG~,d‰ę&PÝFÔŁ)ňą•YÖ#ľ|lýHęa {ƒČšM=vjŰćąŰŞüđ#?l j#oK'œN{(O%P­ŽÓ_Zů*”„nQŞĂ72ŠXňf°iűž6Bšą,úZźĎŘôŽsžÜf|T ¤!@K™DNäGýśD~ŘŮůQ‡ Y˘ş ÔĂDˇőhŠ|le–őH-[?’zđś ňCn§g+8śXÚŠm›ÇNlŤnp"?´ŹľŠ‘ˇĽN§=”§¨V×é/­|JBˇ(Őá™ÇE,y3Ř´ż}_›!ÍX}-Ţglú@Ç9On3> : $u ĽL"'ňŁ~["?ěl›–ü0˝Â|çĘĐ@7aY˘ş ÔĂDˇőhŠ|le–őH-[?’zđśS‘*›zěÔśÍc'śU78‘u@ú3€\ľÔĐáÉQ­ŽÓ_Zů*”„nQŞĂ72ŠXňf°iűž6Bšą,úZźĎŘôŽsžľÔ v $U ĽL"'ňŁ~["?ěl›™üpŔʋ>4ĐMX–¨nő0ŃmD=š"[™e=RËÇ֏¤źíT@ä‡ĘŚ;ľmó؉mŐ NäGţ WGí5txrTŤëô—Vž %Ą[”ęđĚc"–źlÚßžŻÍ‡f,‹žď36} ăœ'G-u‚=ˆI h)“ȉü¨ß–Č;["?ş ËŐM &ş¨GSäc+łŹGjůŘú‘ÔCĺ'1ůĄ˛ŠÇNmۄ4cYôľxŸąéç<9‚ŽKB2Č!q”ŠĹX‰ńˆőAäGýśD~ŘŮbäG혓ŁXBÎŚä$!]Y˘ş ÔĂDˇőhŠ|le–őH-[?’z(üK`^hůĄ˛ŠÇNmۈü¨ß–Č;ŰCpćÇŕţ!0Ážƒń…ř6đˇÓ%Ş›@=LtQŚČÇVfYÔňąő#Ї†Ÿ}ăf'pE.cBä‡ĘŚ;ľmó؉mŐ NäO×Đ÷ŕ8Ç3§Pŕ@¸Ą,ŽĘQ­ŽÓ_Zů*”„nQŞĂ72ŠXňf°iűž6Bšą,úZźĎŘôŽsžAĺN!y’8Řş~Cůťńˆ \ŘŰ*euÚůQˇ-‘–śŽXśőÉ- ˙\Œëv*nĽ')Úˆ–˛Du¨‡‰n#ęŃůŘĘ,ë‘Z>ś~$őĐôóÄ›ĄĽ?>óůńGD~ČmęąSŰ6ŘVÝŕD~đQ,šĎŇśţřŢů#…N{(OP­ŽÓ_Zů*”„nQŞĂ72ŠXňf°iűž6Bšą,úZźĎŘôŽsžAË厃Üs߄D€¤€Gďž,FŹ"?ęˇ%ňĂÎö%?]ű˜ŕöőůڃĹ…]]˛Du¨‡‰n#ęŃůŘĘ,ë‘Z>ś~$ő0đó÷˝y0ÁččhÄ‘r›zěÔśÍc'śU78‘bäófăłřŘîpÄČ)tÚCy:€juţŇĘWĄ$t‹Rž‘y,PĒ7ƒMűŰ÷ľůҌeŃ×â}ĆŚtœóäş.Kö!y’0ǁۯű‹BK0Bˆü¨ß–Č;ŰC˜ü`¸ăÚż{cOLď÷‚ô$EűŃR–¨nő0ŃmD=š"[™e=RËÇ֏¤†ůüq۸ŃřŞů!ˇŠÇNmۄ4cYôľxŸąéç<9‚ŽK†ÂŰľÇ'AD€$ˆ`Ýžé)řű5× ´#„ȏúm‰ü°ł=Äɏż_}l߸ĂűŽ:Hň ť đťűĆăŽjˇÓ%Ş‹Í§őhŠ|le–őH-[?’zćóťí°á żHąîřœ˜˜€ƒ‡ˆüPŘÔc§śm;ą­şÁ‰üc|| łńYÜ1…Ű7é‡ÓiĺéŞŐuúK+_…’Đ-JuřFćą@KŢ 6í:Ŕe>„4cYôľxŸąéç<9‚ŽK†ŇýŰĄ´gŘűN$H˛ $A;g&“Ťžţm(•4ßCäGýśD~ŘŮâäGŠX‚_~ĺޘcĐ=cúŸżö H_ŘTÇEŸP–¨.66ŸFÔŁ)ňą•YÖ#ľ|lýHęa˜OŃý|ţŃŤńšoŸÍ´ßňÉĽęç…cS™m­"‘ňŠů‘–ÂđđAŤń9öëýŽ "ÜPWĺ¨V×é/ć!ňƒ/ÔŽSuĂ|iƲčkń>cÓ:Îyr]—J%Č_ˇN{|Ě@HJ`ł@žóÉυJ#„ȏúm‰ü°ł=ÄɆď^ůíĘěS°Y ůőßu}BY˘şŘŘ|QŚČÇVfYÔňąő#ЇE>y`¸2űĂlȞ=ť ,Ę'—ŞŸŽM=vfśľŠD~Č+BäG:v ŹĚţ0›2öƒľr%öPž Z]§żtš‡ČžPťNŐ ó!¤ˢŻĹűŒMč8çÉt](üćáĘěBňČ ĘŘw'ö÷ÉÄ>Ůň§}ţü…o‡ĂŒĄcŹ:űťá‘ÇKE8îÔ5eöńhהŐiKäGÝśD~XÚj’żřŇĎáę\]aǃż*„Çč[&ܛXœľźUĆř˘/}]ll>¨GSäc+łŹGjůŘú‘ÔĂ"ŸĎ=6 ß^?Z×řóţvtt(ŹĘ'—ŞŸŽM=vfśľŠD~Č+BäG:v ###ާžńYظ2î÷ěąskuÚCy:€juţŇi"?řBí:U7̇f,‹žď36} ăœ'GĐu xí:ČßźŃx|N´ˇˇĂŽŰżĺ~s?%÷S,˙eä|,~‰IěńČÝ÷A˙Ţ˝pň9gF§/ůQż-‘vśS౗ď|â[ňƒ-›éĚćŽőă°{áÂŁŰj§Ä^ôĽŻ‹Í§őhŠ|le–őH-[?’zćĂfĹřáůQĎřdiě5ĺ“KŁÓŸŞ2‘Íg'śU78‘*;ôf~„ɏzĆgţą]ِ;q+ŕ¤$ČOy:€juţŇi"?řBí:U7̇f,‹žď36} ăœ'GĐuéĄT‚ÂŻАśăóP ‡0Â;j0äöko€iÓ{ańŠ#‰üH–Č;Ű)°ŕé—ţĺóđŔ­ÔupˆQ6ä÷÷ĂŒŽ,=/kA˜¨.66ŸFÔŁ)ňą•YÖ#ľ|lýHęa˜[đômk‡ŕŚÝůDÇ'› ÂÖ*ČĺrĐÚÚZ“‘r;ľmó؉mŐ Nä‡lÁÓÁÁďń˛$Ç'› R¸ó)Čtť7ö…4ů)OP­ŽÓ_:ÍCä_¨]§ę†ůҌeŃ×â}ĆŚtœóäş.؂§?žŠëöśäCŁGٜG€d –ô\ůĂÎRZÜOߚ5§ŢŢß?‡ӎXí›R aÁ˛%púĹÂŞ§­†EG=3ú “ßw–őŁń/…ž-‘uŰůaiËů%*šw}÷ÁÖ'ˇŔŁkń^uËÖűČdŞ?IőxcôČŮ9xΉípĆ­pÔÜĚěr ëDÓĺ~Wm׼‹ ˆ‘€LŠ‹M–­Ě˛ŠĺcëGR…Ÿ˘{*˛oaÝPnߛ÷^uËÖűH{|2¤ť{š÷XLKK+dł&Sƒ1ä €ąź@ľŠD~Č+BäG2vÁŘał§ňůź÷Ş[śŢGÚă3;żZO]Ůcć@fA/@O8™P ĺé@lŹqu”zÍJä_¨]§ę†ůҌeŃ×â}ĆŚtœóäR—lěœŘuJöyŻşeë}$9>UôőőÂ=÷Ź=ĂýÚď~ňîÇm((”?Eˆ")&G ö€ÓD€¤ŒčÂGŠT`†ř3IhŒőƒĆ'Đź ńI 4/ŇŸ‡"E€ä€*‚8|ŕ/fcv€@˜Ú˙đ'}` 1J ˜‚Ć'Đź ńI 4/7> bŇ „wjc.ÂáŽFhŒv ńI 4/h|Í "=&D€Lâ;;"1ăB“y@ 1J ČAă“@h^Đř$šDxL>ˆiĐ@ š4F „ćOĄyAă“@ 4ˆ!@ 0ĺA@ @ „)"@@ @ LyB @ aʃ@ @ SD€LřďH'"4ú=é4F }Đř$š4> „ćEŁÇ'Á DŠT‚e‹fÁĽç§tŹ\:fôvAÖɸGŒ˛:ţw,ačNč{XćTś1"éW}aÜ‘ęWlń__?d#Ť{]úŐř(Č´ŰôÚË ­lęžL]˘úUwNd;ˆĹĘăŽřĺqbÜÎáV݈%čĎÁS#[áÁGŕÖ˝wÂöѐÉd -°1ş o!œąâlXľŕX4c)ôtô@ĆŁáÜÂ!V'îߊů>Pb+•c\_'ÚůˆÉe9ęÖQ–ŁY;éÔ•uTűP÷uřşŔ´r Űzý„Ć>ĐŸăăƒppp ěŰű0ěŘz ܞúř<˘+ Ďžß gĚhŁşł0łŐqÇ'„+ĂŠýFŻŐ{_(7ŻZ'9_’öՍ†úúž}_()N /k_†űoÉ-ÜW@X?Q€;‡ópíŕlrż§>>—-„g]z6œqÚ °rĺR˜9ٞŮj́A˙{oOIę‹ôHo*ë‹%ءžxb3Ü~çƒđ§kn…›śĽ:> QŇÄÇ;_ótx΅'BÍm嬒ČeÝëŇŻĆ'ňCŹ_u7yäÓĎ8Y˜ŢÚ}î焾ăáK_ 7íš ~öÔŻ'BâăňÓ^gŻ<"„Í-übuâţ­Č‘ďCâ__“üĐů‹ó,ŞhÉyţMë(Ö9Čš\¨Łl'˙Roc´ŤƒK śľ÷yŸs܋UWŔö-ˇŔ“ţ2q"$ >Ţ˝˛ žˇ „7—MËkdÍE~$bƒ"'šźČ őőc4ů‘h9„S˘ő̸۳sě㒅­đOłťŕęÁqřʞ‘ĉ6>O8ţ(řçwżÎ;g9)8götďsöY'ĂżźűŐđű?ü žý˝ßÁƒ­#"¤ $e°ĂĺĎ>ţýÝĎőî"ůÁÓŮČę^—~5>‘býŞťÉ%?¸~Ü\ϙu6œ9óLřĆúďŔőťţ’ČA‚Ń‹V]o>˙­Žż,L9ňC#HrŹü@Ť:Šuň…rĄe;ĄXůĹb„łLŚŻć/:ć.<šď۰uÓ ‰Ď+ˇÁ˙;ž˛$N~TĹÍG~ …žŻúÉTé'éË0Főw­ůȏ$÷_ů!˛yö´6¸dZ+\šó \Ő?–Řř|Ůĺ—ŔűŢűN÷—ĺQ`Žç^v>œsîđ˝ď˙ ţ÷+?$$e’"؁á_y>źűőWĆěořĂ@䇺îuéWăů!ÖŻşkNň#řΈÄXń&čií_můM] 6F_ô´—§żşËĄÚ/Pű×ω/Ă9ň}HüËăůĄ[GuˆüHŚŻ˙îvÇçŞŐo†ÖśŘđřŻëŸo_Ńď=Ş#’C LË+ů ňC×WdSŃž‰ř2Œ•ˆüŕ•g]ýĎ›3Ü;ĐßŘ7R÷ř|Ű?žÔť{=0č@¨ŒD|ĂëŽpÇÖ8|ĺk?'$EPËŚ„`ć‘2ýŹîuéWăů!ÖŻşknň#\~Œ—ÁEsŸî53?ˆü@ETuäĺVuëůĄŰŞá,“éëŔÔçňU/ƒ…Ë.Şk|˛™D~@‚žˆüĐ-G Šż÷_[ň# öH̋{ŰëŸlć#?B˛`㊍/ŰńIPƒŔVżfk~°Ç^*cö7üń‰üPÖ˝.ýj|"?ÄúUw‡ůřăň7ÂüŽ`şâ<Ógk~°Ç^|Xţ Ő~Úżž-_†5räűř—Ç'ňCˇŽę:ů‘L_ţůysŇĄłŰn|˛5?Řc/áj Ë+ů ňC×WdSŃž‰ř2Œ•ˆüĐ-˙ˇyݰŹ5g7>—-„+?ţ6 逍/6ÎčJéŔŃ(wBŰÁ÷Lčođɖ?šň§Őý´¸Ÿž5kN˝˝ż°•1v˙ýá—Ń‚§D~ŰĘŚîÉÔeęÁö­{o…/=ö?ŢTAW‰côݗźoj.xŞ$9ůĄăˆü¨řGiüŰn…ďü’ńřüŇęîT<­Š‰üĐőŮT´o"ž c`ĺ"?LĘٟŤ‡Ćá_ˇ Ď_ýň{0}ú\ éĄ˙Ŕ.xá‹_§=>§úúzáž{֞á~íw?y÷3á~ ĺOąü)…>ú>᝺T@k€¤6űƒČ"?Ŕśßą‰üůÉΜu6ü˘ă—°k|'č‚Íţ ňCVUyy UĹ:D~čöƒ*F8Ëdú:đĘřsž 띯‚ąýńÉfůĄśŃóEä‡n9ZŘHý%¸˙ŚA~0°…QżŇšƒ§ úSíŮ]铏Ÿţuˆzý)é‘^ňzKÎňĆŰć§v!YĐ#0 ƒ1ăĎ:˙ ňƒ§˛‘Ő˝.ýj|"?ÄúUw‡6ůř9}ÖÚĎJ2˝3WžD~ˆę Ş#/´ŞŁX‡ČÝ~PĹg™L_ţQ+>ű;w‘Ůř|‘ ů"ňCˇ-l¤ţÜÓ"?\ŇÓf4>ŸýŹs€@ 4lźŃZ Ƀ<§uÚIGřG˜đÇS ňCY÷şôŤń‰üëWÝM ňƒáŘŢUeű@ƒ@žjÁ ?•~Úżž _†5räűř—Ç'ňCˇŽę:ů‘L_ţQ+~đˇo–ŮřžČeÝëŇŻĆ'ňCŹ_u7uČö}açⲏ@‹@žhĆŇJ„ý†˙úú|ÖȑďCâ_ŸČÝ:Şë@äG2}řG­řáż]ÓĚĆçQÝYŽPd‡a1‘şž"›ŠöMėa ŹüCä‡Išh˙]ޚ-ÇÓŸ+W.Đ㍐dAk€¤€˝]ţ‘ŚrH䇲îuéWăů!ÖŻş›ZäűLËő€ z:zŞýľýœř2Ź‘#߇Ä?JĺD~čÖQ]"?’éëŔ?jŏ˙mi5Ÿ3[ëźŕ‹ĺC䇾ŻČŚ˘}ńe+˙ůaR.Űgd0ÁĚ˝@ oé€f€$„Ź“ ůĄŹ{]úŐřD~ˆőŤîŚůÁţɰ1WŃT=ý°_ˆYůD~pĺD~ŘôdLÇgdS¤&sůĄë+˛ŠhßD|ĆŔĘ?D~˜”Ťöߏ÷v ýń™ÍŇĽĐ(řăMw|tA3@Ň@ĺ ČeÝëŇŻĆ'ňCŹ_u75ɏpš.Pđ×ĎIŽCäZŐQŹCä‡n?¨b„łLŚŻ˙¨_Řçá ay,"?ô}E6훈/ĂŐýˆČ“rŁý—@ ’ˆüP×˝.ýj|"?ÄúUwS›ütM€ąż~N|Öȑď%śR9‘şuTׁȏdú:đZń…}ËQhX^‹Č]_‘MEű&âË0Vţ!ňäÜh˙%„ĂD€¤"?ÔuŻKżŸČą~Ő‘q`쯟_†5räű@‰­TNä‡nŐu ň#™žüŁV|aŸÇrÔ–×Ä"ňC×WdSŃž‰ř2Œ•ˆü0)Od˙%„) "@ŇBőd C"?ĐŻĆ'ňCŹ_uwxÁ_„mˆü"?¸r"?ŹúI SP.ŤŠ‰üĐőŮT´o"ž c`ĺ"?LĘŮ%Řź-+”őeA¤Gz¤WżÁD€¤ lƒ‘ čWăů!ÖŻş;|ȏŕť.ÂúD~‘\9‘VýÄŐ kX岪˜Č]_‘MEű&âË0Vţ!ňä<‘ýWĽ ‹5eƒţ¨˝=%Š-é‘éŐŻG¨D€¤€ĘÁ6řů‘€~5>‘býŞ;"?t@äůÁ•ůaŐO\Œč岪˜Č]_‘MEű&âË0Vţ!ňä<‘ý—@ ’0ô!ň#ýj|"?ÄúUw‡ůaú?§Şîߊšň 'ĄĄœČÝ:Şë@äG2}řG­řÂ>GN˙@@šŹ*&ňC×WdSŃž˛rÔđĺČüdXů‡Č“ňDö_@8L@H@¨Ŕ+ßCĺD~čWăů!ÖŻş;<ɏŕť.ˆü"?¸r"?Źú‰Ťƒ\]m \VůĄë+˛Šh_n‘Ą/aŕhĹ ňä<‘ý—pHc;h°ˆZvşzÂT i 8€#DĎ˝‘úúŐřD~ˆőŤîˆü0ŠţVęŒ\y“ЇPNä‡nŐu ň#™žüŁV|aŸ#§br# \VůĄë+˛Šh_ޚŠ/”—eˇœČ“ň¤÷_B󃑓EH„ă:ŽůĚ[ĄY@H* ňŁ~ýj|"?ÄúUw‡7ůüŐŠţVęŒ\y“ЇPNä‡nJRâ9upjó1j"?lú‰ŻƒŇ:ÔŹíó \¤/+G Y9ZŘčůj,ůĄŞG A X[^s$ŞŁˇAä‡IyŇű/Ą9&l‰‘oˆ.ąAdáP i!zFč}ˆüĐׯĆ'ňCŹ_uGäGđÝ˙[Š3rĺAN\[МČ•RțÝ̏ŘZčH|‘˙¨_Řç(î^ęBÄ‘şž"›˛Î@y›ÔěOşąc;Ăťö÷ţqjéĂzŁ…Ô_íÎ÷Ő|äGbc”LˆžŽîŁ-Śţd6D‚%’Âg€Ţ‡Č}ýj|"?ÄúUwD~„eşŔřßJ‘+râÚJĺD~đäüő!ěČž¨'źĎ`ĚgÜ ęşý„bhôS,F8Ëdú:đZń…}ŽœţQř°F¤=ˆüĐőٔt‚čÚK|_‹!Aąąc!řDVlŞÇGá dĄMŰJćŻÎvçű"ňƒ †Ů ClččɈĄ!›őAë„%’0řůĄŻ_Oä‡XżęŽČpžŚˇ™żŃňbź,ňW('ň#ř[RĨÉ1ÖĎ%(‹Ţś“ÉF ŻĐŠő’űű ‘ŚuëůabŁçkňȏČńüŢĺůŠ÷y'ö7rŃT.-•cÔ\D•˙áţ˘ ꁙtůŤłÝůžˆü Č!#,dD…ÍŒ Ý|xßĂe<„f‚’‚“"? ôŤń‰üëWÝůĎÓá6óˇ1ZRŒ—Eţ ĺD~`yKUGď{IP7ďS‚ńń~˜ľĐż˝g[ZZ{#$ˆG˜„ëé8Švđ)ŢĚQęvץ6ž:†ż‰f>bržԊ/ěsěëš>Œi"?t}E6%Ż"?xűŞ÷KŃýřß&˛-PČ´@А+Ą óqÇ`Ćľate.ăÓíč=ôKÂ3BÂÁb” (‘Iw<‘ż:۝ďkj‘›Ýß`ú‡˛ ҋÂ'œ=ńp`0IÄ5×ó÷ĺ8ÉߌţmŒÁD€¤ď‚Č}ýjü$ČoÚnüjž?tBń…‚śBI]0˘ďĐůÁ÷Š:`ľÜŹŃüM@äZŐQŹS˝.…óĺňÜYŠĘJ!]F~ Ük.˜ÖëŸđÍ[V€ť˙ś:;gE|8˙áý§ş]›ge ‚m?ĄXý‹Î2™žüŁV|aŸŁ`_×ôĄšşůĄë+˛)iüřofřœ ź˘NŠě&_D)”`_÷ Ř3g!ŒÍ_…Ů 3}äZr• 6ö Ł#ŕěÝšŰ`ڎÍ0gĎSĐ[ĚC[ÖŹŤç`u˙ f„c8^'ř"Şśi[ÉüŐŮî|_‡ůa8H—.,֔ ”/Č{{JR[ŇŤ3q˝đ1ňŕÁhkk…\.Ńc*ů|&&ň.YŠř,ëő(ňSéă:Ź—Íd ľľZBă>Đ­ćW”ÎĄý >=Bý $ ůa __a€2BŃ^ĎMŢV&uńsAAîD~ë€Őrł:Tóäş ň­ę(ÖŃ ?b$A#‚¸- Đ;ťŕ’­pßÝۼғOY}ł'`¤Ü˝đjŤÔłóŽnEtœhŹpcƒâ:ŠÚ Ĺ2Đč§XŒhśš>¤}řG­řÂ>ÇÚţ1ńa‚¨‘şž"›’Ć×%?Řeî˜K|ěĂl9âx8¸j ´Í[0Ł­Í˝ju/‚Z ›ÍFö¸Z~é2÷ÂlĆÇÇaýČ(×=3š îÜ =-YČ9ŃќĐq$|ÝÄ#FĘŠšˇ•DFäa2 z|eë֝đż_š.˝äd8íÔŁ]YgYŕŔŔܸŽÖî˜ €ŕ@Ú`Ł´ˇm N›ˇž~ĚôőtÓ#/„CD€¤"?”úŐřśäG0u^Ť˝ ž[räGíĚŹl;˜ŃŞ‹¨îŐpD~ÔäYmfcůFů‰uä"7FM"D‚˙HKž0óć`l,ß=â•s\ŚĎÎĂŔŢq÷ÂŤľ6/‡˙XKľ0˛A$7öŻĂŠŁ¨P,~ŠĹe™P_ţQ+ž°ĎQ°Żëúˆôƒ ˆüĐőٔ´ˇůÁţp; ›Ž>Ćל Óf̀ů]]Đĺ~ÂĆk>Ÿ÷Čö Ć/ťʸwˆ;;;ÝťĹ=Ţ÷ŃŃQ™5žx Ü˙ÔF˜~ëu°t÷&čcw™M9vd6ˆ‘>tâő4m+‰ŒČÂd@E~ô ÂmßżýőőđŔ˝Âçżôv˜5są7ŚŔ ľŔ [C#ÁFi˙x\ťy‰ťń\z˜;ÖŰ˝qO‹ %’ˆüPęWăېĽ Ű EíeĐVćuÁň ÖŸˇ(TM<"?‚6N‚üţę‚Č0ĘOŹ#!?bä@xBg%GŔ{ ä…1˜ť°ÚŰspĆy‹<ö}žűuÝcĐÖÖĘщú b8N$ĎhČY/Ąňť)ˇŠe ŃOĺ˘mŒf>¤}řG­řÂ>GÁžŽë#ŢđÚ ňC×WdSŇŢ"ň#ňHšűéŸ(ŔşYKaßš—A߂…0Ó%22ƒÍčđfw ü.~źń[*yzlVH.—óf‰°ĎôéÓĄˇˇ†\?‹—Áýß‹ţö{X\‡6W?Ľ¤› ĄÇÜLŰJ"#ňƒĐ,ĂBĄCópĚŞ5đíďţ7Œ í…ńĄčĎşcŠF†GáÎíK<ݑąqŘ3œRú4ăîÚł;:;Záöí3ŕÜĺŰ<$\‡đl0šBhV’ˆüPéWă'E~ ˘˝‚ˇPT}UˇŤäD”ü¨>Vř ŮpęVÉ ËĎMFü•IX]ˆüH†ü°™ú‰ąż€ľe‘żB9‘*ňŁŕ^Í`Én<žŕiİ2ƒŞP*@Gű)Ÿ\-?ŚŁ’O{GşzÇ`|t˛™÷ą–ę§Ą vśţ€÷™LeŠä›w]7$Ţ(–F?•˙‰ś1šůöuŕľâ űűşŽNŽĆ@ťr´°‘•Ł…žŻć ?ŘżŒ¤Ü6Q‚'Nşœ§ ó]Ň˘ŻŻĎ{ĚeddĆĆÜ1ç]]0cĆ,—™]]ÝŃƨ;.‡‡‡a űahhČ%.Ű˝#RŘ,’ţÎNزh) ^ý Xšg3LËeŤ$Ćf‚”ÁňsLŰJ"#ňƒĐ,ˆżqeϞý0{îqpĊY?ĂśÂÁţm°űŔ^ččhƒ’K<ýöŢĐn¤<~tÚí˝ř^_w{íőގ÷Â´ĽˇR„@„ü!¤|IžJčB(BÝ [Řę]oóÚŢânßŢŰš§ÍŻ‘ŽtTf¤‘î9śŻý>śŽ¤™ˇĚ;ŁŃ‘FEóu˜ýGÇŔę{p˘071†sĎZ™B ů˘]f";+ D€Ô•ŤmsŰyehďůQ+ňĂźÁŇŕşI ˆÝź1Ź*ą˜äˆ{ԉćĚ/y&ocĺ–pěËcݏ#ňĂWN&.g0Ď̟ćZKó‰üđĺ;ú_ô‹ˇ5ëëŃŮŤZIčßRvĆPbE]§Ťúë! nĘbl˜O›ýś`ü¨Ŕ$%‡‡ł8|`uuMFnĺŠ23ďś\1 H"?ÔlʨÇyZ„tC'(ĹĐQłuęEýĎá<°çş7 őœóĐŐŐĽ“‘199iźîŇÝӃţžŐ!„††Fcéî6oĘffŚqěčQLMM$ '@úúúŒ‘!co|žžăqÖžGљII_‡ąŽ9•:QÉ#ňƒp2ôš[cŇÓĆ~4ˇtűňëJ“˜ŻCK+˙Jˆyź /ÜZő]Áý˛80–Ç]ťŹńœb˘’@X ¤V ňCőČćŠ/VÎ7>ÍW,čůĺgˌĎ<Ÿ@IŘöůfą0—‘Źź'˛Á—šĹiÜüÚľŘqŃ*Tk—ńęóŽG†đż˙s őmćSe˜ĺŐBë‰Éó ĐNĺ?î:fŃlśľeŸ)ů—ś9“ëŞ6˜—Eął™MĐZęŒâ”frX80 mxuZšÓBßaą”ôKůJ˝ ¨ŰցD[qb/L/!ˇo Úńy4%›Ň’†źf—•$‰‹kN"?Âc'?ŹtU0Çó¤šÖŇ|"?„ůŒŮí‘/ć0°ŽŽ&äÇrqŃ%}xlç0ŽĎŠZ1pĘTsÍ Âˇ4;ś˛˜xÖNĺ?î:fŃlśľeŸ)ů—ś9“ëŞ6˜ĘŁŤŤŰ‘%B‹NŞ\páE8rř0††őßőZZZ ŸŁ/z%ž]œÇöƒť]ŻĂ˜?â’'Ě!ą “—Yďb[+œüˆŐI ՆE %4śóIżĐŇ8 $§ŒôŮâ ´ü"§ Ž×Ýhé@~pdRdIRÍ_} ĂÚuëФ“!Ď?÷ŒńŰĘG‚đWn†^ú:ě˙ęΞG]Bł mývjŽŸl-běeS‘äƒę—ČB\xGHÄŃ?Ոg˙$VˆŠœW}ÖBäGlňCöŠ[‹ü˜ĘÎBť¸ën9?p¨]}g3ÖžŕĚÍÍKđw–››[ƒí÷ľ`Ă{ŽÄȏžÁÄ÷˘łŽŐ Ź‘ %VŇK#?Tb ňCŞ+Čw˰X1ĘeX¸rěŻ˝đWĐ´NUđ˛ĺ 9˝O§H&ő'×)IŒ’öąÖaíTţăŽcÍF`[[ö™’i›3ÉąŽj#$†e§ł:Aé,†Žš­K~řÚÇsœĚK8ĐłŠKޞżŇÂ_{á8çœs_yń‚Ďí‘]T#@8řü"ÚYŰđěłűŒQ#Ü7-ćŘËߌ–˙ţwŹ×Ť*/ż&É&/łŢĹśÎLňăĐ1ůq15Ťv̜Ér"Äz †ËŽ&Ń×-ˇľ”Ƈĺ#­N$Ž '‘g•ŘŹkä鹄/M:^–'Gˆ"@jćXˆü¨ůa_d—ɏůÜ"ŘöŹ~ůp‚žo˙ţCĆöŚMë]łÔ77ˇK-ŔOôŤ^ž Ç ˜ůÉZË#AěřŹ‘' ĺWcœd‘žr2Ĺr"XКÉň‰üPąRƨ-sbŔŠ9ôŐíĂËÎ?ŒB)ÁąěێTŚ MiߪĘqçZ‡ľSůťŽY4mmŮgJţĽmÎ$ÇşŞ Ĺb§ł:Aé,†Žš­“7ňC”Ήʥ|ÇŻ~)Ö´ˇČÜܜńŰš}ťI~Ěýäçhžâ %ü÷2ËGaęKÔÁ}nذ0üńýěš5xţ˘ëŃöđĎô‡I×| ĆS㠃’؉üˆ`K늞´é󆷭ľ¨Kr SÓćńÔÚRB:äÁ eő*ÝŢH%íD žĐ<žVŃ×W0Ž}9Ď1SžqooŤÄ+"@č8Xžaů85(ÄÓ Ěąů›üđú÷’…RÓIýFćŐnňƒăßť˙ôяËpށĹ<ĂŸZ2–l>řęĄ˙őç`Ą›éO˜ ćMź]v¸bŻT ‘žr2Ĺr:ň˘€‰ÖL’"?Tc4śůDÁz˙lé¨ýŹôQQĘNbáąÇśŚGqŢú1œ×ű8n\÷]źxő'°5G†•VľÂęÉÜeŃlśľeŸ)ů—ś9“ëŞ6”bpjD Ng1t‚ŇY 5['žüp÷G+ÍLĺťÓš"önť}ýƧnů|ü5–7Ů ęśoĹŢ7ž…Ű~‚ 𛸥ě–łˆŠŢŢUčěě2ž6ĂÉ>¤ţŠk1ÔԆcîpcw—-š|"?§ âĘŸţÄ猥şĺ`űŠ "@jV^ˆü¨ů!ŞŻYýiSëŰLű2íŮłĎŢ~z÷^,EýŠń˝ßšÇ?Üąh,żŻoZ-ĄĄă˙œ…™Üź4öJ(D~řĘÉËéȋ&Z3I:ˆüĺ3gžƒ,°ĘXÔďşřŹôř" ú N'ĽĽ),>ő9”GýÂü sCÁ7Ÿş őuÍĺ%íc­ĂÚŠüÇ]Ç,šŔśśě3%˙Ň6g’c]ՆR ž›XU°ŕtC'(ĹĐQłuęüŕĎƑAáüˍIH[[[ą°° !ŽŃ‘éŐhźńzěţÓżÁŇţlhŘgžT,bjrŇ8Ě-Ěa1ᤠŸs„——…Oşzđ’ë0•ŤŒ4¨ź* M;‘lN:ŞÉ ăđĄ#öţÇ?ö)|őËß0&6&ô Lm`œÄˆüX.ůaŽôpűˇFđýĹ|Ý;`Ází…?y^t<‰âŰ{ö>ƒd"é{FOËaďPeX"ß~JOť`­|‚¸ösWaL{JżŘ,$מËʡZ…HĐŕŠC†ČĐrzň˘ÂiŸ•5‘Ş1zËČô~Ř8X‡ácf˘ŢTŠŽ6ŐŁqG’M'–7ȏ'?‹RvÂŘw’Ÿzřtô]ϙKů˝­ĺ1ůą[ŽÝ ŠT*WĽ-ćtbá٠磾˝ÝřÜ-Ÿżƒ˙~ Źń™X÷÷ŕč‚˝?šŰ{Ўţ Ro~ću˛âřŕqLOOŁG8ńä!SW‡îÎnôŻ^­4—Yłf-Ž=lŒBáej:÷p:XIßŔ{qŒŽäeÖťŘÖiJ~Ä꤄SůĄżĂŕŕţĺßţßűîđÍŻo|Ókń{ďým[ćŕÁý8tđ@ ő6bÆMˆ úü-áT 5‘ľůÁýs’ƒ5§Q×X üľ—[CuGFGń/˙ü cűe/{^ýš—#*fćášćZߞćiúS4Ś,ĽŸţĚHNÜüBhőf™8ђX׈ÂŃ"҉„ýéŰJH4ňĂWNŚXNˆëON;đřŹŹ‰üPŃUF'ŕy\[˜(`vbóOĚŁéâ&4_ÔhŒ–Ş5¤äLjN~ěźíŤ^ŒTşNňĂ"&íTţăŽcÍF`[[ö™’i›3ÉąŽjC)&ԍ A˝xó⤳:jśNůÁéžăIߘ-1˝ő|t55|óš?:ťş¤dĹ˙ňw¸óÍżŒMcë§>‡…߁ƒŻťĽMĐ×׏–ÖVdҝ)ędĘŚŚ&18<ˆá‘!lŢźĹY†ŢŢ^?vKKKƨ”f}ŮżezŸŢ‰śL˛\tćŚB$őBäGt[„“kÔjâO˙ż÷ă=ďú#źý­ď6ú”—üŕ0úĺ†`;ŢžKœát˝S 0ů!(/ĘĽžŒ÷ó9švOĚć|íE†¸ŻĂ\˛ąů™c(óƒŸ9n¤ĄXDî÷?€Ü?|Ě\Ţó#ÍBâÂ,äłv,•)@ˆüđ•“)–âú‹ g™í}{Mä‡jŒ˘2–BZĽ”cżoGż;Šb>n ŞAF~dł9|âá—éäNjÎ4‚F~Äkkq D~,ǖk7¨#Úâm“/1Lśö ľ§ Fz.—CoĎ*ČĐtţš8ű–ąa ĎĚ-!}č0śüËŕœűÁ@ď*´ľśśšššĎŮrŇăź Šą Ď<ó FGGţ´¸ťťÇ¸YăżńÜ^V'iKţwM]#EEy"DMwŮ:˝ÉŞôQBdˆćËPCĂ)'"%Ö­_‹ý÷DSsِüŕŕäÝ´¨—ÂJ 5‘ţň" ź˘úr~ý…1œžäJdŕBGg;˛Ć’ĎW^WáŰV:—‰ƒŚú$žřŽ¸ŹsÔXžřŽ FZኧQÚ[!^řváɧ+ž›ůd%wče§˛Ďˆü`Šĺů xÍ`ĂYf{ß^ůĄŁJ "äř“âbć°ď[GÁŠP2ňƒ—ůřš ąýJ"?˘ŘPЁE:B!¨o^œtCGÍÖŠG~0GĂ.JxŚwęë덅“ő H§ƒ',Ţň÷F[K“M‚húďZńkßÄŇ[ށâ#ť|ňőőuŘvövtvv_y™ ˙ô|ďŞUFyŒ2éek_ݏ…t=JĚ–$v"?Ş`‹pڀ“ Ÿ˙Ň'…äpڃZŔyŐGä‡Tގ%B}YÄŸ0 I›\ŕxýë_›nş×_w *ěßći<ď ox âbëę&üÓoœc,|›#;=ăžAŕi33ĺúĐoŐu’„Ďb”ć^ghŚ@ä‡B9EžQŠżHđřŹŹ‰üP1<ń,Áůą¤/|=zpĎÝ5Œj#ˆüč|É'QŞëC2U"?ŞŃÖ ňĂŔ)6አ–ôß̙îŐČd2ĆÂçţhinF˛Y´žýÍĆEŁE‚Ś "÷ŠüßüPţíłŔGulÚ´Ĺ 3:€0ŚşŽŽN'b2úC‹źąÍ—c=úy˘$ŃN^f˝‹můAXŮč좂D€Ô ü—…ČŠź‹Ŕż´žŹ$]ą ß85őľcfj zzťńëo}3~ăˇ~ ýý•áź|›§ńźîž.T —\ŒAýéuAż¨äːžÍÓ8fçfŃÜ߆ź~#XbňĂz ƈǨo"?BË)ň ýŠ‚ ×D~¨Ć(*cÉ%Ä7$^ňĂÚŢ{ďqL . Z#?R-kažW$íc­ĂÚŠüÇ]Ç,šŔśśě3%˙Ň6g’c]ՆR ,4ĆHԋ7/N:‹ĄŁfëÔ ?˜Ä–ÝOős~şŁËńa ÍMáŸđ4uĺ%ŘtĹEĆž“á \¸ý§Čţú;|ŸĚM$Xˇv˝ń…—ŠéŠP?|N’bąh”/ƒíŤ ŇĆ B4­.‘Ëľń@ ŹpĐ$¨ľ˙e!ňC*oÇ"đ/Ť/k䇵ÓÓ[{ZŒ ގÎNxÁYď}űžłˇk…dSVá8ţé/űŤßůV#crbuőu`˝Iä§KHk ;,^Ć(–ršo•ů”[?:ů‡ÝƚČŐĂcˆF~XŰOÜu×˝y– 5ňĂYÚʞ†íTţăŽcÍeľľeŸ)ů—ś9“ëŞ6”b ňc9ś\ťAőU[EMCSk‹1I7ĄÁɆ†ĆFę–í…OxÚ˙ď˙€Ák_ůě’A‚plmŽ3ÝMLbî_ţ÷4ěŔ+ŻëłőŰÚۑÖɖɉ‰Đ9řh‘lvŃ(Ÿ”5Ż“5珅3ç>0Ö"CQŰ8sɏˆ}ôĐ1ů—}ŚfĂżúsŚËU>éě^[rŁŁIô÷Čmń/َ WěLúę˜^ŽˆŠˆüĘŰąü‹ę˒u–­PПőÔ'Ռţ„hdd˝˝î Üřë0 ćk*ˇźüE¨%śnÁćţ+mb|ÜxňĹQXA~"T"k{ďkćK2ÖM>‘Ay°őÝ>˘Ŕ­Gä‡jŒá10a aäß~ćń\rËýćŹqQČNbćČ.°–s‘*ěBizż„üŠ•›Ť 9ßńÂ|6Â|8÷Ĺö™’i›3ÉąŽjC)†*“á‰jé,†Žš­D~č?ŮD XŕżOÖ§*EŸ†ç“‘f—˛XZĚbfnÖřÔ-˙ÚK˛šýń{pď_ţŁ!ÇIMˇˇýő/ÇŇČ>|ŢťńřŁőذĽˆóVW.â[[Z0=;ƒ áóƒÔ×Őĺđ"“Š3ĘĹýżĄ őp qÝěŃȏĺڊN~pŹ(úŇŚgĚ띶ÖR .ÉAH€p9žŰÚRD&Q ´™IëŰVé2c8éĐËŃß_4Î#ü7“ÇÁ×<Ţ „ŽƒĺÉ–"@jçU ľůQ‰Eŕß)oN€ę¨/8Ňuů\1bWĆPIŚ’˜Ó/ÎřPَŽĘHëuř_Ń_ŠşNRQg†_äMN šŮ$`´5őČ?šˆşňĹ&+×o9JťšĚm"?‚ň`ë‹}GAůŇĂ“;Ďłf’tGžĂ˘_†č ňÝ2LÉż7].sbȏRšĄn[R†üŃEdfĽD_xf;.]8Č-L`rrR'?ÎĆüü<Ső蝻ß(Œˆü°crŹľĐ!9^‘*ĺ“ËœňCÓtr˛7‹s.7żźÔ‹ =5…'żwÄ&<œäGśTŔĄýąĽš LéýŽ%Œ7ţʼnńéZK XýŇŞ‘69YއűŘľĺ}Nj§Í—Ő֖}&ˇÖNB™•C~Áâ§ł:jśVůaĽ/˜ůJЇüŕŕ„˙ _8ř$ăŮĹEƒX<~ü¨ńgá‚O˙Fn~˛ů"ŚĂRވçG˛úďłéčĐd _Űš„ˇ\QoÚb%$Iô­îG}]ęuőöHI ܇U.^F^oH4ňcšśˆü8ÓŔɏ÷źëĐß߇O~ćc ÎtR 0ÇBäG%q}9.ţ™ydÚ2 œ+äQ?Đ'ZZZą”]ž=ťaşmúS%~1g^\iřÜgž‚ď}÷‡ĺ§FnzŃőx×{ށƆzĎF˙™O˙§_÷÷Ţn<­âóxärK˜™žÁĚě4›]äGăšVŒk‡Í84÷ŞuʤHĽzˆü€­/÷ D~¨Ć“ć{o°úv´cěč,öÜ7čR2ˇ'&ćţyĚǟx G7˙Ž]ł[7ŻĆÂbúŁb›üŕĂěgGžC˙Ë?"%?ěؔb„äxaŃlśľeŸ)ů—ś9´OJ1D#?œö#ƒĹOg1tÔl­Lň#Ą;SĘ$ŸűĂI4ˆ†Š'őßO>))¨Ŕ l6kěs¤VőbÇŰ~~îżńg­/ĆÄťž|Ą„ćžuhďßbČ|ĺÁ%ÜpVë;úďs :!Ů?€ Ë˙íćĺ,ärž×^hΏĺŘ"ňăLŔ>űeĚÍÍăÝż˙N9r ď}÷Çűţô}śĚÔÔ¤ąĎŮ㜷G‹zŠE œ˘ ¤`ĺ…ȏJ,˙ůˇ’J~[œp(¤54u6Á >á(_ršô8xđ9ăb­žž]]â/Ě$R:鹪…ą’q!Yy˛l…ĺ†yňˆüPó­ gLŽ4ďšIŇů抉eX€Ž ß-Ôü{Óĺ2'–üľÉŔůŘuĎůÁˇ§ç˛áN˝ć ˙ižň–Ję7sšq>ŕ¤ă^˙jœîŮćȏńqŒĆM/|!Ň­ëg;xçüĐ Ż§rä>˘řŐÚÚ˛Ďä6ÂÚI(CäG5[+“üŕŕ}ŚŠ¸d<,ŕˆ5ڂ‹ü |bҌžĎo–œżsk˙ŕwń‰Ň9|jÂv43rHçů“h[ľš"ĂGş€z]ƒŃ7űűĂGwq˘„˙N_{+ŸŸ7ˆ#FäÇňlůqZBŔJpňă›_˙Žą~đ‡´âąn}ĺďχ4 ¸˜@X‰ ¤0~`ˆü°cř‡Äżók/[Ź<˙ŒĎßň PƒÉ¤Ľ.Ł“ů"îüéÝXŐçmĺńǞŔącƒčÚá??ťó^ôŽňef׎'t’eŤVőOĹÂPZÂŇHÉ´=áŠ5ç‡-SNŻT‘°őŐbPsë0њIŇů抉eX€Ž ß-Ôü{Óĺ2§ůÁŃŇ]o^ňƒŻńăĽoüĎ÷đéĎ~őuiÔý;eŒŔâ"óů>ţăł_ÂË^rvl? ŁĂÇqýŐ—Łł˙l!¨ĚQYŽtßńÂBmĺűdXŔqdç‹mËeNň#čx‚ĹOg1tÔl­\ňƒƒ÷Ž&ý؞™3F7ň…χľ¸¸H€ptwvcpX˙˝ÔÉ>‰Š…żűĂpńý#řđWvaa~ÎH›ÚŻ˙f‘ -ŕk÷âěz†ÎŽđĎĐó/Ŕđ2qR†—Ż81ޤăő´°CÓ"?§=~ソmŹ9 Âż„řŻ˙î&?86lŘd,™ˆ5‘v,˙đĎBbĎé7IŞ THڰg÷>457ę v‹oiiiĆ#?&ŐçşÍÍ BÝfÝ&×Mꄆ ’kęQĐoöl‚LJćüʃ­_eňĂŁĂDk&Iwä›+&–aş‚|ˇ SňďM—Ëœ:äG*Ł?ÝM2ůÁ—Ćfß~öůřř§>k|ř=Ÿ01Ľ?!ŽĎdôuÂ*Ďóţ÷ˇăé={qĺ%çŁoè€ŠŹ™ˇŽ=mžŹśśě3%˙Ň6g‚ö‰bC)"?–cËľT)Ő˛%HçŠS ˝ďMNžň…O >77‡0ôŻ^mŒ 9xŕy0ńĆŤząóc7ă%WŸ­ű0/+ůHŠAóSô_ٕA˛yęBý,.Vž¤ÇFő'ućoƒ&‰Q–.‘lV48 ňśßüU!ůA œé ¤`ćBä‡ß?üłŘůĺwO€ÚçýE.χíô§Hm-ž…&ÉÔÉÉCˇPęËşÔаž9–wT‘Ay°őŐcˆ&Z3Iş#ß\1ą Đäťe˜’QÜb™“G~°€FÉi%á×`6löśúĎŻ~Ľbɸé:÷œłąuëôHb)—7'H,Očȇó<<ˆő[/D¨Öľšëióeľ5ěóšŠi›3AűDąĄĂňȏ cA,<ĹĐQłľňÉ i=–Ňč ů™ŰlÖ @ř(Ş0đ×R6oނ™ŮY<˙üłŽ Q9ŇI|ęçâżţěfôt›#=,$[LŕťĎw‡ú˜™™6?oŻ“›œáŁ0WE}2Ąc@ěD~D°E8-đśˇ˙ZUÉŐk^áT˝S 0ů!đ˙LąŽř¨ íPAn)‡łůřą)LMÍbýúĘäkCƒŁ<6‚ŤŽş ĂCC8tř Kw`őCwxdg0°ŚĎÎ;vtH×3t—rK*EAc+fRGʡţ‹šJőů[?Z QÁDk&Iwä›+&–aş‚|ˇ SňďM—Ëœšä‡´ć#?–JlßŢç}pç.ƒčŕËĄĂGŃÚ܄ů…EăôÁçÉç :™É'u,aďs‡βӜ˛ˆüXŽ-×nP]TɖĆÄYĆń­gp2Ąýč~ô¸Ú Xů{~nMÍÍŸ `ăƍ8xđvď~k׎óÍpĺ–üâď_€?űĘn|űރ ÂqśŕŢçó¸vł|ÔäŘؘý*/ŰБă¸KHiužJNĆPżD~D°EXQ R‚@ˆ"@j"?üţŕŸ)ÖUąTDĄ!…ŚÖŕ9@,dçŃÓӃwżçˇđĎůF†ÇĐŮюéiý Ös‡ńŤoyÚÚ[ńĚOžÄńG Á‡î10äÎ^ŔęW Řş[śŽCG{&§f°_×ýľˇžŮĐ=tč ~ÁţJŽ–Đ ő§‘*"]ţLŻ÷ÚĂ&˜ť ˆüPAL´f’tGžšbb +ČwË0%˙ŢtšĚÉ'?œi^dšSČš_YżŠŤz[}˛Ł“sH˘„|Ąˆƒ‡ŽčOŹSĆŤ/ZyT>*,Ÿ×›žŃލʱç]{o"‰üÇn#řX Og1tÔl>#?Źfg§ŃÖÖn”‰/3şýδűłöÓăfŮyD~„ÚRŔĄcIiŢÔl*8“ĺŹWČźkKnt4‰ţš­\^' ‡ŐüÖÇôräYŇő)žÍă°Ň´€OÇĐń˛<9B|R+0k!ňţ™Ďsɚ7†šaœżŽRęS›sƒ#•Jcpđ8^˙†W˘ŁŁ ˙úąĎ`ďÓĐŰۍ÷ŕ÷đŞWżCƒƒ8řĽ]X‡^ý&Ë™ÁoŞď܃clqéîŮ˝ßĐýĂ?~Ą;<<ŹűP‹Œ­Ö ăœqWĽľVŠ gUůĄCT8íŔSnQžšbb +ČwË0%˙ŢtšĚÉ!?x+”qаfS;žÜwÜ5 äüóşÇĚĄé’NP}ƒôŕCâůiĄd~6łP(#A:ť{ Ž ĺSN%ĎÓćËjë˛}Ůqdç‹mËeˆüˆ˘Łfëô˜óĂřrŠńť` đC{}}wísë×ó´śś_iYX\@cC#ÂТ;Î=SÓS˜œœ4ld—& â°ąŠÉřÚ Ÿđ”ĎůńÂKOŢ~űŸÇńÜłŔgď;żƒ.ăǎ!“Š3F€đ‘ ăăč}~š’•ŃQŰ ň#Š-EŹ(úŇŚgĚkĄśÖR .ÉAH€p9žŰÚRD&Q ´™Ń/ƒWŻ*‚™Gu2ď(.RĺWŇxéôrô÷›ŸÔćý”ÇÁ×<Ţ „ŽƒĺÉ–"@jf-D~ Ŕ?‹PW|ɕôţ*ľŃ ý$͇Ń>r×ßp-nźé:;żż|ěčQ<đ‰;pYă6´§[]ąŹÎuă˙t+Ž|˙‹ÄşÇŽłŐóIU‘^ۀÜCshĐ˙Y!:ÉăBŐ>‘Qbˆ§xĘ-Ę7WL,ĂtůnŚäߛ.—9uF~°€§>—^ľß˙ńSŽW`Ú;ü7^üł¸ŮLŸi4?Ł, ĹdɜřÔ,ŠEf|Ň3_ŇpéĽW Ä_{ŠÜo1ˇĚ˛ÚÚ˛Ďä6ÂÚI(sę“N˙Ę`áé,†Žš­Óoä‡Ţ-[u~ŕŮ]>çƒĚhnnFcc#ub󖳠ÝýĹzćńÇӉČ<Î9Ç?ńďźx ~éšUřOďĆź7m=;VW.?çćő ˙)´ľľazzÚ cîދ—˛9ýfĐ$K4IŒZ@ěD~D°EXqXČćĐTŸÁ†ŐÝřÖ#ó¨Oűs_q~8Ą)ĂžXđ&a1ϰq9ŸĎübÂJ ľ˙!ňCOňƒŮň|ŇŇÄŞh's~Ł448ŒŃĄ㕕tyRÔĄ˝GqěGű°mžíÍ­6ó`šnJ7⟊5¸ďŻ~ŒWlĂęklÝÉą)˝h ŤúzëZ0[šňT§ŁŢ]áů)+3œqŰűŢľÝ.L,ĂtůnŚäߛ.—9…ČŁwU3n¸i+ţçŮŁ@G§}rßťëI’MȧŰxgFЏ ßd-é›ü3Қ9ůŠîʘ¨Ó‹5á-żôÄ//˝ö‚’aG„,<ĹĐQłu“ŕŸ[çSđh¸źŽˆoî{==]‘Ď ŢňCÃč[Տ¨ŕŻŃŠňKĘöŚ4žöâGť&đ/?<„Oţć&¤ü5ś"sňZéVý”@2QD)‹+Ž™NŠ0-ŠŻëń§ż÷lÝ´QÁĘç&zíE`ţĂmČËš,0áŚ$A=Ý-rzgPÎł_ƒA巔ß<­Ńobž~ÇÖŻGCCƒA`ŹZľ ÓSSĆímj“[ŕúĹB!T:ńÂm˜˜+ ˇ5ű„&…Â_+Ňý?żó1źxI/‡ţ›k”ęą ň#†-‰ď‡ŢOJ͗aÁ:ŁžFşžëzę‘IiPż:Žî9—g8<ś„Ł#rD%ád‚Z9cŸČقÉQ,sóóč*™CŕƒŔT8AÁI‘Ÿďǎějôtwč7Z9Ôľ§‘I¤ur%áŠEřoË´ŕňUç!_âOŠóHëşłšy<ţż{ąîŰ ŤúzBOöüľ™™é9[Î9ňCsTľFäG´„‚j`AkŰ.˰‚rUdXĺŘđďM—Ëœb#?uAíÂozŢ˙Ž›pÖY˝řŻß‡căÓxÇ_~MÍĚĺň˜™[´e—´ŇMH• $YZ‚Őcř'7?řŽ7ăĺ7\„¨°ŰÚŃ™q„Ńk/ţ|ňr. L¸)IPOw‹œž#?ě$VůIéÇü  _Ţů0FŰ[š7ř'qůk(ĂCƒ:٘4^Q'M úo¤ ř'sůÂ'RÍ嗌9H&&&Œĺ™}ĎĄďąűą˝˝ÎuCçý;‘ŃmN.D׏łó=Ću.+ĽŻŒkمd;˛‰9äJő¨ăm§/ƒSyýÚTţîŔţgO•™œÍŃńCXŃ ¤`ŽĹŘ'ňĂ_śhäżřI%RXŸĹřŘ$ş{:Ľ¤żůâ#?ršćöŒ sĂęNsrÄ´nØEžěߘŽyČ Œ9`řΠY'Mř^gC;6 ÎcčîĂčťaƒá+´<ăX[@ ż9Mx [ż:äGUžÇ1gʘX†…ŘđäťeXĺŘđďM—Ëœ<ňÚ´8¨XČaŢe^ý’óđň›ÎÁŁ{áů#ŁŸ]@6WŔcűŽ}'›3'„ÓĘ'žžps/úzÚ°eý*\uÁfdŇŃĘJĹJűVFÔ{ڜiâŘ1:÷}2,ŕ8˛óĹśĺ2+üp8Á„›’őtˇČéG~¸x‚ňť/vŤđž×ߐÁĺĂĎŕ'PßPoŒfä7]œř8~ü(z{WĄŁŁ*ŕúĹźZ?äŘo|Fޚ€•O|zôč1,Ü{^ŐPBFKŮEĹ'Ę#ň#ş­ ÂÉĂŢý7ŁŞŹ…O4<Ѩ“„Ů äç`[Im’̢ţ–Ô˘ˇpQqNďu/ü ŹR 08މüđ—-ˆü`ŇXę“uČę7E‹k;ő'T#ččl7žZ9ą´”ĂäĔA~äFőŠŰăâŢó<Í~­Ć3ňƒ—Só” 0‡ 'sóŮS‰U.ě7´ `ňĄ˝˜Y=líŇË3Ş—§-°üđĆb<ľŇ7čHÇ!`apFtŐjŠT étҸ+čO ĺw‹‹yŒ|kŽë9ßźx˛l•Ék°}ÚöÄÎĘR6ůa(›ŰćóťÎĆ}˙ť éˇÖ=°Ë“ĘđQ& ů|Ń.On:‡Âƒ‹hhođÜźť_{Ť*‰üĆŔÄöŁ€‰Öś]&–aş‚|ˇ ŤŰţ˝ér™SoÂSŤ?YŸÂM&2xöŮăČĺsȤ38•ŔoęöíŃoÂ6űÎ67úř˛Úĺv`raí$”!ňCž žî9sČç\ Ćk^ĺƒ=“Đđň6 ßzŕNěËdŒßڒńié:;; ňţšçŸEww/:::¤7;uşn‰É?SŸç“bfvژđ4ŁËóW^ĆÇÇ1¨§ďž÷A\ş˙Q\ŇŐb˙.kŢ`Ü4+YL”ŠŘmËbč(ŰZĆq˘|ě*Ř !œ|4d‘ŠcČԗôžR@ĂüZŚ—€Ů"ňKę„Ýëńłƒę_O´`ô•Âé "@j"?e '?L]SŃ|Jĺ /ôŰ;7ŕÎďí‚öęmhčk5.Ň ž‰× sK8úßOáÚŚíHóa´ ök/šŚšbŃ|ţΛkk3&cä‰ ýßeíçăŢ/?†5żz6ę{…ĺÉO-áŔ—÷âŞÖ uc•šKŒë9nËQš˝Mä‡0l? œ~*mĎüyż*ůnf׻Ԇ _.sj’Ž|˝ŸĽRiŒ Bş;‰ÎödłY“Dt]ťy.ä4ŃSŢJ˘Ž/Ď/l=?N$’Ć(­ŁÇq|(‰–ćŒ-WśFš˜ÜFX; eV6ůá,›˜pS’ žî9ýÉ­|žőÂxőłŹÄűcťNÚżŞ%oß{;vç^ˆ­Űˇ„'?ÚŰۍ J'&Ć01>Š–Ö6ƒI{IMÝPB4—Áě &&'0??gĄÜ? arrÇôžřěýâügÁ͝Ͱ~!+$HyäŚäžČčś|"‘;(Ą–ŕ׊›1­­Zżžœ[ĚbőĚ,Xv ƒ­IĚ)ښ[bhŠS'L,ĚgŁ4„°Ň@H-@䇠lŃG~Ŕ5rĂź`KiI\ßyîűĆS˜>ˇ­çŽB}W4ý)Vn:‹ůgĆ1˙ŕ0Žî8Méűľ/ů!šđÔúkԏ9 ˘•'Űĺw¨Ë˛éDW5Ÿ?÷$ę.ë@űyÝhčj04˛ă‹˜ÚŤ_řÝ7ŽKťÎÓËînoZu†[ Bä‡0î[N?°í2žÇŻJž[†UŽm™ Až\ć&?lúŽœŞ“{- kńŠß‰×żń24ˇ”ĚĎ×:Ż”4ÍM\h˛ÂťmnyśËŮö^ĺOů‚Ě˝LŚą˙(>÷…ĐPŽ}ŐÜe@ÜśFš˜ÜFX; eÎ0ň~˙ňőtˇČéO~˜4WŻ4~#ç­<žŢ›Iăľ,Üž˜žĆŚgDĹ‚ńŞ Ÿ„“‡ 󘚚4^qŤŤo@NjđÉSůë3ü“śüKgšĽ%,-eą¨ë'u9>ڃUfIOç#>řk/|yţšƒ˜Řů.;ś7u7ŸçŐŕ'?ź°ň‰üˆnË'ك:&jjVíŤxg˛œóË/Ţm.7:šDGkí:ŇŇlfÎÎńÉsŔô>4‘Ń05‘ŚĐx‡Ć hL?ÇĘŕ爅ůŒš˙ă#)äY%6ë÷}z.áKŽ—ĺÉ⃐Z€ČĽŘĂÉÍ*łĂw]2ƒë.ÄĄCĂÚ}“šE㇣1UŢ†Nlčž)ýIŻe‹żBăZá"?œ7Q× ×EŁ1ˇAšLĆŢ}łÎŒ+ÇşTŽí˝GvbčáĂ8^ČňůćŒňô4tă|=/¤‚íPÝôů!Œ…űŽ ű˜Cš-á.ƒUnaş$ß-Ăěz—ÚäËeN=ňĂęXîür9őă;nDą´Ÿůä#úÍԜŃOłÓxÇď^†Ć&÷ä™éE|î3ę7K-¨ô5xZĆíżähˆ\nď|ç%hmkpÉ.čWr˙úńő›ˇ6cdJ}}3şşś"•ގIϲ ű‹LŚŘÖ(ˇƒä8˛ó!̗˜䇻őÂÁ”ŐŇÝ"gů!Ęô˝ ƒĘążŞ.×kEüôÉ{đÔä&Ď݁ľëV0r¤ŠŠÉXř+,üuO>ÚqaqĽů’}#Çű'G8!ŇŃŢnČ,..„ˇcNx:Žg÷îGËăĆĹ1\Ž“IMđĎr|.ÎÔĘbŢˇŽ¸bäéŐ<昪|d['ŸüŕX?PôĽMϘ7źm­ÁsSœ /ńÁ匹wtšŚz yô66 Ńa~ŽşT,‚ÍÍó ł°´.-3čŹ[Ä‚ÁmÎ×čM–nÝ˙şôt>Ęű>ƒŻŰZ˓—KČ:–'GX>ˆŠˆü€BěrňÚóĂŢ/?ľ˛žŘbzK`Ck?Ö7÷ůě™ů•gHĆ_O,*ĄşÝűoޝ#5W;[ÄţÝäb2™ŃmĚaëÖU>Űý} Ď>Ď߼ÎHŰŇý:ŒŚŘÖ(ˇC@9ĂÚI(sz‘βF‹Ÿî93É+SŠ1ĎH˜Ý •ĐpľNLlŇožvíšĎęĆŽţÍhYˇÝ=íčhoó šýő$f ˛°°¨÷ËqŒŽŽƒíߏ c‡°]ËáüÎÔ'>âĂؖn"‡ČU[>‘euHBľá%‘N§pî găgˇ=ŽăëŃÍZ]˜ĹţúA ooŔĺë×ęÄC żyS ´ťvaďŇvL—Ú÷‹x‘ĘŞ{iMNăŞU{đśëŰĐÔT/Œ@8ŐAH-ŔŹ…ČřŠĹž¤­lK+g—ĘߢužĆâŮ!‰ĹőŠ[gyě›-÷ÍľVžšňVƒ5gőI\ŃEĽ}CÎÜ|ŒőÚ ź6ËŁQ|UE䇂ď䇭ďüë.ˇ0]’ď–av˝Kmňĺ2+k䇱e=^ś4ë)łfŒY= ţŮ) “ŞłGfhĺqůÎ~ćZ3ŘŻŹđý¤Ž;4,&WÖŽIcď39]śŃ.“3qż kk”ŰArŮůćËeNCňĂYŕ(`ńÓÝ"g6ů!‚óˇËG‚”úęŇxioç-Îă™ýâČÁ'qźĽĎľuŁnUëŃĐP‡¤~ÖŇI‹üXZĘcqq ‹łsІŽĄ{vŰőeSZĂY-uhM5ÁYZÍQŤPD~X ňăt„őšiďžľîîjÇ•Ż¸ťŸ~OLŃÉĆ4ÖŹYË{Ö2|Ůžm#ŢÝp>„šůE—ý…󺲹!řUŠůEł/55x Oăö¸ĎFxiinĆőXżž˘¸DŰŠ"@j~!ňCP65ňĂžňÎ!ťN{Z@,ĺK*Ÿç§gƒnŢË%3ž^WÜřG„8~Ćž65ˆćü ňCSń-z•HĚń×]naş$ß-Ăěz—ÚäËeVůaÝNyóÍžűŘOé$ĹŁěG>—­řŇţu–lśí;FÚWŢNĚx˝erŽ?üŃ^c2Fg~:UŻ$Ű¤Ż˝hpW"žr°JÄąÚI(sz’Î2+ƒĹOw‹ůaAsÉWH×H.×hž˝ŚAżůŞOc&_ÄńĽ!Œ9ŠąƒŔ\şłéz,ńţ›ŕŸ/!­/-ů% äłhŃ ĎžL˝:‘Ň×Őh|r×[R"?‚lůq&Â"AřŤ0W_y‘f˙ÖÖŻ[m,^LM›ýd9sN8 ŒĘÜĽrž_ŽÂJ ľ‘‚˛E#?,[ćgüXŕk/•‘"ÜReÂSۏÿ5´śbNíćÝ"RJž"ZżZٖńKŔÎӄáů!‰Šřۏć]3Iş$ß-Ă*ǜ̆ _.łG~8óŻÂŘ$ˆŽL]&Çű âĐkťŁ­üăŇöDSůaÚ2çĐik[‡ą‰´˙€ĐŰڛ„1hšą­Qn î|óĺ2D~ř #Ý-B䇚 MxâŁ+ż•ÁôV?ăZÓIcA3PĐŽ…B ó…äőí|ŸÁMęrőušÓhHÖšÉÓč&AˆüđgŸ@ň#V'%,˘Q ŢíĘä°×ćo ˜lpNFěľ)+Cœ(_D~+ D€Ô ĚąŘűD~D˝˘Ď¤ąx'<őDz<ňٞíâĚcVi\Ĺ#ň#R Lš,u0ďšIŇ%ůnf׻Ԇ _.ł2Éă ˛ăbŽyH+†ööšÇk/áţË~ŻÉ@ă_žXăŠc&ľĄ ćâ!ň#ČG<ňĂYöŘ`áén"?déüǤ3Mƒƒqő—ŠNJ—iM%ĹçĆňŁůýűˆË8ˆü¨€Č32Rĝćî+Î󹗰X.âôé^kB;˛}áT ľs,ö>‘QcwƢIc ŽEc —|E=ŢÍ;ě´Ęó1Ě!ă-ŽŠ'šą'ňCÁˇ<†¨p–Űľ’ď–av˝Kmňĺ2+{ä‡5—€ćźx ­'&σBůĘÜū6œŁK*ůD~×5‘5łŃł˙D'?,Xš%Gžó•c_0"ÄלFœyLLd8ýť>x+ˇtˆüˆnË'Çá„ÁKxXi""DD,ű&ϋ#ç-‡lż’FáÔ ľƒűęČČąËbŃ<ň捕ćŇ×$ąWĚ-üpćÁń9]çČ8F„XEž+ţ‰ü÷CĽA”ŕ,ˇk?$ß-Ăěz—ÚäËeVřk/64—Œ™˘™Ý”Ébdţ48˨ ^{‘דł”Î2jŇŃ%D~°@Ë#?œ1D Ow‹ůĄšnô'ćĎśî_Źt爔u„ö˜„ŠfŇĂś Ą‘ńlůDâŘ"œp„˝~Â!#Ij ń„ŚL˜”F œŠ ¤p^őů9ö(ą#<„ąÔžüü0/óÄ7YD~Hb`*žƒÉ+/ ˆüPąHäGeÓńČŮ>Αâ 34ŃW_ĺóÉqšÓ–Ç&ƒM xmů!kk9ăóÎ"ƒ…§ťEˆüPMgŽ<ßóZ+Ý;"DPżÎOĆ[đŽđđBö€ŘžĹbŢš-•tCGŮÖ2ŽĺcWÁ–O$Ž-E:–”ćMÍ&Ą’“ÉŠÓs )"“Sľ§&'żmt’Ôž'FŽD€Ô üźDäGäŘŤËÉ!?ĚMMŇTD~c`*ž‰üÚ Œáä‘•$ ŇFś&üÔ­Üx]›ÄłIH-Ô‘Áu]ňĂ‹2Xxş[„ČŐt&Čó“Ž<ÇĂ_ośőÉxŮČŸ OzŎ×?‘Şś|"qlEŔú˘/-čk"$]NFnœ{˘Qš˘ĐŽĽCí{bäË ľ?Ďů9öęÄBäGx §ůa­Ł€ÉÖĚ˝ď–av˝KmHĘ%–9=ɏJ šÜ†cäG°M"çn §Y[:Qž8†€r†ľ“Pć $?œŠ€…§ťEˆüPMg!:šL˝œŕ˝7˛FW ÉŇËđfůݖO¤ Ç/áä#čő—ĺÚĽÇyu…^w!ŹdR ů9öęÄBäGx §'ůamŤ‚ÉÖĚ˝ď–av˝Kmňĺ2§;ůáMwŹ$Еbš§ŽYŮŘĐ"śľó§Cą„2g&ůáž&&˜pD~¨ű`t\6döbÖťh‹ČU[>‘*ż„S˘š8D“§žč˛+D€ÔĚqĄa-D~HcŻN,D~„Çpú’ Ń”™wÍÜűnfםPˇüǛ.—9ÓČg>˙Ť)ú÷á,Ľó ´áÉŰgJţĽmÎíņR D~HÍ+Śł0ůjڊčƒŮN,ůáÍ˝˝…üĐ$éđŮ"ňCՖO¤ Ç/ae!ˆŒ¨ţgpĽcĂ„ "@jűBĂZˆüĆ^XˆüČ'˜wÍÜűnfםPˇüǛ.—9ÓÉU˙á>œĽTśáÉŰgJţĽmÎíņR D~HÍ+Śł0ůjڊčƒŮN.ůá/ĘœJé‘1lůDŞi‹@ ÎR 0ÇBä‡4öęÄBäGx §?ůaĽG3.çž+Ż\é̗îX ňĺ2D~¨ů÷á,Ľ˛ OžŘ>Sň/ms&hŸ(6”bXYä‡3žH`ÂMůĄîƒĹĐ ´ˇĚzŰ"ňCՖO¤šśá  ľCĺâ…9÷­m"?Ş ‘á1œ䇕§ g\Î}W^šŇ™/ÝąäËeˆüPóîĂYJež|ą}Śä_ÚćLĐ>Ql(Ĺ@ä‡Ô¨b: “ŻŚ­ˆ>˜ý‡Č(é,†Ž˛­e'ĘÇŽ‚-ŸH5mÂ"@jëⅡ˛XéD~T)"?Âc ň#D~ˆň‰üˆŐNB"?Dq* 7A䇺C'ĐŢ2ë]l‹ČU[>‘e‹@ NCRůßD~8ě#$VIÙE~XkUů!Ę'ň#V; eˆüĹn]"?TÓY @{ËŹwą-"?TmůDN”-@8MAH-Ŕ‹˝OäGub!ň#<†3üXÎD¨pŮbv˝ťÓkAž\†Č5˙á>œĽTśáÉŰgJţĽmÎíņR +›üŢ@Ŕ­Bä‡j:‹Ąho™ő.śE䇪-ŸČ‰˛€CǒҼŠŮ$T@r$Gr˗#Ä ľƒű Č*ĹBäGx g&ůa퍂 ś‰üđçKm„Ö“çAĄ|ÎR*Űđä‹í3%˙Ň6g‚ö‰bC)"?Ŕ”Ľé,Lžšś"ú`ö"?˘¤ł:Ęś–qœ(ť ś|"'ĘVÖ}iÓ3 cÝÖZ Ô%9’#šĺË–"@jç ‘UŠ…ČđˆüˆŠŠ-fם;ÝąäËeÎTňC˙W*ŮišŚšŽMĽňy|Xv!!,F™}Śä_ÚćLĐ>Ql(ĹpzÎ¸ŁČŐtžlœ;ďw‹1b'ňcšśNOňƒ@ NR+W#D~T'–pňăwŸ{CšE8QŻ%1Pׄw ŕúö>X7Ë;ú$šEwş˙źĺę˛ "?`ëŻ<ňĂZGAE—ŮőîNwŹůr™3‘ü`hëHăšk{°u[ÚÚ3ČĺJ8|h>0Š={fL2„irŰÎRŠc‹ŃÜ*é‰6côQ#Ć "?ÂŰ!*ˆüPMç”cŠÄĐřŠo!ѡ…] ű—ďER‹vÎw­vÓ"řňQKňĂ>ÖJŇ'˘­@ůČśˆü ÄĂgîţćGć‘üoo^yAĽÁ>y—†żżŐÜ˙ó[4źý•źoěţčL˝ż’áu;P\ř×&€WŸÇđׯĐ@ œ.H€P}WD~T'ľ‘Z˙Pβ"žĎÎŕ“ƒ{đ_#ĎŰ&-ic­eeD~ŔÖ_™ä‡ľ­ŠŠ.łëݝîX ňĺ2gůÁôť-[›ń{ďݎŤŽY…Žîz¤R 46Śpöövźĺmgá5Ż]kÜ Im |8K)Ž!,FłlŻşĽŸü§Kń‰^b0”"Lj@"?ÔüG#ňC5ݲU`•óďjEů(=žYԅëţáłhúŢý¨űűOűL"•t ćäG)FË­÷ĄőöűzË;PbńlĘGśľɏČ”P+\ľ%mo?|Č}]űŕJ?zđťOí<\‘˝ĆacŮĐL?Z‚㤠œ^  ľ‘UŠEü°wtlëíÂ;.żü ŐŁSłřňŁOęěuß?ŒëŰWŁ/Ó'ˆü°Ęî;0Śâť†ä‡} ¨‚šę˝źé_ ňĺ2g&ůŃ֑›eęę’ú>ĂŽG‡qđŕZ[2¸âŞ5hŃ×W^ՋƒfńčŽ){$łĆęť|hśuă_ů&L>z„ŮśLs•Wnx^ŠTԗʻ´ĹRN—IťýÂ!bĹhÚpű’בjţŤŚ–ÎÂäŤi+˘f˙ŠůÁëźäh7~<ő„TÂ?,Âú-wł§0“@)ęü6‡÷˜źžŸŃs5 îc˘źaĽkžňXÝZD~0Żźł’şbĽĘśs”×Í;NŘđŇşRL’¤Łf‹ČÂňpn_ M&ç9Ti~¨ďtěď<čî?2×Ý-śö1="@jć¸Čą"?"ƢN~X7ďZëFRFŢŚ†n4\z!ţßÝűe'đqţŢ[lců,ž;vOΏc^żQęHÖă–ÜŇšMŠ4v͎â“Ç7dßÚż—ˇő—ýk¸{ęž>źÇŘߺ˹ąĄD~(ĆŔęuähU8ëÝŢ÷Žůr™3sÎ~ŁőÂWäǗżô$Ů9‚„ţ´¨¤ßšÜu×QüÉŻBSS×ÝЇŒŁŻżř‡ćřÜ/|ńY\xa'věčŔwáśŰ şŤŽęÂŐWö˘§§Kš"öîĆn=ŽńÉ<ĚăŢ$GŽ¸Ź /¸şý}(J86¸€Ÿü|Oîž6ĘöĄ?>Ťű+¤ç|ějě?4‡ż˙ŘăĘąž.[^ԏK/ěB{[SÓ9<ôč8žÇ î—ĐęČ5˙îzˆ Ś–ÎÂäŤi+˘f˙Šů!3Ώë6Ąéă_5öçţôHmż™—żZS3Š{žŔŇ'˙lč8J-mh˙ę­śn㜠Đůƒ‘ýÖ˘đĹOiÚE—#óĆ_Gjó6@ď߅˝O"÷Í˙DéńGlÂŁîƒ‹ô5/Daßn,~íóhúí÷#ѡ“/ÓĎöˇČ\űBäۉ…O|żű‡H}.ŘĚ4–žóuôĹ"8Œ˛74"ýKoCúş‘čęFi| ůť~ŠÜ}XĚ"ĄŰęţó˙k—šůWŢčËÜßśóAéë0L’.Żdyş;›ČÂňĄiE\ľ1=UŔž!†š%ýŘŽžfłú5nFCAgC&t‚äšQ gő2L/Ϗ˜yífţ[Ě'84|îV żx˜Ńu×vŻšáˇŻŇĺύŻűŹů[÷é_ařţ“ŔOkřŢw“¸Œ§Ÿ*>u—ŮĂţţuŔ/]Fa偐Ŕž0ą"?"Əü°2‹łycł8[ŔęĆĘPŔéTŃ‘XN/dńW‡ĆL>gěó ąŃü"î˜8Œ˝ “řŁu—ᢾŤŃ8ş šžĘărôŰ#?žÔ÷9z››ô¤näg‹â‰üpÇŔęuä)ż2<~}kAž\ć̝đTӟď8żËŘ?° ťtň ĂGYiIctČÜ\ßúć>ŹYŰăKĘ(Ř>oşŠëŒ<é|yó›6âĘ+zm™t:K/éĆ9ŰŰń‘íĆč¸Ůż_ń˛~źäć;ŽL&ł6ˇËçżüŘ9 &:2ôru?őu)üń{Îƀƒ éîŹĂ-7ŻĆ9[[ńˇ˙ş…˘ĽżˆüPóQ DSKgaňŐ´Ńł˙TŸüĺs0ďý”źĺ¨ÁÍö~ę˘+ }řc˜{×/ŁEDŕÉƨŠ›_ŽŚ÷ţ•ÇÍ:Ň:!’žđRĚ˙żĄtĎOŒWnR\–g6ˇ é…Dc“!›ÓËŃP>@X]=š˙ćcHööűZ}Ţůű˜›Ÿťý‡Fő”t™Ćú4R6WĘżŞÉ˙óŤzš/ĹĚűމ$%ßjşŻ ⏪llj;›ČBőpÍYšN€đ‹úƒť#ŽÝÂđĐţŠ ĂŮ} durţéĄ:ýzxôpĺčę-ćQ˙ŹNlźĺË&b“šCĂýžňú/˛A8Z”#đo?OŕÉc–%~{Xđ•íÇOUȏ_ť2_şœ˙0äA Ź4Đ ľs,D~DŒ%:ů!úˇŇOTĆś××BYŕŠě¤~Ł•Ň™ö ţćĺ7áż~ý˙ŕíW]jäÉÎâń…Q”Ś ¸|yĂľ{jLżĐ2uő›Š}SŁFú•ëÖůĄS¨#Ôó—S,hÍüér™3•ü€ńľ—ŚŚ$ęëMýŮg'‘Lfô‡Ă¤Ric;•ŞĂcMáűß;„ď˙1HÉqă˛f ßĐ ’˙÷㡇G°eK“M~üđÇĎăÝż˙|ř݁é™%cN‘ןj­AŹ$ gmiE.WÄÝ÷Ĺďž÷§řý?úŽŸ3t_ń˛ÝOúżăGˇ°ýýĆťnÇß|t—1zäe7÷äGQżsűčż?Š_×óţĺÓťŒ2nX׌Žér˝#­Ëeľ5ÎňĂCd0ľt&_M[}0űOíɧœ“רťôjŒ|řpäíŻÇüƒ÷iÉŐz:ďgŚpřĺW űŒ9ŠqqĎS8ř˛+0ű…O ŘԌĆß~żA~,<ô |Ëpđ/Ââc;ůÄhř÷٘NŻ XţRë°´˙Y˙;1ň‡żc,VŻĎl߁…ÇÁ‘ßř?üđƒ̛§ş[^cž†Ł/É7ýşA~°BÇ˙ěýxî%Wë˛ÂYR¤Î:闿 w˙ ^v˝ßřWżˆC7]‰ÜÎýA•-ă8qgůA¨.ŽÚTi ĺy@üŞ:|ďÝMxíEţŰĂýcŔűżeę]ş!‰żxĽ.Cäa…‚Z€ĄrąĂœűŽm"?ą,Ÿü8<3ƒĂK 8”Ăƒ3#řŇń}vŢíÝđž*aŮźqÓ&|ň5/ÇgŢđjŹIcîĄ t/TFL&s†ĎËťMdQżh{fqÂŘ~jaĚ~‚vIű€8d"?Ü10…:B@19Ł‚‰Ö̟.—9sÉË@}ceb´……˘~?”Ňɉ„12JÓoŽřÄiŠT=’Šzƒ á7LNüüç‡ńóťŽăčŃ%ŒgqÉĹÝFúŘř"ţ÷űP(Śp|h ?şuż‘~îö`џlŠřűěÂďžďçřň?Ťď'ą”Ó01™5äş:ęË1$\7Ě˜˙Ă|E{Œ´{<ŽGŸ×ď­ŇxđŃ1ě||ÄHżäüN°bî‰X‰üPó/Ž!2˜Z: “ŻŚ­ˆ>˜ý§Ćä‡Đw%qú;˙…üƒ÷ yě0Ś>÷Żvz˘Q˛ ď(Ľ˘‘ŚéëŒN4&uýôĺ×Bk0GIýëß#Ľ“%Šé)ŒňŁŚ~[pöůƐŠăFţâŔžÜ<ů¨ů5+KďS˙ňwĐDîž;1÷‹ťôäŔZs˝u/|ą‘6ó“céţťQ§!ŮťŞËŢe¤gŽ˝^ďŮzŮXą‡NŽdŒ9@PýÁ$UłŒăĝMäĄúŘÜ]D_ŤŮgŹš=v4îœ>`ÇjwÚŽĂćz]gkŰK86°ßóHÇkÎۆUů:ůô¨ž  š‘,ž88„űŚăpvcůEcd‡¤éoSŠí ˜Z\ÄÓůqlCžČšŁ?Öuv s1ƒŠÁ1°Jşˇz IˇĘÉěřůD~80њ‰í‰eˆüŕćsś­††´kňCžâ$í%Q~ULӟ;c9v|Ţ F8QÂGvđ9?8şťđŸ¸^$ő~ŘÖšŇ ’š[ęq͕kqöÖvc>‡G"aGć×?™1‰ć ] ŃIMżqęé6}]ő€ąxŃÓYo”6aĎ4G䇚y~$0ľt&_M[}0űω'?ź( C]2a<őĘĎLV2Ňic(|2ĄšJ™Ö‰LžžĐ‰ ëžň}ąńŢ~W! cŁHĎNŁNˇÁɏ‚s˛Ňądrydô˛_š™4$hz9ŒWÉR}ć^ŰK_i,^$ő|^ڔƒXá¤GZ/pD~,ç8QÁĄcň/‚LÍŞ}-„ä‚ĺ.Y—ÄŸĘc÷q†ö$16gŽě8ťGż^-_š›bŘő,mĹÜżdMRo›"9fMe ŹnŇŰë¨ůëË_iŮҝŔčl űGÍvœ]Źô!SÖ"yzŇţzŰÝĎUFnžôœ4Śs84EÇÁɖ#Ä 5‘ŃbYů!űMŻOĽ°śŁ/;{ ŽiěCöđźŕi¤iëřřâŕÓFJ‡Npœˇśë:Úń­Çž˛ýpgЏbÝZÜśďěžĂ+[ĎÂÓÖë/kÖĄ°@äÇÉ ?dÇ@œúđ”+X†Č+mfś€Ľluő)l9Ť wÜ>¤“ •|ţşËůçw`` ÁŘ˙Ꮟz‹IDEĄXrN1€‡wٟ“°#ŃɌ|ždL^ú‡ď9טŕ”_ í?8ƒÇŸŃ ”ěŘŢíˆŃsăŠ9uŕţ‡-ÖÄöľ˜­|.W‘jţĺů‘ŔÔŇY˜|5mEôQ9ĚN"ůáČKjfQĆĚ=šOÄYJÍąďěCł?żÝ6lwynqtÖWš đWU8!aŒÄĐýy>ËÂI‹źĐœ—%ĚÎěĎn7) çń¸°`ę2™5ť Şflj;ű4#?"vŇőE_ÚôŒyd´ľ–uINMîĆs8˘?ԛg8`žŮ‰öśŽ2랏äŕDĆ^™)ĸé\łmŽ.UnžŰ[ ŽöJ§Íǧyúxś"ŰŃVđľ-ŃéĹžĘá}/bhoDhŞń’\49ÂňAH-Ŕ‹kŸČ,Ő%?.čÇ_r™Wd(é„Dn8ë"?œ:–[§űçëú¸ţŔ\Ł“óřžŞČ–Ÿb_ÖއŰđ †ćđřü0–Šă˘ë˘ćUŔR@ Ź’.ЁČˇ}_9™źœÂ›Œ8őá)W° ‘Žş×űÄ㏏âň+úąys;Î;żO=5k\4ń§š--IźîukŻŔ\Ŕ÷žH×IşĘÁGhXm82şˆÍ›Ú122Oî cdOOŚ4cŽ0ý‰r*ƒK.겿îň÷˙´Ď>?mŘxë/osۆť5>ҟal"‹îÎzüôîĂřěWöD ?žřěřš3F‹$ůč­šm "?â‚Iv™şNl[}0űĎŠA~ \kŒ‡ÁVářQ{{âÓƒ6>bŘ1~ş“z)ä‘ŃűŽŚiwĺšßś7Éâ*BĄ€ÂČR˝}˜úÁw1ţ‘˙k7ĆçŠÓi˝sć MCň8˜$:jśÎlňƒpbpÍćJĂüŕ ł]˝™ż^jőWmJâ{—ô<~Ă\2úŇU[Lő];ťŻžŔÜćŻjď2oŹ7v›zQđˇŻnŔ˙wc:!óĄďkř×7ŃÁCXš 9@jĎ]@ä‡(–ęÎ'TL:<{˙˜ąĚ=4Žů§Ś‘]r]§“ća?]ÂP~Áć^H˜?ZAç>vMbć™|÷é§á„ĺo ĐŹłďćěöwL4ÖŰVő˘q6)UŇe1›”ČGýÉÉ+- œíbď{śÝ2D~8Óř ' î¸ă°1)ÇŻýúVźéMëqŕxÉKúđž÷cˇßvИ|Ô gĘÎGĚů7z{›đęWž…††z´w4ă÷ŢyţíŁ×ăÝż}žq¤RîşáŻŽ_ÓŽ#Ť|śłŮĘmŇö­múSŽ´~ęŃđa˘ăşŤ×ಋűô'cőظś˙ô××ŕ?>r^{ËóŚËUŐh§3üđˇzD0É.S׉m+˘f˙9‰ä‡L%ÄViaŢX§VŻ…6°ZK;rŢśd~J˘÷˝ŠúŽÔ76˘ó­ż‹ußť}ŸţŇzZ(­•eîgwŰm/š­/¸ő:ńŃ´ů,ŹýĎoaÝwnGŰŻţ†1’…“%ŹüĺśôYŰ ő€eęüŽ–qœ¸ł‰ü œôˇË$poůő“+7WzŮUĺ$YyŰúčn4ߍYÓĆpŃZóAĂW,áýRöčđW?L`dĆlôW_í‹×\ĆŤÎ+â•ç›?ž˙ű ťÂJŠœW„ĆBä‡?–ę‘ŢßpoóřX×҆_ŕ(rĹ"ţěůűđÁ —ăÂŐýřÉłĎăńá!źol…Rmőő¨O%‘-]žós\ľnžˇ{Ž-˜_™šBż`,ΗÄ1°Jla1¸Ť•ȏJý“Ţc Îvą÷=Űn"?üyüénăcY|é‹Oá-o݁L&‰K/ë1'n˝ív>:Žd2 1ĚISŸŢ3ĕ—÷㕷l4'rĚđźgߤ~ďS҉ţôý—bn>Ö– Ž›EKsĆ.'żIÚó씭˙‡ď>‡ŽÎáC˙ďq|çLJqŃyÝčoĆčĊKKE<ŞűbfÉŞĐÖ8ĂÉgJD0É.S׉m+˘f˙9őȏ0^âĽ'AĂĹW ŮщŽĎ|‹ßůrŸţgŒâ#č~ďŃpĹ ĐđľťôňűŸEib,žoO:-Âç™űĘçĐxĺľČŹßˆžżţGˇJvŮűď1Gč\ö‰ÇĐpÉĺzŮŽ6–Ů?˙Ř÷VZ`lj;›Č‰D ×lÎŕŔXe”Ć+ŰWmrK_ť…“%E[÷ĂŻ¨ÇŻ|>‹š%†ˇŮ}>şöŹ$ţĎĽQ_ą(ĄT,á/_]‡_<_4&EýÓď$pš^Śś+4¤V°îʈüÄR;ňž‹kNŠŠ 4­RF=Ë|áËűđŐ˙ރĂGfŒ‘%œŒŘ÷Ě>öďážű‡uő&§ ř—O<Žƒ‡gŒ9@¸Ü7žý,~z÷GɌqóx~˙<>˙Ő§1<ş`źFS_—4ʐËkř‹؉ďëä ĎăežËáţCřłż{‡Ž-˜ĺ Š'G5…´Ó™K~8Ó"Iv™şNl[}0űĎÉ!?4Ďśš„ŽË°eůźŮ˙ů*Śż÷ &ǍOТŠĹ‘‘ťőťúŕ{°¸ë!”fgŒQšĎaü“˙ŒÉřË2qy˜Ř§Ž9Ó5Ł™Ĺ,†Ţő˜üú—‘?~L÷—Gqz s?˙ ű­(>˙œ9AŤžLţĂß`îž{PšŸ×ɑ,X{‡ńú]`ĺ1Q6‘„ŤˇTś×´›_xą°ąŤňĽŽŤ6ťűúŚŽžőŽ&źćÂ4ş[4Ô鏻ˇô$đ‡/ŽĂ—Ţ–ŃEă}žśŤ1‹żŇIŽŃ9†żř^ř9†@8Ą)¤kŽ}k;áX[K˛ź¤Ę  Ç÷ľ_|ńeLMMătGŠT˙’Ář÷ň]‘ţXŞO~đuĂEĐę“(Nĺ°°g֔e^˝ň ł~ŐTżŠ évýMi˜n^żŕËĄ~}#R㪪0WŔÂţ4ďh…ŚË,YÄÂŃEŰ7řƒ'n5ŢŠźxÝ~ľĺˆŚ—LŤB;áä‡ţgřŽ_QîŸĎ^Űă6ć´Í SKľŃł˙œňƒ'çô§ł‹úR`̘|”Ď“Áo—˛sdb˙ÝK/Ž §÷ŤŹ.ËťOˇžĂӗôô<3ĎÔü+.™„yüçk–ĎQ.Ɖ”ŇbpŞń’œTnÓś—‡öĎÓíímxôчŻÔ7ůđ]~@ň‹ˇBy)–—’caŽľóňÄIâ˝S ŐNä‡?–ڐ|™ß5éʓ’|Ń/ŹŸ›Ă‚Ç÷źţ¤˜íŸ/ű7ĺ§žtů^Đođ†sóŘ71a×ôo@iĘăUbSÁUNć­V"?„méȋ &Řvś˙ËóĹţĎ$ňƒŻř2'%R:ّHy>JÖPţÁśF~“"ęäBĘ +L˛Á"?L[šA>đ|~ąmĹŚ•żĂídG"Š˙xŐé7<œT)NJf̰ÉóŒľ^6¤MRÐ4Ędć%ůmŸ^î$c°^`3ĘŹ§™Ÿł!ňŁä‡3O L˛ËÔubۊčƒŮNůaĺY¤˙Y2>kË ‚˙ęłyÁœ4{‘ŃÝř‡ ´dÂhť”Eči>ŞBOŻ+űâ6’ĺ~›H0ÝďŰfœÖ¨ţԋ܋IN$ ˙)TäR6qaô8ó 0źŒL3H–”ŚŮ:ZyÍť_R3IV˛Ęc•I+:á ÷oĆÍ [LƒŚEŹG&Ę>3Č0zŠJB'#“Ô`ĽYŞóŽŁ“,D&ˇ4‹†şR B>Ą\.a%€Z€ČA,ľ#?źyä‡KWrcĎäž[ÁŻ|ćŹŢnœĽuęôdž"Ë*öŁĹ@äGĽţ˘‘ Ń.ŕ˜`ŰŮvü/ Ě÷Żm&ÎłmćŤŘŔ)E~Xk‹ŕŕˇ7œüH0+]óÉڄÜmjîk& ’0o€Jeg•ÉHËD wĆoĘ_›) Ťc6b˛.šqƒĆI>g€iKł hŒ*á:Ér]:ó—ßND~8óâ€ů6‚„‚ÓCmEôÁě?'—ü°ČˆDů•˛ňף>”r”ÍzőÄ",YgzÂńZš•g%ƧkŽ<ˡľŸ)çkp×HÂĘ+ÁELhĺQ$)V­a­í˛đű˛„ť<˛¸-}"?ÔňĚcŽČp恐Čš|ĹÜĘ"?řöD2kĚ Âçý¸`íjźéœ ‘{vŠ"Ë*öŁĹ@äGĽţ˘“Ö~T8íŔ.;‘jţEëňH Ǎ ƒÇ&Ó|TF„ˆc`.gžMX.8e™§ĚšUöj´5ˆüř ćŰ NľŃł˙œ\ňĂ ëćß"!dňNŇÂkÇK TˆMŞă҅üMŔ)¨čřŕ9öě2/ă8aŢR-ó˜c*ňŐ´ëř%ňƒ@ œ™ ¤ ňC._1ˇňČžź~űyř•^f ó_š,`ţŕ|E–UěG‹ČJýů!“9őɡg)•mxňĹö™’a eXŰD~HüG“î ĘÓYDů°ˆŠWD~8/2Ěee’ó‡0§/ôľO ,Äž§üžr2y9UČéEżN;°ËN䇚˙pÎR*Űđä‹í3%˙Â:ĘůĄć_Ľ˜RF‹‘Ç$ťŠňayĚţCäG”tCGŮÖ2Žw6‘*X?PôĽŃd•$Gr'Nް|R ŘW}D~8/2Ěeĺ’ŇX%=Z D~Tęoy䇵Îśăöýůţľĺ[”gŰ ĚWą"?lűLÉż°Ž…2D~¨ůWi'"?˘ú`1tíEľŕƒČčś|"'ÂVŹă—^{!"@j"?\ćB䇯œLąœˆ_10ßD~xזoQžm30_Ĺˆü°í3%˙Â:ĘůĄć_Ľ˜š˙(`1ň˜dWQ>,Ůˆüˆ’Îbč(ŰZĆqâÎ>ĂɏČ”@ V6ˆŠˆüp]d˜ ‘žr2Ĺr"~ýĆŔT|Ż ňƒ!âS-[—Č5˙á>œĽTśáÉŰgJţ…u,”!ňCÍżJ;ՀüSKgĺĂň˜ý‡Č(é,†Ž˛­u%śEä@ œi ¤`p_ý ‘.QfŚ{Mâto‘ážc`*žWůamŤ‚•˙2מłl‚t‡oQžm30_Ĺˆü°í3%˙Â:ĘůĄć_ĽÔÉéMz0ľtQ>,Ůˆüˆ’Îbč(ۊQWb[D~™"@jç՟ąůáefş×4 N÷ćůî;0Śâűô%?,M§}¸Ę&Hwřĺ1Ëf`žŠ ůaŰgJţ…u,”!ňCÍżJ;ůŐ‹Ąh/Ş­D~Dˇĺ9śbżD~‚D€Ô ĚZˆüp‰23Ýk§{óˆü÷Sń˝ňČk­ &Z3IşĂˇTD~(Űđä‹í3%˙Â:ĘůĄć_Ľ˘“N‘ÁÔŇYDů°ˆŠˆü(ű"ňCĄœˆ_10ß+Ÿü°ŇUál[{ßąś|‹ňXů/‘Š6<ůbűLÉż°Ž…2D~¨ůWi§L~ČŔ$ťLM>,Ůˆüˆ’Îbč(ۊQWb[D~Dą†őE_ÚôLÂXˇľ–uIŽäHnůr„ĺƒZ€Č˛/"?ʉřőSń}zVž2<ą9זoQ+˙%ňCц'_lŸ)ůÖąP†Č5˙*íTňÙ L˛ËÔäĂň˜ý‡Č(é,†Ž˛­u%śEäG[p& BŐQ,•ÜW~D~xÜů”¨Ő_` LĹ÷éC~”X4śÜ’wڅ÷(•˙ůĄhÓ/śĎ”ü ëX(C䇚•vŞůÁJţ'ĆA(Š*ÖťË$ʲtIł˙ů%ĹĐQśŁŽÄśˆüPąUdA‚~‹ôtš@8Q ţVRL,̙ƕ‘n7D~ĺjőSń}züČŚóŮ—]8|ĂSśĘšČež|ą}Śä_XÇB"?ÔüŤ´SG~půYDÁxŢcČťË$ОtIł˙ů%ĹĐQśŁŽÄśˆüPľ5‘Ÿˆö{K âƒú[m@HŐĄáůÉăć ‘7D~ĺjőSń}z‘|=łxęĄjŸ:lëÂáť•5‘Ę6<ůbűLÉż°Ž…2D~¨ůWi§*“úżŇüQDéŸĎ-ÜF>˜DM–.Écö"?˘¤ł:ĘśbԕŘ‘Qlí/čý-B˙|öŮC 'fSíŸURě<ö ˆüđş!ň#(PŤżŔ˜ŠďӏüŕËČě㈂ĂĂOŮ6,ߖ=˙šČež|ą}Śä_XÇB"?ÔüŤ´SőÉŽÂäDÁƒ3y×>ómx K—ä1ű‘QŇY e[1ęJl‹Č(ś8vćsˆ‚záĀú[m@H•Ąinţ÷• ľů!(2‘€ZýĆŔT|Ÿžä—?2q—Ń÷TŔĺöźĎŢ'ňĂďĂYJež|ą}Śä_XÇB"?ÔüŤ´SmČţ7?ü`¤ţů㹏ώËŽó˜ý‡Č(é,†Ž˛­u%śEäG[F˛ž~Gv1R˙üяď@81ŕýMľÔAHa §†qëó›?8ÖB䇠ČD~jőSń}:“wbvńˆ)ň#aĺOLÓI{ˆüřp–Rن'_lŸ)ůÖąP†Č5˙*íT;ňŁ0|?ŠóƒĆžj˙<°XÄĆsŽz‚Ém‰ň˜ý‡Č(é,†Ž˛­u%śEäG[F˛ž~[.‹ƒĆ+0ęýs˙cřţî@¨-x?ăýƒHę‚*Â:8‰>ůČ÷_ƒ!ňƒIňˆü÷Sń}ú’%VÄîc˙iô9CRńŽË˙⹯_ƒqÚ­Ź‰üPśáÉŰgJţ…u,”!ňCÍżJ;Վü`z˙ZÚ˙íXýó_ĚéýÓă NJyĚţCäG”tCGŮVŒşŰ"ň#Š-#YOçż~Ÿš›Ő??öńŻŇ×)„‚÷/ŢĎTű'!R Ô|Čßţâżđç×üZůJĐqŃd,D~ůî;0Śâűô%?řĆŽC˙bŒţ°~ ˘€ů郟ĆÍWţŽË>˙K䇢 OžŘ>Sň/ŹcĄ ‘jţUÚŠväÇŇž/Ł?âôO> ä/ĚáŻ76ű3Y€"“$ˆüˆ’Îbč(ۊQWb[D~Dąe$—Ó˙vnĆý§ň§Ň˙őťpÝu7ťŇ§f“Jú$Gr$,w÷Ý?3úYœţI U?PKĽ’ąţÖŢ{ĐQߊw_ôęĘE“ąůAäG¸ďŔ˜ŠďӛüŘ}ü Ř?ňCűÇAőGÂŮGćv4Ôˇáę šě‡Čež|ą}Śä_XÇB"?ÔüŤ´SmɏÜţo!wôÎeőĎŻ/˘+Ŕ{×4ú‹Ŕ$IĆ"?˘¤ł:ĘśbԕŘ‘QlÉĺôO,Ěá–Ő??ôÁť÷(Ţ˙Ţ_ĂôŒŠßÖ<*„äHŽäÂĺ>űů/áß>ńߑű'ATŁ5€s˜ŕgű!ţꞯ T,żCä‘ őSń}zżöňČĄÂÓÇž{h ł>đÄ7ń“>Š_Ô‰üPľáÉŰgJţ…u,”!ňCÍżJ;Őöľ—ěŢĎ#ť˙ťU韟8:??0‡˘ó„ “$ˆüˆ’Îbč(ۊQWb[D~Dąe$3󵗿™›Ćg"źúⅳň›´ţůÇőße°<đ~ôů/~ÍE~ĐŤ/ľŠʃ•é2?€˙gßÝxdh~ű‚WáĽ./_%ÂqI䇿¸D~c`*žOď OůœÎ×^x‹{gőŃ'žšG†ŸÂUźg­żÖöë\[ĺĺ1a>‘Qc”ËůĄć_Ľj;áiv˙ˇQrźöRţÉG‚<4“Ăď­iĆ+:3~&I2ţů%ĹĐQśŁŽÄśˆüˆbËHf愧|Îçk/ŐčŸ_űú­Řýô~ź˙}ż…ëŽ=!:ř„§ŸýÂwńēĎ,ŤÔ@Hŕý8<;‚?šű3řÔcßËÖ_†KWmĹćÖtdš‘Ô’•‹QćXˆüđř'ň#Ü÷éC~đ Jł…iĚ,ÄČěăƧnMâCŤĘƒˇNĎâGw˙:Úţ['AŽÁŔŞsŃŮś u­Đô|"?@äG 3‹ü`|ÄT~V';Ž˘0šÇřÔ­9ßGmú祼ţŕŮi|ź!‰—u5ŕň–ÎŞOĄ3ĽéżĄn]f˙!ň#J:‹ĄŁl+F]‰můĄbŤ¨ú˛_';vćsƧnMâŁ6ýóŠÝĎâ-żńGŘ´qˇźě¸ňňópÖYëŃŐنd’›Nđ NÇ'Śń쳇đŔCOŸş5çűЈü8AĐŇ5ÇžľpŹ­%Y^Rĺ…?ŚIëKűĹ_öŔÔÔ4ÎDđćšâáďO„hđžY­ęŁÂňAý“@8uAý“@8uQŤţšŃŢކG}řJ}sJ_ňú’Ó—By)–—’caŽľë9ĂŹ:Ś 5†u;$ēŮ0 ňľ¨QAý“@8uAý“@8uqâú'A"@Nœľˆ1ꙎńŁ@}”@ˆęŸŠ ęŸŠ "=Nˆ9 đěŒ3N xq2¨Á ţI œş ţI œş Âă䃐SÔ„SÔG „SÔ? „SÔ? Š"@@ @ œö „@ @ Âi"@@ @ œö „@ @ Âi"@@ @ œö ä$@üt ÉţN:őQAÔ? „SÔ? „S'şLrQ*•Đžž:—nDçŚ^4t4AK$`˙T0”ˇľĘ6łłô?šcťbŰü­qč¸l™zžtŰŽćńěĎöeoĂł­‰ÓËz~‚rˆbSńł˝ł´Â:–¤G‰Ů™ł'=Ź˝dĺpٕĹ,HWŞcyĚAÇ+Çơy)ÎĎbiřćěĹĚîČ "Ą÷—ZűljnE˙Ú5čęY…ćÖ6Ôe2FĺeĄ˜ť¤b̒ľ,ÇDŤ@ą ۔ÚňďĘ 0™JR ąœ´˘şeűš8÷‚‹Ävˆü@#&Ғʅ&‚\¸Œş‘˜.nj~ÔŃŐmÜ,ÎLM-ťžóoǟüńF´Sn/†ˆ¨ëęŞ*mާŽG/älrÜKsUŽKeÝ5ŢaŤŞgęF׹œĆđfŠĆŇ ŇŐ´Ž˝öj ězěńe÷φk^ŠĆ˝Ażęˇně4ľâňJtÓžŹY•b;"ApÓŽy]Ă_FĹ6ŒIdÇ[ŸnߑÚ\ĺŘńčœ „ w\˝ŹXÂĚăƒg$ r˘z٨F°F~\ůť7™ Qnô*×` ň#Ä_XĚövxĚŇr„ľ—3=JĚÎôŔ˜=éaí%+‡ËŽ,fAşRŸňĂs׍o@ŰĹ7}-Ź‘ŰÎ=O,@ä‚1‘–T.´0äÂeÔĺˆü€Ä|t9ˇĚš ›ĐÓˇzYý“üxĎ{ޅh(ˇCDTŽuuU•ś ×S׍Łr6 9*ÇĽ˛n„ď°UŐ3uŁëXNcxłTcéŠęžóoÇŤ^őŠeőĎş ŻEĂ Ż|×5šŻXÎkţßwřŽ<:žëąˇoĄĎ5‰Ó7óŘľE<ĺĆT– ŽITFˇ]ŻC|—í˛Ŕ˜ÜžE1™éš/&wYDeThsßőŞ7&‘*ľšĘąăksLţcGt-­hÖçšßź=ŻŘťÂAH Ŕ,ůœ7|đĺ÷ ÎŮ ŐŮœ'w'‘1ŰŰá1KËÖ^Îô(1;Óc&ňÕ÷ĺoAşŤ?ň*—çs~œwńĽ2„[dî2ʝYŇĄś‚ĺ˜h(ł<9š#&Ғʅ&‚\¸Œş‘˜.'–ٰe+ęcőO>çÇ_|čĎ ĺöŠćÎc]]UĽ­ÂőÔuă腜MBŽ{iŽĘqŠŹĄĆĂ;lUőLÝč:–ÓŢ,ŐXzŃt>đGďĂşukcőĎDç*4žô—\żőŽn"A“¨ŒnťD‚¸}WĽÍW ˛á}ע~m;č‹Jľ U?P9cÇ'<5żá>ą9;Ÿłƒ:;óŕî ňĂá#0f{;ş\`ÍΞ^cHđŃôľ—ĺ腜MBŽ{iŽĘqŠŹĄĆĂ;lUőLÝč:–ÓŢ,ŐXzŃt݂/zŃMĆ((ŕŁ?Ňç\ńľ*‘ N;Á1‰ĘčśK$ˆŰwUÚ|‘ 7m1FŞ"@Ş Îԝuóšž™łł9;¤ó wvxwg‘1ŰŰá1KËÖ^Îô(1;Óc&ňÕŽsŤ~1ŚúŽ$—[-şŕ#ňAŽ˜HK*Z˜rá2ęrD~@b>ş\`ĂşjąŤˇ7R˙|éK^u”=1DDĽ ęŞ*mާŽG/älrÜKsUŽKeÝ5ŢaŤŞgęF׹œĆđfŠĆҋŚ+>~oźń†Hýłnű%#D‚Hc*ËÇ$*ŁŰ.‘ nßUióD‚tݰ™ćŠˆŠ"Ź́K7‚ȏ€rˆbSńł˝ł´aíĺLł3=0f"?\éŠ1×oŘ^öçp.€•ßճʛ`ÍJĄBĺˆü”‰&.Ł.Gä$ćŁË6ŹŻ}[Ɵ—Vퟗ]~)ÔPöÄ•‚ŞŤŞ´U¸žşn˝łIČq/ÍU9.•u#Ôxx‡­ŞžŠ]ÇrÛĽK/šŽüř˝řâ Ëijý3ľn›Ű‘ ň˜Ę2Á1‰ĘčśK$ˆŰwUÚ|… -Ž.ëx—°REXgçŚŢr‚űDîě€ÎƒÜŮÁÝ?ˆüpřŒŮޏYZްörŚG‰Ů™3‘Žô1gş×”}: €•ßÜÚć*h°VĽPĄrD~ĘD“ —Q—#ňóŃĺÖßž:›ĚTĹţšeóf„Łě‰!"*UWUiŤp=uÝ8z!g“ă^šŤr\*ëF¨ńđ[U=S7şŽĺ4†7K5–^4ÝŕăwÓƍĺtľţ™ě^đY"Aœv‚c•Ńm—HˇďŞ´ů A6t–ĺ˝ KXˆŠ:š|'pgÇsÜΎí>čAä‡ĂG`ĚövxĚŇr„ľ—3=JĚÎôŔ˜‰üpĽG‰Y_-ˆ‚şLĆ.( •fî2JŘ%j+XމV2˓“;b"-Š\ha"ȅ˨Ëů‰ůčr ëoß2Ré4˘ łł#D˘ě‰!"*UWUiŤp=uÝ8z!g“ă^šŤr\*ëF¨ńđ[U=S7şŽĺ4†7K5–^4ÝđăˇŁŁ Q •o‰#Heľ9‘ n;ŽýT{=Ő U3žţâěLÎç<¨Ú}ň‘1ŰŰá1KË!Źc"?„é‚ŘN6ůÁ˙_\‚ف`ĺ/4ů䈉´¤rĄ…‰ .Ł.Gä$ćŁË6Źż}Ќó@@cz &“ÉŔ|㯪9ž¸.CtŹ=eEAk)éĆŃ 9›„÷Ň\•ăRY7B‡wتꙺŃu,§1źYŞąô˘éŞż‰DQú§ţęčND‚TŇCˆˆ˛LpL˘2şí âö]•6?…IhסUR8;‘łŁ9OΎě>i€Č‡Ŕ˜ííđ˜Ľĺ`!íĺLł3=0f"?\é1ČolJ ňAŽ˜HK*Z˜rá2ęrD~@b>ş\`ĂúŰW S”=EśY)¨şŞJ[…ëŠëĆŃ 9›„÷Ň\•ăRY7B‡wتꙺ1ĐӄüXěnE$H%=„ˆ(ËÇ$*ŁŰ.‘ nßUióS|$Ąş ¤Vđt0çAěěŔރ›Č¸c“Ĺlo‡Ç,-‡°Ž‰üŚ b[ąäžƒ$˜‚‘2ŃäÂeÔĺˆü€Ä|tšŔ†őˇŻ@Ś:({ŠlłRPuU•ś ×S׍Łr6 9*ÇĽ˛n„ď°UŐ3uc g<ůĄ!üFŸHyݔm#(&QÝv‰qűŽJ›ŸŞ$Ąę ¤đt,çÉŔŮqÝ' ůá𳽳´Â:&ňC˜.ˆm%“á`î2JŘ%j+XމV2˓“;b"-Š\ha"ȅ˨Ëů‰ůčr ëo_ŒšШJ({ŠlŚRPuU•ś ×S׍Łr6 9*ÇĽ˛n„ď°UŐ3uc“g<ů÷ œĂ%‘ p¤ ˛Ź6'Äí›PuR8;”ó$ŕě°î“ˆüpřŒŮޏYZaů!LÄv*’ŐťČcî2JŘ%j+XމV2˓“;b"-Š\ha"ȅ˨Ëů‰ůčr ëo_ŒšШJ({ŠlŚRPuU•ś ×S׍Łr6 9*ÇĽ˛n„ď°UŐ3uc“§-ů§­-"A Đ!¤ mN$ˆżÍU 5‘žŘTü…Ĺlo‡Ç,-‡°Ž‰üŚ b#ňŁâ)Ř –c˘U Ěňä䎘HK*Z˜rá2ęrD~@b>ş\`ĂúŰW cn4Şʞ"›ŠT]UĽ­ÂőÔuă腜MBŽ{iŽĘqŠŹĄĆĂ;lUőLݘÇ$‘~MÇuÓ‘ p¤ ˛Ź6'Äßf„Ş€Z€š;˝łƒşO ňĂá#0f{;ŮRѭ言ȏ`ĺč)Cvç0I$éD‚,ŤÍ‰!ÔD€ÔÎÎîě˜î“ˆüpřŒŮޏYZaů!LÄvŞ“Ë#B˜ťŒR1fI‡Ú –c˘U Ěňä䎘HK*Z˜rá2ęrD~@b>ş\`ĂúŰW cn4Şʞ"›ŠT]UĽ­ÂőÔuă腜MBŽ{iŽä¸”‘Áşj\ŇežÂôÔ|Ć<&‰ü¨ âőM$ˆąÄˆ9ĺAH- čîÎ"?>cśˇĂc––CXÇD~Óą­ ň#îs—Q*Ć,éP[ÁrL´ ”YžœÜiIĺB A.\F]ŽČHĚG— lXű dĚ̀FUŻ3"?ä:ޜă^šë:‡şGc„–ˆEó%Ö +Ÿ› QՓي"?BĚ âőM$ˆąÄˆ9ĽAHŕěˆîN"?>cśˇĂc––CXǒô’ša\,ŰĚłĘśł1ůáJ'ň#DΟ_N´¤rĄ…‰ .Ł.Gä$ćŁË6Źż}2ćf@ŁÖ•‚Ş—@Ľ­ÂőÔuă腜MBŽ{iŽ}^uŽśđĹj÷ÚKبŽVĆ ˛ÇÂD~D-ŻŇ œĂ‘ p¤ ˛Ź6?CIBőAH ŕě€îÎ"?>cśˇĂc––CXǂt‹äˆ2ňĂIŠůáŮ> ä‡#] Ě]FŠł¤CmË1Ń*PfyrrGL¤%• -Lšpu9"? 1].°aýí+17ľ†¨TݍJ[…ëŠëĆŃ 9›„÷Ň\^O>ÂÁ[bbÂ_f5âĂK~ČË&÷Š::Ĺk/ˆüˇä:|ˆńú&D‚XbD‚œ’ ¤ ň#Ř_XĚövxĚŇrëؓ^ž ‹ł3•ˇm"ÄSxë5 ˝ě?D~¸ăW#?YjPŃ!ň#P&š\¸ŒLÎ3UŇťnXĽ{JĆä2öVˆL$9ń1(n &[.°aýí+17ľ†¨TݍJ[…ëŠëĆŃ 9›„÷Ň\fö'‘Žl$FŘČ0&÷äW4ňCÝg̏ȨÜWä*ݔHJ:‘ Ëjs"AË 5‚ťsƒČ‡Ŕ˜ííđ˜ĽĺÖą€ü€8ćRŮ3ś5Ç6äulÝ,‹ę"Ź˝$ĺ ň#ůáČWA¨8‘2ŃäÂe,9űf¨$_ąĆJ˛(Oɘ؛k+D&’œ‚ŒŤŸČd„rňƈ.ذţöȘ›ZCT ŞîFĽ­ÂőÔuă腜MXt=ËŻ°?ĚőťůQ×^ÜŁ=D>ĺ#FäąĆ<đˆüˆ`ŽH§ow=T| "A,ąĺ „Ş#BŐáîÔ ňĂá#0f{;$fĎ’ŤüF˙čŮâňƒ!źîYٗ&Š™?­Ňîô°ö”Ă‘îí呥 ň#P&šœ‚ŒqÓ,W*ń› ’}Ź%´„ÄVÉ6ĄišÄ§§6Bd"É)ȸú‰LF('oŒčr ëo_Œš)‘‰" •‚Ş[ViŤp=uÝ8z!g]Ďň+#?Ürţ}žT,>h…B*`Î4ÍaŸH$JĽő%ű§\7ä”őî{Ë ŒČH0O˛0#Řmeüćk•z1ÓM9SÇź–ĐĚ )—Ž‘]–ąŽçŹË0ÍaWjÇž,'9Ęhü×Ę×nßLcy‘ˇoĄăډ9ęAT?n3=ŹnL; , &Q5ó KZŸn;âúՏJ›ťíšéşmWű•í`™mî;vź1‰ěxë3f›Ť;ž6÷փ)ă>vD}ˆPmR 0ÇŚą-š94ś‰üpoÄě‚Á‚ę˜ąĘ6żQĽ{bf˘˜ËĂoY9§/§ŹŤ đÖk@{ Ęá҇y˛tűHWŞăӓü`¨Ň/‘2ŃäBüŮu,ÇožŽžüb4Ô×ű Ů%Ü÷ŕ#H&“>NŹÜÝ7JžÚ`â’űöTäd\ýD&#”“7FtšŔ†őˇŻ@ĆܔČD‘‹…JAŐ-Ť´U¸žşn˝ł ‹Žgů #?̑Ľňb’üŞ› 3Ó(=ŒÄč0cĂČLŽaqřƒžß.ßHTźŤśŐń Ӹqkmmmv˙U!AˆüÖ‹ŚŤhžH"A jsˇ]3Hq=˜2A$Ąú ¤† ňîŘd1ŰŰaä‡ŰG>›ŐŸĽH§%uŹUF{8Ó1Űś––ŔŠ%ó¤ĺ(œĺ°bć'NýÂ0UWgţ¤;ë˘TţEk/O9ÄuŹůb–Ś+ŐńiL~8Ű+.ˆü”‰&âĎC~?üÎ+Žr~>—Ă+ošŻyĹË\úm­řޏď@:1*‡†ĎVĺFÉSL\rߞŠœ‚ŒŤŸČd„rňƈ.ذ` 2ćŚüčW–‹…JAŐ-Ť´U¸žşn˝ł ‹Ž'÷ë'?ćçćPBbd™Š äš[1Ň܃łq+2Ů9—……t&ÚëP L,žhŔÓŁłřÝŤ&ŃŃŃ!íá‘ÁzŃtC,ËndˆY!$ČŞĆ&\żj­d/A]Mó>jb¸wô†Źó‘ r;Ë$AŐ 5‘pÇ&‹ŮގF~,NNá/Ďţ9î\_,œdCƒÇŽěĆÜłn0;5‡ š/ĹśžNt4&LhĆRÔÉ >ŮbQ/7*Ɨ"ß/i8<5Ÿ=„tKł~˛˘×^\éD~„Čů3ăËÉ1‘–T.´0ää2Ž/ţżÚ˘7áÚŐý8tř˜oTGĄXŔ9[7ű|œłm3žýý[ÁšOŤ]¸e>ZdýÚ58r츑 %ŹžižD4Í?zKVXe9W?‘Éĺä].°aÁdĚ̀^˘* •‚Ş[ViŤp=uÝ8z!g]OîםČűËřř8şżţy49č–,”ĐţĚRŰťđÄLŲnk*şvTüwvf~ yÝg]&…–Ć4lÁ‡Çp]S™LĆěťLüę ‘ÁzŃt= "ˇłHŽtŽę] :š<˙śÁý\4É B$ČJ 5‘pÇ&‹ŮގF~p :ƒ]ŸĹ×=]bfŔ$"ě“$uě~텿ËܖhEC˛Ç'ł›qŸď™Ă/s”ŤXĘ Uכ×oĐŠDřăDKä‚cvn/“üp¨D‘2Ńää2^ňƒî¸đüsđ+ox-:;;°ďŮçńwý7ÔŐ×ŰR|@Ďó‚§1‡?ţ7—Íâƒďśé„ÉřÄ$žú˙ÁŽ'žÖI’´­WňŽ4‘–ů“Är 2Ž~"“ĘÉ#ş\`Â)Ș›˝DU.*UˇŹŇVázęşqôBÎ&,şž×ŻorŕňţĚĚ,&'Ç1:8ˆ :ůq|ą`“uú€Ţ¤I&ô+ńžú¤őF(ęuRqŐĹě|‹Kćź"…ĹRş˙Ćú4vŽŘ´d "Ä&>LĺGŠU‡ˆćtYg9zjşńę‘HČíŹ$ Â×aʸíř~ÜŽ ô:LÄc'. B¨:č+05‘Ą1ŰŰá1{ýó!r_łGbYüúšGą¤_Ě1˜'ţ°W\Çnňƒ/Éd ŁÓƒúÓ§ ýéĂüR sŽ…ď/äĚe1o.Ů|“3ăÓőúkĎőĽyQFäGpĚÎíj˝H ň#P&šœ\ĆK~ärKřľ˙óZüŢ;~Ă&8śľozý+t"cœů,–ŠúęZŰüO+ňúš hÚÓuŢôúWäG—nó=żývüú›_gř˛‹ÄŃ|ž=&ŽĐS¸ŒŤŸČd„rňƈ.ذ` 2ćf@/Q•‹…JAŐ-Ť´U¸žşn˝ł ‹Ž'÷ëNäŁ>î˝÷<ňČ#8v쨑6[(a:o.łˇ|o]J'AĚĽ=SýËĆBÉýĽ>„czžXžšŇo˝ŻďÄ‘:QÜHżđá4+ü×\śÂżđQÖqžˇ|žv×+žë oćąëˇăö-´ƒSýë0፲˝őřcôGYjmî÷M_‡)‹ bň;„ރZŔs˛uv_ş ťÓ3–ü°/x*ţ,ňĂjęRu¸¸kľ!”tbÂňap%÷ PłNą6­îĹ}náďú¸px-Őޘ2—Ś4žyçżăŢýw ąŻĚS'Ňö’•Cr$ňŁěËĺĂÚŐ$1E‘2Ńää2^ňƒŁ˜/ŕĘË/ńŮyéÍ7âÜsśrŸżď~ÇېNĽĚ/P”žÍÓŢőΡ2œ,ŮqÎvźěE7úě]uůĽşŻ˘ď8ń>w‰#tÇ.ăę'2Ąœź1˘Ë6,˜‚ŒšĐKTäԃQ)¨ş •ś ×S׍Łr6aŃőä~ý‰…BYƒhŹ`[K;ZëŒes“{ÔÔĎGçń“syt*‹jŁ>ăŒ\_gîKňOŕůʧŚťczΧD‚Híœf$'?n?ž_P?D‚8}‡Ú!䤃^ŠœžłÓřŇםĐȏŠ?'ůa$/NčWJí@˛żľéQüٞ.4twťeŹŃ"p”ŰéÁxuŚçœłŃ<9R) m •š Vw>:ÚË10¸OŘD~ĆěÜŽ"ůál_%ů(MN.#"?P!učđalŰşŐ%Ď Č÷˝űŕCK‰„#Ýą]^_sĹeĆb|šâš¸ă0ł&'v•­äţŞ„ýÇĄ[/\ĆŐOd2B9ycD— lX0s3 —¨Č¨+Ž`BĽ­ÂőÔuă腜MXt=š_ąN"áŸOăČbůň{. ÉúS•W`^ĐՄRy˜vB¨.šęÓƃ†\ą„şt™T2PžČ`=5ݘuh@Ť8ą7éuŠœzŻĂŔS8¸‡ŰŽ•_{Ź~TÚÜ“™NŻĂˆëÁ”YÖŤ~)hH­Ŕ?/D~xśĂc6N>ňƒ˙-ĺ€ňä†}mú Q۲YŘ9ȁŕ˜é^ds%_2.›ë“VńŠíĺ-‡°Ž7aaéJu|’LńWÜ–ËÂä˜h(ł<9š#&Ғʅ&‚œ\FN~Ŕ˜7çöŸÜé’/ÍžœL$]äG¸l*aöKţJŒˇÝńӊ-˙c8TžFIŒîD"?"ʨ+E1ĄŇVázęşqôBÎ&,şžÜŻ\§ŤŤ MÍ­úŠ6iżn’ÓɏźžÉ—Ľ’[wQw° Ëń%WZnيaL~ڐ’ôڋşžšîňÚĐyýÉ5‹u ŕ–h$ˆßˇź>đş)ŰFPL˘2şí†ĎůqŰń~y ˛źc'´•eU ľ€§“0oş ŁşÓů!(‡mËuö°ń˛Ÿ67i^ 9olqĚĺ šRůŚ,ěŞat&‡c“yóË.[‘ŽŮšMäG 9š#&Ғʅ&‚œ\&ˆüŕ{üóľ÷=đĆĆFíwü“Éĺ˙%l"¤dŘž÷ţ†ŻĘąktt—ŽÝ˙}p'ůQŽIwÔŔ˘hŠ´U¸žşn˝ł ‹Ž'÷ŹĂIÁŢpŽžęj ŹŰ€Š†&lnĘŻÁđeCŁű˜§f˛Ř­˙ţńĺůůNˆüÖSӍY‡R?D‚@ŕ[hçT"Aŕ՗ƒü¸íŘąď˛]@$H€%„PmĐ+05€łs8|g'&ňғ ůÁˇľ†ž˛żJ >“ŔëW=ŻM4ŁžĽľlˇŹĽiáur˘iŽOĄ.ĽĄr˛beťD~ĆěÜŽů÷şŘćś/“ńŻe–''wÄDZRšĐÂD —ąäř§6™žđ×Xřgi­!° MÍƧĽƒF{đ×T–˛9ŠyĂ˙Tn*•F]]ĆőjŒÜfĄhú(Ÿ-Œ9Ć'MŐÉMˇÁíŘǓć/šťFçÝea2B9ycD— lXű dĚÍŔF —cîkbőH *mާŽG/äl¢ëÉýŞU˙˛Joozzşń‹šYÔ;‚ŚŮ)4/̢-ť€Ź–Â3—oŔÍsGqeGƒK÷(NŸ>'L&'ƐÍVž4!ťńáŽ8Q—úúzttvë7mő.™Őýřó?ůňylŮźÉNżń†`÷ž}xôɧ+DŠó‚ÔáCŕ١ËÂd„rňƈ.ذţöȘ›JEŽšwŹUžZRv&h-%Ý8z!g]OîW­œş&9R2FCuwwŁŤŤ|¤8„şş^Ź“#S˜ÓI‘ă:9ňŒžě;:…ÁĂsˆ –_˛“ĆoˇJ÷uš-D~čŠé‡q;)‘ śÝX7ħ8 rëQ“ü¨Ô'ˆqŘ%dĺƒ€96œ9D~@ł´LP—ÖÉrl[UÄyƒ‡°7ׄ¤ńţ??™$|ĺ°ČëÇVf“ŚÝń3& .ňĂů#뉛¨.‰üpo{ĘĽŻˆb‹ćś/“ńŻe–''wÄDZRšĐÂD —qĘń§ĚżňŚ×ůň7Ź_Ť÷)˙Oń1Ą“ާ˝yź˜™ĹR™ŠÓɎ֖V¤ÓKKK:ŽÎÎ.4ˇ´šý­[Ť Ÿż_űĽ7â‘Ç? $+%w^ÉůQŽšwŹUžZRv&h-%Ý8z!g]OîW­,Ýʨć!bm[ýosrąŻo•Ă/ĂúcÇđÍÁYŒĺ[\e`Ůiۉ–ĘéĘČ,–››"ŽĘţ#ƒČ@uÝ0ÓD‚Ŕă{Ľ vě‚ăĂ$? ę Ëkó˜$Ąú ¤V`đܸiŽmxś7–ĆúL&?˜ŔŽçĆźžHd Âonٍ÷íęG˛{œ#?P~UĹI~đí  ë+0{ęËŻŔ8ÚŤüyÍJ|Žm D~ůCN´¤rĄ…‰ § côY3“Ď׹qíÚŰÚ<2%!ů159Ą“ÓF_˛.„Ž=ŽC‡ŻÁˆĐĐЈőë×a͚;mBˇS(ŃŢŃé’Méd‰yńR9ŰŰ۰Q'c9†DyVëćČˆrĚ˝`­ đԒ˛3Ak)éĆŃ 9›°čzrżáAx_{1Ó Dŕ"?*éZYŢÜ毎˝fÍĂřüóP˛ćŇçYĆW٘]V×=ŃÂáČŘÖ>_ŇoĚUâ,Wčh"?uÔuƒ­Ú­@$ˆŁBbÜŸ,ŽŘ{ˇęÄÇmGV˛ˆ ¨OÄkó$Ąú ¤`î‹"? ŒYZŸ-+Ý|őĀ~1§s`Ɍžă˙l^{sˇô<Ďľ ­ß(Ů$EÉYA̐ƒ&•LÂuň…3>zíĹH;ť|Xťqɏ8żĚm_&ă_Ę,ON´¤ráľş\¸ŒWŽ˙ŕ;~ĂĂĂXľj•ž°°ˆŚ&÷|ósł˜››A˘|U´°°€Gy‹Ů,˛Ů—07ť€y]—Łąą­Í XjĚëäČ^X˜çží}^śŁG:ŽĆĘq0qtŢ]&#”“7FtšŔ†őˇŻ@ĆÜ lÔp9ćŢ °VxjIٙ ľ”tă腜MXt=š_ľ °n.˜űbAJ|¸ó,ňŁd“&üËJŻża›ÎtîÄÛq,׎‚ţ;Ź5tŠý–ôßŢ"ÂŔKКÉcG×Ţpq=6nŘHxh‚wÖ˘ĚRĽM÷DżÇár;ŠóŽźO$âߟ$¤3íVřŕ‹ń Âa×_Ÿ‘ X^› rŇAH ŕźČ!ň˜Ľĺđْ§óIPľT=¨|˛Ď‰×l9†ŸÜ7 Vß`ÇR)ˆší|*vQ`}†Ůĺ)ŸĹ­řœç<ĎÉ[ł ]ŠŽ‰üpokń.^öe2ţU Ěňä䎘HK*Z˜rá2%VrÉq2c~>‡}üřŐ_~#Î=gŠĹ’üČĺ–0==ëk.ăcăxôą]XĘĺ1:2…çÂÄÔ ŠĽ’)“č, H§čhmĂÖÍĐÓӁűx]x!şşş ™ééiýÉqŇúb“ź üsťO?˝_úęc~qŃ5*+xî+ć­yŰĘÉ#ş\`ĂúŰW cn4ŞŠsď0[ńáŠ%e›‚ÖRҍŁr6‰YAË%?,Xs~8!">*űNňŁr“ĆłşşşńK/ť g=ňŽýĹmčYœĂ}é-xkÓoúĘŕř™´}źaÓQěčKčdJÚŐßř+/ýýkąiÓFű QJŁ?ˆüÔQ×U‘ ţzđř>ľI7n=rČýQ)#‘ § B¨:ˆŠěc^slÂ:gşą&ňĂi׸‘fÖiÎăď.ŽAkԟ0'ýŻÂđ/Mü憇đoÇn2>‹kt­SoJ…ŕ'TÖW`Jł“fŸ ecŁ OœÖś .”ę˜Č÷vňĂc_A€)‰/'wÄDZRšĐÂD — ’kĐɎç â#ű~ůŻÂe—_‰ö6÷¨ŒŮ™)ăzƒ_đđŃ!ť߅…Ĺ,ö=sĎě?€Öövtöö:^›1 yă‹w?řśmވóÎ݂'Ÿz W\q9šĘ#Ař+5]]îŻĚĚÎÍâá‡ÄWżńĚÎ/Ą˝łňÄZé&“´] œź1˘Ë6Źż}2ćf`نË1÷S°žZRś)h-%Ý8z!g“˜T-ňĂŇó~Ƃ—ń’^;\ŹĽĽ—\|ŚŔ @ÚJâ×ŐXÂ}Š™Ň8_uő&lŰśŐáťrSyŇS"?uÔu#‚H=x|Ÿ˛$ˆ?>b˝öâ-#‘ § B¨:NěˇĚÎ ůaĚŇrřl¤—Ęg‰Œ~3ŐÔ'$?,\śvk0¨“…Ŕ˜óúM×ÚŚuđţ08q`4‹ÝÇąže=rú“cťî“Ôą,f"?¤Ç¨ĎŽzŸˆ –Ă‚äü™ńĺ䎘HK*Z˜rá2R9GŁttu˘ ďéżţ­-Í.]>Ši>_0Fđ‹‡~ŮĽ<ž|ú98rŤ×ŹAKkŤüŕHŚŇhmmC˙Ŕě?tîÚŤ“ O<ůdŮ^ů\ŢřŞŒ-ÍÍřÂWž‰%Ăt‘%&ŒÎťËÂd„rňƈ.ذţöȘ›.ÇÜ;,ÔV€żPxjIٔ ľ”tă腜MÂ+HœË˘ëČu+ ᯕTîœ4{^¸ÖšăŚ-H"Ć/‡Ď‚^”śśv—?/ů![ťËiýčb–j,˝hş'ňř 8Y<˝PqçőJyßďSsŸW2Ö5…[>ŔŽĂ?óŘ]ˇŔw}áő-°#¸.ň]ż|űOw^;nßB;Ţëaýx믛˛mמI~ÜŞ/ň2şíBx˝âťl—ĆA›{};eThsßąăId§JmŽrěŞ"@j"? =i,›üpĆěşPƒ_$˝{ŰN,NMKcf|XüB›Z6ŰŻO'P—u†M훑Y*z%'ůářÄŽ}’fŒČŤ]>ŹÝęQ/dYX ’ógƗ“;b"-Š\ha"ȅ˨Ë1¤Ňu¸ćšŤíáě—ĎVóĺNx,ę$äĄCÇqlh ˝ýýF:‡9B„•×0R•mp›˝ýŤqdxĎ8ŒbĄˆcƒƒśÝlvŃĺ“îóÚŤŽ´'V4JČÄĺöî˛0Ąœź1˘Ë6Źż}2ćf`نË1÷N@Ӌ"ÂSKĘŚ­Ľ¤G/äl^Aâ\•ăRYׯgšdkd–SŢťć›|ÂăŚ| úƒˆçR˝ƒKş|L/áülść)›híÍ'ň#XGM7f˙tŞ bűöŸöN]äLJŻž¸Ë"*ŁŰ.‘ nßUis"AN8č˜ZŔwbpwWşä$@ä‡ŕ+0vĚ儥iý&'­ßĆŤ;¸Śý9<źÔ‚¤cNŤ ٙ\Ň}ŹyZë“čjNgCÓyd îwŚzLçw_ˆFB}{§U\‡Ýʡ&Œt­’îö Ĺ:&ňĂ˝˝<ňC&ZĘ,ON´¤rĄ…‰ .ă•ž(–ô››’Nę˙řH‹/8Ď­Ż7Z1—ł'>=tŕł9<ýěô”'M­ÜóT:süqÜĄ§wv=š›7mŔĐńAŹ[łĆČËçsđ~V÷â‹/ŔÝ÷?h;ŕý>é"gŹĄš‚ţg™üI,L&ś\`ĂúŰW cn6j¸sď°P[% §–”ZKI7Ž Î Ż q.‹Ž#× ×ŤźţbÉ3Wžč3šÖşłł_÷r ŕŰG6C›—”Ÿ˙N—*ŸŁšĚbËş’Mt:ËáÝ‚ȏ@5ݸ=Óűj@ŻĂęÁă[őՈ-í­ř­sĎ6IHgŇt‰ŠLxť˜ĆÎŃa\ŐŰ/×јË.Ű5>Œ%cBco}şëF\Ÿ˝ƒXÇĄú ¤Fp^ü˜ŰD~řĘ᳐nÇěĚTÇ[śîĂý÷o@‚Ď  ivr óŘÔ´ ÍéfŁ`Ʉ†Ž–tš–4})x­14eąľu žŸ?‚tSł‘fŘ-Á>IÚĺd’š@”ę˜Č÷6‘î¤ĐÂD —Q‘+ xéÍ7`Ăş5XŐۃîî.Ěč$Ł|"SăÂCď3KKK˜›ŸÇđđ8őžä^Ďá?.W ĺ‹ M-Í8~|m-ĆŤ5Ć(Vž45]™(yÓĆőřâ|ŁŁăÁCGńŁŰ~ŞßŸĽüą€ś ”“7FtšŔ†őˇŻ@ĆÜ lÔp9ćŢaĄśKO-)´–’n=œ^Aâ\]GŽŤ^űΑćyś˘+ú4Žľćb—^ząą˝ćńÇńóÝá;Cça‘5¸xTŒÎäŃ#I˝ßiŇŃÎ}"?uÔtăőLKŐ??@$ˆ <žUnˆŸ›šÁGă/>_H€š ¤;ýęsűpíŞ~Ô%S𒠕đljž˜ä YQRŸ‘ ˆŐćĄÇĄę W`jçŏšM䇯>[邘”TœĂjƒĐԘƯ­Ý‰ź~Łe•Ď ҐM”çţ0 w4ŚôźYö‚ţd{!Wä{­kĐRŹCą/'ÉbÖě"?Ԏ›H}ÂSŽč`˘U Ěňä䎘HK*Z˜rá2*r…|/¸ę2źţŐ/Ç%]€5ŤQ_W‡şL˝KŽ5FÓŻěř2=3m¤EŚž2ZůAó”ČBŚŽ7㠙׉MË~ŠäîĂu™:ŁLk׏Ƽ_ˆ7žö¸ţÚ+ô˛çŕ5-mť@9ycD— lXű dĚÍŔF —cîj+°d‘@ä‡ZTƒüpęˆ^ń’Ž\p^}őtƒĺfÝşdh:g|ÝI„@2„ȏ@5Ý*ôLĎľF%^‡ą|űť•׎ۡÓÎm:1˙‘GŸ@Š M%„nw^Ppďđ –řÄţΘ /#|m.şž i—˛]Q}ˇš˙x;s^‡!TD€Ô‚âěŒD~@`Wü°ˇÓuB¤8?nÚ4ĆĽ1cî^˜%eßŃ{ĄŸáŸÖlLŢxăsůŔ‹ÎŸŰ{.rúÓmăsşÉ!š  ňjÇ ‘ÁŽ˜‚L4špU9NöŻęńĽ74¸Ÿó×cú“$ždłćDĽ Ky$Éň î@“úŤąţËĚ¢ńšÜźNÄXö˝Ÿýlhh„}˝Ćȧ?iŰy’X˜LlšŔ†őˇŻ@ĆÜ lÔp9ćŢaĄśK D~¨U@ľÉ'dŻ˘xÉKŹŁŁőúq27âzĺĹ?¤`ŒŃ|ŮyD~ę¨éVŁgVL xŻąœžýÝkĺ“ 4'H"AV ˆŠœĂŮ ‰ü€Ŕn ňƒŻ'Ŕćëw]î'ˇÓűƒč €ľýým÷cizKłłŘŢv6ꓕłŢs a1_’ţp >Y‡]: 2g>ír·ŕ#SŹc"?ÜŰ ä‡żšŔDŤ@™ĺÉÉ1‘–T.´0äÂeÔĺ˜ßŻDÉxş\ĄaĎőHT†š:ľBíYĂD9 b’(űšë‹k–¤%ˇLł0B9ycD— l؀z†§Ů5\ŽšwšŢľŕUD~¨U@-É Ţš9ü䇃ˆLŚĐÓlÚdŮéŠ21ĎěŃYA“­: ý¸b–j,˝hşž^^Óă7ŕ8dńô"!ô†Ř”a"AˆĂލ>‰żŞ "@jg‡pv>"? °Ť@~☚DCˇď3¸ßŢӇĽáCaű°-}-ů:Źj° ÚR—Dc]Ňžč›-@ }M=čNś"ďřäŚőЙÁݎö{ŐD~8ścô g9œą)ƒ‰V2˓“;b"-Š\ha"ȅ˨Ë1ë°ÁÜܜ/w~~ÁľŸĐ’öćŚ&#­ŠąŢ5ZƒIý1˙^šoľęś8éÁGœXöžOtzËÂÁËŹyű‰ÄŸ•ÄÂdbË6Źż}2ćf`نË1÷N@Óť6š,D~¨UŔ‰ ?ÂôÜäŒWĐÚĘi…Ęo˘ćé‡S‹Ě÷zš nZTš¤p—7š^4]O/Żéńp˛Zčɔˆń–Ń{ÍĺôíďnD‚ŔaWTŸD‚D‚ÔD€ÔD~řË᳐î=yČbNŐóŤ*xń˝šqhĎA°ÜDx÷y{pnĎśA~ŃÖӚś‡đN/‘+Ş]˜YAžÓu6Jú•1)\Š’Î1…×1‘îíZ‘–×*43žœÜiIĺB A.\F]Ž"•JŚńÓ;ďƏ?ŽŁG`zj ůBÁ˜čԉ„ń™Zs„2ĎŃŃÖh ‰ˇ]1ą/ß^9‰ëŽXeܐľ´´ŘöI÷9‚—…—‰——‘—őŽ;ď2ž\łV “‰-ذţöȘ›.ÇÜ;MďÚPh˛*BĐZJžâčąŕœđ ç.ŁÂN4ůĄi•óąő[)ze… [zÍI‡Y)_ÉđŒ™\„ÝßĂ ýb–j,˝hşž^SOM7ŕ8dľĐ ąF$ˆŻŒŢk/§oˇ;É$so[$H–Hœj$Ąú ŻŔÔÎÎFävĂČsŮBŚUż¨Ş|ÝÁBĂş-řĚĄëđŤEóśK}ů3ÉË0Đ4†Ń%óS™MidRf EÝöÄźęč Ňúßů=çŕąń}¨km‡yѦُŽÜuĚĚ+HQÝ b&ňáä‡#_ Ěľ ͌/'wÄDZRšĐÂD —Q—sŽ:™Lbjný×OĄŁ˝M hjlÄë_űôőőÚZœ”0ćç€9'',VŻęÁŃá ¤Ňih_ž=G_(ň8{ËzÔ×ŐŁŽÎœt•włDÂM€LMMâó_ř‚1d~~ăÓÓ(zY›ýYI,L&ś\`ĂúŰW cn6j¸sď4˝kƒ…ÚŞ&=MÉW=œ^AâÜeT؉&?TôŹŻÂpäŹţ=!Wž„Ëk>d6— R&?˘]ţ3K5"˜ÓmdĺčŠé‡ŹzÁ&YůňĆ˙e ú:LĽ~Ü1šęÁă[^Ÿ;œá¨Ö×aüuc’ żĐIkVőŁŢř:L9&8Oůamî­Ow݈ëST?*mîśkڟ†_‡!T4¤p^ůÝ0ňÁ1kŚ [Ń ˙(d&ƒƒ=×㎽)ä§F]yÓů> eˇ˘ŻyI­ˆ”nŤł)iU ĆřÄlą(v†žĆôŐu˘°´XŠ‹’y˛´ęJ\ÇD~¸ˇŁ“ńZ, •UCŽI 0‘–T.´0äÂeÔĺÜ䇽?557LÎᚃÇńŔĂOŕŃGwiň‹–T:Ľ_ÄiƲuë6´47˘­š %{ôU%*抹’mŚ—řčŢntwuęDKżm7•JűžR?˛ó1üâĄ]ء˙(ǧőC1m’.9qc0o‚¸ZbČ6Źż}2ćf`نË1÷N@Óť6˜‚­ęAĐӔĚÇŃcÁ9á$Î Ż°şęu[+ňËV˝/[ŻžU^kăWő•×` ,.ÁdŔhäGŽšn\=¸~ƒ5Ozĺw÷)AtMĄšĎS4Äg§Ú#AüuS!Ah$ˆĘąăId§J#AU ľ€Ő$—ČAz”˜é24ë7A_™|9Ć÷îÖËcł-°4žŸšÂđĂ'\hxÝ­i$ůPyÝ|>Ď0>úŽŔˇwm˛ćE]É}ƒXrŕ› D‘ęä‡ű&7 ,(•UCŽI 0‘–T.´0äÂeÔĺä‡|FsK3Ú;:Đݡ ÷<řďio:•1ú!_śnÝŞ'M8ďě(ć—ĚŻ*ŮƙkŤr<•ÓK|."nşţJ¤3)ô ŘvÓ)÷1^†{x=˝}hÓËÖÜÜb|>×› \OŞź1˘Ë6Źż}2ćf`نË1÷N@Óť6˜‚­ęAĐӔĚÇŃcÁ9á$Î Ż°şęu{˘ČŢ÷Rĺ Ž“{çÍ‹Gů¨ŁŚWO˘ßb"Aźet]ŸČęÉěœDZ7$H¤6'Äé{9mN¨>ˆŠˆü€Ŕî2Čщ+‘[šrżg\ÎÖ´’›.ÄWŸ;‹‡Ÿ5ŇĚ^†ĽRe˜űdë8F:ö`OýăxŚáiü<˙(Žfa1ąf‹łŘ—ݍűfďÄOfž‡ŰŚż…{gďŔhaŘöœŇ/đÎď9K3S•8KÔ1‘îíeŮx`Ž•g3˘“`"-Š\ha"ȅ˨Ë“• ó¸â#:ÖŽY‡Ąáa—D"™4ćÝŕ}•/7Ţx3ęqŃšgéddEc$s-ćŤqĚvĚm źâĹףĄžŰĎŢaźZcôÝ6÷áÄŕĐÖ­]kŒqKČ''oŒčr ëo_ŒšبárĚ˝ŘŹŽ Ś`K*‚ÖR2Gç„W87źÂ"čŞ×j5ČçH k[”ĆÁšćú˝pÍÓĺy fxjÉ @\vJĽNjUD„łüŃu–٧Śp˛Zč)Bôűol â-Łô:夓 auC$H`O4 B¨:h€Čě.ƒüĽóuCiŮóTÉŞ‹´ţt÷žÔKqޏc][7Ćňl‰ťľaŒŐgОGJż@ËĎâ1ü@ĆŤxí…NôćVŁią #3C\:‚éŇ$ü8†ýš=¸¸óŘĄ]d°ťŠó˝^šE2ÓPŠ._Ý3ČNĆD~8ˇ#Ä ĚľňlF”cRL¤%• -Lšpu9?ůa˝űď”á-Ćé‹\.‹7źć•xĹKnĆSťŸÂęţ~—ľt:Ľ“&ŮÖڊŽ!~ţó;qĺ…ŰńÔ30ż˜3ć0^cąćÍaćÍXQż8ëîlĹ Ż˝ ÍMÍ8{ű9Ć(§m/&&ĆńÁź?řńířúˇ€t&㸴¨Ä`ż6ă;śä].°aýí+175\ŽšwšŢľÁlIĺ"CĐӔ ÇŃcÁ9á$Î Ż°şęľZ ň#*2™4śô$°sŞĹá#@rĆD¨étÚvjý*ň>.šdUPRK5"=QY×ÓËcęŠé‡ŹÚz1zŠŃPŹ“Í bꏘ9A˜JÝćq^ű)ˇšˇ>Ýu#ŽOQý¨´šŰŽ™žňç!T4¤& ňĂmˇşä‡}âž„fŒţđŸ,іuëńŸŁŻĹžĄłěźgľ<™šGs˛ÁŘ/ąö-ÂQ5˜LO`_ÓSx´űAŮpK9dş3HľčO•3zˇIjĆ:ݞFÝĆ&ěéy ÇqÄŽŒłťˇ‹YÝvš$ĺQ Ź|6“ĹLäˆü/Lšpu9őĺ9zňšţô}ďÁ+_ú"ă˘d`őFFF\Ň|¤†Ip˜Ł6V ŕŻxşťťpŅçŕ’sĎBoGŇÉ$J…Jú“¨zŘXŰߍ›^p)^vóľ:q҆‹/ž]]Ýśsî÷ĎŰČđÖčeŕeyĺ-/ÁŸýŃďëäKŽ\q(̛€jÉ6Źż}2ćf`نË1÷NPł:7˜‚-Š\dzš’á8z,8'ź‚ÄšáAW˝VŤE~ČFzřóĚŁˆO<ÜŰâżźÔ<óĎÍ­W`t咤¤ó„ŘĺCD¸ËUg9zjşÇ!Ťś^ô^ę>”ó š%ôˇŹ6”K:áq_];Žjƒ¸4Ýg‹>ż4Œ"łĐÇDśeĎ.>…ł°Ă(Çćś5x|ęM;ć<#ň?:‘Cä‡s;F̈ř‹_Ölúĺ˜Ôƒš#Ś M.\F].ÚČkƒO>:93…Ÿßu^~Ë-śdss3rzż<~ě˜ńş‹ ĺO×2WC'<šŒ%օ ƒƒƒČĺs."†ăgwýÓÓhnis…Â4l>0oŽŠ\`ĂúŰW cn6j¸sď„4+KĆü;árń@䇪E~řó™pl|˙óđÓĂmȝżÇ=čn÷ZY‹žÎĘޔžüýC:1’.ŕ÷/ĹĹ[ş*ó”}ř‰ć)Ż*=QY×3QĺăU[Ż Ň0C$ˆÔÎJ Am J‚řoÚă´šˇ>A$ˆŤ=mN¨:ˆŠˆü¤G‰šü‡{/Ů13w˛ŁĐę;€¤˙I0+JhÎ4Űi73ÖóĽ%ăÉÔtAœŸFľąťńqœ5żĂ(r{}‹^Žb%Nç f\D~8ˇcÄě(‡2˜pÓ/(ǤÔ1™hrá2ęrńČ M-řŻoü/śžľëÖ­ÇŃcGńä“Oâ÷?„śśVüŢť~ǘżĂ šű˘g˜Ň ŽOö ˜Ÿ›Ă5WďÇy睇5kpřđ!|őżż­+-ŽPĘ]´’ óć¨Č6Źż}2ćf`نË1÷NHł"°dĚż.D~¨Ąšä‡ĘŤ/ăăăřĚCiÜ?؊ĺ`>ŸÂOö7`űŔbeŇc_Íqł θ˘ë,GOM7ŕ8dŐÖŤF‡DŔM{œb‘ ľ"AźőI$Ȳ۟V$Ąę ¤ ňC%fgzPĚĽ؂N‚4ŽŇI .˛s­TŇ<ÄóZłŠc›OxڔČDH-OWŢrŽKeĚ Ćƒ59$źí彨łÚĹކg›ČizD° T$Ǥ˜HK*,M.\F].:ůa^ŢT„ů(„ţ4÷ŁűVářĐ0։‘fdŸ?Œô§?‹_ýĺ7éykP <Ž˙üňaçcťQWW§>˙ßXżögXÝżJ'c† %ӕĎäZ×'šó*™7!T.°aýí+175\ŽšwBš%cţŚ`+ˆüPC5Éż óíOëäⷞЖM~X˜˜ËĄTJH˜?–D~,G/~?š"+•Š D‚Ŕk§ B¨>č+05‘öv”˜é˘˜5͕Ž5tťČŽââ ‹‹(díłĄVŞ /é˙fKYý/C-đ˙ˇwv\ĺŮ~çŢÝŐőś*ś$ËM˛,÷† ƘbccJL )? )$~- Ą…L3Ąc Ř4ÜmŮVąŠŐŹ^V]Z­VŇś{ţ9Sîrćœ3wď•Vťďc_í™sżď;ućμӜȁź÷œ…0Ą›?`×ćh~C)tšBg'2•WŚŢ&ŸŮĆŢnpW~DmZZZq¤§KW­Gç‘>L›9ă&ŒÇÔöéxč‰ĹŘ´i3ÖŹYZłfőjlܰ=ö ŚLmÇŘńăŃ>cvǒĺkŃu´Í-­a5ŐĎŒüvځMŻÂĆOjŐl'⠆a…śf"˝ ,bUĹ;j-~˜Žţ8zô(X݃_mš€Z!´ƒĚłÜS)˛&Zű&ű–ÔxŠZűUżŚ#EöqʙNb•WýŚ;Ń ć8 ŸčžTű‰˛…°ˆ)ßü†xŮ"73Žb&Ý?ŽĄ?Uq’ýYąąy;LvyĐ´)°ü˜Ťö' eqUeëÇ<=ßN•ˇĂÚĂ+@ęŏr:O›ŁůÚ6˘FëTWüHŸ1şë•–ÓOěvm ţ4_!Ć`ƒÓ…z3S(ŤÚ'%JžňíeŞ.ŏhşŠ6Süˆd›měí'~8ž@)*™îrKkŤ'„DűGžńĺâ‹.Ŕľ×^‹mŰśâîÇůç/D{{;Ăž}{ąrĺJœuć™ŢT/ž˙aěŘľ×{śˆ\[ŰÚ*ĎqâsŤ|†(ŁÉ"™a´Ólz|6~R;¨f;_0 +´5éa+/'í Sűľ>đp?Ňvńď{z{ńôúN|wM;"çęk‚Z 晜\ĹEÖÄ*çŏěpĆ+8źüʙo^ âű š+A2űź:W‚šĂ+@ęŏhÜúˆ2-z:>čpp´œ~ĽsZEuĺX ×öźŻɌŁŘ§I÷cčOUœdVl2ŻQöO˛?sßř6ƒsŐţĽĄě ŽĐś W‚ZĂ+@ęŏڼí%žŠŠ;Đyu…ŽFD/ü{”'ŠQx;ćáwčŔFхGăë–1 îgň?#ýcMÄu˝/C3üKëemˇďë€ÓŽf?ę&~DâćGÄţ$’™6i[m€ Ko“ĎÎlcoWťŰ^bŠp1xOnx^ĽäŽR.<żlŰŘ؀ Î÷.­˙ĺŻ~ĺŠ!ű°đü˜>cFˇFsK Zƒ[VŽ;ę˝÷H÷tě܉+WbĘä)¸ĺ–WxWšDšháB bJ–řĄiL•vځMŻÂĆOjŐl'⠆a…śf"˝ ,bŠ—jb 5"ôߘ;Hý­šĂrřÚ÷ԉ?Bäs?žńt#tC­é†<™˝˘3˜gšŤY­}óľJ?;_Í<ľö37¤*ń#žW‚ÍŮ|EœŔgH\ ˘ěŸd‚W‚'˙JRs(€Ô Šu¸ňCş•˘ŽfŚľmÂşĂíhnôß3ÎÝÁz˜eŒ!Ďv­ßŽ•ÚżţrűśűPśď߂QłŚŁÜĺřaÂ˙(§Dšâ‡2_ŃćęHĎ'aa“śŐ˛ô6ůěĚ6övľ?ź yĘÉJĺ‘Ú˛e3Î=w˘lܸß˙ń=čéíÁ}<ŠéÓŚŕmöôôô¸Â‡ĐŐęŠ!ŁFÂWžö-ěÚ˝˝ýhijÂźyçzˇŃD‘eHtâGćeő"ŮLaa§Řôř*lü¤vPÍv"ž`Vhk&Ň Â"–zŠ(ÖPc!B˙šƒÔߚ;,‡Ż}O ńC^ýŃŐ݃GVíqL‹“yیžžđy^˛~NüÊȚhÝÄÄ|­ŇĎÎW3E­ýĚ ŠZüČ+^xůŐ'â$|(‚PŠ´c˜‹ ¤ćPŠ?j+~›ÇXű˝›'™ň ŻúrܙŁwbcçn 6Č ăŹśuX×uqb#Š‚ˆ.:•|HńăVl\Â„6ź7Á ž! b §PIGĘĐ÷1Ĺe›s#bÉL›´­6@ĽˇÉggśąˇŤß••çDž ŽijjÄgżřUźńöWá˛K/óžËą{÷n|á+ß@ë˜6L5ýŘšçfϞ &ĆJ;xđ:öÂř‰“Q,Ńsü8>˙ĺŻă_?ř~ď9"ÝÝÝxfń3řţţŁƒłĘ?2ě45éaK˝T k¨ąĄ˙ĆÜAęoÍ–Ăמ§N†ř!×ă~WhÜ~°Tń#(CâDşrFˆÄĘď3?;_Í<ľö37¤jńŁL°GDä; >É"H e˙PIő NžBjzáÍWŠ™mŽćŤÚ,Wú’HçGüŀFŘ)ŽŇ>ÍćڙăńWaÇÁY˜ÔÖç9ŽůY Í-Ć߅CýÓ+™Ń­_ěííÁîăč8؅]śŕxĂaŒ?[!č 2.ĺ4iŠĘ|C›íą?‰dŚMÚV ČŇŰäł3ŰŘŰŐůś ýPT?ņ<|Ÿűü¸ü˛EX¸`>yâ)ěď<‚ąăĆyfņF´śśáŕĄCiÄÍkkmőâČĐMÍ-Ř×ىOî ¸îę+°bĺsX´x9Fľ´ĄmôhŠ™všš‰ô‚°ˆĽq$Š5ÔWčż1wú[s‡ĺđľďœ“%~„žGŽ÷˘^ČsNě`+‡stM´nbbžVég站‡˘Ö~ㆠVüîą¸ “"ˆČw@|EëgNOôƒŞ(‚¤ú8)"Š=@ę7o)~dś9šŻms%ß ó‚ކQÍřŢ/aFă~Ť_ó'ŃR˜Œ…+ŃĺĚAżÓbvqűgý‘^Wُř6ażŽB  ˇÔ…Ł˝űĐ4n,ĆL™ňĎuy;éTĆ%pśďcŠş6çF(“ńĄsÓ˛ô6ůěĚ6övő?B‚‹>Fƒ–f<˝tľ+~,EۘŃeńĂł“ëKÁÁśm;1÷Œšą˜Űśípż+ÄćĚŘąăđü–<ťň\ń˛ă&NňD”°P‘¨SV“E2Ăh§Řôř*lü¤vPÍv"ž`Vhk&Ň Â"–Ć}(ÖPc\Ą˙ĆÜAęoÍ–ĂמsNŽřáî,şbăécűÝuވţÚ_2}ô€[F1r@bKdM´nbbžVég站‡˘Ö~ㆠVüˆ–DäÔAÖꄿż&(‚(Úäç!„Ô uâGf›ŁůÚ6W6XHĆEmmřIß˘Żťň–—đy¨ŃmE,Žű}ŠżĎý+?˝‰ś%샍Rc[? ĹƸM9áTúĹŤ–[Ż–VŒ>…ĆQHŠ•ňžwrô1Ĺ]›s#”ÉxŽĐšiYz›|vf{ť'~”G2.“vR ˜8e ˘3–_‡s§ÁýţÇ?ý9ZšĐÖ6ÚËëî>âĺ5bEĘ6Îĺ'Śp$ÖqŠ•„aX-í„ÉÚIkDą†Ă ý7ćRkî°žö}r˛ĹIÁý}›}ú üÁŮOá÷;ŚŕX?jBŃ]ŰÝßŮ˙łŕ ťîΏ}gB"k˘uóľJ?;_Í<ľö37d0ž)sŐAiđE‘ď€ř$ˆ ;ťĘeSÁĐAHÍĄR˘;Xń´SIGć4ĹEBßXĄ•şËä¸YłŤGř Ô˜›Čę{E_¨Ú™ź„^$Ŕ+ńĺľźĺXN%ŽăůD„'YĹežĄÍÉňň ˛r„ÎV¨2Yz›|vf{ť/~”‘;6"QĎĐ.z흨ě#ČłÎ{vá??÷ßhnĺĺ?ާŘäßڒ'’U^Ł;銪Šd†ŃN;°éńUŘřIí šíD|Á0ŹĐÖL¤„E,;´“Öˆb 5†úo̤ţÖfŽ[űÚ÷ÉÉ?˘ĎňiiiÁ[_~Ž^ˇÎ{&ˆ}pb̘ѸđÂŤźt–č‘ÎU›˜ŻUúŮůj楨ľŸš!5?<*GŁÁPÁ)'‚DËŚŠ # ő 2ç+i§’Ní/PüČĚWÔ˝ŤźcćTŇ"ÜaŤlcĘ/ŁśOэZtc^ţ‹ý¸$Ú,ÍDĄ˛ÁJÔ'6^4âGR řĄĚ7´9Y^DVŽĐŮ Uf"Ko“ĎÎlcowňď¨]üá¨I;'˛sŕ7zt›÷vˆđá‹Í­cĐĐy]fyÇŰA˛ĐňŞHń#–0™0šC;i(ÖPc8Ą˙ĆÜAęo-渽Ż}Ÿœlń#‰\ÚۧxŸ¨˙Ű+r•_'Œď3k)–$ćk•~vžšy(jígnHmŏ¨{Ć\š"ˆE?EXΝd›‚8¤ć@ęBtg‹âíw˛ëÍ/o8ăußˆaډ 6ZÁˆĽ é|áÇňӅH:ž/˘u D˜řdeаícGŃŻ0÷ýH?rţ@ˆŹĄłŞĚD–Ţ&ŸŮĆŢnhˆ!ţ™Ţ„W2–ěÉ[њš0Jžţśš nÚ˙ℍp˙Ą|F9{0ľ5Ři6=ž ?ŠTłˆ/†ښ‰ô‚°ˆĽq‡vŇQŹĄĆpB˙šƒÔßZĚq{_ű>9™âGR|ˆ.‡éčŐţžżÓ-+ĄO¸N:áďg2ĹK?sCę"~D]Sű)NĚ.şďő‰OSŐžBÎ8 Ÿč> Tű%‰˛…°ˆ)_$âŞöאگJ–­ˆŁŘ7J÷cčOUœd*â$öçÔý“ěOŔÜ7AlčÚ‹1Wí§Ęâ m› óô|˜;Ú:ZŒyÖ:$bHĄR˘+Ĺ$ڟCü(˙)¤b!ZˆQšúBÖŻP>Hp"iE~ÇK"iE~Yh‰Ô'\v*m œ”řť†â‡2ßĐćXyɝ Üd˙ĘE*ŰNo“ĎÎlco7´Ä¨]xĐcu)TĄ2#v0–=Â+e§Řôř*lü¤vPÍv"ž`Vhk&Ň Â"–ĆÚI[?ęëçűę}T"ˆ—ö3bße}*6ˆ­÷YąÓy‘5Ńş‰‰ůZĽŸŻfŠZű™RńŠuŠ"HĚ'Ţ?A˘q?ć#S!ľ‡H=PLpŠALXô…˘îÂIÇu’=ů7Kä(—§č‹Ź>‹w‚6‡Žbi$ŕDxe @ń#Ń6Švf{ťĄ+~”—I"ĺ" q<˙˛ ŠśÉŽgc§Řôř*lü¤vPÍv"ž`Vhk&Ň Â"–Ćć‘Ęŏúúůži˝Žo•ŇtÂGüSŠoZĄřaçgnH˝ÄŸôo2E¸Oź(‚Dă ~Ě)‚ÁC¤NPü@˘ýƒ?ÂbW]TŇNÄϏĽhłŐ•NDđPô˝˘mĄ˝ĺ>‹¤Ă2Œ}LńC×ćXyĘű<ˆŘĹ7‰‚łěô6ůěĚ6öv§†ř‘$<;\ţëjň *uvY(kĄŹB~;íŔŚÇWaă'ľƒjśńðB[3‘^ą4îĘšĄřQ_?ß7ŰG+Hˆŕžu͕Iżp˝őN_$ě(~Řú™R_ń™żÍAâ>ńţĄ3ř1a"Š9@ęĹ$Ú_ń‘ú%ëüu?QÄŃĺGüâĎůˆŚƒg„WuDҎ\}2Ż( óĂ[t`ŃÇ?tmŽ•—ľNX›TŞogŮémňٙměíNMń#ĺ¨[ő`“MŐvځMŻÂĆOjŐl'⠆a…śf"˝ ,biÜa9RÖPü¨ŻŸďköQ ţąĂI=ó#^_hEŠů|jᛋŒßhŠ qŸx˙P‰Ćü˜S!ŐC¤„“:cŁ@ńC‘ݍťşźŒg~! K¤ÓY}ŹżňC9ŽŇß)TŽ(IĹĽřĄĚ7´9VޠŏŠov–°°ÓŰäł3ŰŘŰQü@FřüvځMŻÂĆOjŐl'⠆a…śf"˝ ,biÜa)Mó•Eí…ţsĺ(׎ňĂQü‰ ">˙lo{‰^ůĄťR$^žˆk‰ÍśĆěg站‡˘Ö~憈šÎ{ 2~Ť)‚Ä}âýC$gđc>RDRk(€Ô ŠALXô…˘îęňW~”oi EœXń#u;MAËÔÇ?tmŽ•§Y'r!tYÂÂNo“ĎÎlcoGńáóŰi6=ž ?ŠTłˆ/†ښ‰ô‚°ˆĽq‡q¤˛'F•ý7ćRk3/­}íŰ;Ôŏä3?r””iśĚzĹsCN¤řĄ:čK­{Ab>ńţĄ3ř1"Š9@ęŏ &,úBQwuyęŰ^üt¤ÍĄaőĚˡ˝DŇp ń2bcW…@ńş6ÇĘ3­ƒ@(RYvz›|vf{;ŠČŸßN;°éńUŘřIí šíD|Á0ŹĐÖL¤„E,;Œ#•=1ŞDčż1wú[›yiíkßŢSEü •ž6Ďűˆ8…ŽJ˛c‰hąśD˘şUůŮůj楨ľŸš!'Rü¨8SĄB¤’__„Ô u„⇢Ń|EÝŐĺYŠŚ|Ť>ŽňśŠvmŚřÉ6ŰŘŰQü@FřüvځMŻÂĆOj5’4ÇŇFK ¨š›mě„ÉƑʞU"ôߘ;Hý­Íź´öľoďŠ(~¨Č{ۋY<Ńbm+˜ŹnU~vžšy(jígnČI?ßw¨dPŠüN8†~ˆ—­îOEŠ ‘|Š ¤z(€Ô ŠŠ:DóuW—Gń#Ţ~ŠŠu"á—ĄHŠb ›|vf{;ŠČŸßN;°éńUŘřIí šíD|Á0ŹĐÖL¤„E,;Œ#•=1ŞDčż1wú[›yiíkßŢá"~hœBתüňůÚlkĚ~vžšy(jígnČÉ?Tű• Š •ţq ý/[ݟŠ8A"ů#D!5‡H řĄ¨C4_Qwuy?âí§ř‘Z'’ů–D}TÉx–Ţ&ŸŮĆގâ2ÂçˇÓlz|6~R;¨f;_0 +´5éaKăăHeOŒ*úo̤ţÖf^ZűÚˇ—â‡Ţ/ŸŻÍśĆěg站‡˘Ö~憈“0ďU.Ń}‰JEJ˙8†~ˆ—­îOEŠ ‘|Š $?@ęŏĚ|EÝŐĺQüˆˇŸâGjP´9?B™Œgémňٙměí(~ #|~;íŔŚÇWaă'ľƒjśńðB[3‘^ą4î0ŽÔŕVFB˙šƒÔßÚĚKk_űöRüĐűĺóľŮ֘ýě|5óPÔÚĎܐ“.~¤&Š  B$’Od¨C¤NPüPä+ęŽ.âGźý?R넢ÍůĘdżv`Ó㍰ń“ÚA5ۉř‚aXĄ­™H/‹XwG*{bčzFƒĐcî őˇ6óŇÚמe?ô~ů|mś5f?;_Í<ľö37d(ˆń˜AŒq"ĺSA$Ÿ"Hž1'ľ‡HĄřˆcźîęň‚z”„ˇóV ţz;dĽdaZ#~¸cđW—ž‹ŰçÍrc”Ň}ŻhĹœzâGô#"+Khmňٙmě톖ř!×Oᮜу-Š9íD|Á0ŹĐÖL¤„E,;Œ#•=,ćj>4EÁTĹťBŤ(-t­Ę/ŸobžVégç›m0ŇŏxlŠ Ć8‘ňOEdŢÄqřŘ5—â†ÓŚŤăPÉl“ŸOd(ŇR(~ ⯝ş<ÇŰií ˇ3—MŸ‚É--č- `óĄ.üfÓv,ęŘçŰ:ań#Čťqv;nBž.97ôN°GőA¸DýŹâ(ۄ 1˘˛Ë%äë›ămňśŰe{Mœ ü?şpţög•ťňżZŠ'śHôCźě°?ϛ2ßží*ĎďŸ\Žű6íróED;ň}*ý ęŸx›Ňý™ŽóÎ ŕŇöI¸jÚTü~[‡:N°_éU˙$űS5wœx›˘s'łM°ódĆă(ËVöÍ˜ÇăúůsÇ0ćĺ6‘šC¤Pü@Ä1^wuyţ†sRS>rÝĺ˜ĐŇ\ŽŰX,`Á”‰Ţçgk6á{Ť7zŤg~”JXşs/^yÎ,ě:r;\!E8 ĺߢd}@ńă”?"!íYYBk“ĎÎlco7tďI'ŕC˙ôw˜0~|9ŻąąçÍ;Çűüü—żÁrwe' LĘSŰůK Ĺ"ţçk_ôŇ?˝űWřŃO~٠Ɉ•ЧŘôř*lü¤vPÍv"ž`Vhk&Ň Â"–ĆƑʞ@Ššž˛@SLą)~Tp ľźč7˜g9Ş-_nJÖž‰ůZĽŸośŏh(Š ѲmE[ϙëĆWž;Ă@Rý/[fľšżł!š›‚*8uAÖěÄÂɰb߁rťß~á|üŃ|_ČšîÇ÷`@řŽA@äHÝ ř‘Źťş<żb „?<řq˙úMXź}Z›đęçâôńcńęygŕÁ-;ąóhoeƒRĺX•íLp…‡ťqŮp  oţÁ}ƒBc3<ýŁÜŮat"¤ ĺď ĺ›hoƒč¤űŘ­O)Ü"—kä¤Ű,‚ wyăçřxŠéuBŮf(çUľˆČżÉduvf{ťĄ#~HQńˇżŞ,~<đŕĂXúě ´¸gŒoťĺĺ8ý´™¸í/ÇÏ>‰ŽÝťË~Ţ΀ˆGí(EóK•öFEȽp˛.%7ŻŰŰŞÄV—+"e;ą2=aUc*í šíD|Á0ŹPĚźĚXf;arWFHŰŠk-˛UĄ_żőą)~$˜ˇ…w˙SĹgŃ#O>⼠o{ĐŇęç…’pAŐđĘsC†ŹřQI$ZśIiokĆٓF{y;şŽać˜\7kÜýÓţ’€ďd´ű>ľAîZż+÷D‡{"1dBó¨r:~|N$ŤM~~•"Š9@ęŏdÝŐĺEžůá̜;Ń?¨ZďŞĚŸ| ކtŐîýř—Żń63GˇbGwWâ(w'íögŕ3§şÂÉ(ě?v‹wîĂ]kśápoŸWĆ+Ν…ż¸lž÷Ďţöďó on(â ógáęYS0ŠŐő=ڃGˇěÁVmĂńţ’ˇ9şőŹřË+Îöęđşď=Ўżŕl\yşÉî#[öâŽg6ŁGÚ:ţĆŞšXŔ^4 ×ΙěĹÜçÖsŃÖřţňí8ÔÓ_÷ î•óÚqëźi˜9ŽŐ-oOo;ˆo-ކŽŽŢ@Q÷q|íć Ĺ="ňo2YŮĆŢnčˆޢ;pçœuŚ—~~Ă&|éŽoşÓľŕŮ=ˇfţé˝ďń~ĎgÎhnjéířťw˝ÝłýŇWż‰Gžx*¸zKŕ%7źö–7yßýżţÖm؈1ŁG㾡˝—^|!&NŁGaŐę5řŃOďĆÎ]ťqĺe—ŕoŢůĺşüÁŤoő>˙ĎĎáŮŤźź œ‡WÝzćɍ‚ť}X÷üüěž_ťqÖÂ_MžţĽĎxe}çwĄóđaźţľŻÂčŃmXôô|ůkß™sĎŔżéő˜{Ć8xwýď/đŕϕĹŠjuˆÁ­œúő[›âGš’+pˆÓg—— kV”Óý3N‡hk‹ťbcĎqď˙5œ•KÎCpÜőŚ4˙| źäŁÇĹb;ë× ř{˛aÇ68ňy[ÓŚcŕęPşđҰ–™őrş řŔŻQX˝N×!ˆfˇžsĎF˙Ko˜Ňi',QĚaŁośŏtś}ŢŠ ^ţMgˇ{î2ýËuťđśKĎ@[cŽ>mŢş/ć3fT#ŢsĺٸaÎ4şżewŻŰ‰GˇďE”Éî~ćoŢx˝—žsĹ&|á™u^ýä3ďţń*ż÷ľ?{Űőęx×k^ˆYc۰áPŢtĎŁžrá”ńxëÂł°pňxݜŽČń‹ Ű𣵛1tŇ;/šNŸŽ]ÝÇđšťŔw_q=ćŽSŽÇĂŻ%VšÉ˙}ŔS/œ< o™śs˘+îȘÝřĺć­¸Ëý=(‹#ARs°žHM R(~ÄëŽ.ŻRůˇäî0uďq…ƒ´ť#sŚLô„ůÝîžźăžßšéŠMM(ź őÇŽżłÇW6ÂÓ]qäÖsfá’é“đ÷/F×@˘×ŘJ‘El,˙~ăEŽďčňwíŁ[đ făÂiđ÷-CŻ+l”J~oş§wšâÇ çV.]|Ĺ93<擏­÷Ĺ×ćÓ7_€3&VbÎۂל?—Ÿ>ďşçYtő–ź~úűkÎÄMó*ąF5𒳧âĘYńW?]ćžčCěJŠvóŞ Däßd˛:;ł˝Ý|ŕ)J8ěŠň6˜ŠS'cÎéł°˝c—7]÷îߏw˙Ăź‘“âCƒ+`v=ŠśÖV\|ŃB<üř˘rœË.žŔKďŮťkÖ­GCc#ţĺ}‹ÓgÎđňĽř!E‰ŤŽ¸ Ď?ďýŔ‡˝m„˛ć%˙!Ź×_{5ţę˙ž5vŐĆŽďÂóńŮ/~O<őL,ĆĹœçÍ+/żčşŤ˝úŢř˘ëĐ<Ę?ťŐ>u Ţńś?Áž}űąňš5ń!MRüČśłESLą)~dŰVވ&"×'ÂćcëXožô)8ťvTň\¤đ䣞PŃűŽ÷cÇzŮĹĹO˘x×wbçlل÷3°^|SvĽJhźăspvwřËÍ-pŽvĂYąMލŇűî÷AŒŸHńĂÂ÷DˆѨقEŐńMgMőţv9Ž_ŹÝ…?šxśˇ/{ë9Óńđ–}ĺ¸ îI…˙žĺœ;ОűƧcţä1ąčęéĂ.7Ö´Ń͸rĆ$|>8hżzćä˛ŮÓ'cŰá­ŰԈÓÇúçÖĂݞ˙ N›‚Oßpiů*JYË3Ý}ęw_zÎpŽ/ZîŐiÜ(˙v›QŢ÷ˇľ!}č8Zޞ#cȊO^{e<渹xׅç㌱cđo‹—ňJ ˇBjßS/Dt?âG<í(ËřŚ ŢňŘćQřĚÍ/ÂGo¸Ż?ď,œ=e‚wűJŃ=(qÜ °´­+t„âǡž^?ţţŻńŠŸv÷ĽfŒiĂ+ΜQ>0*SňE×͛ĺ‰ýîň‡~ýnýęÝř轋źËéϚ47Ÿ9ÍMdgpú˜źóŽGđÎ?„Ý^ŢősŰŃ"O~ť;poX8ł,~ÜńŘsxĂ×îĂ'î]âŐç´q­¸Íš/ýŻ_áď|\ąg̨źýŞ9ގh˛ăăh7oF”ř‘óAĐ]Ä33líěĚ6övCKü¨|ăŕW÷Ţď-3Ÿüř˙Ăżţó{qűŤoĹYsĎ@Ń]?‹îΑ@úűűąčŠĹžíE xy’–ć&œ<ţ„ˇŽÎ;űʞř!ŻůĂ?yţâŻ˙ť÷ěĹ÷sĆěYxňégđŚ?~[š6?ůß{pű›˙ËVŹDkk3ţě-číh,^ú,Ţňçďp?ďĊ•ĎyyňťoŰQ™lRüřÄ'?‹ˇ˝óW$ˇźü%X˛tš›÷7řô}šźýxá5WAŠ?™Ä†Tm4VŠ5™0š+#¤íÔľىŞ•TWZśoNŸl_űv uń#Y¨Éłđť{ËâGáÖŰQüĐ'áźéO]ľĂ=ęěDĂŻę}ç;ę?ŘT *í3ŕüíżŔy˙GÝŁžs˝ď‹÷˙ ÎŢݙĺ8›ÖUď׿Î'žç_ţ ˜4Ĺ=Ĺ=…Ű)~XřÖvޛHěxA’űŤ•ßńňŸčďtĆ>Bú7>îsŞžfjŰ(œŤ÷vš'şz°ń KÉ5ł&š'ćŠĺ¸ˇœ=˝,~ŹŰ߅/<ő<ž˝| ćN+ާ_`ŐžNoůLwŸVŢJ#Űľ`rĺęŹËŚMôŒ/jŸPîÉE;÷{_>gşwňŽŽŁřÔÓĎá#/Dz=ţs>n;ëtLuW“SH.~jńJ<śsO9ď_-Ă疭ňÚţŇÓOĂń摒Ď,]=ľĎîóË{ĺł15źÍ.ł?ƒź°0c%ęçÁšj?ÚPvWUśPĚăŹ6ůůs'ŁŽ¤śđ zX…2?žbE'|ň‡b¸‹ŢY¨bní@OߓřË`ŚŤ>ϛ<ÁűźaÁYޛ`žźx5ž?tÄpÝ,_DXť÷îZąŽ{ĐőűÍ˜ĐşĘű!Yšď{fIÄv˝çm¸bĹ çř—ÔţnÝ6<ąmŻ{`VÄÛwă†M¸fî ź`Öüdĺ–XŁżúř*ŹÝ×ĺĽďZşďzŃޏÍԖFlăî㕠Ѳ+öňęöŗvôN¸-ëčt…ŽŃhi(âZWůÝŚ˝Ţ7ž1Ľ\ޗŸŮˆĽťyˇXnjŔkçÍ,€,jю¸Ńݧ•/ 8wâXě=փ‰-MŘ{´SZGáü)ăźú^*…—^wŘż•ĆÁ×lÁCŰö Ç]ż–î>€>w]˝pę\4Őˇ•WŒě9z<>•ÜôŁ;văE§M/gÝże‡wBQvՏ×oÂĂ;:Ü}Ř–îÝçƸ`ňDďś/ćh7ćąc‰ţIö'ŻŠÔˆLj:P٧ĄřOŤŽü€żÂ;îYă':öáŃ-÷cŽŤf/lŸŠËOŸŽ ŚOq—Çŕƒ×]Œżűí"ěíęĆÔŃžŠźi˙ašFšžŢ?[ť5ŮáÄ7ňŠ‚[č´1žďËćÍö>IŚińvÚ"ÍFǑˇœfŻŇ˝çyř ‹Ů>śĹ[ŢŕŠ$˛>Ž[yiďVěô7d˙Čé´qžÝôq­xřonI•-E•‰Ž¨Ňq´TްZW´ďSăô˝2ĂBüˆŽ•B™L[Řؙměí†ę•>žâÎĺEŽpđřSOcś{śGŢbrŮ%âüóćc–ťüţżŢ˙Áa{ÖG>ĂăĐĄNŒ?—^|V>ˇW\vąkÓć­Řšc—wU×ęľëąaăfœ9wnšéĽŢg˙ƒxnőZďAŤŤ×>ďŐ˘x‹„\–ť3ÓŰ+Ď ¸ă‹ŸQ5Sݰčtvv×߂ˇýé믏ÓGşg´Ý6–\˛§§ˇ\–Š )~XŘ }Šv…ZyJÁá€Ö3NóŽćň‹@ać,8ŽW˜päsAě+ťőM^3ű&LňŢĺŮíߟYTiΙ(Ęç’lۂÂcżÇ(÷#ƍÇŔgaŕňŤQ:ălX4 ŠŚćöąó­ĆĎÜ맔řáíÔA„ľrÓŮSËÝ'Ż‘W„,ß݉7œď ŻŚšśMĹĘolsĄA1“üçxEˇ$BT^F°ö`'f—Ďž†wš'3§ľśĆbŽ ŻtI AŒÄ× RS(€Ô Љt†řĺo*Ę˙1ŢYŚ}ÝGąľť›×oĹÝk6aĄŤFěć˘Í݈ß8{:žˇ|mĹYn[äŮašQuZä™byĽşˇˆš<Œyđůí(ż)"¨ÔŃžR Ţ…‚˙։؛!JrŁż4^ z‚‡uŠĽň&úcvŹŮßČz[ǂ÷ü‘°óŹĆËűg„‹ÉłE貅…ŮĆŢnh‹y@3uň8ŻŚűöŔöŘś}~ń›űźŰZ>üôžůqĂ ŻÁzˇ'N<úÄ"ÜzóËpń… qç÷~čÝ#yäą'ź×bĘ{…ĺŰ]>đáăe7^ďŠ){WkČçŒ\wÍUŢçó_ůyüIŎ@zĎ@Ú9‰vÉŐLÖ7ÖĺŤZœXvÁŤ—SŇÜňR&…ŃFc•PóPŘŘ “ť2BÚN]k‘ČŽW5ú(?ě ­Ć3üi*Y/ďÝgŠěÄęŠycIޜď|đăŔŞg-›?CŽi}Ţúć—ÝÝ݇ô;R^éąńPˇwËĚŠăq¤×ˇYž§Ó{Ŕęe-q›fđĚťĽťú"uÓźz!n>ÓżőT>ŕôšýîyť’+¤L*ĄžÂ6‘'*ăňĎW\„›ćœćĽw=†Őüň.™:9đtRýCf„Ô ő€âG"­?dĆôÖ|ňĹWyy__şż’ÂDƒźee›:”ˇmE ô`OW7ÚÇ´aîÄqąöżqÁ\ďrÂeťbɎʙ)}ŐçŠ"{ŽőŽ ůŐŞMřěĂË˝ˇX÷ÓäŠÔ˝ýn$ďĹH§†mp*éJ źKüv>Šéc[q攱ą6żĺâYhqëźxÇ!,Úź;:bጠŘ~°úĺřďĺ…÷ Ź~yˎqGy‚‹p,Ć+Ú÷Šń ęĄĚĹĄËvf{ťĄ/~ČąœÖ>˙öáxËßúÎpďýż÷^™YpwšśnݎđŐą­îúě ŽîwĄ2}Z;ޏě477{vĘˇÂW`Č˙š\qĺٕĎáž_ßçĹX0ď\źďďލśśVźř…W{‚‰jŻ]ćěÚ]šů›ßţ<äď3ş˙54Č瑔bW”qtYÚA$…ŃFc•PóPŘŘ “ť2BÚN]k‘0ŘUƒŢ™â‡]Ąš<剄‰îËţ˝ŔŽmąŻœpŮ]_Ĺř Ŕäʙm§cĘóüôŢ]ŢŐ=ǎ áŹsP¸îF˙ÁtÖC|ó‹€|žČâED1‡ Í6šâGÎ9 őÁ#E(do>g*•ŽĄŮýzáěÉří†=8pŹsÝUkbsĆ57˘Sž˝Đ;?ňPTÇ{^ÝRwW gMíÝÎ"‹•Ďůhqc^6}˘w‹Œź}FňČś=^˝ä› Cńă-ťđ wŸ[ž=ńĘ“+ˆŠč˜Çňď­4Ąřńťmř匭čęíĹÓ§–Ôo E+„Ô>ľD÷oâióAŹ—ŒĚöa/~_m9Řénô{Ëo˝đ\źůü3qĺĚŠxéÜYř÷›Ž+okÖí=9mÜč?œíœ)đóç`RS#^túTźaÁźzŢ,œăţČłĘŃ-GřĚű‡6ěô–_:o6Ž>s&ܲ3§NŔ7Ţôbüč­/Û/9É_+ĺ˜"ě—~ˇÖ9ż}<ŢxŃ,Ljnpë> ˙ç’YxݧaŢd˙éŰż[ˇËű{ڄ6üŮ5óĐŇҌÉcG㯺÷ţőKđoŻşČd#ŠVůyşlaagśąˇ;5Äyđ%ŻöđÄ—?zÓëźgd\~ÉE¸ń†ë𑞿|u”|EŽD.Ę[[vďńŠŰ_uŤ÷WŢÚrđPg¸UÁM/šwŢń|ćß>‚Ë.ö×)jôPÝǎA>X^Šßœ“ŻŠ•oiijlÂ3K–Ąˇ×żô÷ŻŢö'˜8qZ[Zńć7܎Üů5|ö?>ę˝ZWŠx([ŻTł°Œ–PóPŘŘ “ť2BÚN]k‘ĐŘĺ^CľąËßZĚ]{_ű:kńĂw‚ŠŰ6Łřű{átDńW„\ľĚËv.¸ÔěKóÁ[“~ń3vl…ł§şýČ÷w…ÇŇ—ůéČŰ#œí[=¤řÄCőá@ńÓC˙Ęe8ÖӃŢqăËśNKKfM5ś+óQk?sݟŠâGč’ő@Éřv$š_÷ ›Ź}‰ôožc¨ Rű€jŸ'g¨ÚÄVí_ąn>ŰżES^ ńá߯Ĺűűœ˙š˙9|úńçËŚŻ<ǎƲ]ţoŹüýüċĎ÷ŽšŢGţč‚9HăxˇÁHfŽiÁœqŁąűČql+Ý őœ‰ăđ–‹Ďń>!;:ťq÷ęMąWŕzľ‘Źű{K7ŕĘYí˜5a >ô˛Ëb6ň‰ŘOnŮSéă(éfř1żłt^pĆT̝<~ĺ™Ţ'dűĄnüôYůl’m=ˆűVďŔËćĎÄ[Ż:ËűDytă>˙,ş@Ym6ÍŠHI5ˆČżÉdÜÎlcowjˆ!ňľŻ~ăŰxď{Ţá=ČôUˇ¤_oůܚľŢŐŢŢ3C xäąE¸ý5ŻÄěY§{6yˇż8ĺUě‘'yą¤pńř÷¸¨Ď~ŕĽ˙÷ž_–OÎČř.\€K.şŔűüű§>§/ĹßüWüřSďšo|ůâX6oنŽŕbs-)Ĺľ:„]ľ+§Ţâ‡]ĄU”ćý+_][ˇ¤tlGńŢť˝OW (Ýzť—,š'˙ŕÍ(}˙›€+|4|ţ?bќ›nĂŔ¤É^]JÓO+Ÿukřî×Ü#ĂWĄpĺľîáˇŢ+vżů%ďőŮNxp%ŸíuĂË3ë˜hŞUť”߈ZűYlgŞô=éâGÄ5ë :ŻAůlţ¤Ö&œ7Ĺżrcっ¸gín!mيx󅧣˝mŽřŰ'1 ďÍw ÜóFřű_>Šťž]‡]ŽÂ,ľťë(~ąj#ŢűËÇp¤ˇTžźž‚ă='¤ÇöďůŮcřŃŇőčpď~סÓýńxčůxç]ş?Rň ńUĂ ä…HłˇTÄ_ßľßćyď /˛>ňś˜Ÿ-یżţń"îŢsAäĂZ?zď*|ú•Xżç0Žť?FÇzűątŰ~ź÷§‹ń‹•(÷9ŏ\óm0ˆČżÉdÜÎlcowj‰ţó2 X˛l9ţţŸ>„‡yÜ{ކź*ăčącx~ă&Üůŕ_?ń)W{(?_CŢĎü蓋Ęqź×ă>˝¤ü˝äH×üăż|÷˙ţ!ďá§ňv•Ă]]xňéĹxß?‚uë7zeKű/~őëxÚ÷Ľ;ÂV$ÚëĎíŘS@œrƒ3ť†â‡­f%Ѣ÷ŁřaWhĽ…Žč—żľďúG8Ž⽒VžÝ?ÎŐ×Ăůű˘żľľ\żž‹Ż€ó— œ3hnFš\łÝ“oů ôßpsš â´YîinW8?ѝ͌čŠýŽ˝óžW\ë +ŢAĹh÷ oáĹnůďG˙ił•uL4ŐŞ]ĘoD­ýĚ˝~ʋ‘źĐ] rÓŮSĘ?%Oí8äíFǢťgKvúW|ȇ…žčŒÉŘvř>óÄóXěćKÁBŠOn?€­ÚŽX‚¤Íšŕ-…^9ň5ˇnŮňy"R ń^”}Ô=Ůw‡{2pÝ_,ŐPđžňăŕE’żƒ~?<šs/~ąÁ=ąpźÇť˛EŠ/2ć×VŽĹ:W ‘o‘<•ŻŐýÉúÍHăđJŒ6ůůÉőÔÇ"߉,‡éBäoř)Ÿ†ŕÓä~ä)źń—\rů“ňMĂ﵌˘„ŰîúœŸ!â+HtcžÜŕTń#D âňy˝˝—˝{}¨ýň…ďÍ*R@đޒ{6ŠżĎľďCI>ą>Œ%wŞš<‘DÖcŔ=@’vŇG>[ĂówcË爔úz˝2Ë6u° žoŁoŔő+É'ŘËHMÍŽÎŃä1ĐŰăůz- cFě…wŚWs˙¨ŽŸgăśĂť+gŔˇ+yOÖFUÜš6ž­Űáó†âG¤îßŢďÜćőŁňYá:ză-ŻF¤Jˆ7Bí;’ŏJžż^Ęú–üü†- Żö(ü1p‚qog’Ÿď~ó+ŢU#ň 2˙ůŮ/şëiCY‘ă"×csŔ[IüőG†(7ϔ ¸6rÝ)§UdLYžŹWŠ4Œą?šź§‹Čúý7ĆČ+ÍdÝe˝ EY׆ üWí÷Ę(z<.xu–WźČxršœŸ=Ab †a…bćeĆ2Ű “ť2BÚN]k‘ĐŘĹmV<ó¤őúšléS™6?ě ľń”W[4—­÷ôóscŽŽŤ{4xoEňބä­cňV´>ˆÄށ\OĂuÄŻ‚ËÚ@✲ĚpÝđnië ĘiT–SŠ=ŒX¨šj ۀâG…ë_ô2ëőłđ查ŽĘżřN¤ 'qšĎ)Ÿ&Żř8 ›đTş‹[ąq"6úşř>N"nĹ>×:Tm béYă[p~ť˙ŇU{ş°ľóXšěĐţěIm8k’›ô˛]Řuä¸÷\8yëôÔŃŁź“;şŽať{ríšŮţó9žuí:ş•Ťˇ`ęXœ>śŐ‹ý´{2QŢî"óçMƒŮă|ąr‰+pȇŚ:AýZ‹˜7i&67BîľîëîÁŽ#GqŌI^œ§:öă ť}ŃÔ homĆ1w]~dűîrťgiĂ칣ŃěƑWO?şcZÜíĹü‰ărE-Ć\$ć§EŮA\GŰ&×?ßĎ[ű–5ޟĂůÖŔ%Kž–…”Ę źZN˜ţŕ3|J‘ˆüţ0E7tŠoŠá^ę`-~@ç%ŁÇKÁďĽÉ|Ňe„éĄ-~ř—{Á/ÂWÚʃřÚňęâP˝eďr5ůúنQnžťĂ5ŕ0ů—ąop÷&ťy…Ś&˙ 1Ą!ýĽOŁÜŃ*zĎ )„YđóüKčÜęxg¨ýeůZÝđU˜˛~2–L;lZĄA–Űŕđ‰ŕ1aNŃŻ|Đ*‚Ëڊ^=ĽP¨ÁńmďŤ`œ7?"őˆÔ!/"ňo2ˇ3ŰŘ۝šâ‡żŁâEƒ÷^á­c"\OTŢŞŘľ´´`F{;ćĎ?Ű*$üţá`¨lü×ŮúB`!>˝ )\8ÁsqŕĺĘ7ęyb¨'€ˆň•!ĺ+NÜmCxű›HÔI~çjA…ż­ę ëÓŕ4u ę/EřvN‡â‡­Ý VJ ?ě ľő”Eżwť‰]“ÁĐďŠőýčË*ʜ’BGRěP—Ůç}"ŐőâôšE}ZOĹ664ۀâÇ`pPž|7ÉŰaÂ6ĹűgëĄcŢljhűe‡öë÷w{Ÿčą|űË W0ÁžĂĺ.—üfýnÄŽŹƒ~XĺÚ­Ú{¸2 AĘ+CÖě?)Űß“WZÉ+G–ě:ó‘ĄďÝŘ;h_śç œˆMŘnů|mî§R?ÇúúądĎţ”ŔđŰ-;ĘńŁíń÷áx;ŒŞM~žŸ;¤fPŠÂ_!"ŰăDšâ‡*ß)|! Tô/'B¤>ĺř…ŕ)hT~ýąByc"Ÿ3P’Ha˙RŢrƒS?üíMĄ\†żÝs­]_œŃrüŢ+nĺAQŘćržăoŮ ţFOś­ŕVÚěř‚NĄž% ;+čW‡âGŽůŠC„"‘ekśąˇ;uŏ'˜Ăr-ˆh~ÂĂýîĘK/ÂŰţô-ĺź5ëÖcń˛ĺŢYŕTx)~Ź"RV–])eS~Ľu°SXH¸{Űy…UŠ"ćH˂“>Ťâo?ŠßlCńĂ֮ʕŇĹťBŤ(-t­Ę/ŸŻÍśĆěgç›m@ńcpřűHńƒRťK$ű =ă Bw@ĉőOň@?Ůń˛ŐýЈ“+e˙$Ç<ٟŞ8ÉţTÄĄ’Ů&??ą#Cj:@ńšĹŘ|dŁ$˘?ŽeăHYÁÁXtĂ+Nä Č‰Ç’9áD6ȉ>öž/”7zĺś9NdÚ苠źňU-Ččc'R˙ČÔ4o(~Dę‘Ńf;„vą’-Œ6öv§žř.†9Nl%+2´Oę=‹ŁĎ=Ë,ßÔňoĹbüęŘ\At§™ĺz3ĘQۄAœěA‰™ˆ0Ĺ…g†Ś?ĹťBŤ(-t­Ę/ŸŻÍśĆěgç›m@ńŁdƒ"HšM•śSIö'(‚ˆ|"Š=@ęAdOWf2ĹE~ŹYÓŮmÎ<(@ę<–ÎęămŽŚMă+#\¤ř‘kže´š*DVś0ÚŘŰ ?ń#Ó&b÷܅;żűC7]Bř|bôöĄŹmf<“MĺŢĆOjŐl'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸšž6BńĂŽĐ*J ]ŤňËçkł­1űŮůj楨ľŸš!ĂNüˆ„¤BDݟŞ8A(‚ -ř˜:ÝôÓ?´ůąvRü¨¤)~¤ę‘ŃćŞYŮÂhco72ĹďůĹ"‹hlhô>ň9 áĂQÓń2#ŮrĽMĺŢĆOjŐl'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸ†ŻľPü°+´ŠŇBתüňůÚlkĚ~vžšy(jígnȰ?RűTNź˜Äo?"6ńíPr)î#6Yű"é}ÇPßG$âVěăq­ă@ŐŚ vlż%ÝŚ¸˝&N¤üôPŇűNHí_&ËVÄQě#šÇ<ٟŞ8ÉţTÄIěăŠű'ٟ€šo‚ŘĐľ cŽÚ_7”ÄÚ6Á¸>ÚB¤D7>É ĹŠVă­‡Şm?2ç•5"+[měíF¨řuĘoqŠźÉE/s0’-WÚTţčmü¤vPÍv"ž`Vhk&Ň Â"–ĆƑʞŠ6vŮý),l2}m漾Ż}ů?ô~ů|mś5f?;_Í<ľö37dřŠ(˙‡éč>DԆ"(‚P‰Ä„BjząĄĄřAńĂjź˘őPľâōM.; ›ŘŘfŮ(í‚Ůĺ8Úg~h#ŮrĽMĺŢĆOjŐl'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸÂÂ&Ó×f^ZűڗOńCď—Ď×f[cöłóŐĚCQk?sCN5ńŁŞ)ü.‡é`k/6ą/€ˆM|ťD$Z6E™"(‚Ô u"šĄřAńĂjź˘őPľâÇŕŏ (~(…*”Pş “MŐvŮ6•?z?ŠTłˆ/†ښ‰ô‚°ˆĽq‡q¤˛'†"„]v ›|ŘĹĄřĄu ]ŤňËçkł­1űŮůj楨ľŸš!#BüˆCDŞ6ąłöa"eSń—)‚ r%™PŠÉ ĹŠVă­‡Şm?Źć[5PüP8 U(Ąt&›Şí˛m*ô6~R;¨f;_0 +´5éaKăăHeO Eťěţ6ů°‹CńCëşVĺ—Ď×f[cöłóŐĚCQk?sCN]ńŁÚyňďt˜Žî[Dm(‚€"EHŹ|"Š=@ęĹ}~bă’î‹Hž˘m?@ńƒâG*ÓÚÎÂ&6śY6JťŒFWe—mSůَń“ÚA5ۉř‚aXĄ­™H/‹XwG*{b(BŘŘe÷§°°É‡]ŠZ§Đľ*ż|ž6ŰłŸŻfŠZű™2Rć"ˆm¨ÚÄÎا‰–MÄ_ŚBj :Bńƒâ‡ŐxEëĄjĹŤyU ?ŽBJ(݄ɦjťl›Ę˝ŸÔŞŮNÄ Ă mÍDzAXÄҸĂ8RŮCÂĆ.ť?……M>ěâPüĐ:…ŽUůĺóľŮ֘ýě|5óPÔÚĎܐ‘%~„PąŽU›‚Řű6Ѳ)‚řËAH-ĄR'(~Pü°Żh=TmŁř‘o^ĺ€â‡ÂQٗBé&L6UŰeŰTţčmü¤vPÍv"ž`Vhk&Ň Â"–ĆƑʞŠ6vŮý),lňa‡â‡Ö)t­Ę/ŸŻÍśĆěg站‡˘Ö~憌HńŁěJÄ:Tm bgěăDËŚâ/X„Ô u€âĹŤńŠÖCŐ6Š9ćUä‡ÉŠ GĄ %”nÂdSľ]śMĺŢĆOjŐl'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸÂÂŚPüĐ:…ŽUůĺóľŮ֘ýě|5óPÔÚĎܐ)~¤BPąŽU›‚Řű:Ѳ)‚řËAH- RG(~ Ţś źt_DňmŁřŠ&ń#b› ĄűJXŘQü@FřüvŮ6•?z?ŠTłˆ/†ښ‰ô‚°ˆĽq‡q¤˛'†"„]v óˇůĄřĄu ]ŤňËçkł­1űŮůj楨ľŸš!#ZüPôQąŒU›‚Řű<Ѳ)‚řËAČ`ĄR'(~ Ţś źt_DňmŁřŠ?R™Öv6ąąÍ˛QÚe4ş*ťl›Ę˝ŸÔŞŮNÄ Ă mÍDzAXÄҸĂ8RŮCÂĆ.ť?……MĹDo“ŠZ§Đľ*ż|ž6ŰłŸŻfŠZű™2˛Ĺ(&)‚äˆU›‚ŘŃß)Š ŮqF˜Bj:@ńńśĺĽű"’ŻhĹPü°?".vÝWÂŽâ2ÂçˇËśŠüŃŰřIí šíD|Á0ŹĐÖL¤„E,;Œ#•=1!lě˛űSXŘTLô6y řĄu ]ŤňËçkł­1űŮůj楨ľŸš!#]üˆÇĽ"q­ă@ŐŚ vô÷Š"HvŠ dPŠ˘$R„čʛĘWl¨ăiŠ?ŞhóH?J%ä!ëŔ„â‡Pş “MŐvŮ6•?z?™9vv"ž`Vhk&Ň Â"–ĆƑʞŠ6vŮý),l*&Aűs• ¤×gŠZ§Đľ*ż|ž6ŰłŸŻfŠZű™2\ĹŐúŚ\ŠÄ§"q­ă@ŐŚ vôw‹"Hvœ ‚ˆźë'ą‚Hčé<[i˘+m*_ąŽ§)~Pü¨˘Í#Iüů=ČC_oo*â‡Pş “MŐvŮ6•?z?™9vv"ž`Vhk&Ň Â"–ĆƑʞŠ6vŮý),l*&›ţäáŕÁƒńxBY‚?ô~ů|mś5f?;_Í<ľö37d¸Š’C‡!Ç'ĘĄ"q­ă@ŐŚ vô÷‹"Hvœa.‚ tŠ=@jŽƒîí~2ą˛FW˘čJÝđÄÓ?(~TŃć&~xš[ہŃ⎣Gşb9?„ŇM˜lŞśËśŠüŃŰřÉ́°łńðB[3‘^ą4î0ŽTöÄP„°ąËîOaaS1‰Űô—;pöëç† +ń„˛+(~čýňůÚlkĚ~vžšy(jígnČp?$›7oAžőÓ9źEąAD$âZǁŞMAěX?§Űˇ×ĉ”O‘üĄ/‚ôíÜűő“ŘB¤ě_˝>ľ’FWžčänpâiŠ?Şhó?ź?{W ‡쫔ë,ŠČŸß.ŰŚňGoă'3ÂÎNÄ Ă mÍDzAXÄҸĂ8RŮCÂĆ.ť?……MĹ$m“M<óĚb¨C ŘBńCď—Ď×f[cöłóŐĚCQk?sC†ťř!Yśl9rąGţޚ&)‚äˆU›‚Řą~Nˇ)n݉)Ÿ""ůC[9śf3HíĄRcÇAǓKb+gtĽ‰Núč†&žŚřAńي6TńCÖë#Ţşgƒ´ŰÝą3đV ˃â2ÂçˇËśŠüŃŰřÉ́°łńðB[3‘^ą4î0ŽTöÄP„°ąËîOaaS1QŰt؟kýüíýPüĐ;…ŽUůĺóľŮ֘ýě|5óPÔÚĎܐ‘ ~H|đá\ë§ŘöhęwšR>E‘ˆkŞ6ącýœnSÜ^'R>EDň‡ŽŇőĚJëő“ŘC¤†„´ťcv=ą8ľˆNöč&žŚřAńي6`ńĂŮöD×ßŇđ#~ôČěéŘŠ@–Ĺd„Ďo—mSůَń“™ag'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸÂÂŚb˘ś9|đzŽ÷ŇśëçćÍ[qď˝÷%K°‚â‡Ţ/ŸŻÍśĆěg站‡˘Ö~憌ńă~­Űś{iŰőîďmaŰĂŠßçJ=(‚ˆD\ë8Pľ)ˆëçt›âöš8‘ň)‚ ’?ôDî§V w—Ĺ2EÚB¤†„“łP(`ýO~…Rřf ŸäŃ Kż]śMĺŢĆOf„ˆ/†ښ‰ô‚°ˆĽq‡q¤˛'†"„]v ›ŠIFYnţîŰŤZ?żňßw¸żĄ0•//VŤşűůžů}ÂBŤ(-t­Ę/ŸŻÍśĆěg站‡˘Ö~憌ńc``ßúÖwŞZ?ĺďŽ|űZňwşRŠ "×:Tm bÇú9ÝŚ¸˝&N¤|Š ˆä!ÄÝ?Ý÷ďŹ×O’ u˘ťc7Vë•BąÁ§)~Pü¨˘Í#Xüđ,–|Š|őG^äU ëŸËzvĹd„Ďo—mSůَń“™ag'⠆a…śf"˝ ,biÜaŠě‰Ąac—ÝŸÂÂŚb’mÓąmKůꏼȫ@>ţ‰˙°ś§řĄ÷Ëçkł­1űŮůj楨ľŸš!#Eü|ćł_(_ý‘yČŇ/EJ6LRÉŞ6ącýœnSÜ^'R>EDň‡†˛ďť÷”Żţ ľ§˜‘ď$ŇN"­úŸbđiž>}ćŸ?ރ‘€w¤ťÉżˇş šŔÄůç€âGzCJń#šŽ˘Í#]üXů?ëţˇŹŽ‡MD×ŃÇy-?irĂâ2ÂçˇËśŠüŃŰřÉ́°łńðB[3‘^ą4î0ŽTöÄP„°ąËîOaaS1Éś‘ˇ˜íŰ˝kPëçsĎ­FÉ=K}ůĺ—i}(~čýňůÚlkĚ~^ŽŃW3E­ýĚ IâÇ׿~'~üăŸjýÖŁ JS/đż ÷œ¸}eĄňeědvÂFGÚ8Š8ž}ĚYSv[Qv4d4ŽąÉŽKĹÇIč‡s mRÄIľ @ŞœĚţt‹8ĺ¤cč‡tŮéţ̈“Ź‚q̓ýЊ“.[0ôOŇG=o“]›;ÉBŹÇ<ٟžÍÁŸ?€C÷?–{ý477ŁŁcç×ܤ<{"oĽţʏP|€*6‚@ęˆ\ŹYžC‡1éÂĺ3~@—q ý™ĎÇďÁʟbĎ Ž€˜vYppgw0éçǂĹl(‚čÚ@q OD85DR űż÷ó˜řQíúyŞBäƉ­X:7mÁîE‹Ń4f4ÚN›ăÁtpđXIkň‡ŠXĺ(~Ä۟Őć ŹXábĆxEëĄj(~ÔJü<Ĺ㟀صtP?ÉuT^ ˛gWšššĐ6f `ŘńEĽM˛ Y6šě,lbc›eŁ´ËhtUvŮ6•?z?™9vv"ž`Vhk&Ň Â"–ĆƑʞŠ6vŮý),l*&jůŔÓmŸÇ‘Ý5]?ĺ• ÷ýöˇ?nÎ:ëĚJ] mςâ‡Ţg0~vžšy(jígnČH?äO?ôĄáé§×tý”W‚8ŰFĄyĸ٠2ŘbEœT›(ô)‚hâCZ9úĚrěžăű8şęů+~HN”âXä;‘ĺ0]ˆüM  Á§Éý4şŸń—\rů“‡ub¤!w”DäŻTh›ŢŽöË/Ářyç mĆ 4ş˘äD ‚ƒÇJZ“Ÿ88ʤ‘HSüˆˇ?ŤÍAYą2ÂEG+ZUŰ@ńŁjńC>`­§NçV`ď ďUˇňyţYŕđÇlp?Şu´ľm4ŚNŸń'şé1hljtË(Ƀ^ĄŒOlrŮYŘÄĆ6ËFi§ ^Ľ]śMĺŢĆOfŘŘډř‚0ĆŇÔL¤„E,;Œ#•=1!lě˛űSXŘTL‚öťúĐsü(ştyŻş•Ďű¨÷ú9gÎ,źä%7â˛K/ÁÜšs1qâř\—SüĐű ĆĎÎW3E­ýĚ Žâ‡źŇCîwoŢź˖-÷^u+Ÿ÷Qďőcf™u0ĺ|ˆąłÝŁ™ąnAáÁœoç/TÚá$8"6ĺ=Ôn:NňNĽTe; ›°ěôވŘGâdÖĹ÷qq+öń¸Öq jS;vОnSÜ^'Rž“ę÷d?ÄËV÷§"NrŹŹĆ<ٟŞ8ÉţTÄŃ̡ěţĚ}ĆŽM‘:şűˇGşŃ׹=ë7áČâĺčÝ˝ŻŚëçŠĘřńă°dÉÓWšÉCî§ĎýôşŸţŕ3€¸ Š"Qq‰4 Ř`fő,˙đ)ż†bMň §V?\G <\? şpý$dčRŻőóTäD u%œÄŃ őŮ*ű3„ ˛7üľţaŕ:JH^¸~2táúIČĐĺÄ­Ÿ$ 'ˆč¤V)ćş‚‘ΉřQŕ:JHupý$dčÂő“Ą E““@r˛W}_1!ؓůƒŔu”=\? şpý$dčBÁăäCdŔĄ ×QB†.\? şpý$„ 5(€B!„B!dŘC„B!„B!Ă „B!„BöP!„B!„BȰ‡!„B!„B†=@!„B!„2ěĄB!„B!„aB!„B!„ {(€B!„B!dŘC„B!„B!Ă „B!„BöP!„B!„BȰ‡!„B!„B†=@!„B!„2ěĄB!„B!„aB!„B!„ {(€B!„B!dŘC„B!„B!Ă „B!„BöP!„B!„BȰ‡!„B!„B†=@!„B!„2ěĄB!„B!„aB!„B!„ {(€B!„B!dŘC„B!„B!Ă „B!„BöP!„B!„BȰ‡!„B!„B†=@!„B!„2ěĄB!„B!„aB!„B!„ { –v„B!„B!C+͂W€B!„B!dŘC„B!„B!Ă „B!„BöP!„B!„BȰ‡!„B!„B†=ľ@ř–B!„B!„ÔƒšhśŻÁŐ.y„B!„B!ƒEĽ9TĽ?ÔúŠ „B!„BŠ5ŐŞ˝$DXćB!„B!„ŘRs˝Ą^Aŕ­1„B!„Bą#Ş!ÔEGĚ Ââ{Š„B!„BąÁFG¨Zgě-0Ń č*Z!„B!„BHš,ÍŔ¤5ä˘ˆP,G?%!pĐqB!„B!„„H­@jđE¤žeĐ"ˆ’|ՌéŐ3ÉűvGl-juą !„B!„B†R+š›€ůy˘yő‰xYůyďš)_í‘řë }}ýŤęőźUB!„B!„œŠH­@jˆ *m!JUĎ ÉsYFVBó˝'€ôöö>M„B!„B!Q¤V 5¤Ż ąŃŹě})ÉŰ]B…&üČô­]űÜnŁö‹EB!„B!„H@jR3pűŕkQM!ů<A=¤ZDhŇÉËUdzúúú~ŘÔÔB!„B!„ŠH­ŔMö "~dÝú’ëy*lUA"#­p(€ônٲánăx!„B!„2‘ڀÔ¤Vŕ.ö"~őG¨)ŮÚCnAD'€˜ž¸šĚ‹V0uLWW×ÁăÇ{>ÓŇŇB!„B!„Œ\¤6 5Š@}ű PC€üE ÓĺŽ"ílœŒ´Řˇo÷ćŠSŰG766^Đ××B!„B!„Œ,Z[[ÝĹwV­zö[nâ˜űé>áEáQ“ˇÂ$Ÿ ’‹<HtŮA\ŕôBH™={v=3cĆiӋĹâšA!„B!„‘ƒ?î^ž|É'ŕ‹ňö—¨ř‘|*`÷v#6ä°š D•ç(ţzŰľkçcííÓÚFuÁŔŔ„ԃ\ !„B!„2„‘Ďühkkƒźň#"~„?~˛Ţcső‡V\Č+€D—¨ŻIúˆÄ˛§ęěŮłëéI“Śls՟‹ …BŤA(„B!„B!Ă)|477Ëg~ěďëëűŘŞUĎŢéfwŁrĺ‡ü  rˆJřH’űę‰S…ęʎä§Iƒĺ†Hş1HˇŒ3fÂěŮgžŠąąń ýýý“Üä§T*Q!„B!„BN!ÇAĄPˇš„)|üp˖ ßx*Żüđ^–‚Ęm/Ń[`BŃ#ë  Ę7ÁŘ IŰź"H!ř)†4Ëżçž{ŢuŁFşŹĄĄxžÎ,ˇß&ŔţU˝„B!„B9y”„ŔAÇ[űűVöôô<łvísŔ;ŽŁňś—ŹŰ^ę&~HŞ@˘ËŞ7żč„PřP‰"ň*‘ĆŕoŇ×tŤ !„B!„Bę‹ęa¤ŃO(^ČŤ:úPšĹ%)vD—m…ĄŠƒ‘ؓ|–G¸MG)!.^„ ŏ°áŃ+EÂŤ> ‘|@-‚B!„B!äÄ%Bń˘Y.%ň“ozщ5?$y0°N1QŠŘ‡Ÿ¨Čځô•#ˆä‡P !„B!„BNŃă˙R"˝’ˆ Ń´Iô°šíEľŹĽZÁ敷şŰbLĎ âŻc(›B!„B!ő#K€ˆ^’üks‹‹Íƒ?$ƒMZ%€$—Ub ží%Ť,Ő2!„B!„Bj‡N€H %EÚFđP Фs‘÷˜$Ń[bLĎÉş}ĆQřÉt¨%ŻIŚuy„B!„B—ź$K ą=jvŐG”ZŠśWƒ¨ňTiÝ­/ŽE!„B!„28„E~Ö­0:C%vÔüޏ(ƒ˝$JžŤA˛|łbD˙&ÓI(‚B!„B!ƒGX~'Şřk˛AĆrŐÔC,Đ=ŸĂäߏ2Lů„B!„BɏÍ Ńĺj˙ębքz Ž!m#ŒčҰČ'„B!„BČŕÉs+L4-,žÓĽkF˝…ƒ˘œÁÉą<˜WÝR!„B!„BjČů˝í•'Lüœ(ŃŔć Áƒ"!„B!„2t0] błœ•WSŠ8qäy~…B!„B!dčcűÔźś5çD §ßB!„B!ääbűĘÜ<ßՔ-€„œčçyP@!„B!„B˛Šľ‘÷š!uçd !y„ Š„B!„BČĐ#˜q…“-€„PÜ „B!„B†/'Mř*HŠ!„B!„BČŠĎI=˘ E$ B!„B!dč3¤$§‚B!„B!„2(@!„B!„2ĚĄB!„B!„aB!„B!„ {(€B!„B!dŘó˙R›71“4<IENDŽB`‚kolunmi-bazaar-7b9c8e1/screenshots/flathub.png000066400000000000000000004625631514314607700215750ustar00rootroot00000000000000‰PNG  IHDRT"@!—-tEXtCreation TimeTue 10 Feb 2026 08:23:00 PM CET䍁tEXtSoftwaregnome-screenshotďż>dÜIDATxœěÝ|[ĺš?đG’÷śÇŮ{ď„ě˝H„ máŇŢŇAé¸Ýˇˇ{Ýś—îţ;č -ĽĽĽ@;@„˛ČŢ{ىăďmKţżżG:Ęą"yŰú}ůkžstäX:?=ďóF…$Bˆˆˆˆˆˆˆˆ($ TˆˆˆˆˆˆˆˆBÄ@…ˆˆˆˆˆˆˆ(D TˆˆˆˆˆˆˆˆBÔ‡Q¸Š—nŹ;† Pˆˆˆˆˆˆˆ(Pˇ XşKxÁ…ˆˆˆˆˆˆˆZŞËÕŽ2BY?C""""""˘Ţ/”°¤Ë‚•Ž )mź˝˝×GDDDDDDDí§˝ƒŽú6ŢŢî:;hptŔmDDDDDDDÔťÔwŔmíŞ3ƒ Gׇr_"""""""ęęC¸>”űśťÎ (Zš4wšąëˆˆˆˆˆˆˆ¨whIpŇÜĺĆŽkWP„œ8Bx\së!""""""˘î'Ô~(ő-8ߒËíŞŁCˆ–„'- TX­BDDDDDDÔ;5WaŇÜůPB–vӑĄDsáHSׅŹ4u=u?-éŇTxJ°Ň!ĄJGĄTĽ„úłąu4w=u˝–6’­oăĎŚ–Ů.Ú;€h,řöł-Ą §X&""""""ęYZ:ÝqkB”–,Á.ˇZ„´ŸŚ†é4¨;ď ň˜`˗\ODDDDDDD]/”Ą>ÖOí2NiY0bÝ×žŹ–>śYí@´¤*%đ|cˇ9ƒ\ď ˛6Š%""""""ę™Zڄ60HąŽkŹ2Ľ^ZVľ"\I[+TZZ•ŇŘĺŔ“=Ö!îCDDDDDDԛŤąŸŹ ¤Îœj}?Ýś“SŽ+î€exYŸ#ŕ|ŤB•śöPq\×\oW”üÜ´é­Ĺ“'O˜—09**b¨ÇSŸ* ‡řQxđ8ŽÂššş e‡:şkٲĹo‰7XŠňý´‚+ŔyŤzyB°`%°)mH•)b{p¨÷kIĎ{˜bUŁDŘÎGúÎÇ.[ś,őńÇ˙zO˙ţď6J!""""""" Â,W._Îyňžűţă‰M›6šŤ*Ţ \ą*Uęlç[ŇŔ6XO•f––*Í őiŽáŹ=L‰ŤĂzâöďßÓ¤I“>Ë …ˆˆˆˆˆˆˆZ ÁĘáÇ2mÚ´ÍĹ š:Čd…*-m\+b“ÚP•ŚŞS‚őJ Ś`xOl^^Ţg““Sî"""""""˘V(..z<==ý'â­TÁ0 `ĄŠ5 ¨ąj‘VTŠ4¨„Rl+Hą~"L‰+..ţfllÜ-BDDDDDDDÔ••Ď%''Sź•*V¨â–† lgjs•J( _ƒ5˘ľ.Űoł+ö*m>‹Ę†)DDDDDDDԐ1 k߄7âÍ ě™„=ŤizáĎ&ܖY~ŇxŊ˝Šż:eďŢ˝ë8̇ˆ¨sÔÔÔHuuľÔÖ֊Çă꾜N§DFFJtt´DEE …YƒÉŽÍ˜1ăYiX…be¸lĎ1ěÓ'[—CŇT…Š#ÄëŹ ĹZŽ=P‰\ştię”)S>#DDÔĄęęꤸ¸XJJJ4Pa˜Ňýá5Âk…× Ż^C"""" 2drufa{6!rm•J –^×ô Ňx3ZGŔ†ŤHŃEź•)řŞ->+ëâGúőë÷1!"˘ƒŞ”Sϗ””ÔíŤUŞëęeëéj9Ĺ-nóŽË|"ÖÇ% FEKtD‹Ťe‰ˆˆˆÚMnnîÃú­9[nN5âíŁ‚€{Š6Šiź—JĐę•Ö*5Łľ7˘ľúŚD›S˛ůśm=§G&"ę8¨j(**ę=RRR$"˘ľŁs;֟ś–Ëă;+¤˛ćÚ ¨Ř(§Ü7'NŢż ^ˆˆˆˆ:ŚS6ŸŸÖšłĹćT-×N§lŸń§ĽÍiƒ*Ą4Ľ Śąé“ ÷Ů´é­ů Sˆˆ:VyyšPďŇ]_Ó˙}ąDŮR4L\Űq?"""˘Î„ě„öŹlŤ…ňľWsp›ýÇ5iŇřŮBDDC}Đ|–zźŚxmťÓĐTŚź|¸Ň99Ö)ßš-M掌–>ž/ťĎWűoĂý†¤şXŠBDDDâvťý&ŕźŐçÍů].—żA?Ρ•/ƒŘ$ÍĎćSoű)×7Ťą •ćRšĆ“Ŕéˆ4P‰Oœ$DDÔađćD˝SwzmŃ3Ă|ěî_˜(E•îFƒűăqDDDžž”––JaaĄTTT\3%Îă:܆űŕžxL[ř2$3MevĄf Ş%C~{Š8š-đ: 1Tˆˆ¨Ă°:Ľ÷ęNŻ-Đóybg™üŕĺâFƒűăqDDD~ŞŞŞ4$ ĺ "܏Ác[˗AŘ‘ćgđiIŢŃ@[{¨[É5Mk=žúT!"˘ĂŠ‘{ŻîôÚb6Ÿ@9%̓ěqDDDÔťĄâ¤ŹŹLZ Ĺ2Z×AöL ľ*ĽYí5u@chiŕ†ˆˆ:ŮącÇĺŃG““'OJßž}ĺ†ÖČmˇÝ˘c]ᥗ^6ˇ˙InźńyĎ{Ţ-ąąąBD=Ëţýä˙ř§ěۡ_ŠŠŠ%55EŚM›*wß}—L:EˆˆˆB…ę’Ö†!vX>wĆÄÄHˆšjobÚ<&š-AGKĆľ9ń!"˘Ž0ĺsŸű‚lUTTʅ ™ňťßý^~űŰßűďƒŰJKËäÉ'˙!üŕ˛aĂFVËôbĂú\Ű$.1Ć)}â˝'đ3.ĘѢÇ:|řˆÔŁ /uŒO˙á"ůČÇĚżÝ×$//_‡˜ĺććéĺř¨üčG?mó8v"" /xßhKeJ ,Ť ďE-É%Z[´W…J v›†ˆˆˆş*S‚˝y=˙ü rǡIFFż×ʏü3sű‹ň‰O|LƎtš8`ťůćۃކo ^zé9yřáßČsĎ˝ ˇÝvŤ<řŕ‡ĽľJJJä]ďşWĎżřâłmęƒÎóç/Č׿ţY°`žôVŤWŻ5ű­T’““ä•W^jpۂQŃĺlĐGĺĄ;Ódöđh=˙ŰÓäé]ĺňĂWŠüˇăţł†8dŢźEzůÉ'˙&Æ]ŰZíŤ_ýşdg_–řřYťvÜsĎ{ĺěŮłňýďO–.]"Ôţ~ň“˙'˙üçżô[ż÷˝ď>šá†Ő’žžn•\óÚo?˙ůq šŕóŸ˙L(‹–^xŃ,ű} ].§Œ?^Ţ˙ţ÷ÉěŮł¤;°~ż~ń‹Ÿu›m""j-ë=6Tۡo‘ŽĐ•)Á–™˜˜(! ěďÚîÚ¨4×ԅˆˆz( ó (gΜš&Pąœ8qRžöľošçżJsFŽ)QQ‘ţËNgŰŚÉťá†uúó|D :„)P\\rÍmol|UHŮrő[§˙5żÉĺÝ7'N˘#š˙hđŔ֊§ ć u<ěk+LůŐŻ~.“&Môß6hĐ ůŔŢ/sćĚ6áč§4TY˝zU‹‡˙üţ÷ÔôUGťw{÷™ç‡ćƒ˙\!"˘Ţɚš˝a™qqqmRšąü˘ŐCÚťB…a Q/ž)ćLŸ>}¤1xŁťéŚľŇ_úŇdȐÁBÝ*V‡VŤüâż’G!™…ąňňáĘf{äXy˙‚ř ăAU NmU__ŻŰŰYëŠŹĘTŚŘÝɓ'É{ßűňČ#ĐđĽ%J]]VśŔżřßZe†}‹ę5ŹóńÇ˙ÖĄJ¸˝ŽDDĐQ•&­Ń\˜‚/ż&Mš$_˙ú—%99YŻCEńwžórŕŔAyůĺš\6B•6j×7‰ÖöP 6•ß˝ˆˆz4  CyFôś3Ś™oť˙Ÿ¤ľ7ź‰ţéO–űîűOšůć;´gËOü]+fňóóýŐ)đ|X~đƒ5xüöí;äĂ~PűÉO~FNŸ>ăż Ăyđř­[ˇůŻűÖˇţWŻ{ňɧ,ăxżóďÉwÜ­ŰđĆoJo†ŠŤZĺʕůĘWž._ť)I>ź(A‡óƒëq;î×R‚’ĺ7ßÜÜŕúŇŇRź}EVŽ\-wß}Eą żóóŸ˙J>ó™ĎÉ…Kľ÷áýć7ż“[nš]–,YĄĂ6ŤżĎëŻoŇÇ}ôٟ_ţňײlŮ*ůŰߞ‡úĄ^áGÁś ĄBo´€a>MYłćzý‰ę’–ŔżS+@Ăđ-@Ŕńą}ÄěăżČ˙üĎçý÷=zô˜ůˇřiYąbľ ao‘/ůŤ’™y5ÄE8ňâ‹ëĺ=ďšO/^.ëÖÝ*ßűŢ÷u*M(**Ň×§_×eü÷˙Ţ†ßƒOúł˛jŐ qýɓ§ŽŮŢ .ȃ~\–.])ˇß~wƒß/"" †v7Ă~>lŢžb>_k˜ňĹ/~UÔćždknŮ!–a´*ĎhĎY~ˆˆ¨Ál>99šÚ3Ĺ:E˜ňĽ/ýżÜ2)É;–uŔ€ňĄÝohHGÁ7ďźłK†&łf͒;wĘc=nŕjäÎ;o—ëŻ_Š4aâĉćŰőÉ ˙ýď˙Xú÷ď§w–ôíoÇd˙Ţ?cQKýńIZZšddô÷őřřĄî‡ëŽ›)áŕŕÁCúsqFŽÜó‰˛őtľN‹ěŽq9ź hŃkĽ%Ă|Zýtúôék~ÇĘŠS§äßř–¤¤$ËÜšsü÷yţůçőç„ ău ̡nÝŽCĘć͛gÎo•ßţö=ŘđÁüĂň:,ŁG–ÔÔ4™>}ş<óĚłňöŰŰôžŃŃŃć5>§ŻsTT”ů[%˝fóôLiJż~ŢĄ}……EŇńńń2sć ŮłgŻžVŻźňŠZźx‘y=Fřď‡@A&*ZćΝ­%âşô xIII‘żţőoxĽĽĽš`gľ?~Bž{îy}=yä7 ÖűƒüPúöM—Aƒkp‚†şv&L˜ ˙ćßzëm]öŸ˙ü'óťÔß˙8„rýű÷—ŘŘÉÎÎÖż &Œ“ĄC‡ …Žšćąßýîˇĺ _ř’œ;wNCüĆßőŒŒ óYď[mZvˆÚe–ŸŽjJKDD=‚†~ô +NŸ>­Ă|FŐ €¸˙ţ˙ԃĽéÓ§Iddd¨ŤţđÇzĐjYľj…8sď˝ď6e eٲĽzpűꍴŠćŽďhłËĎ}î3ţ@ 4ŃCßzX>őŠOČʕËĺ̙łćŰň˙Ұ(33+hƒÔŚLœ8^žţőŻęyôŠAȃĐ)\ „ď¸őVłOWĘg?ű)é(SŚL6ĄŐ˙éůĎ~öó”`čˆ=PINN‘?ýé÷’ŕ­ˆ¸˙ţ÷ˊË5Áď¤"Ű˛ekƒ@ĽźźÂ`?Şż×–áÇë‡ćЧţa‘ɒ%‹5¸?~ŹůÖrˆ¨"A¨g˙ˇ ¸˙]wÝŠçżň•Żé˛ńšYż;ßýîCâ ˙“=PšéŚĺŤ_ý’6;|Ď{ţCg8Úšó*DÔŁt§Ś´ÍÍöˆ!ĺ?řÁ˙ůCč×/]›Đ#Ti˲ť""jJňϝ;ŻĽ÷ř†Ck DDxß>0Ž3d` °cccCYźVŠŘ5ÖËp {úôYů˙ď& ÉÓꨭmŮ4ťłg_§?ń-9śł˛˛˛U]č—,š:ă fŸA rţ|Ś„›1cFë›§žzZŢőŽ;eđŕŽé…ƒŔƲjŐ* TΜ9×ŕ>WŹ00$ M•q€Ž™ƒPف˝\† Ö LuëÖjUÄolŇ@Ĺ énžyô&AńÜ0Ä hóňËŻúďßR¨.ůć7żŽ!çΝť4œÂ”ęXţv|ă_ÓŚ¸đ÷ż?Š'ťóçĎëOüNáßü_˙úwšx1KĂP Ęží WŽ\á?äČ1ßuWwžň•/ÝVkĆ.ü-7nŹ*˜&žˆˆ:Ţ ˘˘Ž~Ą†/ĺ"#{f4Á@…ˆˆ‚ÂIZ¸pž|ík_ipÝŻý[= ůřÇ?*Ą@Ů~KšŇâŕéӟţœN[Œa¨ZŔÁO(=-ě•5Ngđá(öo>ęęZ^VŽ=0ą?Q•ƒŢřFżŁ•`›ŽZŕwĺƒüˆ–ŁŠęŒ3tz¤˛?΂ŢA?ü[ŮśmťV4 ÇfŞ™5ë:éMîžű. 8Đ@!)öU T‚üĺ/ŐýmU4ěŰoż­C¨nźń­ Ă hżöľo˜ŰśęýŹ}˙áĐźFÓ, |˙ű?’gŸ}N‡b8!L Ń &ŘkŮ˜ŇŮÂfśDÔSu§Ś´ř|ĐT% ú`}ń‹_ŃĎtÖg@T ă:TŽ¤ŚŚ6šěîŚűmu řf9 ą „>&8ľ7Çj ŢxQúӟţHżQďׯď5÷ˇˆBmZfUÖ>|Tb8ÁńăǃŢwÓŚMúU;›6yҢŻK88 J§ŁlŘŕmŠým5jDŁ÷?u괆)A~˙űߚďAíÓR(Ež?Ž”––ÉcýYŻĂ°îř!Ž-0cB4đĹÔČřĂŁrńâE­âÉĘĘŇiq=zÉ$''ľx6.TŤýâËwżë­đÚ9âýˇ…7€`°|ô\Á MOœ8á˙–ĂúŕᇎĂřĐăŚ%0,6nÜčżMŚßýî˙čőM¤‰ˆşZsÓőŤßô‡)PpÂy„*_ůĘ7Ú´ěŽŔ "" Ę 3Y Á:` T őAHýüçż4ßGĘý÷ż/äá?vVŁL ťŔůe˖č-z>üô§?7ëpÉćÍo]ó8ôF¸t)[ž÷˝‡´‡FK§áĹpĚ ňď?#{öě1vW´_f¸ „á#űŘ'őŰkěď-ˇÜ,áhölo ˛k×nÝ- žúŐoh †azÝĆŕ@ü˝ď˝_—^>€  1h`Ší@ôÍ@ĺÂkŻ˝&Ą¸éŚ›´1퍯nԐnÝşĽ7úô§˙KĂô¤ÁÔČ8Ůášcęď<‚ 4dn *]0źîwvkcX„ mŹK÷Ţűýůž÷˝W{Ť Bá%*ÜŢ|ÓűozĘďôĚčۄpç˙ţďű2zô 0›űćŢ˙ţ˙Ô&´›7o1‹>ŹĎăȑ#’˜˜ ăǏ""ę8žÓÔ[x/GÓřď~÷[ţj„*SĐ窚ew7-ýş…5DDtňňrý&ßíŽ3ožuz˝IÚ SšbˆEMM­@¨ňĺ/˙~ƒƒ*ôĐřřÇ?vÍă>őŠ˙Ň&ł/^ňĎFÓ8ČCS„@˜"řŢ{ďљ„‚ůđ‡?$éć€=G ¨M6Cé/ћ ŔÂPźîčˇÓčm‚é­Ssžţëż>a֓Ą IјôŰßţf“ĂoĐĐ3 ? †­Ą×Îç?˙9 šŁ*0Ź CNz#|ӇĘ ˝ĂôČýôĂ*B4ýío6ĄécúÁá!B•‚‚‚f—űƒ<¤Udx 0›†Ď!hA3g4ĄT¨üú׿ÔđĺŕÁĂÚCů°-V/Ľţđ!™6mŞ:tÄ$[4Š‹k>¨EH‡mŸ3g–öcÉĘĘÔĄŠ?üË i‰ˆz k ůPOÁ>Ů@0/żü‚ôöĄ=8ëp[[–ÝÎZ”8Zp˝CÎӌ“ÓöÓ:š|§ß _?!BJ1ˆˇ u4‹moßűŢ÷ƒVDFFÉóĎ7ě]‚Tđ sGÎöÎ0 ĽłŘ?`aLśu9đźĺ?řąüë_˙ÖŮs0ŰRo€ŞŰożK._ÎŃćŞřÂB”O|âÓ~7N{ěBDDÝGwšĺJKKuHg{B˜’˜˜Ňc˘˘"ç™E愒ŒMŻóÜž“ÇvŞˇý´ŚSśŸ 2Í2‡üQP‹--[ŢžŚź~ɒ…×Ü7:: oZB=*3PĽcUhX?Ď[Ṕž2 ńŇ<ôĐľÚa *b0•w¸Ă0Ÿ_ţňgňšĎýOHýhˆˆ¨st§Ś´€/ŮÚ;PÁ2ť#V¨őQĄh†’y|c˜}ĺř˝2ĐOĂâă{ÇAuwә*á YQ™RYYe~Ď'čpŽAƒ …ýłĐ¨ź=$$$ř›š‡˘3*T¨ő¨P÷Ŕ@…ˆˆˆzšŠŠ =ľ*SZ[Ň §M&"ęz۔Žt_["""ꉄ ş¤ľđŘî:ÔÇÂ*DD˝fćh﹪Ô=tÇ)‰ˆˆˆZCuđY•*-ýʊ´R0œźťc BDÔ ŕ‡JďÔÉSľ+#˜ĄÇjV[[[+nˇŰ?ńŞqq/řÜÓ‚ "˘^ **J߄đE˝^SźśDDDD=‚’î>„'T˜MDÔKp†Ţ‡Ż)Q÷Ĺ@…ˆ¨—ˆˆˆ¤¤$ĄŢŻ%^S""""Ꞩő"’’’ÂFŚ=^;ź†ęCDDDÔ˝ńŤ/"˘^U ÉÉÉRSSăoüe5ý˘î ÍŘŹFl Rˆˆˆˆz*DD˝ĚypNDDDDÔ1¨…ˆ Qˆ¨…ˆ Qˆ¨…ˆ Qˆ¨…ˆ Qˆ¨…ˆ Qˆ¨…ˆ Qˆ¨…Č)DDDDDDDD=ŒĂᐈ—ţě ŹP!""""""˘!J^^žäççKßž}%=˝ŻÔ××Kgb… ő((JA˜řŮE*ŹP!""""""" """""""˘1P!""""""" """""""˘1P!""""""" """""""˘1P ĐŮóVőŽŽ˜›¸c "׆( UˆˆˆˆˆˆˆŽB˜b?Vf¸おý—Á:ďńx‚ŢNDDDDDDněÁ‰Óéô_g/‡s°śŠőâăg]]¸Ýn=á˛ő3đžDDDDDDDáŔ”ŕźËĺň˙Ä)""ÂŹ„k¨vJ`RSS#sôˆ¸Îœ‘úěl‘ŇR”ŞQŘs:ő˜(2`€¸GŽ”ę Ľ"-M˘˘˘4Xą„[°VŠŚ ĽşşZ\WŽH⛛DvíňŢ.DDDDDDDԀÇ#őĹĹ"ćäkY! ƒęH TˆˆÚ‘ýíܤ PXĽBDDDÔ6N?Q!<ą>gك†*Ôިľ“`aJ˝4Ź0N!"""j‡ís–˜hxb‚+Xa¨B… Q5¤ÔŰîcżÎ~šĽË'""" - >Ź Äě˛ůŒe+bŤVá jO TˆˆÚ 0L ¤XםO°ĺQăüaˆ-(qŘŽwŘŽ VX­B퉁 Q+V™x‚)[€°4UÂ€…ˆˆˆČŤŠŕCƒ_P˘?m×9ń3 XqÚÇP…ÚŠ QˆŤJ ¤xBŻdilůDDDDtmđaćc…(NiŚh`ŹxŹ*ßO˘ś` BD‚ĆÂ+( RÜžŸß}ôvßĺk–'DDDDÔGóV`âô…*Nßy—ďg`°âÄç0˘vŔ@…ˆ¨…‚…)×T˘řBëTçńˆoäNóö!ߛşżŞĽ‘€ôű›|ŕÔÖˇ* ˛îgßŢĆîÇőp=\×Ăőp=\×ÓSÖăxźżBŜ4(ŠŤ‡ůüĺ2§óůËĺ V\žĎ`Nďý Cj *DD-В0Ĺc QjqÂy\#ŃÇKD˙⊏3ďäNďňôńřŕý–D?,8œţ5ęEńÝÇa­ťáuzYĎxüߴؗ)AÖ#žőx?¤×âzZőúXżA\×ĂőôŞőđď(¸žÎ_#Č2ő:óŮKĘ+¤îrśT;'ŽŞ*‰0÷‹4ˇGâłÂš a >ť1TĄś` BDԌzűůúŤ!ŠőÓ RÜž Ľ?͛˛;5U’-’„YłĹ• —ËűAÂÁˇi"""˘v…ÔŸĎÜnq—•Ié;;ĽäíˇĹ]T$ns]„*N§˙! U¨­¨ľŚÔ SŹŞ”ó†])ŽQŁ¤Ď k%fčP‰HLÔŞ""""ęxřěĺZžBbF–˘W^–šS§¤žśV?żE⥊ˇJ¸a¨BÔ TˆˆBdUŹÔ[ ú¤˜Ÿ:Ěß|˜0%mÝÍk~:Ł˘„ˆş/ Hëö3 Wţ^<˜ ˘žÎ|‹HN–¸qăÄ!/‹á3YŞůl–“—'uůůޙĚß9k¨UÂ*j *DDMhěđĘ>ýążwŠ9Ÿ4žóa˜BÔ˝a<}eeĽTWW yŐÔÔHUU•ÄĹĹItt4(ˆ¨WŔg2|6K4ŸŃJž{Nœ˜ĄŠÓۈqş+Čß;V­PKpP?QT§ř.c¸O=šĐĆÄHňœšŢž)DÔm!LЍ¨ĐBŐNyyšîƒ"˘ŢŸÍđ ŸŐô3[Ŕg9ëłQ¨XĄBDÔJV…ŠVИo9˘GŒĐŮ|؀–¨{CX€Ą> ‚Ă~AĽ †ţ`QWk8DÓ­§Pa‚żQ‘˜  šĄŠčqg>ŁáłšűÔ)]žUmĚŮŠ-ř.IDÔ ú§ŘŻł.ă ˝˙m|FDÝŤ/š‡pu%ü­F‚á™SđwÉúű×áo:ú?áätşÍGžĎjľçÎI=Ţ$Čg:_Ŕˆ…ZŠŸü‰ˆšxŕeŸÄr8řňˇř €“Ă<>&†= ˆ:ƒýy{Áň0Tڏ¸X‡aŃŃ1’’’"ńńqú jOŇű¨¨¨HňóŻ[ŇŇŇôDDÔ„)ř›ŹŞĐú fUŻŕgLLŒVŤ…ž)ćł>ł]ó9Îwť}ŮüLF-Á@…ˆ¨ Ž~ťQߪĄ>ĹĹ%˛eË;vʌ?ŽoŢD #ŞSĐŕvëÖíúďů…Lómjddô“9sfÉňĺËĚů -OˇŘʰ֎Żř–ľ7ţ-xőŐ ňĎ>cžw­Ü|ó:ůĎ˙|oŁĎűĄśűÇ-h ‰@ wľ‚ž(6ţ&ęPÍf}9ö Âú[‰ę‘ČƃŽFŕß{caJ k¨"ţÎ"Tiôo¨ţnXqLÔ TˆˆZĄ˝Ţ„KJŠe˙ţkB•1 ¸ˆ¨gŔů^xQöí; S§N‘řC+G“—_~EŤ2ţă?î‘>}úř“ŸŸ/6l4 Urď˝ďÖżo˝őśde]”ťîşĂ\ŽéuĄĘ+Żl‹/ęţzůĺWĺ}Ń瘓“#ۡď”C‡k…ĎŞU+5 Úšs—ŔÝvŰ-BD]ďňĺËňӟţ\?ˀÚ~Řw&Ož$Ÿţô'ečĐ!-^.–a>Vż”–>ĂŔ†Ň˙‰Á ľ"˘6jĐK%DĆťÍö* ę‰đÍ)BwŢŮ­•(T\.§ âľjeîÜš ěÜůŽŹ]{ƒ˙qUUŐ¸ šeŔ€ţ˛dÉ"]ÎącÇĚ7˝˜}¨Ţ¨äč7´))ɒ(gΜ‘Aƒę4\Žs}ź\ştIŇÓÓ%99Yş3|{Œýĺ=_Ůčýđœ˙őŻgäôé32oŢÉÍ͕˙űYšĺ–uröěY)++3űy˛.kŕŔ:Í3ŽËΞŹŐ/¸Ë¨ŹŹ2U.IJJ2ű6Kúö퍥5.ě/ěâ˘BÁąZZZŞ^GDĄÁĐ˝O~ň:Üą1ÉÉIćß_ ÂT˝ŘĂŃżţőďL@ýóˇ/AöîÝ/§N–üA˙}ʊ™Ć•ś|f# † Q'›<†ů 2aĘŋ—¤  @?$ŕŕĺ°řfF8 #˘î őř@ “ŃŁGé7˛{öě“čč(ý÷irǡű‡_QËŕß ţÝŕo`cĐO ˝âBa5Łľ*řۇő‰'žŇ€!ęu×Íú8˘ÎÂ@…ˆ¨á€â­ˇśčžEA˜‚FŻ˝öş?~B?,`XŔ˝÷ž‡ Q€Ŕ٤¤DƒPPŕ›Ř!CËůódٲ%Úë˙– Ży,n4hƒŮśmť ^Štyř›đÜsĎkEV<äknŻU-cQ•‚„xLwmz‹d÷î=ţËÖ°FüD źsçN ˘ěťW_ݨĄnCE *ęë˝=T-Z('Ož–;vJNNŽlÝşÍ\ˇ@”‡ţî+źŰśmÓżťŘ§G×ćßx-PńsŕŔA ĽP™‚JüM&˘Đ Ň !ĺĽKٍŢÁď=÷źGĂËPÎ4†0eíÚ5ň“ŸüĚü]Ů-+V,7aóŹ÷ąšÔu*DD­Ôš’Q|Cƒo˘ńĄEyyyňúëoČĉdҤ‰úmljjŠ8Q÷‡` 55UƒTc`H†ýŕ8GEúň~ł%ëÖÝ(/ž¸^‡śÄĹĹk@ƒę Tžŕöôôž˜ Á–-ok@€ŕ}F° o ‘(Ý‚ „AxnŁF4ű¨\xp˙p[`„`#č%ƒŠ]ťvË˙ř'ůČGĐ2ţ!C†Č„ ăeřđaćöjšrĺŠ>nôčŃz–×U1¨dÁЀ ć›oł/éß]ź6X>*†Pق€A̒%K4„a… QËáßڜ9łőď‘ţýÔëO €JźÖ|Žą÷cüm@…ţf¤Ľő1_‹uvľ`k ýĄöŔ@…ˆ¨áŰQŒ7V/c˜Ď‰'5LAÓE,ŕƒ›Óő ¨2AőÄ3Ď<Ť80G• ŕ@`ßžýröě9­¸˙ć§N*G5Nk5z} XE ˜˜(ĽĽĽ2lÎ'É?ţńO=č_˛dąěŘńŽYçšĺ–›şmE ”ä˙îwťďžSfΜŠ}N†.O>ů´Üwß˝ţýeÁ0œż˙ýi \ćΝ#…žż‹Á’đí7*ü6lxMƒ+לPy’˜˜ •)˜UëCřrýőŤô †RaČ%zÜ ôÁ~çß_˘–Ăżq ąkŞqlk>×ŕ16ižƒ€úÉ'Ÿ2aë2bÄpYżţeyâ‰'ĺk_űň5#ę, Tˆˆ:Ţčí,đŚó¨LÁU(]鉨ëáŕUďyĎťĺůçŸ×đdŢźš:CuĐ×}TfÎl8Î?>>Á„/4€Át˘7ܰFjjj}=SRľÉ#Ş'ĐLl¨Ę@Ÿ, !ËôéSőo Ö:´ŰůÁv1BŤAгĚÎ}f–.]ŹSĆn;ŞrŢűŢ˙Í›ßŇ&´xĚý×ÇľŞĄšxăoĺ°aCM0Rf›™ş̚„ž úĐ´/ ‚™ůóçéO܎ʔźź|­ÄA ďÚľGĚ„Jţ & ţMţć7h¨ (Aśbý M|đÁ›đs€„ěłü lţöˇżéŤäuÉűß˙žkšúă3Uwý{H˝ß5ˆˆBԞĺĄ8čBé>>°Ěœ¨çÁ?[|°Ÿ|Dƒŕß7Ş!PÁ‚ÄCtđ-+ŕń8P@cY”Čă`•lŢŮjÜZ‘‚ŢřńŽwÝeú#ľ2óçĎŐę”îú÷ۅ@dÁ‚yZ=ňôÓ˙Іł8ÂAŚDüć—Ń[=dШĄ•U9‚`PŘg+V,ӟX>ö–ŰpaX%žŮFPR[[§U0Z…ƒ34ďĹăĐ?e̘1‚żęj…ĺQhđˇiůňĽüÚŤTě“úőK×ű…Gi űłú!T˙fń˜P§Lśpčľ"˘.„öh@‹1–™uŽŽ˜  !Aaa‘Ěcřî1Ô/ p˛ A_;ôN „ŕ p˝Ýţśa_ ŔČĚĚÔ@Cmš‚Ş¨¨TíOcgßg˜ýČ.p–ěSœť?‚+œˆ¨őđ7CŰţNŁBô”jŽi´÷ţú7‚Ÿ§Â2<ź/bč&~ÖwA2Ć@…ˆ¨ á›eÎćCÔš:Şšć†=QGíŁ[nšYˆˆZš’Ş`Hd`Żk(5ŞÎPĂa{áżřňĄo…b}$*ü#""˘°‚Üöqůt-oo'~ËKD] ‡PĽ‚Ą<˜˘łœYżqţžă6VŚ„/ü. WVWa BDDDaź1$Ç>{5„Ą2œ)ƒˆşŤĂúp ěŐbˆş""" +řFßxVVV6;.?ÜxAFůgă!"ęšPwĹ@…ˆˆˆÂŠŕ'JȃËGVů<œçÁ QÓ¨QŘA`€PcďŮOĹ2Y}S¤ľ """ KV 9Qk0P!""""""" """""""˘1P!""""""" ę–8×B÷Ŕś„DDDDDDÁ1PĄnJ÷řş0`!"""""ňb B]Ş5AJ¸OmŮŢB™ÓÚó Vˆˆˆˆˆ(Ü1PĄ.Ń\$ÂФó4ľŻ [ŹQ¸c BŽąĂ÷ŚěŻtŽŔ€Äţš Wꅡ uOĺĺĺú3&&Fˆ:‚Sˆ:Q°`íö÷ú 'ęMíűŔ×Éţ""""˘îß^šrE Ä펢ŽŔ ę4ށçÍÝNËŞH Ţc˝.öŠVŞQwăv{ô3ŤÇS/.!j T¨S4–ÔŰ~V×ՉŰÜćA5D#ĽŽĺ°ýtš7 —9EGD\s;^C†*DDDDDލP‡kI˜RévKIi™HAąD––Kd­[\ŹPéR–TGş¤6!^¤O˛$'&HŒËŐ 8a¨BDDDDDኁ uŞ`aJAU•TçäKb^‘8˘tNóZD×ÔI´ š<…%R˜ž"Ń}%-&ŚÉP…ˆˆˆˆˆ(°)-u¨úfŽ/¨Ź”ÚŹIĘ-d˜Ň!\ÁkTc^ŤB€AsŻ-QoĆ@…:UbpWÔÖJĺ•"I(,ęÍkU‘_$•uŢNéţ>7 Ȉˆˆˆ(Ě0PĄSßĚmęŸ[ ÔłÄç^‘+••ÍžžDDDDDD˝ęÁŞSœ…%éöő,xͨT1Ż!°J…ˆˆˆˆˆÂęt8đŽqťEŠË„z¨’r} ˘Q¸â,?Ô%j<‰Ş­Ꙣkjő5$""""" W T¨CŘë‡ű€Ű\ˆkĂpŸˆűď“Čűß+Ôzu{JjóihóڕÚ^PkeűĘöŠ•‰ˆˆˆˆˆzůĄNe"ŇÚ_>†)í#âŢwI䃔ְżvöCDDDDDáˆ*ÔŁ0Li_U ľ•*DDDDDDáŠ*ÔéZ[ĎŔ0Ľc´ĽR…ľ)DDDDDŽXĄB]"Ôq†)Ť5•* Sˆˆˆˆˆ(œ1PĄNіƒo†)Ł­Ă؄–ş3ôúńx­ mG%DDDDÔs°B…ˆˆČ¸xń˘:ä­<ůčGĐ0%#ٟdffĘž}t† ;ßŃŞ•ľkoŰnťUƒ”IVÖEAű ””ůÎwž%gϞ“üü|ÉË˓ČČ( kĐ wÚ´)ňöŰ[ľ‰íŋ—Ěr÷ë!/Ö """"ꨨA/L›Ÿ N§S4`Ao”˛˛R ?0t(%%YƒaAŠŠ)růrŽ`ňp„(?ýéĎĺĉ’žžnmkÔě>„ž+›6˝)ŇJ•řř87nœöp!""˘öƒ÷l űĹ{şy3˘öĆ!?DDDFrr’(•rňä šƒęT–ÄĹĹjŸTŹÔÔTËéÓg´b%;ű˛ö[Š­­Ńá>¸U,ăǏ“űď˙OšăŽ;t8ĄÉ¸qcÍu1˛cÇNm~‹Mk­é›‰ˆˆ¨íđ}FFFşôë—ŢŞYüˆZ‚żYDDD":ÄÇŰóä˛üĺ/ӐłőŔŞU+5lÁĎżý-WŢzk‹6˘EUKYYšš‡Ă"NzÁH^^žÎ„™‚Źţ*€Š,wŔ€ Ů˝{6ĽEĂÚ>}úľŻ¨¨Ť_j¸…¨ýąB…ˆˆÂ*E0ËfýąžľB˙“ëŻ_%+WސââbŮž}‡”——Ë… äÖ[oŃű͟?OC•ŘŘ8ˆě6ˇ—ÉÔŠStjd„"#F —ĺ˗jľĘćÍoé @ÇÓŰQ•‚°ĽOŸž2cĆ Ĕéˇf'N0aMźQĎ ęśÖÝt—P×yZˆz/)˙řGĽśśVâââô:ŒŻFČňŠO}BgîAĺIbb˘ @ŇüĄKzz_yßűî“uën’ĘĘ 8p äç_ŃJôUIMM•/|áóréRśYžĂ%‰RUUŠMi ¨˝XŞ$''Kdd„LŸ>]{°p¸QĎĂ@…ˆˆÂz˘ :TĐ(ĂpěŹôë×τ'őWŮŮ`X*KĐlÖ ap÷Ĺ ˇ2ŘôfÁňp_4˘ýç?˙%ű÷Ô*—5kŽ—¤¤$!"""˘ž‡ ….WăU!!Jŕcí%ÁŞK{|eeĽVťL›6U-Z(“&M”¨¨(!"""˘ž‡ Q'Áě?˜Ő †ý`¸‡űőL TˆˆˆDtŘNGĂđžŔ!>ą^""j? ‰ČÂ@…ˆˆÂ +Đ`°ADD-a*C@‰(ü0P!"˘°bPÜnx˙úçËMŢŢÖí' Wö0˘˘ŚQűÁ{ Ţ[ęę*}Á}C˘0Á@…ÂBŸ>iňÍo}YFŒŢŕúqăĆčéúëWʡžů=šrĽ@:BuMŰŽŽŢ~˘žĘšĹÇ[’]+‰‰ Sˆˆ¨Ýá˝%66FJKË„) Uˆz7*Ô륲#Xa7räpůĆ7ż,Ÿűě—:¤ŇŁŚŚFZŤ;l?QOguˇČĹuUUUňÜsĎÉŤŻžj>—J„Ë%úoVËšÍýŃwĹÜY/ă[G|ű¨3™ËQćßg­šŒˇhJinŻŠ­ŃŢśŽď[ŹŰWƒqőzŮ,OKÂ1ÎŢwŮž}&Lœ(˙ůŸ˙)ÍOëqDDÔ}ه˙pÖ8˘đÁ@…z= “1bxł÷C(ąć†UňÂó뼽ŐŐÖIku‡í'ęÉŹ*§łáˇ„•••˛cÇóoćy‰‹—ýűKUuľœ;wNňňňôĂ1 +@A¸‚ŔĄe˝/`A‰7ÂO˝G\ž@ĽŞŚÚ%Ţđ÷ąBNŤQa-`ÁokůÖeÜ˙ŇĽK’`śŠďƒʀ„ˆˆzź×Xď;ŹN!ęýX÷L˝Ţ˛ĺ‹[~ße-żo(đíuku‡í'ꉬo­śŢŠ.ŻBrřđa=?q™>}şŒ3Fƒ}œ§^OwČP=Nś!Dßeďmžëë­Ç4ź˝Á}}˨ˇÝ×~~ËŃŁGĽ°°Pˆˆ¨'qŘŢw„Ő*D˝ęő† Ňâű6T:‚ŰÓú7Óî°ýD=UĂ´ ˙"¸¨ŠŽÖcIII:D'1!Á{Ő$NkGƒáBÖy˙”ËśËţëš˙ľ÷óÝn›Âş •+V5 ő SˆÂ ‡üŮÔKĎ~ăëéŰOÔźßż Á†÷ ö*VĂX{¨FÓi_ ůÁP"|Œv›ű:m=TŹ0ŚÎ×ä1N_O•Ŕ*z?T§đ9QˇĹ!?Ôë˝ńĆćßwÓŚˇ¤#`öÖęŰOÔ[!Č8zäˆüýď—G}Tţň—?ˉ'tfž˝N9Y_Eśôzű¸ziÁňë›Ůö;vJ~~ž^FsęÔi9{öœœ>}FöěŮŤ3ŮázÜÇ:”j"ľÖwäČQi/؞ŁGé L-šďáĂG4„Úż˙€6ěĚÚôď?+ššyţŞĄ@Ř/˝ô˛”””ř}Y^}“œ?޸5ëÂúńZŘ{Ţŕú7ßÜŹ †ƒšxń’ůűžI÷;żÉ&""ę™XĄB˝ŢËë7ĘőׯÔYpšrćĚ9sß Ň""[˙O­;l?Qo…“˛˛2É3Ý.—wČŞSŹj—/ ­ˇM›lŸ˝ÁĺŠW„çęT´ř†ňDř~ZˁCxt§śvą†٧۴†5eëÖ풜œ,}űöՃú'NJTT¤ôéÓDŽ U hšrĺŠOBpgţžŒĐě÷í; ÇÓu^šR`śÁcî/ńńqR^^ĄËAŔeŁÇ –eA(Q\\"'Nđ_‡ęšňňrj”é2üÁÎ×Ö֙ĺUęr°Ý¸_tt”¤ŚŚšP˘HсęţÎĎż˘ŰƒÇ%&&úׁíA8tňäi}ܖ-[%##Cg^B´cÇ;ňüó/ʄ ăÍ6'šđ%__k\ś\¸)ë׿˘űpöěëôů#ĚÁu7ß|ŁÎ°„ç†mŠŠ6ëIŃű”••›çWŚŻś aĚŚM›ýł>ĹĆĆęőx^55ľşŸđÔŐšýűűű-((4ˇŐę˛qňžnľćuLÓ}„Çc;°˙đÚb_qö""˘ŽÇ@…z=|X˙Ö7ż'ßřć— %Fŕ>Ő2Ú|Čn­î°ýD˝z¨XA†ĂwÂĺz[OsˆŤ˝VłXÚc]6!ŒËíź:dÇw@ NmlknˇzŹ T´ym˝Ç?¤ČťL—ˇ§ ś§‰mÇcŠ *˘  @ƒüLIIуđŇŇ\ .˜ŕ`?Ňť!ú÷ďŻň›7żeţvœŐ€‚„¸/nŸ9s†Œ?΄-űőďĐŮłg5Xąb™†<ޞ˛a% f)BŘsňä)çˇßŢŞaև ăňĺ˝nĐ AşŸÜn\ş”­Ő<ö@Qö×;ďě2˞˘Cń<4Ş¨¨Ôĺœ>}ZúőËЙÔŇŇŇ´Šiűö ,Y˛Č쏺­oż˝MÐéÓ§Ę… tß`¨˘9ţ‚†Cx]ožů&ýBő <űěs Lš2e˛œ;w^ˇőÎ;oÓ°ÁĎ믿ßXłŽ×FĘąą1BDDD]‹ …|ăúŮĎ|QnX{˝~ śfĂ9o>´nzs‹Vvtd)mŃŐŰOÔ[YU5ŐZa˘3˙ Š/Đhś‡J}@ëńrmkH z¨ (ą*P{¨Ô˜űăvk=MAĺÂkŻ˝ĄĄˆĚĚ,Yźx‘† 8]ž|YžzęćŔüv]×Ë/żŞ!‚ąëÖ­3ÁŔć‚ë˙öˇżËÚľ7č}r`˙äääčś ěŔĐ ‡šďž{Ý&úŃä_˙zVĎcÝ~°oąŒťďžSÓW_Ý 7Ý´Ö=Éf=oČüůs5 ZştŠbXö=÷ź[ˇ‘ˆˆˆş 8hyáůőzjŁGOIkľĺą–śn?5Ă6„"0Ćœtçruf­Ŕۚ\MeˇäqÁ JÜŁGÖU V „@˜0bÄp­ŚŔp AŮłgi1aÂ8­ň°Ş3ślŮb–áŠÓˇo]Îȑ#5ÔŔvvv“Ű„`÷šp!Ë8ŻHQQąsAŔ€uŁ"ĺäɓ:”qďŢ˝Z9‚Ł˘˘\Ť422úérP93oŢ\ŞźŞÁɌÓĚKtľőŞQ˛˛.ę°XoLL´ěÚľŰ'LąXƒ&„EX&Â(ž‰°—=žkŚMĆP„QÓ&[˘Ł"$-ŐmÖĺ­Pńx’_!•UŽ*–ßşš‚†×芁ƒń˛˛R=ˇŻzqXý7œÄÄÄJZZŞF˜““Ť˝E°îž}ÓeΜŮž ß‚ „VogËźMYëü aą~ô;Á˛ą,TŞ 4P׉pŐ1 °l4QćΝc ďöŁ˙‰Çăíقeßxă :TA ‚TŁzł :Ľ_żt"ƒeXý]t ša ~>TŽ?ĄaÄÚľkl?Ö?ţ<ůĂŐŞTŁiH˛{÷Ś„ĐŐ&¨ÖAȄ^4ăƍŐŢ*gϞ×áBÖë‡×'{5ŒˇßŽS_ŤGŠ=Bł~׏^{ożoŸ`ň„J É"""˘î …­k*OŹzš|PđŰÖƒÝć@•‚GLĆ Ż2÷­—¢(ůí)R]]/îV”§ŕ Íh^  *( ˜(**ŇcÖŹëd˖ˇ58ŔŚŁ*eňä‰ÚxuçÎ]˜`x *7V­ZĄ!–‡P`ÌéşLTÂŕ2–‘’’Ú`;žäććęĐ#˜Ä:đ:xƒ]ŽCľ ž?~PĽ‚çƒë°|(Ř.ěGě_„AX.–ƒJ 'Âk„`A z¸ŕ6"""ęz Tˆˆ(lĄ"ĄÎ(ă`Ůék[Đ3ĹŢCĄ .{|*¸Îęu‚ëŹ)tÁ곢Ë6ÄŁ§Ž-“yÓËt9sbäOÇIËŹ÷7şľo­ˇ)ëÖݨę€  _q€Ža"资t„$(p>}ú4 %P‚^)"Źŕ§e˖j¸Ç# ŔÁ;ŞL°ÜoÔ¨‘xŘM:Yƒ *HP5‚j-Đ´÷˝ď?ü*N°ýča‚íÇpŔvTWWi؁ űA@a‰OëŽ›ŠçńńœŹ`'ěG4Ĺśášăş@čobÍ&„ű&$$ęv!ˆBŐ Ş`°íxmŒ`ů¸ ÕPíƒ×Án{םîŇp ÷AĎ#+V,Óç‡ű Ů.nC„çŠ}ŒđëĂëˆűăľA?ěo<7޸Vˇ Mhą”a¨~Q×c BDDaËpžáp‡˙üąŰ#ƒśÇÖűîWď1'ˇC/cȏőX˝Ÿm}VÓԀ܎Š Ň큃fë „a88Bhb‡pÄ‚Ę œě0U1N¤XýP,p˛ `čׯŸžěú÷irŰÁ*اSś`4׸Őţ|lť%Ö.pB{ˆäÝćŤAž{ŕ2­ő{Ź AŠA‹ŐďĎ5p_Që`8#†ZĂ6‰ˆÚ‚ …-Ťo NVď ŤŇˇE¸"48ńÔ{źˇťźo›V5 šˇZ÷ˇú_xôPńőDqx{°\ȍ•„sŢŤ ŁĚăĚş#ž\vŮŞJŃi–›éĄBDDĄÁ´í/žř’Έ†Ş="˘ś` BDDaË[)âń‡ Ö0+Ôp;ÜŚŢn]Ž÷÷W”˜“u› rŠŻŠCĘĘEţôT‚DGE{{ˇx"$żĐĄÓ({ĚŰătŮő­hŹBDDMB#4ËĆěYDDmĹ@…ˆˆÂ–ˆxCńŸˇ˘ $zŮ6ó[ďeˇËíżœžűëc1㋿ˇŠfĘ˝”ƒ€ĹŠ—#\`ĐŁĹăŸ~Üb|Ű" UˆˆÚ•ˇç•[§E'"j+*DDö{§ 2ÜÇvu˝˝Šý>ŢŰÄ?|§^Ő{ďáđ]]/ :˛Q÷Ç@…ˆˆÂŞHŹŢ)ޞ(ţ \v9˝3˙čßíVľ ‚ëąŢęôP‰0—˝ÇmVƒY°îgąnˇ–Ż=TœNöP!"ę ĽĽĽRYYŠłxŐÔTKQQąNOîňÍňFD**Ôm˝đâ?„şNĺ’5B´Ÿ‰/İ˙ԓ\˝ěđ]ô~zš^+[0Čƒxos4ÚĽÁ˛|Ű#őőÂbt"˘öőż˙ű=-@ĚÎΖ7ß|K{ěqůéOtÍŹ]DD-Ĺ@…ˆˆÂV˝ŻgŠŐ#uuuŢŰ|A.×[A‰ďvëžţž+őÖÄČŢ*ÖĚ[Okzdűň§¸ëÜܸ|3ü¸}ˇ{đ¸fz¨`Y999RXX$Æ ŐéƒqÝŠS§ő›XďĂëuú^LŒ*Ŕ6ĘĽKŮć›ÚZśÓňbŞŢ`JJJĚmŃŐč4ŇM)**2ۙ+}űö‘ÔÔTÝś3gÎčôĽŃŃŃ2pŕs[ß- Ű~öě9III1ËJi—o–ąßóóݘSžn Ś8ŽŠŠŃŮ@JKËtJdlť}˙deeé~>|¸šä‚‚š|9G÷udd”yNéöâqŘÇôoŐţ#˘öq÷ÝwĘŻý;ýŰ‡Ś´÷ÝwŻÄĆĆQk1P!"˘°Ś-LěÁ…ĂŃě ;őśÇŤRŠr˙F—ĺkŮR°ě–@(růňeŠŞŞ6§* T0laCllŹšŽRNŸ>#ƒ ň?řĹĹĹrüřq¤K||œ†29&LŻ!Qyy…3QQ‘xœ9sNĎ:D¤Ľ°Ošœ9sV×-ÉÉÉşÝŐŐ5’žžŽŰÓđ€aĘňÝn†8Vp…@÷Ç4×.­Ë× Ę]§Ďˇ…ĹúNŸ>-WŽ˜}—ŹIff–ن* m.]ş¤Ű0xđ Űž/’óç/č}‡ ŚËÉĘşh—iŽ‹Őý†áC† ÖŰŽŕžIIŢ׈ˆ:ßřńăĺž{Ţ-ožšY&Nœ +V,׍DD­Ĺ@…ˆˆÂV`—öAqiÂáôÝŚaG˝Ç{ŮÜ•*NĚÄsM§8m—­)Ö4ČVuˆĹßcEęôP‰°ŚhnA,Ő'/^ÔđAg–Ńż†ż ĺâĹKZÎnUr <@€* Tľ €ˆ‹Ë“}űöËčŃŁ´Ę";ű˛VŽ 4h Vj xA¨ xą‚@xî(­GŘë?Ř \Á6!¨ AP͂m@h‚ĺc|Pé1fĚhЍ¨Đí)))Ő痐/eee2räIKKťfyxÎŹĎá ^ §Óáߏx>¨LqšœfŮĺZ"2¨ÁcąŻąţĄC‡j„JœáyFFztyčĎ`-łŽŽVˆ¨sUTTĘšsç´z ‘5ţ~L™2Y˙NěÝťWďƒ˙đw‘ˆ( TşPůfíł[śK”ů@ůťe‹„ˆˆşŽw–_ĺÉŐkŚôG‡đČŐŰ­Y}ě6㏿1mpÄ>[ďŒ„Â>ăt^;ě!*+  Ö:  Beʔ)z=B ”ź#Ř@ üţý4´Ŕ˛ uŮUp9##ăšő D@eǸqc\0$'NœÔƒĐX•?+°Ýšššćú 5j¤ 2Ä˙X„eeĽ2{ö,Ů˝{Vž : –ƒp•.Ř^œ&Mš yyWäôéł*yyyr @ ÜFŹëÜšó2cĆtóÜ÷kx†  ۃ۹°/Q…b‡0á Î!ˆBĽýŰněçƒéóĆs@0Ä!?DŤźźLžyć9Ůśm‡ţűśłţ>ăoŢ'?ů *ÔŁ|řˇ¤ÎźOýxŃ*jjjTę4ÜFl{ý5ۈmBŕƒ@ á†ř  ÁžŔ>˛‘#†Kzz`—z_ŐN’†EŘ߯ěŻ7Şe0ŹËC؃j„:ŐJDÔq0´đ‹_üo=o˙`ˇ~2줞aʑÂ"=Śüĺ҅ UşńvBó!óż6oŐ0exb‚ühá\!"˘Î×\\aU¤ř/7óŰĐý¤%˝Xťż˝ŻJc<š}uëüĄŞ.Đă!†šŘˇ;::F{Ş=zL‡á~¨ŕŔA>ÂLý\QQŽ•'¨Ü@5śˡ‡E„.¨ŢÜ7¨lAĹú‰ ĘA–‰jcǎk¸`]nž‡ŁŮ❦nG“Ř` aš`#""ľňÓ¨—h(‚ç˝k×>|˜ôéÓG÷s ě[oĺL–oRźvŔńN‘:, !u>+ś†VÚĎ[?¨POó“Eódtr’S~tÓÉ7ď§ÔůřI'C˜ň ڜ2ŘŚ1ě.NDÔ"Ěéř¸H‰pFšđÂiN柍^˘"MPávi(ŕń8´‚U§w(‰ő&†–XŐ)ÚńQőW{ŚŘżő´÷ZŤ‡Šu{ŕ‡úˆČˆf?ŕŁĎ†ő Ä[q":K Ź˝T—i–‹űTWWi`‚Ç`†ĺ`&Ož¤ dQ݂°Az‰ úÁzśŘ56Ëփ0ÂęąéŇ`'˜ń}Y˛łët™(ˇˇĂö œŔśŁúÄ;4)BűŽ šÄşËB…Š7´ˆĐ۰Ţk^çF*BŹž,V(U[[ŁýP°<ôUAŔ‚ý‹á<eěU4č ƒmŔ>B5† ĄŞ€"afPƒó8ĄŠ/ŇQ{H5\˛Ŕlůń7ߖ_™cËž<śěT T:Ă"˘îĹ騗Ş$>ś\Î_Š–ě<§ P%ƒ2ęä\V””WEšóŐ&|¨—ĚËQRXěň˙ąÎZCtP˝Ç߄Ö~ą5§­÷•žÔ;ëý—ľ'‹ő¸zßLA-îƒ&ąQQĂͲݞŠoĽ‚4h VůmÂőrƒfŤč)€ËŢę o5Ş)źłüDi`СŻ7ŹeŠbŤÇˆ5Ěg„ ú!DZZŞ XÂkÚa ŚPFĺ śCd° œG؁ýˆŰpśÓśaP(Ăit˜•ď9aŰf̘áżáö…‚ÎD4pŕ@˝ ë›4i˘N+&´]ʉŚM›ę>äÝ^öP!"˘öĂPĽë1Pé$ Sˆˆş§Ó-‹f•HTDŠd¤×Čë۝2of™ ę[+ƒúEÉţcń2fX…ôKŤ“g7&˜@ĹŠ=<üŠŻ‡ŠÇ€ÔچĹ8|=R”ŐcĹęĄ"őţŰ5TA…Š9Őůzp¸ń¸fBTDŕJS°^„%ii×Îzc ý ź­…őŮ \NNnźůŁĀ}VĄŔ°ÄŢ|ÖŞiË6ڃ샌T"`˛{ ÁQGb¨ŇľXwÚI>łeťţ‚2ß&ţzŮ"†)DDÝÚbœÉŒ”hs\îŽuHu•CΏ”„řzŠŞvĘĺ|—?iB‡,źŽJbc65ľzŚřŻŠˇő]Ń3Ďěcżä_ŚŻZĽÁuDDDDM@¨ň ŞŕXó\i™ü÷Ű;„:+T: ?u?G„lߟ"{DępžňĘ(Ůw,B˛r$Ż JŞk#¤˛:ZÎ]J”¨H§ÔşŃ3Ăí =|ĂWœ.§oYŢŮsN‡żz§ČˆˆÓ)cˆˇçŠS+R<T‰ÔűB‡żÇ†NuĚ~DDDDÝ•N‚.ĚVş0ł Ťy•KÖH{ˋŠ’ŇűÉqĚśĐĂT˘=WV.ëňr%˝ŚFˆ(t“ŒTŐ&Kߌ‰rĽřźDE×ËĚYł%3󜌗&Ľ%Ľ’”œ$—/gk3ÖüÝ{Ľ˙€Éč×O<¤áDzeËt8ËáC‡$űňe:C=Μ9ŁÍJç͛§AĘÖ­[őgRr˛œ9}Zg|écn_źxąÎł{÷nÉÍÍő˛OĺLDDDÔÎ"ŰuřŐW'ąĆśaj+”aal§śę\S~6|¸HJěńa ŕ9ŕšŕ9ášQčXDEÇÉČQc%6.A§ž6}Ś,X´\ŚM›!qń 2dčpšŹ”„„dmi’––&ŁÇŒŃĘĚě3qâD?~‚ Zú‹Ó&SFŽĽ&ŠćžsçΕYłfÉŕ!CôśńăĆiĐbő%šÎ܆Ő-Ţ鏽'ŤŮ-QcŘŤłk1PéD UşÖłý¤"„*z <'<7"j„h4Ť!†Ű#…EERmţ6#ŕ(,,”óçÎÉȑ#ĺȑ#Ú0V§×Ĺł äćäJ„ W’“SüCzŹę4–-//×iŃÓفé¤I“4TÁt̸Ő*:…2ŚMöMŹ'!""" ŽaJ×㐟NĆ.Ě]ŁČ||4!QzŤ#ć[ôLEꛄˆZ%e&ěx{Ë)++ÓăĽ_”’’ >đĂxrrr$++Kożh~^Éżb¡öAŮľ{—ěݡWŽ\š˘!KffŚäĺĺIľ ]˛łłĺÉ'ŸÔj<jjŞ5\Aŕ’ŸŸ'ĎüűßzžĆÜ? }SĐoÓńb6Ś%""˘ Śt Tş€Ő…ů&LÁ87ta~tĺRĄŽł ßKďUoşvŚ¤Č ć ŽˆZÎíńh‚&2"#"Ľ¸¸X‡Ű :E§E6ÁI‘9ĐÁHeeĽ9_ŕ­@1ˇ:uĘ?2ŞZJL@ăô5—­ŞŞŇ ĹŞ8Aŕb]ü,**ň?j}Áhmúe"""";ű,˛ż4aJš9ƤÎÇ!?]żđřş˜š"‘˝pJwâ‡ěHN–ŢnťyŽn *XĄXóM„ři÷÷1q{Ä]ç֐Ăęib éą.ăśZßP ]†ívœGĺ †ôčrÍ ÷ĹuÖýq×YÄŹí@œˆˆ¨gaq!u†(s ‰cI†)]‹*]żřŹLéxG¤8 Jđ™ç:ŠŹTˆčZ ^ŁÍßŕ™×]'Ôa:40ĺ1‚ŤbÄ{Ůa.{§@öVšŕź4˜÷wâz‡Ó?íąuűeűvŘo×Çű.ŁĘÍj§OŸ.}úô""ę9ě‡DéwË u=*ÔĄ´Ä˝‘Y*üŔ˛qăFíĽ‚†°:ÔĆ6„Çű8ßĺˆ˝ŒŰą¨HsšÖw"˜ő§ŚśĆ˙Xü´†î8}ՈőžĘ—ď2–çoB‹pS˘'wÜq"˘ď1ř›ŽáĄö÷"꽨P—Š1o:1ü>ƒf´¨ÚGăă;Ľ9m§rĽÄúPëĆSg‚H˙uUîźóN=ľ–wH¨wČh¤Ő`œˆz=öPĄ.SV疎ÖۛѲšÓv´ŞÚŽíˆÚĘŢřUŤG\RVVî­0!""jGxoÁ{ ŢkŹ!œŔ`…¨wc BÂäň•>(—f´ś™@ĽŁ›Ó–ŐÔ}M‰ş+|¸ŒŒĐoËË+8ƒľź§`ś8źÇŕ˝Ćę™ED˝˙ľS§łźsŤë¤ś‡Ž„K3Ú@%<ĚÉm^łŇď"†(ÔÝYC{ź*.׎žřS[ýQˆˆˆBaÍú†÷ź§ÔÖÖé{ ŢkŽ61ç'%˘ŢŽ=T¨Kŕíő)—ŤjeHl”t„)áWbŮnž{G5§-ŞŞ–:ó ň#őÖZŤ ŹŐ(ś´´L˘˘˘Ě)Ň65ĘĘHźÓŢ×ęÔ÷xAß+Pa˜B>¨P§˛fýq9âŽtJq[RÍ)!Â%ííT|ź„ŤŽzîčRižŠ‹téküŔ@==TÁ´Çř‰PĹ;ć˝F˙.ytöaĹ ĺ J¤Á4÷ć¤ŕ:VŚ…*Ô!đ6ŇÔ!Iž Ž‹Ѝ–Ň:Ä¸œá°Ů>N]ş$Ô~ę<őRéë;Qă} ›ŔÔÝXpńŤëpxK˛=ć÷şžŢ;ńՓ]o#ţiîő„Ĺp?…*ÔᏪ{Čo’üČ‘s9zŮÓHůŸŰă—9ȉ0oNNž!u)Ćă51›8đ´^<ó˛Dö룯Ą\˝Ęű“ŻusöYôď’żŘÎU) Tˆˆ(űÇűű gô! _ T¨ÓáÍčŁÓűȑÜbéSă­zŔ * ĘkpŞ•ZO'Ř0+DDÁ>î{/!˘đĂ@…:E°*•Ańń’9$]Š3ó¤POPh–ˆ!úÚYXB=•=L öűË_i""j ?ű§MŚÓÔ[Œ–GšŸsúgHń€T9!ü2¸űÂksÖźFšƒűĘźýőşŚ>Dđăő$űNDD-Á÷ " Ä ę4U*ÚÝü\:xŠ+”W $Ľ´R˘1ŰšŸśqÄľÇéňH—ÄG›SŒ ę“&ËÍ ŻŸʰďžüPA˝ Ÿ‰ˆˆˆ¨%¨P‡jlś{¨‚2ŠŠć@}xR˘d••K~U•TÔšĹĐC%Ô –Jx˛<2¤űB˘9p\„KúĆÄȄ„xIŠŒôŢ/ Lin9DDDDDD˝ęTV•Šž—ŤĄ ŽĂűÄԔ Á ‡uG3× Sřm>…#*ÔáŤT UŔdW/ŹzčLAC{'űFŽoěąDDDDDD˝ęͅ*" ƒ˝p;uŽć†)DDDDDΨP—ąWĽčeßőőˇS×j.H!""""" G T¨Ó&ţë VěŘCĽs47Őu¨!"""""ę­¨P§kt㟠Ă}쏡Î×\5 _""""" W T¨K4V­âż˝‰ůŔ°…ÚŚ5Cx¤Q¸c B]Şš`%čcŘĂŁËpĎy1PĄn!ŘTÉÔő Poăńxô'‚ŮŔa†:m{ŔőÝIOŘF"""˘pÂ@…ş%*Q{BQ]]-Ůٗ5ŒHKK•¤¤$˙íEEEćT,.—Kú÷ϐČČČnZ\ş”-uuľ’’’"ÉÉÉBDDDD]‹ …Ç˙Ť &.˲e‹ĺśŰn•¨¨( Zţú×'äčŃc2~ü8ůčG?ŇŞ0ĽŽŽNňóóe˙ţƒ2tč6l˜ÄĹĹJ{ůË_ţ*WŽäËÍ7Ż“%K u-§őrHPu2eĘÉÍ͕͛ˇČ… ™:AĘöí;¤¤¤DŚM›ŚU*ľľľRZZ*ĺĺĺ”Řá1UUŐzÜîvťőúĘĘJ9xđ°<ňČďĺĺ—_‘ÂÂ] BŚźźB—YUUŐ švYY™šžLo°,çq.geeÉšs´šĆRSSŁÇŠŚĆť.l/փëŹőCEE…n3–IDDDDmÇ "" J.\ ;wî”cǎkčńŢ÷ţ‡Ź_˙˛†+V,“ Ći•É™3gĚ霆0c̒!C†HjjŞVł\ž|YNž'™™YfhŕąbĹr­2y≿kőLLLŒ _úkeJD„÷mť˘˘\oß°á5ÝFÇmn‹4ĎmľźűÝďŇçváB–YŸKÖ­ťQJJJÍóúŤVÉ|ěc ľ‡üQX™1cš,]şX M8ň°ÁšůćM¸1L+WÖŻEfÎźN~őŤŸËř :TţýďçL@qAvěŘŠaĚ̙3ĺ7żů•<ôĐweţüy\̚u|úӟÔjTŚ|éK˙ŁŐ)>”|ń‹Ÿ—Gý˝ź÷˝÷JNNŽYćłţa:ş“šš"ßřĆW厝îĐŞ™ĚĚLY´hüüç?1aÎ{4dą†!ěA€rǡÉĂ˙BžţőŻJrr’źôŇzŘxäşëf ŞYPƒj–ŁGšç[ŹU0ŁG""""j;V¨QX‰‹‹×}SNœ8i‚™Ú;•%¨A˙‘}űöÉ˙ţݎÇJ~ţ>söě9m6‹Ę”#GŽ˜°ĺ'zU.cbccőhv­ýZPՂţ%ż˙ýŁZľ‚>&˜Qčřń“ţiœ“’MČłD&OžŹëBĹ *S.\¨Cy $O?ýO źË”yóćhôÜsĎËšsçu„43f̐-[śjŸAďźłKƒTĚôé“&DDDDÔv Tˆˆ(ʏ\Nío‚ž$'OžÔĂz0M\ŃkeʔÉ&ČŽÁBô%6l¨VœÜsĎťĺŕÁƒRPP(‡‘Ýť÷ho”e˖^ł.„#¨&ILLŇ!EIpօ`ËŹËĆíŢŚľ­tA(ƒŰ0ÔýVĄ *\üozĄŚzFŕƒŔÁ†ĄË[o˝­Ű¸sç;ş|ôOÁňˆˆˆˆ¨í¨QŘÁp™¸¸8sÎĄ?˘¸\Z ‚P##ٟö2A%ŞEn ¸ČÎĮ̂ů UfϞ%N§w$­U…‚eĽĽĽęŒ;sçÎ1ËÍĐf˛999Zy‚őz9t8!đHKKÓő:tXFŽ)ĽĽ%Ú°ú Á-†­^˝J–/_Śëۡożř X´Šfܸą˛uë6mP‹JôR2d°Qű` BDDaĄÂT}ŕ'‚Œřř8™:u˛'[śź­Á‡ŰíŃĘÜ6nÜ8­öx≧´bU,yyš:ĚŐ+ńńń„  9uę´ĹA“Ř•+—Ë#üQ~÷ťß›Ŕf 6ŠĹ˛o˝őéĄJD„KÖ.ŻYłZţň—Çu „!ÖôĚ2„Űć`›˛ł/ËŰooә‡P%ă­bqčs5j”Î(„ŕY´hĄÎ DDDDD탁 …"˜ńgěŘą‚ Š,B•Áƒ‡Č—żüEyöŮçľ),ŽCcŘľkoĐJ“UŤVjŐ *?p;ŞIîžűN˝ĂlPňž÷ݧŐ"••U‚pcőęŐ&t‰ÓÇ`ŚďLCk´ş6l˜ LĘ$!!Ńż}aĐTa †ő`ůǏŸĐŮ}Pĺ2eĘš˙ţ÷˞={ľjfäČڇýZ˘Ł˝Ăˆ0Ź U1{÷îÓY…0“‡űľG ŽwŘ.[睶ŸÖÉĺ;EřNřԆOu)55ľŰĽ“`ě8`Ě;žÍCi4J­űďťBD*üEÁßë'ZˆÖašZsžÖüŹ1§jü­1Ů1×_/Ť×ˆK‡’Pw†÷LyŒ´VďTqŕ5F€ëŃÜ•,!âătřnGƒY<łç ŞÄjF‹~(X.ŢsŚ ZŐ*x<ú˘`Ęb܎jÜ-x+-,,Đ÷,Ü7Î÷ťƒËXOEEĽöSA#Ýęę*˝ Ĺö˘jˇcźÓ);Ě}ŞĽoß>ş>-/˝ôŠ<óĚł:KĐÝw߼3 …#ˇy_ÍyőŠÚ°A"Íűd´yߏBľŞ99Í~~Šx‡ŕÚ~Rë\ţňW̗E úůŸąŹaŃŘŻĹ|v›g~™ŚUŹ1§:ßÉí;yl§zŰĎzß"ěç%ŕźb… …źąăM';źÉăU+Áx‡ĹűŕËMNN֓]S ś.|čÜžÄĆۊ §`0ŤUeƒF´čƒ!BDDDDÔ~¨ő2¨˛Á,Bééé:dičĐĄZaCDDDD퇁 Q/łdÉb=QÇa BDDaÍę˝EDDŠÎěADÝ"" KVřóęíBDD$šI`Â`…(|1P!"˘°ƒYt ¸Ýß5őA‚‡\mćn?ßZ-ëázš:Ďőp=\OwYœxzĎť\N˝lÍ`BDᅁ … úÓ^{źA >[†˝ˇ QŁŹb+”ˇŢOpĄ ŤUˆÂ "" Ţżn'""Bg˝Á4ÇDDD­)úžRSS+ľľľúނ÷†*DჁ uší= OŸ>Űčí‘&ŐO‘a‰ ˛fčY9x DuAůäţü+ňŔŚ- Žű٢y2ż†QĎdUŚÔÔÔHtt´9Eń/ľ”˜§TW;ĚŠZßcXŠB>¨PˇQkv.•WčiŰĺ\ůۉSňšł4`!"j-Ť2Ľś•).­Lá]""j/xOÁ{‹Ű]§Ő*‘‘ŹT!  T¨Ű:QT,ŸŘüśüyŐ2I5i?ľÝoÝ!›/]ö_›’,1ű—¨ˇB˜bŞÄĹĹ7ř€‹ëóóóĺňĺËRQQŃâ)”qżŽú ŒĺfddHzzşÄÇÇ uřۍę”ŇŇr ď­÷†*D˝ęRiŃQúo9Ĺ&Ń÷ĚäVVÉ˙ŰHž9ç:!"j +Pq: ʰŃKaĘŻýkyóÍ7Ľ¤¤Dşlă¨QŁäCú,X°€Ą Q`Íôƒ÷ë}‡a QďÇ@…şÔ ën—ďÍŚĘ|{üěŮóň3 Řƒ•ײ.Ég§O‘¤¨(!"j)ű4ČčŸ8ĽeeeĽlܸQ~őŤ_IAAA‹ŤS:ĂŢ˝{u{ÌĂ@…ˆ¨Á{ý=‡Á QďĆ@…ş—KŢ=z¤\,+—'Oń__cޔʂ€Ś°ťróäšsäXa‘V˛DšoúÇĹÉ܌~rëˆa2$ĄńƒŇÚZyęäiŮhš‹ĺá’eƒĘ'ŚL”P`ž1!Đqß68Íć ř8™gśőŽ‘Ăe 9ߘŁć1v›eäWUk™ä¨H†łjČ`šač`ŘčlIŠüëĚ9ٓ—oÖ[)unIŒŒĄ‰‰f?ő“;G0—#ý÷ÇĐŠwróŻY†UÍýÇłzţÁIăĺţ ăZ˝˘î,ŘZ*űöíÓ&‚Ý)L|?sćŒäääČđáňˆzŽîöžBD‡ u;s3Ň*SQé?_QW'˙ťkŻźnÂ;ÜŁ¤ŚXC4´ýŻŠ“äž1ŁŽY>šŢ~ę­­rÁ7–jˇ[Ã9šň™i“Ľ9؆ożłG޸˜}Ím'‹Kôô”y¨ŹšÍ„;vx‹Ĺ0Śż›@'đíÁJţĺ\ŮjNOšŰźpޤÇĆ6¸ĎŸŽß>vÍđ¨Âęsş˘łýŐ<˙̟#3ŇűJktĆ:ˆ:~…Żţ_űÁEw…mă‡r"˘žĆގôžXœBÔťuţœ´Dͨ raUjŕ˙óoď¸&L ä6÷ĂĐĄÇÍAż˙Ľm;„)v¨VůĹÁ#Ňk‚…)viţo÷>ِyąÁő6aĹA”@ÇM0ô…­;„›/eËŻ˝&čTRS+Ÿ5ۈʒPuĆ:ˆ:O˝Ř?Üö4 Tˆˆz–†!>˙†őv T¨ŰŮ$¨ČˆóVi rew^ĂĄ+ą˛lЙ¤Râ7&8WRężüŇůL9f‚Š@SSdNFşD9rž´LšňôéłAˇaéŔţrŮ†Ŕ/"~˛ď€ç„,;ŮŕöI‰ZMóůSe‚Ůť#…EňNnž˙ň?ÍşíâĚzń¸_/]¨?1$ǂ*š§OyďĂĐ!r˙ř1 ŽÇizß>mZQw֛s LaK555ţëŹËľľľR\\|M%‚šŞŞ*˝f?Ü§źźźŐU;xօuśćą••UÚ(¸ŁB$,ë•wŰ*ĽŹŹŹÁ>îhx]ĐŰŻI°}ŇÚçx°ÜRó~×ŢUZÖďVUUľ˙ő´Ž+--íĐ!vX.žŰ•+ćwąD÷śŁ9ŘNëß^këßQk1 ' ňCÝŞ!Ѓó=ěâÍüÔ>izţ_űč9ňÇKe°Ż_ĘŤ™ĺk;vůoG'Ÿö ă٘uńšuuÖ šyřP=0ĺ#›ŢŇĄ- R˘ŁtůúĽnCYÖΜ\Y8 ż™ăë† 1×UëőĺćƒßŻ–,đ7Ü]5x Ź}ţĺßg × úÂ*hěĐËäîQ#ô<Ľž11ň̙ł:L¨_lŒLLKŐŰÖůžßi.N›üŕä†}cZť˘^Éáđ•k[Qi˝÷ƒrk>-;ͲDŽŢÍś~YXX ‡‘ącÇČŕÁƒôşĂ‡Hšůˇ™––&{öě•Ĺ‹5hʋČcǎëĚFÓŚM•ääd=}ç]2wî‰ jŘ80ß˝{Ěš5K"C쯄u9rTˇżů{Ńö'ÖA<‚ƒÄÄDNJ–y˜=ťĺłĆá9]žœ#çĎ_Điľ ȐaÆé7nĂ~Â4Ёźä˜żűýűg„ź/ŻĎŋÍëą[_×ɓ'i <'Lń””¤Ďëĉ“˛hѐ– ˝y23łÄĺrę>4hÄ˜żííŃ8Óíö˜×ň˜ŮĆD]ŢŔ4H9oŢŰ őő2dˆô5!~`ŁčśÂ~;yň”ţţ7VĂĆ!C›ç–Ţäă°}ťw桢˘"łż'K\\č˙ˆˆ(ü0PĄ.ľŕŸĎ5{Ÿ[†Ó 4I Şs÷č‘ţ0V$Oœ8Ľ•–M/ů•˝yW<•)V˜Ăä?Ǝ–_62ěŐ.,ٚĎbşÔ˜Üé&pčg>p[I†9*`ţěĘÍżćŘŞÜ| ´$›ĺdĘŐ}°É„#ż8pX˜ůc’“dů zj‹ÎXQ`6#â˘Ĺu5@ńÔK]yľxŞjB BL˜™'ŽH—=›‘Úâ ŠŻuˇúëL`ďŮłO6o~Ë€_’űîťGblŒ5RRRR$**úšŠ ŻžşQ§NMM•)S’őŰü ^3đc‰ƒm—ËĽŠ8pđ‹ '„ř6ß:ˇŚŁŽŽŽ1Aƒ[<Î~Ŕ읺کľ–ƒÍÂzP€0‹C@ƒűˆWƒ`ËŤŤs‹DE™żU5°Źçąll3.#¤9uę´źöÚr×]wHvöeŮşu›L:Ů_k6oU÷9[ĎëŔsüӟţlB’nĺ^X/K–,Öuœ:uJĎ0ašľ/ź'§”˙ć7ż“Ď|ćSć5Höm§GŸ–om#ŕ6ŤňĹZ–÷ňËtŮ Ź0ĽÚńżřĹĂrď˝ďŃýńć›o™€h–.ĂZ.î‡ĺYË˛Žˇ^ƒmŰśkŕ€fǸ~ýúWäƒźß\ćßÜűˇ^+ůÝÇk‚ÇŘ÷{ŕóŠ­­‘×_C2Ě 0ĄSŒ<ýôżôuE`ąsç;˛k×nóťzŻţžÔŐŐúŹĺ`űqڟĹu8Y•-N§Kď‹×(pżUTTĘż˙ýŹ š-A_WŤúźűÁĄżŁVĺ ž'~7ŢxăMNÍ7ËŹŐ0F„ 5 uk¨ řčä z>ť˘âšŰ­a*×Ů•s€ ˜J|¨ (㽎߾ßZÍ3 T‚mĂ´ ŰđŰe‹¤)˜šhcćE9xĽ@NáŰBłÜźŞęfű–Ź6Dg<˛Ô™ĺ OŒŐ+#“̡ŇK ”딈V|ű×ë ęöĚąadbŒ ¸uś$Nć P wEäŹß+%űĎK˝ť…C%́ž+6JŢ9Gb†˜oĺ##Äaćŕîüď_“ŠsšâŠŽ“ÖŔeffڍž?^‡Ľ$$$řoǐ„×]7Ă_)L ÍA0Ę„źź|˝™ůůWäńÇ˙Ś dlÜřşĚ™3KFĽßâŸ>}F–-[,żüĺŻ5h@‚*ŠoźAŢ~űmfţ† Ź9aţfDEy„o† *ˇŢzłěÝť_öďßośˇ\‹ Üžýö6yéĽWô`xíÚ5z›ĺřńňĘ+ô€Ý劐w˝ë.­âŔşú÷ďŻŐ'×_żRfΜŽűűć76ÉĄC‡´JÁŞ2yäz_lǸqc´RĎf̘. Ě×đÜjjŞe̘Q2mÚ4sŔ˝@ˇó׿ţŽůŤW_ŻűĚ ifÍşÎěÓ<]îóĎż óćÍÓăđáĂ>ŹYs˝Lœ8Q+ J |yüń'´âۍíÇő>PÝ1Čü­Ĺ넡+ožšYˇýő×7ɤItHĐŁ>&.dš×dŠŽűůЧţ)řӌ@cŊĺşßąÝPą´bĹ2}ŽŘfk#Ăďʙ3guýˇß~ŤrŘżřCč0iŇDó|W™çrTŽ9˘Ż-–*§xóĹ~P…ҡo_Ý7˜ň•Ax->đ÷›%JJĚX*eŠŠ.˜ŕčU˝ż7ŤV­Đ ĺé§˙ĄŰÚĎźG/_žLĂŹÇ{\_ź6ř˝Äuýëú;Ž +ěˇÜÜ\ó{u@ŸĎ… äʕ+ş˙žţyÁČ&ěßéÓ§Ęž}űu?b{oşi­x؟kfĚŔk'DDD-Á@…ş­ć`ýK3§I´ď›ľâškÇĺ')ĽNŠjxBŠbóaŽ:ČÁORäľ˙’˘Ł¤1E-܆ڠĄîÍÁDAučcń1U1*uţq:xß ›Ę˝˜­ s=z\~´pž mbúčŽZQO ÁG„S ˇŸŇĂYz]}GŞóŠľRĽĹĚß OU­äm<(ÎŘh¤8$29Núޚ"ޏ(q8[7ĚČgϞÓó8@?qâ„(bȎý>}IşlßžS¤SRŔe–¨ŔˇüëÖݨŐ¨|9zô˜żĎŠľ,\FľBllœ˜ăŔř­ˇśč/†Xx|űfĐ ˛téůóŸ˙*wÜq›YFĚéşq`ŒƒtďôĐšşî1cFëm 8ä?ŘÇ6cx˔)“d„ńć ů Gü;ÉÍÍÓ çđ;‰×oíÚ´ňøÚcČ…žcP—Âk'}ĚŽ‘ć,†ÍŒ1şě’ŁŽ .Jƒ4 ^œfůƂށJjŻ˝Ž¸‰ #Ľ…ŰĐTŁ|uÇ.…ČndR˘Œ3Ďwjß>:ź&ŘśöÔϘ*ˇŒ&/žť {͡ÉgLřQ¤Š †&}mű;ňŘŞeŠÎXQ`‚O­[Ş/IŮÉl˘ƒJ‹(sŕažŃơî-m^‰j–ĘŹßp‡D÷KwiĽo˜DëűVŕ`U%Ç í‡‚Ą>8pl Şöîݧ},p`yéŇe5j”Œ?V‡gŕ›|CƒspZĂMź'ž°Ůńńąţ>¸†nXă źíifYéz•~ŚŹŹÔ5Yzđím¸*ţ!č9‚ƒo„ž*\°ŹsçÎëząŘŢa^ 5P=2xđÝwǏŸô çŞ×ýç}í˝ëĐ#žaŽx~ŘxţV¨‡ĄeVŁd2¨¨ą0ÄďPj@Sx""˘–` B]ę‰Ő+üJs)ÁĹÁţ_ĂVËţü†}R2ĚBT’ ´ŠśíśÍ cŮa>¤…˛ űÍźŔm¸çŐ×uxú§ Ę­&œ˜m>đ?{ö|ƒ0Ăg~žxÎôcA Ň„/ĂŚLÔ烠ßţĹ|ČľJ˜ŃÓ÷kEƒÉÎXQˇ‡Żč)Qç—9€5|„Üá`–fcŸ%ĹęÖőVŤĘCďWçńo}ďlžýÇ7ôö7áD…~㏃zŹý6Ź Â‚\Řă ĂxđüîÝűĚňq9r„>öŇĽl­ŔóĂp‰œœ<*ƒƒŐ<Ű g YĎOűëڞŽĂ×Đťăjď0%?¨ŢŔÁ~žţÍö>Đ gźË˝şŹČČ(–*oГŁa†)Y}KŹm°ŻéxNnĐĹzmʟŢŔ!AOxÎ@p`nAř„>%“'OÔn„(8Ç}°oQ5ý„íAőĚ­çŠu`_#´@`°ă÷÷ó>ŻH] ,‚ÁŢ­^1xNř}˛ö—Őżá *S°|„*XÖĐĄCýĹóEáS¸/nÇžE…IfćEö3wîl °0 áî‹ßs\`}i°˝Ť|ż‚#<˙+W u9ŘĎV ƒáSƒÔŰń{€C˝öá÷ÁÂŤ§ śUN¨¸Ađ„ËÄp?¸ A‹q×éżńśMíƒőĄ˛ĹSŚL֙ZpđŽ€ť¨âŔA0zpXů€ŕěěléĂ(ź X]Ú;ٞ˛BjŃÄŇăƍÓeR,űۓ: Ç:P÷VPxÇ"đ>G§ŢŽe˘*Á 8Ěu žfŠ˝ËăǏÓuâz¨œ°†ZXAˆ}Ś!pŁQ(z¨`¸OLL”öPAГ•uÉÜ8uX‰5\—űůúda8Œˇ‚ÁťL,ۈŢ*7޸V^}őUݧ^3räp˙z1<ĎńŸ˙|FĂđß}÷]ş,ĂzĐĎĂl0ÜŻ-ú Ç *"ĐëC„"˝úękş, C˛†Eá@~ţüyň÷ż?%O=u\wĐP5&&Ölkźż’Ĺ‚ç4bÄpmŕ‹ĄOöęTÖ ŹYłfľüă˙ŇŕŻ'‚ î‡>3ŘÖ?ţń1 SĐg„ ćąů&Lťd^˙Mşńş ěÂPTđ<őÔ?4œÁď^o4žE¨…×´ą!2Vu *|žyć9Ý؇˜™ż›č_‚*œ°żĐ÷C^yeŁăÁ˛ńşĄ —ńďŻ)†ľĄoÎSO=-›6mÖm]°`žîüzßźŐ2¸ a ^܎ç‹×żçŚ…`Ż-UbDDŢ-¸Ţ^lwÚ~Z'—ďá;ĄŢă#RjjjˇK'ąžýł>Üzże)“ţßűŽP×úŃŢňt@_Ž­wŢŇâ xâäiůŮţC ŽĂ @s3ŇĽ¤ŚVöŘž=…HóáéńUË4Tˆ|Ď|hźůĐo>`¸R łí˛BxŇ(?Ůwđšm˜ÓŻŻ”™Ű`?TJ5ڟťiD™mÁtʘVق!Nߘ=SC•ćĺOÍsË ˜Éč}ăĆČǧLÔeŢňâ+ÚĂĂ~1¸C†pýop{_łü×Ýŕżü­wö\3-ő<łďRÍÎ5CË<óŰşŽŢĆ;Cn˝˙'~;Pąƒ` ż+h0ŒŞ§Zs€sýő’ąz¸Řа[°†Šxß ęô ćVu†|<ôĐCňČ#čűD˜mŚ_˛ô[=U*NçHÁś“zpöţ÷ż_űU`˜Ä­ˇŢŞý'fϞ­Žč‚oß'MňNq‹Űđí7ž G…nǁ;žuJO”A÷.”‚ÍćŰöŁ—Ä]yíĐÁ3fČŻ~ő+sŔ=żŃçgU)XłŇX—˝Ő1Ţ*ŤĎˆ}čŽuX•3x+|ÁOkÖűĐ&ëz\gÝnźý:k– ű,3W_=gŤpŠ÷?k›ěęÖL9Ve_î¸?ŹőŘg˛îkU=XëľfŹńV1¸T:ö ąž‹UdmŻ÷cQ˝˙XűŇZB+řšZ‰su­}k=Ÿ_đ3pjaď}˝Ż­ýšŰ+˘PƒŰ­Jű2p?ëů[ŽîżŤűתňóŞˇU]ý=˛˙>46ĺ˛u_űsôn“7dłżöjŽŤźł/Y×YIxęü_@xŤO쿃V5ľ ÖuÖëm˙ľżDmß9TwáŸúYżwüýęÜ&”ÍyőŠÚ°A"Í ¨ÂĆçs/ š-čA.^3ŰOjË_ţJƒ!Ö{Qgţ{ˆŠŠœg~ŕŰv|‹Œ[už“ŰwňŘNőśŸÖ›d`9ń5߈ąB…z”w)o]ş,ťmÁ fďŮt1;čýœ<ÁŚŔşáCĺiˆœ,.ip? [ą Ü8ëŤ0 Ó$c}{śáMł]Á|núTýc łĚ7kö@• Ÿ|k[ƒűǙśÁŞTđ§çS&É×wîö_‡Šą‰ŕ#“&4¸<Ĺ|ł¨X;¨°AhÔÖuővÖ$BŃ똠"dɒ%šŕĂÊ+ô~˜ůáĘmˇÝ&;wîÔa íľöŔÁ~Ů~mÖ}ŹÚ`ˇ[˝/×ă 2›—ľ.űŁČ Mş#ClܸM–Ŕ` ŘvVJXŐ.Á–ŐÜú,U_ؗlťZúźŰĆĆl{ŹßIKTTăűŠąýŘŘëěýŽŹőŹßšŕż[ÁˇĽĽ×5ˇß‚˝ŽÁ~O(ź @ˇú!đ&"j ÎwJ= Ňă-œ+Ë hň~¨zůô´ÉrßŘŃ×\˙Đü92¨‘ńŇiŃQڐľšmřąŮ†Ľű7y?„(_œ9MŽ÷ ÷LIlše *AF''5z;ŞHž0ăj@ÓÔşńüŃXÖîFłţ‘ś€ÉîrEeťŹƒ¨7˛*”P5€a!˜ Ă0U(րćK0|bôčŃz`čĚäɓuHŽŤŻoŰp""j=47~≧tČ Q[1˘§EvĺćÉsç.ČтB‚ĺrJ˙¸8™Ó/]n9źŃŠ|Q‰ń§•KučÎkY—´ĎIŒyěÂý忌N’Ň S#ۆď/˜ŤMZŸ;{^‡ëä˜m@`ƒ°Mj1ýp`pƒâ—KČßOœ’ fݙeĺét˜mMťGÔ0ă7ŢjrÝXîbćüëôYّ“§}Y0Ô(1*RšçáOˇŽ!âŽmcž­űÝňĹňŘą“˛ůRśd›ç^gî"#ôśöXQŻä&pňäIŠƒţű÷ď×P3–x{‘8eëÖ­:Deß{öěŃ ĹŞ@ظqŁöQa BDÔuPQxůrśöî!"j+*Ôi>?cŞžÚ †ĎĚň5 URT”|xâx=J‹Ž–wÝÚě2Pä>×'sfřiB•÷Ť§`1Gs0ŁÎƒ“'š“„,ŃŘ}bĘD=uÔ:ˆz#*çΝÓܨHéۡݍ:Ah’žžŽ ú¨ >Üßs%##C?¸ŁŻJ{Ďňƒĺĺääę7­Ă† ŐęŔ6ŕ[X4ÍE°3hĐ@ý‰ƒ|+(ČÉɑ’’R˝Œjšž}űř¨  @C|„``=—.eë4ĽX7†?ĽĽĽęőŮٗuťH`ÝŠŠŠ-Z&śłt$$ÄkŐ–@ËÂkyńâ% i\.§ž^ظŒ× ˇă2śűÉrůrŽî—‘#Gčvšge]”!CksćĚY_đă4ű.AhŽwąJ‰¨‹,^źH{ě/úˇ˙†ď˝÷Ýúo’ˆ¨ľ8䇈ˆ¨p𝗗gžŮ<ŻAŔž}űäřńăröěYŮąc‡9ÎŇęőë×KnnŽěŢ˝[Ţ|óMyűíˇĺ… rřđa=HoO8 G0éšËË+üŰyęÔiÝVÔŁZáŠä č),,’ƒiH‚ĄJeNž<ĺŻÔ°Ś„ĆO„gϞÓ`ˇľփFźÇŽ7ĄB„. ł$ay¨ęÁ~DȂőœ>}ŚÁc\•••7Řë§Uƒçf[••UúšŕqĄVÖžŔóĂž(..1ŻUŚ.÷ôéÓúz"DAŕ‚“ö9ě;ŤĘĺÜšóúZcöl˜ ĄĘŃŁGÍs*ĺ,OD ˙Îń7C4G)ˇÝv‹Œ?Nn˝őfY¸pţÝŔß6 '˘Ö`… Qs=ˆŸ7ožöCŮľk—VĄ ŔL?řŔn ÷ŔŹ>8hFX€BT$ LÁýÚ†Ąz€Ő0¨<Á,C8HŔŹDýűgř‡ĽŕvTŇ`ČŇŕÁƒô`ËŘľkˇ (‡Ge†up1iŇ$˝ĺĆ4´Á6XA`Ő–…jôôž0`8˜Á>:{öźVÍ rfI˛ĂóA“šš˘Á*€jk˝Ű3{öuf3őu@`ƒ0ŚOŸ4łŸ eěŘ1ćůšfQcۈ×$++SđŐ3ýű÷×mǡ×ř6ëĆ떛›'cĆ\ÝN+ŒÂśŒ=J-> WŤ|Ć 1֣ϝˆ:ţnŰśCĂoü-Ŕ ˙–‹ŠŠäЧţĄ÷é×/]–,Y˘ŐrDDĄ` BDDÔ8Çô¨QŁôŔÔC† Ńáň ŕ#|Ŕ7ĄcǎŐáA=fěÝťWöď߯ĂqÚ Â$o_”jsp_Ś=;0ôäÔŠ3ZҎ ÷ˇž­MNNň‡,¸ott”xŕ }`2ŕ~qqą:T÷Ç2Ą˘Ő+óćÍiX`•––i 2qâx­ä8zô˜9?AŻC• ™üü+ž\wÝ ˙c^!ˆ˜9sşŮg´é/"„¨(ąWy`Ň´iSu.ěďŔ@ËǡĐS§Nip=S—"/3ĎyźVœ Aĺ€ŢçiőSqš"‚~{Ł=RšaýŘ;ď°ŞÁćb˙!œáp˘Î‡Ŕ˝Ź+s:9쇈Z‡ Q3ě‡Ŕҁž)čůŠ T!ŕ€zňäÉZ‚Š”qŕ '†Ý BŁ˝›’;8Ç:œ „Ŕ6˘:ĄzźX\q`á-)pۊ A‚üÄ}pk™‘A{ xÁó ÜŤŮl||œŻ?ŠC+Ojjju9¨đAhGŽťćąxŹž/ÖyhdŰp‘z›ˇ’Äc˜Ž­Ážv˝ÓéĐÇb;°ƒUëžÂrűÂťNˇ?|˛CŔ†ß őAˆ†€Í>Ź+%%EƍŤ $O#F ď°ŔDt-üm¸á†Őćďń˘&UDDĄâ;:Q3Ź/5q€JHcȌէ'|ű‰Ţ)‹/ö5:˝¨¸/*U0ô}UÚłBCfPśŽ*  Q+B T̔––hpŰ\­F‰ŇĘ4ĚĹś`ŰĄÔÝť­)ćŰÜ Âcád5`ľ ”Á)˜ŒŒ~ţŢ2pŹJ˜jEŕú””äڟ¨ cŹÝví7ĚŢż]]>žŞQ°-8ah’7œ‰Ö +x,ö1ІęýĎ3?!tB…Š˝Ď ‚„U¨bš:܇*D ˙Nń7'"˘öĆŚ´’ópý…,ń°Š^ˇĂ׆¨ca˜ †p Yéž={´Á*šÎ˘ňڜ8qBގlŮ"ĐŰp Ş őiďƒjôů8~ü„öLA/ŹöčU‚žGŽŐËč7bU›X!z›ŕ1‡ÖđC”pßącGkČám˘[­˝Sś TŔúZ A փ(xüđáĂ4t@Ď GŽŃaF¸l‡ŕCř úËňN=ĺŻ BŁ[œÇ°ěOT  eĆ,<¨^ÁžÂ'ôvÁŒ<¨,ąš÷b=hđXôDÁvŕ6¨aśo Šßvc›kkkt˜Nxí1t 3ţQďŔ  꿡î9ćƒđÝŁF4¸>§˘R~uđ°ĚÍH—4ó!˛1o\ź$ýÍÍ Š)Ň^Ž›o/–•ËŠÁĽ'Řf<žˇ{Ÿ$˜ƒ—'VݐŽřÚüíäišqč`Iiâu ŏö>ć`ĺţ ă„(ŹřJPňććÍŢĄ#őčËqLŤĐ!Bk&<#€A €€p€]T\$5Ő5Ţj—v*R@FŚřĹŠ1ŘŢqăĆé)*1Ť1З§Px‡íDˌÓŻš !ČŹY3}, œ`ʔÉţërx ńmŤhH¨$™3gś„şxćΝsÍm¨şY´hAŁľď÷ůóçůĎŰ+xnźq­QďĹ@…B2Ä|űöÂMkš˝ßŚ‹Ů2Í|ŁŮžĘ1óMá;šy=&PůőĄŁr߸1rëˆaŇ_›'Nœ’…ć›×ö TˆÂ’Ó!ŽH—8cźŐ¨/ńԚ°ÄíwĽ[CŤÉŹ5{DŕÔȨÄ(-+q™eEE`‘â4?ZŠŔáDDDD= IQuľŹ}áŮvç-zycÖ%ůÝáŁzýě~éňĺëŚË/‘—/dé •*żXź@Ε”Ęwwď“EĹ22)Qž0sš†-xܝ/o”Mž(;!ľć[ÝON›"k‡n°^, Ő°%;G^żőFýfńOGËS§ÎH•9¸Yi‚–ĎϘ*1MsčˆäTVÉ7f_ý6ôŽőäKf[g™mnlŻ›çöŻ3gĺ—Kęc.•WČ{7ž!ŻÝz“˙śhsż9y˛ůöuć É{`tš˘RŢóęëRižÍ>žď ěĚɕ/œ§Ăq5ëÂí“ÓRĺ[sfJźů–xíó/Ë_Ż_.ƒźłCťć^Sě7Táů ?ËYßshj?ÎA źc։aPť­Ëćçü o_†łnTĹäUUË8ĄBÇĺŕpę:îŞ)Ú}F˛ŸyGr^Ü#—Í)÷ŐýR™uEĚ?–/ČÜŐSS'…ŰOJÎú}şœË/ě6§=& )1ŠGˆˆˆˆ¨çáj5T9|wîuňŘńSňí]{eNżtůěô)Ňτvzr˛¸DV>ű˘˙:TĽV{ćHXCJ ĘéôW“4%ݞR†ú†ÉćB $H ʲĆüżf Üc¸Î×}ĂšZFsbC˜Š3đül˙!Ůr)[úbZҨHh3ĎlŞG.”•ËŢź|łűjHb…JâŽîOlk^e•mZ6›^ƒçĎ]Ď_đ_‡Ŕ݁=iî5M‰şú:!ł^§ŚöăüţýäçiERžšß-&P{ďŠ3’_UeÖ_-ÓRő1˜8N>xD>đÚ&I4ŰqďŘŃ:”‰¨Ë˜˘;꼄*ľŹD!"""ęM¨P›,8@O¨şřżÝűä—ć€řŰsŽkpŸž1ŃZ]á'P‘ĐZ}bb$ŤźBŚôIÓËÍů(sŹbcŐŕAňÁ76˙’R 7&űÓÔ2\N‡ ŽHˇ diĚĆ̋ÚT÷éVi€~~ŕ°Ţ†*Œ•fűŢČş(űňŻČÍ֌ŃŢŢ$>“á 42Mč‚!3ĄÂk€áIŽŐœ–źŚšÜćůaƧ9'3ÓűęŹG¸˙ŤfŸĚÍčçŻđI4×c˜N–>ůÖ6˝ż=¨!"""""ę.8䇅ęƒŰÉ0 }9Đô•8xF•I„ďŕĂJ2ÍíčŸ2Ý׸Ýň×§ôňɢbyďĆMZŐ ĘŽ¨” _•›† ‘?9Ś•8ř˙éžÚk%Ř0TL 4ő0aŹ|nëI0áć'MĐʒÖ@3]TŸÜš~ƒGşyÄ0Y>Óű¤´T SB`ȓ%˜ůćŚ^1‰KŢ3z¤Ţ§%°˙w×^s˙!ňšéSäkłfh“[„˜i ×ĆM˝ŚMiîľŔPŤ?;)s2Ňő2†ýńč mČż˝ĆéLN>~JGPŠ2(>Nˆ:’هvŘśîź}DDDDáÎтëśËÖy§í§urůNžĆ] áBJMMívé$Öô“˜ĆŇmk͡ĺeeeŇ˙{ß ow(zDÔüEÁßë'Őů*śj}Ő[¨ŞŠ‰‘˜ëŻ—ŒŐkÄÇ ¨;Đ×͜źďu‚l"ÁĽN_hYPP żůÍoä?řKw‚ eɒ%ň‹_üBŚL™"DDÔýářŁŹŹ\p8!.—‹áx7⎨œW_‘Ş $Ň|ˆařř"3Ҝ0ŐŃz‹×Ěö“Zçň—żb>w%˜ ‘úoÁúüՙ˙˘˘"ç™Eć„éeŃżĄÎwrűNŰŠŢöÓ*䎟—€óŠ*ĐüCN0ĂęŕkŐŞUň—żüE/#x+˜Ç>Î[?ŻłîŰÚŰť?ŁŁŁ5PéßżżQ÷Ä@…z=ôô¸íĽ 23˝Ü=j„B‹3fȟ˙ügٸqŁäççűC;+čź­šoX‚Ýߤ4ś|ƒ3}útYšrĽôéÓGˆˆˆˆ¨{b B˝f•yóöuBDd‡e¨R3jÔ(ŠŤŤkP](°Š¤ŠŰ­ĺ‡ş KllŹžœNöŽ'"""ꎨQX‹A˙s""""" """""""˘1P!"˘0Q´ Q{đžżŕÄšaˆÂ"" uunŠŽŽćô•DDÔ!¨ŕ˝Ćĺâ!Q¸ŕżv"" .Ů‡^‰ˆ¨#x<_ƒs!˘0Á@…ˆˆÂ„Ă?u1Q{óžżđ=†(œ0P!""""""" """""""˘1P!"˘°Ö]Çş;ü˙#"""˘îˆ …-w]˝dž,“œ R[ăśbŸőŇş2đ˛u]` ărŸ`Ëid=ƒŸ”)CÇ%IrŸ(aË"""˘î‰ …%„)ůٕ’uşLŞ+ÜâńtŸR•ڏDD•Itl’ÄĆ󭚈ˆˆ¨;âܑDD–<îz)-Ź•šŞîŚ@]­GƊjĽśÚ#DDDDÔ=ńk/"" KőőőâvwÓ*BOwmđBDDDD TˆˆˆˆˆˆˆˆBĹ!?DDDÝŤQˆˆˆˆzV¨ő`GNŸ>#G“ŐŤWItt´äććÉɓ§¤°°PF%cÌÖű]¸)‡‘řř8™1c†$''IDDÓ0ęčâĹ,)/ݐÁƒëcąŹsçΛĺÉŘąc$11ĄÁcjkë$''Ç<ŚĚŹ{Œ8ŢďoĘËËĽ¸¸D 诳ľ†f˝ńƛҿ†¤ŚŚšuȸqăÄĺr QWb BDDԅ*j+$Ż&_ŞÝŐŇב"Š }[6@NNŽźöÚ&@9)K–,ÖÇnŰś]ŠŠŠĽOŸ4yýő7$--Uϝ;ßŃPĄĆúő/Ë-ˇŹ“¤¤¤fÖPŻë¸t)[ŇÓűj uuuz›Ű햊Š )((”¨¨HÁ<Đ.Â\”ěěl x$&&F—ńÄOĘý÷˙§Yo˘†5ŐŐUfÝĆččŠŹŹŇŇR]nJJŠ>ŽžŢcîWmśă˛œ?Á„DٍQ—c BDDÔTHŕ€Ţél˙řz„Uš˛Áł]ĘŞKdᕱ2{B‘–­ŤŞŞZöďßo’b P9‚`ăěŮł˛fÍjéßżżŢväČQ EeáÂůVüčG?••+—ű<śŹŹ\ˇ*22҄#QţĐ˘ŚŚFO>,¸?‚„)gĎćȎ;$99EJJJäşëfšmŤ2ן×őÂňĺËäŔƒrćĚYŮ´éM™;wŽn*_°œiӦʌÓÍcΙe˝cÖW-'N”ůóçʕ+şí‹*+Ťô5!"""ęjěĄBDDԏÇm‚rsĐ_Ňń¨î¨“#u§äĚŔɍ,wMm‹;Š`{233%;ű˛ &H||ź./??_úöíŤAILL´Œ9B+CpC€N`čϙ3çthށÉ[om‘Í›ˇČĄCG´"¤Šui †­_˙Š,[śLŚN˘CŽ\š˘,¨>šőÖ[ô1§N’ ĆËŔäîťďÔĺ_ştÉlűxY˝zĽźđ‹&Đ)ÓeΘ1MŤm°\ÜC˜°>"""˘î„*DDD¨Ş,—ŹSE=yn‹+GZÂSď‘üň<9Ú7GJ咞]#űkŃch °řÇ?ţĽýQPša</f‹ËĺÔ TŐŕ~MĐ'Ő'Nœ”—_~U˘ŁŁdüřąúӂ>'vƒÇ 'ŠŐ÷¤9¨HAXƒ^-‘‘Ą•-ęƒmĂ2‡îŰŚz˝ Ő/ŘfÜýTPƒëqTŤ ’•/‡P CDDDÔ1P!""˛ąW˘TäIՅ3Ňgütď$<ÖMÚâ$°–¤Šž'ő nמ îŮUwHň¸E˛j%ľ0Rú ͧ´Ź „¨č(,<'UU•rúôiY´hłšp!KďłgĎ^˝îňĺË:ügÁ‚yúřźźü}Hş`؍u>°Y- ㊏ŹÔŢ'Ö~Bp‚Ëó9*ĐĄAL0L Á N¸ ­ap}EEĽď˛CołzĆ @ÉĘĘ2Ű1E×ęÔéűŤŹŠŠ5ĺ"""ęz TˆˆˆÄŰÄ펕şšjÚĆc„Š3'%6ˇP\“#́|• đśéđ ňß˙ô?§Ă8xď+śűáÚĘş*9V|\vzIš3A˘óke°k¨ÄĹơ¨!-îƒ*;î¸ÍnQçĹ×ËŹY×i#WôIÁЛ .Hż~é:*>0DčřńşŒĺ˗J\\œ™6ě—íĐTC…6o~K‡Ľ§§ë}âeذaśźůćfmXëp85 Á튊)ş­))ÉÄ¤ŚŚÉ¸qcuhŃđáĂtšVŻĚâƒmOKKÓĆł¸~ȐÁş,<Ţ{[Ş””kU ŞkZZECDDDÔ¨‰xűä^”’ËÄQ['ΒR‰;~Z’*Ť¤đÄŠĘĎgd”8"\â0ÁŠMj5!Š×!A‚ƒ{ ԛ0%&>YęŞ*´B#&!I*+Ę$Ƅ%ވHqťę%Ť,K^Ď~C˛ă/‰łb°¤EČČ´Qâtľüma‚ @ĂÖř ÎŕƒpS":T+J0Ónǰœ ćkÓZ„VXŃ"˜.ůúëWh(ƒP a –‡ţ,¨śŠŠ)/^Ҟ-ńńą€`¸*Q°#F ׀$**Znźq­äććj82hĐ 0róÍëLřÓO/^¨Ă—`ΜŮZƒť‘‘¨š‰”nX­AQWc BDD$Ţa8¨9q×TK}Yš8ϝ“ŘÂЊ1!șÓR’y^jq›ŔÄc7§–ޘËć‘&hńDEHË))ý‡Hĺ•\‰ŽŠ“”Cĺňĺ3’’>H&¸Q&{JöÉůłÇÄąbÔUIżšd˜1ěj8" ö•"ÖôĆvhV‹S¨Pi‚S0h@‹™{:ŹU9“'O6aέ>ÁÉZŻĄ ”@x üöΰcëÂG˛Ěě ă0§á¤Śi’ŚĚĚ}efŚ×ţen_™™šM1eLŰ´I i°a´ścś…˙œ‘V^ɒ%3Ý/ÝîjwľZÉ{ÎÜ{‡˘ 3œŽŮ€S& ‚ ԇåĂ!)S°Ah"¨‚ ‚‚ŢÝzôC×î}ÁŔœőż~ƒmIk6~ô¨“ČŽ^ńҕ°‹J8aw;ŕđ¨-SŸcSď-á:w‡ĹaA‰ť归ąŮžk Ö ¤¨ݔ€2Łß˜3¨UËrŃÝÓəQ…ű´6˘ł˙ţűjĎbäLAhp–ł>úÓ§ď†qăĆBĄ!ˆ "‚ ‹4,1ŢtĘ ś!ś[7¤öčŁ$%’lĎΕKQ”‹…Öľ( ä¤Á9{)ŹvXݝ ĹfąiO“˜˜X¤Ĺ¤ '1ěšpU:Đ#š †÷ŸŽÎ]s0ßąîÔ $ćڑ׹ąqőöPiIř›1ĚȜŕVĄľÂ)â™<›yAŠ*‚ ‚`‚š†ÓaG•Ĺƒ´œŢ¨´W`ăÂ?áYłą•ĺp9­ˆIwĄ(Ëǎ<ôŘPŽžîNˆłĹëÜ*i]z Źp;R3ş 59}{ Ă—\,V¤%e 5)EśrlvĂU^‰nE‰čҧ‹ÎˇŇÖÄA„śCÝn—Ě&BŁ ‚Š ‚ h<şír{c볆ŽBJV7XŹV$¤f`Ky˛@ŸŒlO[ľJaýi+Ś Ţ2ú#ÖÜ(p#1{0˛2ş!99ŠŠ™:™Ş1ǏÝĺ@=y”8ła$öEVJSAAÚä,‚ €NRXRZŒ-y›Q^YĚŽ˝Q^eGĽÝÎ˝Ąź{7dQ"Kż~°÷IlHZW…ƒĆĄű€ačÜoâťv;~ÁöĘČPbLffW%ŚÄů?ƒăĄ•Î ŹwlDi†1ˋ0¸ó¤&ĽAäA„Śeǎ(--ƒ]•땪œßž}ť.űAę‹x¨‚ ‚’:ĘĘJń×ó°üŸĺJIF§´lŹ]ąvO&LÜ[ <ŘüĺÇHŰš+áą;ᆠ?nţ‰IpŮ,Řa)ÁŠĘľŘľËdX-1Ś”(^šÄ˘ţípcu\žŞ­č’kCW%ÔÄÚdŚ A„Ść–[nמˆŰśmáß~çŸ >ú :uęA„ú ‚Š ‚ (Î*lßą yEŤPšŽÖ¸V˘Ź¸°ş1˙O7Š KŕI°‰VěP‹gE>z”e[ËQn-G‰Ľ[3*´ č9źââfíab[Ű­(DnJ °ąӇ %>ľŢłű0yîć͛ըkúö탴´4˝żźź[ślQŁŻůČČČĐÇbccýďăˆ,§;Ţ´i3ťžŚ8;;;좟~||ętݜž”3ję{ëÖ­›Z§ę¤ÜĎŃâĚĚLôčŃII‰Q]“÷Îišů˝8ýrC“áňˇmێ 6`Ȑ!ęşéŞĂĺFUU•úœľJh+SżMwőuQÓ8ý›Ż_ż^nWĄOŸŢţŠĄ{ăßcëÖm;vŒśŁ-[śęë4H˙mxŽĂáÔżwˇn]Ń]‰j23’ 4='žx<ü)mƒ´ĹSO=Y•=IA¨/"¨‚ o’BęÜöŔĆÍëPQä@Bz,:ŤNtŃö2äĺmƈácÚ=óűl…%HůˇŒ;2şj7”ÍĹńÍÚŻĐ+Ž?2’TGßZÝŃwšŘ°c˝Ştc°>!eÉNÄ.(ĆN=öDb\tBB(ňó ´ŔÎ?ăť°ó^QQŠ;ë<§  ;wŇ⁢˘",_ţŻ2˛Ő>›žń˘¤¤ #Fě¤Ev4ŘᏋ‹Ő"ƚ5k´˜Đťw/¤ŚŚFuoźNaáäćć˘WŻ^ZŔáŹ#F Wżç}xΆ 뾘aŔďÂsyřř@’Ű6›Mw~âő˝ń<Ţ'żłËĺÔ˘Y8ŠßWYYŠ;Wü(.ŸżdÉR$&&ę{ÜşuŤž~ÜÜ<-UUŮľ0|=ŠOk׎ENNtéŇĹ/zmܸ={öDqqą>7;ť›ž÷ĺ˗Ťó:‹ "ÍŔ!ƒľ¨ňý÷?ęňŽS'‡’A˘AAĄĂSeŻÂ†őë°nŐF%ޏaKr#ƕ˘„“*$ĽÇŁŹČ­:Ő[`铌ŠNVXË\č]Ö Çî„ř¸X• I…čÔŁ ”Hbxr0É펊řjó7HЈĹć‘V¸UßšŰÖXdęÝ pzô왃M›6)AÁ­÷ą“żqă&í Â}@(ŠĐ#cÝşőÚ3$''G (ţüóo 3ü|~& ))ÉZäĄ 4xđ %ţ”Şc‰Zźŕyééij_‰öéÜšs QĹ>( Ă{ăű(’x<Ő߉Є ”¨’ (zÔPPá˝ÄÇ÷ÔŻů˝ƒż3ż'żgeeĄ´´TżŸŸăń¸őoÂďÁűˇZ˝˘ŒĚ6"Mˎe˖k1”6[VVŽ~ýúháô§Ÿ~ÖvK[>|˜.ăAę‚*‚ BĆŁÓv%¨lÚźŰ ś˘— úÉŤWŹA7%ŽtďŢţžˇ­A)âPŹ:ëqšNôNěKŒ—W ŕtȓGÎ3Ľx”–RĺŹŇׯtWaYů ,­\.Žt&¤ĂVćA_w¸ŹnT:+[LÝŤd6ţ)$X}Ţ0†Ç=čB݆›0̆BĄXPTTŒQŁFjáÁŰšOĐěxüóĎ"í-’™™Ą g8_Óă%žCfذĄű),0†–… *áÄŞG‡) 0ʆžôĄp3t萀÷2YdEEšA^°ŕýŮôØřůÝyżôd9r¸ŢżfÍZý™Á‚ =Lř›ôë×7`?ď…^(ZĚ"?RSStŘ˝Gřýř~žĂŽŗp%üěĚĚ,ý^ţÖüýů9ćĐ vě(Qsăwăš;‹Ěô$Ë‰Żžúż˙>O‹ŚŸrjŘ_8@•1=DPĄÎˆ "‚ tht§:!}†öCiZ1’˛łT‡ž™i‘”Ů ą.¤ŒMCş%ű+ĄD $‰[ËaIŠĹňÂĺ:Œ‡bU§œeĎŘ'^ ĽĚä[ŠđcúR8ˇ•˘b@ޒ܈_]Žž)ƒđqîlôŹĘÂÎ='!K}iޟŘX›/˜…bʆ ľg Ĺ~_›-F FÇ‚Łśô$á1îKNNÖ zZžO!T‡?&ĆŞ™`AŔȓB‚‚ÉćÍšZa˜ Ţϔ)ťhäßWčýŐ×´i‚÷Ëk3”‡_3„Ć€÷Ä}ź_~ż§áŠc† ˙FъźćčŃŁuXÔŞUŤľ÷ ÷E Ţ/… =ü)ôęŐS{ţđođ×_kŤ1ňÁ‚Pz­]}őAh DPA:0ŢÎ5;đŽXţM؈2ËFx˜Ł0UÝĄ;{Wé3ÝĽJ>ů×­ä'ćŕ/Ě]÷7 qą šW"A„× %Ą0’””Ź=VC€9V(H^,(ŘĄ_˛d‰úŢ#ľřBo zVPä řŔ0îgţzšPˆp:úł‚;ý^xýPB=4(zđ}<ÎűdŘϢE‹Ń˝{wFd|Ś„šLHđ=ň{qá}Rˆ1~KŢ#˝g:uĘŇ9\VDaʸW§ÓűťsÍ×Áż ˝}8â=ţúœAÄ,¨đˇąŮbőç ‚ ‚ĐöAEAčđŘ]U(đě€;ƃ˜J%Š¨ŽŽŐjƒ­Ę‹IÜ._I;äVľŐ§nŤZâb”Žâ֋E‹a‚ľŸ‹UŁ.‰8NŸźS *;Űŕt;PÜř:~ {ڑo-Ć&ű×ČZ›ˆ)É;ŁOÎ X-Ń%(Ľ×󧔖–ů’¸şu2Tć ˇĆʕŤ´¨Âd˛H†đ0oÉÚľë|)I:ˆÂן.˝+ /žĎDˇŢÄ´˝îÁŞŤš÷KŚ_żžzFzzđœęœ$źŢE žÇDľfčÂĎŚB‘‡ď›bgr8źűźŢ)I>Ż›>*)m8Ď~wo¨ĐvŐŞUÚk„ż!ď‘6LźůfzhÁŠż(†Ź^˝Z}/‹ö2~ Ż7K‚§ĐÄP%Ž™L—ż˝ix]†<ńžx˝S$)­ ‚ ´=DPA:rŒ°&Ţ“ŕň™ń柩NĆË{äËař=ǎí›jڊvÚI‡Nńúü] Ďçw‘ü)‚ ‚Đöh÷‚ŠżÂ‘ˇ‚ ‚ “ŽɃžÖl÷„Ó;œ¸=J]Q=FbcU§ŢbÓ!9\XťxCUĚ3´Xô1=Ť%†2‹:ÇĄĂex=‹Ăޏëd°ń6-ŇŘbbőőăă‘‘šĽg ŠŠ@JýěŘ{…ĆUBÍzĂNžŢbŔďC/‹şî>¸żśë™ďB‰ůŢ̘˝Qx\ęz8ÂĺGaň\3üÝjťoăw50Ÿk=źç`IAÚ>ŻËŽ0XĐ!nĚ$tž‘6ŕz⼠‚ B‡}ďŽŇ¤iםŐîÍękfgCA"ăkX|ŠˆEO„ll,áŻ`ńÖAŚÖDđů<ź‚ ‚ ´u<Ýť{űŕh˙ƒEí>˙€z†~ý ‚ ‚ ‚ BÓáęß_÷Á;Â`QťTĚÉ÷s]2` AAAAh:Ř÷fÜÜ'oŻ´ű.LW•žĎřńAAAĄńaŸ›}oöÁ;BHsťT W#ÎÎP´ËĆaAAAA Ő×fŸ›}os_ź=ÓîÔł[‘ąđéőRI‡ý°Ă ‚ ‚ ‚ BăÁž6űÜě{bŠŮKĽ=Š+")-㡸$$$ `ČP¸öŰ‚ BdžőƒÍfiľÓúY­˝‚ ‚ ´vŘÇf_›}nŁ˙-IiŰ(áźTl6›ţo;ö#ސđA„ŒU‰)™ÝdS•~ëŞđăâ­Č욀ř„‚ ‚ ´ZTŸš}köąŮ×fŸťŁx§:V“pâńxôşpčPğwŇý– ‚ t,(˘¤wŠCżŇ°mSv7Zlo$§Ç"ťoâDPAĄ•´Eťě˘Ă|â˝bŠábí Î íVPĄFńÄX›˙ †ÇŠĂ‹-űě‹ő¤ŽZۚ5đäć%%€ťu4ŹA„Śƒ˘J÷>IzAAÂ@Ż“ÔT ;Î~ýP2`*ÓźůRŐb)f1Ľ#L›l‰bżĹôÚŘśšÖĆă[lž%N-ąjɰŰsŃBPL ^ť\.Ľ—¸őÚXŞý}Žą˜ß+‚ ‚ ‚ ĐŠ4ź’@lŜ7Ľ5ˆ)qqą“Őj‡ZŘ١ŤĹé[\žĹmZ<Śľ!˜ˇ´­i÷!?fOănüŃ)Žđ0 (Ü'BŠ ‚ ‚ ‚Đ‘ žŮxm^‚sŚçľw:DăiVĚÉjƒ㾁+‚ ‚ ‚ BGÂ,ˆ„TÂ%žíBŠA‡T ByŤ˙Ń͢Š)‚ ‚ ‚ BG&”hœŁ4ÔvG C *$”ˇJpŇZz§t´AAAA„ÖD(1EA!Ź#ŹV+bbb`łŮŤAh­ˆ "´:(œTVV˘ŞŞJ (‚ bMĚŰf{aEhI̢ ĆćýĆł)Š ‚ ëö¸Řív˝őH||<´Đ"­ T„V;ƒĺĺĺZLĄ&ÁBŠŮcËX‹"ŹÍI°HÂF0ŸIcż1ň(Š ‚-ŹG***ôBQ%)))@Ź„–DĄU@ĽŹŹL:‚ł`b)lL$''ëĆE\\Źľ‘†Đšŕłęetčrž˘9C8 a… ŸeUA„h0źŘö ´4"¨-NiiŠxĽB‚….‰‰‰HKKŐkAh͢ ăߓ““ĐŠS–a,..Ńkă¸!а"‚ D‚m#ö(Ч¤¤@ZT„Ľ¸¸Ř)B5ćP#!3;Ľ]şt!EhÓđůĺBAĽ  P'7ˆ°"‚ D‚˛lĽĽĽAZ ń Z S!4Q !Řá*5599=DLÚ |–ůLóŮ6?ëĆó/‚ ‘`_‚} Ah)DPZşé‰˜"51:“Fx;˜™™™čÔŠĄ=Âg›Ď¸á‰eäQEAˆö)ء„–@B~„f‡îy’3E1‡řB ×YYYČČH‡ ´gŒgź  Ŕo ÁÓ- ‚ B8ء°Ůl’¨VhvÄCEhVŘAäl>‚ „Ć<rzzšˆ)B‡Ď:Ÿůŕ)ÁAÍƍ› B5ěc°ţ„ćDĄYᔙŇH„@Ě3ůIޞH˜ĐŃŕ3Ďgßl Dę A!Ź+ŘׄćDĄŮ`ƒ„úB ćŽbőŒ>.tî,bŠĐ1áłO0Ôˆ¨"‚ D‚} Ö‚Đ\ˆ "4"ŚBxĚÉ8“““e6ĄĂÂgŸ6`NÎ,‚ Ń"}Ą9AEh6ŞŞŞ ´=>úč,[śBă<úîí@şž.yS„Ž m€ś<ۏxŠ‚ ‘>‡ĐœČ,?BłŔNšŒ2ňÖ[ďŕ…^Şőœ{FDsňË/żâ–[nGŸ>˝ńÔSăűďŔă?‰ěělużĎ@h|ĚÓÄĆÄŘÄ;%œqʔéű˜ÉȐÁ8űě30qâ47ß|óŽžú: <Żżţ2„Ćƒ6@[0O#nžőG¨Ź‹:č0˝=~ü8Ü~ű-ţct‘?ŕ€Côö܇aÆBÚćgü™gžDŻ^=ýÇ>ýt6yä1 :>x?Âyç]„ŐŤWăúëŻĹÔŠť˘9áôŔGyŹŢ~űíב––!Ö|bcc!M´N„f…šHçΝuĽÎĽoß>ţýĆ>.IIIhiŘQÝ˙}qňÉ˙ĐtF†:ľCcřđT§;˙˝\p ţřăOí ڂĚöÓt,Xđžýö{‚Đ<ěťďzŮź9BÓ#}ĄšĄYp:ŮcÝőBţýw.şčR˝iԄ ‹Ĺ‚悎÷]t„ŚÁč,z×ńN‰‚;î¸U‹ôZ9çœ °pá?ÚŰkܸąh‹4ˇMˇh ĹĹE6"żSăňÔSĎ`„ńHMM… B{BúBs!‚ŠĐ,HśíúQ\\ŒŁ>^o_wÝŐx≧ôčüÍ7ߨE˜_| K—.GBBźąŽSO=99=ôůgŸ}Ö­[Ż]ş?üđc=’Ÿ‘‘SN9 ťď^:Á°…×_………şC:iŇĀ{˜3çgÜv۝čßż?üa˙ëɓ'bęÔŠxůĺW°cGąj”ĂĹ_čw=]˝z {ěIŹ\š˝{÷œ§Ž_Ś˝úę‹ÚC§#cuŻůâăă DG\\>ř@-¨,_ţŻ˙ŇĽË´­p?×ŃŁGáüóĎŐáA„6ĹçóŚ›nPĎ˙ˇj¤ţO=łĚYgĄF÷ÖçÜsĎýxűíwqÜqÇŕňË/Ńű^ýMüďa—]&á‘G yOL„÷üó/â“O>SvQ„îÝťá€öӜɐ#Lˆś6bÄpý YúĎN€m6axoĹÄÄčý"Ź4 ëdńôÓĎůŸńP|˙ýú9ݸq˛˛2Őó?'žxœö úĎNÁśmŰqÍ5WaÌiزe+N>ů4ýž×^{IOƒýŮgŸăá‡ŐuÓsĎ= Ah-ízÓ÷ľ×ŢÔíŽ vVm–sý홢˘"Uć?Ž˝şŘŽ:őԓj\‹9;Ţxă-|ýő7ęütíÚ{î9Çs4 ”Íœâ?÷´ÓÎÄ̙3pŐUWčN˙›ožŻžúFľĂv GîŞÎŘ_×F˜#Ű{O<ń´1â`™gž!2Ň÷š ůšɟŇp÷Ko‘ěěXťv­j_żţZ¨Cúő덗_~•n ˜yŕ‡PRR˘;Œ[ślÁ}÷ýO7ŒÉüůóqď˝÷cÓŚÍčÖ­;6oÎӝÁhXąb%ž}öyUů÷P7~ţůW=ÚIvěŘĄŘ×ańâĹHIIVŁÜzëíjb}7w…訨¨Đk#Nš ĎÓO?żü2W y˝U§ąŢ>í´ł°jŐę€÷ţďj—ŕ‘#‡cýú ¸ţú1wîohKžţ%=âĎzyyšn?ůd`GrŊşńÝż?ŐI͂Pڂ9äGB—#Žđć™řꍯľŕŠŮłżŔ]w݃źź\Lœ¸łÎ[ôÁłT'ôý÷0rąŹ' V_gńâ%Ç&MšAhlܸQ ˝Švި~üń'Üxă­úŸóoźEˇąHˇn]ńčŁO(!qkŔ5(ĚPIIIŃŢÇŹ›^zéU}Ýřřxěľ×ţswÚi'%¨ĐŰ÷ß˙€dzŸ¤Ĺzś×{ě u­ˇôqŠ1×]w˝(XŞę•=@›"#}ĄšAEh¤!ÜpţóŸU§ě1œsΙzĹá°ăCVÂĹ•Ş˛˝ťí6U łf}đžÝvŰM'd‚ŮîÝťkĹŢČ71kÖÇzMo“'žxD{ Đ&Š‹Kő{îşëv=’CćÍ[ ×…/..Ń#9O<ń¨qîŇ÷*ÔíDoFĎÚľë´×a‚MBAĄ@3gÎP Ůçő2}únzôđšç^x? >účCŞńú°?üŽ#ń áôÓOĹ˙ýßőç2Yáy督÷˙ôÓĎ畕•űď#‘BMh Rw4,ëYözw>řÚHœ~啗ă’K.ÄÝwߎN˛đçŸkĆđh\źxŠ^/\¸Č˙ţE‹Ź'MjţÄт •¸óÎە ~ĽZߌË +WŽŇޏœĺűîžűÝćšő֛PZZpă?—]vą˛Ľ´­Đ˜üöŰ<-°_~ůĽţsݏâR-¸SČ˙îť|מ^xnżÝ+äźńĆ;şŢúúëoőguéŇYˇăî˝÷.zč!"#ő‡Đ\Hȏ ´Ř)40Fü8RČĹ̆ ^Ӄ…Řl6ôíŰ[4ćůGőׯ_Ż×ÓŚMóŸĎm6"‘““ĚĚL˝=pŕ@˝fŁ„°ŁK›o¸Ě2Ě(¸C+x‘Jżnł°ƒgK–x;v{îY=¸×^{â‡~ňwě (B̘1]  jĐ^2ˇß~rsóüӍSä1CˇíAƒBˆą‘ĆÇápâÜsĎÖâ˝?űlśö 2ÜäˇoĎ÷{<Ţ|óm5ŢĎş†!r}§×$ë•ţY¤gŚŁgÖ˘EKÔ5śë0 ää$]$­ †ŁłőíŰW‡j2q,Câ\.oî3œ>Ú­[7ݞ2ŕűV­Zƒ‡zD=óŰt¸3áŕW8XWŠ—§œĆĂ÷ĺĺmńˇÓƏďOZĎö =„Ahˆ "4 Œw—qĂ0‡‚P!Ěť0r䈀ó‚§ĎłZŤs „Ë;`ţŰDűw˛ZcÂ^×íö6ČÍÓŐ÷,ԎLćq`ă5))Q7l>úHŤ!ÁĎŠ9žÚH^WóYv×8' :ĺ”3´(Cťdžv"˝î܁ˆ=DFÜľ›–őěžxâńZě~ç÷tޚňň ˙qŽÚ‡#ö葭Ëř1cFižĄuě`Μ9C‹ë~ř‘ß’Ayć…ć€ĎYllœ$˜ÎXö_rÉĺZ€átă,˙Y7˝÷Ţű¨ ăüzżÓľkÓçťMďƒ’kKh.¤Ő.4 ŇAl\ŒQť˝Jra2łUŤVˆ‘`Ž ňÝwßű÷1v¸Ąô왣×ů4Fć˙=˛×KGĹ\éKľČ<ýôjy\ψĹvł˜˛ÓNĂôšÉf ˜$Ďžýš^łQűůç_číúëľ1Ű˝Zř7ac–F3ĆßÍZ˜Wˆb G2_xáížÍmĄ~˜mAĆMsŠ 0@{¤b aˆóvŠäF]äϚššÚ3…šQ˜o…PH7nŒś™Ůłżô3‚аŹ6lˆŢ~úégľ¨BÂóŃGŢ0ç#ëzňš&Ěýłuë6˝MOBćá"ĚAgœĂ0 ­[Ťs¨ŹYłV‹)@b}Úi§č¤´ĄîÓů4@Ż98Ŕäý´/z9Οż@'ÂeÎ"ăó,X óŤ~řBd¤ď!42\ 4 f7bĄá}ôQzDđ­ˇŢŐ1žěü˝aÆE}C=HWÜ\Î=÷B]ŮďŘQˆ†˛Ç{ŕíˇßӍî‹/ž\-Y˛Bíđ÷ŻŞ˛×IaCöÇçčđz‹P,a™?3ĂýÇ÷}íˆsĚQzÍ|/˝ôŠ>çCŽĐçH&'$ qťîşÔł~nŔ1ÄáÖ[ďĐ#ĽLř)Ôڂ)MŸYć|ŕ,lćQpîg^&Užíśť0~üXěĐe9Ă쌐9&Ť%‹-ŇIČ)jRdŒ‹‹×X^‡áŸ‚Đ\œqĆi¸âŠktš~ 'kÁÂČyÂöČÁp>˙ß˙ݤ…EŠ%,ďée¤áÜfťŠĎ2ËůĄCëë2/Š—™™ĄŸsÎxőŔŤ˛?&äŕTvvwJtÇwaćĚÝu}łëŽťč¤ţ\pąT&ĘsXŃĆ8SĐ[o˝üüŐNť@]#[ˇ­„ČH’ĄšéNhÄŐˇqĄ‡Ę=÷܉ącGŤĆí2üţű]á˙ď÷ęé˙˘eçwÖÉ?LWínÝş¨†Hçăă(ÍíˇßŹď“3 qa˛7Ą&ć#ˇ+*Ę!Ô>sĎ>ű¤nŒŇ[„#‡LźÉ}ů3sá…çë°6^9:Č)Ć9]&áě%]tžî82Á2÷Ÿ}ö™ď§ÇËńÇŤ;‘q(lŢu×mzTó‹/žŇ+ňÜ×ÚB°}Móů„JtÉdâW\q™îÄýöŰ|Ź_żÓ§OӉ7“’’ô9;wÖQ2nÜ8ÝąäL$ŁGÔű† R#UšÖ?ü?xœÂĹY†ˇvإڃ$8ä§k×nJŹ8G{Ş 7ÜpŢfšsÓM×ëkΆČsYwtéŇE‰-WkąćűďPuĎZœţy5îëâ‹/Ôӕ3gó N9~ÜqǨοM×#LDKĄĺú뽟Ď\uwÜq›năq2€ĘĘJü÷ż×@ˆŒô=„ćÂĹ~‹éľąm5­%ơŘ|KœZ8̚aˇ;ćBčĐĐ˝‘î‹BǁSý•””ęĆa§ő´ÓÎԍí?|ŻĂ{aO—Ě]zqąńf„MĂŃGŻĹÎ>Ĺd´Bë„Ó\Ó>8ĘȆ1ËCTqE +Œ[Ąîp*dNwÜż=ËĄĐž`Ȣxü qqą“Őj‡ZkÇ<Nßâň-nÓâ1­lEćmmkDşšhl K’ÁŽg k*;=SŚě˘F'Sý9T8ăŠTp51ěƒÂ gČ0FĄ#B -BŠ ‚ D ë ik ͅ*BłÁüĆt˝Bű†nݎÝv3^ýM-¤°cÄ0 Î&aä¨čč˜gžâśya‚aT„Ž m Ř. Ä;EA¨ŕœg‚Đ”HȏĐl0œÁČś.B`ŘíĂX"ÇP)U„Ž˝S8cGîc,î#Hȏ „†šg$)­@š#äGüh…fƒ§€Ą&ě$ŇE• m…S4 BG„Ď>mŔ°PA„ha_CÄĄ9AEhV8â.cAÄSŒĐnWVVaëÖm„ŽŸy>űÁö ő† ‚ ÖâÝ+47"¨Í ĆÁÓŐ BG%¸“Č×ĆČ<“qnßž]ç’„ŽŸu>óF"Zs˜+‚P„űB ěcH"sĄš‘¤´BłCW<&)­ŹŹ„ ^Œ‘xÎôc4˜[%77Wogff@Ú+SřŹSL1DEńNA˘…ý I- ´"¨-BJJŠî8ÚívBGĆ<ۏńšHî3b€ŮŃd˘ZΔ$í †ůž)†WJ(!E„A!qqqşo!-*B‹‘––†ââbU„!ޘg1 N¨ĆgYY)şuë&ńÁBť€łů0mEEe€gŠ!ޘ§K1EAĹö)ĄĽAEhQX–––Jř ř0‡ţ˘ŠŃąd˛Î5kÖ"==YY™"Źm )…(**ŇĎş1=˛!$J¨ ‚ ńĎĄĽAEhqXrt˛ŹŹ, ôA:FçŃđT1ň¨pŰĺrémîăvII‰öî˘Ýdddha%>>Î?Â/­ ƒ|fŤŞěZHŮąc‡ÎĄĹçÚ,¤ž)ćçŢźAÖ L@+9S„Ö€*BŤ€"]öŘŕoĄ#c˙áÚŠç6;ŚĆ(>;ŞÜ—ŸŸŻłÉm㾈”BsbBĚbˆąÍg—BŠ9éŹ9Ä'ř‚ ‚`†}$ɒĐZAEh5°`¤ˇJbb˘UŞŞŞt§Q:Á9UŒ}fa%8q­Y@1ÄAh)‚Ăv‚…sxO(EÄAÁ€őI||źS‚sĚ BK#‚ŠĐę`AI7>.œŮ„ ]Äى”Ž˘ĐQ2ÖfaĹOŒóŒľšą!ö"4'áfć1ֆČ΃E„A„ŽŮ{‘ĄÍôjä"­T„V˘‚ŕ%\Ů‹Ë|Ž)BKÎó$ŘE[„AAÚ2"¨‚ ´B…9VĚP`‘ΊĐZă΋EAĄ­!‚Š BÁd~mJ`„–&œ`"BŠ ‚ mTAÚÁÂJđ~AhÍČs*‚ B{AA„6J(Ahmˆ€"‚ B{EA„v‚t\AAĄůAEAAAĄŽˆ "‚ ‚ ‚ ‚PGDPAAAA¨#"¨‚ ‚ ‚ ‚ ÔTAAAAęˆ*‚ ‚ ‚ ‚ uDAAAA„:"‚Š ‚ ‚ ‚ BA%ÇAš‹Ĺ‚–Bl]šąuAčˆ­ Bű§%íź5"‚ jŔR BÓĂÂŘlkÍQ8‹­ Bó#ś.ąuAh˙´„ˇv:´ b~ŒmˇŰň¸ ƒšŕľZ­ţ}†˝5EÁ,ś.͏غ t ÄÖĄýÓvŢV谂ŠńÇçÚétÂĺr酯u𹂠ÔsAË혘˙š‹Ífó̍Y(‹­ Bó"ś.ąuAh˙´”ˇ%:œ \Űív­˛%$ÄŤ"Vm[ÄuIšÚ ŰM;t ˛˛JŰb\\œ.˜ b‹bë‚Đ:[„ŽŘş ´šÚÎŰ"–(ö[LŻmŤim,1žĹć[âÔŤ– ťÝ1­Ł Śz]UUĽ˙ŘÉÉI€ -GeeĺÚNăăăľęMęS(‹­ BëEl]:bë‚ĐţiL;o ââb'ŤŐľ8ÔbW‹Óˇ¸|‹Ű´xLký͟ mţĹűG/㏋ôô4)ˆĄ•@[¤MŇ6iŁ´UłíFƒŘş ´~ÄÖĄc ś.íŸĆ°óśNť/‰Ě‰Ş¸”——#%% Ąő‘””¤]xKKËüŰ\"ĹfŠ­ BŰBl]:bë‚ĐţŠŻˇÚľ \WTT 11Q bAhĺĐF]Žj›%ľĘbë‚Đ6iŻśí¨œä{: íÉÖ:ę.v/´Węjçí…vňc.ˆšíp8ôkĆ[ ‚Đú1l•śëM€ĺ1¸!#ś.m›śnëf×ćşş87佂ĐÖhŤśŢŘ6*6/´g˘ľóöD‡ČĄb$°JKKEk$TƒJY‚mł´]Úp4´v[!4mÉ֛şn–ş_hĎ´E[oď„ÖL]íź­Ó.C~‚•m&ÇĄťQll,Zš†˜ĄŢ+nƒB{†6KŰĽ 3k8mÚě:ؚm]„či śMý]ß:>š<Rß íö`ëQÔćî¸ ´hŻ11áíź˝Ńî=Třä399-Esd B{„śK6\ĂŃl]„úÓZm˝ś:śąźI˘šŽÔőB{Ą­Ůz$űŹ‡šŘťĐŢIJŠÎÎŰíÎCĹ(|Ě˙˜œĘŠ%ç„"œ˛'ʜХíNÁĆç›´1šŐ’śŢŘÔgTKÚ­ÍÖkëčÔe´˜mťśú\ˇ>Çňľš J!,´uhťf;.ˆ[ĘÖ“ş” bŰB{ĽľŘzctŽ˘ľéhD”p6/eĐVikśŢX 1žg({[Ú‘ěź=ŃŽ§M&ŢBŮÝäŔú) -ŒƒŻ#ŠĐńŞŮîˆöŇ\śŢ˜4DdŰÚ-mëőí\™=c™€GŽĄŃ9$źg.l\rÍŘrnsm|s ăľůs¤ł%´uÚ˘­Ó–ËĘʢ[Âü=âââô4łÁ6,ś.´˘ľóö@ťTŞ9hR˘UŽk$+œ‡J¸Ń-ă˜ŔB[Ĺx´#ŮP[*łë*ÂÖę'ś-´ZĘÖŁŠłÍŻm ' Iŕl•yš°˙óœŤVŔłq=,ۡ!Śd,°¨shŚ[,<‰IđddŔŐčŮśţ7b4âťg#>>6›M ,Ä,ŽDÓْ˛@h+´„­×GHá6§ÝúűčuŰE°–WyoĘXŕ |j?ˇÝ˝Rţý…{’ŤîBçΝëlëĄö Bk#’ˇÚ˝‡JSŇĐŃ,6ČŃ,c 7’e,ld™ZćëťKJ,­“hWŁŁ–””°_:R‚ĐxD˛ÇŕmكUZZŠňż˙€cΰţ51[rő9ąÚ o㝽mąŤÎ˜Ý+ĄeýZŕŻúTŚě+閍ŁÇĂ6eFŽAJJŠž)Áh „ęlIY ŃŃŃ4oџȹ˙ZX+ŞĐ˜d~ń.śtÍÁŽ3.E†Y‰+‚Đöč!?ÍuÝp 0ă5věŞ1UTTĺŤÜXżČŰäŘPRfCeĽ.ˇ÷Ďcu!!Á”d;:g9Ń˝ Ч0x@ ŇÓtC+Tc‹„*Í÷ŇZ ß­[ˇâ‹/žÂ>ű셮]ť˘=ápyđî‚2,XW…*§S$ŕČńɈ‘ŠŻ>Dă܈VL),,DEɏČÎü×_‚=GúĹÔhEÔÖ@cŰxqq1žţú[ݙ5j$̍ćBlşyhN[ŚCelsĄŔš#/Ÿ~Ëן#fk.tşL“ˆR_l[ň`űęSXÔRŮ­;ĘŚí‰Ř}BFÚs%”°Ň–ĘAŚ9l=šÁĎpŰčÜźfş?x-â w )čöĘĂŘÔľ;J˙QkłďśĐŽ„`ÚJűź!ˆ‡J=ˆÖĹŘŚş]YY‰ÜźRüţ'°pIŹQ’ÔţÚ ?§+Ľe\Ôů[EËźűcb<ČîZ‰áCJ1aŒ9=R˜˜ƒm.\›ťÁEÁhʔéţ×üœŒŒt :Ç{4vÝuŠ˙Řă?…O>ů k׎à 7\‡ÖČńǟ„˙]ťďž{ěą{Äó—ç9đÉ?ĺŘTčDQEőTa_/­ŔźľUČÉ´á QIÜ­mĎF#ԝhˎ-[6#Îózvú^ť'X?EAAŽv &áF¨›ťQlëfčQ÷űď?7ލSD9ᄓ‘››§_Ÿ~ú)Í"¨ˆMˇOę"ŚđYĎ߸ożŽ%xŘ*ĘĄ”&27-Žźű<Ÿźmťď ŰaÇ Ťg/-ʐŕ™šŤ,`[ćĺ—_Ő")í099 S§îŠsÎ9ÝşuCKpôŃÇcőę5¸ďžť0cĆôú^›6mĆsĎ˝€šsSƒ^ĹČÉ饎7 't˘îč’{îšożý.N;ídœwŢ9Z7őőJ1Öš›7ŁËƒ× qĂz4ęłzÜÖgtBĚ^éœ*‘„SńN„Ö…*u¤. 0 )MýgIž‡ŐëSŐţ†vb6ć&ęĺË<ЧťM*Á˜‘ńHOO÷ +‘ ŕć*|{ôČVÁBüúëoz9űě3p晧ëcG}¤^uÔh°ăuď—;NŒegŹ¨ÂŽĽšv\43ŁzĆA蘄kÄĺćnBŞíId¤,†ˇˇćA×ôůXłmW¤Ľí˘“ŘľDG*ƒŇ÷f`xÓ4Ś˙đĂOşךs'ÜrˍčÓ§7šąéöI´*ŽPäçŁxÖť°žő2leeM&˘„ÂZY„ŮÂýÓˇŘrđQH<đ0tęŇşԶ9Ë šgœqVŽ\Ľ_łăW¨Fí?ţřS|˙ýxá…gѡo´E–,YŠóĎż%%Ľú5żE.,w^xᙥ—BëŚ.žä†šŮfč]™ńäHY˛ME•39ˇ^Œ Š™č:eZ@]ę?'‚˝‡Ű'BÓ#‚J”D[02…”•áëŸąas&šîž,Xš6I/=~¨ÂŢÓó°ó˜ŐńJ pŽ­ÁEšŞ~÷Ý7u‹â҇~ŒťîşO?ý&Mš¨ÝőwÚinşé´Ł"â(ś' Ď6žó•ݖÎWÇÁÁí˜ëźźÍHy‰Őb ô–ÝR_SÇű gĎŢ5ڟk ˘Ęwܲ3G{ż ƒ"ôv›8qšąéöG81%¸N§7FŢ?ĂóĐ=ˆYőŻ‘-ľŹ‰oź×os°á´óĐuôXí™j$ťŠĘ‚xX‹)]ťvQuůíşĎWbÓ 7܄ߟëŽťŻżţ2ÚÍŽżţF-ڌ?7ßüčŢ˝VŹX‰+ޏŤV­ĆŁ>ŤŽşőE:ş-O¨6;=ϸ8vXJ‹ŕąĆŔ“”ŠŠ %džő(ҝƒćÂVY†7ž‹MźŽ´ƒáq:a+.„;)Ödo>%z¨SHKČ_t؝ź=ż ŹŻŇaťS&ŕˆqɰI¨ŽĐˆˆ ROÂ5ŔX0ŻZ˝ }‘€Ĺ˙fFŐo,6çĹăšâńŰe8dŸ\ ĐÉw][ƒŤ9ŕhőᇊţY¤Gł>řŕCÝ3Üg;î\~ů%ZxyöŮçńŮgŸc˖­JJĹnťMĹĹ_ E"RPP 7sćüŹ*˝J Đ'Ÿ|"vß}†˙ó–.]†'žx ţŁżďčŃŁÔčÓš2d°>n|î‰'ŇUx5~űmžĘÎîŽEzŇdeeę÷D ꍅΰǭę'gŽć^ <—ď‘ü m“hí¨61Ö|ŒĎuŹë]d$/ňé(ďÚwNrü$WÎR睈N:5kGŞ!Űx8ŰŁđÂ0‚—^zëÖ­×^(Ó§OĂYgŽÝí=ôHlܸI_sΜ_°óÎťŕĆŻÇAPŤ˝SÜ>âˆcôHşđ×_ë‘öÔÔź÷Ţ[ĘÖłBŢťŘtű#’˜bŹ)Ţ~ô,Ď= +Éś’?ŠmÍ XošŰN8ŠűŒĚLš hО€ÓĹΞý…ޞuýMX]ýuĘŽďÓŻ‹ŠŠ´§,ëň^xI×÷ŰśmG—.qČ!Šşú?~ďľhÎáőîžű>mó >眳”Í~€ż˙^¨˝Ôößߐ÷K“Ç{Bľ9+á)A‡˛LčÝťWsç͛őë7čöҝwŢę/ ¨•Kő PnnnŔ{Řöřż˙ťß˙#lśvŘĄ¸ŕ‚sőďüÍ7ßáꍯøqc1bÄp]ŢŃ3÷?˙9_~ů5^yĺ5íůÂp)śo.źđ<BR#|éá‡˙‡7ß|[•U uŮxď˝wę߉űX–Íœ9˙ýď5~OÖ?ü~ţůÝń WLieXUHzń ”?őśänÖűšş, -ąŁĹŽ•Q0Ź÷Áď× ĹBąáÉ'ŸŃ‚ć„ ăőšů”nžů6˙ű˘9çŠ+ŽŃ"ď?''GŮî˙°aÆZď•^4l'̛ˇ@ )Ł0pŕ]ݟqĆŮŘąŁf'yńâ%z=räˆĺW^yÁ4VÝOoPPđ9§ÇÖM7Ýęokˇfośăţ/‹´¨bS ŞťHs÷ç;°D# EąbÁÂćőJ G•ÝŠ÷>ÍÄÚ e8âŔ<äôčZ#ćş%F´ÓÓ˝^&u Ĺňĺ˙ę5;ObÁ#Sl6"8’DwÜ7ŢxEđ$ëÉkŻ˝5kÖęŃççŸQ7üfΜĄFÍîÔďťüňŤt4†&pTˆ%Ž€/Z´X/üž|ňQÝŃcCë”SÎ@4üşŞ2ěąą˝â0žOŸż˝ĎrjjŞ^Ó닡ˇôž˘÷çÔŠťkĄŸKoŠŁŽ:ťě2 űî{ fîôç@c.ß÷îťďűŻĎrc„)z˙† ő> 7TŮu×ޝţ÷ż‡tběH°Ţ´#üďbS=ß8SÝžĄŔ §[ęmĄaˆ‡J˘SبřwE.ž3y[[Żşš~S‚|,8ő¸M:¸GŔ,@Í=˘ýëŻsőš#)ĄŘwß˝u덯žŃ Œšs× Ył>j”dwÁߋ#iÁTƒh+%&ŁüáßęmĆi^ľO&÷‹Ç‚uUřkCMˇÂ) ´.˘qĄĺ6łĄ2ńG{mŁ )*ĚEďŘďźb “rp&0>§–jĎß;`„ţ$ÇmDŚëiäĺ]ŹÚm=’Ôś„]#u´˜mĎüť<ţřĂţpŁ#QWĚßwűöíǢé<‰Mˇ‚í.Ôą-›7ŁňŢ[łpZ˝kJńKÂńřýČťřjd÷ČŠŐöë[0WË;z~°çTÉ´ËůóŐ×d§‰‚§vgŽÚ0çŞíC¸á(ź™ŕ×Áe ó–ĐŰ͌‘ŤÄŒŃY¸p‘¸|m䧟ćč*ô^yřáüűÍeT¸ß3Tű˘)0~KŠ<†GŽApYÚŢŠÍÖŮĄˇ|p:˙˘"A•ý‡œ¤Ţ¨Ö*!~ł$Âú¤iŔ´˝™‡(ĹÁôŒÍű˜ó đŃë@ÁöoVĎNš+‡Ťçtě$`ö{J!ű ‘ˆß˛ Ý/?šžœ1ăCÎúŐ0äĎК5kđŮgłľˆhö¤" mŁçĹC†ś14 óîˇß>Zčcžƒ–Ď?˙´öeh™#<\_ăťď~Đ÷Îđ"–+ ŚW™wZö)ڋ‹éʕ+ńŘc×úߜWОŞđĺËIť¤˘ĚîÁ[óźâLA™ţUŽŐ B}•(7šľzőf<÷FëS ślÇ ę^éŠŇ”ŁXá0fůĄk* BćG …ِ}úéÇuXaAĚéR ĎĆ.Ó]–°ŕ=ŕ€CTý¤~mœóÍ7ßúŻűő×ßč5=NÂÁ#Ůź9WW„˘?7ŽŮ9i‰Ő&ľŁÜ{žŘß×Vá­ů5ó*đÜ#ÇKŢZçEźŸBĘöM+ŕů÷q5Z[‚h ŐĐăhK|ŐçˆE…WP1ˇŮCĹŕĄâ˝€ęÄ/F˘ăE=˛Ξ[ÂSĽ>tëÖŐďnϲ‚3mpĄ2­9”(˜h읝@6Î@Ž˜#źá›nűD#rÔşěŮÇaýýW´Uâţœ÷+ĎéďbÍwz“í˝ˇ×óëÎ;ďń{Q€`’xŠ)œý‡*Ă&†Â|!„*#Š4GsŽ‘@–ű ĎžĎŌѹršÜţ÷† e ď!ĹĄÄćĄ×gubŽ–Š„íć[b>ćgj,ă:uňćg1źečŃb 2ŐÖ6‰„!ą<َ ż/˝_$Š>ď:ďŘ/oŁËˇF˙ĆŁnNSËĺwŻţ|ťxýKŕőúÜˁ3/nź›Óť÷żŚÄ—“Ĺ2A -—ŢŹőŒżôšŞ€ŽWクâŕÉ÷[šç>.PǞždu‰ęö6ŻE÷ëN°ůĆć‚ .QíőŁpŮeWŠçľB'^6<Ę čŠĆđ7.K˜LžĄśĎ>űţď˙ţŤlčn}“ĆłźŘ˙ý´Í.Xđ‡?”‚ an4j2Ą4ađő×_‹'žxD{Ş!Ŕá`É6wUřźWúĆcDN>ű'ЛŒĄş‚ĐÄC%‘Fł¸lؘ‡—ŢNŖmm'ĘËďgý'˝zv×ű{+˜#˙ü =Ćär„ +ÎŔĂšIŢŘ :î¸˙řFČţĐ°Ńˆbě5˝Z(Ě0›ß…Âcy,|?g.`ĄţůcĈtîŔF8BmÄÇZtÖđĹŐC쀽ń{hEž+ł´^BŮ>Ŕ˙~…ën†ÓƒâĚŁýa+fŒŽzpă=¸la\Wj¨9ŐH,ŸˇŐëĽbuyɃmĐă Uş$üŒÜ˛Njäí=ŰG(•PŁŐ@ÓM•^8şvúé§ęÎËŐW˙“'OÔ ÎäÁF”á"Šhěy•Xfp¤‹3ˆüţű<ßěB/Šň(|Ž$ąéöE(Á‘˘ćŽOfÁúé,´użŇ^}đáş\Ş­¨—]vą/ĄĐ@[ŁĐI‚p›Ú2“°îłĎ^Úe˙œsÎ÷×ŤŹ§9+áÉéˇŰDÁ…çL˜°ł 8kOiiľ Ią‚áAě„1‰ë)§œ„Ÿ~ú/žřŠŽĂ“’’tŽbĚNd†÷~űíˇčôŠÝożƒuRlŁÍB‘ˆɆŔßĺěłĎTÍťuč?ţ¤…˘źź-:Ńl¸ŮŠ˘í"ć‘cyy≧čÁ!΂Čđ,~ÎpÔŃáßx;RĐ%Z1qěţŔ××Üß{ˆwŠc&y—ÚČQśńțŔI{S!D$ś'Ś!Ţç…ĘÖj÷ĚeŘĽK/‰moÖŃ´Îôe`m#l—ÓţłqăĆ€É Ř6bE? #´Ë™3ghťŚÜ^{íQ#8ŠŤ, ÂÁpťŤúď|üÄôÝň ügr žţą%•Ş+4.âĄD4#:,XŢ˙$ë6ĹŁ­ąncźşw›ţ9ŠŠM›6ŤÎMœî$=řŕ}ľv`˜çŕœsÎÔ]™ÍŸ &‰Ľű,FĎ>ű¤n@°ąó÷ß˙čљ{îšĂŸ$‹ 0ž3iŇ]đ3Y-?›űŒ¸äPđ3ďż˙něąÇîú5;W^y9zöŒ>ÜŕŔQIˆŚîâ){픥uP›'‡!˘rdĽřď×ĐsÉň­Ü§˝ N%„š‰ŒžíŰś rŐűpŹ{×ďEěÅ٧žŠHąn÷zĽ8ÝŢ”ßKĹ´ö{Ź ÚcĹţ“8 •_ko^—1ŐárŤ´f˜„ńć›˙OçP`"jNŠĚqŽzů’BÉŢůúĽ—^ŐâÖe—]˘ßsĹ—éňä…^ÖÇkClşíjpÄźŚ­lYř7đěăh0­ÄĒŢ|Ű/ŇeQmkő) óâ‹Ď*Ąňd=ČÁr†SϘ1Mď7ňÚ2ĂO(ěPźäšƒ)œę<Ús(B<ôĐýjÄ{7= ÎNE‰ž}űęăFGńźóÎŃĺ˝I,řSŽĐĂuâĝuĎĎ?˙Ş…†păP07ËŤŻž¤GČ)â˛ăGŻ~WNë^›—\´~řĄ¸ő֛´ŕôÇéúÓž3i,…úÂßíšçžŇm%z×ĐӗĄLÜÍéé;"ÁĎ<ËËŕ‰ŘžÚ'ň›ťö.|E=`-ÔEš˘.˝%ŞS7M?Hˇ‹›ŞŽgŽ3ś‰:ęí-BŘ67{ç‡śŃƒłó͝ű›śU–cL˝La‘öÉňŠĺŸĺŕ৞z,`ay– Ő5óůârí™rĂ™řeU•žÝ' ŐŠ%ŠýÓkcŰjZKŒoąů>ўͰŰsŃL†ČŠžĘJ‘#PF˘łhßoŢ6Ż9BýŐw;đhËy@öœ‘Ą;*FŁ$xź-DǍv|ľÔ;÷}pÂĘôD+rÔ(öŢŞă52G˛ŠG Ĺ-V´lq¤Éœ3¤žśnIL!źnńŸoĄçŇ˙ƒ%ΊJ6+Š­°eň'čŤFylďXű'şŹIXĹIÇ"gü‰,沄MÉŞÇŃ/áSUrž)ž5c˛•é-y-5Kjł°˘„—;ë*/AZçqHľ-AqeW¤¤÷ńçx eŰĄ^ Ą›n>ÓÖ#Ő繛7Łôňó`[ľÂžĹ°9ßʰ]˝QcŰô>KmďkóvÄëůŢl~Kđ5oľúU}Âsă]葓Óćëwśš(”BŸƒ>\{v°ł5qâm“ĆŽ×#Ů;ëčO\˙x*üEbUÇúśŸ~ăТđžĎ<řćă°§evĹúżÂ°źábüÝĂÎ";eĘt˝m΍ƤÓ7Üp“ŢţúëŮZźźúę봘iÎq¸Űn3ő€çG˝ŻEIÎPErňĹŸ S§NÚŽ÷Ůç@}oHxmÎäEQ–ű}ö9@çbzä‘üÓ´żřâËÚw÷ݧä9 ŚÂîÁŐďçäQÉJśŞ:: ďţQ§+°ÍÇcwžĽš]Ňj BŮ9iÎú'..–ăËč>NEÍé[\žĹmZ<ŚľÉ'<`ؤ†‚)!?&jSxŃçUŤ đїŃO­×ZůřŤtôáĂýÉŹBŃn Şă\ŞĐ~Oތͤ;!pćW€ÖK¨]Ú ‹^ŢKŒŠăFZl>69Ýşň§8b˙çô\ó bâUY­ÚdU )5Ži~ÍxäDűU ;˝Ą>ZTńxzŁđłŹ–Ꙛ÷佐ĎS…ŃBväÄ>‰5[ŽÂ†ŠrŒĚžë7œî=ÇëЗÚÂÄž##6ÝöˆÔšb'­â“YˆYů/ĐÎl aý*”ŠOéÇÖúÓÚíŸmŽc=Qç5Ł‹ż~}uČĹvň‚Î B( ť× CŚľ *'Ý×ňb Ą]Ţ÷"°˙h wcČSśőŒnÝť7ŠM3§7ŠQ†7ç”)“C&w6čÜš“žŠçöŰďÄ AƒđÝwßë~†yÂzŐPátáSřzІ„“Ä8 r2lřwKuŽ4&ž}s^˜PÝ,›ˆ)BƒA% Ą\d™!üă/ăaw´ýŹéUö|ňe"˛ťyłň“p.Ą~°“uě„˝­“p.đĆ6ôyŤ—˘ç/7 Ćm÷j҆ŸžUŹ%+Uă>1óŢAĎŐłT+~Ýڒęcž6C (¨d¸r•^Îü)žŤŰçĽâö ,ą1ž|o°KK€Fo-Awë‹řŤě8lČKDŻŽO`㌠ÝkœQĽáˆMˇ} ›ÜR¸oç˙ŒcĐř¸8ˇó$í< –ţÔť/Ⳳ” 뀣"UĹŤ[ľÎüWú˝DC~y<Żś|JĄ͒q=śćďŠääĄúu[´qŽf>ůäcj”ú1̛7_‡ü0yőÁˆóĎ?§ŮfŃÚ>´yŽôŘô[ř“v>ŘűźŔ};ňTo|“w]´Um—COiœŃŘi7 ­+ę„K  ü=Xţ­ŠPęg"žŠTˆî@ľäôVʏ/@FđŔŤŔń3˝ĄżAôZąyj0‡^ĄžocŘź‘0š"Ĺ &œĽíŐĆý÷ߣsýóĎb†ÇÜK7ŢxK@Ţ#° *dżýöő{.†szfćb0Ó0řŇK/Ş5ŘíQIxૢˆ‘˜ÔQö–Ah(ňô>óśyÍ|?ý˛/˝“…†œdA˙ž1Ô߆^=ŹČŰćĆ[TFőŢcO@—,+6ćşąnƒ ËW9•j\˙¸I–ľ'•iSşjZB„ÖJS…üD˛{Ž„Ś|t!2ňWĽš>lnďëÖ%ܒ.g Ľ$˝×|ĺ-ýXę1>Áƒ…}ÎAď‰ę‘B7Z.Ľ…(^ćŔÖKĐ×ţž.=ăS‹Řy+ŇrÖÁWéUö“ď+m} sI Ÿ÷ŠÇ'ŹxźŰ+ ÷Âʍně3~*œÝąĹ}%zöęWĂMě[h4†­G˛kN™ýřßoŕă­ßă–×ÖcŔŚę¤ă ůqftBęIg ëŕĂ›’ŠhpVí@ĺzŐiÚř°Ćţ/´/HDń„>–Ÿr6loFzzşÔďBŤŁšB~ü"ę–-ȸu*R ×Ő|sŞXüßb%n˜’B5ŕńîÍŔ/oe!Śg˝Üo,0z_`—Ł€ža’˙–Ÿż|ű đó7@q˜iĹÇď œq)°ďűoťxî!߲ńÖgqčą:ǏŘx n¨Â7K+u¨nqPڌ$+zfذψDě”-ĄşM‰„üpjŻ/żŻ_Ң„x F°aä0›Sl0‰°čŢ-ßÍącŰv7RS,ú\cbNRYĺAIŠÝşX1zxŹněĺôˆÁ¤ńąşľnŁ üíŔߋœ¨˛×M\áűżü>ŁvځŽ]먲 B'š÷ #ww6ž´¤ěńyx0pëˆŤRĹhĽŚ¸•řáRłC•îXĘwčĆ —EŘüu9 °ŔąR‰—n›şD–ăLýyn6řX>ŰŞ5d1úěú ˛GÎWe…ĂçĽâAŔŹ?†×ŠńÚ/ŞýÓžÇ"Ç!¨¨´!)~3’đ4ˇnÔJźT„Ž@ľwĘ6|ąígŐbňŕĽ={ŕ旊А§ßcC܉§˘÷™çÁ[ˇĆš->)ƒ.€ťß™(]~7âó@ŒŐižkŸpęÝ>—9‹oí <–Vň*ň Ďöç:ć:žő°{í_ĄĹrʃb ÉĚÎ|8ůŕ7%ˆ|˙°č;݇Šţľ^­ÚŤÔňÖŔUďSŻyíCÇrîĐ6Ü­přIŔ‘§¨Ę;ĚěAWÜ|5 XżşĆĄ¸ĎßEĹ>‡hAEęń@ĆöŠ×‹ÝéÁ; ĘđÇú*=ĄâŽăqř¸d óT"`x§,^ćDîś´:ż˙€˝ă1i\ŹRÇB.ËžóOK‚-Ö˘=üCĄ'qxj„yóuß^1zŮ/~[ŕŔěŻë6—zîÖ$,ZV€]ÓŤtŽ)ŒÁk÷ů[rŃsŢsĘ}B ŰPLfćV܈ł”IŻ7 …›oŠJBrŮ =ý_Ń< ßK€{{œŇeŹząúÄ źÂŚUuˆŘšs;ăąýŸ1Čű{ťĺbôąŻ˘Ç؅>Ĺ$˘X|Őc ňz¨X•č>ĄĎ,[× cmF—řŸ°Śp2RS'iO4 íÚ3ľ Ľ„šfošƒJ7„oE×ü2˘v]´őÁ•՝ď{ ĂGÔ8öď'~[mÇĘ­.ä—y;a’­ŘՆIýc1¸[uĚj‹GÚđ˙CEˇŕZt,â&.~ë÷J<7§\ *ľ1¤ť §OMÂŃü‰;‡}çď`˙ëPÄ9–Ă[°˜D‹˙ Ő1䥢˜ř€„Ž‚ 4?b!0w68Wúüżé­Q7‘bŻÝ㐒Üü#AüĚ=ŚŐ-†›ßmŢ_ý]Ť÷I‡KčxđšçHV̢‘PQjOLŠ13‹*ĺ6§cf<„A“_ƒK‰(.%Ź8cŹjŰťpŰÍm&ăó%ľř„ż¨˘–͍Ŕ÷NŁĺ LĽe,†Ř˘żĐ-ľÄűÚç@ĂÄś…Ž@(oSşý˙ű;`SźúŁOĹśŒč:V̙Ň垇ĔˇćUŕĐG °,Żn˘„!A‡?V€7Żđď‹Oí 눡”^JďXK˜!ĄÄţ—˙‘.× Bý6‚Đ^ĺ…Eěí=Â$÷ęM†G˛”ŰsĆCd˜ozďăQoV,Vٟ+kěvÄĆĂ1bŹwJhAZŒ/¨„›6ՀEËbQ2Ň,˜8śĺ 7&Źĺ=ԅ–Ć*‘~AhkDń+EÂß?řQĹŕŠÂeä.bňAW"6=_‰(1p(ĹĄ×Ţm-˛X-j‰GíKęV€]nxG|p{ĺZLťö%ؒ]ř냽}šÉ}^)NˇiŐB‹oĆooћđ6Ăö‡úneľ~wąqĄ-îů5öSPůŤxšß‹ËS˝ĄĚ׍Wgô@4$ţç4¤ĺM!äňˇŠQLjĄřŢ+Ţ.ĆŰ󪅏ÄÎăPŐýŇęüI#žř˝UBŸ“R5Gwé7„ö•ށSCüîľ<zÁœ*šŞLé?&ü9;ůŽýô%ęEţVŕÜ#}a~äő‚NÝşA„–E}HŐŻŞ‚í;*ü9ý†ŞPƒŹď˝nG(*NÜ Xľ,äáâá;#11‚ ´,"¨Ôă­WŽe'+úŸ‰!7ĆÖÍŁĽ);ĘV§\*ĚmšzEç†ňÓOs°óÎť„]N?ýěˆ×Řź9WŸťjŐꐯ›Šƒ: ożý.š‹ćţ<Ąv8Šťz1bşcΙbΝÂY}zŞăC”}í¤”Ó! ŔĐ`XşjTŠ…a:ˇŠ'0ČéBŹu†Oxű´ú{Žx'6ŤĎcĹëŠbVV|ą'~{ř4ďT_Ş3”Ú51™ęşą–jQĹ,ʘˇŮw2’SúrÁX+űGŞ‹K.š<¤ŸuÖyh)–,Yp/“&MĹa‡…—_~5˘˜D{<đŔCQPP€Ö„S‰rwŢyŚOßťďžţ÷ż‡´ ţ^x ŚMŰťí6S˙],řóߚBâÂüe^)€ISńyr˝¸{ˇZTŚt:b| ܙ€öŇ7‹`oD‚EĹeÚŰĹ{ƒÖ˜8Xz_ŠŔÜ)@Ř˙9ANJ ČŁRWQ5Úzýă?Ĺ{ěƒĆ¤šę˙ÖDcýŽ×]wÎ;ďB˝ÝŃ~Gs衝ôČÁ–ĚÁĄOćȏŸ ü> Q“ˇřňqďvŸ‘áĎSbŽžš¤xčD “âŸv°laŘSě§űĂ}Â%œ–DԂĐôČ,?>Bšż3ăęľu‹‡?:6â hÍAŹÍ+ěüđKô‰čVŻłcĘD‡?Sx}g7n,^ýe˙ë3Î8G}öŢ{/ýZÔôŽĂ{ď}€çž{Ÿ}րĺ&"”ÍSPtŻZěDŕ›IÇŹ;÷+ş8}SoŃC%ĆŤFrúbÎŇ‘ŹŠÔTո鑪:0Jœ,SâEmĐĺżá:!n+ĆNťĂöxŸ<ůɈáŒ<<ÎäĐę3ő˘„œ5żNDjĎ5~ĐlߍĂ+ęŘ}y[x{FżÉ´ć˝ą”wYźÓ3;ÖŞďŘŠjŒ)”wŮe’ę´Ÿ°Żąěź!ĎĐ}÷݅=zh1âŸáŃGŸĐă3Ď<=ě{„3Śű§™m(k׮ÑG‹>x˝zŐ-ńŠ =_}őľRîŐ č‹/ž ƒ T˘ěaßłző- Ě˜1 wÝu›v{˙ôÓŮŞƒuž~úqŒ= í‘Pbëóĺkav%1„3k2-řztWěůWÍi”]j”šÓÁGř_ż=ŻRç?il˜Đ–×>a˛×†â{çú›`ł˜<,žoŕ1TÓ`űőÍLć› ČSúţ ‚í2Zۗz˝m2qℐáܤąĘŚśŸŃM9㐓ż8ô .Uˇ?t,pͧŔČ="^Ż_Ť”n_}Ú{DíçQ‚˲€×žNž@ľ%×~~•j;œu(đÇŻaOŠLJEâŘ ÚűF„–E•Z`#účýýoťíf˙>žŸ^JsçţÖŽ•HŹŰ6”ĺyĎőž!đýŚ}Żď’…]— ąĘpN̄Ɉ5 mœšŠŕľ AĹ—Šňä鰕UóDCOŃxL;,ŐÇy űސő{´H˝Ţ69ôЃ!x˝4((;†NžţD‡-ď=¸ák`ĐäđçmXüöžw;%SŐ÷ň/ ö .´ÁÇďTŸńBřsŞÜšP ;?ƒÚČëż2ł˛BŻAh^:tČO¤äll|ě(Š>šlN+:gľžŸ”÷Ň˝kô÷S°#ÎßŕjŽÄulě{쉘2e:>řp<˙ü‹Qż—÷ÉÚO<ĽĽĽQ˝ÇŻšá†›°ëŽ3ÔČÚţjÄúńZăĘé"Ëó÷Úk?Lşťvç¨/áľfĚŘłĆt”tŻ˝ćš˙"ZrsópÁë{ÚgŸđĘ+Ż˙óĎżpÎ9h—}şßrËíߙߋD~&]úyW_}=ŕ;věĐŽż ŕ5^ýMý˝n˝őް÷Ĺϸíś;ąçžűęëžţEř÷ßţăĄ\’J@—bŽˆńÚ QŘşu›Ţ÷Č#ŁĽŠíšćârš‘T˜bŠd߲] !›LbŠÇë*ěß6-nݎ‰žÖ8ÖćQ’Ty’§ĹŽĺóöĆO^čϟâOPkĺbń-t.ąŔîŒĹÂY{ů’Üş˝!@nľŕôzŞčY†,ސסmqyďÁéMR›d+őçPiŽ<*LěýřăOę甶~ 'ăűď8çwŢS ˙#1yňnzmoěgˆż;Šôói¸żÓcăˆ#ŽÁ̙{ësĚĎu8§-6^Ű÷űěłĎő0aČŃ)§œĄˇůŰ3üˆĺmëÔSĎÄĎ?˙Rë˝Súűď…ČĎĎ×÷ľlŮrU&ěVë{bÔ3ř‚ď˙Ž;nĹŮgŸéЌiËĎ9Ëů|W‘/wЧć9Ś}EqnźľKÍŠMS'MńoӋdy^ýŠHđÚ+LS/Ű:Ď@čÜ)âdAœg‹żŽkŽúýÍ7ßÖĄs´ zIŃŢĚüřăOÚVXď~řŃşNŠ–——§=cxMž‡śkΞů^zémk|ßńǟ„ožůÎ˙>^ç‰'žňżŚíň:_}Uݙ}ęŠgô5 •WŃ~7–lďœ}öů:Ń\Ż3ţýź÷ÓN; ‹/ń‹T“›nşW]umë†+›Ú#†¸@OŽŘ!Q!/bepçţŔúŸóÓkŐeFZD$łsőöGŻ{ëĺPp˙•§_}ˆH˜č÷(7h,!Ľ5„ň˛-ĚvzGćĘ+ŻŃż;ˁ`ä÷i]H•Z`㣴ďźsđěł/ŕË/żŽř^6Lţűß˙Ö-[ńŘcŐÉ5Ÿ #ŽĘ~ňÉęóo׍Їz4äšü-(t°3w˙ý÷¨ĐÓ°Ůlş€#űę¨8đĂ?ůßłmŰ6UđýĄo"ZX(îşë}}Ž&ń~ţřăO}lƍ8÷Ü 1`@<÷ÜS¸÷Ţťôą‡~,ŕ ‰˜9sw|đÁŰŞsv2|đ,\ř˙÷şä’+ôľ.đČ#ęÂů÷ß煽'6B/˝ôJŻgžy;wV#űç¨F햨ž×e—]Ź*ßÓŐHŚ_|ń N?ý´vŞÔß3Ľ°¤ćŹ>愴kÔóś2É+Xř˜DßbUœvśćŔ†ľŁąřŻýđĹű7ŕŤY×* $VçKĄbąŔaő.N‹Ek NKu:”ĺs&ŔQë˧â[âě^ÁF‹(¨Wž7YZđńř.–S‡e˘É˝ŃXÜ{ď˙´]yĺexíľ—Ôłž‹#Ž÷?GsćüŹěëA]|ôŃ{8é¤qíľ7čRc?C›6mFRRR@xíďňË/QŽšł<6ţăsüű(h̛ˇŔoăľ}ż=÷œŠĘŻ­>űě“Ęn˙§ˇŸ|ňiÝÉă÷{ĺ•tHí^#á8ě°CĽF#÷Ůç@ÜwߪŁtƒYjƒĺkqqąŽßxă-Ź_żĄĆ9і1m–ç%ޞŔŸ aąZWńŕłI؜Tˇôčߜť:zďĎú2wuľ‡Œ#nXí3ýč]–°ůUâ-;š­~/**Ö˘Ĺ-ˇÜ¨ęłűą}űv-ŇüöŰď¸âŠk°˙ţűj›šđÂóđôÓĎjť¨{îš_ ‡*1ňym7ß|›Ş 8'؞)–ĐÖÎ?˙\ýžýöŰG."EÉ_­śťšs×ď_ëß÷Ë/sýâemĺU]žEžóÖ[ŻĄOŸŢ!żoEEĽjă<Šî÷jÝ>čŃ#[Űę–-ŃŐÁľŽljËD#&tîŇy†E<Ľ…ŔmJ”Ë #vM:źZHá9OŻ”÷Uąšú†í,TĎыĎÜ[˝˙˜3éâUóš,|ţO]gÖkˆ×äÚ댊źQĘËöšyšá†ëĐ0”w˙ýß{ŠĂŹY­'Ĝe /ë5~ţůW]ĎϞý„֍„ü„ÁŰĐâ€pô*CEţ9ËĘ=xîU5:šçx߉G'Â&÷ Ű@Żź]Že+ŞC9ŮVœvB’“j/H°áŤ˘křŮąę;ŰœO!8`?Lœ¸3ştńVHtK÷Ý÷ń×_Ťqϰď㽹E÷wvňÓÓÓQčî~䑇ëíĚĚL%˜œ‡ŰożK5RÎŞÎŃݗ^zN‹(ĆąăŽ;Fç ÇGFF†î͞ý9öÚËoËBŻsçNjäj˘…×äB† ŹGĆ(x0fqÍl´ŃľÚ`Ÿ}öÂwߎˆxŕţßíŘcÖ•Őźyó1jÔH=úźhŃb|řá{ČÉńşĽR$Š­2ă(ßgŽ­fîŘc—ë‘ÇK.š‘ ‹x§NôďÁuk‡ gy%âčĽĹ°—/Ô'XwŚG ˝Tň•¸ŃUux˛ÔëTľ?ÍŽăRœŽXüľt,^ľ6卅ǚ ÚP1°ZÔ˘ţé4,‹zmE VőYV1ŘěńŚ?đĺI`VĂ†ÜĽ}Ń{ä’ŔűąŠű-łůB},ŢŰĺv˘Ă'źX˝ Ă~lő;V9úůn,(„‹ĄlŹÓŢŘ())ŃöFÎ8ă4źřâ+z¤ľ{÷nZäHKKU–Šz´&>ˆPÚĎ$ŠƒŻ˝ö†îP™ËˇóĎçˆ÷.!ߗ––ŚmüłĎfëůüó/lźśďˇÇťűď›k^-Ż˝ö&îźóV춛wĎž}˙ŁĎ§çI¸˛ƒżEd²ąH°ĆŰ+ŻźŽ=bؤ—ÎŮgŸéÓ§és˘-cÚ2F}^ťďľţĐ9ű\Ę_˜Ö×ĎZăߗܧŻť)r§łrkľ‡J\ÚxC};ü÷˘Žö•ćü*ąÖ Ÿ`Ôôő;Pć/2ęçłÎ:˙÷7k;äąçž{Ç,N8á8}œő˙śmŰľčpÎ9gésBÁşŰxî “Ťžúęţg™˜í™śöúëo)ăRýLďŁW(’XîPÜ`8 ć™gžŚëPÂýK—.ó×y‘ĘŤhżëěC9ľAĎ2 ľ†pJęCŽPőň‡úZ y˜‚ËŚö„‘, ŰzOňćGžČŽ<ŕVŐŽşk~M/”ę÷¨Ż§ĎV ŚOĎWBČăŢş6^ŐńJ­^TşŞ<˛:7> |\čĎ{đFŕľ' %‘:|TŁÖăÁ´ÖPގ·ß~ŻúéZ´˝íś;pőŐWř ­TjÁ;jtN<ôč`űřóŞ1…,[áÄsěŘczhCůţg{€˜B6ĺşőľŽ=<ľ‘ÓÝŞ…gm?ˇ'ŚŮÂ=?Ř0` GN)’„Š1` Ł_|VÖ֕ĄC‡ź>|'¤’Ł´Ą*VĘ_ý­ţĚ 6`Ŋ•zżáBĎQ2z GŞ™$2\ƒ0ÁÉŕč R^^áíT<6ř–/˙7nŇŽţ]ştx;ŚfŘš3ŽÁó;uĘň‹)„ Á‘#Ă'Qă{Ři4ß ć–`ă˛=ÂĆžgKŠW€čoĐ^ƒ˙žşwŚ„ubžÚî¤:>c\ţ*k7Á;łŐsQŮ –Ř8ľ¸aąÚŐbSZ‡[‹*Sb<Ę>ÝN[­‡PLń}†ž€ŰÖô@ďaf7džAľÔě‰&Aš$TzöÉě^1Eßśłńó>„JJŰłgŽ÷Ő=1!ěü…uëÖi{çomĚ(F1’B‚×%ŸnĹăąűîÓŃĐĽśht"éq,2imm6NOv:h㸿ßĆ#}ż`˜’9L葒’Ríz^ZZ†ţýű…|;u 3ÚyçqÚS…0vř}6@/#ˇJ0,O.˝ô"ý˝)*ąĚĺú­ˇŢ¤ßO˘)cÚ:|ˇo–ó~ýӎęWôśaA˙LŒ_]¨_ÇeV×9…eMďĺeţŒ¸ÄÎđ˜óŁÔ*ʘÎń}™ŐŁkŽú=55%`°ƒĎm‚Ď==ÄčĹeÖŹę°>˙„âd¸’ŕ:‹ŢŚsć<°Ďlφ­Q€4ĂzŒ8ź'nó~űmžÎQ´}{>Ž9ć(-Œđý Çáq#ßP¤ň*ÚďFą3ě<™Ű,,sxl+ Ń,ʰíă6řý‰č.°]‰"_<uSÍcYގťć`ÎŔ3—°QëÝ_˘Ę‹üBoÓA߄Z=¸ţݍŠâ"ŕąđ!ŘÁl02@kî~(VžđÂKz1?żýúőŐB$EJ†ĆqƒŢšlٞâq†ň~řáÇú†łœ|ň´'W$žFh;ź6ěsĐâÚkŻŇmđý÷?Dg?Ë/żü mh͚ľřß˙Äß˙Łë\ŢĂ9çœé˙ý‚Çz•eué5J”6ţŕƒ÷áůç_Ňu"?—ç¤Iý÷TŰľŞÇú”đw˘X¸Á›P|ţůÚ3Ží+~×9s~Á̙3 ´NDPi$şw‹Ń#ÎľápxđĎRGČc,t„Tx,źÖŽxÄƆ/0mŞ•Ý=65Ťo´p´ô駟Ӆ ŒŢ˝{鰕HĐŽçŇ͞*uUkƒ“ňՖ¤Ż°°Pô§ë G§§N˘G.şč2˙9Ě Oၣól˜qČáAfü<ކąáFĎvŢ;-ôź5ŠQŰČFm ďÚ*čćäšv‚]ńˆI î ›;\_Ţßî7ČăĐyW–Źg]wl’Ľ˛űœî˝â=OŹVzُ•€bŐ˘ŠSąiq…&ŚUâ‹:Ž×üú§¨ľŰăBAn–Oőý Ś-čPu#Źž9Ĺîžű>= ÁW(pPˆâLvvw-‘'Ÿ|FG~'ÎČÜiłgŹ…šH×ćŔďUW]§ëu`ÔĹ ŒĄĹ,_ř˝XMžău÷Ż*¨ŽŁ2“›žůdţ {Ĺ6ßV˜*ňŤ8=ą­Ś<Ś¨Ç°óóOOÚSmޝṵ́>4(|HBż~}ľÍpÔŮ _ÓfŒĎbȐáYÂÎášçqŸ9ůs¤ňŞžß-zŞďĺ˙ú_sp„őśaďŃÔÁľŃg‚‰ĆSƒźy]"Lsl`‹v;!ňyŠj°ă25(xíŤ@Źo oň^Ŕ[ "‹)$A‰ ƒ¨ŕě“g4YBZ'ĽĽ€OęĘAÚFż~}uýG;0ڕćĐ8†“˛nůęŤĎ´=‡ƒ×Ľnćg1„°[ˇnÚSdżýöŐ!ň´-^+++SŻp6z˘ĺääŕĆŻ×ƒô4ُÁ˛Ăl[FŰ ń&ĄŠâ(CçůčaSRRŞ˝U˘š6˝ÖďČĽ.Ó[s…á>ä œžžůT8°"´NDPŠ–Mś˜Ş¨ÎÍHüSڤP},+#üű3Ă\;NŮfJşŹŒč ŮX5˘Ý\ő+ -vD˜8•^wÜq7Ö­[ď?n¸ÂS1 iŚR|睷iQ†Z]`AČXfŽ(ł˛ŕČ7ÝüÖĂF;>Ź 8’K%œ™ű™ě5˜ƒ>H7źčŇ)&şŽđwZ˝zľNźÇ߇łů|üń'uşs2PTáčó˘đ7¸ńĆ[jMPHaˆ•ĂŐW_§++VL*ČN ݥɨQ#t%F×JçďIĎ#3ŹL wčż#ŐüÖ Ÿ-O§$ŘK’}‚‰YD ‘ ÖiÚ.ąiacî“P\ĄDˇÝżŘE ,U¨˘Č˘ŽŤ|2J•ď5÷;<Ž@1ĹM1ĹťÄ'ŠĎq{Í*->Ĺę_{ěj;ÖK|ĽWLaNZł ˘ŽWzŇź“š˛QÍ6pčí@›Ł˝_yĺľ o>€óőˆŸqć.ŕL<BHkx†h㴝`ćűQ`ákŽćQ eăń„ŽŐ‚0m†ĺßűďĎÂ\âOFĚîťĎP+§ýbůÄó˜č“xCSC 1,ŰčZÍdžĚ Á2Œš,(˘}ô‘úœhĘŽ42´Čř†=}ôńţDœ´ÎfňË/ż˘ľÂÇ<ÖçÁR§ńŮŁÍp–zq´:ů>ńĐCřm#Ń´7ރ]ęi›źĂ%Ÿ‚ _s?D*ŻęűÝBÁ˛‚ ¨Yv°ŢfrKś‡ŒŠŁŠƒÍˇŤ‚Ë&ŽÜQGçfÂČŽXv†zĐs—‰v[;áę6v˜KűF™çnřLŐŔŮC‰/ĽĘvďSó´Ěčß{đqQVĐš2xÁŚŹżC%Ľĺ`1B]Ů&žôŇ+ô3ĘK,†Í0T‡íőƸWzś˜aýkŔ†!ęy8ëgěărÚiŢî̆áźa)ÜT–7äӘA+Úk׆ôŇË­ZôÝMo›g(ZňS ět$ĆŤ=˛zšžš ˆľY0fD,ć˙U3„gç1á•˝ÇĆbö×5…1ŁbM>ŞĚŒčtłŐ ‹‰iž„G×_­n0c}zzšýaH;*LÔʎ]ßöÝ7pj@Şś_|nlpt•Vň¨‡ƒąšlTńÜää$őš‡jÚ|üž{îS…á&í Cáćá‡ŐáIL wÁçj>3,ˆéaĂă9?/ň=Ő“đąăÄDź„<Ţ#uŃBWΆÄÎ]űccm8ýôSk wbÁÍŮXYŇőń›#GÇ3Ď<éŻx˜PřśŰnÖż§};v´Vđ/ťě*˙uŚNÝU'ěăߙëĆĘßT$''b‡;iŽ<ď9Š'0ĚGďŇq:Ţ0 m6tÎܢt ‡z›E'őPł2ŚOvÓĚĽŽŚÄ#1-ƒÔyĚŁâ=ÍŰ9ś1yŁË ‹[ýÔâqy×iiŰźBŠŰ7­łÇëu˘E“%¨ÄY`íźĂëbő-ĺVíľbQçV:murŻm(|ŽhG|~é-Aď-&dހłRń;Ӆ˜žT|žčńaŒ‡z†8 G„?ú¨î”ú`Ř8…SłGóý(ŇҏłpşDŸ{îŮşŒătËěȰ‘Hˇb†Ű„‚.Čô”ă´Ń´5ş3üčÉ'ŐÉ<ŹoCń‡Łbœá‡Â Ű÷ߡÔ=š2†á,‡p†^ň=A'lDóxYYăççi,XŸ§ e(ȓ ޘ÷UďFiŹŻMV­ŚxˇIý›žŽÜĽuť ÎÁÜUž¤( Ň95|PĽ+­IXօ]v™Ź“Ö˛^ĺÂş˜#ÄĚ=P,8ë ÚĽGš:œłńpDœƒ'ôş¤€xűíˇ„äP¸`~" FŢ0zĄŃvYďóý‘ĘŤú~ˇP°mÄ63řY̧ňďúHGS› nWvÚ)5Ę&zŻń˜‘'ŽŢ5fŰćwçkÎäÔVÎŁBAĹ=Býýž§Ů>u˘D‰ţs?Sƒ-ŞţâMŕĐ:LG=a7ďě?Âşś …NŚđąŚĘŸŇZCyë Ë_vŮ%5ögff Ą4Ĺľ™Ó‘ůθPü5 íńľ!¨ ­ KűC wXMkc‰ń-6ßÂÖ[vťc.š ŁĐäƒÇx6řŘř3\´CkŢ6ÇŹ˛yßcůXż9'âçžvB"ˆŹOUVzđâXťĄÚ;`ôpŽ9,áźAYśžůA.Žî÷íƒSŽKT"HäséżNźôfEÄózgoÂtňĎVÁÂŘ(ÍskuĽ:|Ýuׄ%ˆ‰§ţóŸü#łÉyç]¨žąžÚ ˛.÷Ô\Đ‚Ý Ď9ç]Y2žľľĂŃ26nůŘ)0'ĆÖ jły^cý†M(;üYŒLů1 ŞAɐ?ÜÄ´bS‰˘ÁŔĽÝ3ĚĆĹ*C-ńŞ(äoŻ‹ľŇ‰i­SbüIim..ęRl7bě\œ°ŞŽ*öXŐşg_x;ştÝŞ UÔzTyăQëĘD¸ˇfŞ—J˘é—Kf…ˇQć˧âRÇŕŽ…5ւí }z÷Ôżc[łqƒË.ťRç6 ś7ĄíS_[TŸÓťé‚/nÁ2ˇá YHń]DŻŹJ|`ă ěqăţłgޗĺyá…é†0´ť ß\Q=łUŃďÇ#šň[ӝ™D]?žĐkľÚX9Iă^÷˛śUŰڍUŻŠ,ŕš“ dݲ+2ĘójżŘÉĘ޸QQ^\˝7đ÷\oHŽ[ŐŃw˝Ł ŠCŁ{?űCԀˆŁÖÓţşŕ6ô?óB=8bŘqcŰ2˝Ş(424†Żíšç~Jŕ@ ˆ„O{칯9ĆO/o†Ç‰ÖůˇÜożƒpâ‰ÇëYk( <űěóřěłđSSäăň嗟é×ôtĄwČ=÷Üé?‡žRœÖœůJČ>ű , сé?ţ8GOanüL0OQ–á­p Ő7 ÷%˝k( Ţg„aOFrŮhŽÍi“ůl3(Zř8S g5{ťŇ‹ôńǟ§ŸÎҞ3ÁżOk%”“ćŹkââbů ŞŃF=ß­Óé[\žĹmZ<Śľš2 UŮú‘ŸZ 1tĘˆŽąd‹‰îÁHH°ŕěS’´sčţń8÷Ô$wDx1…đŘńęžË÷đ˝gŸœ•˜BbŁôCĘĘtčďÜáh)Ýţ8ss ߏ˜oŘú¸Ľď)6HN8ádb@ďş)Ó™aT×/,äă•řQŢ3ůé5ó¨˜Ă}B­7%"ÝS†,‚Ó˘‚.oȏÓYĽśŤÔşľítUz÷9+ýűŽJďkÓÚÉ÷¨ĹĽW.—C ›Ń%m‹ö8AEŒń”ÄÁcWâHf1,‰ĺŢ<)Ź2XtŃ{…S*s­öTĽłbŠs,kƒ!xf7|Aˆëśîą(j†÷˜bŒWžę6§Q~&q5윍ĂÇéS뗗'N3]ŰYU„„ŠŸ}݂Îüa>!Ž™ňŤTXzˇŮú]ęB4ôžŘÚ}4"ňo”aŒů›€+U{jŠiü˜^*—źexÔ˘?"Š)n†ůLžŽĂÔ[JülÍĄźôÚâý°@聚eËćNŁ×5ĂXJ4×ćýđ7b_ÁŠĂî˜s†Ţ÷F8.}8㏠­-¨D*tŠŚĺdG7;N].;uFi~ŚIDą„Qôڗ˜ÖĄ–ŇpФĎÔ!’ˇ]JİŤĽJ JáâPB‰ą8M‹żWDĄŕb,.§nŐ0?R5ěĘ(˘¨NQyŒ7ŽZÜEjD+˝ÖĚ^1…ÚťN^ŤFůŠc˝IjŢ*Ežîú;śe8ŇĹ0™ ZV¨Úćúź_jݰyR|[ž(_Lńř^ň˙trŕ‹…_űŻ}ô„ ęÖř"Őî6}mƒŠ o †ÓهH6ë_[j9ŚÖÎřĄmś~„úR[•ňţQLaűűűJÁ˙ťösţţR‰)j|ő_51´ú†3ëĎQőviřk°yŕ˙‰m=ú#łWďľU#ԕĄ) uĺŒsœd‚Ih GQ€ĄqÇ{˘ÎÍ.”—a|=ŽšËv.˝LčÉúÜsOkšsĎ˝çŸąá{â‰G,0Gsmćxâ>j~˙ýzS!śÁ0/ űĚA ËoćScŠP0‡=hŒÜfBóŇĄC~Ěç‡Zóýľ=×nOíÚÓ9§$é0œÖČęľ.<ýríĘ(§t˝čôľ7vh@˘+ł+ĄńZš›Ćt ŽÍćéQ4ďóŸ1ôôŮČ곉é%Ţ0shúă_űśő9jžĎm<ßüă‹í§Í0á-]ĹT%ëĄúŞîߪ§Mśz§LfȏjwŮ\ ůńxC~.Xí.ľvŁKĘ6\pô˝°ńú őaQëń†ý¸cl°fŤQszÉ1̇ëoȏł žŠDXmĘŚUiüCÖQ3m_=Ęě"ĘeXš›†ŘzmśÍ÷Íůó7\˛Ě˜ŽvOŕ˙˙ł­˜}⠈‹ő “ŽwŕđÇ `ně%"ąĘŹgŸ…1˝˝â‡K‰Ş•żND<śŐ¸ďđ!>5=“'ż…Ą#§úCýˆŘžĐ’4UȉöĂk/7Ł™ ‹'ÂlžŮƒ[~R]ƒžŔྍůŸx2ŒÁŒÄN@Z`ů" ĘS˝żswŕқ•{š7i­™GTű7 Kö8Ýî~R{‰„ ő[ný4U*&ÜŚ'§ŚnMHČO#\üaϞ]–Ů­˛ĘƒÖJ•=ň˝ĽĽäŁgN–ˆ'B‡!Ôó̈́˝™ƒ{`G÷míäMüěĽěĄ<ăĎ⠜Ô˙ éąĘ{Q6ŕÔ(•ĽĘKe•ńTŃkĽ˛zqTj/'ˇľgJ•jTŞňŢęÄQťž óR3|‡^*e>•„JX3v˜fń1čľť0AĎěC•âŞDÄw Ăš˘ů-Ą­ęyf#ގ^Čô¤Ô ďńťĄí3űąř6s]…xôˇę™TĆ*áăî#Óe2r^ăŢŁŇüb ŮźäA%ŚlG`OM”ÇMçě¨ę†´NýC†ú‰í ÚBVď~؞Ú;ňÉš˙˙Uýą??S j58ůĎ×Jü8 ¸b°Ŕ7#šUŐÉSîPçĚĘSBËBŕŁŐŔy7ÝzxĎŮŚö_w60s(đÂCŔ–ÍęÚ€kόJL!ö ť….YlšőÓ”ŠźĄĐ“!´ "¨Ô '&eę“Ó8‚ʢĽN|óŁĹ%n4”âžŻ‰Ş(î­oĎ|­ J,t4‚EÄΝ˛;ž3œ• (+L ĘĽb =u˛öĂm{ b¤ăę^ŹUΊŃ6‹RôRÉdł^1ĹmVÜF˜5łX]8vükČIP ąR%Ś”úÄjěÉꆝž)“á]›DŔʸĎ*WşwëĐŠ{Ú3ÁĎ7Gu‡ŘꍀđÔ ď1 )ž qĺůĽďă/ŽNű8zB"ţwlšö.Š/q꽨kľső,\+7/FRţsâć„ËŻ’ç­żťą}Ą=MXC1ś÷ˆ2ěyëŕ΀˙$ˇîĚ}WĎÜŤŞ—w?xt1pĂŔÄýŞ˝Ozôν řF˝÷ž€ž}˝ű׍vÁ-—“s”ŁĘŁ7ŁËąâŒCĚÎťę‘~ąßśISŚ  2yňD-ƒ*a0 +fŃ7Ňđ §5^ž˛vqŁGw+ň ܸç‘2=ÓĎÜůF/Žđ\ž‡ď˝ç‘RlĎwëkÖÊŐN|ţmU„+ť1~´Ç?ŞÔBG…qŻŠJXŹÜo <+vlÍRâ†ÍçŠäĽâ áĽâ0Ö1HX”ŒëşźŽ=üř!읹\ŢäsJ`ažˇP<.‡QœZHq[ŤÔűyn×.Vtβ"1Á⟽‡^/•lW"ĚÖmn”•{ď­ß\q~22ŇË)ĺęÜ/žŤÂď ˆäŸŇ9#Cu‹č,…´Đeçćý ńč9v6˙˝šP°Ľ:go÷=˙noJçM7gŠŃËň¨ăŒĹv{ź‹:'6/§Ű~ŔԁËđNîîXRÖ/ä=Q@qŤëó’q1vLËúűvţ)1ŞŒ(‰őćEIRBJ˘ËŰGŞňĺJĄČŁłWů^ŰźŻe‰zöKŹUß×ZKş Ąż[p^$Ah/D˛í¸¸8Lî=›?ĆKIP*Ođ&Â}`Ú§ţŰf/ęł˙‹§÷ť =3łő‘Ń˝b1ű’,ź=ŻĎĎ)DzS*sjäÓwKRBJbM3n,ĚĹ˙}v=žčłœwď‹Ţaţ‹ďžBدŸˇŔsŠě]’łŤ$¤|ŢYXwÚ ŽĎbăvD˙ćž;ź¤ău Ű  žppřIŔَßY§ˇŘŮAá>bż‚вČz!Y:uę„QC˙Ä7żvřŢy:°p‰ťOĂŽ“bk •§Á‚Ü-՞)JÖŹsé%ňÔ{ăăBžN5jýë|žűɎňŠČĄ>dĚNŰÔwۤâ‰ÝăB™ł•n§XWă{žčî­=cą"ŢjCRL’cÚöŒ+mĂÖÍ6OŽěîÝđóAýĐűŸ"T'Ł$ą)éePş,L@Ť‡Ż­&qĹX,ŢľOľ°˘D!öm¸>ő-lHé„?Ť`Ľ=Ž4”¸ź#Ň]bŠĐŰśCă6btâ Ä3ŚÇińvŽâU§,Áĺ˝6=PÜď1›!¨BŠE§ÖňXbŕŘœŽşS1>‘Ç‚e݇clN6lś˜€ďn^o׹őjÄÖ[ŽPśMrrr°sÜ|ĺ˜ŹžÔđH Č˙bßęŇM8îĂËđčž7`4;Y€FN˜œ¨—[œ˜ťÚU[Č/óÖů’­Ú#eň€X˝ćĎ ‹qÎě˙Ă­Ý×"ÖÂ÷T $†yV‡ …X,„ÖUNC˙ěl˙6ću}[ŻFl˝í`.:eç`Kć ôČ_ýřœgőD˝ILR$)¨+ö§Ő˜.Y„Ahˆ R ćQ­)“˛°`Ńvě(éń}ĚYňů7U˜3׎Éăc1iç8¤ŚTz_|[…ŠŠú7<(”ĐűäĐýöýśŔ_~ˇŁ¤4úkg¤nWß­“ţޤą g—ą/t–ŤFW¤°ŁŽ“r—]/…–rdĆ&IŹ•Ŕ矞ZÉIIČŮs4Ö~˛}ţ)Dáś Řb]HHŞŇ‚†…ĘŠÇmňNŠöJńŠ*žmcŸĹťÝËRˆ^qó”@ňťw_°šio}OőĚA>§TZ˝˘‰žCÍSP-Ź8ŤE•Ş­đTÄÂęóNY›Ž”ău(CššŞ&ś^ąőօ‘í ž3ńĂż)}Ň;*]CHAhŻ”Ŕ]ŢW[Ť pܧ—ăÔ!‡ăâŠ'#ÎVô™S*G;­r•ĂŽ‡~Ď,z““\Ř#‹šŰ‚mŐVźë÷h¨)>w(Áś*ăýÓîĹÖk"śŢúĺ,°Ň66őšP7AeÓRŕŞ1ŔĽďĂvC¨Źţ{đţËuz[yrĆOŠči&BË 9Tz„6¸°ęÓ§F]‡ş”aĽe|ýŁw?\Š×ŢŠĐ d—ţëÔa8 ĺˇů,[áÄâĺNźţnî| T 5uSř]Ć [Ţ˝{íoœ‘ë*5j•[U$ŽZ`#lť˝Ž2-C¨g›ž}űôÂĆc‡ŔkSچ Űó2`݊‡ŰŁŤŇSBĚú*ŻJ%FçXń.žóÝ>o=i›ĎóÄ8ďОzE˝X|‹ŐúĂmßÚą5 ÎíɰŘcŕą[áVëů9Ł1dđ=ƒQS!śąő–Ĺ\Ż2 ;[‡Ôš'ĹżOOľŠŔŠ•šŐűřˇ}vŮ;˜ńŇ x~Ţ;(Ž(E´•—ŕŮßŢÂnχ'˝­%‘k{n÷‰Ťúa‹?w B–—LŀÁ#Í#…ˆ­GFl˝m`äU˛ßufÇŕőžOeť{ĂŕČ]ë,ڐÜAŁŃŠsčÝŚôXáôŐ3gî Ś źź<Ş÷púŢC=Ň˙ú ƒĂŰoż[ë{˘9§Ž4Ĺ5!⥣p˘njݺcůš ČŰŢŤ.—ŕŒŠřG‰)˙D1#O´°řfrچĐ-k˝ţNünWŽŔ[íĹÚ¸.”8˝ůt˛b“!4=Ąr-˜G°čÉA/•Ą3ĆbÉĚ őE.{ôyŁx?ťfˆO¸0 JW2Jӎ×ß5Ň Q´ś/ś^7ÄÖ[/F™Ŕz1iČ”Ćg!Ľ*ňŒž¸ÔŕčK—+~ÎyH¨ĺďüýgŔ%'*ľőĄdçÝĐĽÂ}ćÎýM{ífgwÇ÷ß˙ˆý÷ß‚ ÔD•(aÁŐˇo_LÝůgĚúŞ;œŽX´el6ŚMÚŞžÓ”&)”óŐčLpŁËŽ”ĽW˙ü.úËś­E˘-ý;ĺŕČQťăčQ3a‹é؏#_ŒÁ7áÖA\\,zőĚÁş“Ç"oY1şŻsĂĽD-JTéÜ­ ‰NŐ×qyí‡á?ŞăcńT‡÷ÔU,1žmřÄÔ.Şł°Bœž%HPqÚăP–×E祐bqYą%1Ű'í‚i}z!>>M…ŘzÝ[oĚËÄŃă1}ý|îř-h|9|xO8!%8‰­]éyóőb쯥Ařź\Ě›ŚĘˆ‹zlFľÁ…ń„ ńŠ‘_E âěŘĂv›Đ¨Ţ)bëuGl˝e‰F`íŇĽ Ö÷š‚V~‚zńó›ŔʅŔ5ď=‡ă@Ęc7ŢęmÔG\ÜÓöÓŢ4Ć=7Ÿţ%ŚpP&9Ym!‚Š „AB~|Ô6‚cŹŮY™śŰ(Œô7Ú:#.ÄÔ]Gřgöȋëbgěî@oœÜ’|ü•¸ĺŤçŕRĐÇí§\3Qî¨ÄułŸŔœľ ąŽ0/™ƒŽLĄ#:—JĄáD˛yÚF‚"Əƒ%§FyJźŇCb•X‹­š)(.ŠWí#›ń¸cŕqq ţăßö…óá?ĄÂ‚ŒP‡50ôÇţcń‡˙8ňP˛˛+,Jä­˛éĽÜ‡ÌÂÎÇ#)1A—ŚđN[Ż?bëMG4iii8vřČF'ßŢ(Â{ü1BAű|ď7ŽŢç S<ž}Ú§ţ]”]ŠĚ8†‡ ăŠ5 Č{>o­čƒ˜ěôwl,ďąőú#śŢ:1ž}Š;&ŤĆ:Đ%Ú°¸x"đˇŐűŠ s÷˝h€WתąÓ3xPŔLœY‡ŁŞŞJ{ĽěśŰTL›6sçţŽ‚‚@/§T~ř1ě˝÷ţ˜:uwÜqÇÝz_0vťˇÜr;vÝu†>÷ŃG‡Ë~"–‘/˝ô >řp%čLÇńǟ„ožů.ŕœŇŇRÜv۝ŘsĎ}1}ú¸č˘Kąr媰×|ţůuřҊ+!*aWXŃ}ö€}şĄW÷ŐhŤôęžűíŐ9*WŕúPę Œ­ćÖŠoކMĹŰđäWă“ÓîÇ {žŠë÷<ŸŸńćœ˙vęÖ'žqîűᾐ×y˙‰¸űťWĐPŞœ<řÓ[Xžm}Tçłr>úŢq6mŐŻo˙ćEěúŘ٨/OĎý;Ýw\Ř㌽.sIlzKęůg8\zZ*&ě7żžŇ.[ŹUbŻJ€čbXĚKPîcŠRK…ĺ›ÓPź‚bJ,JHąTÚŕ˛Űđů˜Ąť÷td¤§úN‡űŽ Al=řŕC<ôĐŁa?ű‰'žŇď9˙üsńňËĎcżýöÁu×Ý žôq–Ż—^z%–,YŞDœ[ń䓏é>͙gžSCô!oźń–şÎŤJČyƒ „ 46ňc"T^…PÇhŒ{OŸ‹foEAqW´%˛Ňˇaďi…2d˙žÚ čşތąv¸UçW˙˜­]ŮčÚwČäďÉJLÇąŻ]‚ň"źyâmhJŞ\vŐđz:ĺ`H—Ţhp–qn˘ąy†ËtďÚ#Žš†*˜ţňzÄř`*Ë,Ř\ƒŒĚ*¤Ś8áąXu؏ĹâVŰn=‡Ew€űL˙9|ď˝÷ţçž{–j§$œ[QQ×_ W\q)öŮg/˙{rsóđÜs/bÌéX°ŕüůç_J˜y˝zy§°žéŚôý1šŔ ś'žx<ňvÚiĄ)AĽÂ5ÂČÔ]'˘´ä|öC,JĘ2ŃHKށ™ť,×nyFCŤśĆV}°ťjÖ ł˙ˆ‘Ý„ltšTĺsáŹű°dË<}äľúźHp4iΚżqřČÝńÄŻďÁĄôăÇî…kgžŹ—V•ăĆŻžĹ/kţA™˝{ Ă­ű­>Ë…ŠžQ¨ gݏç~˙łNškň7ăŽo_Âoë˝ÓćÍ4ˇís6Râ“"ŢËÖŇBÜôĺłřa͟H˛%ࠝŚâĘ' 1ÖŰpújĹ<5÷2ÖnÁŽ}Faxvżˆ×Źr7^ňbĄn„łů¤¤D=ëýŘéřŢófź˛6‡÷|—ęÜlˇ˘¸ÄŒt’“”˜âĄmY˝˘ ŹZLńn{ĹýĄ&!!śý7çŃ×--LFi~ŹŽXue5˛îódą'ĆŕűÝsĐéĐi<¨ŸSšÂĆ ÄÖĹÖŰ:´…Ν;ă?;†Üšů˜ç^^H ľ/H%‰(¤„Ú§^ĚLő`×Ě" Ô4ÉŸˆâ qĚ'ÖęľZ-.ÜéOÖߊ1;[bëbëíłĐÂpšqS§ă§-7`ęw7"ľ|Zuoó÷<Nť™™™ž]?0ŽââbüňË\Ürˍţ}7fÍúë×o@ďŢ˝°nÝz8Œ=*ŕ˝;ď<ž† 2r䈀×|CŠxŢŕÁƒŽ­]ť•••7nlŔţ1cFăÝwß×3-[ś\•süb áßđ€ö xĎ'Ÿ|Ś˝XN>ů?5îS ů "\Ą<ŞCtŻ˝Śb÷ɋš\żŹÝÍ Ĺ”ébß}ŚyWF1JUŸÚÉäœAüť}=&ôÚIoł‘ÂƈÁ_>ŁÝooŮç,ÄZmşA +śoŔö˛BźuÂm8}âAxjî,ü¸úO}ěŃ_ŢĹw+ŕƒ/ĆG§ŢŤFŻxqŢ'ČNíŒ/Î|HŸsÝĚSđüŃ˙Őۡ~ýř`6mÚ Ah*ÄC%Ą\…ƒqÍÜîżl1?ŕťšĂPŘJĂ2ÓśbƤĽŘżţ)’ImŤĆ.ŹßpUţ&źúÇçxřĐ˰^îpűÜ)‡Ť‘¨˝qĂçOăŰU ˘ş^źŞpŽŢý?°Zʏ¨óQxü—÷°xËZLë?VGČʕ蒒WŽŤVŘłÓ:ů×YIizűůcŽ×벪 Ź/Ú‚ŽŠ™Xžm]Ä{řcÓr,ÝşŸŸů †véŁ÷]4ő(ÜüŐs¸}ßsńńŇ9ˆąZđżƒ.F‚şßÝűăw5ZöůňšZáBĚöNúäd 싸ăbńmÖĎóęZô\SޟCˇZŹ–%ʏ°ĂnCaĄ ń .$'şUC͍¸XˇîŽy˝U<Ú[ĹcńöŞ Ďďgz×N§ĺq(/‹GUśí‘ÂľözQk¨%7'żßŁöŢôяáîo|‡pßš)[[o­„ó@ăö.“&ᜲR<şţ-ŹôřށŽ)ŢœÄö¤.ôIâôşLîpsřj„m,€ŐÖ ąŰÄIţďŮTžiw&ś.śŢF Up’’‚‡ƒ9YÝŃýçg1jĺGŞśm>1,ż{oüräyzđčۡOTöŰśÍŮ}F‰˙ţ÷š€ý=ö„Ť9ëŹ3ôýą­1oŢ|íąbŔ×ÁüóϢ€×ýőˇ°Ěď3čׯŻ>ĆsĚÇůz°/9/…ăíŰóľH’“ÓCçßďwŢĂîťO×37‘ /<GuÎ9ç\qĹŐxá…güł% Bc"‚J„+xšŚa°˙L$&ÎÁż•`ă– IćÝčôěş3v٢ ˜™!;YÝزYj:= éÜs×{ SĆ[ŸňÖ­¸hÖ˙tăčáÓpŐôő16dxn4d$¤ęFá:ާËëR{ÁŽGĄÜ^…Ť?} ĺĹÓc0ŽQ´‰˝w y­×˙üOţú>Š+ËŃGU˘;*JŸń6m×ëĂ^źÉqŢĐíe;ôš.Ă[Jňőč]ýłr"^7Ć"Žc-M¸ü ôúHINBßŢ=‘|ř^ř%{6ÎZ‰q?ä#ÖŽD¸”ŕáRâ s¨¸ŕ(wٰB˝ćüVbă܈ľycs+!ÖăËąâ픹ܸ]V%¤ÄŔ^EĎ›jČŠĘ(^…Ű^!Eƒů32°ýŕţ:ąkçŹZŔĆnt‰­‹­ˇ"‰ĽĆ6™9cwxžóŕÉőďcš› NŢ,¤„Ř×Ƀ zćÁÓ$[j ń ĘŻ˛Žd(Vâ\L›1#`6/ó÷ őÝëBH[ď"śn śŢ6ˆfŕ„ÄÇÇcć^{aq|ńÓěňçS ËŤneť˙LŢ›Ž>ťěşŤNBŰÔíőplÝşUç'šűîŰ1`@˙€c§Ÿ~*N>ůt,^źDçE9ě°CtrYŢ/–/żü kÖŹ H†O8łÎ“O>=÷ÜŤWŻŃłüqÄa~qƒBĎŮśm›CŽ;îhuÝGôqŢĂożýŽ÷ߟ…;î¸EŸĎp †đ\}őu¸ä’ őLMożý.žűî{ěąÇîţĎĽw1Űmü.'žxŠžiˆIlĄąA% ľyŚŻŮŮkOĽˆvţßĎů ‹WƒĂ‹–Äfs`Ā?1mJ˛*xŚ×:mjc†ÄĹÄÖHÄučˆizt‡#8Œˇ~ń˜pÎ{wĂŚ“÷pĄţźŮË~U#QŤqë>gĄĄ¤Ć'áş=NĆ­űž…ľy¸föcęóîÁ—žXăÜ<Ő8˘+ď{ŽS'¨÷­îmsQäřŮîŠŢQąG˝Ł{ƀf%ŚŠą,l*ޮ㽓㼕]š#ołl ÂŮźyŰ˙aś{öˇÇt,UŁ#_ěźĂ>ڌ‹Kľ bU‚ EŽly| j=.œn°{`îfY|)‹˙E }QÔÚjRźŰSVIĆ_tBżŠ#ąçNC–š˘sŚ„˛óŕíPŻëƒŘşąőÖO([>fŘöž3÷@ܜxźźę#Ěu. şRýó¤řŢđúƜJ¤Ř˜ěŐ'”˜s¨y”ƒáë9ĂM㏘gvĹχn†=”HŃ\íőpp& ťî:ĽĆ1Š(={ćŕłĎ>×ۗ]vą>÷ž{îCYY9öß_œvÚ)xőŐ×ŢwƧaѢĹZŒIVƒR‡v(Î;Żzf-ć8á56mڄÇD;G‹$^č‰BąćöŰoщq هş>řŽšćż°Ű™Ëe$žyćItęÔŠĆ}sß=÷܉łÎ:OĎösŇI'B)ákĄ.˘ŠNhĽÓnÝ6ă‡ÂßË"/żw‹xŤtë´هŹŔŒéŁtÁgÜ{mkƒ†Îq–ÄŞ•yF€Ćţţ—üţ˝öşK€ť.]—ŠcĂťőÇqcöBCšüă‡U#n îŘď¤Ç§¨Î­Š Ţ‘Ś$[źnđÍ]ˇٞކ˘MwaóՈ׺Â<,ظ sÖüĺqŠń cmú]“łôˆŮŽĘ,Űśă{ŐqÔýôţťÇ)HKHÁ#?ż­˙ćOqş+űů=ýÝ.TŁk‹śŹÂ×+çEź˙¤˜8-C´˘ Ą€cŘQѓ“EC–aɂ•ň]>-)CŒËĺ éń¸őÚăwö[űDݜ”W8ąřEŽR´vh"ĎČ@Ú¤ţ˜6b:wĘÔůR8˘ĘÍ?x;Ôëú"ś.śŢV‰T—Oßm7d¤ĽŁŰÂO0Űţ;ě{ˆş<”¸ä“FH!ĂăcpdśĎ;%dˆá­bž–wŸĂ‹ßśě„žGbˇącj ńińTl]l˝P[oŢG¸Ÿń=ö? {öÁ—?Á”…Ď!Ľ˛‚úœec§ăß#Ď„3t2ióçˇTŘî‰'Ż—p̚őŽ›Ţ]tž^Ěyäáţí?ţ@Ż?üPüß˙ý7ä5÷Ýwo˝đťrĘIz ˝ZŽżţZ˝„Âř\&Ćýő×!MAL˜ý– íĐYĐkĐă[n¸á˙Î@3ăMçŃŮ ív;ŇŇŇPÂuF­ÓŇR1xpodĽ­‡Ĺľ ĺ•ń¨ŹŠěfÚ¤'oǘĄbĎinĚÜ}2˛˛˛˘şgƒĆ*œŮxŹtWgŨꞃ&ŕűUŕĹůŸâëó°|ëz´îŢď_Óűč>üÂ1׍Rčßę‰_ß× ĽŠýFă'Ő0Zą}ŁNZg>ΆФŢĂ16g0ţÉ[…Ç~y/-ř=Һྃ.BçätÝXNPŻ×ţü_üű›v#î™Ţ//ř ĎţţĄnŽëÖůeE:ţťsr&ćmX‚ć†{Ă؞ƒńíŠůxî÷pĆÄC°˙°]đçćŐg˝‡÷~§ÎĎŔu3OÖqܝÔçńZ/ůI'­sŤçńŐ›ˇq)ΟrdČďIˇŕÎq))..Ń.¤A˝i,[7ˆft×Xł1ŤCm˛ťwCV˙llšŒ?†Ú°#тŘrRJUčŽń‡ďXŒ\(ţĹćÝçáÚťč<)žun,š”†yGw‡ë°!9cF ˘Ĺ†y‘šSL1[[olšĘÖëZ—sŐA}‘ľ5ë[Qâ)Ż~só¤îó6˜T‰ Uđ‹&–ŕŚVĐÚâ=okEOü¸ĺD {œÎ#P1Ľ!ö/ś.śŢŘ4g˝nŚś˛ ” ń޲łł‘Řw8ćƁ­x ˛JgąËˇ¸kŮ6Q–š‰Ž<îS.ÄŽJLĄ8üšÁ÷ÚÔőš 4ľŮysqë­ˇ>ŤVLVfXĽŰˇxB,@=\Ń,Qě%¨XQSD1›oĄĎa€ ťÝŃlŮş Ľ™…°K3KuiiŠßSŁĄ× ~mŢźoűöízşŽ%ËíXžś/ňwdŁą'Vb†Ź´ÍŘ{=†ľjĹp*w¸}Ą^7”ÜŞ"ŘƒŚ ´;xýŻ/0kяj$h­Ţ7´K_6bşž16ŚeäZlt%ÇÄCdăĆMşÁÁđ:ŁP6F”ŰÖ jËJźÍĹŠžoşVTV˘pG16mĘĹŚÍy(Ů´Y+JĐiM9ҶّžĂ…”7lvs Ë—Í‚Ňd+Š3c°Ł[<ň{'˘`p*RzeiąŚWŻdef !>ńj1fń ×ŕjŽĆ—Řzý[MSŰz¤şĂjŕs˛Z1–a•Nßb–<Í"‹YlAĐ6BpAĽŽ× ˇŻ6%??_'[Zł6k6tFîöl—v†ő{˜TUƒÔä|ô蒇ž=ˇc@˙NčßżŸ?Ťu$%ÔCÜŘśÝăÂŐřrˇDĚS%Ֆ€ŹŘćńfjk´TĂ+Zť7śőLž{ąŰ¨ŹŞBIiśç °`ŠKJQ^^‰ĘĘ źŃ “02999ŠęťŚg¤Ł[×ÎÚ Ĺ,˘Ôg:䌏¸ÄÖëŽŘzxšĂÖë3@˛nÝzüöç<|Yđć9–˘Ša@1Vž€×ţ˝ž× Ş™ôőŘdÇWž1¸­ćfěŽ8,+ľU30|Ô$=i‰ąőş#śž–TH}DŽsssń÷Ďßc§ßžÂŔÍżF%¨”%gŕ׃NCâG`̘ŃţÄ­uąĺpűĄľŇQÉĄ%ć˜JóžpůĚqٌÁä2vl6oVŁÖ›Ö#7ość§  (Iu¸’QV‘ť#I'łőřţ,V‹ ś˜*ÄĹV %ŠDuŹĘ‘•V†n]ĘԈuşvAĚ΁ÄÄÄ÷Ůң֌šî—†mö¸<Í7ĺ\[E]­ł‡Úźm,Ź4âă=HJJ@zZОŮNp:UăPć˛čҍEwŔ{™%ĆŁ*b•hÂ× '⾸˜Ż|?ĄśkŰטˆ­× ąő–'ŘŽkŤżuŸ>˝őôœŁVŽŔ?Ëă§b~Ő2介}WńT§91áń‹#^ÎĘv#;m:‹q‚ßÁc;Ş2°Şx46;Ś`ŔŕQŘg@Ý 5î7Ô:x;Ôë† ś^7ÄÖ[?áĘóv(ęŃŁ:r$ţě=ë缍IřźUÂ@Ż”Ĺ‡Ÿ…ą3fčśťůóB­ƒˇkŰ'BË#‚J‰Tř’p0Göë×W/ěTęŘ2ŞďeejÔşĘŰŮryżąĹTBBźÎv’’´´^:7 GŠÍ÷i;š× łÚgǧŁĐYŽ2g„š0ś:36I܁[1áDÜ 3ŽďĄO[ĽíńŕnŸgŠ;ČCĹxßS[–˙ŕ{÷:ÜžŚ@l=2b뭋út¤hËC‡ÁŔ°ó†qXľjţŢş ËWŕ_瓸RSH!ÝU~Nď"ăőYŕgčĎľ˘°2›Ę"ˇr8<}÷ĹH%äő}k0[ŒŘzŰ"TY@"‰Źô0™4i"6÷ę…o{Ĺ°ŸĆŔUż\ť\ľŰŮó4$î{ö;&Ź(ZŰvműAhˆ Rj+|ƒ‡YX¨víÚU/ő˝‡h_ˇdÁŹ“ąĹŚ Í–¨_•¨t;áô¸:´Ë06J™ő_\mƒ`7ďśuăźŕ“!°˜ őŢŕĎlŹ}MŘzMÄÖ[7ш*ćmĂŽ(pôëçW0[ślUËl,ČŊ˛ ŘdWŻŘá.C™§•;ÔP ŽëëÖ3v•ÚQîHB™#ŎÎ(qfŁČŐ Š=Đ˝WwŒëŢ ™™™÷U—íPŻąőšˆ­ˇm,QzنöVÉFçCÂ_}cݜ1ôĎOXźúěŒőӎ¸iÓýmýP6Ű҃Ÿ‚ 4œv/¨4UAŽđ%Á…n¤×ćýá>+šýŃÂ-Q8ÓU8N\_…éšmŽç:’Ýď3ﯯđQW;néƗغĐPšÓÖë2:j›Ł\8ăN%Rî@qqąö<­¨¨@U•]{žŇ#-Ö‡Żóz@…9‘Óulyż´4% dčJÁ÷V—íÚö5bëBCi őşůł˘4 UĐ •Ţ*[űőŚŠ鲀3…íŮżŸß+Ĺ|ÍH۾턜FGxŽ;„‡Š×ŁÖÓčĐP)c$3ľu¸B}^4űĽ`Ú ^ۍîÜŚ˛őŔĎo÷áĕPÇĂ]ŁŽÇĹž…śNKŮzC:R0Ý;‘ěěîziČ˝„{]ŰąÚö BkŁľŐë՟~€$’: çy^ŸPąeĄ­S;oë´kAĽÚÎŞ@Úl1h Â5Ć *¤„úźşětLZ3´]Ú0‰ôě7ľ­‡úĚPâH8q%Ôńh?§žÇĄ­@/Ž–˛őhźĎ˘őB5SńT:_B{§ľÖëćĎŽOˆo4×­íu¸}‚ЉŚNo/tˆć-ŕÜń6["šŠútŽëá!EhĎĐvÍIZĂŃ\śęsI}˝Núš‚Đ^`xLKÚz$ďłştښËó´śý‚ĐZiíőşń٤6oó>ƒhÚůbËBG Ú:˝=`E;ĽZŮöNaZRR‚ć€ŸIŕˆtN´ŸQŰuú‚ĐZ íÓ“p#<ÍmëÁ4†mˇ†Ď„–˘ľŘz8 ľ?œM×Óᖺ\+Úű„ÖN[Š×Í÷ź/’]ÖĹfŖ…öH$;oO´[A…B9Žš?;ZqĽ.KC>SÚ´YÚ.m¸śgť%m˝śűińTÚ­ŃÖëÚaŞoéZŃޗ ´Úb˝Í}ÖŐĆÍď„öF´vŢ^h÷‚Šáj‡‚‚B´MŮ!jĘk BKC›Ľíšm9­ĹÖĂŃ,AhĎ´f[ŻKgŞĄŸÍg B[Ś-×ëiƒbĎB{&Z;o/´;AĹřƒ™&üCzn'Š‹[Îm0řžęZ˜J‡KčHĐVił´]Ł06?÷ÜGZŤ­ ‚mĹÖŁŠw›B<•ú^h/´—z˝žípiż HvŢŸ˙‘”–ń[Ɣ†ĹĹĹ:SxRRZ R° B ĺĺĺÚVľýšc0ĂŃl]„@Ú˘­ß_¸„ԍu}Ah´×z]ěUŞŠˇÚĽ Â?œ9óžĄpŰl6] Ó Éét!--‚ ´.¨lł0Ś­ŇfkSˇĹÖĄíŇ^l=Tc1Z‘E:cBG@ęuAh˙ÔĹÎŰíŢC….„ÄPšKJŠQQQŽĚĚ,ÄĹĹB„–Ĺnw °°@ť …ąĄn›m¸6ÄÖĄőÓl]„Az]:açmv+¨˜nŽÍPCífâ­[ˇ"6ֆÔÔTÄÇÇw˜ů˛ĄĽĄ]şÝnTUUéŠŐoźebb’ż 6ĆáÔmąuAh݈­ BÇ %m=..^][l]ššĆ˛óöDťöP U ›“\.„.—K)k;Ô;ř€xôšĆB;>Z:"ćľÚšĎâ+ˆ áPsׇ+ŒĹÖĄő ś.ąuAh˙4Ľˇ:DRZs,&1ţŕƝ*sáË}R Băc4†‚ăŁÍ‹šĐ6ż/ŇuĹÖĄő ś.ąuAh˙4•ˇ:DăœäĘx‚ _㾁ʂĐpĚj¨9¸ŽŞ-ś.-Řş t ÄÖĄýÓvŢÖ邊A(Ľ;řn.Ľ„Ć'TĄjťŽŸ!ś.-‹Řş t ÄÖĄýÓvŢVéP‚ Ľt'ź˘˛ÝŃAhn‚37vA,ś.­ąuAčˆ­ Bű§Šíź-ŇáCé6ś ‚ fAšŽPocĆbë‚Đňˆ­ BÇ@l]Ú?Íaçm‰+¨`Aó>Aš—Ś´=ąuAh=ˆ­ BÇ@l]Ú?bw\P10?ćDV‚ 4-Í=’$ś.-ƒŘş t ÄÖĄý#ž`ˆ ‚šęś$˛„Ś'Ř֚Cá[„ćGl]:bë‚Đţi ;oíthAĹü0Ű2՚ 4-ÁÓŻűBĹC7bë‚Đüˆ­ BÇ@l]Ú?-açm…+¨˜§Vs:pš\zákc|Ž ő'8 xLLŒÍĹfł…œąĄˆ­ Bó"ś.ąuAh˙´”ˇ%:œ \Űív­˛%$ÄŤ"Vm[ÄuIšÚ ŰM;t ˛˛JŰb\\œ.˜ b‹bë‚Đ:[„ŽŘş ´šÚÎŰ"–(ö[LŻmŤim,1žĹć[âÔŤ– ťÝ1­Ł Śz]UUĽ˙ŘÉÉI€ -GeeĺÚNăăăľęMęS(‹­ BëEl]:bë‚ĐţiL;o ââb'ŤŐľ8ÔbW‹Óˇ¸|‹Ű´xLký͟ mM‡HŃË?°ąx˙čeüq‘žž&ą ´h‹´IÚ&m”śjśÝh[„֏غ t ÄÖĄýÓvŢÖi÷%‘9Q—ňňr¤¤$#!!‚ ´>’’’´ oii™›K¤ŘLąuAh[ˆ­ BÇ@l]Ú?őľóö@ťT‚ ⊊ $&&JA,­Ú¨ËUmł¤śBYl]Ú&íŃÖë2"'ů„Ž‚Ôë‚ĐţŠŤˇÚmȏš ćśĂáĐŻo)BëǰUÚŽ7–w:ÄŕΊغ ´mÚ˛­›ÝšëăŢÜĐ÷ B[BęuAh˙Dkç퉑CĹH`•–– AÚ´YÚ.m8šŰÖCu†¤s$u§ľŰş™Śśo)C„öL[˛uAęG]íź­Ó.•`e›Éqčn AÚ´YÚŽ‘ŕ*Xĺn [oHB=é BhZŁ­ýF#˛ÖľLrChO´[ĄaD˛óöFť÷PáĚääd‚Đö í҆Â8MmëŮŠqEjŇZlÝL$[m,ą4šëH™!´ZŁ­×…ú §bĂBG"Z;o´;AĹŹp ˙˜œĘI„śm7Ôlfľť)m˝.Š†Œ>KCKčč´´­Ý‡ŰßĐNVme‚”B[§ľŮz$ťž–z_脳óöř̡ŰY~Œ?œ‘œnG‚ ´=hťf;Ś]›3…7Ľ­×ÖĄjČu˘™&2šsĄ=ђśnŚ.vížpżÚö—áö Bk§ľŘz$š˛Žő>ąeĄ=ÉÎŰízÚdâ-”ÝRH B…śKŽÎÓŁńl=šŽ’Ńč‹ć3Ăuœ‚Őö™RŽ 홖˛uóuŁŮîľŃpd>#˙ƒą6—\łqiŹcbbôÚč4z‡šv/ŠĐ^hi[ô™qNmç…ű>Rß í‰híź=ĐŽ•j×"4)Ń<(R0 Bý1L,R‡§)mÝüŮÜćtpĚ`^ĺ.C,`łĹꎑÍf M î ďt,Ü=Ôvž ´UZĘÖŁPƒˇ)žĐĽš¸¸k×mŔ/²WaÝúM؜ˇEE%¨¨¨Pç0”Á[Ź ÉIIČHOCvvWô흃Ăc̨áčŐ3)))ş aYBĚâJ4Š” B[Ą5Ôëá>3ÚýŃ'‚†;nœ#ö,´u"Ůy{ĄÝ{¨4%uy8¤#$m‡HŠÂÂBü]4ël?ĄĘZŹ ŇX¤:zĄ #'~$ş$ôE||ź_`1Ű{]ń^„Ś%’˜źÍĹnˇ#ż żĚ]€/žţóţř[śĺ+Ľöä{v§ĺvlË߁Ť×ăǟçëý6[ z(e—‰cąďÓ°ó¸QČĚĚĐ3%Мà +"ŞBĂih˜_}Ž/a}‚Đ~č!?­ńšőąZ'—ď.(ÂuU¨rz0e@ŽŸŒŘůŰ5 !jŒĎĺvqq1ć}€Uśoő>‹Ç‡úW`[BËjüëţńĽŠČÜŃ]ʃŃ3~Ň;#...`äŮ ”Ŕ"Ţ+BGŚ9m=/c› ˝M–ŻX…7ßýŸ~ůśnÍşFýěÎápcÝú<ľĚƛďÍFďžŮ8xż™8úđýѡO/$$$+ľyŤˆ¨"´ZŞ^týÚʅŕ}ć\/ćý† á|搿ŕkJX_M-ZŒ%K–âĐCÖí'BŔožů›6mBNNöŢ{O­ŸŚśăրx¨Ô‘ÚŠH tc}fk/P9r7eĘô€}, űôéN8¸?š‚Ł>ŤWŻÁ}÷݅3ŚŁ9XžçŔ'˙”cSĄEŐ#“_/­ŔźľUČÉ´á QIÜMf™j+ÔÖŔbƒiëŽÍXaůžŢű‹^,ţm¨´” 7îoäáo,r˝‹äÂltň Dϸ‘č;ÉI^ˇţŕđ } ü Ćžp÷'ąŘ‚P?˘SŒ5…”%ËţĹ3/žŁ„”QV^Śť1`Íú\<ôÔkxńqŘ{ŕô“ŽÄŔý´ç[4Ţ*M%Ş|ôŃ'x÷Ý÷u]cŰaĂpÚi'câÄ „śD4Ţ'Ą^łSo,•U•Řl/Ŕj{.6; PáŽB)Şôš)ˆGRL˛m™č—qYHˆO ţöÎžŠŤ ăOŇÔ)…R(îî>lcîcîÂؘťďcîΜ9ó06śaƒáÝRŹîŢČwž“Ţô&˝‘ş?żK’››››4ď‘ç•ăMHŠi}umë÷ß˙ŽI”i§œr’Üwď˝ŕᅲČűC‡Q‚Š˘Ţ • HăëďůęXÂ$Šoß>r˜˜˜ˆ]ťvăąÇcd…‘#ÇĘŰ~ř:u”÷ŻżţFŹ[ˇ=tżTŻëŠ)Ď/ĚôšßK%Ť ێă–IŃÜ1І…Ѥ*ĄxlÁv˜4A…ˇŚRaEŢ/•WňŽź“c9Œ\ÓaěÇXŠCĐ<ż âĐB"&ꃴ‘@ŁWôű=ŸSâŠBáŸ@S|xËú(‡Áť}Ożú9šyĽGՎefçáĂ/~ÂÜů‹qÝĺçâŞKÎFëÖą˛­0ŠVŠIQĺÝwßŰň~ŰśqŇy˛fÍZŮżúę‹;v ÖŽ]‡iÓnB›6­1oŢOP(ę#śÚ}­nZ^^ţËߋĺ۰֜Ű͇Qd˛z}XKˇB ĚŒžööÔ"úcpx7DFFÖË´ž@l˝:1çOŸ> 6ü‡ńăĎ%&&šÄ”'Ÿœ‰=şCĄ¨/(A%@ü5ž999ĺöQ}fd†Şćí<žhčőžxâčÚľ‹ôěϘq+V­Zƒß~ű˝Ö"HjFŚňçä1żo+P‚JŔۀJ{Ě"´ŠśÂn1š )çq&—â.°8ď‹AŠ‘fمtÓ.lsü„°œhÄdö^ŹÂƒŐ͝u¸EŻx^[eĹ%ŹŁŇ÷šžÂŠvŸ“§?ŻŔĚçßÁŽ˝JŸŻ›ßAZF6ž}í#,ükšğđđđZU(,}ôѧňţ܋sÎ9Kžűůç_Â×_‹O>ůźÚ'Y EMHdšvŸcWöű{3bnţżřÝśĚi΂P! M%Ř´„kevţb´ĎkÓăœČ1čÝÁeϞÂJm§őŐ[gTŠ™BXťŽđ{š2e2Šú„T*‰žŃ=,źWd˝ćĄ!ˆ›š´‘+Ëdű \ÖiźTĄIEŔʄ÷ű:ŽŽŕİgϞRP‰ŠŠríOOOÇoź…e˖‹Ák>şwď†+ޏ 'œ0 ÉÉɢ1=ÓuěŮgŸ“Ož‚M›6ăŕÁCrßO<-•tož0ć_žůć[â5[D#&Coşi::wîäz˙×^{˙üłBŽŇ×gžy:Žźňňr“Y=œtĚđî•0‹ŻŸ0NȏĺkÔ¤ŹáĄˇ­ü‚|d€Ý-ÝÇyOűˊáîžç­ÉcŸć,Z‹ĂX‹őÖ 4Ko6čƒvÁĐ&´ťřÝFHo4=ţ˘Wü‰+Ő)ŹTGhđsĎ˝(k]tîźó6Ô6*}Żiŕm2Ľżĺ–’’Ўf…7?ř…EĹĽG×műÍK\ťq.žţAÜ{˸â˘3ѲeËZU8Ф—š0Ÿđœ3fLÇšçž-ۧyóŕ‘Gţ'ŸKNN‘^g-ŠTëk—/˙Gž§wď޸öÚŤpÔQŁ]ďąqă&9زe+BĹXjĐ ¸ńĆЧOoůź–ÖűÚk/áË/żŢëčßżŸ˜č=ŸţUîËČČĤIÇáÁďssf)¤Âi~i{ńiţüfúĹ&›ÜĄÚ8lĘÄGX‚Ďs—crÎ@\1 ýbş"""B>_ŰhŘ:ŃúěË.ťDżpáďň8Úű´iך"n+3ÎüńÇÜŇř—.]ŽüYĂż Ű– ˙ý\Lž|<ž~ú ×y´×Ţ{ď]8˙üsĄPÔ4ŐŘ44^ü5ŔޢN˜_™‘‘^îľٌŽĹŰűň>ľ S}8ˆ%K–ŠÁÖ|YX 2ÉĎĎŞädŒŠóĐĄƒącÇNÜw߃˛áäąúz+C† ưaCĹ`i˘Ű{œpÂń†ď˝{÷yţŐŤ×Ęs÷ěŮCłşöÚiČĚ̔ÇÜwßCřĺ—yhÝşľhČϔĘüŹYďŕłĎćŔßvv÷Ő.9ŞÎézĚcż[—EĂD ÷M*ڏ’ b)¨ČMülşűÎý&Řě&y+7×~ŁăMnÇŰ6dY`wđXŠWńSá}X˜ü*Ö'ĎÇÁ”=˛ naaĄl[źŮv űôĎU š3g>)ĹË-˘eúCƒg̸ +VŹDC@KßŰz¸ŘMLŃŕ>>÷Üo™Řx°ІI b =Ň{÷ĹăćűŸĂ łć ż°¤Ě–ëɖ“WˆGž}<ţ†tčxĂôőY+ B#F —÷zčQÜ~ű]RŔČĚ̒Ą÷tRtěŘíÚľu˝†ý7÷sÄž˜}mŰśmĽˆ˛mŰvÜ|óí2…€ĐQÂcx{ÜqÇH1eůň˜>}†œéĄhĂĎćlk˜ü駟Ë:mœ ţúë|ż}¸˘é¨˜Âqŕţ#đôÁŻpIÁëřŮźÎ)ŚÔ%âÜóĚ˙áâ‚WńÄĄ//ޛ×ŕŮ>yŢ7z\bëz~üń'iÇ|MnnfĎţożýŽ|ޞă|O¸ŸBŒ_Cégœ&/[ö´}B!…Ĺɢ¨-T„Š€}~šó€ÝÁBdÎ*ÉukÔd­đŁëވBíë:jNŞ4ظÝrËMÂ3ŐK>ć '!áÚˇo‡/žřTŞňsć|‰—^zU6ƧŸ~*{ěa9#źŻĺV˛úˇż*ďż?[Şć_|!ŽťîjšďÉ'ŸÁü);‡n¸;wî”űé)›8ń8\zéňwyÄźąbOĄ×ç†u Áˆ.Ąxô§ ˇýk„—űÂQÍ ¨ŸřňT ń[`uŽěS–îC{rxÔMŃ×Vѧ9\ÇďžTŒ$oF˛i36ŮžExV,ZŮzĄ]p´ í‹Čđ(é-ň,n[Ń@*Ű.4”4ŁĎŹGĽď5~éË)T˛đě­źˆU붖Y?Ł ŠĄ|öíINŋ3oC÷n]eP“ígŸ}/žřŠěCé1ćö /ːŒ|˜|Ýi§%ë&ü÷ßFŮ?k\xáTŃg_-#YޏâYŸMŤ˝đĘ+ŻK1…c…Bßýk÷sssńwňzô81ýÎSźäsL řĺ—_ĺcŁđa_ŠZ2ĹŃ˝{÷âßWăĂߓŠF¨ô˝ĆOEĔëďxˇîF}RôHońÜtĎ ˜őüÝč&ú0˘JUŕĉĄř÷Üs§´+Ú k˘-\ř‡ugÎ|ÔđuZ_ż}ű1á™âö$&&FnœŔ}ňÉg2˛•b ))qˇONʈ6>ŕgÖ&aœ¸9_S…‚b˙$%5ďg.ćX›ŮŽş"є…;Ÿăň#pCË)hŰZî׋)5-ŞTÄ֙ÚËąĄˆÁ>˜)ôiii5>Î'e8&`:^#aúžBQ[(AĹŢBéô0ĂŮJŹĹ˘ 5<–u; ňeçÎFȓœœ\|ňo!̖0Y{ ˆâIé-SH wkQ.•ëTüE¨*˛Ô„˛­gĚ˜Ł¤PAúőë‹+Żźsçţ„›ožŃďkŤzYÚ÷=mÚľ.—; Ba‡ÄŠžłág‡1ţoX˝zTá˝AőâeQ* ˇŕž)-0Ś[¨,fšá@ů´ˇT4ô6Ä(´œÂld§Š'řĂtŸŐ˘NL(×1FŃ+î+ˇĺËŹHłěFşi7vÚç#,7-2ťŁ]p?t„¨°–2*ŒB„~EyžjšliĄÁ\كĄÁóç/ÂĆ1ÇíVçÎ]¸ćšiRфţY)^ˇ^Lžfť˺ϓ@Ň÷ř­}ś2W>ÖŇ÷T´YĂÄhrĹmĎŢx̸ďE!ŚěACSô,ý÷?ÜńđŤx㙻d¤‡/QĽ˛6O0k Pô8őԓeýnœ(=đŔĂň9ohßůȑ#\ѢšPĘ~÷á‡mJ„œą]áXa˙ţ(•%Đ(óCI‡ńXî7řŰ´őťču>2-F|f2->Űvp-ł\Ó˘JEmb´†ŐZąÔ¨ę˜~°p-k´°"SýŮfP¤5j$ŠÚBŐP opfF&BC|),).’ľŞZż€ďçđSÁó9Ď÷Şę5Tzœ?`mbĹ: ŚČďż/’ˇ\’‘-Dë ô'-˝AóŽëłŮœ“#íüô˘spĆ---]ćoŇsÎÉĂ7n܌űďżsć|‚űîť[ž†jź/.Ů ÍĂËĚ'3ß.ë+ʊ/ÂWkĘ×Jáą\)DQ?ń´'OřJ(Ü›ähuRœ5O´şđą™<ŽěX>ścór,‹Ű ]őć9˜Wň ~ÍxKŽ|‚ÉŤ–ž&ď´ŁöĂŰw f9NŒ´°ŕ3Î8Gź¸J ™=ű#ůޓ&'nÇ{´ü^?řŕCˇóQLůęŤĎe#]í”m†>ŹĽ<üđ¸őÖ˛MaꀊŚ?˙üƒŒNŃç^{HúŢĎ˙ĺťígúž˘aŕĎ1BX‡äžÇßš ;P#V{›CŘpŮ‚Žq­1°wW5´őíŠNíZ#8Č"Ÿ÷wŽ?–ŹĹă/Ζ^aŁt†@ž_0âŐWߐő’(tjçaÚ ŃDK­Ö÷Í´WÂ>œőŘSŒŐ꧐ß~[(oďźóv<účC˛85ßSĄ¨,ˆ)Üöُ;s?Ž7bŠžżą wä}Œ=‡âÝúno6^ăů@m]ƒăeÎqȂżÉŰčč戍­Ň8?Př>ăƍ‘ę?üXîcÔŠŻ…%ŠęFE¨T­ÁbčyË´?[¸Í÷ LAŘç¸P†ÄëCŕŮpbэ„†•z’-Ž[‹Ľl_~~˛sňdځ֘ůŠRńĄâ°ŽBuŔI'HœXQő&lř8ŮĄňÍ4 N.žřrYЎd s/ľĆű)ưˆ•hŽŔĂ},FÇÉ‹Ř14‘+ôěŮłWŽęĂbu<Ž<Öx`¨1Ă ľ5ě™ëÍs0ךçfD ~­ˆ&#k|lB§–l)(4RTůb•ńÇށ†‡f+rŮÄü­ĽőS ‹FŃ<,&]D‰Ăí˜ňǛ ŁWĘď;zĹýx“ŰőŮYA‘m9ˆ}bH\†čœŽhg€ÎáĂŃ*Ş­lGŞ#R%Đ`-ěW_@zňä°xńŇrľƍëĘĎfJCy=Ç}ĽhІľ4$_¨ô˝ĆK *(ýýoąđďŐ¨ Sßpü„!1¤7Ú´n…pŃw1Ý×.TŇBŃf`íĆ]B0ـmťŔŰ/iÎ÷‹Đ§gLťň\iCžźŮ…EbG)Węc´k¤pN° RăŃ­p{'łĄEęb¤‹IL›6m\ťŠÖćĺ戉~`Š E…˛QÓr 6fŢ Űz6˛LŞÍ%ŘęOŘhR>öŘcpÓM7Č}8Ţ˙mŠ„3ToÝş 27šËŠąđ•So˜“É™-6´ ćŇÉS´Z \^155M 7L%`ÜwߝUZˇałôpSHšíś›1pŕyî>xGNؖ.]&Ż•—{eÁ;œ68[ßC€ßčäţáP4Lh´ť#Ř/ŁAˆŠ↯ô ŁâśÚ1ž‹ŰÂ%°¸żŒ‹Űš ‘źŠŚíŘRü#ş%‡áÍĎr-šjô™i Ş’ Q™˘ÚžR4ŒR,Pé{M#1…ýćÂżVâíO~*Š=âZG㪊“qĚŘÁRL`Ş‹Ńoś[WôďƒSNƒe˙nć_ýƒ‰é†II,Tűěës0¨_wLôbďĘÝNˇŇ}œ÷Mş‡t÷TÔaqŰÝXŒ~š]•÷+C ĄÁW_}%–,Y&Ťđł0ľ&ş0ڎĎ顀uÁ—S{ĂđaŠEĽď5~ŒúńŹŹ,Ěúp.öLP{bĘŘá˝ńĐmŁ[ˇÎ.ąƒ›ŐfCfVö'$"+'O čŢĽZ4o&' ěŁYä~ĐŔţxěŽfxň•/ądŐVChăś}řđ‹ů¸}ú…nËŽzNźT߯hŒřĂó–ÍKS7áCŃ64xÍÓ:ᤈ1ŇyŠlBˆ}VŚsU°Î;ÉU„ŠÚF *@Ň"ńwG—ć%‡‘žşůŃŃr’–“)H!//W 1ZڏĂQąkĐ^ăKŃVƒŹŠĂ WýP+4<ü…ÓVă‹vÁbŞD”‰w?§ďă×ăëřŇÚ+ś œü¤řž:–>ߴہ‹Uú^= :lݟ‡:55Óď~ ó­FmaŸăĹGŻÁ¤cGÉž—“/œ#ł>ř Ÿ|ű‡pĹŔŽâĐ<*9y…ŘŸ„‚˘bŮ_töq¸őşsdä ájvËWŽÇÍžƒb/K•^yÁ xúáé2MXő÷ŠúFMôëţlŸÝ/$/́ĽĽ×W.vŒÇ]mÎF´pĐ*ŰVÔgŒěœÔćo3$$xŒ¸É—‘˘×ÂZşŮJ7ťnsčnľE0ˆ¨P2žFą)hů •%Ş$‡“ś /´b“ž2(,ȗQ* ÷ËNLB›%+räĚbfś˜ĺ­‰ˇAf÷}\9 E˛e>vsŸęľŠRQ(œ+qí/؍“ &;JWЁGzn 㑚HzQşOmˇ ΈExmĄĄŇ÷?ZtĘćm{đÇŇ ş8Ž~_ą;v Ə$”Z ĎęËo9?ü…`Ń?_pć8œ{ę8´‰m)=Źvť ÉŠ™řyáżřę§ĺřüűżEż_ŒożááĄRd9Ź?Ž?zć˙ľŢđ“|÷ër\{éi2¨ŸŠRQ4ihűhvdîÇ7ŚQ)rŹp$YĹpäˆ9Yž˜‡•؝›Ĺäělĝ5łŔÔLř“cBaŽ ƒ#ŹúmďŹÄiéĂ1˛ŮiŰjźŽPÔ-JP 6Ü\gBǢgdJ%i–´imNCŰś­…(ŠĐ°0„厪É$CÍŚŇ[sŠ"Ôú’’bXmVš” ë$ŻY‹¨§_ÄȌL˜ƒĹqr3—ÝZĚnű8â*yďudo܈˘ËŽ@ë҇jި•BŃŃ Š´ł9[a7•/BkF™Díţœ÷"´ŚrǛ<žó_Üśěš@ӎŒÓˆb‹:ÉČ8e÷î¨ô˝†/5Ąˇű“ŻÖj!ZŃăźÓöŚŐ>łăĎ%ëńĺ‹&#Ýz>Ž?v„đâEĘ>_ƒĹ;uh‹!ýťă‘ççŕ‡ů+1|p/œqŇ8)¨0şuęÇ`áâ˙`7pĺćá뚥W.Ş–Š˘ŃăĎöéý¤p Źߊ>&!¤ŰˇfŔą= ؕ űž8ä6TŠćÁ0uśÝ9 ŽîÍ`î sßp„W^hĄ“çłâ%čÝIŽÖG”m+u‡TüŕYŒ68ą’ĘśŽ8ë>쳕ČÁ•TÄć̍Ó !ްP­Éd–BŠźÍLß^Ť`K0l˘ąOٲ1ÎDW„ř›‹ĎńŰ<äۑ9}šŤR¸BŃń‘FAeÉ>؃á-brÖŰpEˆ8Š^qĽ˝âąâyźŠ\ôŠńńĆĹm;÷s[‚]ĄhĚh)|‰IŠXř÷úZ‹N!íăb0t`O§ÓÄiňÎ'óAŤźęÂ0ĺřŁä˛ÉžĐóĚŐ}&=3RłđüŹšxďÓů˜,ŗpyށýşĄKÇ8ÄH2|ďšóW`úUg‰óGŞž^Ń$ĄÝÓ)š/ë0ţ0oń~ÜęTŘż‡}}Şčü+)ž‘]ǖLŘśdʇRÎÂ˝Š—V†ˇ‚iL˜ÇŔŘÚ.š6ăęŹ#2íÇŮś(űV(ęŠ šoÓÁŰä*,kŞŠĹ^„Ö–lT–ââ"„żů̙Y¨,Ąs@ÖĘU2ꆊů•)xŤP48KĎOGfPڏ؄9ŘšŮKou÷mB´°ŮMâžÉë1e÷MňxťÝäśżüůľcJ7óŘ<Îé~<|Ď]8:ÇôRĹۍO§ČŸK×#'ݍÔYQ;[˙^… îňďŘ}{÷'˘Ml4ŚžyŹß•śÂÂBeTJ—ŽmpđH:6mŰWZ@Ů$ŁTőí"îż÷áÄ üťvŤěëUŸŽh góňňđSŃXÍ^„’őé°Ţ˝ öIŐ+ŚxCtȎíBd™łÖ[V řŒ…°ż°  č ™ňłđ3ńłi}v…BQó(AE‡żˆEă˘ŹŠ¨šŰÓQY‚Fř†¨ ô~;žúF†?Ť†WĄ(W÷Ů]°ŤTˆ(6lb¸é3É×;ü[śé„ÝfórŹ÷ă˧ßÂłă\a Ec!ˆłyżŻrFjŐâż.ÚHqƒoĚËÚ¸uxL߉iŮ< Ěٍ¨f3˘ŻL üoË^™6D(ŇtéWZsŠü?žĎ‚?×H1ÉóťQ}ż˘ąŕďˇĚąîďďăfűüÎÎąŽČ.í§”L_ë‹ářőL%ţW!ZhŰ(­đ…˛s…˘ćQîÉĐ7F!(„sń˘Ş&ÏĘľk7ރ ›ä¤QĄP¸ŁŮ|˜€†Ą8´P—^ă,ë^ěŐažăžÄÉM˔8ق•…˘f9°›jś¸­vNĎâśmÝUş˘É Ľű¤gdaăśřZ §íˇˆŽrMŇ2rA íŘ>Ö­fŠŻs°ŚZÇą˛IKĎq=ÇĎá”Oź|ŹŤˇ‰ ežL đVSAŐZP4FřťćŇş›‹č+2<¤őL",2u!fgŐîŒn @ń…#>Ög…řóţNXŽęói˝Ś%†daSÁ~´,n)ŞP6ŹPÔ JP m‚eśs•ĽŞ *&yžĘ\‡řŁĺUVŠq'XœÇnw÷čŠâ´ŠŚ‚?ovxx8Ćś‡–i1HLOD’ĺ0RBRÓ,Ë} ĺŇ{ţŠĐv9ÜăZ+‹CŚĽĽ!qßa¤‡&‹-9Q鰆Á¨­żóęß= âśBˆé1@ *Š&S^6oÂBqi´HíвE3LŽĂeů[éőŠůœ.°ý~Đ˝đ,tč% Ȣs3 Ł.[‡ÁÔ*ŚćÁ^ESąöŹbĄœÁ‘Rʗ›}w{rO)J+„ő…M0} çFÁgź*ßŇź-8ިŸT´ĎŽĆň Eí˘•&Œç„˛:˝VˇÝv'–-űÇő˜Ť zĹ˝8Źf1ňw †ćš@q‚—––Ž””ńý&#Ľ iĄG‘,#XB´ŃGZÜVťoĹmCsZ }‡eçóbßj ŚhLĐK˝öżŽÔ˜Ú€6tű´3dŃX—L*öuëŇV Űv,MÝŃĎĚ´ksyyÜće­”ŽŰşŮgJjś,Jé 6k7ěÂĐA}\őZ*Óˇł_çëŸzęqÔg{ěq™ńÜsOŁ6ř⋯đ駟˴Şü͛7GMQ۟­!ŕĎ9BAe}/|Ň= Áűoýĺŕ˜‡´‚#ŘŘF|%Ń8BĚRxŗžŃŽý´PöÁö]˘ߐűšT8ÖĽŠĆÉwD‹ƒŤ ÍÚÓ˙†>żŢžOśo>ĎQ {çóŸţ~ůe:Œ–-[`âÄăpíľWÉ-*Â駟Ë.ťS§ž'S//şč29FžîşkĐXhʟKJPńĘ;ŹcÇ…›ožIŢĎČȐŽëݟŽożý˛Âq uÔh!Ş|€ƒĄcÇr˙Žk׎“÷׏Y‹3Î8Íu<9BFGĺ7ľŠňŇKŻ"''GˆMŻš R$˛ Ä‚ćĄQrŽÚŁS§Žň÷ÄßsJJŞYRqX 4ƒŽ1$YÍ2` .)'n4ˋFˇž]Ü&=<'=ĆÜ ‚üíQ´ILLđ„#H1Ƒű×"ĽşLšTŔ{zPŮ}“Űő´(l/Wü0B‰(ŠĆ„ž§€šuçZ‹Ná;ŸxÜœ:y”GńgF ë-„‰0lŢ~;öĆ@Ń6”ÇÝNĂę ť,kŠpŮdbł™°{_˘ßĎľy[źl×Ę]§ňbW‰˝{÷áĹ_Á]wݎ!CWŤ˜żçw!~řáŮ÷(*†f˙ĹÂöw‡¤řAǘŻé]özT?ŇßŇ;ZnćŠÝ`*´ĂöO’rŤRœEŃ °ďĚňZôrˇ{• *ŐeĎ,Ęë­w`űö¸ôҋѧOo9’(–%K–âĂßCŤV­PIsÜqÇbŔ€ţhLÔĆç:ńÄS¤CóŹłÎ€˘~Ą•jb ߄c“ĹŒјuŃ¤"N.˛Öű/šŚTQQQčÝť—ë1#TŽ?ţ$,\ř‡TŠk‚HMPŮľkˇrECt‚› ÂcÆ˙\ŃށňNrrŠČř7l řňhń1#•fďţ ‡l‡Đ.(=ĂşŁóžčÖŹ+"#"eÚEAţžé˘"ŕĂGjKAR𤇼"WÖIąŁ­˝ŁL!ňeg9řŰíÜš“s…ĄôtŹ]żKCçĄ8Œ%p–ľtâžŇcňŘç==¨SHy-zԄJј0r†H‘Tˆ0ŐFʋíÚ´Ŕ7ž-Wáń¤m›–8iâ0Ě]°Ďźö=Ţ~ţD5cäˆÉđ\ů…xćőďĹÄЎ)B¤aíÍfsň °eÇżŸ+áPŠĄ âöNJ\Š0ŒŢ$çž{śÉő ţć­™(6×ÂĘ=•Ŕf†yR;š9’ œË6˙œäšŰŞŠżw'd‘ŮŠ$kÚX[WŰĘ}_~ů56n܌Ď>ű]ştví?é¤qĹ×Hą˛‘jt,Ýzë 46ëçR†Zĺ§X„ťŁÂ°<$ŮfJÄx$^xfGcfłPxžŒ|;îý6žMÄŃĎƃ?d 3żjĹ­ęœÄąafč ůůç_…Ŕ2Ĺí !#GŽuEŠ0L𫯾Á}÷=ˆŁž„)SN üŻďÁüđáÇş"RE”=şc̘Łä} -ŮŮ922…0”–ŠAź÷ƍ›pőŐ×cܸcqÎ9SĽ@ă =X7ß|Ž9ćxůy˙÷ż'Äű:‹Ł-X°Pž–Ą‚S§^,ĎĽÁpUC!ŠĐKpç÷Čóq{řáÇ\ç3ÂßńŹ~˙ÄOă„N’ŸóŚ›nÁΝÎĺÁçÍ[ ˙LőůđĂOä}îkŒčWžČĘËƁ’C° aă€őţÎ]ގ€Gv=×śĚÂź= °űČů=ňř6mZcĐ r°qć1gŕœ^çá̰sq|âÉžvŽj3ĆmiT-íÇł~‚ö˜sll,F‰Đ˘H׊@\šŮŚ[FY[=Čf°4łśŒ˛~yeS‰Ý[ô‘˙ęš81 €ż mcĘ=[űöĹťŽń´­ş†ÂŻuϞ˝¨i˜&6cƭ҆O;í,ŮîŐęŰߤŚa _Zz>Ě´ŻŢ8Ššď–s…pŇŞœ­;í;7^}*ÚĹĹ`óö¸ă‘q8‘+˙9SľSҲpßăŸaĺÚ]ˆiŽל&ĎŻŮďßË7 QĽŘď5%Śä¸•šŠžeĘËŹYoËž“ż÷K.š˙˝Řő| }>—ܘž;yňɲĎbŸŠOiĐ÷YÇ{Wƒý,ŁSČŮgŸ+ŻźśÚ>[S‚żů]QerŹpl΀}ŃaŘżŢ űű;áxm+ě/lvn/oý­í°}źK "ö•ÉŔ<˜lŰšŠM8‚něËt^7gą[yP Ě7őóůÚ݅Gü ځŠóçœs–›˜Bčř™6í:™BŻ#ąYO4Ű"š­ńœü­ÓfŽżţFŮOëad ۔ń㏓cdŚěÓůd„ÖÇ/^źDţţi<đ°l;žyćyyl?>úč“rŻńpßŇĽËä}~ŚçŸIś ´ůkŽ™&ÇřFŸ‹ŇVéńv~Ž#xééň|źĎcľkţő×ůBÔ˝@ś DľľT ¨Č`#](/EKňMÁfĚ ÷ďľŕ[Nű,żlĚÇřžĄb ĂźMů¸őË4ÔĚĐÇŰuÔÜťńÜLg`fEřŕƒE#1?üđľhŽŔ+Żź.… oP Ń 'ź?lŘP™ÚĂH‹œ+rLˇ`D@eޛ ŮM7Ý*#aţxĎ=wĘç ËVNbńŃ뎝AF4źóΛ2ăŒˇÉţřńcĺ­&1*a˙ţ™˛¤yžřa„š÷Ţdřú'ŸĚÁűHH8€W_}Ăëgđu<˙&ˇß~7śnÝ&˝ ď˝÷–œČóš“D'0 żýö Úľk‹3Ď<]ŢçžĆŠś"ŔŽÜ=(qŘË-]œď(Âö’Ýř)kž=ř2ßţ,foűK–ăpę9) Gşk×.2ýěô“OĹéĂNÇ nƒ¤Řç­Ľ‘°BŠKŠ‘‘ăuÉe›niä@–fŽČŽElŤŘrďct=żÍ9s>‘ŰłĎ>%ŻLďc¤Oc†ƒ<}ńěł/Hᖞžn¸?ţ”´oEőâŻďâoúč1ýJWbnçŸ1Ç;mžâ¨çĆtöm[á…ÇŽ@›ÖŃXýß^\0í%<ůĘwřcÉFŹßź.ۄçgýˆóŻ}Kţ݆˜–Qxî‘+Đľsœ|˝,j[dŧß-•…jý]Sn~‘×ÉGuÁ‰…€ťďžŸţąěßîťď!ٗTNŹmćů矏˙r93<űʎß~SF ˛Ďb˙ŠĄŐp{ăWq˙ý÷ŕ÷ßI‘Căíˇß•ď¸ăV|úé‡B>FžwĺĘ]Ç0ň_|ń9Ůż{ÂţôŃG’÷çÍűQ>&o˝őŽ<÷M7M—ýîÉ'O‘“9˝¸D8!d˝…ŻžúźÜĕý,Ç äý÷ßĆkŻ˝T­Ÿ­1Ło ř›?\œ^ÁˆmčwżÚëƒkQrî"”œúŹ7ţŰ˙ÖĂöĆ6Ř>Ůëˇű`űiżsű!ś/öŔţÁN؞ßŰ=ŤQrÉß(>a>ŹW-ý™°Ď; Ž~ßŢÔ"ć[ú#ä—<÷˝9ŚßEäŠRdżkôTށ8N9r¸áóŁFâ^đeł@[[¸đw1†~QžƒBēO–Ő ú÷ßUBÔźOÚ Ű–›ožQ 8ü­ű‚bÍOüOž†˘ĺĺ—_-Óçžűî+Ń6Ý#ŕw ĄŢxë­wĽ¸ň ĎĘT<ք¤ŘjÔśÚVrţ˜˜9ţ&Ó§_/ďkEˆ K*ÜyçmÂîgËÇM˝ ¨ TĘOů=ĂB?“ĄA¸(đŐţľŁ›– ś™÷Ÿ-ZT3VĹ'cËĄb,ŰUˆ‘ <}–JöG}*G›Ÿç wȐĎŰnťYćÉ:ˇ˜JçĚÖ'ŒŇ}ôű-´)s› ܋˝:Jë•8ăý4S&ҋ6`MĘXR‚Đ!¨z†wGߨŢčѢ;ÂĂÂŃşukC!E˙X{­2?Ąv0˙€h_Ša’ë+; ŠĎÂmić˛ú)NOˇĂăřśčâ5ݧ*+žé}Ź%PÓé} :ééăŔˆ.=wGŽqĽ$*jFe=+ F‚üüűüřŰ:’VíN„nBđ¸ůšÓüŚĐކěŮ/ĎŔłB8Yąf'žýu%ž›k…ŽŇăŽŃ÷Í8 =şś“Ë';qŕóď—`_B˛SPńCAąUś5™ÖóŔ÷ĘZ[-[ś”Ż˝öjŮďoٲUţöĽ[ˇŽBuFdÄĹʼnţň$Ů__}ő•^űŹůós[Áˆí݇ôďßëÖ­}÷ZY,’‘4Ÿţ%ž~úqŮ“Ž]/“×Iď2ŁY '¨3g>*"FprÄ~‘°oäűóÜsć|%kŞL™2Y>׳g)úÁÉ _°7‚“%­żĺ­ž6Ku|śŚ'ş9ÖŔkă9çĂvďj8öç˘ZžŽěcăę>BPĄäaę ó„ś0ßčĺ˝ćŽ#LüžĂKQĚ´ĺV›`š••%ošĚşÚoQ;ŽtëćÝfśöČ#ş"yéŔd4ľÖ^Ńv.žřB\rÉEňyŽgYǎÂފr3ă~B{üţűšŽsP´¤řIÁcčĐ!„C‡Ɉwmţqß}wKĘčýmŤ9?ŁŮpÎĄÉőÜtÓ 7nŹźŻÚ€şA *UdˇĹ˙@ŚH4…GЇcďtŚ|\9žZD8˝O—Ži†ˇ˙ÎĹňÝT4%˛6ăUŞ'SZšŠĆ3Ď<é3"ÄρkůůŢU~6Fä°1ËÎź|!R8•v-zĺěłĎ”Şô˝÷ލʾ÷ž={dš‡ž!ĺc˝¸Á‚^lő'B~Űśm—Ý1ÇLâ Ą ĎHŞ˙źĎÁ֊+e§ ÁA*#L–,Y&ӛŽ9ćh9¨ň†Żăy}ąą­Ü ŢɁžč\x}MvFťŠöĂnr.œŤƒ T (/n”ˆĄŇ~ŰAěĎ=ˆ?s— 21=ºᬎ§ĄsLgˇÜfoâŠ~šCv˘ťňv@[ŮÜ}ĺ”XܯǤ[ŽU‚z”.—\ÓuĽŁOď3⧟~‘ZFLń7ČF|q`uĘ)gH“ƒ*˙ţŰ(Ă_żţzN@+…ŃĂöňËŻŠ×m×*můÍú‰ ĹQŽîŨ0 ޜéŢŽ‘ᡧœrŚ<†áˇÜţůgą›ÇHƒśö×_‹ĺçyúéçäy)ZÇđćwŢy_ڌ‹kƒóÎ;GžƒíÍkŻ˝)e đÍ7_ČÉÓšşŻžtzĺč˝ă`Œ2ôţőíŰGz°|˝ˇöžL×bĘĎËżÖĆ1œ™mçż˙Ž–í'=_œÜůşÖúmŠŸNZă†Ë§ŕŠŠąbí|űËżXšv'ŹśŞOFB„ƒĺŃ;§ĘĽ’]5ŻťIŢxň:lŢž‹–o–Ejsó Ń,2 ˝şľĹńăbP˙ŽĽK-—ľ+ÖěŔťsţbJ`.›Ă\ă…öy}L]ˇnƒ°ŠýŇ9Éăďł"đ7¤‡“öUĨĎâďěÔSOv{§`ŮşuŹëüR8§Ç–+jäććšľ-QQÍźŠ)ŢĐÎM'ˆöŠt°đűĐ좲ŢŤăł5FŒ~ßܗpâ=d„Iľ‰)^p$äÁ6gÜLÝŁtvW˜ŚtX<1˘Đnü+# jBŠ^0ŃŁĽúč_6´5}Z4_Ďq0Klˇ)r›;÷G×1üMЏŢğ6mĘŽ‹"ˇć˜ÔŕxČß IzŘŻÝqÇÝ8˙ü‹¤óv̘Ń;vŒáąśU•=żžöíŰťî7ĺ6 .Q‚J-áٜÎ(ÁŽ˝ůą#8ԁ͇œ=š™÷řřžáRPٖX‚5ńa EČĎ-F\–5mŐáŢá22ƒźňĘkŇS;nÜżď[Œ5RřŮ!p"Ą5˘Ü˙ŇKŻČkaĄZ†.V^ŤQASKřihß/=VŒ¨á$<ÍŁO‘…ű8Ů;öŘc\ŻŁJĎĽëČć“O>—KϘqŁáűř:>ëk*đťŕd>1/ČsŠĽĎ•ż-+[:Ĺń(+:y1ŒűŻ` &gSŤňé<ţ Vć91ȎȂ=Čćńž&ˇ"´žŽ•÷Ă "ŃľcW—¸W“_N…Ąyo=až/ó˜ożýi“x̜ů¤˜(t”ŃT§žzŠLĐ *| ‹N2 ĐRí( 2lžáĂŻż>K0>řŕ×q~ř!œś•÷™7ţĎr`çëľT¸)SN“áˇŒÄrË-3¤ÁźoÖÚyő՗ÜŽFháÍ€šśoß>ŮÂ*Ńžág>ôoź%EŠüÎ]ö¤K[ůĺ„ˆ%ďOŸ~łaćH˘' ć{N›v­lo8({îšÄ{fI!FƒWocŞSý]k}öÍÚ%fłCjٚY0ů˜Ą˜4~â¤ŕűŤđë˘őHIËŽô{\uá$ŒÚÓëŠ;F&Ç}ĄĄfŒŇĂŃíâK­–Šš4"E˙Bţ]żw?ůŠ­vgJO˜jAÜb­.ö­´Ú0#3ŽźŇ÷ňĄíóŤS˘ č9łXŞV´¸žŹYŸ­ĄR‘Č GNI`F SlŽŇŐś¤çŁPôŃš%^Wę1|ż˝9°ž¸ xo;‚Śv‡™ľS"*ţwŞÎßű2öłkÖŹsE8ča4Ç'´ďڂ×tăÓ #Ü=E’ęÄó{ĽPúóĎ?ˆţw…OłŻëÚľ+Ţzëőr+ó7ŠČůýĄÚ€ÚE *U¤§ĐŹ ń}L¨0ŞŢŻůłńRÂa˜,b`ł%LćE‡• œB,ÎűŰăÖ/˛P˜Ÿƒ˘ü\\ś5ץţĂĆVKxňə˛Ř‹°iN*¨˜Ň{ĽEuTWmN¤˜SȉÔčŃ#]ű) p˘Á;^ó+KŻ^=ŤęwŠnk“)zçôjwż~}ĺÄLď•bî$=Ţ\†ŽĐKĹ΋Ţpž–Ż!| ë3đ9-d‘~†íń /ÜÂÇ#AĹßńÜOď5# ´÷ Œ :ŢŘ$ÝgCĆv96ň\nŘLąĚ-BDż<ą{ôŠvLTQ3´ŠhéćŠDŹäóŒň˜ĐétŒďŒ#I‰H6A˛%™áé(ˆĚ+ˇ4łűő”^iY'Ł3ŒjľíŤ,ô˝˙ţ‡âˇ\"„‡ă Ą‡†vÉt(Âđ]zo)‚RPad ŞQÄ  J/Ő,ň*zb”j÷ Ď`óć­nyć 1ÖBđBĎTfűČ߃>"ÄŠŤ]‘=ži • ĹŽŽëq”ÚE–^ÝŰăŽig`úe“ąhů|óëżŘ¸ýě존‡A};áúK&{ ĺvbňz]|ŽěŤ2ˆ[­6|ůó źôŢ<•ŔřÎlŽQ•k{źţúË.*Ű}4iuôůF}ŰÔožůN8ŽuŮŤ/=Ç÷§čŤőˇ„˜ví*5˘Ń­[WŮvłĐGăň1mż"öP™żWM~ś†żĂpGŕŤ/MíëÚT ¤tĚŢ6AƒEűŢ[ô]›#anG°—ż#_–],S‡‡D?˝7ö™plÍň}Í.íý°}Ëő}`>ľłhŸ;Şw˘LQ”ő<< Óćĺĺ ˙=ikŐšD¸?YÉ´9}T#ŕ8fŤl¤—'Îţ“+6jýŚgűÄ÷d4  ŕvÁç‹íěŘął\ôgeÚ*ç¤MPm@Ý •*2šČŠšáÁ>먜Td˘ âů߲đÂÔVr ÷ňďYh,0U†ů˝ô¨žyć2nđ`gş ĂĺšÎ=#18‰Ş(¨đź8˙üsÝŽƒ…ďžű^tg˘*œsŤy'&e˙“žt(ß~ű=ˇe2™ŞĂ•‚˜ zŮe—ȢĽü8°˘7WăŘc–ž_îÓ\”~ńĹWné>LGáŠA'ž8]tŒ¸R7Ożă9c˝ zćY/…J?Ż— 1ro0%ŕîťď“čI“Ž““ˇn˜!‹˜i^i~˙,Źűú믠žŁ‰*čoĘÚé\ÇC gž8[wĆ7óţł%›“[€ňbˆSœ  A„ŘżsŞLÓŠ&ŸK„˛rýźýŮ"ŹÝźĎšÓ\ą TXxŞĂěů7ő\‘ŚE‹hY̜#ÓÍhK´#|Ô ŐŃç{öYl_é$ř믿qüń:mî’K.”hŠ8y˘á…^vyŸĎ|Pԟ袊Âińş đ܌âb톧žšYĄs1ßתUŤeşB uh*óŮ(Xł˙ć÷zË-7É}Ď=÷"âăăń曯Iůńǟĺ…‚™>˘žĂď/Ҹ]šFĆ"řóă„’s!t,ß>űÎóçŢ"D–Ő–:ć.WßŰ.„•S`_|DFŚ’QëłaN*@ĐŐ˝(ÍMáŐ*^3ő„üŐW_'ÇŽěoX\úóĎżżŚÇVŚÎqeMŽ_==aĘSމ&L/Ǩ,‚Íy:FŞÖD˘˝0ĽöŠ@úbĎÄiWVé  }sźL›7ëTŚ­ňw~~wWpĄŐEô$6 1Ű|]Ą•*#dwäăůČPÕ~•ŘpqA€!„‚ßśäcÓ+%?ć´|,őĘťW58řç âĹ_–•źŮ0ЃüÚkoČBŽźłŃšăŽ{PU8đ`ž1ŐeωĂ÷ŮHuÔ(T6požůŞL×áő3‡”Ĺo9ÁŃŕ óý÷ߑ).l‘!”l,ő“=†ŘsYb}Ž$ĹN(YóDƒ+…s5!vt„‘$ú|=ţŽgüęŤ/ĘçščÝ ‘á‘RĐ`zëúpÉČŠLYIÍJFTŤ(Î*ŻŽUěL™&Ŕ´z}čąe˝ ôä2Ź•á˙úú"üLŒJa˜*˝+\^Żţ˝3ě9Č,ڌőbł¤™Ń.¨&ˇ™ˆŁÚňZľ>ÂŽŔ彚Dąg…ůřřý8ýôSĄP rL݊?˜„îId*W›D/ŽTd°GçGżíńü]S1b@W<đÚ\<ţî<5¤;útm[îÜ,<űĹüŐxňÝ_‘›_SPő.yęIŤćĄčÓ˝Cľ­T(ę;š(Ę1öQ–Ţř *óVż˜B˛Šaű5›˝Łp œß ćS;ÁRľ¨´ŃA˝jl?…BJPi@¸<ŃŞ˝T(*„7Oł{ý”]Â+V~ša™ĹŁKĺq.—\*8`˜äžúă?=¨ŔQ‚­Ĺ{u(&-Íě~~“.ÉᖖDJv$8!%3 Đe˘4„ג%ËdŞĘđáCeZYc&1IÖ$Q(A›XQTźéŠŮˆlŢ—vŽŃ !Áî‹Nq‡‘ rVmMŔˇżŻĂ{ß-Ç wžë:7IÉĚĂCoĚĹźĽ›K-Źä7 {,ZŸăU/EcÁ(ŇL–Łcú U~Ň"ňýŸ°[łňďŃ:L쏂šmĐFÜçă1…bˆIlrLP(ÝŮÂůV$Ŕž7Ž=9ÂC`°ŠĎÁ‡ë˝:˘ƒárÉőy°uŇI'ĘÍzŮ˙ůg1ŢaôŽŠŕ)•‘}Úâ­_ˇŕŻuťŃĽm .ćKqĹÜťěűýŒÎĂýbPaߙÇęŘ'Â!îëq¤ÂúÜF˜„ĺĺ1pWĚFGfuB\ˇ8÷kQvŽPÔ:JPQ(Mފł7ű˛…nQž&‡I!R˝˘?>č•ʡuorť3sÄuŻu?Ţ)ąDFĄKŽ2gU ˛_5Që 0v>ůkr ŹŘŸ”‰g>ţŻ}ľSĆöĂe§ŒĆQşĘşeUĄw—8DD„"-ŻYyEhÓ˛Ţýa9\ČT Q)ąÍC0aD_—Ű[; ÚEcDű]sŐ¸Sƒ‡ăű.XÍvżŻ3‹CuŔ•~L,J+6Žćƒř\Řçî‡mŢgDK)öé°oHƒiTlŔçśŘÍ8-x¤ülMST(ՋTľBąĂ†˙&o÷H÷qţW>}ÇXÜĐĎă˧ć8ďřKrŢwxˆ-úk+Aq]Oůô îď`o+‹) Haąw.Ö˝%–nwŽř!SîJlřaÉfü¸t úwk‹KO…łŽˆ–QnŻ×&,Ţҁ4ńFV´cązsŠ}Š˙Vm= ú>0Ä ľÉ¸ţmŃŠc{È´ŞNŔTż^†ę×ëiz´ý‘ÝbŘŽ%XwuF×f0ß6Ś+zÂţůŘżß/ź:vŽËS׊őŐÓŰcDďŽ"ŸŢ¨ĄEŮzĘÖF(AEQŁŘvdXóEC\…~'ůśbše˜ňŃ28B5Ęu•u™{ä2ĹţRnxIŃѧܔ?ŽT¤¸­v”ű>Łâśđ™Ô7˛§aşĺŐR4´ WóćÍqքžXąg•˜Ç”M ´tş-ű“qßŰżâŮĎ˙Ä™Ç ÄŒsFç¸nçń6yÓlik| Ź6´k˜ć‘RUIĘĘŤu1%<؄łŽî/EŐę´sŐŻ—GőëőŁč4ޏ‰‰ÁšśQXď8ŤÉ”J^cËPÍ菠sťÁţo2ĚĂbuY„Ń)çÚGÉĎTbІ˛őň([WQ{q§Š&G‘P˛eІŘl˜S‹s‘^Rĺ‘_Xˆ=Ei ůΎҭôžÍußäÜě&×16Ăăľc´ă=ĎăÜĽçt?Ţřœ÷MÇĂÇń&قŃ?ś7BBB\Ÿľş[5ĹÖ­Ű0räX×vÔQpć™ç⣏>‘Ëi —>ţř)U>FŃpđWˆË=j †vmî,k°1%'3ŻÍ_‹Y?ü#=ŔÜXET´}ÚćZÄ{̚ťBœ'ǏîƒĐ`ääaűTŻďWSŰŘŢ­0bHżj]ŚRőëţQýzýBűÝłţÖą}Ga¥Ψ7´ ‡ůŹ.@—Č ˝ěčĂ]pLߑޕťj˘OWśîeë Ąb@e+ü× ÛĚđŔäâě&XrŹ…ň6&¸bŞ˘ęÚJPhˇ•‰ ş4GuŐ>.zDŸĘSşŻ&ŠŰś*lśmâtĘ /<ƒöíŰË:7›7oÁëŻĎBqq1ŽżţZ(âéŠnŰś-.8ş6%ţ‡"ŤwŽ–3ő.[ż?n^‚í)ńˇ„Ą{Ť8ođDL< – ŚýsdƒĚźL:X{đwi A3{rĚĹÎ}Ús)7R`A )7+÷čk čӃ,n ]”@ţ×ÝŇQálČtíÚUl]äýţýű!-- ß|óT•B›\1Jĺ„ Ăą`ý~,ňXuÓ#™yř|ŃzL;í(\zâ\řřxë—U˜8´;.š4ƒşľ•śˇ9> ď˙şK6íƒ%؂§Ž?˝:ľFAQ ^ŸťŚZL÷áçœ2°ÌR­Ń)Ş_Ż8Ş_Żč–ŃĂFࢿwâíž+a75,ÁŔ,úú †`ÔÄá5qŞl˝â([oÚ(AĽ‰PÔ­;8ő*ÎÉCaVŠ2óQ”‹hT?ŮÖŰ­nűŽä¤áŞ/ŸđŔśÝqéđ“ĺÄrYüx`ţ[hß<ÝbÚcă‘Ý8˝˙4U2JňUc\ËDGGc|PwĚłm/'V˛‚°&— aö˝â<žfŠŰ:*XÜvpËž~ë§T¤~ňÉgřšš&kŽš Ç?Q>řđœqĆ9xĺ•0{öÇŘž}Úˇo‡ťďžG5ş"o…ž}ű ##ůůůreƒÜÜ\qŢ×ń÷ߋQTTŒÁƒâÖ[oFďŢ˝Ü^ˇfÍZ<ńÄÓHNN‘ç¸óÎŰ0`@Żďłwď>źüňŤřďżM“ăcŽ9ˇß~‹Źż‘’’‚ .¸W]u.ťěyü?ü(Ž _~ů™ülŠş%Ou›6mpŐäAؘ´)šVďçŰsß,ÇąCşŁŻH>đÜűţořaů6üśnŻ,œŇŤ­4­MLs<}ődœ1ޟ|żž]Žm‡ŇjUPé‚ËN†-ZT›[őë•Gőëuƒ7ۧŁáü'`÷î,ěź ‰ô×ÎĎPSľS”­WeëM%¨ř ~§ţTŒ´ËŽ—ˇŮŮŮČĘĘrÝçq\u4Ćš6÷|KŞÚlˆe§ŕísďĹI}Ƹ=0+!AÁ8÷“űaďoÔzńRрOÁ˝/CU(˛–ŕ­ßăäžcѧľ˙<ÚEť×๯ŸÄ˛›ŢAÇč6xrŃG˜ˇ}–‹Ç•áݕ?â•e_bë]_>Ď|Ě<ńýŠšzń5ÁŠŒŒÄGöşüt68'FžRnnEhˢWŒ/écôQ1eĎĄ ¤¸m”5˝âşúÍŻŽ{ë­wđíˇßăŢ{ďFÝąbĹJ<đŔĂxöŮ'qÜqÇşŽ{űí÷pĎ=w˘mŰ8źńĆ[¸ďž1ţĎŠ˘9r$QŠD| ˙vˇß~7ňňňđÔSKąă‹/žÂu×Ý€Żžš#߇âÍ7ß×tŻ<ćłĎć`úô›ńÍ7sW~iLFÁđŁGÂ;ďź)ś×^{3f܆?|­[ˇŸă.)Đü$„„ăŐW_ÇmˇÝŹÄ”€Ţţnj†ËvÄkK¸¨ő$ťĐŠË^˜‹Żî?Ýۜď›ĎŔu§ŒÂ˙l—El ŠKĐśeŽŘg !%&*vqžwŹĹżŹŠU1%<،ŤĆwÂP!.Vç$KőëŢQýzýÁ׸]oű:uÂui“q$5›b“Đ”‡k[LFçΝ˛íĘÚ˝˛uď([WxC *R!uő…ęülĚť,ąŰÜö}śnžTľb ?éůYřňŇ'P“يńĘŇ/ŃŁU‡€㺀•ĂUc\ťôëס[,˜°ů?l):‚ÖT$˜ł‘gśę˘BŐ˝ˇZ-đ8§űń&ĺ’KâÝśV2ňƈę´÷‚‚̙óîşëvL™2YîëŮł‡>>řŕ#7AĺƧađŕAň>ŇyóČh•ĄC‡ř}›Í†mŰś‹÷ú“'/Óu˛~ýüđĂ7bpÜQ÷Řcă wŕË/ż–ďAXs…Ń0L"3g>* Ü2Şä†Ž/÷^‡ýňÄ˙s R/˝ôN>ů üóĎ }ôœt҉ř믿ĹţWä *ƒ Ä9çœEý짚çŠSĆb{ň+_'‹–'>5§ýď+<}ĺDœ6ŞFôj/7ýäMł­´œ<ńŐR|ţ÷f8Ě&Y ś6ŕ[90gž0^ŁŽÎÚ)Ş_ŻŞ_Ż=|9PôĎ : 3gášĚŘÓ"ő™-qsńńvÔP×>O›ŽŒm{˘l˝ę([oš(AĽ‚XćůĽľŸyŸœ}ľ=kV>J2óQ,n1q2Ş“b[Iš}sˇ,Á ś= b†Iß<÷lMڇwĎť_ç*ĚËöý‡sMJőw(“­‹‡MĆý“ސĎçĺăŃßßÇ?ű6!ݏŁ;őĂă'OďeÄ7§Écnžű">Xő3ć^ů,öĽĆS~ŒśĘç&őŽ'ŚLCłĐż×’œ›ÇžĹűÖ#Â&•ůťťDx éďťVăŮż>ÁţŒ$Œď2Úuó{Î"ťŠšĹhŐŤWOtéŇÇ$§ 55UŠűr“ą­$ ťí8” ›+}ÇažăźďYűÄ\Ĺm=÷Ô˘Ňčqżdw„‡‡—űĚŐM|ü~břđanű)’P˜ĐŻČŁaĄLÂč_œwޅn'L'ÓuŘŘŘV.1…đ3ň˝)žhpbÉ4 Š1ŔîÝ{ ߓçĽđ¤‹*hŐŞ•đ v’缠Bîż˙œpÂÉňţźy?BQżÔSMoď ' ÇáÜŐؐ\âóœ)y…¸vÖ|Œęů.:ş?Ćő퀶-"ĽQPlĹÎĂX°~/žZś )Ůůrľ Ú‚ŸeBÇP\sŇh™ÎTŃ)Ş_WýzCƨż'ź܄ŁQđW!ŢŔßŘ]OE•™1¸9ó8;ńhhŤ‰ůSŞ‚˛ueëŠĘĄ–M­ĄbŽtnn1 …ŽŞŤŮžXĺWLؙš€Qœő ŘpąŇxtá{2$oć”ëlśČF2vĽ@j^žşä \3útźłr.–ě]/Ÿ{ăŸoń×îľxůŒ[ńÓUĎ Eť­ţí˘bńŰuŻĘc˜t%fO}PŢüŮČ-.Ŕg?†.|˙îߊ™|č÷ěâł^ńĺLÎNĹ?Ž7Ξ?o]&óIɞÔC˜ţÝsčŰ?\ń Nęw>×á›#đeaă/텷œ|wěŘC† –Q—N9ˇŽ>w? ‡OÄĹŚfC [˜űŇČڲțͥ?Îä\žŮËńîÇz>çyźIw|Ů1i†ˇé[ÎC]ÔtJ$SyćĚůDFˆŚáDEEů}oýçćqžÇúZz9Đ󲖋FaĄZV˛>â+BC˙ÜđaCpóĞčÂľU}oć ŹŢ›„Ű?ţ ăüƒîüCďţCîú§?űŢřmƒč›Šœi>ľ¸ Š ĹM“ ˙ž}㊴ †ýzŠę×Uż^ń×ßk÷)œŸ,‹ˇgž€Á)q¨o Liƒ;2—×Čk ĆŤŇď+[WśŽ¨*BĹ FáôlfÇÇ#*f0j/#şfŕ'J˙u¨á —ëýJżĂ=i‡đŮşxíŹ; _ޟ>îĄNŸˆ‡ź‹?÷Ź č|ĄÁ!2Ól2ă–Řó1ëŸď°%)Çt&ߋŞy^I!Z7kO/zÔőşvÍ[šnc"šËűł/xHŢć !+ m˘ZbGĘ~ż×°îĐlKŽÇ‚ë^AßÖ]äž[&œ˙ýţžËŁrŠ_"/ĖÚéQő8ĐŻenŸŘ ăÌŞqśŰ;Ť~]őë ψ5}ŔvűÄIǣي|ż tŮSçŤ˙p5ŸătÇ%!0nâXŮFyłĺšvœeëĘÖžQ‚Š!Âôř&ľeő D ‹ć­Â\ˆC¸ąó Jp$ł9Ýť#44¤Zó0-ŚňßHŸŘ.X™°YŢgć•_=Ž[ćž$Ě3ƒ{Ž˝T>ÇƍÇB‹°(ŮކZB`ľ9ĂěfŒ?ůĹE¸÷×7‘žŸĄí{ă>ŃpîlźŞÇœő ńöŠď‘]˜.1m‘YƒćĄţג?œ•*oĎţč^D†8Ó+Róœ^k†&ĺ¤IE ąF÷˜~ĎdRc5…ˇA•ţž>XŸƒ.†ŇsăäœőC(Ž0=čpb"vĺ%cGI2ö™2‘”/&[ZéXíŽ[í~Mˇíai' ízűüF÷+ ӊ.şhŞ,ĘJa…ÂÓż˙ŽÂ÷ßĎĹSOÍDuÂUu~ůež,hűČ#Ę4#FÝ{ď˛^ …ŻŻžúGŽÁœďzëdźđÂ˸á†ëdQZŽH”““ƒłÎ:C>ߏY$ňňňe:뿜{îŮň<?ü˜\ŇiI|OŠ:ăǏ“Ży˙ýŮňď~ýő×Čďqęԋ… ňĄZΚâ­_÷´ýŕŕ`œvâDńčOźś2ťUęšđ –fÜ:ž#Ž?îčó`öë­UżŽĄúőú‰/ĹHX?nbwĢ˜ĹřśŰ&d„˘.ˆ) ĂšűŕŒÇJ_ťv_ˇUíו­+[WT%¨TŘ3GMGôüaúók ň¤ iŽ4{?T 1ř‡UtÖb&nŁ2˜„bťč\9Á¨NXé)˜g ľ7Ć÷.Eo)>5)ŚeëĘÖ•C *ř ć~â™aGßŘ,&JĚĎ7" bš¨qn>đę˕1FˆIâëŘĘĐ,(ö˛Ő;B„őŃ᪯žŔôyˆ#:ô•…›Řř1‡‘ ń‡âKPŐ’Ě˜ůÇl\űÍSČ/)”ďĹęă„çżç¸Ëđć?ßâŸý›đ× oâůÓfŕľe_ăĂŐ?ă¸#Dg1;’÷Ë㇋׎îÔˇýô*>œ…ÓúÇĎ[—⬏îÁş[?Á'="•űëž}F6ęĂ:ôĆ#'\-_ŰŤu'ź%eVżŕł1ĄŰPLsf­řÎëľ3TP-ˇVóx (úýFË z -Ú>OŃOĘÚľk‹śmă䒺crr¤ŔÂÚ+‡““°ł ťŹiŘcĘDzPĄ+ŃGŸĆăžîăLňLůńLęhmŘVą~`ľ!´(ő‰Šˆ*ŒD7ö(´}eĎĽëńU‚ GŠĚőë5­śk„u Áénj–Ń`@íx°UżŽúő†Œ/ű'žmž}ű˘K—.˝K*ۡáŸf{ą!&ŠÍňQ´,Ăđ”ö—Ó CťôCŻa=e$Śv}Fˇž÷WeëĘÖÇŔ~Ďą=7łîVۂJ7KéF‰ŽŇ`‹ââ’ZŤŕŁ5˜,(ȁoë _nM+ŢGОPěątXąŐŠ9~ĂÜÍKäšö¤oëŽ8{ŕąrÉ´ŕR%š)ŇL5Ć…n´IÂ˙(úĄ¸¸XŠA„}1m6,,TN(Ů×]KEîűÚW([ŻĘÖJPń‚gƒëšŻĄ)ž2ŘŞŽĎÂJ×íBŁ‘aÍGžľŠň0߲ep„ ŹGxNźăyœŃëý ,ފŰZ­V™r””,ˇ˝YGœŤŮÓqȜ‡ł -Ą‡¸|đ‰hٲĽĎɖBĄ0Oœ&žB Sé¸"ms\ÂěÚˇës°Vř˝v#Sˆ+vWŐč ŕ`_ŕ@ŒŮŠžáV 6ahűćčŐ˝›qź )žî=ŽTżîŐŻ×*2Ć÷eG|žB‰‘Xâí}}íŤÍ1ş?”­űGŮşBC *>đÖŕ_BJ}­ĄČsŐÝPłą‰ n†ć–pŃ ˘Đn…ŐakŇa„üNŘQą¸j„ë7ˆ+žŽó&ź‰)žÇqC$ăââäFčcô WJIMEąÝ†čˆHá)ë)—oö'˘(qEĄ(ĂČSm$Şý}NžąBa娴4š’ץ#‰HČ,Ŕî H*B†XňA(r˜`í>—°ő$Tˆ'ÍL6ÄŮbGg1ë„.1ÍĐĄ];aďm¤8j]—bІę×ËŁúő†GEĆřö݁žŻż}őĽWś^eë #˝ RŐĆǨÁŐökxkë#•Yކ†¨p8Eđ÷űŹiťó•čq•‰^Ń%ˇnÝşĘÇĚ1g:B “,…˘!P›śn$ސ@Â˙)x´nÝZn@^^˛˛˛‘-ĹĎüü|””Xe¤™˝tRž&88DlńÂT€ččh4oĺVLZ-Ţ÷ľŻ&Pýş˘ŞÔ—~˝"ÎÓęŠL݈íÖu_Žl]QšÂX´ID¨đďXY%Ůůză×óy#j;ZĽşÔr…˘žŕ´ÝŔŽ­Ş­W_˘j Ç˝âůĎóZ,–rűŒî=V(ęueë• ˙7zoŠ#Ü:thŞ\‹ˇÇő)@Ą¨ ő­_TXŃďÓăoŹ_YáHŮł˘!S;oč4jAĽ,üÝ,<šv1ůBUđ'ŹřzM}D5Ԋ† źŃ†‰żAGuŮzEЈâí¸@ç4Ú§l]ѨK[÷&Şu|Mö*ăˆńgżjňĽhčÔ×~ݟ°˘QŐČô@ŽWöŹhčb獅&‘ňĂ[VŢśX+Č95ęK˝”@Q ´˘ĄQTTl¸r'5a땥&–ĘźŻBѐ¨k[ŻlřUě¸"âˆR…úŢŻűs V$JĽ"öŠlYјÔ΍VP)SśKćää "˘úcŐř)5 mW_'졜Śm˝*T&=Čßąž^čs E}˘žŘz ÂŠ~Ÿ~UӋŤş_Ą¨ď4”~ݟ°btlUŢGĄhLřłóƄţá¸qĽ Ťľ%%%P( Ú,m—6ŹŮł ÉÖľkőőyźëmóőZ…˘!PmÝß5MŤ˛ňúçІHCě×+Ňo×ĹůŠúF vŢXhô‚ŠjÄŞúééP( Ú,mWoËF4d[ŻîA• )"őŐÖ.ŤjwJ$U4Cż^âŠBŃ ÔÎ NPŃţ`ú†ËšLa°\ş0;; …˘ţC[ĽÍŇvľĆX?á>Ҙl˝˛/5PS4dŠ­bc51ÁRś­h,4Ĺ~]ĄhjřłóĆ؟5‰˘´ĚßbţcXX˜ř#gËJáP(ő“üü|iŤáááŇ~ő9˜ŢhŹśŽ&RŠĆLC´uýőŐDazeóŠĆˆę׊ĆOeěź1Đ(ţáô•÷5…ŰbąČ™aHVŤ ͛GAĄPÔ/¨lł1Ś­Ňf}ŠŰĘÖІKc°uفbED%ž(šŞ_W(?ąóĆFŁP!Z!ŃTläŁeË„„CĄPÔ-ĹĹ%ČČH—a‚ZcŹŠŰzö…˛u…˘ţÓŘm]‰$ …ŐŻ+Ÿę°ó†NŁ^6YS¸yŤ˙ƒjj7+'''#8؂¨¨(„††6™ő˛Šş†viˇŰQTT$—V+)qć[†‡G¸b}cěMÝŽŒ­‡„„Šs+[W(jeë EÓ@ŮşBŃřŠ.;oL4ęŁY_äJ !´ŮlBYËŻŕÄ!Ő6R9Ň ESCß –Ů!÷™JâpˇFŘhízoą˛u…˘ţ l]Ąh([W(?5i獅&Q”VŸ‹I´?¸öG§ĘĆ„žńĺ>Ő+Տ6ň̏ÖoúF[˙:çUśŽPÔ”­+Meë Eă§Śěź1Đ$j¨hHĎ"WÚÁłńŐk¨FYĄ¨:úŐ¨Aöl„+Łj+[W(ęeë EÓ@ŮşBŃřŠ ;oč4 AEĂHéöüŁëdŐ+ՏQŁë™mtż˘ďĄl]Ą¨[”­+Meë Eă§6쟥Ҥb¤t{ź˘˛ÝÔ~ EmăYůťşbeë Eý@ŮşBŃ4PśŽP4~jÚÎ"MNPŃДn힆gĂŹP(jنˇşceë EÝŁl]Ąh([W(?ľaç ‰&+¨ĎAý>…BQťÔ¤í)[W(ęĘÖŠŚ˛u…˘ńŁěމ *ú‚ž•BĄ¨Yjۓ¤l]Ą¨”­+Meë EăGE‚šŁ”WˇU!+…˘ćń´ľÚP¸•­+ľ˛u…˘i l]Ąhüԅ×wš´ ˘˙1h÷ŐRk EÍâšüšśĎ(şşPśŽPÔ>ĘÖŠŚ˛u…˘ńSvŢPh˛‚Š~i5ŤŐ ›Í&7>Ön=U(•Çł xPPë–›Ĺb1\ąŞ([W(jeë EÓ@ŮşBŃřŠ+;oH49AĹł...–*[XX¨řA‹ű&ş¤PÔ´AťvX‚ÂÂ"i‹!!!˛aÖ¨Š-*[W(ęĘÖŠŚ˛u…˘ńSÓvŢ1°ß¤{ŹÝ7ënľ-¨tł”n!b [‹â⒕¨h 1Ő뢢"ůǎŒŒpű(ŠşƒŁźź|i§ĄĄĄRő&•i”•­+őeë EÓ@ŮşBŃřŠN;Ż BB‚Lj›Lą•ˆ­XlÖŇÍVşŮu›CwŤ…ˇéďĂ㞤I”čĺXۜô<~šˆŽnŽb…˘ž@[¤MŇ6iŁ´U˝í‚˛u…˘ţŁl]Ąh([W(?Őaç Fßé UqËĎĎGłf‘ ƒBĄ¨DDDČŢÜÜ<×}nţr3•­+ eë EÓ@ŮşBŃřŠŹ7u„ŠgC\PP€đđpŐ+őÚ(m•6ŤŮ/ńŚt+[W(&ĘÖŠŚ˛u…˘ńSQ;o,4ZAEßó~II‰|Ě|K…BQ˙Ńl•śë,€eÜ(+[W(6ĘÖŠŚ˛u…˘ń¨7&šD ­€UóćQP( Ú,m—6ĘÖІ‰˛u…˘iĐm]_/ÂhS(šľó†NŁT<•mÇaWpp0 EÁ6KŰŐ \yŞÜ ÍÖý şÔŕKŃTilśŽP(ŒiČś^Ů>[őőŠŚ†?;ol4úţůnjŒŒ„BĄhxĐviĂZcěúlë<ŠÁ–˘)ŇĐm=PÁTMŽM†dë5iŁĘţ™@íź1Đč˝Â­_fK9ŐgÔ@KĄ0†śk´›^펯ś^UűUöŻhJ4D[ŻÎ~ZőůŠŚBC°ő@lą:ESeűŠĆ†7;oŒżóFťl˛ö‡Ó* 3ě¨>QŃ“çń}ů)…BƒśŤˇcڂţ÷__mݛű˛}ovíů™ŠĆHCąőÚčżőŻQśŻhlÔg[÷eßUŇhÇ(ťW4tüŮyc˘Ń *ÎFŮ^/ţ€ŐŠČŠÁ–˘ŠŔß7m80ďNýľő@ěߗ]+QEŃŘŠĎś^Qű­ĚqžUÇ( ‰úhëu‚TvLď)í×?§l^ŃP Ô΍ZP) -BH‡ţ[ŞŃU4V4ń7°ŠŻmśţşŠÔ¸ îivkąXćzŹES¤>Úze'Tţž÷6ňöźvŒjúdë:A*Ű"˘xË+›W4düŮycĄŃG¨Ô%Ő6čĎKĽ„…˘îń´mý㒒$l^‰âšw‘şöâB,–Ř[EĚĽŻŁ}÷ž r˝ÖsŔĽě[Ą¨*2yŞjŸŽčËhżBĄ¨Ř˛ˇÇtŠpIXnšƒÄłř&Óh§źeżÎMK_rzďˏëě[ŮźBQżi)?őĺýŞ6XŃ0AŁçІJuEzŐ$žbźŸ••…Ä/Bˇ‚ľhÇAb`”…佋ą˙Űç5ýDGGŤHE“ĽŽm=ĐžÚ×dL›\yăŁ-k›6ŮŇö{žÓ×Ë×~…˘ĄP—śîOL1˛wŠ'tŒäç磸¸X݉¤Ú} *łS,áąÜĽígM‰lá\ą‹só9ö÷źŐ^ëŮߗłěÚjŇŢ9ŃújOŘ>­ZľĎ=÷"žţú[\tѸóÎŰPߊĚőîH,Á/›ňq(ĂŠŹ‚˛ČŁ?ś`u|:´´ŕôÁčWżW‘UÔJPŠ*ëÍŇsVXXˆmۡcö‡aŢËdcyęäŁqՕW oŸ>˛ś‚6YŠč`K{N ¸ŠÚGłKN˛˙ů 1Íěrp›—šňK9.kfĎFʖhÓŽŁ´ůúnˇ'ž8Y *>ÖŽ]‡ŃŁGšž[łf­SxýÇ?1 ómÝş 7Ýt‹¸ćĘÇüöîÝ'ˇĹ‹—âĂߓž=…˘&¨ˆÇZ‹:áD+//›ö$`uNś˜`F^HG˜‚ĹäČ.ŽłęNȉ•čĘMbŸ#ˆÜ•…ÎAÉáŔ¨¨b ęŃ‘‘‘Ľ“0“[Z€ň\+UÇ_$Šţ>ĹF–äçIÁ34„ăp‹›­ÝwޔżOĽŇŹY„ÜG655Uœ;H8&ZH'j 6_[öŢťw/yMz§Ie9rŹźýá‡oĐŠSGÔW(Ś<ż0Ţ|ĺX˛ ŠąíH1n™ÁC hÚ(AĽ TFHŃßgCJĹ{é˛eRHYGĹsě rËëňůľ[~ĆĎ×>‚áÝÂqÍŐWbÂřńŇCËF]Ă[ĂŤěůŢMiĐľyó9I;ëŹ3Ü:…Ş˘BžŮšţ–‚Jö Ń.œ*HAEţZÎÍ"œáaŔĄEá„ÓęuU_&O;wBŸ>˝ącÇNüő×b7A…4h âââäŔÔôđ?ôĐŁRL1b8ţ÷żGĐśmvíڍťîş{öěĹoź…{îš EuS‘I7:Aö8„y‡ŹX–¤Đް•ˆ­Ŕy`I! fl*i‰-Žp|k FÜňŒHŠ-čÖŠƒŤPľg__žkEĹQc…úE vŽEœedd 77!Á,ĎńŁ3ÂD31o˘Š‘˘Ý/;ĚyŸÂiË!Ňąš––*ĆŠĄhٲĽ+RÍWż_öţÔS{&mĚ02Ĺ@– ů}[TJPŠ, Ö7ԜX°Ąţaî\|ňů—Hę…ÎÁ°‡;.mŰ : mŸ…Ěkqëso"Îńޏô"œ}ÖY˛Ć‚^ ¨¨°R[႞Ąý7.żüjy͚¨iîż˙!9’(…¨SN9 UE…**gŮiÉIހÎÁ•ŒN1;;d“ŘĚâ'Ă1[ÉŽe(â mœÔ˙(•¤ ň÷ߋĽŘĄ]ë’%NAĺ„&tžŐŤ× !ဒž~úqÄÄÄČý˝ző‚Ęíx÷Ý„-BQÝÚwkÂčŽ} řňˆ ˙XŰĘI˛]ěCaŞ‚­0_lŔAG0žA[ü´×Œq ¸ }ťu–iAzaĽś'Y}ô‰4}ńÎ;oJ1Ô -U ˛¨ąBý#P;§Xšœœ ł0ٰPţ}܅˘ŠŻčo祣4F)EEE˘Ÿ;ŒV­b]bj]‹*ÂďmöěđË/󐙙%"§žz2Žşę …sĘ)gşŽ=űěóqňÉSđřăÉyÁŹYocăĆÍŇŃÜŁGw\}ő˜8ń8×ńżýö;>ţřSěߟ€ŘŘV8öŘcpýő׸Ҁ“’’đúëłđĎ?+Ĥݝw“iŽ?ôP=˜aőú<DŮöË×(‘´iŁ•JPѰ` ›ƒâ“Ď>Ă7?ţK÷SŃáŒ/Ń:şDis^vŇ҆8Şóp ¸ä1^;„W罋—g‰ŠgMÁĺ—^Š:Č ˆQŐp LŸ> 6ü‡ńăÇ˘Ş¨@…7üE§PdLŰ´Qa%`ÄŹÉěQô˜Ĺ~j¤ů‰HÝł 1­ZšÂţë3“'Ÿ 2))ŠŘ´i3$HÉÉ)J÷ٲeŤźeD‹&Śh}ôš)ŐM “,ôÄg{ň°ĐÚE%°[óő/Dua Ďü§Ľ–[ƒqâ‘}¸´G$:wę('^u1ÉjÓŚ  ďSTbÄŃöŚ*)ÔXĄ>âŻFŠv?33™Âáb}5ÇŐĆˆ^$ŠltŠŃy(˘ĐYš‘žđˆp´hŃÂ0:­>Š*÷Ţű–/_!‘qăĆbٲĺxë­wĽHtéĽă´ÓN‘b 2d0† ŠÜÜ\ÜxăÍâ6OôńăetÎ…çĚBœyWŽ~řáG<ůä3˘}‰Ŕ„ 㤨2gΗؽ{7Ţ|ó5Y׆ŽÚ´´tŒ=­[ˇ–ç C52ň%Œ;Ś"ߏÍCvÝëó—ŐLÎÔ>[éLMćąß­ËÅŁTˇŚŒT*HE‚ Ăř˜_˝yóf|0űCüţďĎş=Ś-FPH„ÔO¤”b*mů"ţç:UŮ9C[t@S˙[É˝řeő||ö՘<Ś/Žšú*1¨(k čëŹ4ćđŕ@ŻQ)Ő™BT ˘˛p’şz:‹ţV:1bsÖRĐ Č"œa‘aŔῢóŕ1ŽBuÚď˝>Śý´oßNNޘ^Ç4 *K—.“Ďq?Ó}uXH˖- PԁN˛8č˙kË>ĚJoÔ’(Ř óÜ|Î<ş&ŰKŠQ śŸCŰbĹöܘź t“^ŮڞdéűR}¤éG˝úJ]ľ‘jŹPżÔΕRP/œ”ÁĺD’šŒNń<Çń­ZľDvvŽź&Š™žý~m‰*<ň?)ňh0âäĚ3O7<öškŽ”I˜2e˛tôţôÓ/˜9óI1X.D“đŘcťŢg •;wI1…ŸůᇐΔłĎ>SÖŚ˘0Cgô›o:#ăfÎ|Ç“âöĹ_ŽUŤÖČZm]éÂ1ÄäÉÇťŽç×_çK§˘‚ĘŠ=…^ŸÖ)#ş„âџ2Üö݉/R‚JG * "b ÂţX´HÖGٜŒŽÇ܈AˇNžY+›ŕŮÖĘ}Ĺ9ɰDĆŔl6ţó˜C#Đ~Âľh7ţjlŮśÜúśąÉ:+“&N”ƒ-˝gťž‡ ˛qÔŠ0wěŘAŽrîšgËțE‹ţ’Ę7RNĐ.÷ Ďŕ¸ăŽ•űřšO>ů űöĹËŐI&L/űiŽ×ĄB•Ak(Şć"4<łÍYC…?§ŕŇH!°pë݅…†ŕ@Nśa˘˘˘„đÉ´ * ˇĽý­XńŻÜ_‘p[Ú"a@…˘Śń7ÉŇnSRRđÎşĂřÉŃ Öl1ˆ6ŃsI7ˆćů0Őřc[Q!’Ä˙qSüˇ|Ś o/˝°D?šŞý{zz:^{íM1‘ůGFćőîÝ×^{Ž:j´××P á¤iÓŚ-ĂĐĄCpÓMÓe&ÂIջマ￟+?ÓÉ'Ÿ$&l!řđĂOääŽ1oăzĆ9ąbşŔÁƒ‡\}ţM7Ý ˝áŒH8ᄓѼy^~ů<óĚórĽ1zÓg̘ŽW^yţů—‹đ\L#đ…+ÔoźŮ}bb˘ˇÉz)4™ŠD•xŢŻltŠç5EE5“c^[Űśm ŤiűŚmę:t°×c{öě!F“0Ő~űörżŻúiÝşu•ŻŰ˝{°šłeŠď€ýĽ(C'qbb’L"wŢyoš×ÇÇďǨQ#…8Ó 7ÎĂ=÷Ü/ߛiČţŢŰĄň‹Ë~'SGFĘďůˇ-ů¸b\>ú'Ç-höŹhş(AĽ’xKëĄńr@ńŐ×ßŕł/żAfÔPt8öy j×ß9<ŇE˘ĐݚÂŇńÓîďCóŽŁŃáčinűË! ű‚œX]{íŐŽăvíÚ%S ŘŕňłqpőÔSĎJe{äČá8pŕ ~üńg™âóŮgɜsO´×đ;5j„`q;O>™íJňD…*źá+݇0Ü51)9ăoBZçG`+ُA™(ż×č(3ň …GŹE,2‹CÔ‡m­q0!é™ÂKŐĘućmŇT pňň˯ɲ0ľA˝UŇˇoyË<ęěěl×Ňф/ŹĄÂč•×^{ EUTL9pŕ^ÚVˆĽ%`ËM/-~¤˝śśoĹd=3s›uBÚú4ÜŃŻPN"<ۅşU(_{í ˛Rż~}eŸţĎ?+…Čz;Ţ~ű )vx‰_CÇʘ1ŁeT/ĹŽžţzŽttźóÎ{řŕƒäç`ŞŔ,*÷7Ôđ'ĐáB'&ŚĽŹŮŔIŢÜš?ÉvŠ)Œřß˙žNŇ(Čđř>;v”‚1ĎCą‡QxŢPc…ú…ż(rÂúEB´ ŞtT‰ţx瞪Gť>Š Žü|yZ´§ˇń|MŘşgDoЉ|ĺ•×JťbÄmÂČgŸÍńů::ĺ6oŢmB;ŁíqcÔ íMcÖŹ×Ę­2Ä(ÚëW\-ڟBsĚ™:ÔŚMkWaüŠÂˆąĹ;ˢTn-Ŕ=SZ`LˇPY\zÁň" ‹M+š6JP o7÷SHá@bB‚đ˜|„ďüĐ~gŁÝ%? M3§I‹HŃDmŸ'YűV"yݡHßž­GžŕHg-žĆk3)NŃaz_ň&Jr’ńî˛đĆçŕœ“ ÜčŇŮYĐNŤnôjjŔuŢyú|žQ"SxmożýŚôąöÂ\";K—`ýüóĺ@‰ßůÉ';ĂYŘnęÔó¤’ĎˆćW˛qf„‹ž†3rűíˇČ˘xŔ8˜Ó”pŚ/ĄBEk3(¨ěƒŒfÂój m˘čśČ EIk;Š˜Ň#ËśŰd!ZŤÍ{r˘›E"^üŽY3Á×2ÁőE\aH2>œ€ź÷ŢŇÖč%fQş@Ą›öwřđ<đŔĂxôч¤Ţaö˛ô_xáT(U!1…ŰžřxĚÜ„ůѰĺkŁŽąććcqh42śâë>tëÚU #A(ŚP}óÍWĺ{˛§ƒ„ľŢ{Ż|QŰ÷ߟ-űá‹/ž×]çt ĐĂýÇâË/żűŽÁ7ß|'÷ßpĂu2­€‚ë…GŠčÇ „ăz÷yMŒxaűrĆçáv“<Fş°Ž#X)žpLńý÷_Ëş5Lq˘PĚ Ÿ/AEęžĆíÚmZZ ¤˜R•¨’ęŽN)}$˙ăwŽ~ÇkĽ“Ĺ—cĽśÇ@‰ćLaŸ˙á‡Îq6í×íÚ)ŔÚ##ŔčüĺŠB„ý?#ÉńĘH:R2„ƒ‰ďĽ­$Č"ٌ0Łł`-ížéH\Ü}÷}>Ż×Œl†őB4фŃĚ|;žű-'Œâ§'ÍĂÍrĺ.EÓF *•ŔłŘäŞUŤđöťďâď˙ vÜ5čqëL˜,!l:ĺřK )˛}+ ău¸űž\Á˝âŕ=ß;CÚŹůˆŸ˙zž˙BŮűzť WuK,ÍŰ ó)÷Ă~âX¸öĚš`:&í‚i×_'˘ŃnkÜ×FŁËJŰ̼ԐKM ECódsvć™çş˝–ß-[ ŞäÚ )Ixü™D´´Äc!,°bKOAE˙-ϒß#SüĄB•v&매g˘gŻ2ÝĎb ŢX,ÂÓbƒŠ`Y•ŢlAQIĚb˜@%ڤI{Ń"­ę{ÚmŠ‚Ęďż/’}ĽűpŔ¤_ĽŹwď^bß˝b"53f܊•+W Áô ůŮůýÚ>CđŠę›¸’ œ#íĆŚÜ`8JŠPß°á?[¨¸Ć)jŹP?1N)˜egeɚ)$P1¤ś˘Sœ7Îű̈́“…˘Ż™c]_jm 9K,řMާđAÇ(Çُ?ţ”´›ß˙ŁÜëhSŒ&żďžeMŚI“& ńőmi‹˙ţťJF¤1]ĐÉÂsRDĽSĺŢ{”QlÇ˙÷ßFáp‰•ăŒŘŘXyüâĹKđęŤoH;×Ҏ˝]ŻŻÔ˝Đ`:ľ´`KA™­STůbUŽáńmž ‘íű# ë,fä[ˆÉJÜŘK7ćbŹüţĚ;ű|ńůLœxŹŰDF˙k˘A~îš§ámŮdí} ߛ!Áž°áÓm`S¨@…?ŒŇ}č IMË@HXBCÂd{dB‰Ő*~ĎÄŮ\Żác‡C‚ƒ,ĕ$á=ĺDBŤňŻW_…l8čĄ8J|Ľű0ĎZ6Ša¨đgŸ}Œ>řPŽ8€dÔĘI'ˆŤŻžŇ­8žBQQüyŹ CëŸÝZ$#S꣘˘Ák۔*Ž5†§¸_ m‡ö=Ž9Âm˘áŞŻĄőëŹwâ™ÄśOkOĹg ­`ˇˇói<ýôsŇÉÂv„ľSXKK7×jŹP?đ–ŢŁ=fŠ žZ,fC!ĽŒş‰N1Uš7o†ÔÔ4é¤ÔVűŇ_›ă„łÎ:CŚčŹ[ˇţůˇ(žyć ‰Ćˆ:Iî˝÷n<řŕ#nŻ{đÁű¤ý1’mÝşő¸ňĘËeĘkąČ,ÇLœ30buŒ#SYOîóĎżŔ˛e˙ČúIŹŰĆHsŠKPgÜďż˙ăǏç˝LĚ)Ţóy˝ž8mpś)ö”Čoyr˙p(JPŠ úI˝Ç?ýňŠ„Ç˘Ýń7Âa2y”•ƒŤđŹDâđ< [aö˙ô¸ű{ŮmŘűÝýxˏřúJßυ¸Śö'ĚŔáżŢ?˙(ź:Gš ÖևəV7eťuë*sžŠŔ3݇9ŘFuPH\\´j#•j†3ĺ‡K§­XąR>ĎÜM_Ża8!lz›.ťě*W¸!˝YF¨@…ţ&hL÷Iޒfâ÷m .PČô=“8Đű 'ŽŇ‰ƒŹ{d2‹ç‚pđĐ!)*z ľ=x ÚîŞUË˝>ĎĎľfÍ řƒ6ČŠšÄČcÍĽď­Ţ͢.ei>ő›h_VňkޏcCݖX­‹>žýůĎ?˙*MLaűĆhÖ@báHˇk/ ˝ďßżŸLˇe[9bÄpšýsjjŞ@č…fűÇńW á ěˇWŻ^Đ51ĺˆ0Ľ˜˘ Sj5V¨żčűkţžĚb`äœŐDtJeÎc”ňى*DF„Ékע¨jÂĆéŤ%ćYόŃ&Üô0rEĹVÖFŇÓ§Oo!Äź_0‡›üüÓŚ]'7=úŒF×ë‹ŢqÁrIsŽÂu(ĂZ.Ş,ZŘm‡–œ(ĔAÔ*] %¨T BCœé,%ůiiŐĄź˜RŠV7EŤĄâ.‚›đŰó˛ţ‰'Y;#uă/h5ôTbr;Ť‡:ăĐ)7ş7-ÉwŚšđZ˝]­+b˨Fú\zé•r@Ĺe†˛°”ˇ´~6ž,0űŇKŻbɒĽ˛Ŕ,f]şt6\*Y˙Şá +äkX›âM‡í˝^§ TT-Ý'~˙A´iŰFŠ$NáD Œ‚̰ Á”6iľ–Ŕ"uœ0 Ż“ÝÁ“IŽÖľ/á  'ő9:EĄ¨ďř*­Ľďţ˝5ßŰúŔ–›ęr¸^ÔËÇśÜ\|oéƒ[÷âԑĺŇzkS|儇^d†ăł?粧˖-—őča%ĎĐ{z¨)”|ôѧR|aͨż˙^"a­Ö=Ąw™őžţ%!ÚŽ–uQ(~Bll+9žxňɧэW/1ÖřŰ%d×jŹP÷řłu:ßXł,$ÄRŁŃ)9żčí>ÇYŮ9ň3ĐVęĘ֛Œ6ăĆU¸(†˛ÖÓóQFTŮ­BTŞ#=v.!–ż‘]—ŐGńˆ@Ńpxܒ’Üůómx#á§'3ěTů*‡Żł™<ްôqÎţuňvŔ€uš6ă ÖM`ˆ˙üůżÉú ,@uŐU—Ëbtž8çœłä UüĆÇ(—ÓO?U.Űę-˛E˙šőë˙“K(r—Mö'6Š@…7ŒŇ}x?;;E…r)PSŠ bwŘĽ§‰)ď8¤€âŕ‡†KO-˝fĄaĄČLϐ'zWÔ@IĄ¨śV„vďž}x5ĽĽpl¤@śâGš.źž>.ÉLÁk֖č'>CŸŢ˝ĺ>omDMś?řŕźţú,-Ę"•tTÜyçíŽđ}ŁĐűwߝ%<ÔďČžšB!ĺśŰn–…­É­ˇÎmäźyóe*ŕI'M‘Kő÷Y^|ń9éDá’Ě\NőŽ;nĹŁÎDnnj 5V¨ŸhśÎ•8hŐUR’›‰źÔeĽ $/vŤ3UĐАˆh„ˇŒCł¸Žkăó<ž˘Sô÷ĂĹ؀ŸĄĄÔWkčP8aŃhU8Zá SűMşÇÚ}łîVۂJ7KéĆ(&šś(..Y‰ZBk89aÇĚĐÓ\áÁa!¤ŞžSťŻVŠ?vâD´<ęô¸ňÍrń#ň5çÓďç}k~ÖÜÖŢoŰ CfŽŇ]ź˙ĺ žŰűŮíH]ö ˙ů§ôiÂaďዠ#6,V!€u#‰8X§ˆIQBżxuÚzEđćÓî3:eőÚuŘ]„—•šž,,Ç*8˝IŹ•b“ŠÉĄ"„”ôŒ á=+DvN6:ŒIGCß>˝\ŠzÄŰ­BŃĐŠ [÷çąf´Ăs˙$ŕ—Ü6°Ŕ0´ž?6‡†ă´fɸg\gˇşKFmDCk/Xď‚Ń+ŹË Ő€{řáǤćškŽÄôéÓPßPc˙ԅ­3Ľ<%9Š4:Ĺ9ĽáţžóÖű}yOÜe%#sßF)¤Bx‹8Äöˆ˜vnç1?8o΅-t÷ˇd g WšŃ ÔjçŇßzŢW(ę#;'ľůŰ #nÖČĺĽ>h-ÝlĽ›]ˇ9tˇúȅňЧĄR<˝\ü1´k×Vx`: yßZŘK#B\)?}*^T1G6ƒĄH؋Œ=&ÁŃqâ\×ń>ƒ&ĎäĆŻGŰśídx­çXyť+† T튑&ń ^Z@Î, ˜öĆU~X`‘F>ÇU~dôŠxĚçĺńâ_P;vîF×.dgT—'ŠĆí†6¸}oćś…­0ˇ´ƒőL­˙m…ů˜ÜgˆĎ2jH”lOK›0s擘7o\5iÁ)))XźxЌR9唓QQc…úIVVLr>WąčˇÁľÝ†ô=ë{d*BAfʚ‡čN}×o,‚,e…•NŃc4+—ýŚ ˘P(ę%¨TzKzőęý.‚ľ( AáŃrżŤiÔľÁš˘—ť´CBZśCa˘qą´ŕmáĐeŁ8ô'Ňßş˝ąóÝZˆ‚C[1rÜľBF5˘Bžx ŽôŞ%§ŚĄGn2ŇuQäJ\2˝§X ÔBÄ­C -v1@Ł`’W”/#XěA69cHoRjŠŒ^ĄÂŻD…˘břňXN°>;hBIA‘vG gĂy\’_$?KďŽY˛H´öYz}…űďżG~žE‹ţÄ÷ßϕ"5 ěßpĂő˛fZ}Fęš“ƒÎ‹ŕŠŐNѧüŘ­ĹHŮźĹŮieçśŰ‘“‘‚üětáf˛—ŽŢÇ~?$ÍcŐ2Vöý$ëŔçd Ó¨“`ś„¸]ŁóVţ_î~éQrWş)Ěş‰Ťţ¨ąBQˇ(AĽŠPP4p ţXô‡Œ‰îěp”ęF œĂőŹÖ€3Ž(؟ âŢÖßzŢäÜ ‡­ýúő7\.YĄPTŁIš†)gěߊ ť •V/ Ň:ĘoN1…ťUxŚ˙X,AbĐçQ*a‘(Lُě´D9ĄĐ–­ŤU<ŠĆ‚˛{˙A,-n+&J9îĎ{_ iĘšĹvXEŰnA^ W3É\ę@^ď“˝ĽĹqň3ˆŽn4Q*–YS…›BFâ)둕”"Tˆ¤˘Ń)Ń^¤lbJN™˜’™š„äťĹsVX„˝‹ţŰäNŹĹV!rć#+- ‰ ´éÜ-Z9‹2d&ăŔęč4ú!´č—÷˘ÝçJ üLT´ĎŞĆ EÝ •*BŻňčŇĺs÷­AÔŔcĺ}‡î˙ňÁ#ŽŇԟ2É%¤Ľ÷f,-ŰĽ[â‹ňyÔ0ޗď,H;|Ř0y­ …˘ćĐoŒ(9´d.úmůŃ1WĄ$t"ŐŚ `!šf1đrŚű‰žˆą–ŠU+Aôœ ‘ľaÖ,„ěřaKżÇĄ6‘hך‡ŹęŻŇ~ŠŔđÂz ?°Á*P_…kka˛V›CŠ'=[„âÖṘŇ5 =Z„ ˝Đ†É_ďAvqŕ+Ňđłđ3őí‘'‹Y“ĆĽ˘PřÛ ëűĺP—cąâŃ)é{ֺĞóŔžíHO:$DłS|QR\„ří›—ŽN=úĘóQTIŢśqĆW(:EťĎH-~&ízÔ¸@Ą¨;” REčE撻œčäí]çIRŠ‘ţĄíӆIÁ1íźżGK?*0xŽ”źř ˘ąˇ`čÁJPQ(j`8ČÉÚźŠhžüyDţ÷2Ě­:#´ĂäZZ"ŹŐd›Đ˛M[ddf uËH¤܁žÁ™ČŮżÝ2Äm2˛HÎŽ¤çŁđ”K¤§V ŽŠŞĄM^XƒŕĎŹ0!n棜ĄgŮlĆ9˝˘qů€–ŇĆ}ŗ˜° Œn…ń9ÔěYKĺOkŚ‹ĎFAEM¨ ČeŃ9ĘBđ¤˘Ń)EBüČKÜë:ßţ][‘šxĐŻâIňá‰Ú­ˇsŤĚŰŐŽ;Â9ÎwB8˙(,*,ý\j|ŻPÔ%JPŠújÜzXQż[׎Ř!ÔkˇHçŤJ…Ď4 ý’Œ&X|*Á-ă`7;JĎäz9ŕ‘I]ţ‚…×kßz´oß­ZĹ@ĄPT/F^oFžd&@PĘ.„ś‡,€g˛[š˝Ą%{&JŚ<ŃnˆńIŒĹZŇa&Zâćâą]nƒˇ<–É„ˆŰ˙"/'Űmő5QR(*kŹÝ•€ěˆžBŮH…{_꨹ÇLçÉ-śĄ_Ť0Ě‹Ó{DŁYˆŢČÇJ[ŻŔűeGĉ϶­[ˇvĽ(M }żLAĽXŘ|°…ľËG§ř[.93~Łë\ŠI‡‘xh…ō$ńÚ¨čÄĆ9Çý)ťÖ˘óčSľŤ.˝ö˛űÚ~#QĽ¤¤Hśeš ˘Ć EÝ`†˘Ę°!ëۡ/ŹŮ)(JMŃ$2˘DŢ:äę?Ú>ťÇcGé1Á­|E¨ÄšÎĺÚĚY¨ÖykźY‹rQxxzöěéuPĽ^…˘bř +ćŕćđęßfąÎ0ÖĄ+]‘ŽĹ؂œâ‰Ă‚R;.‹Văqař:‹Ř„[1ŮHÚśFz˘|]OĽ-(ő#á“vş$Í[AŽkiҲ­úç—ؐ[dŊݢđűԞXzq/\ÔŻĽO1…Î*v6x?~ŚĽéů}} EcÄč7ÎĽˇ­VöŸŚ ¤%%š™(–˘+ärÎ{wnAUá9x.R˜‘„˘l-•HţďvßHHюąŮěňły˘ě\Ą¨]” R ç0šOˇxŽ”ÄĂŽÇ9IűQŃč~6FÉh‚Šżď "°żf_÷Ýw?>żgĎ^ůü¸qǢ1 }^Ďíúëo”Ď>|D>ćçŽk{ěqÜsĎýPÔ/TĘOacë,L;BŢĎŰłŃăÎr?(-BëŽC÷źˇsh$ĚQŽ!×k|­ôS Ó} ŇŞ~ŠęĹČăËűš™(ŢłĄ­„Rm"T´†ŔŚ;‰]S‹PqEЈq —j¤XĂşő%ígʔÉxíľ7ąlŮ?8ţř‰nĎmÝşMBN:éĀÎEoÝ-ˇÜŽ;vâŇK/FŸ>˝‘˜˜„Ď?˙+VŹBË{Ž"›ő…ŃŁGÉU MtČÍÍĂADnéˇĺëUćąU8žóŠŹÜ&ˇM쀓şG#4¨âvšSlCfa‰x­šÂ×sĐ%?cllŹsżr˘(š0Î"đŃÄAÚâě×)‰GÜÎëˆîs—Qčާ?Úˇočč授p šYYŮ8räölŰ G }żëľŠÉG×žŁź_™Xáčb‘Ÿ­&0‹ČO?ý‚sĎ=ťÜs?˙üŤN jp)ö›ožÉmëÖU:\ř=ţřcP4~” R °ŃéŇĽ3b[ľBŢng„І§˜b4řą‹A-Z‹˙ğĂćşÇtGiАlŰ==ÚÚ =O,Čßť^6ě(íHԀJĄ¨ ţ<=ĚÓNŮö/Bíů`J3MNF¨@ˇÚ—Ý)˜¸îëˆR[ÖĄR*¨˜S–° ­D;ăY€ŽŽ„Öh9r8~űma9Aĺ÷ߥC‡ö4h`@çúňËŻąiÓ|öŮG˛=՘<ůx\rɘ=űăzˇlęYgEÃÝ=QÖŽźLˇçź9>ü?6É´rVĎ˜>ź5†ĆEŔżîÉÂÎĂy¸ýhăUţd—  ŘŽĐ0Sďďţ¸$,Z|ĆýčŘąƒ*XŠhŇȨ-!Ř[,ÎŢŘHTńUś$?ŰuޜěL×sćĂŃ}ôd 6ÔpâÍĹ*¸ľk×V.^ąn]ě]˝HX-ŸĎÎ*k{Jň˛KŻUţďvß[t 2šDâęŒ?K—.ÇŢ˝űĐ˝{7×~~—óç/Ŕ¸qcđᅪŃXˆŠŠBďŢ˝ PT•ňŢ)ýţČČHôčŃńĹ$ŠDWCř~ăđ¸}Š يYSp‹¸rďa‘iuÇë҆´TŹ-—$ś‚=ĐŠc'´l٢BŸĽ:đ Ÿ;î¸pë­w`ßžx×1ľśvôѓ Ăř^yĺő€ĎÁpűÓN; ééé¨NRRRđÔSĎâ”Sΐa“^x)ćÍ[`8iç{?÷܋ňXŚBLząLˇĐrpő°ÎĆěŮáœsŚĘóňÚßyç=WşHm3gΗ2uŁ1Ł_–ńȊůsF–hé>e˘œx"mîűĽcvŠ)AĽQ*aÁ\ń›+Œż:Ă{ŤÂI'M‘*ž‘‹ý)#XeîܟÄoö,71…ps˙ý÷HqĆ-wńâ%¸ęŞë¤ÍÓ3”››‹gžy^2'ă„NÂG}âö:.™űä“ĎČç&M:wŢy[űDčÓěhÚ´›¤ÍęńlĂ֯߀n˜!Ó Ž?~ fÎ|R^‡7řzn´W^_wď˝řlkĽ4kÖŰ2ˆ×EąéďżËç8đĺwąqă&ˇ×đü'tšŤ˝X˛dŠ|Ű~>Ú¨öœö}ţúë|ᙼ@^Wc@oTâ3ňeŐggý‘ŞmYV„ ›˝{t[lšvŢ9š‹O1ĺpn Śţ°g}š=ŰEz=.>ŤHz\*sMülüŒúú UmŘŻ=^Ÿ›Ë=ÇžěškŚĄŠB1ý‰'žĆĉ“]iŠúúĺS~œ÷öéS~ěÖb×yŠŠœă(K§‘qâů;vŒ›˜Âăő›7NŒ?§œ/^;Bî+.*“ŮJŘŻť )şŤ7ŒNĄ=‰‚Ý^3}>#nzőę)űA=˙üł99šňłëńŐ7Fľđš?˙ügŸ}ž<†śÂ>'ĐsíŰwŕÚkoĎŸyćšXłf­süŹÁžüć›o“}*Ÿăř™ŤşU'žú{Žy.üCOżÉţ”ߙ֡ţűď*\}őőâű;Föżěkőđ¸‡~LŽ]&L˜(?űvoŹ^˝FçyEí˘• âMx h@˙~p˘ a‹I쥛L|•‰pSŐQ މsžÖä(_”śôž{ń[çmInŠ“÷‹Ć°—×tŸšöh3|nΜOäöěłOɰÄ믟ŽĚĚLÔ&W_}…ë:´í’K. řőTŹ;îX4kÖ Őő#‰¸âŠk°aĂâ;šV4öOÉÎöńǟÂK/˝ęv,ë5\~ůŐ˛Ó¸îşkđüóOăÄOŔ|ˆ;î¸ŰMTáwű‚×÷?pŕ ŚOżYë݅mž#lďá‘\/S˘|A!ˆß՗_~†?ţ@†ˆßz띆b)aMďžűůYéEźďž‡dz˝ˆýE?¤X>>őÔSd4%swÝuŸdž$_óÍ7ŠĎ˙>Ţ~ű]ˇ×|úéçBdşM\Ól46řÝ&9'J•­bçČ*(Aˇ¨`|tZ7lşnî:*ąáž?ܘŠŃłˇŕçݙř꼞8˝g´×c÷f ŻşŠR×čŸM~F/żŁŞ|w짌 d7e(sőä“3ńĐCŞžA}Äá€WŃÄsŸ×|\APL ;ţlu˘˝ÖS@qEˇŸˇ}űöŻ=qŁëŤHt Š)1…p<ɔÝyó杼ąŻ0a\š¨_}“Fjjš°“ß…SóEJâÉ'ŸřtjÜpĂM2ęgöěwĽłĺő×g ą$Çuöá×]wbbbä1O?ý„ěűŮçWţúű>zÇôHüöŰ/5j¤ëľGÜpĂuâsţ(œ@WČö”ăí;Ÿ1ăV1îO‘c^?3 îžű>Ăë óäÎ;ďs[E2u‡JůŠ$žK(3ľfĈ‘řŕĂ‘ż{B{)÷ýdIĂî:ŸłŽJÇkd„ŠÉĂËíşž)ŘťAŢ8 \¸omĽx†Ď 2XLžN’ƒŽŠSk/b!..ŽJa|C‡‘[uňĚ3ĎÉ%pŮkŇ„ ăe݈|DxšŽ•ąóŘçeíýą_(ňpŇřĂ?şr\)¤°v…>mbüřqňܗ^zĽ˜}*EEĹń Fęž-ĘIDhťŇú)ЙŠĂ™âSz×Ý|5aĽô-LZÚOiqZŢ2í§8~=˛ÓRdڏ§ëC~k3ˆŃyÇ3A’8I'#hsú0a_deeÉŰččhTڀĹÂȘ￟+„Ó‹äăN˜„ˇŢzGÚm™Š>żüňZśl)™9óQœ|ňéX°`Ą!iKü<—_~Š|žgĎr0÷Ćož?śŸ~úmÚ´qíăuüő×bŸ×Íö™ƒBÍ{úż˙=,FgaíÚunƒ0¸Wxs\×}íľW‹Áۧňó´m'’ŸOűnşví">WŞTn¸áz×űÜtÓ ˛ičŮ-Eôч—P`ŽŘ„¤ Ä._rVݏqdœß´ŮŸ~Ţ>Ź>’›˜}svœÖł…Ď׏KĚCXç¨!0ěâłqÝ#AĽ*í;ţŚX<šÎ…:>ŘF4›i Ů˝Íf-WGĹuĎ@TŃö™-Ą°;GçĄač0üDizĄ¤üyÜŻC›3đ–Ż=?‡—ÍqLǧĂotЧ¨Â•‹LćšIfŰÁ>đÍ7ßƲeËqěąÇČ(ŚŃ ˜‘áîő×7 <ň L…"Ą]łżspźËńđ˙ţ÷ˆt:;Żź˛Ź-úöŰďĹX }ô!×1ŹcrÁ—H' ÇŮFpnÂMĎ;ďź)ćvĺ=ţú{Žďcc[É~ă5=\pžŹżFN?ýTéňŮg_Čď—ÇÓąÂߊ6Ţżč˘ p㍷Hg4ĎŤąmŰvYwnúôëetŻ˘nQ‚J5ŔF€?ţĄB0ˇTZ˜ŻÔá,{ç09#J<ö›ä~ă•~‚JWř!ŽŇW*)nc.ň÷8•áĂGx]2šśĄ˜“üC‡{=†Ą… ?OH8 #z‡ŻžúJŮ3lď §ĘXăż˙6Ę0㯿žđäM•vzgďťďnŠS=§žŮúťŽyĺ•×°hŃoŽ×1dţwޗa…­[ÇĘëźâŠË\ˇ/RSSąbĹżxá…gĘ)ül™*ÁF *TڙNat,oôšÓ3Ś *źVŁ´‰Î;‰ç29ąň˝äœtŽ\ů/ 1lŘĄčßęú^™š@Úˇo‡ožůEEĹ2:“A- ŠáĺŒřĺ—_‘Ÿ_ ;cćđ7tŒgžQ"LĹ9´ę7š"OPéRÉf×ŔŹô8:yŒŠxFДЍć Ň´AÎ(•p”ŕĐ+ĐžK7ů{¨MáÄ'Ÿ<÷Ţű lq°Ăß°żˆ=š˘ +•A?°ĄHAAWŰA-B‹ţ˝vŹG*=xHŢg5ŠzFŽ_X­6Ů~qĐĆóЎŮ>ř‚!Őúâ~€[ľŠÁîÝ{ ţ˝™rąnÝěßż_Föp૥‚ą a”Űňĺ˙ČÀ)"ą “¸ÍűŁŰç&Čj0ÜťąÂď+ݍDؚ= /1ŒEf[†[pă蜸zHk´Ž|řôÎúd<ú×XB‚`bĘÜó{ăŘÎQ~_ˇ;ľŔ9J¨ŒÚa—×\Ý*ü˝r2ńᇟĄňxŻý.żWF9qrÉűŤkŻ˝J ü&O9ĺL1Q{Ő5ąxńĹWđĹ_IoŽ6a:?N˛Œ`˙űŇK݈qŔ&1Њ”Nz~ľâŐL8űě3ez¨?ýôC)ôzgxƒŸĺ“O>“‘ž#𚮹ć*Ů˙QHágŃ`H?ۍ‡~ŠúÇ'Îá°QtŠť¨˘ßŃÜ%¨Ät‚aŁÇdőĄâŮĆđľCGAÁÁ˛ÔĚŕ͙ŕđâ™ňcŽœŕКŤ‘Ä:iŹ•ňă?Ëţäˇß~}k3)zژřë›_Ť‰)$&ŚĽüťĐ!Ĺq¤żs°Oe]HýX›őăcöď`ôéŞÚ߀óo‚ŠQQZ_ă×Ęô÷„‘Mzxýýőˇë1żƒ?ţř›7oÁ°k×nš_aÎ}—]v•÷´–‚‹˘îQ‚J€5Šúýź‹k#UŃĂ;זw?˃{J˙/Ýo‰m[îü–VĽ)?Ż+1ew öŹ—V˙~}dă]&]lY휓#Ř83ăöŰo‘ 6NĚIěŘąŁLqaČ:Cő‚ _Ăƨ2bŠFZZş,}Ž—_~A Ģä}†ň}óÍ9šń„‚Cć§MťVx揖ƒşçŸQŚbÜxă ~ߏéü.źMΞ{Ž,ü‘߁Żců=ŃĎcŘ)ńZnšĺ&Ăc} ľ0Cvž 3¤řEq…a†L™Đ`î륗^$#`(ΰ~×ÚššÄí,’)t2jƒjF14źMŔř÷óŇîÁĽ+ô”†§˜Me)>&;ĘR‡ŽP-ƊӚLe˘Šv:ŠeqZĄŹěLĘŔ@ń^üyF¤ÔU” WáBh\†nÝşĘđ܊ÔOá@Š6źfÍ:}ô„rĎs•X*"ŇřƒíЇž_nddŮ`ĎóoíkňM‘â–[îŃ:´W†ßr`H‘Ó”•ßgőzŻĎŰc AáÁćjˇśuěŁoše†,DűŐWߔóR\ţüó/…Ý>îHťv˝LzY䝂 '"čé`”“—]vąV8Q`­öGšŕâI aý§vŞ[¤™żq†'ü,sć|%Sč4‘˜mŻ—ésl—؆č7Eý$Oô%­ZĹú‰N‘J÷9ďGśéŒŹýÎBĚÍLČLM–“oى} Pŕ9"uIţÍâŘç‰&ŢŁSLjQÍcP“P4äX“‘]9"Ćí›|Č9şwď.ĹYý؆ŃzGmŸÎ ¨Ú1ŒžeÄG›6ŁPTśż'^´”~Âś‡ő. #sčbÔ˝&Ěr\â #Ś)Sxyěą'¤h]Dz˘ę(AĽ x +œT 8 ˙ť×!bŘq^^čź)KšvYZ*­âœhĄé%ĽiBşcœĎ•ÎÜč5-Öô$ô>zŒ×ĺkc’Ĺ\D6:„ƒ06n,’ękĐÎBL28Ŕg8.•jmrĹŰÁƒIĎ+•ĽK—IĆŸ'œEi=Eý„MóŽkđťaHßŰ :,ÔĽ‡Q2Âމb=pšP“Q/\j–ž.Łcő°3ĺ`’^­ńŐ§Mp2:i’{aĐeËţ2,TH˜!ٰô0\“ßáD×ĘZ9z¨Ţ7TAĹWD‚›—HLFă÷€ExŻ‹ťŸ€˝C‡”ĹIřŚÜ]Îč!”Đa,Ĺ”‰,ΓÁ­†Š4eťsIÄâ˜^Hę3™'Á”_ Kj ‹Á<'œ„űOjKTaÚ‹ŠŇvYŁĂŽĄĽ§E‹h™ŽĂźb‚Žžú:1ąşD X0 €‚ß5×\‰ę‚9Ń´Yzłg̘.ĹŠ_~™'SŮ8á`ůŇK/–+îpňÄPgţÎ=‹˝ęáÄě×_çÉÁ7œţüó/n˘ś”łnEIÚ9Óu˜cŻ ;´mÚ"Ó$8YŁÍŃ Ćż?gŠ§ˇ6GOĎE1EÍöŸ›ĄÉŒ`aÔ ň5Ěm7‚^É÷ߟ-ŁřÍż1Ł×n˝u†lsŇÉŐX@°!ÔŐŕď)ÚlśÁ!ĂgŔGXh^]•ˆQ!čî÷܉š%¸yţ^,ܗ…ćá˜"ĚfÇŻW@ŸVţ_Żą;ŁvF/…˜+ bś šŮn˜šP0•†ő†řűŁ}čaô"ŰDţȊŁÁÔ2­Żĺk˜6ËXFŞ 

Öb¤PňÍuÎ;ďyĚŁÎ”ečědÄ\RR˛€?GeĐÚ1§(Ó: ţžŸaŐŞŐ2r\?vfš>ŸcĹ×sÜÍ´~Âvˆm …gö­ †Ť’jß Ç/;věó‡{eń|ŁĹ3[˙]_Q‚J5ÂÉÍČÎԌ‚ë>â8çúPÇZ˘ ĹzTLúĂÜÓĘćcelÁîőňvČŕÁĺ#ľ™úÉ5•lž'Ăčـřj\}†‘59sţš’z^~ːcNn˜Ăě/Ä_QZ6^žç@ŁM*Ż…ß˝ßüœ„“™/žřTŢó͡\"…#ĎcőĐcÎF™ÇđoÝ­[Wˇ´ Š0Úy™ŁÉč#‘-Đ0ĂĘH‚úˆˇtو¸ˇď܉ŃŃ ąŔ…Œ^˘`ČՈ´e"4u=šěAĐÁÍK…Š$!AVáŠ*Dp˜ük["˘PdŠ€ľY;äFvCFhwäD Dśđc9Ź%@~ž°Ľ"1Á ĹÎÝ{ŃWüÝŮć˝óľRSp‚A-BÉN’¸éá‰íoôLąŕ€ęˆœ“ţkŽš˛Jk=Ą˝źúꋲ"˙C=*—€¤]˛SŘŰzżšäđ{ď͖"'ŻÓے¨Äqrřż˙=!3u•8qóż7NÖ¸4bI‰Ućqß{ď]Žś’çxîšÄ$ń\ž.7ž Rł/‹ÇîÝť×íœü[ł­|űí÷„÷ęaˇçčůăŕm-7śÍôâłö„7•––ćj—ř{çcÍ+Č6”YÓŕwĚp1KůöÉă!3|VÉÁ˜Ů›Đ'&g÷‹ĹÉ=[`p›˜Ýl řls î_ń˘faA°Úha6ᡍ˘stĹŇv§Â$ŽÓßőy{löÄĎXS“}ţƸšÍ…^*~O/N.YłÄÓn-§ŔC{c‘ÉŐŤ×Ę~Œb &ümQœçDÄWš*ŠLX ă = ľ˙R”'_´We)#E§h÷cz Ñu óSżYôż#Ü~ßFýŹçď‡݌ř-˘QMqíăš˝Ľô¸żŢ} Âq*ŰćڀQ^Ÿ}6GQ5‚íL }“/9űgÖ^˘ł€…h9FxđÁű\B,á8öƒŢ}üë˜>}†\ i̘ŃbîđzĽŁŠ(”0Ë/łŻťňĘËýö÷L§čËĽŸŮVj‹[0"ž5¨(ÎĐŃĚ>ZßӁĂU‰^{í ŮNŃšBŃäž{đúńx.:Áâž/˝ô|šß`cëżë+JPŠ&řć„`Ŕ€~R!,ÜšŢU+Ţnáţ8¨ľ{ˆź)$ ć¨ćĺ”ňÍŤ;ťœKƒ6LNžëŞ~ Y-&č!žđÂóÝRxXŽKŸi0$—Ĺë¨˙óĎJźńĆ+¨*ě”číҢLŘá˛ô,HŠA‘ƒ!zúTÇeGi$zxÂƞ“&Ś70‡›Ţc üŽ´°D­V?;Ĺ NŒ´c5čUc&S”4ŘŮqňÇÁ"t6śĎeýÁßSé´tş@ zÍ÷P[v¸éašŸ ąŹŤŔÍ´'Ϥţ˝ôbm5”<ë(qĺzѸÁh8}D\œ¨ę1J‡âőhQ}žP¤âf„Ń÷ÉśNßŢq÷÷ßeŤ!đťôőˇŻKź…l)Ĕt[@fŚîE†šq0ŻĎŻ<Œ§–@ëČ ‹‹ŔĐö͐]dĂü]ér%ŸfĄÂöYîV âc„˙~ĺ@´o‚Оúp.‚M•žĐ;lv´oa ¸xfe`;ýő×ȕŻř›ĐÄzţî(ö2úI_€‘uÚľ+sążä \ъvÂÉÎQGՅ˛H:ű>oT6Ź?q†žnÝşĘ>‘}žž_ăcÍ9˘¨xÚ="٢Î/ČGtiA Ń)Ú}Ö8‰ęĐ 9‡œ–Ö¤8"nm=‡Ęi´ß7{•iÁééHÝťQźvťkó˝ĺšľč_˘Šžž÷ĺ ' ?“gýę°oĎţş[ˇŽĺúĎţŃ_ßdԟ2ZTŢ@ú7ś5LQ×ŕž )čŁá8eDF 2>ábÜ4üő÷t"ż˙ţŰŽÇlӝźď˝÷–×÷aTŠ>M—xwŠ=?ýô˝×ó5äţť!Ą• ŕŻ0-áť[׎غcTX ÁŁa+ËĚ)'Œ˜BBan{vşÜÇú)NQĆáXhÔlíZ/;Œ^˘aŞŠpßę€ÂĂ˙rˁ @ćOrEgn6=Uúč ôłř)-,ŢIIIĺŇ ˘Ł›ťj<0˛ƒjˇś:=XL•aM#Žşęr™ÚĐ­[W Âk|öŮ祗7A…°h+S‰'1 SćR­ü^ô“+Ž@tŐUÎc™JÁpC @ôŒ9Ü­ĄäR¨üynŚ,PüaZĐO?ýŒ7 Ĺ{–áőfč ţm(äźúęŇkŁĽe¸Łˇ°íúH bŠV?…ŞÂÁƒ •kGieY­´ƒ!áb˘ŕ°•ČđN´` –śËť`xŒCˆ/Aâ8{Ix­ ÖgjŸÉĚöĹ.GSAAf!Ć#='É)ÎI'1Š(ľ•ţٍ;X‚bë—_~-źsÓ ('î=;ś…ů@&lÔ+B…m† Á´@ËçŕŻŮŇîC„F„ ›.mÄó ŽT)1…lKĚ{ďĘH˜ó3ŃkhťJ{d…éyLďĺRĘZş'ű‚K.šPeŃeŠút:°ßŚ7™uL먰¸+ N¤=˝\Uľ~ꉤ˛aýŒ3ôЉqŃESĽˇ›×ÉĎÂú.,˙ÔS3ĄhPđp;MăÁčćeQ%Š*źí=%š™(ĚrF—Ř„¨’˜ŸÜÎCĐ*ŽŮďkâ ÇTtĐąFVzňäÄ˙Gn˛ëý¢[ŁUoŠžë¤č÷ëE•ÄÄÄŇÔáŚÓ§ÓV9ž˝îşkd[Á´ .|&Ć_ĚŠšB *•Ä›¸Â‰cß>}ąióf”$%ŔŇŽ‹űëÄ&W08'÷YbŰĄ¸TPąpÉdłqdŠöí\ŽçĹ5îú=…¨ŁO…ŠË‚´Ţŕä›+0TmѢ2$î‰'ž–+ěPđŕóF*FŽĐËĕ*š~Śšpó<‡śŹaxx˜ ŠcĽćVS„xë­7źćÇ2džľ`ŽÇh.ťČćg8ÝŃGO’駝vŠá9čUcž#_ĎÜF.+ÉóP‰żîşŤÝ–|ĺuPw†čżĚĚ, É÷Łh˘÷ą3g8$E!ŽfŔBŔ é§€ďç­hUEĂ ˝Áh:™˘ŔpBdŘ6ş†€71ĹsŸ~c‡ž{Ď^9ŕ b8{i1z˛Ż-[ę(4q? %6›vksľ))œĄŘnƒY(ö›T´ĺŮůýRDŮľ{:wę 8>§ßęjľEÝC›§ÉœwoQvM}ŸÍűíۡEëV2qrU9űŕŤBÍevŚg`Ťptj^šŐ@(´îÉ)ŽRşIkÚśíď…7ŤśUŹ˝Ă}=ó蠘5ëmýHČ=÷ÜéSS] ‹0qâqŽ}\˘•Ť}ôxŸď[ٰţ@Çzč…ćxę7fš–M~ňəje„:Lf¤ĽĽ RWˇ•züĽühűÍâ톏#šDGN2˛ˇüœýmŢŞ"[ľEHx3y|Q~6ňӓP˜~vqœI7Ч˜ŇVœËd–˛)*âŹm—"Äsžž>;NŤ:˙îż˙^)˘°ž 2dSßt7+ľ)€ý&¸'Ťp3ënľ-¨tł”ntË0ţłEqqÉJÔZăŁ)Ă Ÿg´ŻľÄ+s~ý}ýäŠJô;bŇűŕĂĄÍłyÜŮeËyhęˇN‰Ö——ĺ˝Ä‡.EţŞEňqäѧĄÍĂ﹕_ńGɑx¸b,.8*^~éWJ€~)¸š`Ő4ôt]wÝt!ŞüPé˘`ŹŐ@oآEżĄşŕ ̙\°ŕg9čST.™Ká€B‚ć҄‚ę´u_Ń)|œŹ Xó2¤§Ë^R(ŁN2„ŔőíkÄőE Nü)xЫɍ+_ŤĽQ q$$Ä"›ƒ`1跉kgzP‰ľAâ3•/ŤMl$ĄĆ.„~.ćŔĘĎ(Qyb?‹ť2eč¤ńƒeÝ3SŒ‚ĂäšB›ˇBó-ËŮ˝%°(ę+ŐeëžújÂÍs–âotƒĂZ„ę&ˇČ†wNíKUźÚŸU„ţo­EThĺ|^ŚŕPçˆÇOpŐxđÖ¨ś@QWTgżîĎŢš‚ĚüyżˆsZ…ƒi„;ĆŽ‹ľĺ’yŁżďźuŢwgGʎUČ>¸•i>ą}Fťj$ib‰Ńu;eb‹ţ>#mV­ú!Ą8ĺÔS]+1*;WÔ7ŒěœÔćo2$$˜ËFeŠ­Dl,&c-ÝlĽ›]ˇ9tˇúŞĺCĆt¨•jDÖF?˜‘#†Ëű…Ű×#bRi:FięŽüßí7äpť¤[é'(ÖšÂOů#áó…;7Čűƒë¸ mMŔHŽvÁ”ÖRŠŞ˜RS°('—SSbJĂ—˜ÂpňĂbŐ|îyž&ĄĽ XlšŠĂŽv(čv#ÚˇsvšwÔawĘ Lӑç’1g Œ8á`ĘĆvÜťÍ._ÇAdEŹbĐ' 7Xň5<­×ʎˆNń/[ˆ,›:­Ěš`VA„ŘÂCĹšcť"ă–ŃšG_ŮqŐE=…˘ž˘Ů=ÔŁŁŠđwq$4čj†Ë_÷ó.ŹJČĆ“ť!*$p/ňδ˜hű!•‹P1…FbtpĄË Żl]ŃÔa˙Ń 9Ů2Í<&Ś•AAß)?Ú1t`Äőćí{"u×Zf$!Â[Ä!Śç0„ˇŒÓ )¤bŃ)™â÷ÇË=‘‘5žÖ§P(üŁŞiUZŁŹŒm˘íëœ);ŚŇÍě~ “ű-ˇ Öm]ç4ˇjSöZÍnđ˜ç)‚ ŻeÄđş-H[°Ăt#"ÂÝ ąÖ7öďß/W,P4\<ëĽĐCfZ7–‚d9ŽáňÇÔ<¸řÎ!K'DE†;ó§…ýSç&dWގ“ŇA™Ă—fgJOŠ'ŽŠ=˛Ž kĽ˜œ…‘˙ßŢyŔGQmül˛Éڇ$@Á čTDTPѧˆúŹĎFWž>űóŮ{ņ‚`ű‹ž˝‹  " €€ˆ$HMBBzŰňżçÎŢÍědśf7Ů$ż/ŸafgfgînöÜ{çwĎ9×3˝˛KYÔȘK&ź´“-9•J’şP-—Ăá9™KśRŏďIŇěłĐÔöą˝žpřA”RU =Ľ¨ń§-loěaňęşB0k%-Î+Ľ`ů­¨Š,VK˜÷vQJExDݰ†pž#Z ÂÚŮrr´AŽ}űJhoQQŁs̄ݕźD&%Ť 0d ő:ž: Ą$%g?˛ÚRä` /ź’Ý•r@=ŽGÝţ6Ú-ڍëΝb&ŞpŘRQĄV~† §°s˘dÍń•;E'd;čŔiĹ*!¨8ęķ̞"î÷4<[yůа/Tâ´ŁZp;áĽű|§K_ékGj7ýB9Ůٞ^T™ŰĆŮ."YÖńŚ‚yÜ[fýëŞĘ ˛ýőľöÜĹbŠƒ3ËóH{ŠTPR Ďžäň$Ő˛îťsĽ¸íONĎM$Ă|ř¸C¨ œs…˝SXˆqHo͖î÷9en!ŇÄ9ĺL?2‹;á­ËYGőU•T+Ę`Oŕëk.Žk?˘ęSŻ–n–ţ>3:Z =`œýJŃŁGčZBKŹ˝ČUů°ĆoĄrqĎQŻţJWěB÷œÚ[zŻřă‡üR˛YÛá‡Ă}:ó¨{÷aŢű}„˙ĐÖ0ë§łOӝˇułlkˇoßNé™”–ŞÚČŕźSԶގ’2rä˘żŻŻPŕ˝SÔ9Ú>’3űäĺĺ‰~„Cîă Ěě+ÝGťvîô$Ő;Ĺx}cH­ś–˙{m7Ĺ;…ËşcÇ*,ÔâƋÁڜœň÷™Í^*uBŘ­´×P(ż]l;Űąˆ/„3›čŔ§Ä'Rj|x3ž€ČŁF’ydwŘŕÔ˙˝u´ŢŇYŘś˘ O‡^**ŽSć­ĄŤvĄűFÔČ[ĽX(¤›÷ŐPRbč3wXÄo­őŸň3ŠQk´ůhvŔŮٝ¨¤D›ş˜§˜çٛşuŰß}Žüßk;wŠ™â~ĺŢ×x;\ď”={vÓśmŰ-u¸í1Şúč-Şßú;9śçi™0üŢdq őp§ŞKTx*aNR¨mŽŽÖŠ?Č k×.ôíˇßÉNK[e׎ÝtĹWÉŘuNLŰąc­Zľ†îžű>Ú°a#͜9ƒ@lá/܇áζ㏏„€âRć'íŽóLď,ś(ú66ˇ˜ÁÝ‹űŒÄ‚u”R´ŽÖĚ"Kf.ŐwěKľÉPmz7˛t<ˆŞ]‰”’ÝYN}œ’™I%{ (+-‰* ňŠŤŤě{6Pző˛íűâ+KE9„x#–Ęx­łďTŹîŠ€XÜIL ĎŹa\ž$g%•oůžj:ďçÉŠ¤ŻŤTĐÔ°v.¨+k÷ŁVÁRn×ŘŃůjômłY{ÍŰ]ťvĽËúŘč—<•ť´ŠÍ˝ŠÝ^`-Ö)Éń´x{)}śĽXÔ3ęă”çCšž‹Ň„řzůIňłŔ;%xx„řđeŢ;ĐvQżyn {őîM[ţŘä9VRR"űМŰ,++[˙ލ{§řUxUZZJůyů´uëV)Â*úô9X~–hŮ5ÚőĐ@ť ¨DŽÔŘCäđĂĽĎ>˙ŒŞ?RĎťĚëœĚ›¤ú-)Ąw_˛öč-óĄ05Kż¤ęŻ?ŰIcÎŁŹfËmW]١m!űÖÍdíÝĎíőŇPéÖçmŚúMkŠ÷ŕ!b*[2ʧŸ~NÇwʌSýôÓĎÚ´ ňŔQ‡hΜ<°Ă† ĽƒîKˇŢzt҉4hĐ@ąęĐČpŸ]_k/n/‹5✚ŔÁ"Öř1ĹłX´ó¤¸QU@ÉŰ (Š|Š<˝Yâ52Ú/Ałânît ü)Ѝľ8čŕ{ş˝Oâ-Úűĺ"óĚŞrT#ے’ľŠœ-ę|_6J5ƒÎ”żÇhÍęłWŒÎ;]uv;˝śúSZ´î;ÚX˜GÉÖ$ęÓţ~ÄItŢ#¤wN{†;_ƒřë–E +ü0u°ăhBţ‡4'íhrVěu ăsE„_łW ăÔĺW îý˘üi94Áš’Ž:ŚÍÍîmřűš>} öŰEż~ýčĎ?˙$˝QąpĄ’Ăçćvi6ď_!?꟧GŢśí/!ţl‘ĄÁŠD[ŞěWFłov=tĐŽˇoC%Âčc5,ˇËžü/U,˜Łĺ8p/ńLI§Łř>ýÉełÉ}ÜłďjH8eߙŻÍŢĂÇl‰ň\ŰŠcĹ{ű6ěKíšT<é\éÁrH˙ţ1îĂńŠě•rüńĂ脆ъ?Ę8P=gž9ž^{í şůćŰÄ9'ÓĹ_.==,x›ĆŽ=['Ńíˇß)ŻĽŘšs—ÜwĘ)ŁĺńŠSgˆĆqŤçřŒ3é裏m´|űíbyœ­ůó_•×?î¸é‚ .ŚŻžúŚQš¸ 7ÝtŤ(˙:í´3d9}QTTD˗˙@×\seŁ–N;í1b8mÜŘ0"ňż˙}H矑ź?—cîÜy^ŸËťxńwtŮeWĘűßrËíTQQ!D›‡ĺçć0Şyó^ńşOee%Ý{ďň؈§Ň̙7ŠQ<Ďqž­ćᇣSO=Ž=öşâŠŤ˝žˇöŒ™w ϐS]VDĽ?jÖnsâç>+3EóP!÷`rœî2öŻÜ‰lYUšNäś{¤™×ę˜ -Ň\Đ´%ÎíuçöLQ /6чIíw˛(¨J¤§Š-IŒ|w$ęä\F5ŐUäoZčŚPfŻ–1Őzv•Y/ß@w}1‡b”ë˘AŁE‡kUŐ×Đ-Ÿu=n9l÷ňËŻ’môß˙~>ýđÏ^eţěł/čœs&Č2ýóŸ×ĐO?­”ďăD§ ĺĆ;‹řú÷?„œşHnËĘĘäß/?Ť×l{ÍíÂ}žÍg‹}¸ßčÔÔ"FKŽ8âů˘ÚőđAťŢ~ &*mŽÇěßď`JOϐBGůăwRŮ}7ËQ'É6^DĂ/֎ ‚ŠcGžÜç˛čΓ\Ú>ţëUž3Š§N$gÉ^ůžŁŽÔh†Ÿ–âťď–ʆačĐcéo;šŇŇRéóĎżltއ~,ąó„Č𮠚˘{îů/˝ţú|y}îźvďž?˝űî!ôÜHĎ>ű­Yó‹<—á뎝6mú]~/łg?'ĂÎ8I‰XĎ=7›–,YJ<ň řLoSďŢ˝č_˙úˇWcݞ$,p¸+˙K˛ĆŮ=ž)ź°w‰Mhf݄`Ń!Uó QbŠôTq‹^ůˇ‡żţ–ęk×=iJ‹śV3 Š÷HŃ&NóRą¸ĹöŽÉečŃYTŇ;ˆ2‰íŒn˘ŒŮBTĄdßťQ>”řűüáŠ,†dl<‚uٛ÷Ў˛BzţœӇ—?JˇźŒny)}úĎÇiéäčÎ˝č˘˙ť“Yüşé5ô"zđ›WŠŠÔŠ‘Ć'–, M…Ű‚:˙Ť?VRĎűĆÓöRíčŢŻćŃĐgŽŚp™˝bňČDŸÇ9öÉěš‚‚žýîÓ§]7¤+őqJCgťˆĺ…cšŹ3w‘!ĆÁ(MWBi݃i—X¸xôŃ'd;Č×äœc7ß|ť6íV0ýYłžŁwŢyOě›)!^˘N:z `řâůç_ƒ3Siá¡éCúËÁn˜ďż_&EœącÇĐŤŻž,ęąt˙ýˆmôżýţýűQRrjŁśŽŘ[e󛨟ź<$+HďN:›ŸŸGżýś‘6mü˝Qů˛˛;Q?ńlÍS´ëžAť|A% ¨ŠŽó™œ5vœçuő˘7ŠdŇůäܡ×-ŒčM,ąďl˜ý‡y,ŽáÆç%¨´dü4‡ř°˜Â!HÜÉaqâ“O>ktްalj˛!Ăe&L8Wş8r’N:‰Nb1v<­_˙›<—§˘?Ž7*ýáňřĉD´M&îb¸Ă5`Ŕ‘r),,˘ŐŤĄźOŽŢqÇo,˘ {ŽtЁô\(ō9sćy•k̘3ĨŘHęŘąŁě@öęŐSvÍ(++—žAÁ$Ý=ăŒŃ´hŃ;tîšçPϞШQ§Ę›G\ŚnÝö“‰mšŹ\ö /œ(?Çȑ#¤¸ňŰo䚍V­–ßѓO>*żKţ\wÝőů˝sŘĂ#œžżˇ.]:‹â RŹQ.â@C=Źđ÷mÝţ™ ż‰SbŠ0­¸MTé,„‹5ď™ÇŇéľ!ƒpBÚ1—ŤĄK&jRä~WĂűd‡{íl%RŢ*,Şp¸O–řšőĚ%ęşżOrˆŇÄv’UŹIâ|Ť8—Ë›˙žçA ’Ţ)c]ďtxí{mŐ'Ňřá1ShÔÁÇ4zOvr&ýóíű¨¸Ş”f˙E“ZQG>ąäMú=ȎWKŔ3€ćÇŘ.ęŰÄc=†fv/§ŽVŃ)ގzŮŠŃn[ň5—­k|,+‡ŐóŮ"A(íupíŇNŃŚĽK/Vî3}öYôĹË\pÚqßíV ţ×{ěy2}úTŮföésnřź@Lštľź&—‰…NŹŻźLçĎMśŰ—\ňů™ĆŒ9Ć;“@lŕoŔ“ןđo‡íŚŽžq›ČVľ5ľ”——Gy[ˇR}}Ďë2B~Ô~Ţ)őőő´}Çv1xö;­\ššţúk{Łr%$$Ëú‰ËčsˇƒízÓAťŢ>A•a–ěŽ]ňŽ›1MBżíŮJł˙~łJs~ü€^ú mÝť“îűz>ý°M{ŕŃgÝsÚՔf ,„T”НŸżD‹ˇŽŚĄXyČ0şař…”œ ĹKąů'1÷ ĺ—쥥A‡ví𚾡j=ômłŻýęAëŒÓGS­hŤÜݕś“MŘoCŰbqy?&ľÄköLŮßZC7ćîe+Ë̃T$ě?”ö:˜vé”SN–˘‡‚{Źôňä|cŠ@햿ţŔîÝ{d{ĎbŽžˇťţčÜšĄýĎÎÖ•Ş)kYXaAE{á‚ŘĆhëüw8p ýúËŃo‹÷:—gŢăS9dmăĆ ”™™I]şîGÉI !ݑđNáßiQQĄˇnÝ&Ĺ@śg}Z&^Řüŕ!C(Ç=k_´@ťŽv„•&ૃŚ?Ć#"Ó§MŁÎšiÖłĎPqI 9wm§ŇËÎŚ´{§ÄŢIZmŁĆR՟Z‡ ń´1ŇsEőřNö_WQůĚŤÉY¤šŻq‡ćâ‹.˘K.žXŠęŢfkăv4áœ$ÜŠâXkNČ*ËďţŽŘs…G´Âłą_rÉŇk„Gœx´ŒŸiÓŽ÷:˝ nźńfŃń"GŃ‘Ą×Ă#^,ÄŹ\ůłĄc¸Óö˙§š8>óĚsńă•W^ŁŮłçˆNć8y.‹K^ÔTrr˛éĺ—_j´?5UkTXDúŕƒ÷éűď—Ë‘CŽ%ďŮł'=÷ÜӞi6Ű#fż ~pîů™’âĘ<ůLâ\ä8-î°[–°AńŐe¤‰Î6‹*u<Ň$ťćŐâ˛jď‰s5x§IőůVܢ‰G€ąčöť˝U¤"Úř›6ł§y°‰>ż%AS┋ĽALá2d8§˛ňíd6Ł€"‘ Ön2•âďEŰč‚§Émî¤ íu$Ňçoňő>QşßŢ7úZJäŃÓgͤ@l.ú‹Š*KhÁ…÷ĐG—ÉŃŠĄ= z¤YËŢĄoţř™žuIďHˇöÍűéCşqř?čł+Ÿ¤Ó^œNˇŒ¸T&Ícîţr.U‹‡ă×.¸“ě˘Ó3ů˝GčŽ/_Ś‡Î˜ěˇ NńY/yó.˛‰Ní˙]p7U××Д÷Ľ’ę2z|ě ÚR´ƒŽ}÷!:ľď`zběu´nϺ닚?ŚŁl^Ěfü1ă5‹ăǝI‰BOä§Đ†ÄNäŞŐŚľEóžvIĂďď*¤űW 1ĺLYV_Ţ(-Ńö Ô.ńCí‚ŻÓ?ţ$ÚĎU2wÖŹgiîÜĽ—Šżv‹C2üőT8ŤŃW4ľ˝ăëŻi| Z–`műč~śsçvJM1ţ ]dwŘEŸ Ĺ´MBXa{ëŘą“œ ˆGźSĚDkĘĘJĽˆÂ!Fy[˙˘­yŰdcoö;˛&$ŇĄ‡&Ëm;6m× Eť>í:Úuŕ*Ä輢*>͸ňĘ+(ˇs.=ţÄ2єŤşŠĘ˙u %OšIÉWNўÎD…›ôĎÉd=f(_Ź‡Š^ť+âÚ÷ߤĘűogI[žÎÎʢɓ&Ńyçž+CGbĄó¤`w^v—˝ő֛źöł°Ŕa?á *< 1:˝őÖ2›aO#÷Üsżl´î¸ăVŻý˝ző”ďăđ˝— żV˘H8p‡ŽĹŽ÷ć‘*NL˞*ěŞĚŢ:Œƒ~.M™2Éóţ˘˘˝žQ°pŕŒďĽĽe˘ąOôÁŕďfŕŔr›˝aŇÓÓäČ/,4M˜pĄŒoooSF“?%aű"ééĄ÷"Q"‡C¸_îG$ łtQ…łkkÄÚ˛Ăb‡E—c…Ü‚‰ź.iűUŢžŽšľ•Ü hš'~ęœ8žCX$‰OÖę…zqż„éýŻĺ[!ňĚđĂçIo•Ĺďţjşöó*úď!Ňu…únˇěÝAŻ­ú”ž:ëzÚ&FwxűÚăÎłSéöOgÓ×[~ęz6љü÷I˙SZNëx.=ťě]Zż'Ovźd?ńpS):BŇ:ĐŤ˙ăy_׌Ď:;%Cnϝp›\WÖVÓśŇ=”›žE› ó–aՎM´Ą >˝ň ę×éšoÚ°séż_ĚĄ{G]KlX*ţVzěĚé”$Ę{X—ŢôŁ-űtÓ ą‹Y›­ÖÜNŒ=s e-YJłÖlĽĹ)“Ť’ó~´TŰ*ʕšM'Ôo˘)˛e˛rśg_(-Ý`‚i— e8 {§đ2yň54zô™ôĺ—_É|*ţÚ-î řëpߋz9ÇËţűwóě_˝z 5+ćkęĂ|šzM]|Ů:ÞOK—Ö aĽČDT‘rˆ\óo,N4Ź{hűöżÜžĂ˛żÇBK˘¨űăâľé—ů=œă‡Lă>/••rŔfϞBÚ˝ŤP†öČđ5kYMĔÄőé{°Ďü|Íeçh×ŃŽ˙@Pi"ţźTôçČxăóÎĽńĐüÔŹY´|Ĺ ůDTýĚ#äز‰RďzX›÷T¸ÖŃpŠ'7G=U=xŐ.xĹsÍ>őĄӧӘ3FËńXĄâ,éÜšxđÁ{Ľ  çŠ+.“#JWÎC<‡ĹđčťłwÇśmŰd˛X=|Œ3đßrËż˝˛ýs=>&N<ž|ňiŮ8rů8{˙{ď-¤űš'Š˝üň+ĺçc7e]ăřđ×_˙?JKK“űż–.]&ËĎaaE& ĺ¤tܙbˇbö aăŢ{ď’Is› 6ÎYîgÍzBㆠpÉYźRâviS$[´Ůu<Ţ)Œ ŻŻ­YZ^h''vw¸ó—$i"‰îY{\őšŔÂâŠSmťIAE—óD&’e…\ă´ü+Ňű„וâ}uÚ˝-âŤp¸÷ägQ&ď|´kfяôWUąčěĺD,ź+‘Ýe ϕgv‚Ýáގž7ávşćÝÉ*žŒ‡Ď˜*ë¤O6.#QŇݧ]EM%ݖBˇœ| Ý=ę*Ę+ŢM7}ňŒ¸ßC´ęşyÎÝ-:G<˝ăNš‚.űŰšďjQśĽ…ďÓ%]cWć#÷ó>ł“3ĈX6í(+’ńŢŠ‰ÚH9ť4‡&¸%ETáşuĐ AÔŠS.ńÝ÷ôćnýŇ“œŐn…4šŁÝÉi4ĞGçwŹĽ“NéŠĎc]La‚i—x=îńÔȜ[Œ…ölUýí/ú7Üp˝|橛9çlaϗwß}ŸÂE%‰Ÿ7ďůŮřž,ř̘݄œ t|…ţE†=¤~ůĺWÚ˛ĺ1ř™0Œ‹ßŤrćŠY§ÔZżÍ‚GzzŞĎăfűÔvńŢ=ôч‹äk3q¨OŸƒiŔŔA2GZ$@ťŽv„ ţę ”ÎWĐÇ3DŽÔě׼ ͙÷˛l˜ż­Ľ˛óÇQę“/PÂĺC﫜v59wď”×ĺĄóϛ@W\~™Œ+ö7BeVĆć⢋.‹/.lÉáŘh=œ¸uĺĘĺ^űfΜáőš;DźčŃżçwŢ$đwqéĽËĹĆr1łg?Kŕ™Ř3ĆÜđń4ĘžŕĽń;0+/OšŹ‡E˘›ožQ.f°'ÓÝwßIŔ?ě–żc‘E<3÷85DâNJ+Ĺ—&lĉg+˛ťĎľhďs*ąÄí%˘Ś<öfÔZ h¸ß+Ůľă|_ý,äžqHz°¤6xťXÔîđ"9Ő3×đěáď ř˘Ď¨6ˇGäQˆŃĄŇĎpáŔQ´ŕ—ŻhćOĘ:otżc˝ÜušÓu˝8vhçŢ4qŔ)ÔTf~đ”čÄmĽűF_C™61b(>xşŰÓ/Ĺj“žůë舎‰Ž˘U|5Ú+FźňKvÓĎŰ7ŇŇ­k<#Nśx-j͎ß)75[Ž˜íŤ)§…ůtÔţý¨oÇôä’tëɗRFR=ýý[ňťţœiLżĄôĚ÷ďĘĎ6UŒŽqŹő—ü°ü)ńą1Ĺ}{$˜v[ ţ~şn=}óăjZTבÖ'ě/Î-Î/’X(^Œ˜RżĆ&üN#† žžňĽ4—˜N{¨]b/ kŽšJ.fjˇő¸ž›:u]wÝ4Ďž_œă奢˙\fíŻńš ĎÖÇÓ%+8ż ÓĎ}ĚźVôž*œŔ˜s+Wޤ !‚¤ĽNlÚrXd˛Zž§Ą‚ví:*"Q…×<üÔŠ“ĺL2TPXHŽÂ޸t%ž>N>Ő}źˆłcĘëefv kŻžš&ž?AĆďŞ{˜­Ű€ŕ`ťa3˝f™,H ).MTńJ&˂…[ąŠÇ^mˇ'/ šsݏ§>&‰ţ2rĂŽŰŚ†s<ž0ďĂźŽď¨‰9ęľËŇ6äYX¨ąjKRĹ×âł]ŃZźJœUž×‰âáeބŰč˛÷Đľď=$cŽęÖO&iăŽÇ+s§ëeqŽ5žéÍÇ`ßőĺ\9ecU}źĎ4Ŕđő9‰Ý3ËŢĄeůké›kž‘Ó>>ľô-zů§hřG‰Žáq´Š _ž?Hźwp÷ChĆ˙ž¤—ĎK§1‡ Ľ~[BgÍť‘VM…^™x‡Ľťňdn`ˇžtÇČËĺ{űtęNωĎ0áľ[iXŻtí1gÓłËßőYvv Nˇh9ľŰĆ},hp ‡z ݰ‘~řu }kOٟ…1–۲ČU[ŠĹ÷…SŤ–i:˝ś„ŽŠŰAÓ+hȐţÔż˙ńrF•EżöľĎěu{…˝A9O{Žđƒ2Ď<ôć›oyBpÁ=lŸ~śôJéۡ/íÜš“ž|r–ĚsA%öÖÎ,žr2eN”ź{Ď^ꜛŁI‡]âĄJ†EĘC…AťŽv„Ž%ˆýşîźW7]­ŐâŽŘWÝwe‡sęPWWßl|Tĺ¨ÜćxŚ΢­OHí{›˝n˜RÍ{]ZZ*çéą'ž˘›6š^ˇwŻ^4męTÖ8OâŇPÄtŹ@k‡§Řä˜eÍäŽ {gŠQ8śîË69zůŘíŃ2ěF˘ľ­źI¸śs5s•ŠMöTQ;ĆZ”Č;dČerœüźW˝dŃw˛¤ŽÄ‰ŞŠE\gϤ=Ż˘ŽÝz4ŠĂö\;ŒşbWm)ŐŚ Źßăk>Ł…ëž#Ayr_żN=iüa'Ęé⨽Ó11 /"mëÁJŰ­ßć„ă<ýî–-Ňęü=´ş&6 eO\ŮĹßW*œœŔáv7cxť„ËLŇ.J¨Ť \gőąVĐ[ ęŮY 6œ4]=$PĐćű†gpyöŮhŊhďŢbĘÍíDcÜ.󹅛„žŰ ž­…·‘––*C”8ŹX‰_ 0ÍmëáôŃůďËa@NŃĆą°Â!>Ú´Ć LřN8!?úľYČONN.8ůdżuE8 ]´ë1łsŚ9ŰŠÄÄžó›äđˆť”Ú݋ý8u‹KˇÖű“7žŇK•(Ýß쾯Ž—ńŰożĽ§g=Kß,ţÖëýC´SN:i¸ĚK‚Žh4— ÂS#îYţ<TuccqBoÚĘóĂXÝrĚ9Rę´m‹žz&Ăľüˆ&^5Žž†Mt/qä[°1Ť˝´ňnŚwh˙A§Ë˜îH *u.í/§Ig˜“nM˘ěŒd›Ń‚ LŰík›Ë´wď^™x˛¨¨ˆvíŢMۋʨ@Ô{ë¨DtŰ朚qÚâ-”euQV|=uýîn9´Ÿ;az§Nĺl8ę!͗m˘ÍmÖ"žrYx‚7Ęké)2?÷É[RPßőď˜WžÂH *h×Cíş9íEPAČO„1s-dĚbłŐ6?܌9’˛łsh˙šűÓű‹ĘcăÎK˙źârébŹw7DÇ €ČŁě3cuŻmÝ•3îxÂh\&!5şPĽe¸’Üçy #Ś7uŻ]~Î1{Żó UźËL—áÖüąž R ŠŰŔČN•Ě1ך‰TXW.]€ĐéŠM|…¨mĆŹýf¸}ÎÍ͕ ŁkjjeN&ž&•˝ÎéÁĄCü0–”dót4e ´Ěk€7ěÜĚĆůĂ€xa'~@ĚßśKJIÖ옧m|q~óŘĄ(­¨WędČçQAťŢr ]T˘€ąÂÖďóŐ1㠛ăošCvöřńr?gĂçi‚ő×´ío 1z{ĺ›ÚŹžôĺ|e&ʧDQC&°w>çK‰skNň΢VƒsˆĽńśĹD`ńĺc!ď!ý}d˛Z‹îÝUňZÖ`yˇCˆ)ŐB/v¤SöŒž^Ii#UOpVűŽśL1_E•öZáŘꬄ¸Ç0ţDŒŻÍś\„2{Z 6<ám>ÁŞxŞŕ}vĎ OeĚ!ĹĹ%RĐ`ľd_…NyQS'Y"âÇą¸ř9; 5ÁwšŰ]ťv‹hRZ=h׃v( ¨D ˘ŠŮś‚ăŚyŃżÇěÚÁ4ĆĚ>öűۨłč‡ŹnTépP%‘éy WŒ¸ĂúłyuŒ?ŰáCŽó9ËOSë îXtLHŁ k˛č|ŐPSt,]Žví2Ěß wJ9ë?:\­_m7čĄËŹMőŢĄź´`N0âŠ?{ćcœˇÄ˜ 6}‚PúýŃś}´ëAťĚhó‚JKv4Œ´ÚgVIęˆ+œ cÚ*~ŰMůíë=ČxôiôčÓä~ł˜jEʈ) _ÍYW°Ťp"\_AˆŚ­‡r˙`…ľ/ĺ ĹVŃރÖNKÚz0ŸL0Ţ+ţö‡[ś@űBőbk h×AShmUťđPáżc$+şĐďď_ ×ď özÁě - ŮnpçFÂÖýĹTŤň¨cąH¨Â ąBsŰzŕ{˜{˛ӆ+¸ă]ę1bXąuśŹpí>A¸žk´4ĄŘyk§M *Ş’ąXâČáp’ŐÚróČűR:_čXö Ç"ł 3FjCąőpâ¨[R˜ …P;`¨C@,-[o f\ĆcfÇ#öęqZąfëÁ„úé÷é÷7—MÂS´6‚ąóśBťůᄯ<ՙ՚L-I°łPŻ@[ŚśśNÚp0Mľő@Ţd­ÍćBu %iN[•@ žĘěk°¤Š^Š´fbŃÖ…ú…jóᔥŠçВkçm8jŁ4(Ű9Ľ!gᎸLM I@E Ú lťlĂz›ÖÓ[÷%8˜ÝCżÄ*ţʉzÄ:Ń´őHŠ-m2œ÷Đֈe[÷gwÁŘą/›e T6÷ Vdçm‰6+¨0ŞŇá) íözŞŻŻ§X+üĂ6ËśË6L&[tMÇbmńWN_Ÿ€X 9l=ŇűÔR× i-śŒ†Ó.‡rď`Ż…:ÄÁÚy[ĄÍ *ĘŐ(!!QÎŤDŤR 5Ă6ËśŤˇe3šjëÁtębŮ&Ńů­ć˛őhŽ {í‰ÖfëŃG"Q îąJ°vŢVhs‚Šúƒé+&ţCj ˇĘĘb'ôŕśUśYś]Uë;ź‰¤­‡Ű™ié%ÔňK´„­šŸÖnëMiŁQb‘@vŢťí")-Çoq’¨¤¤$ńG.“™ÂSRR›TUUI[MNN–öŤÁôE$m]ŻH$˜kIĐéąLKŰ: yhŤśŽ6€Âąóś@›Tř§ŸŢT)ÜVŤUVČě†dˇ;(##ą+Ű\ł­˛ÍúSˇ›ĂÖŃY :Ě­˘l€śO(vŢÖhó*Œr!d”Ę]^^FŐŐU”••M‰‰ hYęęꊤ¤Xş ŞĘXŠŰzöl€Řś@űś@Ű'vŢÚił‚Š^áćľţŞÔnÎ@\PP@ VJOO'›ÍÖnćË Ľaťt:T[[+§VŤŻ×â-““S<ąž2öĽn‡c뉉6qmŘ:Íl€öl€śO¤ěź-ŃŚ=TĚ*d}’+ĺBčp8„˛śOźƒ .yŽZ˜ÖžC€X@_Ą6Ř!ﳸ+âdŻJŘlîz_•1l€Řś@űś@Ű'švŢVhIiőą˜ŒúƒŤ?:ŤlüƒĐWžź•0‘Gu†ŒńŃúĹsŠÎ t]Ř:ąl€öl€śO´ěź-Đ.r¨¨?¤1ɕú!+_őZJ€ŚŁŻPÍ*dc%ŽŞ [ ĺ­Đ>€­Đöi;oí´ AEaŚt˙čú •0‘ÇŹŇ5ĆG›m‡zŘ:- l€öl€śOsŘykĽ] *Œ™ŇmLxĹĘv{ű!ĐÜ3Gş"†­ŔÖhŔÖhűDŰÎ[#íNPQ(Ľ[m+Œ3 z˜Uź‘ŽŒaë´<°uÚ°uÚ>Ía等v+¨0FAý>@óMۃ­;ŔÖhŔÖhűŔîÚš ˘0ŞŰ€ćĄš+aŘ:-l€öl€śDo ¨Ŕ€öl€öl€ölĐhÉ큠4x¨„€ "TB‚ @ˆDJPÁ,@h DDĂvÚd7w™ěˆ5Ě4Œ°ôŒH‡ü@T@,QÍ"\…+Č}-EÄő‹h%ĽuBĐ2č5‰¨čMńPqqb Z‚`t‰°u‹Ś†üč ௠Nˆ>ž4ˆ@ÚEHDBPq™źÖ/θ8K DˇÁ˘ŠQŸĐÓdQ%AĹ8•P Š…ŒqJŽş:ű6ˆ2n ÂAóť†ŞwxáKP 5ĆČăbXKAĽ˛˛|=DˇĄTĚ´ =aĺY %äÇ× ]~ŽKAeýú?@”qkFE0ZFPX‚}ä-¨Ô/^ź¸díÚľ@„áľŇÂ|ô‚Š^Ťđ•;%”}9TŒÇ-&k}}ŢVyTřu‚{I-,,üWff‡‹ ”–î{­S§NˆÍJŇ%ިü).ň2  É[%œY~|ÍćCdž?Ĺé.<˜ńŤŽŽú4ÖXk›5Ԑ„VŻIčľ ˘ŕf˙ H AĹŕ˜Ůb ÷Ń/œŚ:33óNV LX[`AlVSC2Zý˘×(|éžđ+Ž„:ËO X#3aEMM¤ÜlX1Ş`Wœ ~ť‰j Ź%°ŚŕóŠ MkĐOŹźT̄#!{§Č2qN8^*f!?ęŐš—ň#čűIDATxœěÝœĺůđgÖÎ-rqw"@°„$\‚ťśhq(Š;ĽĽ…ŇB Ĺ݊‚'h€@p‰ťç\×ć˙>ďěĚÎÎÎęÝîíÝýžůLvvGvwfnçgŢ÷y])s¤ A€4 ¨UŇĐ‚* @w¤RËŀ‚(`'§‚,šŔ@ RŃá–Žf¤ňţźtŠL:,¸ŇQ ĽÓŰűý }ľw°Cmăôv—í`ƒ’iĐő¨˜ÖޞŹPRx=•y ëPSx=•yŰ]ś‚ÉN=őtÉO=őZťĘF"•ŕ‰’Âr‰ŢrSŞůQÔ$ƓyŢŽ2ˆH&€’LPľVşŽD5M§hi7™ L$ Ä{-•ŕJź× 7%“%^%•ŕJF+™F¤R;%ŐÇXď‘čuČ É&—UŰřoí˘˝ƒą‚vm Ź űe€Î'ŮŽÓ ¤$dą{ž6ľŸxMvUěĆ6ËŘ­Ÿ’xrC*Í~ôÇ é9 %Ńç5Ż+Ůej D2ľSŹăąŚ9l^wŘź×t^É&ŚľSô×bŐPQ)šÚ+ăyJÚZS%ŮÚ)ąž[sĹcyë{Ů=€Ü–¨Űdô؀9˘PdEľ,Ť&Jť×ZI7¨’ní”Xó¸žÁŹJ‚÷€Î%QrÚ ÍŁ9¨¤ř–XďiŚX-IK' ‘l@%™`Š>(–q˘č` ™^őY s13‚–qsđ„LăAËxŹŕJŹ€Kť4JľŚJź€J˛Í{Ě'ŮVĚľTěš@×c—;Ĺ\KĹ.  -V`?™÷˛6˙IŠ9P*A•t*Ö'NŠ Ś8MwčŃşŹBhúĐŐŘŐ1z°Ä/_č1`Ž,ëĆx?Ĺ2žV`Ľ­9UËk‰rĽ8m˘äóăÜšϘ0a܎……Ĺ<×ŕ`P­ Čć>Đ}ĽÚëőŻjjjřńÇY0s挏I Ž´„ő`Šƒŕq˝ Çě‚+ÖDľ)ŐP!Ó©ΗLs@EŻ•â2ťCă3gÎŹxňɧŽďۡϹ"ˆŇ“bA–­6l|N|fîÜšŐâĽfŇ)`ŃkŹřMăÉ$ľľËą’0ȒLP%QłŸDIhÍ…›ř~÷ÝwłĆ˙Ś@*8¸ňÓO?ýuŰmˇ-ž6Q¸iŢ›7oţż˛˛ň“ Mľľ5OöîÝűݤŐXá&Av˝IPŹZ+DiÔVITIĽ–Š]Ď>z0Eä€Jammí …‡@577˝VVVvi5VôŔJ€"“ÚZ{jsm•T’ŔÚ%§ŐŸ›§™ƒ+ćÚ*2!-×PA@Ú Ç8Ţ@ĄŽpH‹C˜ăćxQü†“îi8ݞuŹ]ÇËŠbÔRY¸páAhňíă w -°bî,GŹą ˛yž’xA%Ĺ×ô`Šž^sPĹ˝űîťWLœ8ńbȎ;püÂ˝›ăDŃľUŹ’}-ţŠ Vą|ťš)2BZdČ#†˘5k֞UYYy.dČŚM›ţ9pŕ€ĹhŁź¤ĺUážŹšUʉk‰bçVąÍŤ’nP%V‚ZsrZ=JžĘü~˙[č:2‰ťZvš\ˆŃZ1´RtWË枀’MXkTI7§Š.V×ĘMćÎýx**iřř㏧’} ťœ*isĽ0o˘Ź¸ązrŽ?v'€n+Pkk+ů|>9 j-n9NrťÝ”——'ÇŰjěX‡˜K‰{ůQMdy=ĄXA•D‘šXk7E2¨RTT2ž ŰáJSS“ ¨Řáŕ láů8°RXXŘŚŕJI‰ŒCđ ěâéRl§'SSŚ[E‰1ÍúšTńx\ƒƒÁ¤‚<ĐE´´´PCCCJËpđ…‡ââbĘĎϧt¸\ŽÁT!ŠĂP-ÓU›iśÚšSĹüŚćç9VD@Ľ‚ ŰŕZ'ŠTĚxY^G:Bqk•X̀ŇÖAëś÷ű@Žă*éDĚxźŽ4ĊC$Š_´Ë›$#™ź+íň!ŠŞŞ˘SN9ƒÎ:ë\€ŽgÓŚMôÔSOËÇdy˝^zńŗ觟~&ČΡҖ*Vź.^gš’‰M¤ťHĽ÷ŸT´[÷D‰p@ĺüó˙H˖-ŁqăĆd-vŰmϘÓ_{íeŞŹŹ¤Dîžűü8ĺ”ßŃŮg˙Ávžü͞ý­XąŠŽšćJc™c=†.žřBŰeŢ}÷=9߀襗ž#€Žjʔ锎ůó?ĄLh*vë,))ĄYsžśťśU”$_ˈęęjşŕ‚‹e@eȐ!˘ŕt@ö5Š<OÄkÜ-b{9ę¨#CG$˝ĚŽťNĽĂ;”&OŢŢxM/tžřâł4pŕ@€öĽw›ÜŢxmíˆ'ŞMY{×TÉj@…k¨,]şTTţůĎ{ŠgϞŮwË-7Šóń`ʔqăĆŇľ×^“Ň2t啗@W—Š'éHPŮ˙ƒhüřńtÝuWSYY™|­ŽŽN”%n§ďż˙ćĚy#îş9°ŇFíˇH7§Š]ˇĘ¨@„… żĽŠSgĐ{ěcäCyä‘Çd‘3Ď<›T5|c¨šš…nźńfÚsĎ}iß} űďŔ˜ÎÍxx™{îš7bý<ý˙řxŕÁrxŕmŽ?ř`Ž\ćä“O•ďmŽ}ÔQÇŃ 7ÜDĐž|>_Üé|㧟~˘+ޏ†jkke@ĺĘ+˙$*ƒ lÓşS`ÇH+ŚŃž˝˙d*ÇöŰoGłf(&Íôď?L[ślĄÇ{‚\.]}ő•¤(á"ÄóĎż@Ÿ}ö9•——‹V==ńēôĆłăŽ˙˝÷ޓĂŕÁƒŠŚŚ–}ôqń>E͗ŸŸ/>ÇĆóI“&ŇvŰmKĐž%”˝ő֛¨˙~´bĹ XáSzôéÓGÖ|mËşSÔ.qŒL%ŞÍ˜‹/žLT†.îLýzôčAĐąŽ=ö„ˆç;í´ÝwßßĺřœKŸ|ň ˝őÖŞŞÚ*ťE<őÔßÓ°aC#–:t(=ňČ(//OÜąşšćÍű˜>˙|>|đA1ߗó¸<őÔăTTTDO>ů”ŹľňĘ+˙Ł?üገůJKKeó!NvËŽťîäT€.#—ŐƒÁ¸Ó{őęEwÝu;]~ůU2°Â*+{ӝwŢ&+mYwGhݚ*YcžŁša̘1˛ö‡>Œ1ҘĆíĽšWžťôŮgóĺkTąÚa‡É˛F ŸëőZ$‰z˜2eŠ ¨°˝÷Ţ[>r-—­[ˇä&ŽąęńäĎ9š˝ŰÝéę|HîS˙őŻwÍÎ9çş˙ţżËHtœ›nş>n˘Ú͛ˇD<çÚ*ÖނĚŮüq yš”¨ÖápÄ­QÂ)=ŽźňZšr•‘Ceőę5ň5ŽÁ‰ćă­;×tşš*źšŮψ#ÄNXIçw‘lŸ š‰ M?ţ$•——Ń '/_ťďžR{řüóĎŠĄĄAŽżýö;ňąŹŹ4ć =Xăóů Ú_˘.˙ô§Œ€ QxŕqŹ\sÍőmZwGčtA†Ŕ @nůӟާÓO?+bŕs3÷ÎsÇwÉlý'Ÿ|˘xý\yýő7č›oR[ůý~:ńÄßŃŮgŸG>řůÚQGóNրäăŐW_+=Đž¸)OŸƒA9kłđ<|á€JgŚčT€Œă`IŽöâ“.UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TœŁŞjÄsEQ2Ű =Ş@‡ł^Ô'3ţéI´­íćÁś°‡  t˜d.đ-‹ ţä`[´?U C´ĺ"ßn=™źŕoËgíČ@D{mcóúXCP˛.ÖĹ~˛Ať űśWÚ;o˝ŮLÄű>mÝÎŹhTŹ˛ť O5 /€b^—uzŚ'ŠĘT %Ü4ÉĚoˇX@P˛ČzQow‘ďőzÉçóQ0”ĎšÝn90óĹ|˘‹űö˘´uÉ2đ‰ľíy[ŰmoÇ5o*Ű ;@PrB  [Şčőď[éӕZ[LJŚJJ4}Hš”G}zőýLż oϋűTÉö“ =é˜?ƒ>ÎA”dśˇÓé$°§$ńşbzŽ;Lúŕ ŽĐŔˇşšzAš×ë›OĐ­ĹŤĽâ÷űéÇ%ëčΏܴŚÎ>Î7¨ÔO—ďćŁ #űúÖEŞ‹ön.c'ŢgĘt€%Ö6çV*ŰŰĺ ĎÓÖm-{Šx¨ƒO ^1řCC 4MƒjzÔ/ŚĚăd—Ё¸ĆÄÚ ›â^ŕłŐbڝó\´fýF#8Ls"+žGâMłÖî°üš98Á!~ä_‹ˇlŹ÷Ëó6ămxÇźdśˇ[î˝iDBóČ:ó~SS˝ős@\ŕçËל…v⡑•.âٖnöÓ×+˝Š`@˝›ćüŇB'–7Rqqą hp–——'kT˜›ńôÖÖVůš>݌§ˇ´´D,oţ|úňŒóŒŸx˝ą‰Z›šĹx€ŤkKL/(- üÂBš}]úňůůůQ5>Ěëç÷×óƘ?ŸyşÝç5żƒy:çHá鍍r{Ż­÷$ą˝]bŢ:Šź‰ŠŠŠägF.€0U CqPcŢŇđsžŔŸ40œ$U˙ršřh™JGnß"Ÿţ˛…Ţ^V(_ßD M×KřŸƒ ŸüĚÓ ˘Śëďk^~żáŐ´ëŘčéďŽ(&GŔOťĺ˙@=šŞ¨Ľş‘ZZEp…(¨8)Hń¨ Ş68ň=TÔłˆ*”Ńw}¸Ž"´ţš~ŽŘ˝żůóqĐBűü›iÎRíó0˛ZLďm|žxÓíž??^?żďG˔”ś÷Q“[dP"Ąůd\ź&.~€65‡khp ŤQŚ×66yä2555ô֒jđ9ĺđ֒<Ş­­5ćăń9Kó#Śó2z“žn^žƒ<kŁp@býşuôĂwŐ´ÝŞOißEŻPţ÷?RĂҍÔZÝD"ƢTD %´q§XVĽ­ëiń‚ő´áŤĽTXˇ™Cëç÷ŒőţćĎĎÓľďţüo.ÎÓkLß/zşţýěž?óôtˇw:ű ŤCMČ*ť<(‘9Hl–‰Z^ŤiŕčFčÖ.ü#›Ľpó—Čé‘ďi]žƒ)›ÖŽĽ­ ŚćßVДŸ ”ÎPŕD1jĽp •€ŹĽâ żŞ­ÂÓřŃ аÚĺÔŤĽŠV” ›póť÷˙ůýbĹÔt*zz*ß?•ímM€4¨ŠBż°wšœTáj2^çœV‹7†_Ťp5’Óé ˛˛2ëü…ÝźźGm˘ĄM_Qý‚oiĂc/R‹Ş›[#(‘Í|ó ƒ0ćAd } 4śęgŞŠn ŸĎ'?C˘ĎĎÓÇš~3ŚoăŇ>ż.šéćď˙Ť|ˇoĂTś7ď#ó>ƒô<đŔżiß} C=‚ćĚy‡Ú[Ś×ŃPS:ç™XžœŢß\*Ÿs’T6˘ˇvhňE˙7ŤźĆüĘŤĹ2•2wČaťŁ?ü$kMLœ8ŢČ7˘'ŚŐ§Ëĺ&l#“ľęÓyüéc¨rţä^ˇžWŐQpY€TQ—Źi˘RhŕqŚPě€JŔTcEÎŁ/ꅜăß|ą‘ZČCیč+ß˙Đciď?ËĎ4i҄ˆĎĎÓß} }~ó÷c<o:/Ż^Ÿ>ƒ:ËWˆí]–ÔöžXÁŰťu´ťďž‡^|ń%JŐsĎ=MC† Śś:ć˜hŐŞUĆóĂ;”Žźň˛¤—˙ä“OéŃG—ăuuőtó͡ŇäÉŰQee%mÝş•fÍ:4bţ+ޏ”?ü0JVźő@ć ¨ް°ößĆEß~ZO[ý%˛×N’Ş'J5ë骣ˇqĘe8PĐťwoÚsϙrš]sžžÇťĎÍ5-8akkŐVÚFT‚k7’Ÿƒ"W8ˆb¨ŢôG‘Á9„-րŠšv‹ąžĐgŤoV鍍䧍4qxĽńůôĎnmVÓŤW/ăóÇú~ú÷ˇ~żXߟˇÝ~ăœômu2Űť^lo—\ÚfýúőĎšŠ7ľ[Đ#Óë{hţŠƒŰOOÇ ^,/âcဠĎ3i¸ˆ „NϓbĚÓuœ°u˝¸łďćRVŻ ĺ1Ő*‰¨Xƒ,ŁÖJt•płŸ ĂiĘǃK卵tď§.únÉŁ;hťďaëűŮ}WťďŹóśŰnâ6b[.’Ű4ööŽ—Ű{[1/ň§´ÝôéÓŠ¨(œ:t(3šÚK2ëß{ďýhʔéĆpĎ=÷´ jŞ@‡sš\tČžÓ¨ü“ĎčăՅô[c%ŐJä´rG=.ÚD35ŃnÓ§ÉŽ”Í5:%M5řîý&qGß÷îťä^´ˆüÜĚÇÁ,Ń´jЍM€´ń`(!­9ÇJŔdŃk¸Č`Mh˝üIËZ6ŇmóúÓUęzÚnT?ŮTÇô0îtąňŸđëź ŢGlďO?ˇÝŢcŠ7ŃôM´űŒirß䪂‚‚„ó8šęׯ/=ńÄŁ2×I~~|đAFs´Î°~°‡  dTźäŚći|ź÷ž3iĚę5´nÝZŞŤ[*_/--ĄţýűŃŔÉétF,+a×Ă÷„łaéRrÍ~•Ü›ś’?L‘ÓľĽIŤĽBdÔZ‘%r5R•pó­9P¸śJD‚ŰP0F{íýxTúžÁ)+…tĽŹl?JËą˘÷ *Öňź˝÷Úcwłf ­]ťŽęëľí]VV".ĐűÓ AąˇˇÝ{tDm–÷ޛńs]˙ţýé´ÓNĄLÉôú ‚*5áî€í/ô‡L*ĘAŻWËńáńäľ%ŹďvĎíޏ›ŮlüéĘőeRš[d 9]ţo Ź(ÚzŁ9éuŁ Š9P8‡ŠľĆŠS ş„ćך•J¨žjZK莏 é*•Ńýe ůNŚŕŠţ+ŁëöhĄeŃM52…ˇ­y{ó8ďƒÚš­Tůš›ĘĘʨ¸¸ŘX&WšM›ś{Üé—^z1uԑĆó /ź€>űlžQ§ŞŞZF8˜ˇuk•1çń9ďźłăŽű믿‰;…Żžúşü éŕ€ o[ěps,ŽcnÂS[['AÓĹ_˜p]§žú{Ł)‘Ő)§üN>öéӇ uŞ@F$j:ÂÓ7nÜH>oł œ8ÝᄣłF7ÓěE˛UÎŹQM”×ÖÍTöě#li!r¸ČîŇ_ ńD|MŸdž[1żNlkŰłŢ$("y­ZJN›TÓLtˇytý^-Ôˇ${MoŹŰ›{Ěq8´ýĄŞŞŽÚB ňÂ;QOKš\[…óœ|ň‰ôĐC˙5^{ěą'e@Ďěěł˙@ סĎ>{Ńi§*Ozţů—dÓłü‰ŇĹÁ­{vŢy'ůüűď óĎżČ膛˝˙ţűôÇ?^p›Ÿyćéň‘?_CCŁńúąÇ#ż+¤9U ㏾TřŽ;ç‰đű[Ä]řčŚ.#+|tŃ.utáÎu4˘ÂOŠRš›ŠüůGÉŃŘ …>Œř„j ŠŞšž‡–‹řĐ6Ż‘5ďJxk2Ű š ‘ź6”_Eq‘OľďľŚŞYĄëß/ ľľŮűӌˇ˝y߸EŔ+ŕoĽ 6ľ%%ÎUT1'yĺăpÓŚÍĆóącÇŇa‡šp=••˝éú민aÆĘdżœłeřđáóTWWQşöŰo# Â&MšH°Ä<[ślĽ•+WtU ëjkkE@Ľ•\čWQƒTńúäŞŢB ™'Ş Ž„ęŠD.ŁżŚFżŽ ­Cľ ˛(á5¨ĆÜz.˝ĆŠĂHZëwhCĐťv^ceC}îÔúŕÚ>oŤÜwš‚ƒ#ń†Â¢¨eňňňd3 X.ťě˙â&§Ő7Ö蕊qđiܸ1ópNŸtí¸ăŽQŻMžź}ÔkÜ+t4˙vgímĆüČšőőuävľ@…•|úĺ­Z˘ĺ; ľęQsVU6÷Q”PŁŁé)řôyőHŠm"KŽŐôhÔZQ”¨Ü*Ţp¸ĆĘuďĺÓu{ľŇŔŇěĺX‰ÇívČ}ÇůU8χ]n•l6zńĹç´|0)Úi§bN;v %CďŠŮĚíöP{áź.ÉźVW—zŽ!h?¨ŠYŐÔÔ$+ތ\x{Ö-Ľâ…ó´´%Jd×k¤ŘÖTQíkŹŘ.ŁRDFŠč(R8÷ŠîbŮá¤Ć–ÄÍfj[şőĂěĚţóŸ˙Üöüó/P.ŕD´ÉźVZZJĐqTŹáZ œh3QëŠ%Unş÷‹Rúť–Tť)ŽÖfęůţ“dŠx5N˘ƒ+áף›ŠśË‘ůuSs ˘Č Œ•bӛq`eKJŽ@€ŠjRčú÷ňhM]ćţTSŮŢ ă}ŘŮrŠč–-[•P֌.[ślĄŽś`Á‚¨×žůfaÔk={ö$č8Ş@ĆŘ%3őűävĹżpŸ˝¸€ęźŞÛb<Ľ_˝AŽŚúČŞ%˛Ł5éŕŠ>]‰|Q,ÁEo"cšč&EDJ€üMb;řľ!QŽąrÓű™ ʤ˛˝9ą0ďC]gKXűç?˙Ev/Ź;âˆĂi›mś1žs-œüăŸÔŃŢ~ű]úüóůĆsîýgΜˇ#ćéŮł 2˜’e­Ćݙ@Ű § ´ŤdşR椧í)oă2*^ň…–46ÔôG %R1šő¨•GĹ‚(ŚG›œ+É.g;.bĘń Ržˇ•܁`Dł"żŘ&jœ&QXšĺƒ<şnĎVę߁9V8‡I2ű8yUöŢ{˙„ó<őÔcÔż9΁Š… ż5ŚqBړO>–.]F—^z…ńúœ9ďČ€śŰn[ę(ÜËŇĹ_JăǏ—,Şč=/éöŘc”śsQQŐ×7Ďßyç]jmm‘ă\pUVV¤5U +RŠÉ0kt3•x‚Tš¤YŁĺďPŠü›WÉÜě'2Ššöˆ9ČbjŇcWk%NmĹf9‡Ít 8(hS´!@u›źF-nä ŽۨşYĄŢĎk÷î–SŰŢa];Ľšš9á "´(÷G,ĎÝ÷ë׏ŚOŸ&ťR6ťűî{˘‚Ů4hĐ ůřÓO?ѡß~őY8iíi§ýžR1q℈ç܌ëÝwߗÚ5k R‡  䜑>şh—:şpç:Qż›œ˘U ÉS˝:ÜÜǔqÖ¨IbF¸vH0ô(‚)Q8čᰙŽT‚ĆúőŠ6-LqŠĄ8裪M~D‘=¸âŠ!q`EÖXáî–ÚŻ&H*ŰťłzřáGióćpŽîůŒ3N3žŸsÎ"ć_˛dIÜÜ+™öűߟDcĆŘ÷DT\\DwÜqőčуRqÚi§RaaĄí´ 6¤AČŽŮĐŽľÄşJ~Űž†ŠC”Pł=’TŕD8Ńç5OŒš(ú˛Úkü褀ö ¨đPĐĐBNŸš†J0˘ś XÁřۈť[žńý|Úؐů&6ątŚDľ+WŽ˘çž{>â5nŢ3`Ŕăů.ťěŐŐňż˙ýUUUQGp:]âý˙I't"UVö–]Xs3ŚĂ?ŒžxâQšž~ýr(íS˘pýwÔëłGIő‹p‡OŽ>’Öń ę żĂE~Ĺe<ŽČ×ÄPŹŻ9ĂŻ™—‹XÓ2Íi̐Ë;ĺxPŒsΔú_šŠśE|qAËyT|ĄGżË)_ó9ĂÓ şIęU¨Ňő{ľReqv›ŠUőë×WćóĐsz˜ÇőçÉăqO5$ŻÉ+h„† iPMú…­yœ,ăjŞ@§U˛|žŢł6ű‰¨­’  ^Ă$ş OdM‡´ŠĽbnâ™;E—ľT‚Şhö“ˇÖoÔJąÖPqůšVœ rzliŇrŹllD # ÷Č9KŞÜ˛k_rUÎůaĺnÚLůŐËľ1=Ŕ"G#{ᑃ˘=‚ ?wh%şˇ‡˜”#¸˘š+ŞřÚŁ¤đ;q…ß\Rô°%żÝ"îőÇȟJ”I1>elČŠő ËVXšYV¸ĆJď˘ôšä$ł˝ ý´řTZ°ĘK?ŹńђÍ>ZS ŞĆ 5{Uę<Ź3‡ËČ…z9h`…“FövÓānÚq°‡ňݸĄšAȈśäܘ-.đë˝Z /ö/Ü9ú"żhý—"`!ŢĂĄDvĄĚăâ5YCĹO8˜â0r őnő‹)ŘÂA” )OJ0`qˆ JИ' U-¸ÂyT8ңʚddTŤ'ɕU^r;Ć‹Ćé@ŐkӄżŸVé&üBźŔĘćFÝđ^>ݰ7VRo ”ĚöNFśşRčŹ>YÚJs~lĄšżľ xo›&`jňdŔiţ2/ŃZyć˜|ÚB>M‘GšA蔊6U3ŢŘWżjމ°„k˘8ä2zM” ENӃ.Ş °(Fm§  hM|HO+kŞ„ˆ‡[jżo&ˇÜ ľČ PÔ¨Š`QĂÁžîs:cnn tŁQcĽăş€hďţŇLOŮD‹6v͞ł…KÇŠ€Łű¸č„ iŸqБSr7A)ńŠ4/HłF5EMwykČÝźŃ6Šľůš #'ŠjĘ­bɅ˘ĺKQ|b Έź)ˆn“­Céz/ę}áü)–î”ő.•ŁŚ‚FŽ=ßJźz ›şĺƒ<Ů;P{noHϲ-~şäĹjşáő:TÚoOŢŽź}y;tÔTœĂ9=.Ú%v”üÚEQÍ{b5ű1żÎ]GäH17ńQÂ-_ŠŽ­b›7%# +F¸˛Äç ­ß֓ŰáÔr¤DŐP “ľUôÜŇŞ>Í\[EĂMÔÍl64hÝ-_żW ő(HŽRi˘í Š{íťúó;u˛Ź ™ĂMƒžXś•.߯ŒŮ6Ÿ˛ AčtňVENâ;هÇ)`ʧbŹČ|)ŠQ;E ĺMŃň¤DçMу+2˜Ɵ˘ľÖ pÄt˙‚:rűľ„łASđD°č"š…1ŠjZVëSBŻ™ňŚ8LyS8üÁÉhŠřwęőHԀńyjᚠmÝŇ$Öď&—ę˛  ˜ňŠšVT›*á.ŇÍÁż+v`e]CćXáŔJBV˛ĺŻďÖŃK › ˛YÍž ýßŢĽ-Ş@§ăôVůRĚ™6HöÉkyÜŠ’Ă4Ő@QLÉgĂľP´`ŠT ÉhľéĄŔJ(1­Ö§s(˜˘żˇPÜč ­ßm–™ű…“ĺFt§l hěj¨PD óźÚ˛œź6č°ŹŹŻwĐ­ŠŔĘ^­T–Ŕ @Śq T:ÖKß4SŰ+5Ş@ÎYRĺ–]űr€“¨rÎ3§żNFŔˆ[3Ĺdည´ÖVћňDUŒ)ĄŕŠ6=ę2Y ˘5U‚üL-yÄó|ĹEŐ­!%č$G(Čäć@bÜ%ă/–|*Ą YşTލ­bÔP‰ÎĹâçOç°Ď9˝Ć¨ąŇBĺémoHŒs¨ ÉOnŕý0 Ü…+čýrÎlq_çuP˝řbßJ!_dĎ>œ/Ĺ:î s@ŘîT<*‘›×Í˝úhÁý5gŒž~řÓ6˝żŠ_Ť˜ĎGŽ ވqWD?úx¨÷Ł7 Đ¸ÍźÓýÚ4g0v7ĘkE`ĺÖšůTת¤ľ˝ >î}†“ŇBî¸ëíZô Y  t:ÜóęPCľU˘ƒ(Öqs@EÝ]rŔŇurdˇÉNť€JP{Ě#•š?ZMÁĆĆPĹ'>˘Ď¨˜ÇÖJŔ.€Œ  đkލޙCóbVVŐ8诟ä´żűçÖŁ—ŸĂ{ƒ÷ @Ś!¨9‡› ”x‚Tš¤Yٚ˘ŚÝEĄ.q(a@%ŞśŠÓT[Ĺ&âŒ ŚčA}žĐ F,ă'ŃÖůkČ_UGJ0™, kUS—ĘDŃ}ÖPŇ[îrŮZ őűőâO~{Pr_Ÿ,ńŇOë}´Ş*@ľÍá`×W+˝´h“Ÿ÷p҄~nš6ŇCŽ˝<@Çůdi+-ڈźšŒ÷ď§é#Đ2ˇAĄÓi)#kŠh=Ťö j‘ăĆkzS ›f@NKs =gJD3Ą`¸ ˘:¨öÝo)XU™ÖŚŠ#Fn%4Ÿ3čךđÍ{‚FZˇĽ 9Y­+4_T.–ĐşKŰŢľuDž u:÷Ďk sžŠśM6öԗôçw“o/ťľ1Hg?]MëjÔQ8 ňšôě‚&úa­/" ˘ă×xÚ3bž7Đ ÷@W7çÇ‚܇ý™„  t:ÍĽ(č.ÔÚńÖFT,Á#ČâTŁ/N˛öň4O‚F"Zs%P讀7>%ľĄ>"‡Šý¸WjăŽ`t Et,ůTB—%ĄmT>s2[K0Ća ŹUE:gţO|Ń(Ý§Kźôë†äk ńź|‡rG‹OĽy‹p~î ćţÖ"÷@& ůäœ%UnŮľ/˙ěqUÎůaŚ:<ÔĐs •nü@ÄS´ž€dĹnNcjŢĂyTěňŠpí ůšŞ5ŠŃ›Q¨ůżŻÖ(”;EžŠöt¸¨aÉzjüi)Š‹ˇ69îDŽSx\ŽŔ:ŽĘÖIŽĐ8?qŤŽĐ Ş)׊)ŸŠ‘kElD9żŢT(Ô(¨hS›|Jř %ą˝sĹОNZą5@s~jĄƒ&vîvą?ŻO}˙˛ŢOťBľU€\ą`•ˇC{üń¸úäŠţrü˜6ŠrRÇ6Cşlżr:zÇ"zöËúëťľT^č w.î'§íő—őTßŇqŐny/ńţB ČU çĚřő^­_ě_¸sôhmĺ,*Úúš‚MĄhB8JD@E YBůh~MŒs°Ĺá×Ő:ĺyQ %­5bržfżB[ç~Aţşfrˆ€JPAĄ$´rœ´÷WŁÇNpŤËřeÜ0çH1P4ůTB1EŐ ËźÚ˛œź6čPČTRŢŢš`@š“z;ePeň`ő/łOĆË[ŕŸ[čŁĹ­TעRŸ81Ÿ&ňŘÎĎÍjř¸A6ˇšxĎ*đ(TŐ ç4ÓŻĄ6ŇŰtÓą;R‘GŰvÍâNÇK ›čŰŐ~Y˜ŐŰE‡o_H}KWţ㤴+Şâ7=r‰Őě<ÔCŸ/óáŻĺ˘ ÄË"y-@nřaM×ĚSˇĂ<ú×I˝hs}€fÝťş Ţ_Ş@& tRĐUHUƒN’Ń5Ô (ŞÉŠ;ĺ¨×ôů8´č¤ˆÜ)áć>AYĂc뚍Tőú;¤VoľÉ•â1î‹lęŒ˝Œ]łĄ¨|*QM|‚–î”MšXôů,šXœÁ ĺ9;gŐG݈o5š€ÜâŽĚ_4QŹCŻßLo‹ ĘaŰЕű•Đ.Ă<ôĐ'ôݚ莚‚Đß6Š J.ÜŁXT؃7’_Lťj˙RąŽRÚ$ //Ô2űóŰţs^­‘sv+˘Kö.‘wŠîz§Nq߁á^~ěr¨˜2Š€Ůś@ŢÂŻń2/}ƒ.rŒÍHţߙ`AŚ Ś än‚2{QŹ|2kTě.ęšĘ'SM˙C¨bík2áX¸9ěbŮÜ (TEÖPQÉ7j­č̀§%TœŽ`lóď(îŇč5O.ŢŤ„ÜNmë.Ţ觕[t를T’ŻM?ej]őj-}šÂG{Dď69–ą}Ý´×Ř|şonCTrڟ֣0+ÖTw\Ň{;zs›&ŻJç<š…Ž>°œ†őrŃRL¸íÍú-”Ď­G‘ƒ.ŘłŒv‘O% mŹ Đkß6ŃcŸŐÓ~ă éĆC+ä|˝Kœôĺ5čÖŮ5ô귍ԧÔIçďY*—ărŃ2ąŢ'ć7ĐűżtŽ›>šśż ë@Prçô¸h—ä.kűěOW!őXńʈE(Z€Â<‘Až8UMM~,ý5™$ĎM›DŕĄîç/)X×*ťlvxąŠ uČ*j¨ŠŽQĂăĄć=ᮓcŤŚf?j¸fŁŠPx\RM2LŹůT"(azS!—“¨˘@M{{ç‚é#=ôՊVzőťfŮ,Çlc]Pě•FWFţ´Ďš9šv˓_4Ňršbß*ÍŹ´wŔřY3ĺűľ^ÝÇE“xhH­šŃĘŞy*]÷F]Ä2͢łĽ!‰“ľ%2Ć=%ßxp™ŹÁ˛tłŸNZHď˙ڒR"[Č>Žéš‹ Ešő–Ă+h“–p€e\?ÝuTO:üţ ˛ŘyŰ=hňŕ<dy˙W/Í•OçĚ,•|ťĘKëkÔ/ÔĚzö÷M´ŞĘOEy =zjoęY,-Ë[e™gŸm äş.zf+Í_–ű˝ëäęţ‚ÎAčôzîFޖĽTRý•4zeÂZĹIÉhÍůTʉjepE<ŠéQL5-UÔź|!ŠÍA”Áqá*2K >X#AX‘˝ęˆ“!›q5<ލZSó8? †ÇyšęPmĆőš4ڟŤ  ˜žD×P1QM k…>ĹÚE|gĆ˙¤]Ščć7ëčšMTQˆ¤Ň°‰ó˘T–8蚯›čŇ˝KDŔ)źa¸śÉäA.TńÓ˘M~zűçzůÚaŰj ršĆĚĺ"c•—Ä/ęř~nZ°2܉ 7óľĐ™Ó imMj›Uzíűć˜Ë@nhÉáű÷žW+Ë+\ôňš}ddh/ˇŹ]2şVžxř“zšű[3=5ß%Śšd…ƒ%7˝^mäTšQŒł|ˇB׿V-oD˝gŞ™rŕÄBš62ŻSUř@& ¨]‚wŔŠTü5úߥ<÷*j"ňƒÉh­5T|â ¸Áă˘Ć@#ľlř•‚k›(čqq~‡ř'Ę…kŠPčÂ]WT/ľ`T%Ü{Oä8E6ď‰WŁÇCËhMˆBăbšK&ŻuF%ŹĽˆô)jd2ŰĐřČ^r…ÔŮq0dք|úßwͲ‰áć:œßd‰„T–„›úđóNRLďŒiĹňŽËmsęé鯚čwSŠäëÜäfĽ¸#3XŹwćč<9pSŁW6Ë Ę ąž†Ö L&[fJűýZěř'•óÂ,ŸÇœW…›,ą&ПߩwŠ˘—ă÷:rrçîő˛ăŰŐÚ œ5Ő~jlUe™§0”;šéˆÉEtçQ=hĺ?ýşÁKŸ,nĄ­qjÜrwÄŤEůˆƒ(wكú—šht_-8ăvvň;vm„  tţAçËGuíC$c入¤xˆŤäBŹ( ŐçA“›ëÉ_ˇ‘ÔŚf 6:DpDŃjĽxLľRx=JP>çş)s-%ôœ§řBÍu(ԐĂn\כúÄכ™› éÝ0Ě5Tô€‰M>K =Ŕ2˘O×ů“ßg\>}˝Ę+›ăŒ3ňD@…óŹźüm3yÄyž{úy˝Ÿ>^ŇJgN+ŠXžkq-—3Äë˙ ž†ôtÉ.‹šůĐ}6ĐCÜb]ůňŽ×,é_ŽcÄ6&ćý×G 2ČR”ç ůË[ĹÝ Vşţ 2ŁŔ ÷Ţ3Tlž[9áŔĘżľĘÝm‡ŰDŁç€Ü‘/ĘM^ĘIćň„,OšnËÝńV }ž´…ŚĘ—Mƒö_HűO(¤‡6ĘÜ+v†Š˛Ď#§Vʤţ/jĄ7ÓĆúí>:Ÿ:‹‚?Ş@ÎYRĺ–]űňĎ?'QĺœÉŇ+rŽýˇxRGŞ_Ë{Ą<ၸ6Џ˘–ľQ˜jĽ(áZ)z-Y+EŻĽ˘hĎÁ1wKÔNWJHŤS¨g"ËxhžXM}ĚăÝ3+ŞŃ łš†Šb[C%LŃçăc)íş˝;’Sl˜“w)˘;ގĚmr¨tä‹ŕ ×,ŠmQŠo‰ƒN“íbtŠĚAN~űü×M4°Ü)4œ˜öŅMôçwëĺ<ăú¸é˜ľZ"\Ű弙ĹôŠÜü÷ó&jj ĘZ0źLďâä‚Űôw‹ JôvĆŠ•şM_ü\äNřÚäí\ÉO Ü 0ąPÜ,rĘŕ ×ĐĺZ+WPNÓFj˝pBä2{Ë“ƒy˝˙ˇW ĹÂ’v*ĽeÚ-\íK:í¸žnąL@îŕ›*­Gî)ńÄ)Ĺ4¨Â%{:üe˝Ś„Ęó—i͑×ŐřeQ’{ú÷ďzË^ś4h5lwOîU&żű”á‘e­u~ů¸˙„Ú ĆŸšß sŘqšéîŁ{ҟ^ŠŻwÜöâĎ  ×A—Ä5VţńVŽxÄcž\ˆqů<_מ;ň´éá!ü\ŸG>š–ŃÖ%W€AŸˆ…„†˜ăŢđsóx˘eÄŁbçén€\bp´ÁÓBĂNŰ"ÉiŽp‰¨Ů3‹éx˜ánžËlšőđk<ƒ7ç‹ysᄍěÝůĘV\ ĺŒÇ6Ë^}ˆŔĘĄŰŠR =ňi=Ýů–Öô‡ťXţë;ľ2QíÄU錡l˘‡>Ž—ůYßžˆď'Ę`‹Ů˙6ÉfE\Ăe1ň˝îxłFŽkéŽěӹۍ3î/č”$^7ˇ&ĐÇŚG}p†Whŕşö|ä–{˝žů݂Şçg÷ČĂúőČĄřăŽcIľ›f/*Í,fj˘~J—kő?ľŚ@RœPźZ.NL”͂ڣůšOk.~=źŒöşuGřŃᢠâ&U AEŒ;ôqˇœ–Ň8Ż'´žXă~§“|⪛ýüčâçĄqńč,rŃY—ô"ˇ[ióöŞ.ę×ŻŻ˜_‘‹őÉŠiŇKß4ӏ뵚+EÁăˆí C ‡}˛´•ŽxІ s¸óČršŽšżÝŽÇăž"ř• ڜÉĄ!hTÓc8ed'ŁQ öŃürçô¸h—öi‚˘5˘ČŔ 7Íń„rŠ=úhIiőÜ)˛ůOD’Z­ÉP¸9É|,˛ Qhľ˛ ‘69|>ů>j¨ŮŽ–+EWmĆ)˛ŠOTłŐ7wĂŹťÚ´ˆ|*j8aí„IEś֞ŰŇĂÁ“Ó-‰t ˇí8ŘŁ•U• ˇq)˜÷@& ¨]ž]ŽXÉSCšS˘“ÔʀˆœĎ.I­šťĺpp&œŤ%œńúBAíD9ÎďęČWľ`MĐ­­ńӓ_4tŹ“v)’ű TnĎ7ŕ ƒäY˙pÄë/QňbtLń’ÔF&ś5šEgÄź>_(šŹDŽšýú8iăDĄŽ“­ăjÔ¸ęThäicÉjöÁEž?dÚ9ťSł/H/}ÓLĐ1Žœ\ ÷@ś ¨ xűŸMj @y›œŔO8ÂTK-ĎcŐJŃóą użŹ×eáŔ çqqhk×ňŁčăŞÍ8iăZŹ&bź˙q¨hX)@Çřż˝KŠŔí@•Ŕ5TPlCPş=˝&Gsżłd+š‚͏Zf ™;ŨĽbIRK‰m­IjM‰m)N"Ż‚âÍĄdłr<ÔÔGë.Ů:Žuě†Ç{8†zĚdűÝ {řÂ~@š‹îzťÉkł€KźœCM~ # ¨9gI•[víË' N˘Ę9?2ƒ<4÷=SVT*ÚňXÔ<œdVÖ0‰¨•ÂcŠŠVŠéyh9U‰Ń„ČœńúI 5ű‰čHŽŤ6ădŒ—LF˝G˛ĺQčť$Péˆí ĐŐńţ„.şn=Í_ć%Č î6™{ůARZč(8ň çĚřő^-$ÁűîœŮ‹|s‚‡ŚĘÓe.’⭏GĎë6RцkĽČ zv2ĺNą625! gäÚĚÁXq¨ZSŸ #”ŻÖ:Îësčă*LH•'ďő=’ Źd{{t|Ą˙—Ł*čÝ_šéé/›hŃF?AűÝÇE'ě\HűŒ+ €Ž„  i‡ˆTpÂZ~lě}:gyĽâŞ'˘çĺŔŠM--Đ/Im¸VJdbŰČŕŒę =áÜ*ĄŚ>ă<9Tk%oťĄTń‡™¤8Ĺ'áĎápßMr_řóđÉŇVšóc Íý­͂ŇŔĽŰ™cňi˙ ů4}DäU çp”Ů‹ dS–Yٚ(8ÁľSAjč}šl^SRődÔüŠKMP+Ŕ¤–LľRHOR›  ‘/ÔłŢ+#zź`×qTrę~ärťĺçv8”ĐcxHFGlďöŚ6ľ‰AmöjͨAƒ4p '¤#‹”Qa)…Ů)´ÔˇŠŽ…¨ą5H­~•üœ„šƒw#˙]¸ÄßVžKĄ˘<•ć•ä'÷ˇ`ŁZ|Ľ´`•—~XăŁ%›}´Ś:@UAjöŞś<)đ(ÔŁČA+œ4˛ˇ›&tӎƒ=”ďƍCČ-JŻ+Śçú¸Ăôč ÎĐŕ ˘4Nn1”{˝žů݂ş˛{äaýú "p›Őš–J  żß/Çů‘Ÿm~˜JŤŸ˛]F ˆ`‰WD|ĄGŻĄˆGŐ§hüܘƯ‡ŚËDÎϡ—A§¸EŔĹEA‡[wxČ}čîTxÄLr:Ćŕršd …ůy˛A•”ˇ“ę˘~ýúF4/Šő˜qľŹn$ľM–2IɁťŠ"˘˛"ʄ-ÚTĚÎQŒäÂ\eЃz9 r—Çăž"jÄŔ Ü&ŔĄ!hTÓŁŃqŤiœ,ăjŞ„čľT8 Áą ýąžçŠ–Šú碖QœŞ FÖJqh˝˙P8I­Ö­rŒZ)Š9ąm¸Éükő(č'­W Žš".nóO=ˆňvŰAźć O´GnţŁS2PÉj‹—ÔÍuZ Č8Z6ԐR×LJďRRň=ÔšźAqg.H ­AęL8řłjŤ¸ŁŘ Šťg*ôtíż7ˆ AJ0˝†SM¸śHmS(TŠWăóQËČŔŠ˘šzô‰Óu2…ť[6RŢÝ-Ű7!âŞęWI؇<çBžáƒŒÚ)Z@Ĺa<ęŻweÁş&RĹ>š÷dąÔU[Hé[NŽŇBj‹ŞĆ­Ź tęÝČÁ ß6iH'ő@­€n A ˝ V+Ě%,~ż“ŞËN’Í‚*›_ŒZ†ă%J^ŒŽ“É”¤–ŹIjă%ś gDŔÄťë4RŽ=‚\EEM~́˝ůOW&*ëŤ :7ĺű@×iV8 ˛bk€ş é߁€îAČ9KŞÜ˛k_4pՑŮ͗Áů@ôÚŠÂK*šÝn™_ĽJV( ĘÖWl™žp-’KFÖR‘E‰ŸŘV g=zRÓŹŁČ1aĺçĺ“G|'çLq„›ú˜,éččí,Ůä‡k¨@Nŕ}Ąr2Ű›q“ŽĄŇŐđwâ\+h Đ˝ ¨9gś¸ŔŻ÷j&|ąáÎs‘Ź(˛†Š>l-űŠu őiy9z!’äŠáZ*–Ž”yz¸VJds Œ -Łzň¨~ť=Šu—˝(Ż HS<ˇ î8,ý1]š˛˝á*hň“C¸ĆŠŘ'Ę ^)-Ć9TRٍÜĐkßľĐW+ZŠĄŐ~ÁÂőhz…œjsÔ22°b­•"/ř‚pćS}ů6TÝs:5÷š(Öç&Ű)›řpsˇ¸–ŠÇhö“‰š)šş˝u˛Ç™ÖÔ>T|/}." Ą‹ř† ,”5›ľ7ŚdˇęŚňýď rśKÂŔŠ˙óß(0˙79Ž”*ÖŻŽŢ"ÖťU,?E,ßš+üš}/|JJq>yÎܗŇÁű†÷‘R˜wžú– ěŠ8U-Ú>Ô#v ˘™“ă[Ôäĺ,F*9)qTĺůŻŁˆDůĎǍôóúô˙ř;ňw-ÉG3 €îA€pP%??\.-řáőzŠŮ} ­j=œ š>ĽüćTŕ_JyÁMâjSKĆŠ¸Tq‰ç˘g/jÉëG ÎáԘ7šZ G‹zČ%ÖYÄÉg.Ůź‡×Í\15ůQ”ŽÉŃáŇhöĂ5TŒ€ŠIĚDˇÜÓXĆ/¨".¸90Ă\{O"çÄĄ˛ę‘˙Ă(đÝr |˝¸óU´Vlí‡÷Q‚ J]üqmóŢ}şŇEŤk´+žAĺ*Mâ§˝Fúɝ#7~ÍůLxÜ㠐O?…Q­˙Ş ř)Ŕôţ:Rƒ>q-î"żžÂRd7É Éu8Cľ^´`ŠTá*.ŁvJŚt–í­6{S]„ԍľ”*™7äö^öÓ}ŽĘ Ǐ[{Ql6çŒqäŘv)ĄĺdĺŰĺäÜ~8šfNŻžYFţy?Ę ‹űđŠ\´Ž|łŇŻ\gó‰ďŠ ëCî=Ĺ2"@ŃÜJ­ź-—w=M.OU D•eäŢc")âQümů,!ľŞžČ#tĂűkú8m=‚÷ńIÝZO.ą\ŕűDőÍäÚsůć|Ł}ˇ†j˝ç5,ÚV|ž!”ňśăϞ`žĆÖԛţ0L䤸 AÉÎǁ“WŠď/ţßЈîŸ[oLă×NŮľˆv졗6Sş´ďŠš*Ý‚*Şšşc^­ŹŽźYźEƒ‡>\ć˘+voĽšŃű _ŔqЃƒ*ÜŐ2?ƒnŮ;TT• LÉmIŽëËňőŸlJ$.Ä]Ś\).Ycřń䳝j{{ý”2îćˇ!ŋâ|ẁ Sň\äŘSk2óÖ7äřu )ƒ{“sD_rô,Ľt¨UřěWRđzˇşh-yĹçö;=b>ß[_“Ł_Y[&¸ŽŠź/~Fy§ě)k‡~XAţ÷ž—Ýp;ő$ľFŹóÇU\[Eîw#Ĺţ™÷ó{q7Č" Ł”‘R*ŽŃ:m;9ˇDJbJKű¨ŐŸťŻ˙ĐDľÍAÚ{\>U–Dîo>8 ŇVšň] óp+ :ט°ťŔ7[!ŚÝ)ćńĽwł;c8řÁÁ•üü|9pBYn”——O………r(*âÇůX\\ŠŠ @ź^P —+=fşv ëlŰ[ ¤ţ!ăRŞœŰ N8ű É1v ě';¸l#ćţHއß#ߛ HmM#ř㠐űČ]É}ŕä>bŞ–ďEMÔM‘5m\SÇĘ÷v7]B ĹUť"¨#›-}ŽĺxqÍ/Ö5•Ü'Í$Ľ$ŸÔę ţ˛6b=Ž!•ä9}YóEéWAŽý&Ë×9§ŠkżíÉ!‚;éHfůƒé’]*™ůÖTčăĹ­TVŕ ýÇgŽ}Nşß:ÔTÇMPô |§¸XÝaˆ‡FVşd5ţĽ›ýôőJ/ÄE _čżżÄMűÎ˝¤ŞzoŽs<÷U“<ÎŰś€ň\ŠŘt~@Ű ¨î“áÐ/đ' Wż×Çż\Ž]8~˛Ňi\ä/Šrӛ‹ ä5w ؘ̽uät–,­öääçKw{wĹé ŐHm!ąŒűĐ]Č÷Ρäq8Fö#×;Čeâá|%Áĺe`…›Ę8Fő׆Ą•ä{ók`Ů`YŔ4ŒQ“Cľ\ÔëóYŞxÝxIŻ’T@Î2O†jA)ÎÄëĺ|%ž@Ç1–ˆ€áŠ*­6ŃźE­rŘÚ¤WÍ>•ţňN=ľC éŮöÓ˘ËŃM“JtChţnMmř„kLX2˝Ś'TełEŔ Îë z1pđŔ Óí§§ť˝;Œ'͋\Źě?™œSĆĞeűá˛YâJâ§°ŐOţ~&˙;ßÉź&’ˆC= šK\Úck‰p„óęŹŘdťJY+%Ô˝3w­Ö‡ňŔXr´ †š˝Đ×ŐłDŤÍR¤%Ł ,Z§­Óë7ŢOé[Aq…vŻÚÖ`Gűˆk†¤CO˜[Ôp,J &žĎ,`úŽ\ᥞ%ňľ–vŠŚű] óAMČ)ŞÍ‘ůĽîÚŤpŚt†í­xHmJŻk[pS ĽŔMţš?…ż0' ŢeŒœ–ôŞúUcPo ŽŢLžç>!Ľ¸@ŤAÓ˘őNäœ:†ô’]/s÷ÍŢ˙žOr‹şbüԊ`„÷•ůäčS&‚+5rVN†ëč]*{˙ŃůżY*kɨľZ÷Ĺb›¸Ć;ˆż'Şĺށ¸śŒZŰ$ƒ3JE19Ć ˆ˙J‹´ŔŠx/ßóŸ’s§‘äևRĹű(‘˘<5´ś-IO“WĽ…Ť˝˛– ď4ÔC3FćÉŽ‘×ĎM÷dZW ŰߪَBwYN텿+t(ůAF¤’+d`Yř2žszX-Ţ距—›´”x‚Tš¤Yٚ˘–ĂtűéénďD2–Ś0ÚĘšÝprź“n8ľ,LN) ˘sş“̖yPTˆPAY„“ź:w.çq îMŽŰh5HZ|2ăŠQ[ĆQZ@î='’ZŁínNä>h§¨ů8‘-w鬊ő)ý{‡“Ú†şKć.™ůű(˝J´Ú.­>Ů<ÉsĚôˆžěpMçó)¸ŽZëV:IěŁŇ4óÂ*ĄCđąůtÍ˙jéŮŻšh˝†p>ďýŇB7źQK~Ô`´œRs Xšš¸c”$^WLĎőq‡éQœĄÁřÖĽ[ ĺ^Żo>Aˇ šŞ>Xľň°~ý ú[ČeşŘ›łČE|­ÝéÖ§Žč­M7'Ne§îŕ딉SsI[śˇĎ'.Ř]ÔŻ_߈DťÖ¤ťí`áć,,hózDЁŞLLۑ‚‹Ö‘oöY#…{ëą%‚6­ź-GóÎ=@üçŚ\¤ˆĎĹye’ńózŸˆ3ĽÖÔč’kČꢘ›řLčďŚ]Gä‘ǼЧK[éŰŐ>ăxewUŢĄÍoňÝ mÓ/7÷@wăń¸§ˆnŻĎ\ĹÜĄ!hTÓŁ^Ŕ4Ůt‹€ć?u MMT^Îą×H?}¸Ě%{›á‹#N’Ş'J5Z¤˝G" ŇVmŮލMTZV@Ůć¨(˘@(wI›Ö“f—Áď›dU–:hŐÖ“ ܲ]SÎ˙Ó´ƒÖ$čŁE­˛9OGăďÝ‚*Q\cÁ\{…ŸŻ_ˇ!"¨â× WěŢJwÎ˓úvřŸçqázĽÍÚ˛˝×­ŰHe呵<˛Ň-tY)uÍéçVŒP¸ŮOYňA•^ENŞjPSĘ­rćôb#‚'JŒżýBBÓFäŃŽĂód?Îü(ÎsČďÝš˙@ť˛6˙ŃőqnţóúkŻÓÁďu1î×Yď-qËn|ő^g—Š4mh@֘@@Ľ}Ľş˝yžţÚ:řĐCdófm¤ËD EmńRpŐű캐}bs3*%?q’Zł&o~Űčďrť‘ů1}\"ȃ*€\ć?ĐĺđĹvm]­\š††1/â9rŚdGŞŰ{ĹĘUbßŐg§fŠ žxWú–]CÇâ}‘j@…qĐaH'­ŘÚńMuÚ'Tş”!+ô q§ÓAN‡“~ţůWŞ­Mł§Č:ŢW?˙ôš\NšYGWĽ…˛kcô­Ý¸vw/-öEşz9ihOg—؍üřťô@ł€n AhW‰.´óňTrĽÝ†¸ČwˆAö $ľŮKäő“"Ąmş¸y7ńňˆý\ŕ‘źŒ× âŕő-AŞk!jl RŤ_%PíđÝȇşËĄPžKĄ˘<•ć•䣒'hTŒ˛Ť­Ňż˙5z­_ˇŽ sˆ Ĺč1ŁäžÓuT-;ň˘Ÿ/ţ :3V”äó‚Đ9 ä í.ŢEśŢď”)ťPž=ŠžĄ™ ˇ5ˆ}ÄűjęÔ)ňy˘ý Đ] Ś dœľś ?rޔ™3w§ü‰V,_FŞřđ rƒ_ě‹ĆŚ1xiذá4qâ# ĆrŠ– @GAP2ÂÜÜÇîu~t84iŇDqŃ>„VŻ^K[ślĄŚŚf™(5rcdVd`„^……Ôťw/8p•””js%¤ ŔÝ ‚*ć ‹ľć _´ołMŠmÝ-g‡]@Äüš]@AčîTŒąÖV‰XaćqÝk9ÉVěćĹ~€îAȨDf žX§Cv% ˜   AP˛ÎL‰÷:‚'ń!¨g šÄzÝî˘9U˛#n’d€îAȚx=éb^ ťmwěU ËbŐZąNˇƒZ+í+Ŕ‚)aŞ@‡H\‰ˇ dś=@4U CŮuŁ A€ÄTœ‚‹yč,TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*ĐíƒAŞŠŠĽĆĆ&jnj&Ż×K@€TUĽÎ@Qr:äńx¨ °€ŠŠ ŠźźŒAćäĘqƒýßyĽ{ aŸw}86ŔŹ˝Ď78NrSg-âxˆŚ$ńşbzŽ;Lúŕ ŽĐŕƒ[ ĺ^Żo>t°–ćÚźe+Um­ę4”dń ŽGĎÔťWOĘ/Č'h?á¸ÁţĎm™8†°Ďť`–Íó Ž“ŽÓËŁ8ž —y<î)âĄF >1xĹŕ Đ4 ŞéQ˙5“e\BPş…uë6ĐŚ›¨;¨ěSIýű÷%hťÎxÜ`˙ç–lCŘ睎 0ëČó Ž“ěéĺQOkTh#ž°jŐjjj˘î¤°°ˆťięěÇ öÇËö1„}ŢyŕŘł\9ßŕ8ÉŹîVĹńšA€6hlh¤ĺËW’ßď§îČĺrѰaC¨¨¸ˆ y]ĺ¸Áţď8u aŸç>`–kç'™Ń]ËŁ8ž Wd#¨‚ŒBĐ%ńîPaüÝyđś€ätĽăűżctä1„}žŰpl€Y.žopœ´żî\ĹńÝ ‚*Đ%qËîPŃń6ŕmÉéjÇ ööuô1„}žťpl€YŽžopœ´Żî^ĹńÝ‚*Đĺp°î–C%ŢźM žŽzÜ`˙gOŽCŘçšÇ˜ĺúůÇIű@yTƒă şt!\Űťôň“ Ţ&=*ʑ0,†ö:n^|ń%z˙ƒdׂӧO§cŽ>Jś)NW0¤sĎ;Ÿ‚ Ý{ďß(??˝ý‡ýŸyŠC|ç^ĄO?ű”jjjăÎ[!öŰ´iťŇ‡žŇą„}ž;’=6|>˝üň˙’:.tĺĺe4m×itä‘É86:Vg)§ŕ8i”G#áx‚ŽAčR6oٚŇüőőőôČ#Ň‚Żż‘Ď čOˇßvŤ1}ŐŞUôŔƒ˙Ś5kÖĘçű콝|ňIĆtžč;o͛÷‘ˆÂŻ#§ÓIƒóíM;í´#ĺŢ6ƒ ˆ–ęq˞š››ŠśśV{Ťéƒ?wxšĺ´[oťößo?6l(•••QQQj‰ß°˙3+•cčĺ—_ĄŮož™ÔźŐŐ5ôĆoĘ@ÝŃGEŠŔ>Ď ÉPIö¸Đqđ…—‡sĚŃI/‡cŁă¤SNyóÍ9´páBąěrť]bß ˘™3gŇŽS§Č߆LÁq’žT÷suu5˝úÚëôÝw߉2@Đč1cč YŠóţ0JÇ=÷ü~űw8ôč#GL˙âËŻčŃG5Ę-œž,ť~ýÍ7ô÷żß'_;óŒÓiÌéĆ2­­­tË­ˇŃʕŤäó߉2ńޢlœ OЕ!¨]_Vm­Jzţďžűžzč!Ş­Ťˇ]ל9sčEq79V[Xžç˙¸ßČč~ýő79pŔţtüqÇRŽŕm3`@?yb…°TĆÇ_úŮgňš^“ŕ†n @ŔOUUUtŰíwŇgŸžtPĺƛnŚĽK—ĹœÎ˜˙ýŸˆ×FI×^{ %ű?sR=†ôăć:ąďFŠ}KKK ]Í´~ýúä“OSŞ`ŸwźTŽ ŽĄÂf‹/Ś›ošMSŠUpltŒT+8ˆrŤ¸€­ŞŞ6^ăMżýśH˖-Ł“O:‘2ÇIzRÝĎ7n˘›nžYĐŒ×¸lúŐW čkQĆźŕ‚óh‡É“)_ýľPąjjn˘'žx’>ýôsJŻýë# ÂĺÜd* Çte8ŞĄËŕ;vŞŞ&=˙< OZăǏ“U¨ÍÖŹYCĎ>÷‚¸@ˆ 抜˿űŢ{F@…×qÖY SNůőď×OžöÖ[shůňĺ”+xŰ$[Ľź;Iő¸aPycö›˛^“ŕĺW^Ąž={PeeeĘëcnˇ[>ňÝŠž}űФIéôÓN5ڟ-ŽŻíś$§ń<,•ć Ř˙™“ę1ÄÇ Ktáüđ˙+*ćeR}ŢńR96ô}•l@…5J>Śz|ŕŘčŠţVp“R¨đEčá‡J×_w-]zÉĹ4xĐ 9ý˝÷ާ 6Ú.ű믿Ň+˙ăćdŠ]8›á8IOŞűů™gŸ•ŢĎGuÝpýľôűߟLyyČŕ?&‹k“<ůäS1§üń'2 ÂMŠwÜ!ů`ÍłĎ>Gß,üVŽs–ăŽ=†Ră ş2ÔT.CŻž˜,ž =ářăhżýöĽ+Żş:ꇞsœyć4hŕŔ¨hžŹÉ"‚&Œk \véĽFä}ű휼ďż˙QŽ{ů4|G™Ýtó­âwŠ>šVŹXIwŢuˇ|}ĆôIŻóꍎ¤W_}MŽzč!Ćë˙÷ů¸ëŽSĺŔěćKöf¤s %ÂAŮ/žřŠ ňŠš ÝQbŸwŹLíÇFöĽz<Œ1‚z÷ęE˝Ä0sćîĆëÜ,ôŸ˙z@^¤VUm•ÁvŤ_8¨ňĘŤ4iâšśëTJŽ“ÔĽşŸţégů8yűí萃–ăǧ,ĺ&AXŰZU%…dźüĘ˙ÄüŐňüąýöŰÓgÖŔšĘÁŰňfÍňĺ+˘j\›éÍ˸9ňœˇß‘ă\îĺeÓiz†ă ş*U ËhĺžHÖ5×\c[a={ö¤Űn˝Eć­ŕüVk×­“',śűĚÝhÁ‚ŻĹÉćmqWy=•—•ÓŒÓh˙ý÷Yőď.=.î<°Ýv›Agœ~š1íľ×_w§^–ăz—űîű}%ŢCÇwśŮfýţw'‰ŕOJVŞŰ¨;Hg›č  őZYY‰Ě{2něXqÇéHJG¤$–$;Ÿöf´÷výĺ—_čů^ÇԙgœA÷Šż˙taŸwŹ\Ţţ86˛/ŐmžĎ>{G<ç:\“öwߕĎůć_|gŽ“ÔĽşÍn˝íůXXPńş/ÔüœĎI&Ş_˝z5˝óŽü8ňČ#hŤM3¤É;L–Ç—Q9¨"ćůőˇßdmÖ§O%ýńľkS…ă ş*U Ëđz˝)Í+ Â%]ˇv1ţӏ?Ńçóż0žsž›­Z˝FFňY°`Žœlœ ć‹ušœÎˆ vÝôiťRqI -Z´˜žůf!ůÄwžě˛K)YŠnŁî m2cútüzƒnťíŽˆ×š¸ŠvŞjjjhËÖ-Ćxyyy›ćłƒýŸmŮŽ7ß|+ąŇ—_*î*PuuýóŸ˙˘@ (îXD;öyÇĘĺíc#űÚ˛Íůwaţ_Ęq§ÓAS§ě"÷ć^ář÷ĂК‰lŮŹ'8/ şž=z¤”ÓÇIęRÝfv5Px_rň{6qÂx*..N´YséŃG—ç!ƒÓŢ{íEĎ=˙BRďKsSÝ˙ěłrě ΧQMŽ'čŞT.#`„Č”ŚŚpŐN¨{ĚŃ´Ç3ĺEîßď˝OćAŕę–{̜Ic̎šžĆÉć8i._<ńîih›qăčgqˇÚj˙ý÷“˝ ńIég#k̤"›Ű¨łHg›~řaä…ZNĘ83ž^e—/’/Y"ƒdŁG¤O8‘Lœíţű~§ ¤Š?üđcDśýt泃ýŸŠn×ÂÂY}ŸGź>ŻLúÇÉ˙Î?˙<şď˙”šž¸}ćż5……”ěóŽ•ËŰÇFöľ×6ç Üß-˘…ß~Kűńú7ݑԖqyä’K.3ž˙ĺ/Né˘ÇIęں͸†ôwŢ-oŇŇďOů}RË͝;O–?¸f çdi„°O>őtD>—y}L'xĽ ÇtUHT s‚ĐmˇHłf(.z Š˙ţtŢšçÓž˙áű¸ëá&<ěłPo Ÿ>_>Ž;Ćv~ŚpÖöĎçϗ'šwډ ű¸ëlîí篚[‡v˜|)ĄB ÷ĐđÓOżČŢ[ô.šăůţűhҤI4i⤸ÇM˛óAîâß öóĎ?‡îúÓˇ"°zÍ5×Ғ%KŠwď^tÎ9gËńĎ?kÁŐýŃ %@wvŽ([p—¸ˇÜ|Łl^ĘÁ“'Ÿ|şM‰h!÷pO@|sfÝúő˛ŇĽ—\’TŹžžN6e|ł%•„×ńpY“s ”•jľSŢ}÷=ŮD"ĄŚ t|QŤűăöfî-hČŕ!ÓhŒ'JVVZR*ŰC'.”9`˛ŕëŻĺ‰kȐÁśósBT^8˜“ ýÂÂR=nVŻYCO=őŒěʔ'Ě\+ĺO×\%_ăO?ó,}$îę<őôStĹĺ—Ç\'Zř›ďţđڧŸyFžf˝Ë”ě|ńž+´żTĄ]vŢYO¸×¨ëŽű] +wÝu7mÜ´IKœžŹęÍűöő7ސËěźszTěóŽ•ÍóRŞpld_[ţ­çÚŞçŸwţEňľĎĹM=íßîůŤ1/÷üŁ'Ş˝ôŇK(]8NR—î~ćZ‹wß}ˇŹ­X\\D—‰ý6lذ¤–ĺfç\ćäćăܣϒĽKĺëK—h|>á×ĘJKEŕž7ĽâňË.•5LŽżţFŮ4ý?=,óć'™çĹ ÇtU¨Š]†ÇăĄl1b„lÓ̖,]1m‘¸ŘÖUöŽwŰżrťhž8Ÿ˙ŲkĝĹWʌęgžqşźh?íÔSÄÉw%ÝrËmÔҒ|Ď ŮÜFE*ۄ*7Üp“ lčfW+…k.Üąr|Ѣ%q×űć›oÉ||AÍľ xü­PďRéĚ öf¤ş]šŠ ßů[ś|9˝ôňË4vĚů7ÍM|¸íĄCľ@-Oă$‚rÂŇTáŘČžTś9ŸŰĎ;˙:÷źóé˙1ÍÜ#X ˜Ůć8NR—Î6ărĹ­ˇÝ.*|síŞŤŽL: ÂýŚýpĐăŻ÷ünşé9˜Ë¤üüľ×Ţ Tđš‡kW4ˆ>ä ůږ-[ĺÍĽtŕx‚Ž 5U Ë(y ˛Ó}%_0O2…>ůô3y"|ôąÇiŸ˝÷'š-ôĐCÉyřnÁÎ;ď’p]SDPĺ™gŸŁˇŢÔ.ާNB śór žK5zôhZ¸p!-üö;Z!‚+|Q–Œ‚4ó2teŠ7O=ů´  ěžŰntüńÇĘă€ĹŞ•˘'<6`ěźňżWĺ<çœ{~Äk֚HÉÎ öf¤úŰÅJNb}ǝŚ×_ŸMő˘}Ę)ż§éÓ§Éé|GńЧžŚwß{_ޙ>CSÓ-ˆbŸwŹTŽiťNŁŮožI7‹`yŞŚMەR…c#űR9¸@ďޕ´lŮ2™Ł-Oül?y{ů{ńÚkŻóqŽ­LÂq’şTĎ _}ľ@ÎřüÎ7ě=ôPŞŤ­ŁŸj6ćáÜleee˛V3'Éç›<§‰ |[şËNwë­ăÜqß|˝VŽZEó>úˆvŘq2mˇíś” OĐU!¨]'óÚ*˘çŮrâ‰'ȻȜ,öƒ>”ƒŽkšœtň‰ÔŤWτëá“ä¸qcdMžŸkÁ|÷ÝwśóΙó6•”–RuU•l2Ä5úőíKÉâm‘R9n83T˜^+…ƒ*ÖZ)‹QńČpÁçŃââzőšŐňůŔ;BéĚ öf¤óŰ3věXYóŒŤQϝ÷‘¸pZnt‘ýꍯѪՍe@ĺĚ3Ď  ăÇSş°Ď;V*ÇĆG&?űü3ŞŽŽIjŽĄ2m×]eާt>dWŞż§ú{şýŽ;ełŽçΓƒŮřńăhS˘Z3ÎťBâ°¨ŹěCmă$uŠîçǟx¸ůÂIˆu_lv–Äs…Ď \ˑ}ňÉÇFPĺĎžÓvݏ<ú}řá\y>áœţřů|ˇ3d÷éé$4Ă>Ď éß~÷=*î0[ťÇŐqžÎĂĂ=ĽÇFÇéLĺ'éCy4Ž'č({Šxŕ* |çÓ+h„† iPMzÄÓ 6¤ŰŸČxđś€ätĽăűżctä1„}žŰpl€Y.žopœ´żî\ĹńÝ rŞ@—ÖŇÜBŤV­ĄŚŚ&ęN¸Ş%ßŔ‰,=ý¸ÁţďxŮ>†°Ď;`–+ç'™ŐÝĘŁ8ž —d#§ ‚*Đ-t§daHÖ~:ăqƒýŸ[˛q aŸwN86ŔŹ#Ď78N˛§;”Gqq9NńᡂÂ***¤ňň2r8")“rĺ¸ÁţďźŇ=†°Ďť>`ÖŢç'šŠł–Gq‚ö—óÄ駟E7Üp“í4>/<ôĐińâ%”Iżüň+]vŮňűíšçžtć™gӇÎKińžÄwÍ5×Ęăëď˙GÔ4ëvMf;óďËÁ&×ůńǟ¤Îüw?cĆtÄÇČýÓĐĐ@Ën‡r8eĘ+ŻüO~WţÍIÖçŸAS§N‘ăW]u\ţüż¨ůŞŞŞÄ|3äôwß}ŸÚĂʕŤäoc}}˝|Ž—ĄgĎ~“r š˙@ˇq÷ÝwRII‰üŃď˝÷é˙ţď2şňĘËč°Ă%€öđĎŢGĆóňňň¨y¸ěp žÝ]ü÷żŇ#ävť 2§ŁÎ­­­ňÂĄ_żž4jÔHĘ„ŻžZ@_|)młÍ8qAtĺççÓÜšsĺE҅žG'œp1b„ř۸P^°/]ş”žxâ)úôÓĎčŃG˘ÂÂBęÎjjjč×_9˘ôčQA_|ń­]ť– `źÎŽ^˝zŇćÍ[¨˝ŹXąBţ6Κu€ümČUŞ@ˇąíś“Œä=ö˜IEEwŇ˝÷ŢOűíˇŻźćBô=÷ü]Däç“ŞŞ´óÎ;‰“ěETYY)ď4?üđ#ôÎ;oʂčĚĽŤŻţýéOWŃA͒w÷Ý÷@:î¸cäĹĎnťíI]t>͛÷1ýüó/ň¤Ă󮿍íg{ë­ˇĺ{Ź[ˇŽúôéC't<zč!Ćô—^z™ž{îEÚ°aƒœ~Ę)ż“'ÖÔÔDůË=ňnŁÇăwWĎ%č|1d=és!Ţgsç~$/ž^yĺú駟Ĺń÷úíˇE˘€ŇƒŽ9ćH:öŘcHQš\˘éĐ9|ýő74qâ:ăŒÓŒ×† L?üđƒüáýëďűć›o…Ôˇä2Xůä“ĎDa˙ů[ő׿ţMţVĺĺĺŃ̙3ĺZqq1AŰ$:Ořý~Yž/š››ĺü|ž4h\fÁ‚Żĺć•+WREE~ř!â÷üĨ÷áßí .¸Xţ>\{íŐôťß*_żůćŰčÉ'ŸĄgžy"î9‰qM†!C‰ ­Sœ›ŢĽ˛˛Rńq´íűąťîú M˜0^őŔîž{Οł‡xíA:ŕ€ýĺgćőŽ1\€ß˙q\Ńţp|đAQëüĂΑ˙ţ÷żŒ×¸&Ö§Ÿ~*.ň_AŮdΜˇĺö¸řâ?Šýt}ôŃ'´×^{P[źńĆlŹ5ë@şĺ–Űh˖-⢜—1űîű'­^˝ZţM›6U>˙ŕƒwd° ˝ŽçÎŹ°°@~oŘN;í(ƒSÇ2=ýôłĆowŹr—˙öß–8GMguڜ——mjj¤W_}Y>çßoŢ~{ś´óoů§bكčńǟ¤––V:đŔD÷"Űż—Dżüy¸ŹđÍ7 Ĺţ ˆĎżƒ_.÷ăLü÷˝fÍqŹLĂvëO´çĎ˙’JKKh̘ŃĆküű°fÍ:Q–yM”9ľßţl˙űßëâ›&_xxe\~ďXŰă­ˇćČßDvřáGÓQG)ŔŒkŽ\|ń%â{Kýű÷[ĆČœí Ű:ę¨#dÁöŰoż“'ƒ‹/žLDăџ˙|§8ý…–/_)~ź˙O:fÎÜ]~ů‰}ńŗňńË/ż’ß}÷˝,ěžűnĆú_xáeQ8=UX'ʛnşŐös|ôŃÇtă7ËÂŐ#<$/ڏP:gÎ;r:W×ć€Î‰''Nđ‹Âý>˛đ¤W˙óŸ˙"ŤY^uŐňsđÁ‡T[›|ÓȎ7ß|‹Î<ótťK\×l;v =őÔcâoř\0ű-[ś‚lœ4ůäqÜqÇĘęÔ|Ňăç}úTĘ“î°Ă‘w<8şÄ‡ĘťvmX_xáEYŔâ nŽţó]jţ |RaăƍäŻË‘Ëĺ–'{~ĎĺËWČő˝÷ŢňÉ>űě%ç˝ţúk)dß>űŃ>Ű\09昣dĄbřđaňŽĽÓ酝+hذĄrßń]â×^›-çM4:ţ¸óÎŰDĄq%{îňŽćwŢM[ˇn•Óăý}—––Šť‘˝ĺ||wk,ýřăO˘ĐźXQ/—Ëňo_ˆóĹßфöe>OđE 7ąŕڈťî:Uţ^s0{ëÖ*úěłůr>ŢwőőuâˇŮ'ƒě\+˙ću\řżňĘŤĺůŕžűî‘w†ůbĽwo­vďoŢωÎIşQŁFÉf;|ך5Ř͞ý;ÁMDŸ§ŹřŘŇćŮjźśíśe-L>÷zę)2˜gw1˝çž{Čڛď˝÷ž|ÎM&ęęęE°eA×8äż[nÂÇößQ~řÚFĽƒĎ|źń>ŕZjÓ§ď*ŽĎ7äkŒn|ĚŢxăőňˇâ€öÂűˡÇńܕőî])W,Q9mˇÝv“ŻÜTćË/ˆ˛ŕXYƒˆƒ) âßmóM7ÄpcذĄň˘\VÉüp™ƒ)ëĺżń%K–Éiĺż]>¸|ĘÇ<Íâícž6>UŚD,Ăë<ôЃĺ <=ÄšZ¸śĎ A#ćM´íâmţméÝ[;ňoŁš&07Éä˛Ń.ťě,ĂąĘŘقć?Đmém>ůǛk°ĄC‡ÓůǟmܨMŰmˇ˛%ßyŕ;ż˙ýIôꍯ‰“×RŮśtÌë///3ĆůÄŔ¸ărEţŮmذIž(͸}ďźyZň@ŽÎËw,ř†zöě)‚;Ú ‹'ľľľ˛>tč`cٲ˛˛ˆ÷†ěyŕűЍ¨Čx΅_ ëřxă;KÎÓŔ='ŠéĐšpUrřďáÂoĺÝásΚ@ÖLáBxŹżo;úoŐé§˙A0ľć>ŐŐ5ň‘ďŒň9´óy‚÷UKK ýío÷Éjęf7n~ =účăâÂŕdń[P(.x÷”ŐŐőź úHßž}Œęův’9'ąţýűF,Ç4|Wۊs hËn˘‰‘§ůš6OOă5s>¨üü<ůhŽ!ŁăďĹőożý|ňIâńy>ӛ€ćůç_W]ő'Dă‹RĆÍwřb3z˛Űƒ:L>ęëäf ;ě0™6mÚ,ƒućsϰaCŒńö8žť˛Í›77‰ĘiÜŹĘétĘ@ٗ_jľR¸ÜÇ7Ţ8hÉűfÚ´]eš9šćĎËľ?Ź’ůŕŔŘc=I ˘Ě1P<6Ç˙~q`ŘźżĚĺĹDűř×_“ŽľcĆÁ–~ýúÉ×_ý ™'ˆóýéOWŰ|‡řŰ.•íaÖłgř\§×âß(”“ Ł ¨ÝÖK/˝"O|7ď"1Žţs˘@ĆwŠ™~Ťń?ůäSňîĎöŰo+ Ä;î8YVm䈺ގ4U}űVʝٲeˌ÷}čĄGä]‡—_~^tů$űé§GĘi@áȲe+ŒeůÎ ßU…ěăŽ]N+˝öW­ç‚˜Nϗ’h:t\°ĺ<\ĺŸďr@•kŻqî%ΗÂÍ)üИßvôcăć›o9Ěř÷ڗů<Á‹ü7xôŃGÉ ş™~Ń2yňöňŽ?7ńá;ź|Íž;˸Ć#çP9ďź ĺĹŹ^ľÝJŻQďœÄĚżýŒĽ^˝˘küž|ÁĹů{öÜsfÄĚsĎ˝ Më…S˛:č@™“ƒ›Ź}úéçtůĺ—„ń9`Ţźä…%çşĐqÓŞp3áT›JqÎ-ĆǕ^ű…ą'Ÿ|ŠźČć  ¸Ö ‹œ{‰qłA˙^´őxîŞ8˙ß,Óżg˘rßL™űmP!7qľŮ{ď˝G¨ů˜äý6xđ qÇđȤŚCçÁ‰f÷Ýw_ًwgËKž‹|ß}“ż‰ţž­ôß*ţ}âÜgŸ}ŽĚĽrţůç!¨Ňâ'÷ęvŘa‡ÉÂďšLΘӄkŞ]{í5˛W—NřěĄé¤“Nws­8_ ç¸ăŽťdMI>ĎpmǏ>úHÖbIćœÄfÎÜMŢa>ďź hΜ92/~î°â^C8Ů#_0ÝsĎßdžk.ÜrËM)őčrć‹@ďj™3ü}”M8 ŇÝť ľzýő×ĺşľ —¸6 î˜uťÚmgĆű›/Œy[ë5Ptűźl˘eÖ^ÇsgĆۓť >ëŹseé—_~Ućyřác9Q9q€Ë‡œ´V˙-ž:U+#šóŠ$ÂÉYš ÇďĂ5Lâýđ|ÜäfîÜybߞJďż˙ž,긆ÚwÜ*‚öčœsΗš¸f”.Ţ>ćŔ׈âď Oý÷ńđĂíťOfŰĹĂľ9).7›ĺMšJIâuĹô\w˜őÁ\ĄĂ•n1”{˝žů킻>4hÝpĂuÔŃř.˛4üWTđ:Ž5׎âZ}ôAT~73°ýůĎw‹`ílěĄÓóxÜät>1pť|h„† iPMjhćq˛ŒKřE€”q˘tnRôÄOÉOPÉœŰâwż;UÖ:ŕ;ýœěüůç_’=´  ‰pÓr 9řU€”qó€?ţń6lÝpĂľšƒ{űă/’=ű<ůäÓ2G w?{ŃE´/4˙€.Ír‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @˛TYłô üigvędĺ] čG¤ ă'eš˙¤A€4 ¨UҀ  @TH‚*i@P ޤA€4 ¨UҀ  @˛TQU•˙#Č}Š˘DRńűÝĘöP.č,˛óˇŠš*!^AĄ+ŽP@ˆÔ]Ë ĺHjŞ@\ćB“^ŔčJ)ťB RŃşz™€Ą\ЕtĄš*jPŏ@'Äĺ$ţŰŐ LúcW(HY“ôçáG€Ž\&`(t=ŠŇ…‚*@@ürŸšP.8éϵ”š Ő Qć‚kCä4ë<ÝMw(0” şŚlý$e%¨âŠ JA€ÎŔü㣐b˜ÂCdAŞł˘Ě…#˝Đ7 d.<@ˇÓŐË ĺ€ŽKqPVd%¨âóůEPĹOŰŹw¤ôÁáPŒÂ”Ăáˆ*HY—ÍU‘¤đó`0h˜‚ÁČB”yY€î˘Ť— Ę]›âčBÍź^/Ştć‘^`’(1ît:ÉĄeaŠÇľéöËçë](˝€$›&† LZ3EmÜ(LŮTůč.şb™€Ą\Đ=8œAʆŹUZš[Éď÷FT 4?Ćk™l­ŁŁßŰŰĄ#ÖĄOWĄ”â&‡,4š\<¸dĄĂépŠ9ň¤ŹëČúv0š¸päsżß/†€,<ɂ“( ňô` ą<@GÂď'žśśCG­CŸn.p`Ľ3– ˜ž-P.€Î żĄÉ­ĂéňP6d%¨˛lu ů|^ҡ‰yÓ(ćť ‰–1OTř‡Q1&YłýęÓĚkŇçąNłî>c]bž¨]ËÓxyýѲŒń™˝5f쓋búáçöËč›LžiĹşx˘iq9-ôq#VFť×)ý¤Şˇ(ľ[V~ óvĐO¤Ć äZ[ԈƒŢXˇúRÚw°n1UŢ ÍţBňóé{FUő”¨Żš5<_ŞţEÍß=üUôDśŰJ˙ž¤„ßČźŒůĂD8´of,˘ĎFĄ}ŚD|ĺđ÷ŃżłJą˙v”đo[óńiŢR涇ú> }Ôłź€*J )??ŸÜî D!J”ŸœbşCޚrä\!ĘZp’…"Yp ĘÂ7MÔÄvp{ŠĹ٘‡÷ľ#^ŰéČ!ö1žĎzüEVűu‡˙ŽÂóYŠÜńŃď9oüď9żí/oÄ:´ý~_ťż+}]úźvŰ@Uă‡Čyَő=˘ß7rýÖď`÷út˘ČßąČď^‡ý{hŻĹŰüœ/PÜnwčuóßPôűj˨Ÿ#rŐvöÇEÍc'Öď§žíôßvów˛.ýĂ^6ňł„żƒiI.ů>ćĎa˙wšždĎćmn-đE›ŠeűD~ŢČĎhüčŸŃî}#˘çąîóXŰÁ}<Äţ‘럘ěŽéXeëw7Ż#źîČőSÄ6P|6mşÝ1ý"§›?Ÿůˇ&Ţ{…÷‹b{ŹĹ dXżCě}š"×e˙ŮŹß#ö|‘ËhA…š›jHńúäďVg)0” ˘—ąűlÖeP.@šŔŞł” 2؛yŮ ŞŹi ––Văšoć¸C3$ůĂ1—őĚg?—ů]b.›č#Ş1–“@úą~Ý잫ąçˇ~Gý żŁ>˘’bóGmýшőó—ÍţPlFěţ ŹĎőMŚZçSc/űó*ÉŐnżŞIŤ Űđ'JřzDĆühš`üT„ž˘błfëO~ä´ČŚí4ބ•Öm PIA# í_D˝z–P~0O˘ÄŚĺr§Żŕą%.4ľz˝$nFQ~Q%ä‹ĎË?ź‰Łâí‰˙Lř"¤ŹŹ”:Z.]ü$Ÿ ť´ó;ŸOÔXWE5[W‹ó¨_<÷ät™€Ą\Ęé‹ţźŮůěŮiţӐƒŽmA•”´&Ŝ#ŢÇPS|Ýî}Úë،"˛ťXśž§k‚ÝúŠÍŻń])Ż_ĽŚ– Ő7ŐŃ(qwj@Ÿ ń^yÚçršŒB“~×-WhŸ)ÔVZœ¸ZŻW|ţÖVŻřN •őFN—řĄH6 NmüçÂŐčݞ|Čuú9ŢíΧ‚˘2ZˇňgRĹÍSăb&‡Ë ĺČu(t>Y ޘŠ)Γôϰ݊•ČIJ’ď˜™€Š>—5Úń˘?LŇM‰łśTż_*öÓ#kč¤züĎŰr>ľ r¨‘ŰČźä¸ÝńaŞą¤G° ¨´´ˆÜ˘ĂŐVšŠĄąYŽóüÖc_ľűlJŒĎlz=¨ju[âő†˘EŤšČărReď2-Qř,AEďN1V5ćě1ߍâQ˝˝tPžäĺ;Rb•öJ.OEŢ"ßCĄëŠź´Pt8‰­lg­Ş9ugĘ|7ŠCZ{iQpňúŠ ´šÜ|'{ł`¨]šŽŰ˘:ć“VŐşŃtČmťví:ęÝť—<™;L]?466ĘťĺĆk(\Ľ†÷EkkŤxť[qከ¨Hn{€lăó@~A1UôH՛VËéËŮ2Cš u(ä” rSŹP–ő:NąŒŰ Ëŕ ůĚ:⠎ˇˇ6˙ ŚQ“Âţ%%÷QŹ­fŇű ĽÝH‰1’ŇÇą´őQlŚG}bŹÝ RUŰÉŃóŰ|ÇdľĽyšô‹”°qYôţ1íËöăĘĂѨƒ)?//t eä%s{Ü2蒟ŸG M2Šm}żđ ȈeĄnőAŽ×|§Ćôaľä •ˆ›9EEů˘ Ź„>ƒşCĽĎŰQôœÝݨ‚’>˛z/DZśl9}öšôÁséŰoż—íy++{wő/^B?ţ 0@ž´yű>óĚłT\\L÷ß˙/9o=d!őűďż§+VRuu mذ^°zăJ ü7ÇI Í/üˇŰÔÔD-"PŤú9ďŻ×+Ç]Ą*÷m•JmžVÄšżžvłĚĄ’Ťe†rAęP.č(´Ÿoźń!ńĐ"ŽBB<¨6QˇŐłTS%šŤÔT?˝]íŚ${‰ÂŞ)MU˘'+vˤqŤ)Ź&ˇČ䟝㚪ĆznŮĂĄŞFŞÍJ"^KłŮQŒII-ŸědĹś’Š6‘ź›Y›IOFË”áĂŇŕ}HŻbiGKÄqŸĘríK—­Ą–VoĚ_—8™•—Sß>=¨Ź´HvčwljjëiýĆŞPs˘ ĺ3s—ƒ*U×6SeďRŁp˘:ĄKn$ŞŐŤřšŤůr„ßĺ.ĚZ6đÎhĐ ÁtŮe˙' Ne´uëVúä“Ϩ¤¤˜ŞŞŞä>ĺť#óć}D………´÷Ţ{Éœš=úO?ý, XKiҤ ”——O7n…°ďäÝŠŠŠ >|8AbzÁI/ĹĂÇwssł/((@ ŇĆż'üűĂŔü¨7+ŕ‹3˝iÝoŒSRňň‹Éď­ËÉ2Cš }(t<” r[V›˙¨iNKuNs&‰śBé}ćđűGź+°’lđCľ™ŸCIź%‰×Ň $ľ"Ë˝hđ Ţ˛ţŁ[ďĄüźÔŁ˘”–,_'N ľ2™[řcÉę-bů<-(e존7PF:U‹ i!"œ`슲4{ö›4pŕ 3f4­^˝šžújí´ÓŽ4dČ`q­‡ ˘żƒe=ć}bţJÄ5ôšVâ*ZÁ…duŐ͛7Ëg#¨"ňÇ´weĽ,řđŇúWŇć-ü#Ůń~|ĄGy‰Ôp@ĹÝ#‘xÁăqŃČaýŠľĹKu M‘$"雳&LŽ0Nů/Ç?oGňxܲ0Ôłgq‡#ŸĘËËäÉ\/đë;ďź­[ˇNŢi’w$ĹöäBÓčŃŁä8¸ř8-*Ňîţy<ŢĐ1Ůőń÷˙ĺ—_é駟Ą™3gŇŹY¤T0á~'JۖkhÁ‚ŻEÁt‹œĆŰQoťÎŰ{×]§I š•¨ş/ß9\źxą( ż%ç?䐃h›mĆÉ. P_¸Ž_ż^\řVË.z˛Pţ{ć‹×~ýúËÄöńđü\;ĹP1ăßzţÍŕ;ßü;c]Ţ:ä:” ’‡rAŰ \ĐőĺD˘Z5‰WŇ^ą)žĄ˙Ÿ(Ŕ’čÝŐx/(I|Ĺ>φľ^šÜťŰźUr‡4B(I°YŤ÷iD@E5MO|nÓHDd‘’kśŰéÔXŸů˜‹œąĽ,qˇČݨRQa>‹“ţĂĆ?Ź?|˙=ýđĂ÷…ţA6lMŸą[¨ڈX‹‚TQQüÁ4ĎË'ČĘŢ"zí’óń3˙–””ˆHuľźÓŔ'JŹôíۃę—6wtô V¤PDáIŻV›KôęžáńˆŞ]`Áw7xß77ˇP}}=mذQ;\Xňű}˛°ÄÉçřDËóńńÂ-­PՓ–.]&›ŞM˜0A˛¸Ş*‹+WŽAŔ:QŔ/Ľî€ˇË6ŰlC}úTŚ´œ^ő^O ČĎżřâKúńǟiŔ€ţňoŸŤJó…ď—Ç{Bžôż;^Ž łvmÔy.ó͡ôöŰďˆ}4^^=űěó´÷Ţ{ŇôéÓdŐmč\řˇŕ‹/ž’żz-VĆe‚ącGӁîŸTPEoîø‰ß çü\ӀËř÷›_|Ą^~ě.śr˝LŔP.H Ęí傮­ăƒ*íń[›b5#Ŕb˝˘Mö­Ôä§)‘Ul—SČ~ssd6”yi˝žŠ]m•vŚ$YŮĆnąX_-˘B„Ír‘Ď”¤#ëűĽ@łĄ$QÓ*Ö&2ĹM˘fď&ETĚUIňÄ nűíˇ§‘ŁF?šZy@‘?~ÜćŐŹDUŞŤë" 7œ;Ľ´¤Č(ńÉíÇ~”'AŞě˝ĎŢrœŁŠ˛íÎĹÖjŞ@b\:ňČĂĺß ßâšO;8´`šú÷ď' Fťď>CNç$t••}čĐC‹ät>AsÂ:.8ńɜç2dˆXGuÜłÁ¤IE@˛oJËéUpÍĎeaiÔ¨QTWWK;î8Y&÷c<ňXDŽ}ůX…§ĺËWĐ;ďź+öÝn4mÚTYXŽŹŹ”Iy?nˇÝv 'ڟ6mW?~|č\*ˆßţÝĺü‰čnş%K–Đ×_/”źœCƒď\ëżÖřąÖ—ëP.HĘí傮-ËA•öžš§„5 ”$–^Z‰=k˘UŮM°D3ĚI”ř ˜^KŽľ†C˛ďĐ´\ ńßA5?ŞŃŻ% z¤uúS#—SígIi}qžŻ*1U⽌WQ"'rÄüN~ńă¸fÍZąbyÔ{đuaĄvÓiËGâ[ˇ;üú iá7 éĂ?¤=öŘC&Óqm•tó{6 Ô6”Űa‡l÷›š D6tčPů¨ŸČ{ô¨ˆ˜ÎweôýŃ]îD1Ţnܝä‹/žDťí6CŢIJ…ů6Ő#s'QÂťÄv¸úőŔýiŰm'ŇźyËî>űě%Ťů.[ś…'€Nˆƒ˖-Łß~[LdŠ>=hĐyƒ$™fćߎaÆŇçŸ!óhpSÎą łëĆ5YŮ.čď éCš íP.čú˛TI-,üŹm­iëŇ?Ľš‰ÖlXąĚw­ÖŚ-jüwłÔN ŐY1žŰ}&˛T™ˆ˛‹7‡ń7Ť„›3Šv+ ŰNMaţX_&‰ ŒŻśQŠb…ŕÔó$ ʐ9@ĽńëUţB5¸md˙B‰ŽLď$âč?ßľ2ó˘ @Ú]Š€˜8äó›6‘S_śŸź=ŐŐ×É*žz.°)ń6,t)É&5Lv]ÝßÝŮsĎ=䝸Tľe›ĹŰwúÝ*nËÎĂCýWg׊ ęL™ÄN/xĄý4@çÂež˜ĺsśůâIŤŠRLÉUß×s0°uë6ČőN:…jjjĺ ßlÁoD÷ƒrAŰĄ\Đľu@óS;ľ ×fjmçąä-iĂ1˘Ćn¨ÖĚKF˝kŽřŔ2ŞXÖc ¤DZb’Xü”ŕ5űœ!Ńk‹䰙h÷ZÔ q>Źm JýŇeŠÇ6QźíŹÚÎĂ;KŸ˛š_łŠ ¤UŃ]˝j-_ž,<{čGŻ_ż~2°˘ŐTŃÖŘŘŘĽć@M˝Xo -yß=Ři§e[ϕ+Wwľxšęš†¨ĺńóÚšńÎňÎmqůŽÉÚľkĺ>ç;|÷ˆŰŇsu]ˇŰ#Ť˜rŰDřÄŹˇ˝73WA5ŰşľJ&ťăśű\u¸Ťœ´őjôœŁČ\e7ź ĚUtEÖ<[šr5-Y˛Tî7ţűć<ĺ;ˆÖ^8ěŞř†§šd>˝‡­'­W-Éţ˛:î„~ýőWă5í÷VĄÁƒ…~Ăă×TŃ;ôŚ=üłŰnÓĹosšnsNk’Zč:2YŤÇ\ŕ;[ŕŚ&v9;şÚš傮/+żŠö5’˝|OóÝÔӍ§™iŽU‹"ô “M5VŇů1"zÓsĹU‰‘WľďT‚9捌§63+öAŽ˜/DżŚŘ˝ůEm5gâ}†T>ýmÍKÇŢö#ŁDĎ#kĽ„+MÍâGłEŒŠBűXĄ"™ŹĹŸÜ—üşC Ž˜<››[ePĹôyý˛W ’â™´VݞÉôj›Ě+ k7W™ÚiăÇľłÓďLpł°ľŔĆúődĆx>ásÓ2žCÁYä˝^ŸLDDžčĆĆ&Y•ˇŽŽ^&ă‚<C8 =Œ8ÇËę'dÎđąČďĹëăupűkN¤V^^.‚‚ËĹ{ŽŸaŁ\OWÂ]F~üń§ňű76éĺôÂd8ŔĹϡß~[9­ĄĄAÖBă$œXš÷㡇l,g^6–ĄCӂ čÁ˙#˛ż˙ý˛fڌÓ :˝—Ÿ>}úD4Íá×ůˇ–/š’Y˙Nóď5˙śŒ5Ҙ֡ocœ_ř÷Z]wĚçh.ďńÍŢß|^áó?żĆš<ř\ĎÇ@ccƒ8ž*ÄůC;—p™ƒo|nácˆË’|ÁĎe^Ÿçůřä^Şx™&QśŐkSńńËç!<đÍÁdnät6(tmŮ 5ë×bśÚű(ĹŐÚDR\*ć Ö\*6ł)6ĎU›qóšbŐĆ0.ĆŐčŔŠ׉W[%zÄţMÍ!!ˈ˝]˘ësÄű.ń6pT(.ŃÎ0 Őú’iůÔ ć0JŹđ`ü×M5TLě+@VŽŢ@ăÇ “?Œ\đ3fŒź 5ăýnŽćÇśë7l–ĆV>ąU׉cőďŰ3Ô )0ĹÁEŕeőڍ⇵)˛J1AgÇ.<ëw%ů¤ËÉ šł‰›‚É;–>yźq …ďXpáˆďfpŚž{šyó–Đzü˘PÔC?¨ác‰kÁpĄŤŚŚF&łăv\ŕÚ)üČŐČľ“˝ƒşţ^Æ ĽO<^&{KŸxŰńvçu1\N[ZšĂżďŞö>ä2ˇĽŽ×ý!żÎՎ:h–ŹQ4uę.ňˇ…÷17ŕ t>yyÚnťmiŰm'Ż™ŤěÇť ŇiżßÚo.\ńzř7&Ö]očü¸‡.đšEKnę’eN>˙sm'ŽĹĘA~ä"ÜŰ— řĎÁ.đr|mŢźYÎŁ/ÜC[MMZ`†ËÜŹŒoŔp0‡ËvÝuw(t}ţ¨ ě*j‚eϝÜ\śl+ć5*6ŻéăÉźGʚĄ#•ˆGS`Ĺ<‘éâ>FÂüŠő[‰Iˆľ¤ńĐśKôČcŔZ#ÇúYĂÁŐvN˘dBJÔŇöKŞŤÖŠ;°EÖŔ—Öőßć-Ő´n]1 PI8qŘ|Žđrh‹Xfóć*ăΕůŘŇşQóŇÚő[dm–^=Ë¨Ź´H^s픚ÚÚ˛•ŰQ×9]â+čL¸ĆˆŹńTT,ďt0°ÔÖjÁ.HqáF+qŐŇBYľ”Űćók\ՔŤ ň:¸Ć ęůŽž¸ŔĹwłx|w‹kO1ĚđÉ^ Źh…5—ËÝĺ’j…šIő¸aGżpá‚):ľî,{&|O^†ˇ˘y¸÷č:Ú+߅9hÂż=zËzŔEŻqˆZ*]ßčŕ^z¸GȁČŸ§9XÂç~NLË7NZZÔĐš]•ËđyŸo˘đéœkŤpó”őë×ËcŠk¨đůŸĎi0'Nĺé\žŕőëÁ?.SÄ;—uF(t}]$˜D@ĹŚĚnnůŁ$ZˇíłXR;ŮÄŞÁŻr]€KĹXá0E‰X1/›ˆń~DŚŢ~Lu6TËwR˘—‹’PĂϒ˝ÔŠ ŽYWM‘ŸA= %óŽ– :QŻŰL,sŠńć3=Ń>łJ~q’Yśb|>°ĽQ+ĹîĂqĐf“¨ŹZľžšC'°XBŽĹ˛iK ˘po@z˘:Ÿ? Śůem˛~_”§:5=˜ÂÝdr°„ťKäŰşuëäɕ›‚Ő×7ČŞ˝œgeřđa˛0Ĺw°JJŠeŠƒ(|ˇ… X>ŸWŢeŇkŸđɞ_çGžĹyY¸p΅qN„Ś÷DÁ^–çA"´Hź­ôęĎ\€Š‡ˇoOžŰÚB p`Śôś˝‚7ť8PÂçs„ôčŃSAZe…›˜hMy|2Ȣĺ`Se™€Ë\včŐŤ—xăó>?çk|“…›Ą1žVZZ&oćđrPŃşi.”5%8 ÂMŠ Ęš­Ăƒ*Š\8§˛› ŃT˨˙Z1ůĎiš"VÂÍ=kmK`'™ńh‰čßĂîŁDR(ňQ_ÖúwőÖϤF~~˝?çD­k#ëhÓńa ŕ¨Öç1ć‹ÇžÖIô4ëś Ď7œd[ŰH/´ˆH˙Ňĺk¨ŽŽ ěCĽ%EdýTMâÂwÝúͲf Ÿ y9ýřS#Ţ-ôžĄüÍň‚y˛^u  âB ˇ“çýυ !CËM\ćOĆ\Ť„ďŽđ‰œ§iyX\2 żÎA~änźy=ú _Ż6ĘUڏŸŘyş>oż~}ĺkC‡ÁIßBĎoŔےďđń`׍)ĎĂűJŸ ­<éžřüŽŐVŐňp 8PÖJe|âóˇŢœ§GŐ8ďđ#QĚÍN8_ŸŢ/ŁßtaŒŃçŐ×Ç˝ă0./@4” r[¨ŠŇ֐LäŞě ‰–‰ŠR( nç+Ć S“ 8ßČ2EŹÍVÓ÷0×J‘Ÿ)”řÔ¸h'2jě(Dqó“¨qż‡9űŽłšŕš]c%Öź6ŸC%› ‰Íű™ƒEŠAąj¨ü?{˙mّ‚;î}ŢĽˇČ2á˝+ ”ŁŠ˘Čb‘,R$K%ާ§§§9­ŐšéYkzÖôî™Őš^Zę鞖şŐ˘D'R¤DQôĹ"ŤX(W¨‚+x$<éÝóţŢ}žnGœs@>džŒxy‰'Î9{ą÷yÎ×W§éŞÖCJŽš¸˛—6–%'NžĽłçŚi„Ůý˘ă,Tř@.$ Ź `a‚śn–Š;•Sľ'kQ•ŚîN2.¸ÁŮ!5é!ýšŮ"áöÓt.?MÜšS{a źť.űçWCÎC@ŠĺV pç\dţŹedddd|P¸@Ä FzEŒ óŤK l4—Ÿ‹,\ş¸$H•ľŹę”×5ó¸PžĽZçŹNłfFĺLTˇ}H‘şÝVj ââthĄ™—‰•Šj‰t]‘%˛CIBÁ1 çůAwy’*wG’@ëšíúKjËŽJ_c$öuéşĘ<ľMŤT‰X1çÍŃVA ´;+ě’1==›tœŇ<‰ş`mb$wÇ™,ůpŕ˘÷çöĚČČČČČČČrÁĽ‡KĆRĺ|”7ÓĄ›UĹZDMO¨ŇŽĎűş°Ł´˙Ç'M •ĘźŇCZ—\Z˘äÚXÉhŮžŹŃ6fFlĽRbz¸×4‰'ƒ”źýó'Wz)ž*M­eŠ.o§é׊“éîK–_:O1Ń´–…JÜä1颜…‰ƒC–Sޞ–Óiţ*ś€ęĘŕČttaç3钑‘‘‘‘‘‘‘‘‘q%ă˛v˙Q[k¨Z˘ĺ|mŞ/ýPˆ‘WÝ~Y u Lüq]Ţ3Ž>•Z~dú+Db Ź¤ë¸^§†2n |kXëŹ ]c"ŽënéjęVEȤ¤XÔĚ6•ęvMrΝ÷ůhaľľkź~DlďIŠ¤ÄŽäĘZÄJ—K322222222222Ž`\Ţ1UzRž×RÍťXŽ|HŒőBĘŇHJśÓźľŐÂ=iŐÉ*ĺ‰Ć_e˝Ň•lHŇx7"M.E–čą]0iŇ%׎×*˝Ô#%=Ňă’ĂpÖ#ޢŠęI3ĽÓ#qךUQ˘|üIY†yŚÉŁŽ÷jɕpm™cŠ#].ĆĚČČČČČČČČČČȸ|°N¤ĘĹUžę,HRK–zô6Sß­Ź^óO-üĎZü3ş†đutć Rłw×*Ó>Á4¤˘źhW—Ž&Ü[´<ł.ߛ×hh˝Ć~M•Mů]–şşEÍSḊĘĆŤĺ2Ň7TEV@nšYi­b­S<Ĺż–‰ŹZ*jPůjžMďŸGFFFFFFFFFFFĆ…u´TšpÍŹ‹ž_™öÂ(œľWëůŕeœ'"Ť ŹT(*†a×VÔĹQ‰ôęÔÄ"ş¨˘uŐł˙‚Ĺ’+:śśpJéâëómŰ´ \űř}w{ÉJ8ZW••ŇSGu9ľRqŢĽ&ŽČ'=—^O)1"\|¤uJÂZqąÂ‡ęȕŠ ęÚď ˘œŒŒŒŒŒŒŒŒŒŒŒŒ+ëěţSŁI×@u9VĽœ~=OőrđCS${o‡q"Ȕ”<¨ź˜H˜TX)$BŠŁ&?‘ŢgOŚ Gޏ"#Ť•’ďJu_ăTęî#Ű*´ŽÚ-Úűu%Ľ„Pí’.Ÿœ†ł‘çdNéó“×óž VĚyKĽ¸ötç5E+=ybĹU ÄĄt{:žnŘ@ä “lb객ę)βłn;,{‡%ąąDaŽŘž‘‘‘‘‘qéÂÉ€YäĄ<ÎËń^ĘuX]]ĽVŤMCCƒĽkUr^ 7#ăňĂGSĽZ™Sľ;TЏEĘg…bš*˛˝é~˘nkôg=‘8Ń­†nYë„4q˙hyNK€j‰i)ârQžĺ EĎI’\ĄŠUkbb…¨nĽŽČĘU\y'Ş"Pşů-•YE|¨řzل%ăJ›źşÔč˝V&J˘-a˘$5â‚ŮŽEʏ<üŚ`[JĎ!92-ĽÚ8Đ´°°@ßůÎ#Ô××WÄ_'É8ŘY§8‚%YúD'Uáy§…˜ă’˝—ٍ辸űŮĽŠŠ):{ö,}îsŸĽ'N˛€´wďžbűˇĹüü<íŰwÓ[o˝M++Ëôĺ/…~ńÓ9r”‰“Í›7Óää$ÍĚĚiV ę “6çΝĺ<†‡‡YˆZ\\¤wŢy§Čo‚g˛n¸áú<[•‘‘‘‘‘ńÁÉ˙ę_ý:ÝsĎÝ<Éňýď?UŒőI?űł?Ă('Ož¤ÁÁA–žúŐŻń˜ţS?őš››+Ν˘ŤŽÚKŁŁŁ,'@&8~üD1ţOňńŠŠi–Žşę*zć™g؂u÷î=™TÉȸ ąî¤J˜_{ÉÉĄý%ş[ašÖNWu­}9§kęvţʐŽŘńU5‰ :"RĽCü§”EAc+ uYůď˝ćbĽa!Ąą˘’ĺ€UZFZ`BxDm@Éš.ÇRňDśŸ{fĄÝԚďFô¨ c]Ăa‰}QĹÚ2Üy÷Ź\ۑ´:˛ŒGl­B‘eŠHfŻ ßdÉĺ'Đ.ŞtDÖxcŔź#ş <š,ěĚĎĎ11ňÜs? ˇß~‡ßeĚ,˝üň+LŠ€Ůšs¸îşëx’ellŒ6܌UFĆ‚}¤č˝ăPt~*\ŻiUç>l•F—6*Č"ď›)Ďi]°VۍřźŽŇt$A“ţš4”äQ÷§Mřܔ´ IvčŠűÓäŻsÝőĽśŇůéšűN‘$T\]ľOëĎGwU(EE}ÓŤŤ÷u×R䚪{ äœ´VňmC:šˇňFúţi™szŹÂĎŞž•.ŕvWW[ôÎ;ďÂÎ ś yĺ•W ĄçXA˘,0arňä‰bVj€M_}őľ‚tyŽZ­Uşĺ–›™\DšG}”I+§Nâ+ĚpÂÔ9v"ÂŇ|ăߠ믿Ž…*Ěni˝‘[:#####ă҆âáá!–@`\żćšŤ™T9zô(#Żžú*ë TŕôîťďŃK/˝ÄnÁ33Ó<™2==Ĺ+p‚ěńă' ‚ćp1Ár¸˜\yŁ UjeጌŒKëJŞT“k÷Ş´_s1&r{ËňĂéůŇ\t-‰ Łó‰‘ Še†'W´ NjŽ“¤AŐ•ŽŃĽşĺ[(ůRaO˙Šö¨ź§ŞşRĹqY7­cň…*ÚV'ée{iŞ%Pd=¨ć^ި]ń'ĎůŁ˘`Ůś!ĄŚ2ŃĄKőM7´¸<ž^Są˘ăěŁwtŁÁănżý6Úśmu:6ĂEpY–ƒ…JłŮÇţҰ@Áy˜őž>}†ýĄáŢëX¨,--r߄ë!DíŘąŁ8>â߯‘‘‘âŘvN ó_¤€vęÔiÚ¸­›‘‘‘‘‘qyăó×°Ű\z!`ĺčŃcҘ*B‹KU—śkťëŹřfÎ3˝ŘÓąî\IؓžŇˆ×Î-gŤ¤ś,bhč Šę'ŢCţ‘q˝lUm3.?Ő+Ѩ.-P"–(â˘ô%k›°›ĺJZ^5Ňg"ÜgT8[Ő&愎ÜfŞ˛­zTÜ^ŇUJkż˘’o?M2ApŇîŇ\_U'%lPô\‚÷OŘ É].ƒy‰ ŃPlIňůĎžÍxA–ŔÚŰ0ńĄ‚8'řÝľkŻŕóĐCŇ­ˇŢÂBŇĐĐ0ýäO~ž]„`•s`_p‚[ĐŽ];Ů_úž{îab(ă‡ř3,hý­żő%śZ‰1ĘČn?œ\đ?ń„qT0Św:&8=¤˘ŮŮ– pţꍯfë“oź‰~é—~‰°rĐÁƒřř§?ý)žLAü”űᅬóń HČ ˜`ÁÄ Ć˙ŒŒŒËއăŇóĆm7ÄŻűkÚż>ű‡(KýĹßćúżü΅ý sHb-4í°ŠK u/ĺ(U­đWhĆÝsŸ‹UV• y+YŽP|#+mÜuřϒŢ}‡Óč.$¸UaíS%EUޏŘVŐů)Ąx+%ĎŠ¸ş”äˆŇĺm*í'nDזˆ(Jœô@ ™TŮnŞKú^ÔcOhˆôJä–ď“mŇ)ńŢ*ńđkŸmšFóôQĹ˝!óFń7Чčşý#tpßĎĘŔ%ŚżżŸú âä„‘Ş%/6źŰ\ń Áł@­âŚşËË+Q˛DĆ(MlÝO}ýƒŃľív‡Ý| ř@`Â,M\˙…Ů*XŁŕţpOČÇ@ž8B  Ę^ZZbŤ/ČG^ă–fDZŹ,€2üťäntt„>ůÉOЏüČé´ŽM—ń˘Ůl°Ÿ~&Ó222.G,/-Љ#ŻÓęâä%%T.Ŕ8{Bz܋tĎĹ1ă8î c?,VÚí˰PéďďłÇ‡MŮV&€,€Xn°r…|48—‘‘ĺ‚E>XüLřčVŠż–ýkŰżŽřÓGĂ d›¨‚¸déĐ*K†nˆ,şäŮS9ç[řů ÉťL֘ýČĘÂ2ąľE7B…( Şš0Т**ÎÄ­ Ôľ \Zĺ% Δ ŠcZ…%°ĽUDD't!E\;¸t÷žZ¤T4bżâ–ČYœ”ÎU Z¤×D‘eˆL[÷n–ň"‘ËmoNů§`䎡‰ĺuî=P5ŤűOSeIÄNěű‚l[nźN˜ g$ü9W7¨AŕLP[cQ‹'dštnśÉYž„2‚°äŽîż˙ccç'&Ćm`<ĘČČČČČČřˆšV%@jE‚qß­Ôă&K C˜qż­âăĆz' ›żŘĎ tFĆĺ‰KÚĆ,ULÓăf9Ľ2ôZWTÔŁD˜hiŽ,3ýł˙ÔŤ J°.(NŽÉQpt,%Yâd^ɗ„MĘH…Qŕôtű+.m Ă=•bľČóÉž?VIČÄç˘ô¨:^ă=݁Ži3ŸG×rtDÎ¤Ä §,‹[^ŮU*I]GşDŹČ{Š–^.+Śćeď˛(Üđ†E€“_k­tÄĄ“‘‘‘‘‘‘qiăB倵Îedd\~XRE}@Ĺk=Ôś Ö—÷zΠÇK#<ŃĚk‰íÎkL^#IEjű=,ň¸ŘőāPÄ˝Ž/~)ąNQnÉ_AD7O1QRj ą]yßşLž„ü’üů•”^ž×’UŢIśJÎë4Ÿ.ĺČ4)‘˘ey*śî‰ˆašâ Ş!VD2C¤Ř'ęÚÚ'čöžeddddddddddd\IX?K•Ȇ’ˇ^;IÍ•ĚrŞĘO*÷Q€P§ Ľ×pMűˆLĐşääWŁ‘iŤęŕŠRÉžLŹ’›— ÝŚNČ•će‘9YZŘű•$Š#VdĽ÷ŸśEYBű$ŻĄj÷¨ŘŞĽćŚ“üŁŞ˘ŠdUďT˝›e‹íW+Q~‚°* ŮsQZ+œvMŤ•@ź…2´Msą>䌌ŒŒŒŒŒŒŒŒŒŒË ëčţÓeńa”R˝S>ÍŇ% jŐĹk)ňTi`Ҋ•ZâZRŚĆ姂pH-0R{›:I,,Qą%Š?.Ź/´ŘVBů紑n‰Ó‘uŠJHŞ&J"RD§Äˆ.%UyÔÓ”Žde"چęm”fYůÎÄŤŐťţo;ĂǙFÜ€|}„;…gD‘Ő ‰ rĹ>KůĚ%šRqW.˙uťtÝa]NRĄ FŠoš˛Všz$r9a§ŤzŤ[–ŁZ´´LŃât‰d,AéxČ8&Qäiq.\Ś+GAgUŹ|G$€.+•ž,i„Ő¤x˙DĽŕź2mJ’ôJŽČ4•&8ž<?Q^ž IŇč4}M ×âwj›K'ŽüĐÖę$uRöÝq~ťZäĘŹq Jؔd×§ëڎZ_ w™qąýć32226˛\ńAĺ‚‰u&URUófUŢěő’ŽçUń Ď//—H+é–-2#ďÚC ‘`YS…bň…Ę ťW–ýްťQÔÝę$9n”{í.ńTTLV EżŽX1‘Ń…U‹d,¨ŠDą-#î•tŹĚWZťt9–>ˇîĎQś!…gŚĘŻE˛€RD>9¨Ęté|ô jÉI’ŘwD°•DŒÖ:ęŔŤŹV̆*Yŕ˜zԐ+˜U1ߘś+đ¨ó ÄÇP{źDšőpÍů–×kŮšgŻů~{ë.Ż^۞¨şŢçŰNkĂ˝;ň]ĘČČČȸüĺ‚,dš Ł֗Tá÷qí—Rű>`Y+‡k•Ďŕ‡„ŠşW§”—œřŻR†Ó'E›\’Ú&”űudA|L‹útˇ:Iť UâH´8Ž(âHüs&*a)­9Ź#Ңtîœ¨_´-ňŇé˝ë@ÄçT÷Ş’|â+ý3qiĽ%‰[MłKóJŠňí'ß7I ”É”8_eŰ×7ł}÷ąJLóp9™ăć`”żv䊊Ę܈pƒ–6îďďóË&sűČvßF¸–ŞcŮtšNîw;'óŃş\îZ×É2ş_ëˇ*˙¸ýŞëÜ­UçÖjo™Ž*ĎnĎ'-Ż[ëÎS—{Z­6­ŽŽRťÝ)œ—>˛\ĺ‚,dŹ…őw˙‘ÚazęjjľƒŽ9 ˆŞň#ŠĚˆtÝ q(đ^-,,Ňââbąg§2222.dš ăb ËMLGŹŹą¤íyeŠÓ(",üŻNęřŘóCܢ˛ÄŠälCĘdŠ˙#‘(Žxqš¨şŞTjđJœceźŠ\ĄD1ˇÝm„ÇŠËÄ QéYťý´:šbÄľ é Ë‘ŽtŸn[—UíW4LůLB>T]ÚŃíë(;•ćYs\śł'KdŠ=VVrűq0ä”Xᕃ˘’“÷Ăs^ š".њhŁą*ŕÚí6 ŃŘŘ5 ĘČř0€witt„űěůů˙ne*###ăŇE– 2.˛\°ńđŃŞľZœî~şŞ—lĂ~^Gšˆh'k%2ŽŞž°L!§řÚÜ•´uÔ-"Z,ĄB‚`ĄZrĄŽEힲŢ:Ô×VB1—~M2]Ťŕ–WVpq A”>IŞDDU?ĂZâD'ůÓZ¨'X¤ľˆ<ŤŤ“G'ŤšźęxD`‘#㒼„%Ł}˝’öŽŸŸ ^ˆšâJĺDuRˆxYť-/8Ó^ÜŐŘŘhœ2>t@PŚĽĽ%6ůÍł—.˛\qą‘ĺ‚…tő]wL÷rUäJ’§FUş’’|!ZŁźX•^VM#r!\–’LÂX!r ’ä‚î•00gMT‰HWňq§b‹ -,XTíľĽ`ľ^‘ˇq=tk˘ZbĹŠöľ(ŃU~’‹JíĽŇ]]“ż*šż(‘aLH”Ékҡ9 şDˆPjľâɓŔlÇ.AĆőJÉÇŕÎŰ|Â-…š¤O'˛8rçťżl—œŕ„)řI÷őĺA-ăâ Ůlđ;Öj-SˆKĽ(####ăŇA– 2Ö Y.Ř8řČH•JBEŻFž•. NáŽHÁ6¤„JySYŢž×ʌŇVˆq*n™I]}˘rŞďu TĹUI•nk!ůJ9Gn8—!а“/"bd„KÔě+îEě›{÷žž/Ý_˛UM Ő<ÔŞ÷!1đqg|;Ůű(,.e’gr˔.™í@^ÉgcHqąĎĹ&NËVŇ÷Gœ’/•Š—*Ő×5ź–/HďÝĺ„.#ăbƒÓeddd\ÚČrÁƄ#ĚZ­oĂ ÄƅX#áz¸ˆáďBóĘrÁĆŔGBŞŹE¨čľťSĽéöňuŢ]Ćo‹siú’Ľ]˜Ň(•lf÷u…›’"ž0dŠŘ—ŮV‘ kVW ŢCkŒ`˘b…(rE‘IĐíľľLąJ¸­Oě*#ŘŰ>qŅ•…ťg‘¤Î2GfOéą.űáe§PK’%!:jS>"‰4ę^—ňŞK!ÎMŮRˆâđ4:TDŮÄZ°0ń3R1‘"ňŠlݧę^ě ˘icuü˝/˜ąÇßęh:;ץWŽ­Đéš6u4E}łăÝë/dĄŤśôѝűhd A EÔM&ŇUVFFFFĆ%‡,l,ŕy‚HY^^fÄ "$4ÄĎé…HC^+++vŸr^ VW/äJ– 6֝Té™PŃÝ_Ż*Â#Uś)áĘ()ĺ:‰é˘cR— ěZ\b+Ş“ü“¤Ő$‚Ž •řWG÷ąL\ĄÄë„(ĐZ(*˛Žˆôř`Ž5ˇ(‚ń’$WŇĺVđ÷˘ĂoGŤ{7*ߊŠŐď“`zTýő)É"ď?MŻÄ ‘7ŞŠdŃ>O PlĄâŰ\+$I+Á¨ğ%ěÚ Â”’#Őí҆Śt-ŐľiFĆ凕śŚ?xzŽž|k™NĚ´iqĽ˜Éި!4ńŒ7˝ńĄ&íßÚG?rÓ0ýÄí#Ô\cźČrzFFFFFĆúÁ‘ XmÇY•¤ŔŘŇŤ<Š3&Jť2 Č—Wo$ e\ćXRĹľ'ÓM˝ś˛ÖíźŒIďË_]ÎÇjľ1ĄRĄ5wA‰źˆ (MaĘYИXI,Ttů‚ôPHVŚdŇ{#2QŇŇD'䋊•–-‰ŢXƒ\Ąľ ŚNtťşL"Ľ×'¤Őů˝C&ó’ÓKÍă/Ý?Ő,Iţ•çR…(˛P‘ÄŠ$STbąRGŽČç\Gޤ#ާö‰’kM=—(đŻ„Ę˙üđ4}çĐM-X •Ş„3]E÷^ÝOŸ˝e˜ŽŢ_˘3sâÚEú7OÎŃôb‡žt˙+ي7#####ăŁt* ľ$ˆK"dnnŽĆÇÇ+ÉIÎ8ë”neÎĎĎ畣Ž|¤jKJ˛T ‰*XťXB•k‰Xđä%„ŠŽ ńSą#ÔÇeËU§U—+J*"F"ŤA¨¸sşîž¨\m]ą§d™ZG*(ňr[DD::–.ĘŰ+šRÖćĂÁˆ`JžSő{BĽť. eԟ“9„Ýft§Šľź6}UT=•˘Ë*>˝Ś˛ – V¤ ‘^‰ľJ Slä”X‰*SލI+*BÔS[nDtówMŒĽiĺŹHˇ<˛?íúĺßžţęĹZ\Ő]g‹đüř­ĂôKŒłeĘ`ŸyVŤ sűŢ~ú“çćéËĎĎӎń&ýčÍĂkZŹddddd\žnƂ1Ý/ËÝöËůÇyšíôź<^g‘ć{9É4€k§Ł—––ť*˛,+‹‹KźęS ç>”*Umęˆ”=22L ŠŇ…̨#TźbçĄ*…ß „ëůŕ>JćŻ+”DU•q9Iůş¸ŽÝľO‘Ňíĺ‚Ý˝8-ęęŽbĹ]+DąŰ ĹŢjń\Ĉł°đ8A7m<<˙Źd{$Yéҕ•ŮUKáNŞŻ‰¤Ríló‰­lÔ=4ťäňúkdŰę„pтÜŇń=ŽOą Ľĺť/)ŢŞ@rňJ'VVVVéĺ—_Ą'žx‚÷÷ďßOŸţô'ibb˘$Č8áÇ °˜pAрoűÚˇď*şîşkŮźTŚwy¸kŞö{*ňŹČÚ@óÎ.uč÷Ÿš[“Piâ-ťűčgîĄkwôGąSú öd׌>úâ=ŁôƉeúë—çéĄëil0?ƒŒŒŒŒŠ?ů“?ĽÉÉIúéŸţíŘąƒ~ă7ţ5 ôÓ/üÂßäxnĚvăüěě:tˆĎÝvŰ­ţüéÓgčĹ_˘}ěÚ˛e çýKżôËôßţˇ˙ ÝpĂutňäIú—˙ň×éç~î‹tǡ{9ĘýŤŻžFťwď.ţvErĂďüÎďŇžđ“ôőŻƒ~ř‡?CďžűÝ}÷…r?É'—2PĎ3gÎĐżů7żG;wî ]ťvŃç>÷Y> oű;täČ1Úźyýčţ§ŠBťÝ*ȍ:,//1"ŰČ.ř“€|÷Ę+ŻŇÜÜ<ÝsĎ]488]˖ĄĄÁ,—mpŹ?Š˘ëUŽĐ#6üž’{ąćWCE§Ž@˘œ(ďÚÁZŁ)STĽĽ§É"A'u 䝢'Š' üY‘>(ßťř$J|´VÖŰďŤäy¤ä€Né—r=5ĹíáérzÝĺ=Ş‚îšRĹgtrFĽWŠÖÖÉľjm>NUźwŠžœ’S1a’źý–‘*äŇVœsnD2Ÿ¨~˛r%bĽ|üJ„¤;ÄçřťźăŽ;襗^ŚłgĎŇŚM›X˜ůł?ű2 DűŘ˝Lœ@؁É'ú矁žyćYúÔ§>Á様šřîwŸ¤[nš…śmŰĘ×~á Ÿ§G}œ^{í5úü眅‡§žzšŢ~ű‚Ŕů›šbĆg>ói:xđýő_?Ložů}éKż@?řÁóôĐCňLĚłĎ>W?š­^Ö^ĺ^Ąé…NWB'učÁkéŔö~j&rZM˝m´I?tÓ0ýÁS3ôÖŠUşs˙ŕ•öŠdddd\1Ańöĉ“…œ0@çΝcëŒĂ 3@”€`Áxţƒü€ž÷˝§čŞŤöă÷AVŸxâťL’ěŮłÇO5“/3Žşę*úęWżF×\óâą_kÇă˝÷Ó#`rf_11ÓO_ţň_Đ˝÷ŢCŸřÄCô­o}›ýÜĎý +řŤŤ-–9Z­6_2r…“$As)ő}á…éÁ`9ëŮgŔÄÚř•W^+äŻÍ,MNNEd‘„#BR ž^,z ŤĽIU<ě=z´ ĎŃíˇßĘďBlQÔáë2Оąą>¤Š×–ăCńNĄ˘ŤÓ+]“$KbB%>ĘĐÉ ó‰ćř˂´n%¨´Ž2iŒ´Îu–)%˘…¨‚lHgZăŠëäŒNˆˇtّ^$’lIëžIŰ-T%m‘%’LĄ.űéľTwźŰs"*-1]e×QG˛”›aúş‘,ŠAźĆ 1ą˘Cžţœ*嗖[ËhRk}.żąŇýڍ iu‚_  ”@¤źřâËôw˙îß.f­ţœśoß^̜ĄŸř‰çß/ů+4>>F<đq&`VVŢfSÔǏĐŐW_C[ˇnaáŕú믣÷ß?Ě3Q‡fsŃŁGŃ]wÝÉÄɉ'Xť˙ţűŠôŻĐsĎý  dś1Ą"fűöm… őhAÔÜĚdOĆÚŔçtdŞľV7aű6íŮÔ¤ąĄzĄ+p Z^iŃššvůăËČČČČŘ0h4+ółłłôŘcO°*âq|˙űOÓôô4ý˝ż÷wčˇűßÄĘĎÓÓO?WČƒI˜ˇŢz‹˜~ęSŸdůa~~ĄDěoÚ4Qä1ÄÁsĎ=ĎÄÉɓ§˜Ŕšűîť ůâ(5›mÎăĆo`“8ßűŢ÷™Ě"ď$ş••ĺBž8R(űƒôĆo˛ľŹ'\ěKˇÎ›¤űîť–É )33ÓEۍm3Ĺm y¨żżŸe.Ż‚tŐAžÇŽ/äĽÇXÖrí~睷ÓýЧůšT]çŽMóB{~ë[ßa’ VÍożý.[2#Żşë26&>ژ*DŢ˙0%?Ěњkşć•*ŹŃ˛ź*Ý3II] UYÁ*k ]i/aRvl…Ť‰”@´¸ëJF,š*ňÖÉa%’Z@ŘcąâŽĘÄ ĹdL\^€ŒŠŽĹPz]ôÜ*ŽĽé✢ң˝nŻœO¸š:‚Â'ń˙Ä÷Qş˘mŞH)ąŸĆQQöů—ÉGz„ t”ĄyjňšĽÁmׂŚ*b…bóʀ1á…BÝą3…˝ĎH<ţřĹ@ş‡ŚŚŚŹďěťř@¨Â ÉřřĎHR%eÍx-˛ —|ť*rŠ Ëb”ŽQÄ+ľěş –MtĺĽĺ€ŹĄŽćŇzV‘GUůWT6(ńV+×VAq× éŰrČ[O &Äł‘=t’†’|ꈔŞwA×ŢaŐŮ čĚtBU,%‚ĹnT,!UUťI.D‹ĚK–B™"ŇŞ˜@ńTâ7:‚ÖŽ‘ýĹ>ąf0;…'üuďż˙cl™‚4pűƒY!¸í ł˙4\2e׎Ĺ Ç<{411Î&ú§Ɩ+0ď˝őÖ[Řź¤ /Ű[^˜Š Ň,pA‚i/,YŕÓ "D ś3ÖÚő†]Ô×Ŕ @ÝӂLyăĝĽ=[ú+?‡ĺ–ŚW.Ňč`ƒ­Z˛÷UFFFĆĆĆö;v„Ęë<ţBYŸœee–+ĂĂC,3\}ő~v~ýő7yŒžćšŤyňŹúű:&ŠnŢźĽ˜ š—ţÉ?ůyLG> d #@7€,ŕZX@ĄżőÖ[ âá9ŽŮëUƒ ą°0ĎV[@Ŕ<őÔ3ü šd˖ÍtŠŤďÜrËMôľŻ=L7Ýt#ˇÚ Ö!˜Ô‘×j/ƒƒ]ň łH ˛ ¤Wč7u˙i&ł#iěoŢź™ /X!žÎ˝÷ŢÍ2Z|]Žsw%@őp\‰}ˇÝżîŻi˙úěŢnh›˙é?űí'1{ H…3ľźˆ”i-)€TMŽś‘é$! •Jk*5ĹÔĘÇkŚŤ^yF’évZהLŠ#"ŇźK5ŠŹkX.Ů)ů*ŮiĂĆZn )ђäRŞk%™’<lÔÝgUţuĺםV]uS–TíNœŠ÷Óçn+%M˝ň˜#ƒTůyúrzĐüTRɰE7ŁëŻŢ̂4}Ĺ ˆă ÖÓg7Ššgg0ˇŠ?˜ĺ@D÷Nc”&śî§žţArÝp÷ŁŞžnŔ€ “T)˜Ů@9_e‚­R@t€4A 5ř4ƒDÁ€‹@v F0낙ŠăÇOxĄ ţӘa‚uËŢ˝{ů8ňœ™™Ą;wň˝@xÂőHƒAł_¨ÓŐW_ÍĺŔWĎćŔy_xSV "ä?˙Ý3ôňą•’cHXí´hĎX›ţ/ŸÝF?tË ö7ř[s×´‹çóʑEú˙ľ˜ĄÜ;B˙÷ŸŘACý$]<ĎY6ő6ßHĂżkŢ ś~ßJFFFƇ…ĺĽ:qäuZ]œź¤dŕbÉ×qoă&ß/ĆpՁ啥Ąáb{’­LĐĎĂÖ'Hˇ`X°@Ŕ9ˇüîűďżĎąVŕ y4( ő€ !tśó˜‚z"öۙ3縞f9ŕ†-o3—=::Ćů—˘I–GęîëR‹‡ręÔŠ˘]ŮÂň\Đn @Â}V- @>š9/ä…<ÓՖđž@ś3îUá8ޅVk•­ăz(~6x&u˛e– .>Š6|°ř™*ţV‹?D-nŮżśýëˆ?-~ĽZZŠ’ú2¨Śědű’*˙şDŞTžPŃľdAt˛Ł‰j •ôx¸,Ř tmŐĺQדP~_’@ţXŮTK¨č5žpˇ*Ľ ź=(÷ăsqúô€Ş>[™Ö#‰ARő~Č}yŒ¨űąŢĐ[}U×$Ş÷÷b ’%úđDŮľd %Ċ˛ÄŠť^-Uϲ˛ÎŞŠ¤+žTéVVş-oxžč%/˛{úégč‹_üi&^ň ÜФżšD˙Ó×§éŘTŤŢ˝§€;­%şmO“žôŔşëš1Ú5ŃĎßÓŮš˝yb‘ţŕÉł´ŇQô+ŸÝIwěćo .+ OW"Š’ćß;Wl%ąÖ’É—ĂxSײÍÜ~@Ś€”rîÖkyřÂłO ż‹‹ lÇšŹ^d,„dŔ[‰,ŹփTYW÷]ÚŰZœŹSŹŁkTr}r:&jŞ 0şş4Ľ‚DĺyŞGŠŽ5÷XE%×K—Ą’UGTf9`Şřń×+“ÔüňžśűvÉęčœŮ×q–Éýé¸Đ‰BĽň˝H硫LŠď%†ÖBRßt+}v•ˇ*Ž’†NËOߝä)ŰV‹çăŻU❨xç˘4b_ŚŻš4ÔIX‹g˘ŠÂ%ˆźPEŠV‰HKVi2qe ݣ˗t˝ßŸ…^óH=Ů!+5ň˙řÝŽnšĘ؊č(Oq­O#ž—$RH´ž•ŚČJE§y‘xŢ:ąL˛Ý˙Y3AFƆCǎĽššYOڰ…ťŇvx †9ůŢ=ťiey…ÚXmŞŁŮď_Űt~E8ŐŕĺՇGŒ{*٘I˜/7ŠĽHaąŇß?gN322222.Ö?ڊÜL'„eI TtYąÖş>oAšđzH‚¤‘„E1ᐺËDçtrÍůXETéţ5ő‰b¨ˆc龤kÚ¸˘|łC’U.?JÔ7+j­BրŽŘKȝ ‰˝äÔKŠzBǧ¨ YdUÂ%ťńƒ´ÖŐBUźŠb…(Šs#/ä´ĽDUÁlYć*\â\ÂŠŘ ‰j^í,›gdddôŒ…ů:sćÍÍÎÓđđ [š(Űšwě:ŢX‚öŞŤöP‡ýóě>ąŇěkňňö@łŃäĺ7]J^Bti™Ś§§ŮZ%######ăâa}cސ$׍”QđDKK,Gů†Ź:¤KîCe+]™‡Š”e•"”‰ÎQůpšžÔĽîDľ–)%˘A÷JŚ”Ď; ‹`ĄJ.?ćD [\ŠĺFÍN×ňŁcZWŚŃÉŃ39_ĆC¨¨KrYbÖQI°(™"š^—)•ÔíF>“ˆHĄ˜$тĺđä‹-Ř]G=:Ššś=˘JÔ2("ł ĎŚŹőőddddœ?–WVhrjš-UÚzœú–W˜Xéköń*čYű RÄX¤ŘńE9+ĘwV+áÔiw¨]ě#Ŕmťmâł 6Ëčč­Žś(##ăB‘ĺ‚ŒŒŒľąžK*K˘ %;Ňm**uD„ČÎ*—šŇUrdţTAÔČ|Téx`LTR–ƒ›E*‘-Q˝ĘeEŰ1§TşNפ­Ę#='! TĚž+#lD÷š.ç]żCݔp]wLWÜWÍպDzŞ3ŠY´şŤuúœUEůZ…óŃFU‹Ä7¨U¸6%R´(Žťu‰ü7\PrőQńš¤ŞŐĺ”ę_żwšcyy•ăŮR>ăĂžëĺB™Ö]yelD€ä@@ZXubqa‰ťäžŚą0i4ÍÉ͆ą@Áq*2¨˘ †Hź*Ż6AšóëXgl#ŻT\ĂeňňĚmĘČȸ0dš ăb"ËëJŞhąUÖĂcFAĆZ‰ ]{%éKV*V™Î•ęAĽĺjJ.?|P-U™ĆĐî"ťS&t=ąP™ž*‰_šş:č˜\‰ˆ$Ľ…Ĺ„*“/k‘–Öő$Ó5WFÇtU–k—U A´‘RľWËşŞŠ˛ľxśu<ĽŞëđöř@Á+œÖ?(ŞŒˇRE¸Čmqš%vTt<ƒx źááĄ{ ă˘ăVurqĺ@3áŃö+D°k˛śńR: Y“*X*™ƒ'6“+d)6*çy% 7N„hlÁUWů1 ,ν(##ăü‘ĺ‚Œ‹‰,lŹ_LŤFDHŮ!öCöˇ”L>„í˛Pš6Ž,•Ŕ‹*Ťź~ D.Géš2EŚ­"SŞ JČ+,jdŢîŢT’żŘx[ɲT=ątĺ5Á{íÎZEԓť }Qőüşd¨Ĺu=,ź‘>[%wJ–,š’ăÚä!‰.%؛čŮ$ך履uŠŚt+ś€qŰݢĺJc\ňRxůÝş2B…Wďńý3Ůe’‹Ćľ§cŽĂâĸů¸dʎÉʏÍĺá/MąĘŽĘÍČČ8_dš ăb"ż[ë¸úO`bĽYÇI´NÜuᒐ TA@ňDGÇęȖŞ*z¤DƒU@Ýżú|I“ÄljރŃv;^“_ZhDxĹ^Ĺ.>.áâgŔěő÷Ţ{٤ôC­K—ČSËz×ŢhMi Ă$'ĹgĘ×I‚¤Şď“金2ŃIşjK–(Êh˙Ŕmčp. ¸B !Ś}lsŔ°(I,[_3Oš$ŽBÉŻä-##ăbýKGko­x‚›œŇŚědĺ!ąŸœr×PőD„łt™ ##cMdš ##ŁŹ“ĽJYiŽ,2t PttžšP)Ľ­ f["Q¨4ťSGRŐ+üč Ä$¨Š­şźÓc˛Ž´Ćń^H–şrTĹľn eŢւlĐîUQ,źŐJiĽV¤ľ ×ÜןÂűš7ő÷˙ň•V›VWuŮ%L´FŠşœJ×^/ßcń´+ȊĘwCĹ'´´DJtĚń'š„u‹—٤+ČqÜ•i#b…TzIW¨+’vÉČČČ84œ;‘%UĚ_Ă)Œ¨V”Jž÷˙ÔŔ Jš]‰Y)ĚČČČČȸ¨X÷%•#…Ó’!erĹíـђä#Ó¤űŃ5š¨’|‰6D>ŠťˆŽHšĚî×fVuFŸ?Y’ŢwuU[…*€•l{@[Uß(ŢBÉNęÚMF“î*Ľ˛ěš†őÇoéS&¸ž ëüȉřwtx€Ćdžhű–aÚˇ{­„Ę;ďOŇáăS´´l‚˙­ś:źÝju„ľSťQj•Xt•mżÁÂ[‚dŠk—”h1÷¨Łœ”œUTˆŰvdKb…â 8fUx7ńĽÖ*IŇU°-N łVꟃ֭ˆě|fĂk^~P—:l1SÜxĄlgwËauś”<ˇÎ^ž‘$K€Žľu!Ą“‘‘‘‘‘‘qѰ~K*ëx¸ˆK|Â#-ҝGSŠPK”č.n?őäDšâ)!PE6ô]ľŻkŽťmÝĺúŇ}tŠ‘¸‰HyˇÜ˜›M‹'ÄTDÄH09Ňפţž[’ ô7ŠYl3q˘Œ`‡4ĘnőÓčHA”ŒŇډábűƒ4X\×W\Çyő79/ě7|]Ý읦ťoÝËřWhfn™NžŁˇß?GgÎÍäJ›–VZ4[_,ˆ¨ŻŞiTuŰŠ”`ąiĹe”œ]ӊ%J­ăIIGhů|Á¤ĺ3IóŹX$™Ż5âv lěž˝^$ —D5•žBőwÄB˜ŸŸ§ÉÉIB# і-›‹w´˙źňÁ7uöěYZZZŚ;v×÷űçhnnޏ†ÓôJ’˜źÎŃÖ­[XaËČȸ4áVńÁ(§’Đ7JŻ#ZŇ¢4ů­ œĚdĆŢLŞddddn‚Ěw0AÁĎŻż”ů¤y5í nWÖ1ڊÝ B¤Č rĹ_“*R/ŽČSĺ*4öK°JźNîCNöSђ@׍Ńóeyľçˆ*ȔętUg|=­ťOd `ËEż  8 ‚ƒM‰ÝŻRP'Ĺďŕ`ÄČXAŒlb˛¤ ŽciČţţ†'H`™";š0ńًŹCŽ ŽăăĂ4VüíÝ˝‰îšm/[ŞĚ-,Óés ôÖástüÔlAŹŹRkľĂËôÜ­ż)i—ŽŁś šŽTŁ4‘NUş •ă¨˜‹-ŮRމ[­č(Mš§cÍ`Á˘(Xšg+éo4]9Ŕ yęÔizôŃÇř]šá†čÖ[oĄŠŠ)&÷íŰGçÎŁ•••‚ä[¤˝{÷ň€zîÜdA ,ŃΝ;Šďc„Ż}üńďŇ믿Açďü-Ú˝{ýŐ_}^}ő5úG˙č˙MgΜ)–ůâřn^főÔŠSLnŢź‰ œ……šŁM›&Š÷~œëó#?ňC\&ŽďŘą&&&hzz†ë611Î厎ŽRĆÚŔs^]-úÝYÓŞH cxFYˆĘ¨Ţ G~ĘđÎ:´LŚ$ňŽłę$);Q$>ÍLşfdddé{ąŇd5ü:BčჃƒÜW÷2afä…UZ^^ć•{źK§%f\^}}ëşĐnĆGˆőu˙ą˙ëŠ-PlŽ*—u!YŇ}ż­+I–n•–‚Š*ëŐÂÚ@•Ď•łëžŻ{HŤbĽ.]ŐIU>ĽbIąRߌÁfŤ TúéştíÝ´eó[’ô÷bĘ$~OTÔZz…ˇ:ůpŕ„K¨ßć‰fń7B7ŘÎJéŇŇ*Í/ŽŇ™Éyzď؝›Z¤•By‚ťĐÔěMNű+m“YŇnZĹŠ.é’:E‰TôŒUŐó°Ď×Y“đűĺ݄”O‘'|Ҹř„rÉĎwş_ÁÜ¤Ä Q™e‰NÓÚdËFEX’œ}šh~~Ž—lÄ üňËŻňq2{÷ţ&mßž­Z$ËÂÂ"/ďřÉO>ÄÖ3'Nœ¤ď~÷Iśž*H–ĎĐc=ÎĚŘŘ]ýutóÍ7ee  ýŃfóó ŚdW ,wŰćĺpĂĘ+eŕšâ‚źÎJlF x/ú‹o8…éO‘âúW&Ŕ#wĂîŕ1Ł#sŐ| }W~322Žt ?Ĺ$ţ0ڧçp 2úLLF Tô× T\^du5ˇŇd *Čë|­š3.OŹłűpëI¤.@2= kĺ'ΚËJ¤‰ŽŇkŞ!/şnˇž#Ň­Ť…íŞ Ťę“űşúüZéŞŇ¸‘‚ŹâclŽLË4H34ZĚpu5ÍOľŠŮ§ÖŇ0ť< ŒĐČđ W<ĚRs.—˜DčĄV*”ô§ą@pŰŃŃÁ˘c¤ŰGé–ëwRŤÝ)”ß‚hY€ŰĐ<=5C3łËëÜ.ȗ:[.3ŮŇîh˙ޅ@ń=Ԓ,q5H% œ‹éœ@-Ýt<)"-WÄń@rh*‰2r|J˛˘ĹDŞaQŽD2EBžçř}ꊧéÇüÇزá[ßú6mÚ´‰Žšćjś2ůŤżú*Đss tőŐűiff–g3 XˇÝv+[Ťź˙ţ‘‚ š‰%łłł´oßUô /ą5 ÷‡z^zé%z÷ÝwŮb塇 oű;lc\‰ĚŔţł?űEúľ_ű şóÎŰŮâĺsŸű,˝řâK|î|”ł+xV333LŽ 2A…ś‡`„眸¸Ä„YŒ€ľĚďâ;fE6#Âć͛éúëŽă÷ ď[™ sô ŮŽź˜ń¤ 3tîĎĂľZÇś0‘ĐZ])Čž>ÚV˛ŽßÉČČřp!c­9âÝY+tť¨“ĺX-­(Žä%ÓžRśCęrÓ-ŒáU„J 7Á‚gXee‚ţrAĄ’–,n‚+ËëhŠ"ŹK$I˘)aĎy7 ˇOÉ2Ë!ĄĎßbEëZrBTX âCUtžü€˙Ƈ×$VÜŻî-]ĺIŻ_Zފ‘׊Îgš  %áÜš):tčmě/łAÚšc;mšŁ-[7$ĹmŰśĽ˜IßZ,vvVMĂZ̅ žLOüđě]“Ćǚüv÷Î şó–=…Úf˕Ůůe:uvŽÎL.ĐBA°8k¸áˇLžT°UdĹă*ĎYâĐ‚Řň+DPź|´r„‡śBwsĹe­ť´Iˆa[AŹT\qĽ)݀V 0ŘZ ŠL>AMv:FQG¸áô÷‡YXą=z”>L˙ńüŃĂƒ­PŢxăMśŽšbâ-1y˛\|řž@źLOOłp —eŸŕ™ĚŹ@`pBţŒľöFۂ‰bcŁŇC†AŽÁ k§í-ŞZąˇRňx‡ošĺ–‚Ŕ˝ßĹLŞfd|řŔdˆôýű÷łđÎ;ďňř{íľ+r(ŮpÍm“–ˆ‡fˆb W¸oßžÍĘD_˙ú78Ż={v“%wœ— ä¸ONž+&vŽžŹż´Ú˛ĎÍ7ß\Č;Ą?Ă}br ż{öěágPgY˛Ąâ€v‡ü…˛ŞÎAśZ‹PIÓc ČŘŘX'KÁzxrDŁM-X‰BŠťPČ1%SÄOľĹJJ¸„ Vs*X¤çŁĺ–ϧłJę™.ŤH_şś˛ň5÷¤ĂFliůNĄlˇÚĹůN ;Ô(„VŃa&vrr–Ó ôqÇżeë&Ú^+čxĆÇGi˖°ß,€Ř’Ĺ”sńą6™ŁÂĂ%wď¸'ühŮťkK–h™™[*ˆ–yššY¤ĹĽŐ‚xYĄŁ'g8(.ڊ„›š_ \ŤQäaă~”t× Ž<Ţ|œ äˇ]BGŒPt^ǖ3>˝H[GŹčŞWŮdęF@(n(ށ‚÷Ćý÷ßgÝ}–č3Ÿů ąŠ‚YaX‹\{íN‹}Ä9APZ| (ČČmtď˝÷°566^äu?/÷Ţ{7çÁŠš ;W0WqǏc.=ˆŸr×]w°{Ѝ7ŢŔůßuם,”ÁýV,FŽäŽ^–DhsX˜¤mĽ8fÔ Ÿw‚Tˇö4&ċ٠(ِvPŽ@ŞĚßu_ł/ňÁďë7Ž:ˆƒâ‚şCůbˇAü×qAÍ 6ˆW|ălůRäoÎ+XşAуë`ţţ32.^}ő;vœ>˙ůgňăŰß~„]A1qâÜ}gĹňäÝwłE$,O0sčĐëĹ8s—'Užő­ďЧ>ő ž€Áľwß}WTvÝwíʄĹęË/żÂňƒ›(H­VŤŹXă ˝ÖRý݉'襗^ć61ňŠO}Ň×cí“O~ŸÉXŇŁíË÷ŁýdÓůňŽ“ă¸ÉŤUé>—pÔŽŢŇuČXÉŹőďä áëćţ#‰‘˜ń‰R ˜Ož¸ËŤČ“x_%éDQTK¤$Ôb2ÇdĄ•PĽk’"jËŤşF'×Jß >Ž ˙Ł#Ľ^vĹ<śầ  3c‚\XĄé™9zďÝŁźŇĎP1ŒĐćMă,ĐAAŮ˝{G!ÔmeFžYv%)_zUíÖ8ďҤç{éôť§ .޸'ÜW?mž˘Ť÷nf!DËÂâ*œ§É‚dY`7"¸ -ĐácÓtnząh:]z¸ągN >4QÉbÄ jÚń!>AüŢů“ń ŇČ/ˆeŮ݅XńČH'MVäî•X˘@8@Ş@9‚UˆCˆ{÷îáwď ȸlÚ´šȋofxÄ̈o‚t E0ČCPřĄú /˜Qơ‡ć#GŽĐŽ];馛ndýľ×ńw#)źxŕă(B ĺ‚$ÁžŤ‡[ŐÇĺƒô¨`š˛sçN&3!(eĹŞn%ôik’3‚•Š|čťĺŰŤ™qƕ“fňľřo°řŽĺL°¤Źľí×Ăę=°j°A“‰Ó‚äsďĽO@ä˘ ŒÁřÎ`y KŐ×^{­§DÉ$+˙§Ah<őÔ3LH=zŒ>ţńűٍĺȑŁlábÜyWéӟţd)o¸ľüŢďý[ś†˝ĺ–›9ýW3Š€Ŕř c`bękŻ˝NˇŢ ÷˜ôÇüglŃşuëV&`ž{îy&r˛ÄéÓgxőĈž“;O?ý ŸG,8XČ<ńēÇmd䣉˄~pjj†Űuhh˜ĺ'¸6câö̙łź*#îŃ­ŽX‡ÔUm˙Č#rčożýÖâ9|*Z-ąĘĹ'=ˇmX˝ňĘ+ě†ůîťďŃ'>ńPўŸŽîăüIŒ ëŐöëcŠ"X„*‹O˛ČtČOŒhI”č„XĄą"y]"St‰*‘!Frź‚dŠCšž“+(Xý´ť Mŕn%}dx PÚ! 5 ŤŸ‰•‘âȔŐXRÍDŠ#S´ł(ął]đ݆ŕufr‰yę0“1q]Â=ŚäˇźŃQjŽ,ţkô7źŐ :({-ËÚňŒ[qIłÓ0A_ ‚Nže2ÂⰌƒţĆ7ŃŽŰ隫÷2™vĺMăRĹ˝Ž‘*Őůşc˝œŤOç*ü 4ŒŰĐčPA€[FşPÖZm&SŁe‘Whzv‰Ţ<|ŽŢ=:VRÚŢAź,˛łF‘î?ry -n_‰„áZKś¸4>oą´˛Ě_ ë9“íHŠŹ/`ľ"ărŔ-h-˜÷q€ýš3zÚĚY÷Ź\ĐšVô’g&˛2ĘP<űÜl7ăÜ AâHsĚ[Nâ߆ őHyöÝÉSîÍlˇ”]4ϊfd\Lŕ[…ťV|űíwíŞ|sěŚ ËVXŠ‚ätnŁ W`ŠKL’|ć3ŸbRÖ¨ ]$ŕ —ŢżüËŻrűçŸĄ¸~/A§?{öšŐé }š]ťv1‘ăĆLΠLô.îŇŔĺőäɓlUkXXśŔ“6pąyîšĐ=÷ÜM?ů“?Á„ŃoźĹÖ6EűÂ*uEýPOXő |á…é;ßyÔǎC{ÂÂŚĘB4AĘ|ěc÷ň˝ť!í=¤Űué1ÔVÇ QĐwăš?ôĐCLL­•OĆúavažÖë¨62@H×ę˜\Š%Tt´ďś‰ş‘+:ٗő*×4…Jň7CšČüÓ°–'¤‚ŔŘč[›ěŢ1F[6Óđ`!Xőł[É@“IŢh𙧆łŢpV,žÓN 5ŕSm‰÷yů.˜ž)ŰnÁ˛}Ë2=ýRŃIOÖßc°n°î%Uʲ´ˆ Đ9€@i˛ŻˇL™Ԉü˘ƒÓÚž§™âĎ,őŘäv€™2ŹY0[żs§ąd)>˜g*2.‹Śj   ą•Ź,Ρ“Ť"nĘů@Ƥ7–Ÿ)śmË(›wˇŮ|ťC÷Üś—ÉXłĚ.ŹĐésóôú;géä™96ů&-E˘ŇĘŽÜČŇBB+g{[Y$¸‘Ÿ ä‰I źŒŁ^(;‚dIż­+uĘô…–kY;\ ô)żŰuç{íŨOUv˝bË\‹ŕ˜qŹËžđ~{Y5 [ dÄpqR`AŇđăšň¤ аńTĚqe‰˛Dx°jéŘń^ٸ Îe×DŻ%/㙑qqaˆŠ-477Ë :H‹ăÇO°k.ÜŕnëClôŃďýŢżcĺýŕÁƒl!ňŘcO° bŹ=ůä÷čúëŻe SôČ ¤ >m¸óŢvŰ-ô‡řGLŔ<řŕE™ó|ÍňňŻx˙ýŁ/ů/˜1mĘö3 ߗ¸žĆ˛ž™­*~ř›r×Ä Ź7@öŔ]+˘ü_ř…ŸŁ°BűᾞyćقعƒúŁa‰ŇîQ°ZA{ፐ-Đ/p}*ƒ¤ăzkSšöŃsěŘQvżÂŠŽpŃJŻËîŔë芳Ĺwň§ßř*­Ö-PmDŽčj §¤ałC2mEDAR"P*ΉiˆQ'Ü$‘´Ž(6ŠÎhgAœ îĆî4>6Č&ĂĂý|ä :Źžţ‚4ąÁ[ąÔŻĺb"ľ\Ů6! ßéŽ% 4)ˆçÁ╽ĐX¨t8âżVqĐс~<ŞŇ"'ŐŒ M•Œ“ŽŕüL™;ĺ2´Zš#Ŕ\pŽŐ˘snˇ}{‘b ‹{Y)ę=;ťXt’ç¸Óg“ĺ‚h堑#´oď.şîúŤ z7 “B}"7Jo@ŐOĎšóUĘÔ×­a˛Ě´Ń9ƒ8ŁâŢ Ö˛ďĐ'f—rž[*ȕ‚dy÷ ˝{dŠƒäÖ!˛8ńížŕ\´ɍIbĹfF.˜mę$čĈšr8ö—…‰-„#€ĂŒ f˘RßŮ^€ś‡`022Zőb>҈ő’ş&3Ű)+˜ÄőĄŔěő…ńaB%„:™ 4.¨÷›ožY̸ÝpŢíˆäč—aÚ 3b˜SWůˇHŸŽ¸äňr“Ćîö?ůÉOđ1Ä yEť@yA°[ˇŠ:8 8 kń˛ÂËAśŘmčô™É‚1?AO=ó"  dÄ0íŮ˝ƒŽ=¸ż`öŻf…KR*1ă—ÖŹâÎëwŐ ŽHSşDĽ™&ż k‘„Žvp°ß§];ĆéÚŤˇŃÇďÚÇîCóóĹะLGOÎŇËoœ˘c'gÂs–V[ŽßSÉópU–Ť˙$V(ĺ`Ä˝†tľÖ*W0+„Őz@ ÂÔ‚Vî-fKŽšćj`Š Áä„,› óŮ뎝ŽÂ!ň?VBŕ8<{˜‹"DöiřöŰď°ŰL†Ě~™ŕvÇ9 „Ą;wąO6w(đ8ţą}Œƒ¤MOOY!ď&žfĹPfQ ˜Ŕdxvv†‰ řf#-f~ž÷˝ďóŒ2Üß­ˇŢĘ |†1dévřŰÌňF}Q6žcĚl˝ţú›VHbáîŕÁLH ¸%Ą}Í‘ŰÇґhł˝{÷r[ ž¸D„'W¨;ęŠ}Źh‚Ő bś uƒĎ5fŮĐŚ0iF;ˆ>n˜đ›m…üäď­ˇŢ*„ĐŤ#˙qĹxŢ0×6B[ƒş´E@Îde6Łւ$XŢęä˝* ü쀫T š1Žk1Iá\‚‰źĽhśTÉȸ¸pńÓƒDäˆwšş€É7á&ÝőÎÍENv!Vö‘ŸËSN>ŕóFué@М8q’ÇŹü¸'Œ5ĹDT7cIŠy|ďćf ×Wż Îj'F ŒÝjIÝšíÉ°^g“ޡ#UЎsäńŞôîœ{ëŒĐ™˙ÝWţŒţÉoţjĄ›ŻĎŞKëçţŁ…Bž2ȕ%DK´ŽÉËuTF)k†W Éš6ŘmŠ|ýwWmĄűśĐÖÍ#462P|,ƒL xÓ9eÍpń_#"cQ‘Uś&éXküuŘzŁ[y‰řßąf{^‡$Óp#“5+Ëféš<ŁŐéč¨ZŽ´IşŰhŁX'j´v÷ć-5ttÜuĆ*ÉZШ "(oS7YčciĹ‹„‹c̑vW—V śË9ĎĐŃc§č™ç^Śţ˘SŰT0éťvmŁ›n~Đ(ĂóËź´ó›ďžĽ_;ÎŰ.˙Ŕű„gSšúŹC´ŇO°Kń[œ$Ă˘éüďňHƒ÷ߟäoî})żÜď~÷IVüaŃqçw2p÷ݛY™Ç3CŕX,IŽ€sPřOœ8ÎÇ!耔Ŕ ‚Ů™•~†8¸,ˆ  :P~ajŒ˛á&‡tđçE€9|  @źřâK<ŤŸnX ŔuŰ 0řĂÄupÂf°ŕˇs(Űďż˜É ĚR!oa€wđɞœœćĽĽąŠꀁ ŚČXĄ„ÎîÝ;éĐĄCLf ŔĘĆľ×^{-Żn„ňAŞ`6 m„ yXU „{¨3,D@Ě\}ľ!<°ô$ˆárąŠ|Ĺ!džúęk|ďŒ ßs´ę]ĺrĺÔm‚ŐäLú$˜#M7Ť$‡p‡g—g¤2şa´xŻ6>Š7%×id?xń–'TTˆŤâÎc’‚Óyľí˛ĄnđŒŒŒ‹ Q˜ëđľŇÔĺ…1ĎĹS[ë:啖Ká&< W¸,݀žłÎ*Ő4ěŇżş•QU.ňĘ÷úŔ‹ĐĽí?ü[ú~ëWią˝ˇlÚDëułT‘%ž,qçtʐGiş*)âtI—›óInr\™Önß âd+íßťš QFŘÚdxx€]uŘŇDĹŚ¸î[ Ö N35D ťéŘ †ÚZ ”ËĂ>ÄhNůú˜­ö)“oT{ q›Ä)‘ŤÔŔXĽăÚ-ÉOĹęľ˝%ńźZ ĽîA:"ƒ˘SV ˛{ްB níäĘ7–=xű¸ÍÚí%ż”:6ż%ă3ř ¤NŸ˘3çŚé•×Ţ.H–&+[ۡoĄëŻťš$ËŚ‚ŮF >XłôY˛E5Ö{‘Ď*%"ᙈĘÂ}cńVUR´D[ĆÝwű6şíú záľSôÝgű6גĐS"ř­eDÜę?wIŽEË)ťZKíʢS œ[Ź,@@ᆂ§šoďŤ3 ĎŃĚ4ń7Ż‚_-“†íŽßGżăs˜ŢÂĚä fť`Áá”)CŞşŮí~§œ5íť+DÉ1YfÉgç~Řŕčţđ˙•$(gňb>(_fś 8¤”ëŻáGSĎ9;ƒŢÇß´\IÇ´›Ůvˆ‹=žŔYv9kÔß IÚ톺ťXNnĽ$.čWđÜRs^wŸÎrÄţ`eăîǙ›´üot=ˆ´3Ęęě6#YnŢy!}ÖRłş_ľý:éČĽđŰ ÁiŰŃwœ-U22Ž=öôűźÚŒTĺkK+4;s4Ř9KÎ٧A˛ŕ*eZ;:>aďBżT]&X,АđQ&&ÇĄŮ3‚B9ᑗœ´`Í%avĘäřř]{`_Ąď˘í;śs§ĺŠX__ĎŠ›a÷–%:´“l œ‚;WŤÝ˘V1“ŽgŐé´\͊wÇ̲7KčîŘŢŤ›Wâ2ď šďäkoMҡž|ŸYţ(m'b›Đüš÷‘ɧ"r&”Łěh[ԉë[24 č–ƒătĂ5›šm1 Ańíłš uńIŤ HňĘ­şÔ˛fš°>€ N§1J[÷Ď|Đ?CœÇ}ŔŻšŽžZ׿ű¸ţ­ˇŢć€uJQ4ٜŚ?ßö@z,ˇˆ÷U.—(óÄ,[vďŢĹ1OşjĐÁ5pŻqý†´Źşž[ÝŤŽGý‚%ĎçÖežŇŞĽ—úŹ•ßGÔdĎüü‚ýFÂĘŠÁÄOÂhCďŔ׿ţuzřáoX"ŻYŤÉŐ:ńÂü7ĺĚjKžcě[)úš[n˝•žôĽ/ek•ŒuĂňҝ8ň:­.N^R2p1傌 ŕBd;w]– >?ĺí÷ߣ˙ę˙÷ßÓÓ/ż@­N;R57Ol˘×żňí‹Í)$/ţ`ŠÜ˛mű×ZüJŐ;2Hëą~î?–8‰ #`ŁÖlÖÝçĚƛŢccC´sŰ8[› ĆÉĐĐÇ yDy%RźĐŃ:ČÎJĂÔqî9â8‘Hp:bÚźĆ|Ă*éFĽuÚAłQă?ď¸íoŘ(¨:ŘqT*‘‹“­3f\—-ĘAń óľŠéšœš)Úbn˝ĺ:Ú˛uS°:ŃŇg–y–U’PĎĘ%ôĎJ'č4?mgВ{R_ä’â­%܋ŕĎë@žhťĽT9OeI5efű–W–ŮG,eŸur‘śůý꘸0‹K+ úäŠs|xĆ‹Ůí}űvÓţý{8(⹌ŒŽđLźSĽUh,3 ›żť#8é´Űţ÷Ö=Î҃´Ë@žu|#Řvс´3Hăf†¸1 ÝÍF ^tČÎn^{ľŚ'%ë”P|d‰bŢYűvşmĽ|,ClQ"p㢛4„ǃFV Ýҟ/óĸâ4*óÄť÷ăvłVš­Oŕ2×lĆËšßęŤ.„ şĐkŤňşPóŒŒK ašmí•<c%Œű7$‘(]{źŐŠ“mě9řž˛+ZFFFĆ:!Ë#ë§ŸżţÎŰôßüŻ˙#=űꋴZčK>źĆ:c–Tśƒ?Ďn›e†ôŐÍĘ@˜@,“Í›Fhűś1Úşe”†-q20Đ'–@Č(ĂlPĐ& Íč@i—Ž;‚˘ *aib;—Ź3˜Źi°‹‘ˇhe•ę4Kń@•8F:#XĹÖ)Áku‚ : L {ž\0˜sq2K§Îœ+ţ&ia~‘ڧçčÜä4=r¤P°;ô‰‡î+fœˇlú„/‡I†7]ŽŁ#;TúŔjîËůoŢNW%J‹ąZ;ŮöÔŃ,›íŁcö“ĄHeݞďg邼šwfxž3,XŕF4X-ĆuĹ*œÚ¸ +Úőěšizţ…CLĐmÚ4NˇŢz=íťj“Ś_+ŮgšW§a§V%˛ƒŐĄě]ş[Ó›şĘڃŤüË>ö¤"W2h˜E™›[ŕcX $Ě Aľ R'8Q €"ք<ąâ0Uš"žgĄŠ´ú¸ł 2 f´.֚qvńXzsMĘČČXŇ>¸÷˜Éą\˛1´!ąA’0AâˆsAô{KIűŰ–š™TÉČČČČب€~ôâëŻŃ?ůAO˝ôZ)ô¨’ÜZRĺş;8h",P6M Óś­ăü;™łnŽ^ŽęrŰf^3É×ü ŇŔŕ+Ÿ} TT5šĽŮM DŇ6\€c[KŕÓ(Ś~K2(KXho$RA“V–—‹÷żÍŰ>7íŹPŠwa Ë&/p źˇM„“Z?ĎÁĄÁ‚l4A7űú86ŒY†Z‰śŒ‡Íą@ˆ˜}UGŹP NH‡x*ŇŇĹYŽdB%###ăüŃ/–TĆV‹Ňv9dĺ  ˙vâ€ÜŘĚc™RžTÁŸ :‘‘‘‘‘ąQÁWßzƒţ§ßţ5zâĎвX‰)ŔŽĄëÄłŹËhűٟž…W‰mö9%X âđÂuI¸ˆvńUl6fύ[„%N˘ޜNä5ÝZXQlŠç[Úö¤OP–ůnŹ(éóó‹l23;OgÎL2qŇdjzž-QđwúĚ$Ÿᤠâo萿uÄ AŹ”kł,3%ń* aKŸ†R%ÖŁL°ŘŁ‚?rĽ†`xą•ŠÖ5hÝ!-łuäWÜNJXžPô^˜ Ůş„âB¸^‚(RŽ0…ƍďO8WĄ••eÎ1I8žJ_żI“~b6oË,ű Ëv9ęXŤ'N˘HZé8Ÿ]ŹŔ˛b—Œ†ŰŽr+˘(Ĺ+őŰŐE&ĆǙ\ÄvřkDŤ8żdçsŮćE§B "iiH"k+ö|p’ÄJL¸đ5™YÉČČČ8/˜ŞĄŚGźŐŠV…Ԯbŕܔݘ#ýřŮ V*–ŹÉ¤JFFFFĆFĆ˝“gNÓďýşĐĎ=]*+qézNëĆŠŹŠ2<ÜW4bÁ‹“ Ű_ÖˇM 5–#|–ýĽŇ…Ęť0Řđł–ŃöTâ{o•@ł­‚&. łŸ4{BFh—]‘Ę4ˆ˛š+H¸g€8ŐÉěě[˜Ŕegvv‘-PfŚ8ˇŮ‚<1Ků´[ü¤eÂRڞÍpĎ '„u/°rK‹’BXŞ4Ä ¤Pu ůöגdŇíËŚMIľńů;"Ćó+:J—ş—Č{QiimýÎĺąđŁ’ű÷¨źŐÚא,+l5ľşÚď—v]ZZ4.9xF#ČÂÚĎÄ×Hą– qÖ8\/ĺmbaĽĄŃO†˜`Ë E$Ĺ{€ŐNΜ™ĺ™LDW\%Ľ×ěcËň–?&(o›…hß$¤źu•ÍOz&V$B!śŒý&Tüŕ7 ˘ŕĂëÖ g\9Ф7ŕw“Ń;Ü*S@)ŕšIa-p;6Vœ ľŽ&5:özţíŘ@œ­ś_ (##ă‘傌‹‹,œ ‹:{†ţĂמBßúţwiĄĐ‘źŇWáľ°žXŸ) ˝R(hmk]R(„ 'ü€cĺ”/×!­!WČ*vBŕ€h—'ôp٤ďŞ×)'ŇÂ#Z ¸š¸Ëyffžf ĺ×'“tňÔY:{vš­Lp~aĄHˇ°Čé`ОÚ6ąR:ZXYŘâŒÜÁd]ťč¨*öpp}á–Rf•Q\ b%íôAް)1Qľ‡–šKWľ›‡.myk'Ó]Ld"2ĆÖA'űţ(šÄľ›oG—V•ň6ťŽřQQ–Zlţ]"C°`vĎĹřa7Ť–ÉÉÍúáJœä?GŢÉU|üó/‹ tęôi&M@–`}űŐŐe.î=#CCœďęň"ľW犊¨Óéë˜Ĺ"AxWů÷?˘[-žYD8Q÷Dʐ°H‰ƒÓFËTYÂŚîÚȂSFFĆĹÁđđ˙şI ł‚ ň.< kÍŘąň#Ťw­ŐJCŮe”í$e'óťÚZĺ ęş"EFFFŠüed|”ŔxvęÜYúĂŻ˙ýîŸ˙1>q”n3ĽC<ÁB„ŠÖ"’Ŕ1§txŹŃ)מ2FŠ)ѕă(ĺˆž§–NĘ!“#YHźBÖČÉ ŤĘZ˜źőÖ[těŘńBmҖ-[ âj‘Ýq@€`9ÚžâVXcŁÍ"›f1Ůŕ¸(Î—5ĐßgŘ&mÝ:âg!•eTöýő„™ ß´Yć;ˇÄśŰíâăZYmű'¤a’)ŽYt´/–NŚ2ąâÍ[ʏEŃşuRë‹<°edd\\`Ő6ôżmŽÖňŤô€ AkIŹ×đ˛FśúkgéŤmpZ¸=z¤ťŽ¤Ę8“8CCĂLœ€TÁ÷TŒ_ýoŹŻßÄń‚eŒ!Ušfň‹ÇކŁv kp|/#ĚL’w\F‘θż†aą322RL Gĺ ĚźJQĆĽŒ,dd\ 8râ8}őąďĐ;Gß7ęIcmB…ĎŻÓł.¤ +ˆŽIŠ )ˆ¤ő@–&ŰJ*{â˜÷y$íÍ`AœŔn:S3ł499Kssótśř=|řťî€,YX\â•x8N†]ůĘŞóO.Ń –ÇqŠŻ|˜:é|C|ĺ –ôśÂú2éMËÜb˘ŔYŠ8A îI°Té$î?CŇR%4WŠԃ‚lj`ÚC[‹Y $™ 6Ë<"i!=z˘¨}ŇĽ%=ĎB*bu % DîZ+tZ & ”%lĆŘh(WKOŽź÷ŢႬš§=;Ç9ˆ-–' ˇ aś$ÁLŹYĚ*C†0.@†@´5Œž{x–r&0¤qď•ŮăHKŔxČ7‹u˙ю˙píŹB› "ĹX PŮĽÇĺh÷ÊYŃc4÷ăHÚ¨ÄJFFFĆĹH•ްNq+ő€¤0Ž@.Ľâ>ÝĚLaBÂXj7Ľ#ü---łEĽ nÎĺ´[,ß,őYÂĂĆ貆I;j1ab')‚Ő y÷VâńŽaĆ&śáfd'|!Ô°+ÚÁ ŚaÉ7V6źڞ÷Kv,ľ„NC7 łBŁ#x0†áŢ8ˆ;,o8ŕ|? í;2LČ%ÚĹ žq3‚ôĂ:í:ÔÇ)ÚÖAśW5ąâ-VźEŠČHĹ1ˆlڊűÎČČČČX = ŕ+ÎI2şą\i“‰›FÂBŃşi9y „‹Ş!V<y;k˜–sO.Ža;mbˆ9r‘;°x剂F3Z ąo‰;f¸ínb)Z%PŒeaČw1‘áâČđhI—§ŸP2~‘łčtŚß†źQ6ř{ƒ'=š>čß7͆ąžaÂŚ8ËÓ{W˙+ɞ— 0ś˝ôĆ!ú˝/˙1MÎL“l˙oáĆMąáţoŹOżŽkíE ‰ĐţŇÓ.ΉašÜ,„̰LOÍŇń“g™<Á2Ä'OŁ'ĎĐŃă§80,ŹMą[ Ŕ˙Ş#Ü?¨DwăźÔĎÜNR¤YÚɓUaŠ:Wäd•]‘3Ľ“(ŇrŔŐůšY¨ŽYA‰ˆœ5V´QĘŞ5JĘ!%ď]ynÂϏĽZ´;) \D’d‰~L‚D ä ÇĄäJœ‹ŽźŤč–l ŸĽ4ˆłÂpŞ#Ěž97;;[źw­bŚk…LO>¸źě,aĂ>´ˆ_°y*,N„˜ië`N„t™„ł÷ˆű÷HEVśféŁůůyŽ'sď˝÷‘ĘßmFĆô5 ŸŮŸÝ.{Ę/qžyľíröfUцuĽĚˇôŕX>ů÷˙ňĎéÝŁGL.tnŸÎşĹzwY;֙„TúŻ›ą ­Ł}gk­ś ĽKĎҙłSě˘399MGĽwżOGŽž¤šů%ZY.>†‚4qąMŇ娌ii\źňZy™@I!q]s;nCLŐ秃Ú‘5Š´ É*oSlŁaäefž°4°‰ţę=ŕÝSâ{+݋Ž+ŤĹĄôW˜CˆËtPĚmG$‹?—ÔD‹Kě1Ođö¸ˇTĄ ŹÉ#Ѝ’ť‹Ď+˙ž¤äŠK‡m¸š•œĽ§čŘ{W^ć ­“ äß I"jšŁáލxÖĐż$Ĺ˙°Ş -Ą#rÇŊĘiëÚ6V1×3ąbMĚŁ—Ń>]ń878đ\Ţ~űzţůčŔkhŰś­•ƒ&é“'OŃΝ;ý{vđŕ>×éha‰_ BäŤ_ýÝyçítőŐWóľ/˝ô2˝öÚ!úâşŘ~‰žyćYúřÇď㤪ëŘaBĺôéÓĽşŤČzŠčţűďŁáá!Ę0pßŇás-úĘ óôĆɂ”wKśQüÉţ¸OŃ]űčgîĽÍ#Ź eԍ3 ^Ił kRG}ƒY Hu‚ËŠű~™đë´IN.`ŹQ…`ąŸ––—LĐ|P–”ô; xiß$#ƒ‘ľ>ý„–ȍG~œŐ&ž XG’8˘ß­ŇČuvă‡lÁʄ[†‚őf!DĂŮ ˇeÇ* WÓ$ĺbŹ™ř1ĆýˆWsœŁ×bR%##ăʀY`b™űˎtý+â%˘Eŕn¸ö’—sˇ”:¨sĂDżÔĎ}NŽőA€ś<ôÎ[ô׏?Â}ˇ ƒRŹ+*ëŠę,ý0˘ˆÖI.[RĹ,ńg,P ʞËÎ*‡=yćÍÎ,°Ľ ÜvŢ{ď˝÷ţń‚H™aĺąN`qŇÖąJW7Đ+Ašł ňzĄŠŽšI §ťĺÓčš{BśÍ\Š:ş^•ŻńşˇLCŠD1…á2p" ÚmĽ9°ug"3ó4Ř׌‰Už*Ň•őńm¨5IËGrđY­ËŒŠ((ăNO9 ďSeŻď8aLkÁMŘ6Őa‰mm߃ŔĺhoćÉˀU=m‰ ÇRÇlFÜPxRĚŢ{xÁi!ďIK÷A8yÂČţ}qHťw:(spm n]ć_eŮ8Ð rʗU^ń§ŽXqm> w­ŤŁ Ž˘÷ů ŔĚĚ,ÂŰśmŁłgĎҞ=ťé˙ă˙~ěÇ>K_˙ú7 áüž‚L9I<đ“üÇJ;vě -[6s H<ŤăÇOđqüřqúҗ~‘ţů?˙Uúěg„}ô1ú•_ů?łU ˆŽýű÷óŔA~÷îÝ´oßUźô6H•G}œNœ8Éď6ŹLxŕ~úW˙ę7čÁ 7ß|“>őŠOąK$™#GŽÍ~:uęTѧNqýO:MŸű܏ҷżý}á ?Q\ű›ôÉO>Hßýî“ôţÁNżţëżI×\s5++÷Ýw?ÝpĂu~ĆŸ×Ür‡ţťż˜˘gŢ[Ś•–śŽe˜x…ŞĚJař8ž™ţýSsôŮ[Fč˙úšMĹ9ĘäJCĆMä#|›{ôѢŻ8Áq?Z-ăúăfHńkf;•!őšáĆXĄŕ8ä(¸ę,.-rgźÔYâcč;~ŔĆéł+ýř ¸V~‚KŒśťl‘iá”OŒ3œe‹sّ֘@GĆU!ōQvěěřë´^”3ƒ,ŕĆ4M‘%ąvÖ)&˙0aˆébdęo”*8ź˝Ňâ ˝ăŁ4?7GWĐoĄoŠNÄť}Čg333…l5Î}gœĽ ŇםwÖ+°€ÉÄʅíˆŕ´˙ÝŻţSš[\đJ“ŸP—c„´NIɔDŞŔ×÷ĐĄˇéíw˛ŤÎąc§č­wŽĐÉSgŮ  ţĚŇËĘ˙)ß8f?ŹěBfß7RŘöƒŻuWD@W!W|_îş*•ą†—ˆÎŤšăDAٗguWNudąAQNFšU´˛Ú)°jub˛!űL0:ÍE§ůPÄúâ$žƒˆÜŃÉőD^h 9Ů-ěWŠ4ËPŒ–÷ëhšż${´öÔD"ÔŠP|$ Ęę*÷v‘´pŇ^€k°ĐÖaÓčđĄ*—ˆóhřś OO‘œŃSĄ8/ş}…-‡"Éů°çVŹ[—łĚiâCYë¤$ÎI—Rb%%_<¤”Ú5DxњŽ$V„V|úĚg>EĎ>űۡď ;ž÷˝§˜‘qěŘ1Ú´i“pßyç]śž;qâ[ş=zźؗ˜|ŮľkgńűqœáV ˜ƒ’tórАs zńĹčg~ć§éúëŻg—ČŻ~őŤô7˙ćĎŇíˇßFŸřă\” 7[âfÄqýáĂďDÉ˝lEâđŮg@=ô@qOŸĄsç&Ů*ĐĎüĚOŃoźQ?NJrŽÝФ šyaĽC˙đߞĽ×O­PťÓ=ýP1őSwŽĐ/|l”öm6&žÓ‹ú“çćč?<3Oó9ó˙üüfhŞLŹ\cŠ™DŒčË/˝DĎ=ű 9z„fڧiśPćaQbÔöľnfˆ‹űĽAŕb¨đ¸ŐqnŃ-î‚M•ń˝ˇhltěł÷÷ő{҆I†f3!,Ěâ‚Ó:ë7ž5ab—őąP´qI îČfüb+÷ş&X [˝ČĎ%3ěů@ń&gÁLˇí ˜ü‘]Aűq‹gˆąÂVÍĂlňj›gE‡9 ­Rꊝ2..¤e—łćFž}rĂAŢwÉ:M "[×h¤ÁD}ĄR•8ä8ôÇUçť*iZ9™Xš0`ly흷éĹ×YWX÷œ­>Téęc˙Š˜jl @ľóóKô/ăéń'ŔńN:>*/ů—gh}D‚4ql”\ňŐŤŰJ(Žž¤ €+{euşI‚ÄjźŽrŐ×QĺuTSJ\ż´đˆ4  řFdQP€]ŽVX1j—˜Ŕ2iŹĘ_ěŔäU•î*äZ&ZŒp˘˝BŢNBŤRĹ䬒8e)-ďĜ 3[˛t&+5(˙éęCŃŔćŞë.q÷ĺ‰ çIؙ̗8-HGŚ’Âń‘kŻ?™ˆÇ:ĘĎĆ5H¸Gů—ŰKŽžäťˆU:˛ĘÚ'ĹL`Űš(8’Ęq3•+ţÖýƒĊ˛×”ÚȞsĎąę›ŘȀ˘+X a–äVC›¸ţË ˜Ś˝0ŕÂZĹ­\%Ląœ(ˆŁ…ÂsŐUWą+ż–0â3W(\x˙†††řďý÷ßd˔C‡^ç<öíŰÇiΝ;ËDČÄĝ9s†˙PG#<Źp=ŕƆ4Ôď¸ăvşőÖ[čąÇžŕ|pO›6M°ĺĘšsçř~0;Łl°Çˆ¤ÜŔ€Ą×˙üđ4*.÷‹ç4Xđ[˙Ń'ĆčoŢ;FC rźčÖąýňCă´oK“~ýŃúýďĎŃß}`ŹP^e\9`z Ť .ÓÔÔ˝\ ďźű[DŹŹ,ˇۧbŹą‚ ‚;žYg9bVŞ!?A‚q†űzkfÎÄż]F}'9ȸőlŮźc/.úgŠbVáiú•př:,Ps\Źl¨\ Xň7NśĐ–1ąĹ„p˘CĐZi-Ę202jyÁ}–äAżă,5ÝШu4ƛSfîX+•†'Sx}¨ ÖŰ Á˘ĎF,Ӛäĺ´]/ YFF0ă=‚K.žąééÂۅąT.î€ďĘ˝ł$sDdŰŽŕÉ˝Űë÷q"2žyóŚó~WAęşţăţĺđŽCOЁ WgGd@ŚAű‚0ĹyÜŽ# ŇÖĹ2Ať/--ŽI¨8¸0‘Şň qĄBú/~˘KupnBÝ,_2ŞąP<ł˙WîÇ'o“#ÝřDN5upŰ C¨¨ć"UéԙIž­…Ť‚jřů >Pfü lƒ_yĽřżY˛şxoŰĹĚ"ÉwZ…Ąm•<íó“1j‚…vö˙¤zz 4•ÉCq`Ű4óäP阚[×!‡˜*¤ě/-Ť\WŒJř]-ˆ‰äJw\3”–öׅsĘ(í”QG˘đu*n-ď2ŁBÝxVËúšJÖŃäCAđrÂYÓșG÷MÚ[§ ‘0¨"&!p!֋ť'ĎlřĚCŰ;"ßąGm'n­hÚL˜,/Żú*đ)EĄDtÖmf—BŰ{ž&ŸbŰTŠůâe∌ąDŠżwŰŇĘĹŁŮř0łsC¤Т߂0BŇBđY‚ÁĘÓË/żĘßĺ˙ř‚Ö4Ďzŕ˝úć7żU*{i׎]ě×ÍBŮM7ÝH?üÍâ÷&v÷šůć›Ří.9×]w-}îsŸĽ}ě^úó?˙ §ƒEÉ'>ńýáţ1=ńēô“?ů´eËzňÉď×Ţ\”;EďžűnqÍ=499Ißýî÷¸<¸0Á5é–[na!đ_ü‹IŸţô§h˙ţŤ¸N¸,űÚËLĚĺ źĂ'gÚôđŤKkZ¨˝ÝwÍ }ć†!;Ĺ7ęWôŕuCôÔ;‹ôě ô“wŒĐŽń&elLHáÂ:\őđ÷ÚŤŻĐŰożI …Bäüía… %żÁî(&śV•ă …€Ýx’‰ŽÜĺńżfťŐ)–Ž':@¤L}îĂCƒĆJĽî‰b–NźŤLqŹżHÁ),d(ézc+eǏFà Ĥ+!jq­ż0żľ„ ÇnAzŒĺ ň2Ą›lV/’P!rc›ŮîsË)ŰÉ#´ó*/OÝÇJˆíhHÖ6đť`@ŰŁ­22.ů—UL˛Ą/}éçiϞ=ô›żůŻŮ…÷ď˙ýżÇď”ţ­[ˇňű ’“GŽ)ĆűńbŒž‘w¤Ç8üƒźŔîźƒńůË_áăp!ĆuČŻ˝!e˰jƒťŠ‘#ĆšN˜$Á>do}ë;tă7Сżý–0)9$ ž/|#—^}őUúƒ?řC̏xrÎŞ“Y_˙úĂ,+!îÉg>óizüń'¸]!Á­ůŔ%REĆ>‘Çä/öw­ÖŞw͔×Ց*°RĆpđŕÓ‰ź\ŰLŕö´ŮńS'éŰß˙Žk˜ qĎHůq‚!ĆOŘ´Ćr}Ú}]H(ž Tp§Śň/.šŞŔ<9uÜ\cśűF›4°ĽÇÁą]C4v}Áô-+:óŇÍźłŇSP:I:CQ˙D“77/y!řb•áů“K¤WÜGeŇŚMŽ“˝T/ŁŹ¤Ż•kš›ŽNҸo&U–WŘgŘ\okP4ÜĐ`#XXt+Ü&Ѳ— 3‰Ű.R¸Ă‰d ”ˆLqĺ RěS(›ÎÚ3,Ţ|X Öő Ęş÷ŕ\X@ǒq‡ęjë–^D;6 Rƒž>[oG<¸Öh˜Z+ˌEM™°ÔNdŁkţÜś3\V †ÖŤźÄf“…V^˝ŞřŒĺ€ňMě­UČř°ˇÚ9AHQôcߌüąBTŹ6´ŁkSCH[şNmt 0CňŔ}üă÷ó6â¨˙ď˙2?—ťîş3ŹÓxřĂ5îřßţŰ_âgƒUx\7n)UXŞ|úӟ¤O}ę$Íëé—ţVTÇ_ţĺżí˙ĘŻü§œB›ŤŢm”íöńžżđ…ĎóŸ<Žk!ˆmtŕ{|áýeť,yđ7ÜĄ{Ž =›újG€‘=tÝ0ýĆ#“ôΙUÚ>Ö¤,CmL`̝š2V`ożő˝ő֛Ĺźě]p| VXQh(ŐXU(OZ.,‚ŒYśDlX3‡Ç(;V˛@oÇ8l ˘B;”1LZ!ośFą$Šűs/Ş[j8XŽXŁáȅ…‰)'AiŠ_^78ÄÂęĘ3évÜ“&m°DUaXq}bÇL˛š˜+ą,(Hí,xľżœęď°ůE pl¨ě{›€śN ’™žŸłČČ8_lÚ´š >^Ś3gβĽŢ%|{°T{üńďŇѣǘ(Áʏ<ň MöíkĐóĎżHŻźňj1ɲ‡ă¨IŮaaaž]‚˙Ë˙ň29óÔSĎɡů=Ĺ$ >$ÄBƒĹˆô9 RáńÇg˛äç~î‹˙íđáAvQb—ăŰnťĽ Žsž ..ľw˙şëŽŁŸ˙ůżÉąç\Ÿ…>Ö+ {ŰíąÇgb ÷đüóĎí2[K’Ś„ ČŽÓ§ĎDî@›7oŚ;wD.?Žđ–˛Żł 9†‰+*°D˝@üČtf•Ą<Ѳ¸M‹v흷čˇţřh1.y< énźâôöW B…Ç6ë.Äą˝Öš5ű°>j‹*3¨“gšŒpa§Ń§hh{A˘ôą/ďŔx?ĎÂl>8F[‹ż™“ tÍ'vŃČÖĄbf˜^˙ć{ôä˙÷M&Hřú‚,é+.(8…ÎJ‡úG4˛m†7Ňć[F¸ąˇß´…ôHńp–űčŮß|ƒf-Öéţ˙PV+­éŠhU`ń¸ëۇ¤ţÚt¨˙‹°×ˆMŇŔ\ŽúVž‰ďŞ˛;´´sńiZ,:d †ŌdBĚ8ŢróľFčsuO˘ĂOÇWǝNI#ăę2ąB*^6Y‹e ľxĎ];ë°?÷ißKşŢóżľ×¤×}(+1đöN.tzJ§ …xÓpƒ-RęĐW|ł[‹ą$éüŇú ân,€â23SôӋ 4WřŻźü=w–ă™đj;ÜGj1+i,A@Ôˇí2›¸° KÉΞb{ť-f2íÄŹ,°$˛sŐqV'Lź™8,ŠlPő†''H eÝnQ"cxůƒČö2 À§|ü8 ÇO†h'ܚÁ'Š1ĄBý€f3ł•ĺşr”Ż…˛î=Š…k¸ň¸UŠp ÚË##vLX‚Ú”Źf}ĆhG*n†?#ă|×Š8Hš?xđ[Š<ýô3laëŇßú­ßfKUŹ ˋçžű˝űî{ŹÄĂÚâő×_gRĆÉÔŹcq@?€ë/ V­wŢy“oźńÇvƒk/‚ŘĂŐ–)°HA—^ü~”ž}ő%úßţÝż)ˆ•7ÉšźF•ő`Öe„÷‹ůœœ%˙ú´ýúXŞ/˙ö­›ů#i ÖżĽY´y˙ ŒÇ@“t_‡6ß0B›ŒQ˙P?Mě-ˆB^eSú÷_8ISďΓ źŹiiŞE[›4X0}Ă}4źuvßł™ôŞŚé#ł4ź{€öݡ“v^ť…ƊٌAĹçŚÎÎŇÂ;ŤiÓ ¤ËÖ"ÉžŠvT$X”Ž’hqĐ÷TA^\¨zj̚:ăÔńŠś˙ÂFպ뺂OQ‚D‰)–ÄHU[U´žbpS¤U¨…߲ŒG ě†Ž—Wô.>śĺ,ŸÉ7< ž‘ÓN0wnó‚i6VAP­˘M[ńĘüž`Ůo+Ł­!sđŤĹ%&Múš},ŘÁÜŰ Šř`Š5;3ËĺOlš`?w000,“ţí[čŕ˝,@;w' .Ż*Ąx‡x5ʒiË+­˜¨˛$IdáŁ1$‰ Ťţxb…“ŠˆˆqmeܝLSKR)#ărŢu¸ňŹ ÓĚ,´hščębĽ űœońĘ@#ŮŁ`Că*ÜčŚ Ľ fćďż˙^ĄćŘ)X…'ôĘË ÜXČn? CšfěĐŀ‰¸™‚Äo™ń‚‰Fpƒqăœă>H9żr;1…e‘;:ZůĆׅ7ܨAţ:"ç~Ťánä4?~+"•JŻ!Ëp#<š_ć/˘P7woNsDą‚N7Ź…Ç)đ Üƒópg`k eH%_¨ŇaŹ÷őŃQů°awČL8g\ ÓÁŐî9ˆivđŕvÇÁq,Ë|Ÿ ďđbżm—…)pôčQ&@–€Œqn%[ˇnáóoźń&“‡˘ŽöÖfu…ƒă#O”2@<‚pÁ§°mŰ ůݟűŒ“O>ů=şá†ëéîťď˘Kn3XńH11ęΰ ˙ƒl‘qíľŮ= = Ź`] ž ,űűmĹD\łWyrӇ垅LˇÖ¤öAxÁU{¨˜E<¸j#žUššéÄOyňůgéOţ}ĺ‘oŇJkŐLW‹ń, Q¤ý$‚%÷;˘çg˕őąZ'÷|Ü[ŘďľC+tŕ Űhűő›éę{wS˙Xw8çŽ˙EBŹZjÄČűó´şÔ˘Éć< nď+ˆ’9Ň+ЎBÇD1¸Ü˘íwŃu?ź—-TF6ÓŽˇ1Cxřšc,¤ŒďŚĹůeš,H–Ć\˙ĺ?}ŸÎž0okˇ–§•ŽŘtîş§ËÂ1?ÚÇÖ)= Dqˆü‘̊Đ ľ<‰s0ă8Q*C°şŽ,-ër•t8ăb{‚ÇšÁšGäě%ŹP’!VěÚ+Ží…1ňĺ…m‰@°¤• q„Tln~ą˜…4>Ú(ŘśÂ0ÎŁ#Ćě ž57ˇŔ¤ ʍ< B5ŘóĄÁbm PÂśm6ýSdŠd‡¨dh—FŢ ‘ˇĐa˙ń–#O\Đaĺ—?.#Ę´Š'VˆˆR×垙ŠŇQőçp!őżíž.žGˇŞÇzúÓşŔwn{­´kŐ+šmŢ@Ŕíܲ§˜ĺęW66QmJă*tx‘>qĂ(Ü1HiS ‰ć—ŰôôŰs´uŹIűśô÷ŢÁg\R0+6,ŃŮ3gŠÍstâř1^*Žč“%‰ƒP7`#łťŠ•˛1ßńeÝľş/Xk8RĹdď&Dź.˘`…˘LŹgŹQ5öšI -ČucůÁ+ńˆ˛â6ˆű;yŻî°[vܸrSż´]ڏaĺA‰úĽe+ë†ËV9ĹDbÁh"?yĐlöGA>ÝŻËÔšëj “"Ž.X1–Ap8pŕ ed\öěŮÍĘ8H?(ęťwď&źˆ×\łŸ-!`Á%î=GŽĺiPÜŻ˝öë+fŻ6[K!ÎŻXUÂý÷Œă݌O°ěyĂ 70y7 ˆáb,Ü:g.'ˇß~;Oâ!={\™ńÚ@Ć ę‰ďdŔĽÔí‰ú ‚ކ{Ćýâţц `ąóňËŻř%áÚTľZĐ×gdoבA.ƒ[÷ZpŽ%Đ/]+äÝlqÜ=]hď´ÎÚ0Ł Œ#ď;Bßúţwé7ţč÷éÝbŰ­Ź* §)Š­ŹÂ4Ě8GXÉŽoC‘*Šślˇą*ˆvßľ•6]5Js‰˛ôĆ -Ď­ŇÔá‚4ivht× ŽŠ+5šQű›šĆ÷ŒŇ–kĆitǍďĽńá œč§WţâÚrÝ-œY˘Ĺ™e:ýîYZœ\ĄăϞ#U\×?ŘÇÁWŠ™CZŇ4şm¸Čc˜&úŘÚĽŠPŃéř_ćHđ Hé‚8Cdޕިƒ RöDáYkˆĺ••𥋠m`tjQˇäŞßW§™ÇÂUÚŚÎá@ŕQtéžŇv+ĺę‰&ÓnÁŞE…v÷iTÔşZV)ŁŹdâ:i/ŹʧiWŔĄů‚()Z–݃0Ŕ‚^!Ě 5 aR°Ň˜œË›fŤɓYĄˆ*Ů-/ąÂÎÎv:Z$ąPËŚĎíŽ% (˛>ĄŞŮĔX!ňmŹÝ’Éžj>C’oŽ3żŇ UΞ=gBŻđlĎZ‘ôݒ§źń‹Y'Jr&äbÁ‘*@ˇé°˛ĐîÝťjď…-4ěĚĚrë€#(R—“)=>ÓŤˇöÓ§o˘ż|q! ĚwŃ §ß] oźoWVě„ÍŽă6q㑮’›, ŻĂ0ćk՟Tl=ę~t¸gŁ 4m€YK~đD„ąâěsŤŠq5¸Mš#’lRG,šńľábĎdd\ `wŤňxO÷îÝòáç?˙ă<鍟găo|Ž'?ÓĸËÄ‚œŽöŽ,Äb­Á:2 ‚ÍĂ˝DĂM7ÝŔä d Œó°ę¸ýöŰXž€őâ{4׳ű‰#P› yÁ2˛ H–Ku’mqă×ó6ę™dîo˖ϰ<5dW5C|ӆýľą‘LżŇÇ}Ëůߥҗ(㎊ꡡoßî-S¸k2ĘxçČaúÍ?ţ÷ô'ßřMÎÎŘţYy•I¨—ŠNĽĹI§śZ żlɸ‘V˙ń¤ LU—ˆŽ=u–ćN,ŇÄî1LG ĆtĎuúÚ´ĺŕ(mŁ‘‰!&UúÍŕş´şHď=zŠöÜ]0ŰZtäŠS´8ľLłç樾ԥ‘ąaę˙Áhtç ő ôŃč–Ý:\ ÂM:ţÚiZž]ĄŮó4{nˢł´Ş¨GĆíŚR*óöĺ’řĆU)O3î6¸A;Łr)°ŻT?÷w°t–â‚qáŃ1ąIŕ‚`q˙h“Ď ý,Ü öďż:+;ŒŞer Jş˛Ćť!výŽž>ÁqßMRཅ‹ŢbÜFÚź:ރœüp“8NŃ9qýő×1sŠž÷hˇ´íœĺG:)9ÄYwځzŰíyę%ś‰ &^wőiľZQ^u­KŸăć;ďŚßúÓ˙@ňMC¨8˝Évę!ąÖa“KćÚLůaRąUО.ˇĘĆmÝPK*ăŢ'&ĆŘƒ8ŹL6_3Fűî,˜Öń‚mT}tňÝłôţłÇé̛3t敹BSTLô ĘUĂ´˛Ř˘ć`1đÉŔp? o¤Áń~ÚT2×OĐŚmc´Ň^ĄĹš%Z™iŃéç§iţíăÔ^ѸvňÝY6ĹRĚ3ď,ĹÔFމ˘JîCrRC&U—š_rđü`„0X/­Źše•ýL–ÁĎěՑ2˛AŃv_G4Ą´HŠ…NňÔň ڿݧt[$‚׊Ôçş~@HgĚ| ě?NˆŐI>n† —ÝL›7w!ňR$$űşëř˙ă{˜ČđŰJúlV´Š‚iťtĘ źĆ"AGÍ!RH‹€Š„Űš \ItEV+$Č“D˘'z76>ÜrˆXŽڎ % Šqš—T>vě'ƒ/žĂ;Í1. F@pŔä‘ř¸MťĚ¤\řNCH‚Š+Č ĆPô@r@ rÇź›P śl1¤Č5×\Mo áUW]ĹJV€Ň…ôPŕ@¸°ťe1ă2ŤtAžž‡ű RäV.€ŔbVâúőőÍń=Ł\¸T‚PÁlĘŔ˝!ďýű÷1!„čäɓüâî äÎ!(\*`~Ŕ{~íŽ~ú•ž }/,ĐW_Z¤ůĺNůŐĆ Uߝœ[Ľ?yvŽž-˜kśőłľËńéM-´č ÷l)• şjk÷eě3.]ŕ;=zě8=7ĹÄŚ ˜čČ ć×,iа})“ U˛`˘í 5>ć– Ö ˆ{ţWôÖö “'…`ŠÄX¤}2A‹(ĺÇ.]+†hOˆHˇsď._ĺď!”KŘƒqëQţ>T"##GXЏ‹‡ đkVőۉeÎŇÎVŢ*Čß,Ĺ&ďu‰`A?Š€đóáťsçNş˙ţ;s<•ŒËxGA¤Sź#°DöÚŞ ş  `öƒ1âę`ŕ˝ńĆ™ü¸őÖ[xŔ†i-ˆP‡w Ä|ĄwíÚeÜ ľq…Azä˘ĹD¤ßi‰“ç 7ŠĂŒ \pŒďöUŢzŠ{Ü |ĽAp žf• ŕÄ€Ű Ž…)1öQGÜÇý÷ßÇטŮxC~ŔD/ędbȐ­űˇ,ZůýÜż˙*žI3Ë!öq`>ÄŸS¸pż ˜`éRćR6`şgsíŢÔÇAk;5ŻśďAlŔRüŰW´o_#[§l@ĆwąZźó}ştů †V)üŻ'(]Zĺ­<,ąbƒŽ6\Ü.e—śžöÎ"ҍ)œžŃÇďĽ'5,|pWHpŹFgM1ƒü { xődˆŽFF_÷(Č-‘'Q¤ŕŹ\̰'ϸÁŁÁV)}vYh i°œCß3ˆţDżwČ0Kérň˛˛„Ś%÷e0$ĺ„ví]ĎÁ:nj†űŕ;î¸Ă÷ËWܲôĄR+Řż×ř'.ť,j]{>#AŃVGOž Ç_x–Î.ĎŃŚ˝Ű˜Ü_^X˘ĺšEjŻ¸ÉŤŽ‘ł"ŐU„{ŔžĆŐž†+ć&˝Á+tŠ1œ›mZŹ›űϖ-lę‰rps?ípWAŞLĐřÄDńbˇčÜť3tňéIZž^Ľöbń’ö Ô_ ôÄÖ+›keß íżo5mŮľ‰…˙á-C´kďvÚ2P4ÜŹ)Očß~hŻç(=M”¨é‰€˛tMD•˘šDzs]އśXĚČđ˛Ę}š\ŒŒžf‹äŞ=єSRHhŤ5I§‰_|çŤíÉŻČŰ_Ťœyßs˛IňąHčËó?ްˇ&^eîHk*]+I9­ěúĹvť §úŠëzűJ‡˛”vţŰöĄ(YěÄDňDJd!BQ• ŁÍťçGÄĘŃd›Çś#ţ:lFłăŽnږŻJÄ ŤĄb…EožĆ> [“^ŐZ%] pţÎn†DZŽ;`ĂÇÇ A ÍÉŤVţqŰřs着eÎ) ˜Uy€rŸ`XŒHĺ͔o—UľyŽÖŻčă”(”…kŕşŕ×ĺăę%DÖׄ‹<îęŒ?/2ăďˆIG]ЇSjúT)36"đmăť3Ž(‰ˆ ýh $¸7śŤ•Ç0?záűXG… úXGŞŕ&TšMoÉbây9r” ń‰¤Ž 9c•__Oz¤¤„[.řn‡źMGˇ˝k“$\œ§$UÜ8ĺĆxŮ'É_\ÖšřŔ’¤Ľ[ “mĘZ1—„-Ó´^† rňœš'OŹyYÇÇ .Šç&§Ř °ľÚbb+ľŔJ/*çƒ^bpd\>pDHJ†\ˆ<’ĘFŠňsý&ô‰sÓSôŐÇžMŻžó™:gôĘĺejcHÜy]ł÷*O–39ŢʓO˝ň=óöŤ´ýÚ˝4˛yŒć&giĽĐu˜ĺOŰxšÖą~§Âxj•TŽ´ü ĚZÖғ'Ľ×§}×)rŽ˘Í›&x™Y`îč~}ŠŢ}ř-Ÿ)”׌ćAŻQč{ďŰA›÷ó,đČśaZZ^¤í;ˇQ˙h? o¤ů“KźâĎp˙7Ňä‰iŮ:Rź ՝e;jš! ]qQ˛čI˛™ çQ|Uő•7€Œră|]Śý}F î_ćĄâAůOďYnА–’úč8ľÎŞ„˘¨#QN@łIEŒ•Ö_9â!31Y¤í –ˆ)muły$ǢŽŕ^Žä%ŃáZĺîÍŐ1íXuhhmc¸¨†Šˆ %oČW;śČn"*4´¨ /§Ü3y‚źQö]"Vá%H&AśxžÇ^*<-^÷<>şa`ý!Ÿoyťšfş*¤Â˝ě˙°&qűˆ“âf´%ä~ŞĐŹuÝŇvŇăň>ęó_ťn5ŮŮ´í‘âúǀ´÷ ÄĄLă{s-ĺ‘Đǡ‰„Ő‹ł0-+ŽČ $‚#_ú BŐ/ ëCÎ0M^čŘZź4üŠtĘş& XŇ&Ş˝—Ůlşc\Ý\ ^yšÂ8ÖpÁíőHbâ0ősýp´ÝÂŹp‹†`ĄSmŐ ă!‰ żN^Hš—g,­Œs˙‘} O@ă%–\=sć,ÍĚÎe¢°Ż(s°P˝[fFFŻŔ;&]b36.yźą‚rîiúÝŻü)˝úötś V–V—íʢv59ôÓޒÇĝč ‘b˘obd”I–ůřCôĹůqÚľm{×v=qö4=őڋ´:Ö¤ƒ÷ŢLŤËŤ4?=Ďn?'@Źh;Š!ŁÇŘqěd‚ĚŘĆzÜŞšD “2VO\ŻÇźNŤ˙Ř@ľđ?+ţ[îĐÔ[ł´ëśm´˙÷ĐŔH? 3çfhiq™Fˇ ŃđVí)Ň/|ď ~m’ŢűĆš?źBÍÁ‚@X,ˆ˜Ĺ‚ˆhĐKýďÓŇŮ_žNHƒĘ×´ę`Łk/”gU XéÖ˘.ń˛áϸ ´‚ô†÷­x ‡ ‚Şę…*Éwލ´áRůĆ ^öDšľ1ĹŐ! Ż´'•Ž”kC+PŠ™*oÝQŞ‚suqË<ҤôL,Q[[Ä,¨R//!;>@cŁC>’Uö‚%Q(T>ˇ  †Ź°bƒâ6đŒ†}„Ĺłł‹aŐ!יŘvBšŐŐŕoŻ-{âšĘ(uĊ8N–$’žŠáůr…ĎŮşé+UYg83T‡=>#c}`⪠!×öăZ(ý$űcc-Ć))•Ľ•‹É+śîţăŽř&’.:&m‡HôŃ÷žVKŒKž’%R´ŻŻé—%fŇEâĽ!ŇrŁľ%fÂjzěMMĎp 2œâUűF̲Ť v0Ž‚¤îĎýhFpßÄĘJ‹ŐëԌŒ í ť}XV/˝!#}ć{ôŤđ{ôrAŚĚ/-˛eŠ‹œđ¸Ňć}TqĽřgąąD3óstję˝{ň˝đö!ú—ôďh|x”n>p-ý×˙éA{wîbp÷vnfšfô íťăzÚźgý]Zš[ UXŞŹś„ŰO…NEN˛ťrźm9BE{ĆcŤułT1KƒÚG¤č†ŸÚO[÷o˘MŰ6qC/œY¤ŁĎžŚĂOœ¤ĺă<‹‰‹Ö|›ÚX‰˛„8z,U¨ő•u2gueÝÑ^ÎuŤŤ˘uRń^GdD”“ –ÄK¨Zm×)ČxĄűz4wxЏ a‘Avć*´qDLD/˛ #˘zëň=‰ĆJŸł#M$ÁAAüňebĽB˘•eŰt)_ăŽ2Śß Źşh•žÄÇ.…^íţQÔxJ&Quě­#25V„pBčÔÔ,97E'OžĽƒ×Ýä—gŐžÝÍó^\^MnK{ œ˜@1[™X Ç]ĂťŮGWOIŽp•śÖFÂF꧌ŒŒó\Ôŕ7==Mąë‘NÇ1R\+Ýą0F…ôIĐtŐ ´ż ¤M O°+’l!‘Vł•sŕyb×PÄ/‘uVrüĽ0&šĺ?+‘ ŽÎą`”Šłą|1âj_Ÿs9ęŁ>6ŘÝjłkvd:\ŘĐM~äRLŚB‹‰ ňăgpVši“¤cIŒ3Ó3źRÓšbŹ„ŇË8Ĺ$Ұ Féb´ŕxł¨–ƒďŻX7##…üćđŽŸ=;é˜fd|X™255Ă:ŹčփXŃdÂEüÚţ;úçż˙;4=?ëőF—ŔőË%ë%‚Ął>aúůŐ˘].ôĎšć"ŸĄ÷NŁo<ő]úôÝ÷Ń?ú/ţ´{ÇNžGĆ˝Ą<§Űś“‰”éS“´0=O­BŸqV*NߗeşÉĺ03A^'¤vÇď›kě?ŘGlŽö†"U0ءhb|„uQDő}é÷ŢÁPM o­ĐňT‹—:n-ś˝ňígĚ]ƒi/ Đl“í¸L˘ţƒĽÓ+ŞëžPkďdošé4]ĘBÓ ^J$\9ŠĄÁ~+łČ.ڈółEq0@[[W}„˘~ZSšŞJ(ţxň,ü‚ăqĄ†+Pţ>ź}ŠkKŮZ„Ęş”ÉŹ"‰Ů1WU)´ňŠ;…ŔÚP**ß$13Häۃżaťě$,~Ýzö¨śçç‹Yľ˘c™Ĺ2˝giaqąř>6Ńččp!¨wšíŰśĐŢÝ;hמŤĂĘ$;ťâ™Ż&_ƒĎNĹǸôą82ţąEĎIykš§49ü (Ũ;^•Îĺ{ĄčľŹ‹…p>œ{¨R2.9`IßŃŃ1ż,¸%â)2q,Œ‡ÁâÄ^Š(!đĂ)-_Üľ2ď*ŞäąÎ÷ăZć]Î7@%ײÇńťO `BýKn}dâ.€Aź’ŹA°l;|Ům”gœrăe'şGCˆcG̍ł<žtÜ5f,]Y^áĺŕOž>ĂŤ’-łź°ľV) R°ł‰Ó˘˝?Ž#ŢSާ’q>p$#ŢŮăÇOŇŚB6ƒĹ“$PőŚ/¤}ȅ ×˛.6Â=|8Ÿ{iŃǙ@ÚÓÜ÷ŽÇ˛Ëx‡Ń?zç-úŐ?ř]úڏpˆŠťpşŽĐitluÉc†$~œ˘Ů6ËKˇ•Y˛1PěĂđČËĎЏţgżD×ěÚK˙Ů/ü]ú샟¤wĽŁ“§č€ŢNłg&inr†VÍŞ?liBT1waŠ+ݔ˙Çň(á˝ÔŽP鄱ůbcÝě ńśnŮlďB<ţľir‰M\ĄĹż6IéH˛­{h6÷ҨĘĂɞ˘óƒű`TéČs%Şt}EÚÖ&çŔü‡—––yŚČźPĘżpƒCýDRČŇ2§´˜rCşŕúZŚ)mUVԓ$„BYDĺG˘b…ޝp„Žđü-ů2ŇkĽÉ0YžFGŁ“0)4ˆNťiŻ Â/đĘř:âÖ%ˆ Ôąé؂da™f Kăž.:łç& ŇdŒvîÜS°šó´ibŹř61qrËMi ˜€`ę˘W“)oyeľ˜%Äłkˆ6ӎ|5łâöDˆ g+ Jř-ű€Ť'3rEśéĆ#T4ݚƒŔ†ç˙ígdôÍ}4ú‘ŹÜ]şŕ˜n6ŕrĽŤ\wÂ9 Ų:fTi; .w<í{%Q˘Ѣ“svüďIôÄu§ČęFŰA3&{ě˝c˛ŔśGłŮĄ6â´řö1¤ űĆů‰­âXhR&1AŃCđzÝ1ńˇRĚŹž+ĆŃ'N2م%QąœőČđ0?/šrÇ\éhěŔ6Ź ňňŚ˝Â}Sxgđî`vJđŮłçüÄ[řF6–<”ńaCyëEg=gť~Ó5ÂRŔ ­v‹^zăýÓßý-zř{™….ÄxÄ}°›TԆŒpqM"]Ü((fľ† rNv›X'jQ{ąMb2¸9P’ŠŢńŤäňÍ[ŢDżůę[oŇ?ű˝MßřŢăĆÝÇ[›#ü>›9yó~ť˜WNIü7QDŹh3!Ü4ĘŽD‰~“ĚMŹž62H}cô֙Łôfń‡UŚOOň/ŁÜj‡8*=}RJÎaPç‹ ĄŽ'‡Lšő‘ç×ÍýŘźiœÂRťRS¤ ÍޞŤ’AőH¨č¤§Î+ę˝y+ +żžĂĚ̈üzí˘ăęǁjWZśł/H€ĄŐó;Ha‚+ÎU‘-ź]’Ut<ćÔűTŐc"żPňÄÜQN"Ů{2ljť/WŇžL$ëČÎB…€{só‹4=u–}ľç AîěŮ)>ˇeëV*hÂRˇ›'hďćMtđŔ>OšŔoۑ&\ż†™u”Ö#áF•Ż?d7#Ö^—íeű ~ÖžE)°*îśj‰۲i`[ÎÂőœ!/oš":˛ĘOö2‡œ9ÎČȸ2+•˝{÷ŇK/˝\ěË$ÝBŒf’ŻŤŇÂĂ÷č˘użÁÂĸ¨Ë7^Ä&גЉ –WȡšX‰ š]Ž×R-×ŘI­Ä˝ —[1Đ^ĚvÚbu$œŰŃŤŁ}u1›ŠŘpfYä3töÜ96“ÇqĆ3.ÎJqîŰ3.ŇâÉY;eB%ăÂŕ&V×GށrňĚú/˙=üäcÔę˜8(ŽqfL¨°eaěŞiŒ=â~ÜU¤:üu`yÓ.úâ>KŹŕŻ źAn´V ¤ N°=86Dâ8źf ˝Š] śÝ &˝ŔV›ˆĹ忏ŚsŸPôG†K‚ĎZ%h‘‡ŁSâ“6hŚŤÜ*1™H ™U•¨()˙‘cN•m;WOiV v&›8ç@`†ÄX!~á++m Ýťwp<ĚNŔD/̊yë ×1Rüž‰ XRÄžűʑ)şÜPŽßą•ëčpB.ƒěH•V['í(üô9IŹB&&V½¸÷ŇY­đjBDQpZ%wFFFĆ,Žżţzš™™Ľ÷Ţ{—ę=yň$Ż ' Âňƒľ*9@YľĄź…Rń9ßG[7™88¸&é’[ŽĐ¨"Wä8-H9VGśéűtÄcłÖL։¤KQ †ˆ¨ŇZTŒ­éXáČe‚ÂŁ0)´°°ŔmĚK"mœG 2…—c6ęŇŸ ľhp°˜đز•ƒë—]Ł €(ËAF3>Jq…2A—ń°^ď&°dňŸűáÇ ă M&ŕz…ĂL7YyĐʸnRťtVIʐéÇylŔXrĽmHMD.`ËCz/Ď-q ÚţŃAę›7˔/ŰX*ĆM´NŠPľG”˜ĺődJ'eá•ěŕ^5°>VŠëşśĚ5É ˝ŰŠčó8ŤYQV%WjŞ("žtśzŻžŹ2ŞäŒô|ŻpëÁ ?Ěđđ˛Ę‚Ľhľ–itdĘwQۏ(#%jĺLř#M´ź$dž1ŁEâr wŽ8R•šúcUźN”‹ŞcŤÜSqÇÖĎË/$ÔČ0íÝ5Fťvmóbʐ†}‰JĹoŠ*Už "áFCö7đĄ“ňŽ9öÔŇŇJb˝Śüł >˝eřŐ!H+dýٕ°Jąykk¤â*…Ő„űďĂô_gFFFĆĺô›7oŚţáňqyäzěńÇYŮwą:đŰ´łÖĆu”¸nZ3hLĺŐršnŠaŠf'¸”­qQ%›hAt¸şú+K5!Ż` #]ˆŇ8,Ľ‘2‘ľ ‰1$>™äá,U‚‘!řCŕYČ-ˆA†´ç&§hľŘGÝ` WZłâP“âXjšŻ#63ońÄǖ­;ü˛Í”Ômxx8ť˙d|(ČdJĆĺŇGO¤ßţňŃěâ‚éA4Řx'˘E˙Ü*&äUł,ɂžý*ÁűŤŒśƒźŸZh™ą@‡ \‹cmő™Uá/ˆ›•ĹŽŮÄâ)XĹmľ–PŽ…8´Řś›^§qdJ'śňl :\ևîXż@ľĹ›ĆËkź§Žç]ľ^Zž*)űŐŠşŐ@ŐěuKŮ=' É%xľoB儡 ąŮk—+8“%;ÜőDAšś#¨Şę¨]}´ˇ@ńuł&xŽý]M\Ćss &˜•‰(ÍçüŒŚ-Ę_mëË_˜$V(>îú*oľŇ\ą÷“\ .@ĺΝ;莝ŢzŤ şÍ [§ gŤľjVwCZ˙l`ÖžfSÄĐR‰â:Ďţž~ż,ą[Ą˝Ť$ZĘäK ]Ď/—XvçŇ:vę†ĘYy× nÄĂĐŐśŤyËK쏏Ž0AÂjzjŠffçŘĹ×"śĆbçć#Ç>\ŇĽaƒâ ŇŚ‚są |ې3í˜Č–*™TÉČȸB€~q6żóô÷čĺˇß0­…es¨Ÿú‡™\iŻŹ2šŃlúOql`|„;wÄ:Yš§U%+đ€čXóyMóŘJĒ2ÚŸmök.‡ÉšbĚě´Ú´ş´Z_őąT˘ą¤<|ľ´ĘŒsOęWS§)&ކ&F¨Ż#‘*VÝşuS™@9OA^Öm_ŐëeŻ^WL)˜š<ŇɚęĂŃ9w}Ě Ô 7ŐuĄ‚Ťbd ˆŠ28(fyzhs/2UUĐĽŠŕFŇ*—ełč*š02 óăÔ­§îF|Růtd RAáÖ,…°›ÖәműütRDŠg'„K TDҔŒBç°°¸dýÍ%ťĘî?ÖNG,™ę[>'§.>’\!‘^ދ_X*#c';´.u}km Ź(˘<‰šą ěÝśm/§ŠŐf¤2Ź$o}ÁD‚MÓą+ظU6ˆŻ*bă34,š. ~e݆Ř֊˛éČeŽC9 ›ÖĹzLBÄŰńŤjâCÜqéşpÜíǓ#ć^ŤňŇś\k­˘‰IŠŮš9^ÁçÔÉS´°´ÄDŔ㎽_¤‡Ť+ +ě­„ ŻěŁ0F2QŇh4ísŠËMk366ĆŤěŠüfdd\!8uî,ýţמě†cbšQ ŁC486ĚcVŢAÚ74@{śÓŽëösŸ}ć˝ă¤œ¤b˘´;–ŔP޲=R ¤>Čç;V—°ňtšŚ] ŚáňÓâ@ږlTĽ^÷ŘÚÖ#Q†Ü1­ƒ^ÖTlĽ2şu‚ mZŹ›Ľ nÓŚńň¸ü!ĄŹřUgßK‘ęƒ¤Đ•›‰Ô”ÉůŤŹXőgš`%Wa˛%ÜT´.H•ŚČ9fű”˙§\~*§)ýW°TFY0‹’*‘ŚL<&ćĐćBĺÝo$šŃă‹$ä@ÇČüľm7cˆ|`˛]ukĽúQůŽ•(Ô9:šő¨R‰°g*ÚjuÂ3~äŽdâóQ}lŚTBŹXB‰O‡ŽË ŢŢj…br…\z[g™çůżĄ—.@¨›jŃ7_[˘sómť˛V9ˆ§’ě¨ý†úŠÁűŞÍ}ôcˇÓřP#+°X"?44h‰‰Nä~)÷ ŮbM )-ÁÄŮôš°pqÂaŤľJć}ëˆÎU{ň¤ÁŠ'šFD`̂k‹ ˘ bÂĹtqD‹#]š>ňV0ńŞBŠ*%[ý:!ÚďřIs mŮda~ŚgfhvfŽ&§Ś8ŠYZźo‹6uKŒr°MćAڏ`Á0%ŚáĄŃDĽŃ7™í@;d÷ŸŒŒŒ+ ˜ úî ĎŇĄ#ďřą qTú†úixóőýîâô< +ýŃB†Ůž…űďŮ3“léaâ˘(—RU+܌ 3¨N° á…´ąVq oŔZdN§ÝI”#Ó_kĽ#ÉŠLÜľk2[0ú,ŻTDfŃGŁ[Ƌ1d–Ö뺤ňÄř( -žĹůđÜ~ŞÄ€jáöüʍewD%vç÷ÜĹzźu~šâŁYY^epłÄa-@ŞÄ3WBä⻋nΙ10›˜Fýˆł‹r’¨ ÝK˘ŚĚDřŻÇĹWáCÂŹWŰ|ü‡&ś(Ůî+ňœšM’$2[ űÁĂ?ŰĚ’ŠŠÎĂ00Ň"„¨ę=ĄŔŚ*ĂîĆňžźyAœ¸ű,ţëgk™˜r3Pú–WÚî°÷"Rö@‰X1ˇmÉĚő¸XďŔšššČ6#˘Ź4flđř\ŒëĎ^Ś?|fžž+~ç—ÍrĺU=0úUÜžo€îŢ7HýŁC'WčŰŻ-Ň;gWé‹wŇu;űc4ă˛rŹ5c§ŁČ•u‚˜¸ĐZüęȊE˘Őj{+ŽN§c…ĆŽ}'Ó ŰÖ:Śmێ[á ¨ĂŇҲĺ3,9AćÝnüďěý ´$Çuߏ˝Ţžôžď  $PÜ%.2)Y˛$Ęż%ٲýű×9ňŘ3ÖąĎü>öœűŘ㣑ĆY EmÖjYe‰Z¸€$HŠ$H€Ř×îFďËŰ÷zľĹÄw#näÍŹŹ÷^7€G ť.đşŞ2##"###îýîćýăŃOśŽ ťäł˜ öK$ ‹›­r‘ˇœ‰˘dI[yď äď!ž˙ĽĽ% ˘ĚŃĚĚ ťú€?a€Äśx)S×ýÄ=ŻÖëŹ$˜ĺţĘT*—HSź‘…x3‘gĚý˜ĂôťœymzÔŁݘ„ýâÓ_˙’“— §ŤŁ<âTYY|`|˜…ZšŤ —}gŠFs—&ů8b­TáX+źŚFąbWcđqk‰ďF 6BlóŻó q–*Í8J}"˘Čd‹ż^űmD ŽÁüŕäĺ,T݃Á>ŞÚűmL,ŇfĐ&e˙q6tL­7ćŮᚫYŻ€ň˝kĄë h_™dÖ(fŇDœ˙Í´ş‰ÖîaێéjŁE ű‚Ańü90k›˝šî?e˘v˝$ʸ@żw&ĹqeŐAc&ľčd¢)–zch.üu¤Ö€¸™˜ 3ę 3’ŞäٌIç[ö/˝‰†6Q:vzO4FXŃôłëĹĄ~Ö:ęƤKMť›´e+”Ą[Eډ’Š–‰ÄŹO—ę[ ŇD=k•Ýd'ńs—ëô󟛣Ž4ť‚)B;Fňô}w÷Ó=űË´k¤ŔÂŕ•ů&=uĄN˙ý‘%š_nÓO<0D{F =Tĺ"ě #ŁI]\€@z/Á>J¸šP§ü.BdˆâŞqí‰ĺ‹TÍnEŢú.ž_KRXJ{.KŚjÁ&vG• ťĆ[fĺĄÉôŽFƁ4ąUˆ\ žÎíǖ˙Čy$š”Ć˜żşZg‹¤GkÄJ@%.JpßÁŘńxڋ‘ńgyy‰žž~ źT|śĽŘâ&őÂĺ .E ŃŃϸ1DF °íQzÔŁ›…j˜~âô ąÂV*%ęß2Lý#ƒ4wyšęËŤÔŞš°Ć~Ö–iţŇĺ}š>[ŽeeĘŚ-ĹâKP҆Yr ČbĄ‰}뾨’Ł<@Šĺ"ŮWő›”ě&‚oŠŽÝ cŚ,&yżą˛oĹ+‹ůÍÔ7TaűŻ˝ąhÖn|ëYŞ\ˇ°é/&qčĺ€ëb5].JáŮ}HJ_áZxÍŘ T¨Â)• …űHk‰Hv˘R_7%L„Ő׌›ŇsŰŤ(K ďčJj #}ďá¤GAŁĚFFJ,+r^€­Ľ ďż1ÁuL.ŇJB{ ŚtišFCĂĘd9Jô uŁŃNށ˙+ńX„Ó†2łţÄF5F5%€ĘřŤđ/çĽzžŃ‹/ž¤óç/ĐwÜNăăc‚’ÄS8wîœ&jtâÄmáܗżüv@Ŕ˅…:uę4mÝş•.^źD÷Ý÷–ŒÔŚŽĘubb’öíŰKCCCÔŁWŽ0}ąß˙ڗčů+ jˇťOi<ž‘*ŃÝŰOďżÝjz*9’GÖżĽČËH_Ž~ů sôç/Y`e˜­ZztcďŁŢĹFH[dD‘ 8>ˆ Œß'4é}@Ź\œ[N>Ź!P‘kű‡ib Ć„EÜ1ě Q✸óœoÇÇ%;Äziľ#Ţ´#H}GV#¸â<ŕâž8„ë9!ƒ8ÄîJvńqîG2††ŕ8ĘŻX0߇†‡Ř2% ڤÇO~OOOÓÜěœĺ488Č Š&('Đ~zÔŁÝ „uř‰ŸĽšń.Ś^€X*ƒ[FŘbĽś¸L•:[ `l›-'íz]iŇčţĚű/]Śś•EňŘŠvÝ.悓°Ŕ4^Њă‡1`{ÖrȖÝŹźšăřYŠ"Š5Í&›s˘XZ˜ĚÄpŸĺ>Ţť7ƒ6TÓ!l ăă#tú̅doŽ#˘ZŚĐŻÇ/‹QUÂ$Ńő:%ŤťŇ´騍๞hA9K€ƒ3n áÜ)ÁÜÉţj‘Č›ËGéŘ@/“y­A Rz÷B>|jöă6ąŐ…î_¤‘ăODDYŔ )&,ň•×ٟ‡I€Z-0‚ j>ôŽłäxCâ:˘p/ú…–,;şą6~ôzƒjý›[ ‰Éšž™łŒŕ(8pŔ ÎĂTé/Pu GŐjŸeX…ą39aä#júüńÁň†Ň}H+Di€NŽŐĚ ŽÄO‰ŇÖ+tó6Š“'OŃă?A{÷ąŃ„ĐÍěC=DǏ§mŰś%FĎÍÍх Ů~çΝ.͝ý˝˙>:věȚîTĂĂĂŹ­­ú™=zĺsýʼn}ăŒŐÖ´×.kŮzËÁ ˝ůPĽ#n žWŠÝšˇLo>P˘G^ZĄ‹oč§=c…—˝őčľCpC‡X°ĄA‡vNťÓČ˜œŚHLwŠIąŇÇŇ/ĚĹ&ɇ˛<[ŰÉŔ|bIŢ@śgśpáuĘő5Őőýiľbë×oâ˝°ŢŽSÔä#Ár”ĆF1P‚öJŢ*cćZHöí---Rme…Á‘Ńą`%“‹rJAAaŒôýĚĚĚZ@eŠAôŤŕ-`ÂřC°őpćűězÔŁőčf ŚýĆóOqębúą6#~U•ŞCýœŮgev‘Ó%s&;Ëżś›vo°š ž-ĂT›žŁŇ[yë(ÇâĘŤŒ ň Rđ/€ ÜĘyăĐ|"ňëş/#›‘ŽCKň&ŇčŒÖô{y'!›Î:`­buŒĂfĐ&Y޸?¸UŒY BB˝ä€”ÄŕŕŸhýŠ˜őí`^Óě’I|Ś)ę.ŒŚtY´fƒşDę73Bâ§­Î!›ňš$PˆB[#ŘŇjXT˛™jWÝY0&2ÉŢtôłărEÚz"Űr)~ALę†;ÖNĆľ[űYĎKWă4~DQNÔ†:)j›Řߝ<ÓŮl9đdľśJsóË œ\žr•ślŮJ'NÜb…äaŤéÎÓĐČNÚťß=0“ÎďťŔ–ĉăM™ýw÷ú¸¸‚/i÷,`EéVˆ:MÔýxEńHę<łŇ♎Œ ÓÔԔGvĐĎţěŚwżű]Lů}ěc?DĎ>ű<3ďŁV8X\\¤ˇźĺ^ÓłgĎ1ƒĚˆ-ďáŐŤôŇKg-`RśuÎX$oëe­ęŮłgí|ŮÂĺP~bb‚Íča>îĐĄCôŠOý%[Ăüáţwú˙áßő€—k$Ěág/ŐŠŢÜ@AjŃ­;K´u0Ÿ ‚áP_É+_za‰ÎO7z.@7á݆Đîö÷`%¸ŞÄúE›€ęœ-AiŢ"Ďó¤ HzŁ 7RmŐ˘-dä˜N)ěŽE”ĺvT(¸ň. ´ HǝU‹ß%ě9ÎŘĐvţůPDŢ}î˛}V €ŔřR—=. Š€5Ťľe™űűűíZşËťÜĆîUA_˘úŽ?ôűŇĽËv=ž÷ccÍr…{đ.IáżwĂý§Xě*=ęQn‚\ňą“ü]ä5Š-őQe J‹łT_Zq໗'đé”sV8h,,{P„B(˘ťúœg"Vš°)ZV0ZA¤R`aČ٢…-%EŚŃ…Ć"-›úvŢ|çČ$e<ËŠudPľż‹•T˜Š-UV9 rá:üf˛„éřBZîö¸Œ˜4˜Žš6Ęݚk,łnyCšWR]ß0­×[A4š”6‘•@ľÎ‡ŮĄ@/cmzlÇЊVÉ[Á D&w 1 W™Ěz¨ÄtżżDÓRĘşƒbődŋ &J”âTߜ–šłeöďŤöEI4Ĺů˛ˇ™)DújÓ[^ŽYx–.\źjŻ­Ńî={čČŃĂ44ӏ“=aąŇöî?Á-!-ŐécqźH“ĄÝĽ1öş˝—Ś•ÓĘŐ mmę.ƒ‡0Ć  Äşśßř ­eűnRŔĘ՗ˆt łIŞBă'@˜‡ęagđŻL›ˇ‰?W_ Ÿř•íÄ&vQhÔŇEŕwšĄśqÁîpV­\[ĹxHĚđřPI$žm—ĄŁœ6,‰+T• %Ź/օߌ…4(AiôsÍZ¸ôěě, žŐrž¤†}ń—čęÄ4]ź4ÁAßx÷iŰÖm44RĽ‘ąí;X 7ĺÚ3´*ýeÝR ĂÇ\B—!žÓ˜ IgjpĄíŅ9š_˜§}űö't”pƒ‹AćÝń˝-YzLЉöOĆ2ęůLŻLz (•J™(Î$cHÔŽ$nö' „ˆ`‡ˇÜrœ>DËËËtĺĘŐŔźăÝŁ뭡ЯţęŻŃßţŰőŠB ˘˜rß}ofĆ˙÷~ď2ť=řŕç­śśĘsę#ůú—˙ňĽ7żů^ŰÎ]şt‘~ó7‡ÜOoy˛ŮňĽčƒdDA{p-úă?ţ¤­ďżŃčč0őčÚ ďŔ÷YÍĘŚ5 }Q%GŸ\¤7ŞŇńUĘuŹ‘D +-úâ3s4ҟ§C[‹ké zô:$ąŒ 6ČžÉsÄ´[gÄŮęÄ #¸¸ř4—ďsjvn7í ôˇ]ähDžëř'és ‘ă(/1bb—ÚxËů}) ä‘ßâśÄAkq/mgMYđŕÎ!n \[ˇlg:°ŕâŇä­/ƒ*Ě_719Áë'Ü&9ČbŠĚÖ(.#PÁˇď>™ĎvÔg$×ÔéĘ÷ÜztýÔÁgYG›lŤéőhłéŇě$gř)–aYčxXĆXÜŔď˘YÚ ËT´rNu¨ŻĚ˛[N /˜° áŃ qýA*Šb­+âƒŘÂĹG,8­Ň.A ‹ő°[€Ť…‚őJ>˜@(Ň@I–$î÷\Ži˘T˝ÜÔr–*Ó&hĎŢÝ´´i)•AňĄá¤ĽQ‡]Ć@w”I–MIj]ť—şş+Vŕë‹ĆN 明bfEüÄ ˆ›.“lă+MćX¤EáżśşÚé `'ĹęŃÖ?QŞRź#E¤ÝňZśDżÓ˝évŁĄ°G-ÖPJÔu)Öő!*\&ťœĆQăkâga|ś$b& L!‰îŮ˝Ë3“(—Ł(5gpśQ݇qfżqŸ‚šV[Ą3gÎĐÔäŁÄœűúě‚U)ł%Ńš S´Ďj괍s"ZvœČc ÎłEQŽS’ĄDłÖ; ‹ž\m’÷)ó23E›ŚkŤ•xţĽŔ˘ő_¨Œœ…Ý˝ë]ď ŒŐŰßţ6ţţÖˇŢÇçßőŽw‘ŒŐ˙ůţűp™‚ä7ŽůĄúţ K!˙ĺ_ţ/‰vĽ]—Đ?řŽÇ˛cÇzď{ßc•?`ׄ]aX#ĺťďčŁ?ýÖ25۝€8—ărôőSËtŰSó4ÚW -C¤ÎĹoÉÜr“žôÜ<=qn‰~đmŰ8Pn,rŔfÎŻÉqܐ6q\ąbrAc#×,>\ĐXŘľí­6 EDÝš„…Kź~HÜ܏r]>ݧ8VK<Çă>šp€DażHYŠhW%rüáX`ŚM1ď`8âźUŞ€ šQń1Zœ‹îЏTş€űH­\ĺspăĹ‰k/Ge d3ĂpĹ2í!=´ßÍÔdÓv{t=$sńW óąË‰Y"…` g(PzA‘{ôíŚNždŔÄšö8Ś>ȗˆű¸ÚŕŘ' ¤řčę§VÁjť˜óĘY‡U‹ź!†ˇ˘R‚´éäšvˆ–cP-ÄŔŠ}ż"łś*-CĽü5ZT÷î6kušż2Mő­[h3hs@? Ô­[Ć:Í<) çÖŻ| ę&›ÄGWđ%–s“RľIœt?RÓiĘBšŐĄ˜2űŐ9†NĐ6Tˇ/FŤíR*ŕ‚#ńÇ@‰L\ŰŽĆźC×ŕI.šX}?ňÝtI6pŘÝZ*Eą?ÓŹŹQeŘéôärŘŽŇ ߋRQÎe˛ Ęó 3fö…‡{EŤŐäř°šČY ŕüÂÂ]źt‘ƒĎ–ěĆÚg“~ť€őŮ?d<Řžu€víćň:đ \‡^:{5žÓŘχ㳠ú144Ŕś0ˆyťnąĹ&€:{­cłŐJMA#Ň_6°BDYÁh#ŠSžŹUńHށ6ńľ˜č7Ľăt)E­ç• ;śÓ‡?üAęţŐżúéd\‚m˜đD~ňCtvŞIO^¨S­i²Â;e…ȨDżůĽ)š_iŇűß0BCŐ\ĐÎîŠúŁŻOŇ;ďŁď˝gˆňšžwŁ‘ě ´ëŠv…a2ĘŐ'RJ ľŠOä÷(Ł,^Ó@IŰÇ@cË8XÁ ăýŕNă~¸úü÷$tâăŔ„uÜpćqEÔŽ>R—Ś,— ŘőHń}1ţţX鐝{ě ď.Ŕ= s!,!˜Š{‘ł.1ŁąRŹŔZtŽ?¸–).VJěҤS^ŁjĽÚUzô˛–Šżó;żGßúÖc<Ϗ?FűŘ3ȇ˜hˆ­Đĺ—~éWčG~äc´oß^fů‹8kssóv7xnBAÓŁ˝Ú4ť¸HŐÁ>ŠC Äë5p*–KTˇkhux€fĎM0ŢuĽôňŠ1J]í0OąE˝ü MㅍČŕ ś Š äđJš([xV{J,éFş; y4҂!2¤Ö”wifž6ƒž 1UFř{RKŢQ2SVóS‚6Ô‘˛FHÄňvŞňN`%.(mGJŘ4ú⎠łI ¸‰ă€@ :ēÍDŮu š Mgá •ň¤ł;93´˘˜ÂśOˆ<‰MŞS1jqK&n1hť:;NƒzILVŮD™äĹíuV›ŽJ†+Q<˘ Ë"6‡‹ ą… e)kËtöĚYZ°Ú XďTű+Tľ €“‚ećśm¤ۆYséLşý§ô.Š"Ç<ƒšnąF#ž;÷i8]ďKôÇúyÚšs}č÷3)ˆÇâĹ+ԇeǐ0F,üĹ  ‘“íˆVa”`|oˆôľŸ‹62É{´)„9łvŕl=yáeP„tČ9úß?:F?˙š9zńjƒ.ÎśhĄÖŚvbłśĚIĄdßăˆţč› ôgÎP1gŘZĽŻœ§­Ă%úž{ˇŇ?0Fĺbž÷Ln4bf°ţ*î1᷀ PĄpŢíĂ"ü'A“(¸šřLÔ´PŔžx$őŐUgS*óžă2ëäힼ\‚ˆHř\Q–´]÷yťś)ÎČC.ŕšł<ĄDÖ L eůBęŢĺ<_§xwk6$x>y^čúkĎş˝ŻŮŮ9Ζ†{`‹Qă(¸&ň-V|KĹÇľqü‹ŤO,r⛚”˘¸śŻżŸ…ŢőčzHÜŸxâ ú7˙ć˙Ďóö™gžĄ—^:ÍY¨žzę)Úż˙[ž˘lÝÎé/}éËôČ#r&Şżőˇž‡žđ…‡8XýĄC­"äC=€ŻGŻ:xG@ZXŞöŢ[]š”÷Ƃ*.čxe¸ßYA6•‡ƒžŁzH+Znön@AdÂţöHĎ€8[Ş +P˛g.$×Ȥ´œ(eS`‚ÂsŘ ŔÍęü2Í_ĄÍ M‡nhld(,(݆Ϋ:Älş.R‚7eŐo’DŸO|ďŽřŠhCK˘ý,€ŽŘq(C¸.Q 9ˇdĽi!čŹBđđY­™1S#kŔĺ}&€‚˝ĄŮ×J7$s8~Ç"JęŔHR÷d( <ę+’sŁŰL1Š:Óç´c•éx‚Q˘ ŚŘq€,—/ĐJm…ćgŻ2˛kťMv†ŕ„QäLŞcŔ$  ”埤AV\םŸ÷=÷eÎ_œ ç_Ú—ŁŸţî:=٤Ď=łB/MYxši0*ë^Ĺ2– áŔŢmŞŘ]ôřŽ2˝ďöAÚ9ZrÖiÔŁđL‹TIěXÁÚ$ň{ى­<ˆ(ĎD‚X‹uţtěŠÓՐ%Ď@K „şŁduľĆÖd÷)>ú˝Mĺă`ő D,ŁX§Ąö}ŻúŠ{‰”EœS„Ń{îU,*ĹJmËËKÂ&Cv  ů—)aL|¨ßŚ-ř6s– aě(ňňnšěÇŻ÷VöčÚ s–*˜żĂĂ.vbŤ=ţř“túôKtß}oĽ/ůË!@2,­ţŕţţŮ?ű)zđÁ/Đ'?ůgÁm Žş=ęŃfĐÎmۨuőŹŐ•‚ÜĆÖ!>@ Źĺřˍŧ@Ö2f ´9ˆ+d|ŔXoą˘R¨KJłÎ;Pä2š´ĘmŽIňwŞ#užÄ—ĽdfÔę´2˝@›A›޸ÍZţJĽd‚ĆšĽ;ĹlęüeÖ¸XI€Y&űň$°"LĽî ‹^Á˛“Yťćn G;^­łv‹´FÔŚÁ~˜ÁV˝­ÍžŰç…Ł&Gmnç;ӌštEž›ľŸEâ]Ěx\ÎËHČčw< Š÷>†"ÝpňżpźNř—•Bž5^šÇ̝EO9śL(%ڋ)IÂjaP]SŒfmľŽ{ uŘż›ŢýΡйŁ8 sX¤ şFÔčˇLřŒ+ÍâJ­ÉžúČÝúžđĂO͘°P?ÖI&TĎőäs kb \É(ÚŁ˝îŠhľ:GˇéđÖB’‡ Î=ÉxtÇ8Ś\{.?74Á$ďS@ĘˆLg*dMÁT/ Eƒ)Ž™ Źƒö× ­XaŮţVW]ݕr…%œQ!ĘeŽóâj¤÷źĄË=hëV9÷K SD—%ÍŮŔUâ˛Őňř` Ä‚Cč7‚Űrl”œ—Čg/›ygăď+Ę9pHÇz ™™¤ĎökŠ\˛ “"ő¨G×C˜Găăă@ţ/˙ňŻř7\~ÔÁ‚lrr’ăýŕ]Ć'ŹZ”ůěŮsl}…Ôá87>>ڋľŇŁMŁCť÷ŃĚŁŸ˘rľě\kźGBË*ÝY‘dÁiȀXƒŤCýT_^ui”ݲę(Ćâƒ,“ krI÷×L J[­Œ ^Ăsˆ‰ýŠä|\x} \+ÎIÉ'ą2çf„,@›A›ŞÄO)IgçI‡šŮ8ĹBőľ´Ş‹Œ›0ęzEÜęFI‹Ů]Ż“IĹ×%™ö.—eV*‡ŔLaĄgFDÁ 0Iěď++Ć*G ×´88‘Őť9l)%ÇĘőIR7Ç Jˇţ¤É‹÷Jř—7‰;Čş÷˛Š˘YłÎ˛r<ꊞůz")_Í\8Ł€gҘńŒĘlM:ŇńĚS€Pa•|Œ4třĐ^Úżo—Oӛ§¸Ţˆ.­NQÁ2ôűi<0óuťŠ;—1ŽVđ‘‡řţrŇF—š-CKi†>‰ „ńŠbĄňZދőčľNźÂDąE×úĽ{t3‚AťŽ6bý`Tzu% Ţ2T•JY€J’ė…kK•ă9,˛*ŹWĘ•Şˇ‚IĂÄ­÷‘Ž˜5–é6ÓŔIVߒ÷Š}!š7„TĎţ(OÄPA Y\„`˛(ĂăBÎ4ű—QíŔš˜V,GUKÁŚTŒp+ †ő¨G×C˜_°PůŔž›žxâI÷öíŰÇÖ*ýýOYPeŠNœ¸nżýá=Ţşu ˝ăďŕăZűŔ÷s|ŹiŤŞőčŐ˘ńÁš??AĹJ‰3ď mÓţ­.Ö8+ŔëúrAď†ýd O1H‘RĚ*žß…ÂđŠëśQĘY˝ňG\ÁR uŁŔ|ě Ţ3‚ sV‘Ľ÷ĹXqŢ!*ëÔŰ\ǐ㕢Mv˙qîčȝ=w)!nD8 ŤYzđővŰȨ=KYo¨ű5ŃŽ%ŮŚä§ţ‘Ž•b2ęŘČ!Ś 1ńŠ+ąĚE)ť&fxŹŚ.Cˆ”ÜśĚYŰäť´gbë… IÔ l˛ă’BQŐ_Gk]ż QްYSb7¨źÓ8ć˘N†1 „DI@̈/aş`M]0`žźjÇöęÄ´Ő^,Ĺ÷$Œ+šçŕ‚ K“ţœěąú U*¤’s˛‹g[ Řˇ\„A6nšxœ¨çÂ_>ƒM’ÁlëôĎ\¤ą!n[˜`Çä‚‹f¨hőbGô¨G=ş9H„ŤőŁn–&l@˜ËSfœeŞě‚\B3Ţm(m%’´~)ŇŔŕ[­ 8,i zŰ&J­áŰLԓTRűeö=WçÄŇ{ ŸËű76:ƊŸ Îóž\zrš‘I‚ĆąSâ˜6~|Xi˜oIťsĺ­ôÜ.zô˛Hż4 ŠšXTŽeúźśhëećëŃfćěÁ-ťčë/RąR¤ŐEâĐl‚ljŐ ńÝrńŔ`ÍBâI ‚ )(“r°—ŰÔ)úEIĽ6[Ťˆ˘˜˘X„|DČ č÷B|ŠlaLü=EI‘N+Śł şą@•ÄHÓ¨ö¤ÉĈEٗGÉłÝD÷nE&Y(ŤęL ‚ť‰/Œ-şÓÚĐB˛îŹăŃşWe“LÚ`ŠHů>ËO3>Şđa03šŘň€;`1lę(Ł-&¤ŮHľ.ОLČ%5ëOç$źľąLrčKٍóxÖÄѧřx îS—8-ýđŔIłĺbŃ0Yś‹ÓÂâ23nĹbžýhĄÁ࿒epŠŞ}çΓ˳_7jěďŐóŽ0]žšžĄłç.˛™čţ˝ť­v­âűmčňĺiˇ˜ČŘH? ŁŮňÖHéů"o.ŸKÜo FOǏ§0 rż&5~QC ţě=ęQztł(- uP„$(->ƒP–ĘH&ĄfŤÉA1+•*Ý}ĎÝ´kçNzüńÇčÉ'ŸB)veĺEXŻSŽ98Žx+pZ]]ĺ4Ž[¤Ď9ď泞KO\‰R}ŐeSw˘ň(Ü?§SÎ9…×čč ŃÄÄý š,z1x"{/˘žEފ4ďÓ6óţ#ě‡WZ„`¸Ş/Ŕâŕô¨G=ęŃMB*öŒnŁĎ˝đ(*>Ô<–WůŻXŽ÷…úJJ• Ë ­şÔ  şTR2]€FŒw˙ âV†)yŠRŇdŻźxLŰe†3Jts2eÔ!ޙPŻČôŒlK›@›fŠ"ÚÜäč蠗Ĺ= ĽAą(Rč"ť­\lt Íz0†ÉşFu™Ž‡ş]ŠŽŻYyň¤ô}]E CËLÍ AËVĚ{Ć#ďXž †(bČ€ŒŽđO^úg1PE~ MG_şHžÉ¸łôÍGqSžPPŚEUg’kŤ[g!âÜfjľUZ­­đçĽKW-2ŔçdiňŔ¤őőU(ȔË`¸Tqˇ$đsĽVV(şG“SÓôWŸů }ăŃčÖcűčƒßŐG{vog˔ݜmŒA›`­ghĘVd´`™$Ś5H“Í.N9űŤ]rŮ ňšuuł¨Í§öĆzÔŁ˝LJÇCÉ#˛@–4 ’żdv~¸"&ÚíˇďĄö‹/ĐĘĘ2—kÚsK°×ô÷÷…L9ş?Ř_ʀjľŻŐbŠ‘ˆd ŐýâO_^ďÖYŔLúÖu`^ŮCĘĽ2oŮÂűd]ÚöîAÂ䋕$[aĘFoČÇ~á$Ć1A9@Éý6Š\ĘůjľJ=ęQzt3ÖĘťoš~áSżOy+ű!Ód›ŐĽšQŞe[§6ˇD•ţ*ť Z‘ٲýDާ(R2>9÷Š$:+ΝüďËš(ľÔj sm;(nĹk!–ÝR­WײŠI~l’в) ŠßĂMŒ vČiaŕŇŔJÖ8řÝdî&P'…ŘŒëł$íTa/ŽDĄřáŽŐŃŹkÖV: .&0˙ éy˛ŞÚš+0eđą+ą;IŇŐîC¤ĹMůéŹĆžÉîOÖ\Žh#âŤoA˝,Qâ˜?žŚëXň%  „tÂ÷„őbŢrWŔ ŘgŤÚťw'Ôăě@Ţ=ވ,Aš\ҤşkťňŰ0`1:2ěBÇ,ÂDúʕizř‘gééçÎ1#¸ˆöŐŐCCýĘ$ŰĽŞÄsŹ×kś_%ŽŔHËj:Q‚ƒţĺ‹!˄ôÁeNČ%†PLľÝŘDĚÔöyχTŰqź˘ ĎÝ×!™M^€{tóQoj˝žI@IŁ,ŁĽŢAďBřŮn;PáęŐ œÔřú={÷Ї?ü!Î8‚5]ŔzŠż… ÜwíZ+ŒžžţŽ>˘NXľ`?°‚–‹ŢH,Ť•n$%Ú)7 ˝NćRÇ$Ś ƒ%~P"}Ű6žŻ†ĎD…V´ŤiŽ™kԁv‹ů\`œÝŘsŤŽœ‘qŽŸĘ` Đ^zÔŁÝLŤžŰŁ[v §.Ÿć*ĺUJť<ťH#;ÇŠo¸ŸV–Š^kđšó 2L čřŽ›X” ű‰ńŔJ‡„:)é‹Ý|\Eb­bÚąŹËďđ6mR@JśKĘ^›ÍnmŽĽŠHŕžűƒ9O×ňk  ÁX´Ć`šnźţ0Šł×*Výé˙‘ÔÍ0č^dLÇ @•FĂ['˜8JšœcS`ŃöÔj+l~‹€vEŸËźÍ ­˜ŃZcFę—# g)¨%˜…} œz˜¤,“,‡âˇ)¤…¤lJŒiĆt2ŔKşź¸ ľCƒ}Ě  ’ÂŃ1yqeD™(\źR*„aÄB×ßWűďďkËř0íÝ˝•NžžDű÷nŁ-cĂń PŚĐF=–:?g—>Űĺ›o˛ćŇQ‹Á“\¤ĚŐUWe(ĽňȤhtmŕFPˇYâç˛Ů ÖfŃFőčZ)Ý=zÝRÚRĽĂ]†ÜžÎř“\Sâ}rbb’ă Ąěđđ˝÷=ďĄýű÷€ŔˆÄFá˝JľY[YáôŽ[ślĺ~i I_ľ]=Wě^ŸóA^Ĺ"$Ë*EÇW‘cţĆş0ZąŔ`†—ä3Җ*äčpÁÓI,U$yźˇjWeżC‘ŰCóÜFžSGk(J1ÖÄ֝˝x*=ęQnFŞZPůwŢKźř • T_Šsœĺéyę Şý[ššg°ĽYŻSąŻlAČV iP)BiŽťĆK"e]čJ˛˜Ňލ`՗VI§!˙-X¤ŠBľžŒßH–*ŽXÎ7;6:LD1ÑŸl ë8nÖh:ËnŔQÔyíĆ^‹Őëő˝Jŕ"2tG ×FĐb!˘•,ö˙ţJ)a† a›-W,Ăľ´4ĎŽž@Vż‡P2Ű֍{d“ź4ÂĽîĘdb˛”;äŹŘ÷ĹWŠ Öč„ôŘ_ޟ—ŤÍ°˙axc#â ˛ůźÓ°Ľ™ĚpęŇnŢ- Js‡ ś-1evˆ×76>JßówĐýoż›íßcߑf4Mę"Őó(W˘J߀ C„<ظ—fŁÎŒ8˜NśFĘĺc Š(†2˛ššs¤p*Z Žm\XˆŘj§ŻÜG7őŔ”ő¨GÝëÀ°śbŐŔIśkM›]8CŹŽ°DŹƒŰçJ­ć‚š–ŠœŞőžűŢÂV( ˇÄXá”Á*ƒHPTŘO\ůň%ᎠíçŕŕÍ/ĚńÚRg'hI[łdĹa çb@°Âqż+lä÷wXŽ .Lw<°‚ňPbę‘$$ťeÄj˛Ć[,€ČI.\ç{ Ł¨ŇŁW‹z­=ş^Ú ^2ÄŢţôńOţ-śjÎČ*ak Ëü78>d•~ŞÍ/ÓŇä<îŮJľŮE繐XK×h#őŰ骕”)ŔE.đk6ą#zˇOă–ĘmjÖö{Ü~,ż9™K‚™‡öüţâuĺY‚ÍŚĐ&‚*’U%ň JL"Ŕ›„Ő@Dמ\E  "m!a2ĘoLšţeS=Y“ĽžźĄ„3œÍš k,đÇŮ\H16QËjľf9Ŕ)Ŕ‚źOťŘ?ŕ1Ë6旨˜ď§|ą/ţ'cóyěbăP÷ÁNk˝ÂáT&ĄÄŰ #ä}îˆ:QąncĆ1ɊϡVÜg”¸)h˙ZÍşeţŠ ˇgŕ\_q ‚Cbq¨MyąM|qţĺKć×NĆÖkÚJö9>źß3–ygn”âńóV+đ5o6”ŒÁ'|–J•€ZÁ|źŮ\áz*•>˛‘î$ó•8ʁgk{¤Xrţr%Dš/…ń$2=Ś˘G=ęŃMEŇ;S" 0ĐN,°Ć, iđena‘•°źŔ‹ 9wŢy'ťô-..Ů={ž ˆs•O›Ĺ'Ö÷[)śhzfŠŒ$ŹůŐjÍÍÎrűřîRçœŇŔ߃ô=ʰJéŘ6)D$Ůăˆ‰ˇŻ¸l×YS0Ę—Ô(dŔk›śß ُ°qĘ碪۰ōSÄńĎz J^IJşˇ™Äąőh-š¤ŰÚúЎg˙Ű2:Fď˝÷íôßú4gři6­œˇ\§ ž ŒŇŔ–aZžZ ĹÉ9mëXł´Ú-UĎĺŕ šŹ+žŔpˇ¨c ಜÚ9âĐĆ(y‹du×2Năآôń]¤áÎV_uÚÄě?íđjÓg#ő]^OKáťŮxŮWŠŒţćŸěÚQX’SNYN]ŰP7“a´4?´;ĺr‡É´ťUaÎfÄŠÖäU@„CHf…Žp÷Ëdś¨Żä#á‡Ň`“Ą„š.M1†îß՛ôŸÉg´j]ÓnR…ŠáŒ<č  šÚ …xSh0‰@~aĽrţÂUÝtŕjYM\!îżQ˝uF-îž>˘Ţ‹äfŤÔk˙ ‚?î%ĺ./qŚĄBÁiđŔ´6ŤN j™ě(öEŤ‹2š”Ë›łPő¨G=ęŃk´űH*%$ăMˇ°¸reu•cČţÁ Ýrë-‰śh~~Ţ]E‰Ź?m÷ ÁŇö7‚^źt‰ˇ„ŃŃŃD{XĎűúŮęĹĽuŠĄ%Ő˛Q˘.J}żŮ–9I“ÁăbŸ@QŕĘQ°R‘ýűöG€?Ř× šl§ëŽPÉkgJĄ^ ¨Č>Œx3öŰŁ˝„yŠ?$)ŔźĘç{Š’{tí™`ee…“c­Ňéˇ_IšŘ_ŠŇ‡x7ýţ§˙ÜťaZyÄ*ÝWć–ŘZedç-oY ĺ™Ešż4Ec‡wъUގ­2ÖÄh…ˆ{§."šď…E=§2ЊÂŔîýěYœ˜ŤKŁ×úx \‰ôŚđm MUü2ěg­LŤ´č†réZÖ˘tm˘îĎuŁ“#]nc)śŹHó%ݐ“Ž´aľUŕs'/óœFš!ZőořfÁ6Î`ć­ĺŤ×ś ŚŁIâ‰/LňÓÄ/ ş¨ú~Ž~Łŕs­'ę€6A!˘d´•(t#ĘŠţJWÄԍV˝đň” 颅 n;Ś‹#+5ůŻĹnDđXľ ć ÍĚĚÓĽËT(–éÄmˇŇŰď€Ę°$ `‘Ä(ŃÝË“6ÁóÚ<<ÖŐF+Œm:—ť‘œěQ; `ƒÝ‚š|n_ĐäŐWkŽ1ˇL7âí¸f“łÜxëfÇO8€/4ĘE'Táw^Ĺ)9Ż:%.Ö´Ú÷çaŇߍ¸ĺęĂ'Žřŕ+-Ŕáź’ DŽľ|œ$ZlLö$hqZ(ěQz´q* YŽ?b ˘°Ť Ťœsq€;\o8€k(g뜛›c Ź%.Ł\ŢŐĺ¸ ĚD‘ÚcĽZńZŁŘˇZí§Ĺ…EZľ×Ŕ:FÖ.MY‹ŰIíGYŔŠÚŁd˙‡Ëh+^{ÄRý‰u1Ó'X‘"ÝŚˇ5.Ŕ:ęmy(ŃXćri­Żk[Ö>Xýh˟őčzHöQźsŰśmác˝=´G×KXę,ȍżť&#HšŹ“Ż4ażĺŕazכŢJŸůĆWŹâ6OŚŮ˘ŐĹšť:CC;Fiç‰ýî÷Ĺ)ĘŮš>°u„fkuv2mŹ%ÄšřHpß‚Y> w JŽ-eDinŹźZiP͂=°č礙ąRČďJÉ/ŕʡáÝDK•=  ĐĚěB8e\‘UK´F é’éí>JüŽÖí1­Óí<¤a‡ŹJ˘1 ÁÉzł{ł aL-ź0 ŞÄă Ž6D€nÖŐ5ąF1ײswŐNŠ˘2 ‘6÷&Ëdu×d‹]‰˛&şžPž{ך(Jt1ďŃĎ$ +iĚK o8âôzí™ÝHŁX놀™ąłđ @řł/X´÷ʕ)šš™Ł˝{÷Ń-Ǐў}8Hťń(ňÎű7 Ž(sž†ë’¨”…yŒ}ĆMfZC ě­0În?-ŹžčÎaąR.WĂÎV,ţŢŕżAL(,Y¸H D+xó‚+Ÿű܃4<ýéĎŇ]wÝIťwďŚO|â7č{ż÷#ôŰżýťt˙ýog­öĂ“~ř‡ü žfÖ exţˆˇ0>>F÷Üs÷šOzÔŁî$ďÎZŚ˙ˆČ8Ž5 (ÖZv÷äŘW%:p`BPƒUÉôԔŔăXhâzä€Ő+¨°Ţ“!°–Ě[`Ľčݔ„P~dtĚŽÓÁľFęIgŇýďćú# QT–}ť‰űCÜ˙;ǖĹç"eIÄ1ŕ >Ť^+\ç‘  ž—l†Š5Iĺ¤;†ľÎŤ!¨ôčć!ăݨ1wÇÇGŠG=z%HÖ=đ‰ ĺĺţ|Ľ×+´3>ó™éÖ[Ű9q€5üǟä÷ęöŰOŘsŸcsü[n9F;vě O}ę/čÎ;ß@=ôe:qâV pÍsĎ˝ŔĎâᇿaš* Sż˙ű˙œ|໬†l+ˇ MôŠS§`™œœtAĹ,;v”Á—ąą1úĘWţ†ślçööďßgűzž€*=ęQŽ°Ţ‰ĽJˇ¸#:cN‡%9Ѓ<˜Qňi!° …5łł3téňĽ°żäźytĚt;ŤH´Vđŕ XGŹ Z,--ŇŕŔ` @ŘϰG¸X,ů1@ŇEy˘ďI[čhć?Šd§„u%̸ݞę2½×0’žó•šČšRǟčńt.D~Ÿ”Uű’H2~W*Uv5ęQŽ—‚5˛}?™ŤG=z5¨żż­u\ŤW’°‡Üzčýýüýüď˙-Âľŕţň*Í]˛ á—.ŃÁťŃ•i:ű­“´py†śÚI—ŹâŻžX┪™¤uÚköÝ­řP‰œ…J$ŕ|°<ô֍yC•Ąžľ(%=‹Ĺਐ%źĄŤ•M’U6ĎýÇÄÎ9ŘôŹöô™‹nˆłđ“Ž'Ö§š†ë˘k<—”ó•4OŠvü-v‚ôŒ2áÓ á°P¨{KĆŃQŁžČšrX"€‰Złbdľ]U‰Eš¸Á˜Oę†ě¤š|ăĆ÷@Jp{3ŠŠÓ ŠáeIˇçAm1eVšÎü1ÔÁƒqmľ#şxy–ŔÇҎ]ۨRŽr6 ˇ HĐeАŔHKÝąE‡ŕBH-ŠßnLă ‰Ž1Ř?Ý`icXuÇß …2ĺ‹NkŮdהśOSI>FJäFę–cM:—Ěäú]ŽT‰üókľdYe“ęJľMÇQݜ&ňć"zđŢ\˝z•Ν;O˙ößţkś0  Fţ˝ď}7ÍĚĚĐ3ϋ›Ţéɉ ťž\ @Š‹AB‰şXPP#iœšMűK¸bq•Z­ô褚ů9ŢßtÜĘęŻ>Ż(m˝*ű†X–ň˜´]/bëw^,G°6† ś~ Á~KÜnK\š8ŽJÖK׍(<˙Œś°žŇJn.ÂűXJY}ő¨GŻ$‰Bkvzďy%ˆ­UFFéŁď~?=őâ ôç_~ÚöbŤÔć–éŇłgißí‡čđ[NМTŚ^şLŰŤűhlß6š:}…+ŤÎ'mĄşŮ¨¤äŠŒN…X*Ú!mńýţyĽ:ÜGK“ >y†hú}W”Ž>D;Š÷\Ů,9eł˙Č@8djdd(fHˆ”üŤaB?'A¤¤r'ŽťP}­œŽ)Ză\ú:ţLÍĹdĄŹ—(Zˇ?ݎ!+LÍžœmŻÁŽ(vĽ짋W82ÇW(ŘŹśœŻPŢÔ-ZZđ3S÷ĂŁD¤=p4€ŇŃwV"R“ŞËdő>JKř Š0w"I+işâ(™0dĄş ršŔˆÍ°Ů;0ŠŠ€ŹQF;Ş^ů銤5W`R}TՑŃĂĚßđ—ŁBŠĆ14x)CîMË9Ť‚ňéÇo—Ś9,9ǎŞB,Ϥ˜‘t–°žh’3Ýîł@Sî&b4ŔäC›ŔÂůé‹ÔbŤŒhpœŔ%Č 0÷osyX§üŐ_}šöíŰK/˝t–ă+‘g.îx^¨ńUÄ4tŰmˇĐýĐĐîÝťčă˙kšA°vA›Ď>űXŹpü…­KßF,€Ö#÷n9­O€{íRVühĽL.ĂzP×Ďš˜".“é}M€O]>ËVhƒŒÄ ™ˇ Ç™3/ъ, Ęç\jbţnç[­^ďtdý7€-Z ÄŐĽ˛łA D.hWďi%=nŮV:ƒ)ÁžÄ°KO1*ŕ>ŃŹíäý2DiłéˇhDe‰Ťë¸ý(ÖTšX+ ŞÖę{z”EąŐ˜}Ÿň=wŮ˝ş¤Ó׿ZkÔîí;éŢ˙Azň…çčôĺ źn6juš˝8E/>ü Ýv˙]tô­'č™Ď?J—ž:C;nÝKcűˇŇĚŮ Ş/×9Öd,59 ˛Dź'ˇšŒ’—đ%§,VGbXĆŘ?ŽéŇr˛HąZ˛}¨Ů)!ƒ'´öńš¤Km mZL•ŘZüˢ¤xKJ"M Řk †QŮą N82‘ś‘Ą5!”Źg癄ëĄtkÝŔ Ú4š.3LS RÄáŘ:>F—§Á¤ąV[Ś̑ mާb~&7éúMü%^ŤČ˙ŹUt?ă_   ƒ˘Ôgü3Ň7JŘ[”ý '@Ä7Ő?÷+ďyĆAz¤šHŔ*ĹČ$ĹÁӣŔfÂZE^{=uuŸÓ÷/íëÎ#ދ1,;[Ş”ËŽvÖőv“k€ťűź ZěęńćÖ9—Ć™ăÉ´]žznj…zdH[őKyŠčzgöëvěŘÎc đ÷čĐ!ߞzęiśšpá˘ý}Ŕ?ȂĚđđ ťÁBDL;!Ŕěٳǎ#täČaśjvă|űíˇ3@‚ăşş (.\v Œđ˜Űăh.AŇn˝őVŽ@ Ú¸ƒŕľďxÇýlA322Ě@ € řî:Ím/Ć@á}ÁBˆŐŕ j|†Öšĺx.xŢxFx&•J/0ćf’Žm’vSI—ÓAťÝN\/ŔC70Eęk‹n‚şî>rj‘ĐĆ –zăŇ´Ö~‡[ßó/<ęg€<ďö%X śŮ‚ĐÇQiœÄ%ß^äťě ÷ćďeppˆŽ^šÜ:dÝOˆŇ㭁 }˝ž&2¤žoŞĚű śDÎçœEŠůŸŕœň•:âŔéÝO‚É;+™RšÄŕwúţŇBKúţôýgfúwn|2ĆPz´ôjĎ5X5žńÖôýďűýňţ.M/Î[ТEŤó+túëĎRšZŚ#÷ÜJKó‹ô—Ÿ˘ŤĎ§íÇ÷Đđîqv Z]ŞšđŽł”Đ(ČEě’Ń÷褹8ڊs˙áküşßśJHÓur Ç>R@LPd=qSÖp/L‘+˘ ŘRé&˝Ç›hŠr̂*uGłXI—H Řú"“,Ń­Xş!Zű‚t㼠‰Ö€X˛AędÖ"łÎšÄ\ń6Mď›O|˜zU*ń#cŇ×7Ŕס eŻ[­X„&ˇfëÚíF‰ŇĽý˜91YĽÖ¤îc$ˆB7LTˇŠC‰™Ľ>ň…<ű¤Ç€ŠŃ­ĹCŠ0śq[b4Äî ä­Ž^óŻw` Ŕ˛Č ڰ&ęfš"`Œdbŕ€ĽGŻ m„ŃÔ ‰3g*ó•Ö۸BˆÍŃîÚŽvóÁ;˜ĺ îgX/ý".?ÇdńuFŢ:RbZt@ź‘矞&'&y.úÚB_qMŰÇҒ8`Ň8@lą(ŮÄtŸܰżë4ÍYýOƒGiCـ”ś‚ËJNOĎpßÜq_6rcĽ@Żś,^A‰&Ÿz-KsŒhKŢĂŕZ”zĆDŮóKˇŸśÚŃ÷Đô¨G=ęŃk‘°>mŁžă]ô”í˙ěĄĎą!Ĺňě’Rž¤w÷§ůÉYşüôYşňÜÝż•ˇPޖA9;D¤ uóżJډÂϤmK,Šł›łţxĽ™Ś´ëMVđÂRĹř¸Yyť6ů¸ 'Ju.í*kEˇ#řÜĐ ŠŒáĄţn ec+XQ×Éż&ť¸ş°ëąŽkô¤ PVŸ(ł¨Ű…Qꬌ_äReĆLl˛6o“ƒłF-Q˛]Ł'´‰’Čˆ2&•‘HW@) …tż]‡ľ’€\ţń¸ĹŠŐTLkÎYŚX¤ˇ\ŞrŻEČpňź°x!Déqęhëćc“A" SFGĄ˝{÷$ü˙ťŃľúgëút ĘdÔŁë$¸B ö Ü­ćB§„pÄĄZ\\ŕě_ÝČ̓:[-áő,V:)KóßMXO_Łg]Ÿś<Đ ’žW@•’wˇ‘cbA˘ű’äĎôîŢ?Ą„{Š \@ÖtęzĂë —/_˘§žz"€ ÚęFb†°Ŕo4czĂ뽳Š+ňiÜ;⸤לţţ ޏÔË}ÎţŢ}]‹7.'écč(1ř‹˜R1ŕ•'mÉTŒ%śţÉáXÎ.¤˛ąV3˛˛!X­ž#Ý@!É<Ô-`dzžęy‘śf‘6:FŞźô¨G=ú6[YďÝO÷{ž—&ڧčkO=îÖj V,M-Đł=†Ľ•Ţ{+Š>s•fÎ^ĽžŃA*÷WxmE(éÜ0JP‰â6Âo#”IĘËQä­OňNQŕ]~x=EŹFěäD(Ę9+Í\dßĺ"ť"EA­…`1yˆe­ôŢňjÓćލ‚ş†ŮţO™b°–Ű3â3"VŰŢlÔ9 &? ă­"ďć`™˜œŐÖ#oŕD‰š3zď‹Z y1bĽË=f Ž]ŠHzeü˜9űOŤč üŠ]ídށqŚÂíV!Łád‹FáŃF]{żzÉŘMfÝAOŠbü‘<Đсj¤úş.EŽ<@‡˜ń45ž'˜X "é§^č ŠX՘Œžé‘Ö¸T\q_ŔGŽÔ꜡'—+0Ăě´čƛ‰çƒ&TŢ7SĽD”/,^ˆżÓöY şt›cw†43îđÎÍY ^tűíˇń_O[ůú$033ł,,ĂU+=ßń@‹sĽXHÄŕČ"ưz+×Íj”f`˛X)§‹ ›śȲ€Đn<˛ĆeYčŘ XĄ,žSŁŃÖ'âV"ĺľU—Ô›cŤžBWM `‘Ťó~}6jCgđĂ2ŠŕúĹ/|&Ž^ĺ>…5…ČíO–Š#°<Öu0ší–çƒâ,pńŢĺǨm8îSą˜´ě°âüÜl×gĽëűK“ţwěl~ď‰T&ÁŞ˝'ŒŹq|í~Ě"?žůp×`o÷TŽ“‹#´[ĺDQ”Đ]°UŒÝťŠ>ťRzžiW/m˝\eť€tiƚĎŇW=wő¸ĽÁ;ÝFoďčQzôjSŃŽÁożç^^‹ţăÇ˙ =üôĚ˙#ĂÎâŐ9zţĄ'hßÝGiÇ-ű(WČ[`ĺ -MÎSĄR¤Ň@…Ç6VŹ ˛˛JŚ™˛ţS€ VexA4–ŠšTŁÖŞ-ßp2:ŹS •’­ŻJCýT°őćú*|Ąi9y qTŘý§ĺâŹ@îŔ5-ŰfŤŢˆ -‡ßhŒ–ĹŒúę°‹vZYYâgçŔ•<Ç=kŠgčQ:ÂH‹Id÷Ÿ„đ8nŮ9Đ=/"c”7]ç$Dţ~6i­zMPšÖÚ̍ áŮBÉćŃzZÔkŠŁŰőŻô=f r\, ŇżŻĽmÄ´ëÎśmŰş‚ ÎU˛Ęąi čEQ~ÍţBXÇúŤ-^nDJkéӀ“>žž.]G–NúYƒ¤œ?ä:’%#– AZÇBI ş¸ĎךŠ8\ęÔý(ŕboE]ď)ËâĹ}ĎÇűŠťq>ú=öŘcT°ŕAŤéRÚGŞNśÜn˝Ć^+¨Â8€őó´í5äŘ2/dď.ݘűŕtłÔɢřšË_2;„đ 9ď/^VŞî §Tn㙣Ż9˙ĚńlZ!+Ą¸ošń÷ŔJŤíÁŠ6+\ů4Ç+ťpá˝ýíoł{ÉÖÄÚxĺĘš˜˜bĺ‹ÓsHż{2/>ó™ĎŇťßý.zá…Ůî¨2?tPSíţףNzüń'é̙3슍Ŕýď{ß{Â^’q”ýމçĎ_ ;î8áAޤcz]|=žŤt.Ň}wÝM˙ôďýúwżôóôř Ďşýh•hţň4ú›§hl˙vÚ>ÂköěůINÁÜ´`FąZf°ĽÔWś@LÓĹ@ńÉ-DĘh..S}zęó‹™í3p¤śJ ĚĚsĐ\+yËkUˇŇöĂťY>™ť2MŤ‹+܏˛ÝŠĺ-LĚ2 #IXŇĘgň_—É6ş>ż\ÚP%A+Ńč˜T‹I*L“šŠCäT2 Ň×çYĐÓ§6Ö{˝@›ˆ¨Réfí=u‡3җÇIŃAđ-ĘěkşŽŹßëőI*üÓţ¨[ÄąQoú‰3Jĺ’Koăv;^Üąx´›śLÎĹÔHá p ňRu 5tB @@! &…Äa[ĂÝdŒŤb@#R6 f§éJô.’úRH%^h %ŔaҢČ$Š]aÜÜ0ŮÍ âŽ‘ť5$œ`–+Pzluľ­vŽŞ}ƒ|]ąŕĚÉ]ě‡ÎčT*U˜éě¨,ńŐˇŻÚut!\ËV,ś-'ńîœô˝Č0Čătł6d˜Ô#ř+RŒŒ°ťˆl¨ŘˆÇÇÇYř†P —’ÁÁA>Ŕ§ †-.p`ŮoWŞOÄţ€éýččhÂě#ë7¨wźÁÁN+&ăâ‹\˝:Áv׻Ǘ^:CťwďîpťĂ\F;XŁ0Ţ“Üü^ž|…Ç÷ÔŠSʁGŒdOúëżţ4żżÇގżGx̡oßśfĐ_š/ ܍D@wÂŕÚ{Œfz=Pš‘Ô‚w+¸ F<Žńž’ëE҂ťŽ38VĘę8FiŤ8>”VX襰főY :+  –@ĐČB–ü‰ ž%ĤÁ¤4“¸/nŔUÇ͕6=ýô“455eŰ]ąLeŸłđđű3ő`TĹ×ČŠětČDŠŃˇÇŔ7!ř8âfQ[uôőőóű* JÚę'Y'efQzŻ$ˇˇAóÉ)1U`lʟ3výÁ;‡ý,(€˜u“‚Diz L Ú.…=ÚÉ{÷+~żÄęÇ8p*ň`?ÖŹł¸qůŇV$x~-îབ I(Ń÷Ş…YąfŇ ŸŒ[(Ň üMƒ„2AiP pD´.ŕŐŁÍŁçŸ‘ÝwíÚI˜ůssóź7ţÁüĄЧéÇ~ěGŮňüůó´sçúËżük.÷Ýßý~ť—]ĽŻ~őŤtôčQM~řa:qâ6ćż~ó7›÷=Ě)ěcgΜĽ?˙óOYa˙řŸzęzńœ´wďnzÇ;Hđ"=Šé‹_|ȂSďäőü1 ŕyÝyçtňä)~˙'&&čK_ú ă7žńM n‹~ň'˙żěîű—ůWôŢ÷žÇňG,Đő9Ţ˙a…Šý|@4ÄĎ{=€•űßôfúţ—>H-đwuvĘ$V'çŮÍfpŰ0U†űhhç-NĚąKţŠ 1NňEÄbĚ1°‚X(M ŒÔ,ŇXXÚ@|ŕv ¤+VAl•ĹK3 Tť:K‘•_˙{ipÇ]xú]>yžjśN€9EűŽ”í5§.: Adś Ďt ęćÚЂëŚMłT‘OžżČĹTÉwىZ˙ŹŻ,ÓňŇ\¨n#Cd:~šAnXpV.Őţ‹şő“vťQ´6LĆą QJčÝHqů˘Ű4ţw˝QgŚ$÷e*%§e+˛v, ßś|Čçí[e$²ŮÄi˝{Ôŕ…ű7‘î*F$Â\ ‚eü@ńç$ŔJ0‹äUŚŁ[Ě}IśíxÓ¨ó9DĺÓÖ2& é’I÷ÇhŸ7ˌtBĐU=l=IO8Ő/X܁tÝq&ÎyfôŔRg—¸EÖDV*}œY $ůž‡š]3mÓöÚöӋͧ\ކg( ěÍBˆŤá˛I ąŔŔäŮgŸˇ Ĺ 'óséŇeÂxm߾ݞ{– 0XO<ńoÄĐÂNNNё#G8%ňc=ÁĘă7žńm2ÖX@ Oŕž‘ł`ĆWŹęœ6q›”łĎƒŸĄĆ ×T ´k|† “˛UaĹ˝KŰóčž#Ösą&ÓóMťéč˜;2ŻÓﶞŻňÜÓóUęHkťńžôMĎw™›9Ÿ™0kMéRöčŐ'<ŸU+KlÝş…÷s€˜sőWŸŚ[nš…ú˙ößţŢöśˇň~ôôÓĎŘ2[ůÚ'žx’…öAť‡ä÷óţűď§żů›ŻŇ|źӛîĄĎ~ösœÁďË_ţŠ=ţŻu(ƒwćśŰnĺLa؛ń˝GIÂ{…÷őŘąŁüŽŕ9ˆ‚ĺPłyó$X đ ÁżěŘąÇŃY™–ék_ű:[ś€Żskô„}&w3o„gçţăÖ[oéxďţýż˙tď˝o˛Ďţ>úÜç>ĎüŐ?ü‡˙€^KĊťţíďúíˇĘ­÷‹?OϞ>I­˘[ŻV—V¨}ĄIŤD)”Š:ŇĎ F]y  pŸź‹‹Ň˜_˘ĽóW|ŕŰĐ+Vb„°f!ŰOˁďhśs̔éó´|ušžúK˙n˙Č;h÷Ç¸ţ™K“\Gu¨Ÿ†,ȲLóWgb™R€•ĐX,óomn Zl6mˇń–ĄIčŻĐ˛ÝĐӃŸ!öŃę˛EŻ–7<6fÍ3ątş˛8Ëîĺž!2iI6˘î}ÓĎĘŹß“Ń|6L­[WÖÁ4xÔ¨7b÷#`Y ů6MOY{ąâ,<"‘G֟Č2mp•BÔPˆ÷7*x›Ň‚…~Gk ]ž‹Œ!ąNJ ]ˆ°Dƒ6”¨¤IŽ4^łGűç˝fPőŽ“čŇ7†Ň$­MÜKÜŔ ×e4˘Ŕ( s ĘEńőrNaň~<łi|ĐÚ5Z‰1c ďšăŔąB`ĄůDć+}V›Q°Ŕ™6PaւpőĆ*›×yÆ­bÁ[ÁđĐpŞé\ŕĄ+•<8žY8ĚX|€ščóß-[Ć´XYq Ɩ-[illŒ™e˜ƒp€ LýÁ`qÂƏMßÖŕůíۡ7{|P077ËÖd`ܨ\š2Á&ÁĐt˝ôŇKźÁCxć)™aÁ&ÁŽĐŕÚ3h=2Ţ ě‰'ŘÔ  ˜x0 čĚaŞÚˇo3c ƒ Ŕ.('ă# R9Ła8Áâţ>}šAüÝ~ű ;&OsÝGŽ ÷/cýÜs/đ=LA][€.č?ţŘŕž0ŽM÷B4}XKŰç@ĆֆŔ´ŸhúZ˘nÝ,,4P‚ßiD—Óš{q•Á9Ž 5 OǍĽŤÚdü‰%ƒű9pÝ݃sŮEŠŢşÖÝwŰ)ěó”ľĎkž­[]v/q^R¨ç8–X Ź ÉÜÓÖ,2źŃ`;´ĺ–v%–wDĆIƒ2úˇ\ŤÝ˜$žĎzkRhyuH[B h¨ňäIÎ̇9÷'ň§!ƒöŢ7žń.ţKKötXŒ}ň“Ę{ö0X@Ŕęu˙ţý„Yů÷‚˙łĎ>GĎ<ó +'Ŕ{€@¨ç_á=Ď Ę$Xé×kxž‡ú2ƒ&UŔC ś ÎÝy睬PŸƒß{÷îe0Ę (śđ\҄gńáˆţ˙ăßłĽ Ž˙Ÿ˙ç˙‰^Ť´ulœŢűöhלíôţ×I/ž;Mmť†â?l-­Šy ¤X…C_™rEťTЉěqv}v* ŞMĚĐęäl,Ę˜^š”Ě…qB8 €#| `V+ĂŰFićâ$[­|óˇ˙’î° Îî{nár‹łó´4ť@ĺţ* ď§ĽéžVŹ B:ĺ ko.°˛y\Ÿ—…úhrjŽł¨ç děkPš–ŚŽ…Ř€Ź$ࣞ‹š‰gE‰/ášDČQťI.éb& őĽ°‹řz瞂ß@ŔĚÔEŕ'XÔY ŒŰÍźFS“—YhRÎÖˇ`˜ń%îÝIú%;ŮWíâÔh[ÍNžĹŚÄ$.î–ď\ĐZ‘?k \ᘙLŢ@6…wTŐɉԵQÖŻú’ť´ Rü\MâĺwJˇ”†Zş/ŞC4Ý\âŮÇ@RQD;g “ęY'dsn=ËŇŠÓú‘gâŕŞQ’´ĘőUťąL ;ĎLAŮj+aR-ôť1ˆ|ţř”`FťćsËßD$ÚyÉH†_˜uńůtVo8‡ě/ŹZSaźPŒ=6űjľÂŽ+ ! 2´*—.]ňÂdŽA0Z(€œ‰ń ÝčŻ2SŕŒXlqa‚ YśČ?” .2c őÂę#XˆAaŘÁ4 `"Äu JľÚçű]ĺ߸‚,u`śěČż3,Ź8€̤›‹elPîK„5°€)°Ö B+ĆP–Ü+˜Ńńń1öa—úĹMČYöf]0:×Â[âŮ@8Cuđ`×gg ĺľČ …ÖźVH öÝŔ“ʞřŽç%€…œÁOĘĽ mÝ"@Œ‚8'V8W:ąjѤ•÷mŕ9@ˆĹÜĉű†Ÿ@DƒÚZÄÁÜ˝+ĘăŮę1a‹N?Ç ÂüE9™ť"ň=ôČ#ň˜Ë3‘÷0kě?J˙ößţkúšŸűĎô/ţĹ?ç̐ŻUb€ÝŽg'ŽŁ?řĎ˙…~ţ7~ëO˙ˆăĽŔˆçă’á@śyX\—ŹRĽd÷GťžˇňMZş0Á€ /3~ 9/!Ô2,ą5c˝EőfßB{›Ë;yœłüX9ľP >óuşřěijUJśœ[›Ä.HŐá~ZœT8‚‘Ř•‘ň0´Y´y  ‰v?o?!@s13hŐj}7 ¨l|ŘR¨9`ZbĽ?ŁŒÉşD‘P;Ŕui¨r]K ýéók—ďMÎTŃLXG08Rrbʕ>ËźUxáŽ!ŕiąAĂ%š^ŠA{o#;>G÷mľ(üK4żlxĘEŤ‰ś5~!Z5,$¸ŠŒ–Ć^˘Ž[€†xâĄ=W€‰I}jJąŸ&ő=JV#}Ś(v݉SĺHƒD‘€KjŹĹ˛L^.lx`ň+ÚDž=i7€6km~1 }Á•ÄŹeÁżĆ~¤-ŸŐÁ ‡GY@‡É#˙ŮóœnšÜˇŚ†2n…<´y Ők`|ë[ßbk÷wÜq;ť˙<ýôłV(J”Ĺx‚‰‚Ć %0Ј—€ŕĆZŚŻ}íafŽŢ˙ţ÷yÁŽN_řÂCěÎň†7ÜAO>ů]źx‰îžű.žůÍG\atđŕfśÔź˙ýďĺc¨ Ś­§NfŚÚ-X´Ŕ(öÝł¸ő“Ÿü3ŤŰÇgŔ8@x}ěąÇƒY1´i°ŽAŰÎÝĆ˝Ď`*çw~î˝÷ŰÖ- (ŕ>ϟżČV;ŤŤ™ÉDü”ŤW'ŮĚćg?űYońŇǂ|Đ˜~ç>řśîAD@Fć2´;==ŀËżřE~ŢůÎďô€O•5}xNÎĘec„űÁu°t ćGż¸GXÚ`<ľ[@7AîŰĹäf ÄZ@ÓA2…äžŇńQ0ocŚ>Ž3m5"ÂĽŽW× Ň‰€,Š€hÄq<X’ ~ą|ŕ†g *ű`¤č§ÂiĄTúé\÷\a ô ßâ*"ýTć‘X ,ŽE]Y`Jz\łŹ€(Šăh´}p?顯”ŽœK]éAW§á}ĽibŤžœßcœ A ˙.ňŽDF܃|<šB>@i÷ŸŽžgܧł\ĽĐgÓa>8HmĹŚ‚ ƒuŽéۄŤ˛€4xŻ$ŕçR.ŃÖ-ăÔgÁçVDŹłEĘbƒoŸËĄ-ĚąBx'ĹHf\,•y%`łX­ČÓVUříRDÇŽoÎ%7žcr_ÚrE\o:\ŕ¤Ń€Ž<+ý 4ř(@Љi3 ҄:#Ǘä˘dÖŁmŒ°?b/Ǹ˝ç=ďâ÷Šy>÷ß˙v~°žÄł€űˆś´Aöř‘ůáPćď?ý§?ĹJ™˙ńżÇsđ˙ăŸóIć?ę}ŕűĂűÜŁNČ%ëŰ;ßů~Ga¤­Č@˛OâÝzë­<ö˙Ű˙öořŽŘxްĆůűďçëPV. ‰Bóâ?ý§˙ČäöZ&dLŰżk7ý›Ÿúg4bĺóŸůőSci•ňe)vílÚ˝žUg°ąT°wÔg¨f‰dXKCąüFjŻp˙ˆPŹ8ő0ńž°¸â>†Ş;ˇRitĂbŚ2ÔOý[‡9Ŕ-نëxňńZƒü¸9ňĘŚŞuLA,L#íëĐ 0÷;2[Yš[ż~şęźW–fíD)űŕľR†’#Qś¸Ťď!ٟhŁÍo¸×kśë{¤gDö2&3”}@ČX‹‘ăź!¸í<-/5Šfş)%k_…cĐ|őĎҞÝ;č–]UZŠ5­ög•vÁ*ć•&Í$3ü(ń$ź0‘IZŻt<Ă0<3@¸EŒŻ;QwžŚ<˘4J¨0ô-řŒ{ĆŇ €ŒeÜ۸bîuäÚfđ6Š ^Ž&ć­X ôA¨éŕď0uœŸ›ańJšJeŽ%›$SjĚoĆíű-oš—"-tB(„?ôéÓg˜šÂqXŒhćtŕŔţXŕ˜` @"Ě`řđ‡?ڄ/ś´ŕ„űí´X@ď~÷;CÝ( ďřގ%ú_ëb€ …qŒ}‹Ţ÷žw3ř‚ó.îšçn+×ŔňF÷$ŒČÇ>öCAó㴀)V6Âŕ`+ĆW÷SˇŠé{ôˇáŽS<Á{ŔĘÄĽvੰތ°zmyŏ\Ýä˜11H´}ŰÚeV\Ţ攚-ďv†€ű%˜0Gćěa۞Ç(ň˜8Ť&áđü1Ď85ľí×ŇŇbhp^îXž1hĐÎÇĄáĄ`ĺăq+6ÇłÓć­l_Vě86ŐÜpnfąe–ěxŻŇÚňDŔ XĘ;‹s2~<ËL[Éi@çjš¸y.x1÷îôşÝÖ×& ˆęci’gŮ-S¸kËłĂ~ ’şÓmĽƒź÷(I'KÓzYůäaωRAŽ“ç›[ÇZ[ö”ץĎ}V&üéřOčűžëƒôĂ˙ÓOҙK8ŚŹG”6ňrH}a™N_R˛…Ű‚°,˛–q ĽŔ–p&ţL „^qźri‚ňŐ˛yěú_oŇŞmËÁÔgą„KϜa÷ ׊,śZŮ$Le“@•vgXLĆĄá4–â%6'źŽ,ĎŻ]/˝Âd+ŹY§:4žěSvQeÇbşęŢÇhCǒS3ťdœ`žj7lg>(S*ćčę•sV;d™.Ë\@€ŽVű-cf5JĹ!¤J @ÖR¸´hQŔbŠLˇƒ˙g™ÎžŸą‚w/—rôŇš+vѰőŤŔąŰ’>(wS¨P1Jź&´ĹÇ:cŠ;TЁú4ÔľĄ( É$ŁżČá¨eŠŰĆ$ÁcRďmäז(Ń §ľS-Ě­X™¤nČřEIú" ƒ-C ‹łVč˜sŮxěI0ŕxŽƒĂ$ÚIŐý‘źK.řqjŃĹöľ‡ë€™´™ř&­OŻ)­Ť6^€ äšŇŒ¨B4ĽŹľ6i-0ŻGš!_Żn”E{Đ}÷˝%q|˝:×b¸Ż…_ŻŢ´ˇ°q=„öCL˛ HAœĚy0TJŔźŽ5ţ`¸`ÁôjĹRé&ě¤Áv›đVűDHť hwk܃vUÓuŚÝzä:-ʁ´+EZŁ. 2ŕ€´aÇhÁýŔ… ÇqLâŸhpC´žń'ď+ú“~o…9Ć= `"žu@P1ńFŰZĐ˜…Ÿżp!sŽj K,ô8:KŽ6g­‘}Qö?ěÇ{öě B€IŒĄq pć>&íˆ×éˆ||RÁ„Éř}ŞM.›Žé8ú>ä\ ˘Ÿ?§9–$ŠPŹŘűˆšŽ ”g˛ń@ ŠLup_XZáč˛ŰąŰ‚Ů]Ń>›[n9Ćď?¸z Ž'f•mů\ž¸gěQ°¤uu`œŰlý q¤poüĺ/}‘^xá97W9V˜T¸żä2iž$\î€giüĺ˘ŔŤ&† ˛ÝGGGÇh‡'ťvď .“P^ h'P2/œ+G!MiŔ3ýźp^Ç{ыôőü ą‰`Üśď]Ăń3­¨bee/Ňsƒčú×Řő¨GŻ’őâÖĂGč+đ'ô˙ćŻŮżOPÍîŤŔb\ąëćĘĺ)ˇŸ"'SIJ_,d%Ľ+ ż(ĄPV”šÄ¸ƒŤ3Ôżo°‚ÔĘťN¤…é9Z]śëZŤ¸Š÷,Cdn(P…ź’ĹŢ1ŁĂƒaœ26PdŻńi“ťŐů ő,qé–%ĺrˇKÄĐŔ¤ëjIĄqY3$ęZý†Žu#™¨9ߎ!› ‡ůmČj‰śďŘkAŻá°ˆ‘2XlŃj \M;‚¸ď%ű •éŮçĎŘëwSŸeüJy śÔl]yÚŁ2­–gqş3;ąŽáđďYrpÜ1ËŔGÜm:…˙l`%Y*ŤŹF˘Ž!2ž%2JÔĎÚž(ë˜1¤á˜poŇ%0'lÉÓňuI°Ů¤5Žť.ŠQÖԝâŻXęcĆťQwţÇSÔb “ă“9ý¨ę`˛i˛¸w´¸qćŃEnř~-ŻÖj:a“ÖŞ×,ĽMśÓ‚l‰yť¤é•k1ÎYŽrŢiîÝú™ÎŃŁ—GÎR¨ŸÝŠâ”Š.P¨Nľť^Ż™ . mm"–:i—™Wř¨Đđ™SÄG"8‡ăpGĐBţ´†\ŽĽÝ}$ś„ú*ĺ(‘:ĹĺBbH9! d €AĹ݆•0CCĄ}€(‡ďĐüŁ<,[´•Hž›¸rˆťš/“L?Úz×ÂjAâ˙pŠ2őŽŚ­TŇăŐń<#Í@ÄĎ/ĄX ĚÜóq`óxĚô5Y8í}˜&eÁキS`.•űm”Kîş˙úł›ľ LŔ…D(‡%! ™@˜XßŕF‡˜Máĺ\ßXÁB Ö).vLŹ ˝KÉ[1cëo5Ë´ź~ن•]{l™ńń-<_˝ěŤ_ý =ůř㼗ą…SŠčŹ2đŸWŕ–Űî×F7ťĐ€şgeԖçăőŞĺ[łŮڞxü1ő Üܧќ­ŰY0‘žé Ç2ž2ˇ$ӖŒĽţ$ćd$^UXl•MăćśĺŢ(*xŕKšéŐ˝•kÖZĄÝ{Ö,=ęŃÍAŘëţُýú|ˆţŻ_ű8ýŐCŸ§)XŽÔ¨>ˇčd’ľŃx=q””9˘đ#Óy¨;%ëjXËŽűŁ*ď{pűA&˘bŐîÉđ˜H*ÜúfÚ´´9vcF ͞° ö…órJ–ęzm)ńűzA ~ýżÂZřÁQ×ÎĽžlĂś PEŸI”J_bâ~vňÁQGkYgĚĆfWf= źÂ˙p齼ŠWmˇů—-RŻ‹&’h b¨ÓćEť‰6,ł-c× 1VAu;i'ŚÚ´cűV †•čÂĹ9*TŹĆ/ŸăX33 œfÄeМ­śěćœ/[Ćg՛íćS z$€kz´ÉjŘçş°0ƒej›Ím/ď%}‘ÄlĐ.€ „3zŰśmg‹Ä.Čĺb¸˛ôfăp3Aňˆi‚kyä[ěb!O#ęt°ˆŤ‚sĂĂCŹ…]όľG×FhPlł-Ŕčcşé2i×-ěŠ@ĽÓ㠁\ EcáMĘ Ĺš{ĘĹq0ęŮK¤NygÄ5AÜyô˝áÜ-p‚0öm‰ç˘Űˇ´WfË<,YܗXÚˆŠźXˆ&^\€´_@!ź“2~hż!ěOßWVJĺ,,Pq?Ôwˇp<‹œwĺ)ˆ;FœHž§ń{ŽXœ´$=žO.Ÿ°Hđ˝ŕ?ř—çr…TpńxßÔ×h ›n÷#äúD^É`ýDé|Îť%Ů˙Ąĺ<ýŇK!Ýşźgĺ~:°:t€ÇFŽËüŇű?ža\ęŤuŽËâń!7^>sPΎ!žßC_ü"}ţó˛eLĽZf h\ËńÚěNş1aƒnűÖÍAó!Lü‘‹yZđUTŠôhqĹ2*-ťi[Ä Í($ZC°Śţţ2]şŇHHÔQ@*Q×ÁŇ/jÔńĹ]ËÁ˝FŠx-!Ľ×>f2 Eœř‹´ Ä˙8‹—6›?ˇ°X­­rą"âúŘžŔ™[H˜:ßo”á˜*Ą)fĐ zŁFËKóü,pLŹm vÁÉç:ýyE0㔛mĎ(BŤĺ3i Ç°R)ŮşFFÇIž„ĺS]ŽÍ‘9ż­FňěŮs,BË ŕ`bĽčŔŻ@Α@Ňt•žŃ`’‘gbb’ lyDĽßűŢĂ 6˛í<őÔÓ”ÂMdŔ€@¨Í˝zôíÖź&­ ˘DâÓąSŘČ h)︞• ž˜×?DkËĽ>SÄ$ÇĽŒ€,RV2BIYÝGé‡ô śXIŕN™ărČhí<Ţ9­ŮGßń'`îIÇIŃišĹŐB4ń°pPI,pĐI‡. ”XŘŕS@ýLôóŇŕVZť q,˘()Œó9XÔ0ŕ“w{RNŹ(Úaoƒ‰ĐFÎUë ÷l¸~ź] vŠ’ ™ďTČŔ#ĎF[eéů–u:ťţă2š\Čęƒc<ňMúä'˙ÄĹ+ąEúű¨ß*oźë ÁęNƒ; ŃBšłb÷ÉV[k…§Œü<]ĽŻíkôđ7ž‚!WjTń`›´!  …UM˛ml7r|ŒKÎ÷÷îćgž-N ~ěĺ=ŕ?]HqŠňź˝˘ óý™§Ÿ˘gŸyšŻŮšs7=~œ•&}öý€EŢo™WbyĽNI0šm¤ŞvA:Ëš2÷ĽÝŠëjk4=_ő3×VoéřKr.˝G=ęэGEŢw˙wŇmţŘ˙çďŇů(Osv˙\?Űj'ŔˇżĹŕ>bjÝ~ë úŻżňŤô#?ńăXńçDŤŽ­IÖ˘Ôo|o.ޏ˝§\ŕ šľůe'“űö‘o=ńđŐ˘MUHĄůnł˛ÂüđPĐDD dxš€ ˜Ąßţ­_g@ĺäÉSô÷âoŕŞN`E2u{6Îńžš>]ăCŢpƒ –VGzŐ)7/ĄÉóąŹÂ ˘…šeœë+..kŢ çQ“‚šMsaąÎÚô‘á*ÍĚÎŰ]ŮĽŒ°ŕÉÍ­4,ŁÔo_Ž&ű;ĎĚ-ł•ĂpľÄĎęLeZ€8Ę[ŚÔŮft˘“QÖpĽ˜đŰt°“:mYXXäl?/^äg‰`ś §e/1Ђ´Čhđ !P„I6Вă7ޡ’\qZR#î=ĆőF$-0ŇŽ%ú\œśÖ ÷˘QNƒÎjŃYwźˆÓ‚; ¸d*ÂćœÄ qi­ëĄœžşŹ´s8€Ňr+dŁs÷ů.m ()÷"ŽJ"đJ´u‰ô@Ł.́ľŠ€DĄÉ̄rH›Š]¨P‚)Ë ř‚ţHěôU™,ŇV+Ý řcí+éĆ kp;ďăŽ>ď÷âăD­ý~ó|gŘoâń‚°ŸŃaw_> q–…Jú~ŇßeÉi.ŰíŘFĘź‚E‘dž9qŰ-lqÇŔîËǚŃźŰ3[źGŽBI”ĺ/ďľ\.´sízöŮgƒŰ–Œ(6)㙹ąlš óWîM-ŢK#^˙ą/‚/Şř@Ď]Š~.‰;”ńźA ~™rž9sšÎœ=MCƒĂtčđŽË222ć¸mtü¤0źuĘŞUľ,żU˛ź2ÔáćĽ× Î4Ônˇ3çĚ+oI§CďQztcŻ=öď¤UîłŕďŽmŰéüĽKtńęšą /!´őŠýűąŸü'ô_éătüČQúÝOüýđ?ř1š˜œ -@Ĺ8@|‚•Q˛.Pci…JŁv˙đű`ŁćÖAňŰ‡´ˇY´) ŠÓĚx?ŐČ ™@™ű;ĄQ ”oř¨čiz@*ǏĽ- ňC?ň÷Xsźą*bFĽŐŹS‘úă3&6Žđ[!] %KGBĎ̆Ę˙Í´:.ˆP ˙@ îŻ]L›Á"mŽhzžF‹ËŤ´ş<ë|łűJĄ.aöŔ ”,*85ľ`ëśLCĄdǨa5!uşl…véŐr<ŸČŕM>2|݂EYăRŽs*Ëh”h~nšC¸TJEJçOĘđY€ŠúŒşMöǚž¸j€š|ÔQ‡Xš¸yę™( ˘x+ăTiN“Ăá&›Ľ×ëM‹îö1Pᘌ6-.­Ň˛]śnć4ľŐrž†K´{W!hą LĎŹřŹŕźs~ąq}XYmŞvťO ¤”+Vƒ­nƒA“ĺĺ%H ˓Z ~íyf<Ťś%6™ź(Y{˘™oĂJőm&0´ŐŞłBژvťŸ‹088Āh—şŐYwmŮ2Ξ0 ccŁ ¤`ó`qË-ÇŮŞk„Xč´ČÇĹÜőŔÔ]˛ąˆżűzq[zôú# ˜¤-一<1 M}=h ƒ^Š`&mˆŔˆů…ő@ÜoÄ:E\dđ'Á\qŒ3žŹŹĄP‚ôJĽůďhý p!ë :;ŠśdARkËĹÚFkĎĽŹXÂHv´ƒ÷ ď Xą ął[ćcr’ÝEƒJbé#ÂĽÄ–QŇâ"ůŒŁ¸"ÁüąöcŽ3éxĐ@„ţ0/˘ 0Ń@ö p) ŹÇpč@ŃY)Ů÷@ĄNŮOů;ĹsŇĽwv&x¤oßšcŻ‹ývž‰˘"Ę%S93ȀX›×>*žňІk=Jd bK ¸¸ů@Ĺ˜[۝/n×[ڈŰQŠ/Ç6~n´œ[’‰-Ë8Ý{™ř*P翊=ž'IţIĹJW´°€”öŇŮ3/ŃŢ}űiŰö+FҐăýĐď3ĎO;ĆČęłŇôVZů*sEÎƤ×mm&ďˆÎ4”XŤçˇź[zž§–ő¨G7.=÷œ ř]°rÍ~ úî˛kӅ+—iÖ+svݚžuŮéZnMĂÚ0qő*ýđß˙1ú_ý„VŽŃďüĘ'<°2ę5I-6_˞Š,[gr\•=j֜ń@Ži H]pFmj'•M˘MU­˝Ŕ1rĘ44˛‚d‡ý– ׹p_PÉŞ˘‹ ŸjÖ(cÄJA]Ľ?_%Ćze˙&Nđd‚KIf9 —íŁEšžlŃÁĂ´´ź@W&ć¨]ŻąPŘâԅÄB|űYŠŐ™™ôŹ"ťó”Ą…)AKٰíYđŹF Úgj^˛€B_ĹYؚƒhđ"–ŮZŚÍ lŽĺaD[ę&ş˜ŻDԝ?^ԝ}ôJ-UĆ}óÝŽĂ棝4qnó7ŠfAĽ•eřˆ[!1Npź‹”Ś ܟł E…]oúěçŘXÉĽşĚ)ćZ6Ÿ"әó"ef”­ 4Îý'žtŽ+s ľ[:¸çî˜'çbÔâ9;00äŔĎä˘ ¤ŻűŘěsŽ”âJšVˆÖoDÂsŘącG×óC4á=É")řK\}@HüîŃÍEÝŹ´XŔ6 ŚČ – ¨z0OÎ,Ň1N¤! kÖH c”•,;ÂЖ€RV\jDŕpG„7é@ĆĐ&~  "ŕ†Ô!‚¤•,?Śčz%~Šô żĹâď bĽ ßXQh H‚ŕJŒ‰S!`“ŒK¸X˙™‚"äs:eĎpq)AĘG>0˛`¸€ň’áGÜ6E"7 +˘4CĄű-㙶Öč Ľď)ôĚ´őrzdż_ƒ÷Ŕł/;N>ôUjHĆB6Ą[Md0Týđ›žGŤ[_87-—UJÜtâű Ä}e<)Ёę5݇ÄV1ž>fŠâç(φ 潯˛%Ş™žeĹM•­¨úh@Ÿ˜ŽŸŇl$A}K*ÚMPʆŒA~˝‘c:ó–PÚ˘öƢM–ĚzÔŁ×0={6|g^ÁÇ\MÎĚĐE °`]žąű(€^Cí˛291I?ôc?Jżű‰_§ăvűí˙ýЏ˙([ŹhyŒ”ČKŮXł——Œˇş´çëóË$ć ,qšű*ĺűŹüe—ćJł!œČ gŠ")—´ť ŁčVŔ„ś!)őü9Ží Žt5D ř*żĽ•y@e5>ËöAÎńMˇoüćmä)­łÁ˜5nä’$Ł´8¨śÝŽnÖęعݽ­LľĹŞ=XŁÉÉjŻÎSÉŚ2ÄśTÂř×L އŮŔ‡ŐՆe ŞTˇÚŹv˜˝r̜–óŸŚf57ƒĹť˛ ń k‘ f.Źŕ\Qp˘˝Î¸E)ÎD™ŘK´ńKťňÎ7şsl LŢüÂ"ťč4ě‹:48Â1w°&Q˛ŕ\fŔ0ŤČVQ ŒFúžóć˛ŢܗǯÉ EŒE‹ô"ôɞ=[ihxLő&î3,śˆAśŞ†s€KÝě¸>řAF•Šżëœ*ąE…c~ałűlXĄĽÖ^ńו{OšQ’ŽôřŒő裴ŤH›ë§ľĂřƒe…XQHpcՐhQ[łh7ąB’2Ň'ąbAÝeżf"ĺ%=2ŹVȀđ,VU ž§Ü8A].$KH§ĽFęĐ! Ź­’bYńĘxĄm€)°d‘ëeŒÄĺe`Š‚ţ˘˙I/üĆq‰Ľ‚žj÷Ÿ, ,ēĎӁ&üÍŤf(ČxGPQ–§Űíź3`˛B¤L&üĎ(i•á˙P ŃÖCbý’uipĄăž}÷Œr‹‘ç"1źx>喖‹c˜1¸o8„˝  +ÚŠ ĚQ Ž@Q‡oœNšA‚łŠA=°d‚EÇOˇŢřţ\ßüxĽ€Ł4 ¤)ü;˘Ź[ŒŃ glmť ľ=A´Z›Ł™Ů9Vâ X^ń{F‚ QŹÄ[­mkzjŠ,0o•#G{ëIŹY}–ęvŽ×Űěî ąÚ‘?q]á=ŔSƒk2Ú2Kƒ/`Ńeu,—ľĆő¨GŻ‚k{7Ąąa§œšĄ) ˛`­œ_\ ÉéiťŽM[`ĺďŃď|â7č+Ż˙îŻţ-W˝+Ż}˛ŻđWěXÁZĹÉ;ŹňČ*ůÝCŞ#C4źłÂ™ŘU~~‰–&fí~´Ŕ™€Œ—á6K`Ů´ě?1 Pâbzô÷#>Ç2Ý6oZŸ~ă×?NǏĽçŸ‘~řGţMĘCŹÝĺŽé—L§Lš!Ť’W˛Œ‰˙5ç 1S JĐT9¤„…Pľo€ž95E‹5ËdVFhŮ%ř+•*l6•ŹUśkWV–kß`ś3 •˘<Ÿ‡ťO ŕ Wᘖţţ>f‚"/䃙Bš^¸ĽäČ97— ę 5YËje­˘Îę؜=0ňń˜oĺqňÔy 2ôS}@Šeš%NÍX„ŰSĽ@#Ăů8@“g˜)ś7Mś‚z`Á‚€´ó‹–9šŸŁĹ%  DÖ<ĹB —…€˘ŘKn Íě̔§Ú!S„‹’ó~ۅÎű ”d΅!­V Ük nŽ;`Î x[ř)‘wŮÚc zÔŁW„ôž[DJóÇe0@„”  d‰1Ét¨ř.–)"0Ľ˝÷ ŔĄłI?°€;ˆQ‚sâR B.‘Dgâ´đ^Ŕ“>čśtF“rŰeA†Č°AQ%ř*Ú ˘-{@čŻÄƒA;°bŃŕîM§¤ĆoÉV”3 ^eăçěÇH+řŐk ÄC€ĎÉuݎQ” ŕäđ#ú~\š¨ƒgJŽłď éĎ$(Ę`ŠŃ€ŠXĹóˇaűŽLNN3Ȳe|Ôţy7\ăx1qÖ#;§Ož|Á^ˇLo|ă=<7ćšsVécIËżőE}”Żćýĺ&X”˜(sZŢaš'˝fˆ% HÇMJ… Yp^ť Ýh7nXE×Čkö¨G!źNÚMöľNŘť‘ŢKśŽóîkÁ*6Ś-ȂXŸ0¤řg?ýżĐĎý§ŸĄŁ‡Ó'~áéĂ?đˇăJ‚˜Täsׇ˝ŒS'GÎuÖX%3gĐ2_ŁÜj“ŹtÉJaÖP$e)ÓfĐŚ€*íŔ,ĘŚí„nÓ}TĄŒ}*ĽYƒ64×ŔłOm@bďÚlˇ¨+מ*›nßLgIéq°TM§Ÿ&ĺéŠÓł4˝€Íąę4@ ¨PƒMIZ- R,2ŠÇĂJĽTĚ{scX4 p_Žƒsć .K>š´Ív3*AkY-[FÇnüM§ěŤÂe¨Î.E}ý}ńóÓŔ A”Ě‘Kň\뎮0yąÖÉeŚbŚ?ŸSă$f֖ůą‹ÝsϝŚ7žá^‰ÓkŠ S˝3éMdói8Sůi+hŔ7zzf’ë.—űŠńKJHr424ÂQţqŹÚWľăReV3ľŐiá­¤GńĐä$śĹzœŚˇę͈s‰Ź2'ř Ył˜Ř••%fęű, —Ú4ŢŹŃPm`cˆ`zÔŁ5 ë5ÜP°‰ÖZ j)ŔxiKí˘#Ö"K9 „řJƒ-V $óf"œi 0W°ÁqdąBíF$ Źđ°J<܃”Ńî&éTĚ%DUú BŸ{Rß1nř MZ›ăwšŒ/Zđ“ţ‹‹žN1- Œƒ”Ë!‹¸4š>Qhˇ›uG–ŐƒţÂńEÖx2&¨QôR@ăŮÎv|>ž^¸vY€:ű Ď'ÔwRŁŢˇő\Ֆ čƒs?Ľ`I“óźCąPdËWT „ŒÚŁ)“Đ7Wd|sĘeɕk›ˆ“y%ËPä†VŽI?ůKJŮcÁ–(Nť!Ł@b dHĆ lşTĚí0)÷ăÜŇ,Ż`ľ¸łsótp˙žŻ+áÁ×35qŐjvŻPsČ ő§JF0Zšoź“ň^ˆ5 ĆEżo ~+犯óňŽé€Ç:Í2( ¨šQAśx ™ľzÔŁW–đšßČńˆ°~ "ßßsá1Q°k~C™=l÷Ü~ďĹ_–,h\÷ʖ–S‰ľ5QŐXŢŠhŤ”ż{ŰAÚťc'íŮž“ś XYłč\a)ňńTâ.JýüwÓŤM›SĽo>áßČ-ĘĂCt.ş6%>Ľ}”×ôÇ~ÂĹS9~”~ďw+v˙IÓ–+şa)‹G‰ţfUÝ]Î켗ľdR“Q" P[´F˜PÎDš¤$ĆtašE“łu §=*ń\AjíÍ!r~žš.FЏń`$*\jŸËĹ^łş¸ÂŒ@•M¨(,q śJšČţéÍö3!ށ1–y@ů’ŹQ)Űň ČŃŃÚO?ń̨; >ĂĺŐł•'+éSW°vĚÉŐŤ“´¸´ěŇl{&€U“35Yh˜››Ľ…EDŔ^ą@“ËŔKdŘš}ťDUŤN¨°Ě>ĆËĽutfćž?fB*Äśä?ń‡la•Š6 śí‚3‹Çů…ů9ţŹVú8›™8YöŔeläąaX’aNp6Šĺ%zĂäžes+#t!_˘‰JD ms=8ák˜˛ľ˛=ęŃŤMŘ+ d˛‚„?ąÄáGgށP„tJ|ä¸A’eGÚÂYÄn˛üA˙'€ƒ¸Öč˜RÄ6Áş'BŹZŔ@‰;X’Hć!ü—‹ŹAŸđ]E( Aň… ”.K}oâ¤A(NIJFĘâťôîâ>Œ !ňÇE8g÷g†‘¸Îȧ1ÁëtÜ^œuGŹCŲC÷Ď͉|Ó Šˆôýhˍ|˝ÔeÇ$Ó 9+NM\Čs?x˙„vÖîČěŔ%wc #gu…=VťIgÎší›°Újě–&)aü=/“śˉ›•đeŽUxg”ŐJ˛\Ң…žś€(m÷Œ|ŹąŹb÷ś6€•gyƒëŇŃ#‡9ó[ÜŽŕ ČA[¸LŸ|ńEÚşg;Uň*X%Kq ÜA˜§’6ZYy$ł\彐rz>č8*ĆżLZîA€ß‘¸[źfĐąG=Ú  Euz=”Ä}Ł¤ß €üÔOýíÚľ‹Ž\šBżö‰OĐţ]ťyoŻy7`Ź•ˆ3Ů ľOoď×~đ˙ęG˙ąĹ†hdpˆŸňyúvÓćd˙Qyí™üŚ müČđ ŰŠ …€ł,¸śŇˆ÷ÚŔʔEůáö#ŔĘďţöotV6Peä}ă2Fý\[ŕZűl´2RÉ8F™*Q‰Ë@Ě^ő Š ŕŁĺš0÷ç|˛­~záů¨ŻX§C‡ö2ůçĐÄ݊cŢŕŢšœžŁŐ†Ýp9J‘Źś>ž\飙9řĽ#vŃś-Cüq\キD”ę’ąn*Ť\™H´‚JĂGQ@näEU#ęęBlßV›QÓÓ/˝Ä/0ćÚŇ2@”)Ë\”íË<ȋ ţśoŰÎ ˜0äpëqÚdgň ͙fnُŒŁŹ` źb5żÓ3ł–‘\ĄƒśŮ…cÄiřü2ÓÍnŽÝľP•5ŹI˛}]˛ŕknű¸QW܍Ź0ó0!ËYŚôđěE[]äłOŽîĄ% â\ŮqËŐ,WŔ<é/RŤŇG7"ő˜§˝´X§o ˆ Áë ř.€IV`IF¸NŽĹÚ#ŕˆÖœë˛˘ŃĆzĽłéň˘°c?ĹyÄ AŚ=q™BÎ$›¤7–8(bhwĒB_QŻ€4ĆčÔ­pˆŐ ÖY0w'OžtYĚěoIú$ű’"`ę`źhuiŠę-q-”Hs{áÜ9v‡Äž:gldRč,cď„ó\ˆ’va~¨ŕÁ’(ÍŤq΁ÁŐř,:‘Ű‹Âó†ĹDËřjâBÎÝDb—ŽŘ$SrkˇąKĽľćlء¤ţ8÷ËÄî-řžWü{Áűŕ´ŽŻćâŻi@…c€˜vŕ{ĹŚáă…é=Ł8ΙN=-Ď0 PŃăN”°ôi‹ÂĹ'd $ó;‰ZM; ňłëŮ@íÜšÝňL%š-V΄,rŽŻ3S3TěœöüD[¨Č|ĐŇYľVřSŹšÄ2NŹŇ´ľ‰XŠÉzJƒĽ ąöB=ľĹŢŢŮŁÝȄŒ•× ŞЀĘĎţěĎňţď”űŰN­Gű÷ď§ŰO쳯ڜ@ľ^["wĐꗟ|Ž…[ŤšoˇY5Ń+ŹtĄ\ž¨oŔ[8tö†hmaţz)¨řŰΚgF•PĐkřĆ˝6)JZd8źĹ¨6=ăל N~€Î^|‘.^ž¤žj…n?q˜†œĆ„ŸeÄnAËľ:?ËńŃaŞT-‚š´ÂŽ=pk˘sç.ŇĹśe sbâf™óé%ꯖiŰÖQkśf2IFÍýp7%îBŽ‡'űD2Pwœ´üpÍd§Ch…śmŚééIlŔp#-ä}űxbA#0AŹIVÚŃHć<˜EdĺApF˘p6€Ň*/Ńĺ+—ěüźÄ,ĺđĐ(#¸CĂCV`ŮNĺJ9Ü#ăbçŠEŠůáLŞ#ֆ––-U\ć-Ä_AűƒCĂT.–ÝŤ(ĎÜöŠş2O‡ćŻĐ`łN öü™Ąítnt]1ŽaŻ­öÜ>ŁŮ¨Ć Liš›üć„eÚ<ę1„=úö¤+†đÁgdd$-`DÄm €dąÁú#.@kEŔ&ŇV $P,~ ˜"^EĐ× ‡k‚Ä襾ÓôVb–H6—I,@-DŹnpýAf-|âÚK—.ń8Hś É,¤ăÁŕZěëČB é’!Đi—'uú|ę^Œ…ôA˛$éř/l˘ĚńTˆ-1ąÖ_şxžNŸ>Ĺ.œź‘Qł ŮýL;8IR2öZą$Â;)ëö[MăÜŔßá×~e•Âω÷ËŘMU@gĽ÷K܀ҀˆžbĄď'Ër%ÍŔĘnÚö@Něţbüű/đłô@_™–UŢB„Á #1IZŢʖ”űIĚť¸ëM°2‘ń”Ě?Ć_Ç1?rD‘ąҖ,¢Ćdš$aTűí”ŏרś¸# ‰¸Çh'âJƒů{×NpĘĺ’œúú]Ÿí}!ž Çň™ÄěëßźhçaFśoçŢI0fy÷ K60+’B]‚4ăI­.Ö(şíž’ëDëŤ+7Ź PzÔ#GűŹěsćĚşVꨤi# @•עËÔ&š˙4ƒ ś ;f@߇‡SéE Ž[dź~}f„׏d<7Ů<óĹR×6ŇĐÎľ*fšÓ€Šér‘TLœ×Ž48%a=¤[dM˝ Ż?văËÖWkl}ŃôţôL:ž}? ď é+géę…č‹_z„úűčÍoşúűŞŮ“hýőF‹´7ˆě@u žL-˛0żcűMÍ,Óâ‚3ĄŢnÁ¸Ťœť°HŁVăQłË˜ŕ$ë3“Cë”ÎëŁTť2>8>>žŐ@Îb‡ľBŢŰsš/R/w“'9Aĺk ÇŮs§8=âŘČVžg0!gŽ=|˙E@2 ˆĚúçLĄ§Cę Ťěťw~ëy>S0EřŒ^m™šOщć2íąŤ(9e”ó#;éůGˆ“\Ű{i ĹŢĎ 9W-Óu„_i(ąG=ş9ILçˇmŰƌ‡6ł   Žĺ8@ €$âžÂő8.BáůóçÖ1{bv–S"ă7î÷k ŕĄ.Ô) ÔŇҢwSpă€ń‘lC°BAPVbQLšrů":ů‚Ý—ăbăńląĆX˒!Íj Bƒ˛Çˆ‰łŚœ˛öPů}1 |´Ú> j;ŘŮ*#ďö čh€E„ë,Pˆ¨“ÁMßłvw1&ü垘×Ëç8îƒ/ě ”cë ŮŞĆš"ł‹LËíoI%?—Ń(ęP„´=˜ë]&żř}ÉĂ5­÷JťxŻŽ-?â”â|)ĹSäöÝ6Qh[ć´ź§IąÜ֜{^Ă˙nňw4ąg÷.:zôgćc Š\ä1‘w›Á Ű^}ľnçójblľőŘŋ욱Ýj]\B2Ó.râf'ëŒX”áO,ľd ‘ Đx?Ž^˝ĘŸ¸ď—ÄE`ďϖ-[¸źśˆëQnz%ćófů|üřqz衇Žéš*×҇×"m¨â7ž×[¤¸MŹżĎĽze+…Čšgä׌қśSč$+űť?ĘŔĘącGč˙Eúđßúž W…Ă…b%ťü:Îsq“(lş•1ÉďZC +!ž7Ă-—ó4;3É@ LˆŤŐ~ţÝâ•9qŹ•2őQľoˆśî:BK 3tńÔŁôŕżÁąpîźă(ťţˆŰŒó5v˝ZZŞYíá ­łH/˝tŽ^X\ľ€L…Ý`†JôüÉóí~ߞ­T´šŤŮ9Ű˖cŞ5Âßý8f­hîÄ{' ăŔüڞMŃqôł‹RhKlU˘Ćُ'GÜ?u†î?Î7ň—"­ą1.Ó@ٓ،}Ž&&ŻĐĺ+-čR° ĎNÖř ĺ÷Űî{›´úŘÂĚÂşčůšzEţp†Ł¸ŻMY˝iđ&ÍO(g\Ffۖš\Y˘ˇ\yžŞM'T|nĎô|ľžľËźŐžRŢ>a†Ě“Ş´“ëZnô¨őčĺŢ;€ ؐ¸"ā$ËH€˜â 0@fš(&F܅°†0mľhĽ5H! çXLˆą{÷nôźÓ%ýE˙Ä XŔôAkňĹĺ@ť ŕZô BHƒ:8ŽóXOŃîŢ˝{y<Ч§Ÿ~:¸7HđX”Ĺ˝!N ÖȐrů2}ă᯲…‰ŰĆśż€ĆˇlĽąń-´Ýjůa9{@ŮÓ§^¤łV‡ľÓY$c’1ˆ5=cž‹4bAmŰ*IËĎ. ˚€…Wl¸=Ě08€˘T RcÂ~f‚Ĺ2ç4ƒU†ű,ÄnŚ9'v“ž°đíű/ń6Ň}Ö¤­YüÝ ŁŐlzPÇ)&w/.ۋyâÜxx˘­cđŰÍuíJ•'[â>IpZŹSź‰ őŔT┹˝5i Ä|BÎÇd!ŻDó€Jˆ­’x€äöçś ö+2ÚO@OůtV)ÍÄxíÜą>Čž˙čžą¸!1HZ­0°˛źRăżGĆ3:FYšŘ@~'<,Đ@ňN‹Ű›sCviČĺý“ě_’Č:#ŕ‹Œ 9E%m:ŽCYŹ=:Ĺš<“ő¨GŻoÂ;€˝,aŮç?Ż" ďxĽB7Ýu×]t­ô“?ů“ ¨Ŕőç~îçxl7ť›A›Ş´L0˝tB˛ű—‘‘‘r3… §@Ę[PŁŐ¨­Ssw”)•aąňkŸřĺ`ÖźnUäŞ+Ť. SVkk+/PI~É`ς&Kƒ)$ŒnŰE˜')“ţĹČńíöewqľT°Zž-”łĽC3ĆŕWS0ăo|ŰZYœŁç˙ýĺ§żÂ)ąOÜz؂#;(ĘÇ6Í‚ÎÓ´­Ĺ-[‡ifśF3–!›7tlj}–Ą^ 3ç.ŃĐđĺŁfÜvzLL ,ÄŕĹ)¸…鼤U…ÄQŃÓD€ Î{Nî|D1s% Ąxź ašžś`ÉԌ]ËTƒi¸eÂ'&ŽŇ•Ť—hzęŞŐ<í§mžA?rř˝ůŢ73óTôšŁźĘxŕ˜b šĆQďcˆ‹‹KśÍڹà E^ëKQ¸S †Ôآ€8¨,Ł0vüVWčĕéđÜ%ś4ůĆÖ#ta|7}éČ}!-§Ä•‰JVŤ=4ÎZÍ%ŤĺZšš`& VE…Bé†CÖ{ÔŁ×:yŻ9bbAŹ,čEÇ@”ő†:şđ áˆÍó˝`Ľ{´‰úϝ;ÇŕĽĂ‡‡t )‹rb íĂʤąd‘X¨ő‰;/÷}Áőâű–¸Y˘o>+ńŰnť-˙ a‚ü /pŹŤ­ŰśŇ ĎżH/>ĺcŠhKďÜę-W&'Żňbm—žBЍ­L’ŠŠaM17ż`űr‰-WëŤvëV)ÚD>Ó@„ Jž,ǖ°ŕČű´ż^˜6T偸 š"í p“´CĆÇëhňzî€ Ď{EɀşbÍŇ6ٖ5úYfBŔ‡Œ<ź9cŒsąr‚{ě“PžP "°;x iŢ'&ô]–kMpšrńYÄş‡ťD ÇA“ÝówŽK;śoĽƒűwÓŔŕ€E/§lŮFhČőÍˍĐ+câůŠ>š†D*’J”ş˝p `Ÿ(„˜•S)Ŕ™ą°}Ţłgœ>ýé˙aÇnˆöíŰތvîÜa™ü[hY-= ŒœOœ†0´qNƒ×đnR f|aI´ź´LłsłœšHSS“4:ńL"ęx Ž@ЁáŮšs'[… Ź6Ë-8ŽkWâ Á‰W"Áj!Ěé ąř-–-âbáýp†úE[~ůňeî3@ž„űDť¨[śŒÓˆ‹|đŻƒŐ‡ń{Aě–aœ /6íúÉî'v-°•ßA°h1ŢrĺrOLN[đyŃšÓú]¤Ůh$ž]PҚ~}^”Ĺ_"{›ÎNÓ6ąŞ@*!ś™Źő Ö8w€"đÇą[¨Łż°Śgf2ĘPGťI×٧ľ› ŹEđ]ÉäŔmíbB ٗŘ‹QÚm˝ýD$)˘l{E[Ć[Ç8@ŔYŤÚ âG3žĹüůąh›`ýK$|ăľä~%óÎşńkłĺ.,RĆÇFů9HŔ\ůcŤŽ‘Ňć)33s "e•ŁžQtqRZVᒷ‚Ĺ8ŸÇ{¤3rČ;.î}DâOŔňP7Ŕą\‘,X’}KĆçđîÜÄő— `­dţB€|xŰ3UéŃë˜äݨY™äÁ…gčW¤•Ě8ŸkŢÚ7 ڟÚţ~˘j°đĘż˛Ôź\zĎ{ŢsM ĘĎüĚĎĐ+EhűľJ›Ş4Äϒم Ü 9ˆ *y.@łVɸřz‰Áœ*ˇKëľ°°ŇçYŤé @% Ś(ˇÍłľO™ľ‡e:°g+ÝrdíÚą•ŽŮGGŽě§QťšcĂsÖΚ)‘v\㒏͗ůžbB;ńÍȏĽăŰöŇčř.ť‘ÎŇĺłĎŇ7{‘ňŃót`ßNŤŮĹV,öçö .9MN3*Đ'X`™Îœżj7edŠ3Ł”(ţ-L†€,‘‰3D ŕ!ůMIăGˆI_ĺkËt nĽ~äm>hb‘ď+ř|{ ß÷F“ľYp˝’ŕr.8í˛NfčĚŮ˜iŰž}73(;śoŁ[e i—ąŕ..ĎYŚĚ§˝Ś8ÎÜzĆ'/ĐřĽéĹąýôľwœÜCË TrLúĆő}ť‰ säĄáQţSŒ˜7H sůršĘšČŘĎ=ęŔßzԣ׉ćď 3}w&ńştŚőH70FbĽm´Ź ||¤BJ6‰y!Çľ˝4ǢM–೪DëŹׂ$Č,ĘC8BĆ]źíŘÁ׊…Œü‰ťTě˛ëÝ~źČ~$ăˆúE“Ź" ÜC:°§€'¨÷)ZqhłĐŔqýáž$ÁÍ OÓŽMě⳸Ŕk˜ â)ű”HplŃ×.˛ t}Č*ĘĽrB můL‘?[Ĺń#.m3[%Ůßyăžž­Vbkî#ţÎ NłKV™´•śmwcĺÁŽČgτˆ× 7ŸäŮëąßÂ-`Éźň8ˇ=đŽˇ‡{—÷Sb˛ŕ] VÖyn˛N”}ŚB{h)Äb‘¸)âĘ$ďďśmŰB@醏ż'ó}’×=ęŃë™Ř•Íţ÷đâIúżç?k5ŃŹśŚëĄ‡é,ýĚÄ_ĐżŢţ‘ŔÜ ĘwŢyÍÖ*ŻĄM´ýZĽM TëžťB6%Ťý^“ŇôF"žÂbdЂ*Ť´qÉí:Đ Mö˛RuŽ YS°ôŐŹŐű´FB—–ÍÔmŔ>Rž­o i|Ë462@ˇZĺŔţ´sűQvďÚîM—‘ş0LŒjŻZqZŹůůvW™0§űesÝ\—;aœZ>0\ŠÜGűŽž‘ĆśďŁÉK§éÜĽi:wá*ƒ+;śÓ€}Ćĺb!¨a4\ş2ÀĐŃCťÁÚĐÔ446­Ä¸tX EÉďŃžQ`LőÄ%đżĹ)˝=“KĆÍÄFŒĐŠˇŞ "K.NPŰťYš€ŔVŘiÔš^ޤo™™™Iš_œŁ>;čqphNÜvœî˝ç.—: qUň>¨l[ƒ¸9‘*ŇIfhíď—vĐó#Sś%vł*űxâG4ścĎěÔŹ4IdŠ­ČF“F}Ńj 8MŤí+Ň4sp=ֆśz¸J^s$̋KŐB- Ú^¨€Đ/1ÖŞË +>Đd\—dś‘Ôň†\Ą?âs­S*ë Ň<ä„ 4)ńSŇžXŹ h;֟ƒ˛@„˛“““ü‰ąŔ˜Č}`ěđ˜"–*Ú*{ Ź^x‘`ľ8.A1Aâž$pÔP7>a1ƒ:ň°Ľƒ]_€n”Xçó¤íƒgŸyÚŽŻS1“š‹]=xěš đÉŽ:>e4b­lÝ2FUű)V NPç0dl倬u4ffçřZ'ĚšÖňĘX"ӌśşÍ›4 "ÇYH–X&Ś­´*&ě󑲨PĂKŮ(ˆœľEƒ…ĺ$‚Ž*-PôŔ€%/"LËőÚF“œÇäpy+ăăŞĺóql†/źœ ëüĄÂí{1h#ŽCq{&aĽ" &á#ƒksäž%ć÷Ď[Ţ0ŕ”Ď%Á!oš$1ŕa°ß‰%/?“V[›sWr1Z\ů’ĺgśŒą;0m„ŔőH2r9ËԅĹĺŽç!ϖ D10çž y'V𸠞.)އwžëD°Ú’ôäxĺÝ@UŇĄKě%^ЏňÉűŒňCI,W°NHě&˝śˆť˘ĚYŁn&šššć5 nîťÉI8VtiáYŢ9ą$”ĚdbĽˆ=űˆU8†uĎ~ťUžIyŠ Ď âÂůJXLö(~OŐ&ÜZń2¸ÜŚ]?ÎÖ§• văpĚ?řƒ?H>ú茊XŸĐćk™6Tix­…Ö¸ƒ°‘€Ń‚•EÍ"ři%:´6Ľž!Ş/ĎŃľŃĆAMĺžNçœ(ꨊŁćuŢӁó˜đĄŒzŐh&&bĂO`ţ‹´el˜îşý =¸‡ٿÇö1łˆ)Ýh´ěx š ZÚ:öU6ĖăăĐ@"uä,›Ç–+.…^ĄX ćŔŹňŒŹ6ý…ĂĘĘ239֎ôŃč–]4:ž“ćŚčę…éôů :}ć˘íă ŮMźł‰6ýœšÍÂŹ˝! ăŻ,7ˆB Űnĺĺ{x&ů|0&!ˆ]âZ´yˆĄFź“śqLÎ*R#Ż,Ńěě´Vj´}ëN‹<::l…–^h+…Ŕp9Ď<ĹÖ-Ž1E]’vٸŤÓPš´AçŘţ38|V,näž`?ŃBĂç xáőÂÍëŠhśĹ"őH d€)/”aA¨â<ž‹ĽŔ/˝ôÍŰňH%ßj5\°Řłgm?–y-BúŘAŰ7¸XNN\ľm-&Źó°ţđ…ř2–@ĆÜ+[KK5<2ŠűbÂmďnŃâĆ-'Œă&§f\œ ˘P! n,1Ѐ`đIHú™ &Ďˆƒß"0†ąĂ}P;1ŽéńŒ­QÚŠqô혈]jąWł•ŠŸsą…ON).Üő âţŮr%ś~ ci˙ QçĘ ó!ř—8Ĺs.–wŠ \EËę2‰%’Œ(ÉLrlfÚőĘs†ˆ‚ç +Žub˙ťĺ–[¸mdţBťXs$ŁUÍ[PÉłpY€SÔ-ąVÄ}„뀡"ÄMÂ{ň<.ś<ţ$5ł¸"+—›[ůěg?ÇëĺG>ňˇ8{ŰýŃ'YAř#?ňĂa­”9ƒďžŸ~úVfŢu×B=“V@}ŒŢň–{Áłzňɧ衇žĚăüŔßÁZzđř2_.]şĚëçŃŁGiǎí|,m9w#XE|;é峡će2Że/ńă?ţăôńœ6ƒĐÚ|-Óć¸˙ŘM!$ţ˝Îď?ÜDff%p;4ćĽ>ťéś¨Q[¤kŁkV`ĄR,÷][MfíöƝ&ëŤIüë6u76`”ś ŇřŘíŰłn?žß~Ś[o9dĎ­źŃˆ‚Ś$ÓsrÖQÂÁÄ`BäDfđ$ľUŸYŒ@ĽĘ‹;4M`V9ł‚ĎJĂ ŠO- đE´• 2šŒAqőţ™Ů:‡GˇŃŔĐ-Zpezâ]ź:O/œź@[Çi×Îm4:<@ƒC)‹_śöMŒ•HLzş> Ü%î_Ć×Ő&ŽDř™ó1Pt›r=[üXŕĺĚš3Ź›žž`ixh„Ž;ˇŰ9|ŒƒŕPŕԍNC&>ďŹIdڞ4Š.aĂÖ-ŠťP5,ŕ5hŸËHŹőVăŇT¨0žĎČČ8Ÿg ky‰‹"Łk2-ƒ k¤œˇ‚!5šßwߌĎźćĚ8ĐÇPćĘŘřVg?cÇk j8ŤšťüňuIÁ¤>hšŰ™‚“v ŘH=Żtż^ď”NŮ ĄŻÝ6Á­Űý˘œ¸Él„ <@­ł&ąvY PŃ}tuĺř¸VbëBťŽK°ÍHY¨‰™˝h4] LˇNŁM韒˘1 ŔbŚ@H’Ę"bœ$Ý*ęA;p’ű@˘]D`ÓLť¸˜" Š.+Ďm —.]¤eďrpáÂyţ=;+mYxŘśu •.^âőąZ){w§Č§ămłPŽ˝÷źXŘz‚Ÿ ÇťÂ^b”¸Ĺk<€l¸b„AFŸfŁĺ­FŒzţpŠ€“.@ÁECˇ–ľJÖZ÷"C‚1ŠűÂÂÎYšş ô”Ôx÷Ůż‚ËŒ?” `%ŚÎl>bm#ó ϰ›uŠśLr%ţÚÁşFʆÜXt™e\]ďCšÄzb—´Ă†śÄŠ(Mq˙ü}:m‘‹Ýç‚‚îłIĆ0ÄsAS.š÷ ýĆu<ˇJЏUńó-ç݇ |Ŕ“ÇĚťDYa—ŔŐĚ9 m ż”ŒĆYÍd†{nx+5ţnA"ąj_>˛%Š‘$AŠĹJLŹؕľTŹÍÄíQŹŮ kq•+€)šČłek]['ŢSY中Ž?Ię듰ś>ůä“ްŔ am‚ń}öŮç8Ă@Xž>ý?ÇŤW'hŤ]ŰΝ;˛59‹Ÿ\Ę˙˙ńçôÓ?ýż0öŐŻ~ffŚŮšEʧ–——xžD>yr‰×Mźwťwď˘'žxŠ>Ä@OςĽGŻ˝ë]ďbp÷˙řéŐ¤~ôŁÜÖk6TáŔœֈ8&“˙ŔĆ5Ř_%Í=$A +ŘW\ܕW X)Z@Ĺšý\×ĺnßtœŐHÄĚRľ\¤í[G-đ0NcŁCtÇ-h˙ŢítËńCV€d hąTŕÍ˝¤„ÁŠ„ť L˙ăB0§ËË5Ë@.8M,#xóny |q k‘5„öá‘1%'—+3Ő¨ËíF.>ÇđŘvűˇÍ2ť+tőâ‹d™ŚGł›ĚÖÚł{; ˛őJа9n#QmĚ,ĆżłĆ2JüQrě ŖAąÖH—Đ–*Ą/RÂŔ,Śă[htd”NÜv‚ç-[ƒäsŠšźÖ”¨V\—Ä „:›>Ž”öDLě-ËK‹töĚKtĺęUfĘÜ˝971oú€ŢkSĽŇöî%óxÖc°–<čç÷ďWŢÇ( GŹ™Řçćć}̔IŽE‚ěǑÖôzíĆ.!Dî]o%blh,”RÇbŤ úGÁšĂíIŽů8Öó‹˙ W P"€‡¸€jKQÔh $†ÚŹk'ŹDORýŽrƚĹÇIńɰę€[Š€{˛‡‰Â‡łejühë—v h‰7m?r‘SÚą;ŔĚă\.đ! †!XťÄ™ˆ0^°.Ş>[U…*>Čr xE÷X´kž}ƒ-ŘjrĄî„Evč~ň^Ăł& aŠ!LŠńűKÜ6„pśŠ‰r öďßÇB:Ţ5ÔÚq˙âś'ď›XÓHěܓ¤*—˛źV>€Á3ħ€°R^błČó•úůúĽ…›.űž”lXSΜ9Ç{?ÖČgžyÖţ=GßůЧ>őôáˆ>÷šéžűŢÂ<Ćé‘Gžĺł=Öéž{îö5şy5 ZyÔ€ů;żó̃<ôЗčřńcĚ/ Źs/źđ"?ˇ}űöŇWžň7ś­ŇţáŃOýÔ˙˛ŹčzÔŁW’ž˙űżŸ?_-`€Š´ńZ§Í‰ŠŇhąŤ)†Ŕď˛vŃĆÜŸS&˝ze°‚łžź@"őZ”-~ •ű‡ŠĐĹBĹK˛ŕÁzX‹IýŇż™qp˙ł•ÎĐ`•ŽŮk5ƒă´kű89¸›ŽÚcËQŢŕĄ) FĽŔšĄn­Ë&î5ƙ+Cƒßňeű755OöďÔů9śJ0#Qűź*F,˜@Őë5gĄ‚őyfVOƒşŒĽ;¸‹p –0{žŕ`“—OŃĘŇ<=ţÔi鎚–!;°e ‚„qR÷É?&œéěZó@sSę{Ř\4€çŘŠř3!Tœ^fx÷Ž]&ŠKŮZf+$ 4eIńFžŻš–÷đőOĎ>ű,kîócóČ#ŇŰßţVf`ÎťgĎnö?˙ů/˛ ‚´T>řvŃS@ŕąÇ§C‡r:XÄm@zĚďřގÓďţîď3ăúƒ?řýVs‘́o˝őnűÔŠS<ˇŽ9ĚB'´Pˆ1ńŚ7ÝC?ü [ß!úţŸ_¤żówžŸA™ƒ°Đf Ř녩Â=žÓzĚłÎéë”÷JŤ‰÷-ą|Œ]n<°A”ăŢ;Ŕ$ ęČüĐNRHÇŽ7qĘb LŤz(ĎŽWŢŐ*´ŃNšźsý}pű­äyW:HŹuŔŹ ůË 9#'NÜfה+vď:Eo{Ű[ů™@Ůqçw°ŐĆăă÷[f–.˛ő]“ ŽSÍâ7ž™ĺĎ?˙BŘSŢřĆťč›ß|„ž{îťŢ sšcǎŇ-ˇg~ŻŹT`ŘŁmôoú‰O|‚^Š+XKŕňóz°PÚĘ*íLÄńÁ>-’Űv:ÐÂ(—/ąĹĘĆłe˛ •ŞC.†Ęšä%ŐTżÓĐF7ńҤäxd<Úľ}ŒÓďÝłÝ ƒtŰń–ŠÜĆŔB0—cŕ˝oâ}[Ľ8Nŕ †HRí­ Ó ‚ô-.[-ŕ ߍ­6čěĹY:e…f\°EŽ…RrÖ.âăkR`ŹW $ŹŹ¸xĐD€Á„ëOÂŻ]YLtâX„€ŐĂî'Ź™ź4ĘYƒž?uŮöá í´€€¤-ă#.cP$,uÖc'UŚ‹`‰Ł \…ŕyÄL(yM§ŃdŚŚĹâžÓäľvv[AŔ @=ÜłkŮů•ŁŞe^ĘŢ|i™9°OœĽGěë-š<ą˜‰˘(Ĺ y@‰5­b"ŞoɄcřǙB;Íą)|ż7ďnşěr-ÖĐr bŻ˝îĘÖ%sî;ŃUŤaŸ™™ĽŻýa>öo<Â`„-—Ť´Îrů„@†ď_úŇWˆ`đER_Bő­o=ćq+W€‚h!Â*ĹĽÚm˛Ő4ZâóŽXG.;DžcSTy˝@§÷˝ďÝôńWü;ֆťW€P` 1Y¤Ź ü 6š:xđ[ˆu( TI3Đ>účˇřů8ˇ &3ÎwŢů†Ž>\+¨bLҕKŻĹb"Ž-W$–‰ÖËýˆ‹h˜ľvYDŽ—Ÿäş_ŠY…d\¤źX/`Aý`üĽ ąHAßÜ|\a ` ú‡~cŽ#łNÎÇ‚ IvÍ$ďśÜ4ˆB†üv}E?VƒÉ<ť/U+œâ{‡_ŔłF˜Ż‘Œl’˝$kżŇÁň#—w­;Ž­â-FY¸Ţ°ŹçpřđŸQ‡ˆXúŠâ+{ľ‰‘€¨k‚V‚½iKíś#rşď”ęŁvSXËO2]Ď€câyŹ9DwáA˜HIŇW“ro4ÚňČż§žʍłsI\˜ńJţ‰}˜A†>-rޢE\z°:]gÁÂA€›­é‹’Ă?ŔŒ) ͟Ů>BÉđŐ`^/--ó¸•+%ç~čÇ# ˘¸qsw]â™@ř–€ł’çđËť/兩&ŠŤ>˜ĐŤ4É’Tč¨;mEç\ ń;hű’‹Ę´ ˜nÂŢžk×Nś@Ĺ> Đc…Č3ĎIßĐ[ßzŸŐX]¤sçÎŃ[Ţňfžƒ`hńî˝÷^űţ.˛Ć Ě׹cGčĹOqťˇÝv>}šľcjÎ=z˜Ţóžwą• ŹcŽ9Ä,Ż'’tÝ  1Śđ Çű…ľ Źq 4d1ŒiAšf0™läÔFƒÉŚëÍŻÄAĺryÍk6J¤Ž8W—>ř Ŕ•d|ŕą mĺ"škI“,c5ř˛Ä¨ň’AőKčC„baÖѐdÁq_˛îáĆ u„”ôĎř››[`—Ťžj•îaŃĽ÷Řx9‚PZh:Ŕ e°×` ěNę/p§…[\iÇ-ŔƒX*pźjßÓY ޞËRŻÁl吋Ý@„dŒ<ĘrˇK[E%@9î?cK“ř¸zQ”§XՔŚx’z´Ś…Á żkwŸŘ%ňÖ qß´›Qź!ęÄŤ"ËX¨îÁĄüA1ë‹\Áˇ)ü¤nTŠ˙ÉRťĄmź[Źśëbę`ža~qě9ďŞËŽÓĺ’ŕ:W&Šç [vă+łt ŚËoăŢ[¤xĎ8wxá*ĺ P"`ŠQĎľÓňÉđ=bţăݒŐȋu™X`NăÁ5°˛Iś0ú@EÖRřb‘&ÇPˇˇ TЎ¸ ÂŐ]…–ݘ–úőBřaĺ k!ŒŰkŮ„ýýîťßČ4ŹX‚ĺw{:€ěioxĂí žČž÷Ţ÷ž›-Oúű¸G˝¨V+iĐö ‡  ?”(°Áƒô@•m6ůç˙üŸÓc=FŸůĚgŽ\˜ňž÷źç56y-ڜ@ľ­śÄO”´ŢtÚÇžjŕĐ˝‚2çŠŕAl[Í:˙6ŐnĹť>3C–1Ę#z{‰ËGř%rÝk ŒD1Ôö„~1óšŁ=ťśĐ‰[°+ĎČđ:°“víÜj5ƒnłłĚœ‹¸žKô'šGGqËĆő Z–7ľ\XXaĐdbr–Śgź9ô*[T¸Ť"ZXjÓÄŹe§-óŮ0ą™­ИťŁnĐ` ś5Î5ŢŢÎçćŚ9@V_ľŸÇ×맘aEl0..Í`™šk‘ Ě´ŒŰ{jŇđŘNš›šBW§.ŃĚě8…ó"°-Üe4ŁÜ‡IŸŁ.Ç#JCQG¤|)ˆ´ß[śŒŃí'r&gć^ŕ ´.~Ţ1kbu"L¸0ёă¸+„Šeˆ(ń8“ĺ;+Œ¨ýoyĹ2i+KŹńBdĹČ !-¤+hpDÝ;H˘÷㑷ŘýË1ˇ°rŔ3-ÁJŠTq›˛~'Ň/âMD`§§gč… ö=áąP`Ú¨_<É̓ît.… | cĘAŒ}ç/]âc`–7dŰśměúf ď9V0LşJƤZtF…Ń-ł6́ąŒ˙ö뉠ĆŔ&Ňpď€Œă… —ź뀒n” Šg´‘qH_—ŚAĐB`C?`óž÷˝‡AƒőŽŰ9“}§!wyŸ!Ař ƒů Zč˙—˝?’,IŇ1ľçîáîáqGä}ߕY÷ŐçôôtM ‹`’"$—‹%r!K!dÉřˇŹ¤pťŮ%š38GwO÷ôÝŐŐußyŸ™qߗĎhŸŞŠ™=ČŹŞŽęDW”[•gřńîgĎLőÓO?UPDK+ëňUFÓg]uYôřŕPŠ#jś(`”)h ěäĚPGý}υ‚+zlАŽ~755éúć”Ę$ŻQŃćq´Œ˝ž€ĽÄÉîxĆޡ}:ĆRTYŰe˙˛NŒgż”2Łü~ČxŒ{ˆĎŘĆŘř(­,Żxý–?{čs_uEÓH0öŞÓgHáam7pbWÇD]2 ´ďVMHAtY–ŮĘ^P°ËdťÎç&ůœ,R"œ$Öžyos˜+9Ľcż‚)*˛ŽŒäHŽąÉzDąŇ’ Oúy;R@!2iŠŔހý4„”4Ls:tp?3ŕd˛`<ĎíeĎ^sW÷,•ŹE¤%Šéł‚Ą]ˇŇú{;lˍ[[>íŽAIw^8rY‚7­ęŻ‡Ú ť˛^|ˆGŽ6ˆÇbXِ­œĆ#­~†ďńĎĽ2Ypż´rj§h/ѕ‘*Gľě9žéTĐVÇSTe[méŤÓv‹¤cÎA“/mHűĹ+miŠŇz҆k &m˜ƒ´ŇÚĽKĂű3gÎěú}Żýj­žU8 SywŸľIŐŮvYßWÎb(‚RÓŢ~űmş|ů23§a7)¨‹ń)CǏg†ËsĎ=ÇâŰ_ćöX@MKá<\Qv/•ĄÓQĹ΄NĘ1t•řŁěėűęüŠí!ÝסٽœMQŸ5Ú}[)ŔƒbgçĎĄW~űEaű ŇY@7ŐÔ œ/ ŸZľT<‚0ĄÚűÂFő@”MZZYw՜Lśš* R{šÍv0şŕüƒń1뀔ť3+´¸*Jň`-{fgÝu6†Rm*śV4˛ä ŮéŽÖ„ńĐĚX/evížPuÝ"őţN9‚oËb4(˜RI*cpw@Ľ‡‰ Óցă.ÚąBsnŃüľťtor†ŽŢG'Ž’ź^ópđ¤°ÍŽk€o™™°‚“Áş5Yř.`eîš5܃ęäQŽŚ2ĄRPpžL4M ”¨ńç };ٰbô‡ŁĽ¨ř÷üxxcziyC„dk˛G˝8}gSĆv=0]űŤŽ&YTÚrkË|–á^g”~ńŮ'˜/{`ƒQ#D>E‚qóĘ+ßc# “ Ôď}ﻞ|˜Q, gA™ßřĆט͂ȕ–ą&˘ŽÇݤ2ĘÎ:śgËâů„q," "œzîÜYva´a[ôGČëPCýTĹ ż, NŒÔß˙ý v<÷`4 ˙áúĂ(U]›îŚÎĹÎď'ˇ4őGˇĽ÷Ź›yđüóĎ2p‘ŚiSM‡ĎڄĹŃtS@χcƒ}ăœ`l¨ĂcŒńúHdSgGÁ7¨ŐôMíPćŠDä%MHS‡T˙DA?,ŻMš*˘ Ŕ€Xý_÷Ąěefá9`tőĘÇtëöMZ^Zä”R8Ĺ`ôŮ ƒ˘ke}đ ŇYŕ°ë€¸íSŘQÇľÉ[a\֒żŘ&آ}UĽĂÇkŽßô`]ƒ\R›PqHAĐYg"ÝNui”Yˆç™ĹĆ[-J+íÖWşS ý’'&†Í|Ĺ5Ő+ ĚQăĆŘ)ˇÉ\ĺˇÝéDŕ#ě_>đw¤4tdD‘×!JĘ'Ǚ§ď˝^‘l;OúQ'¤¨Ľ×"Vl8żNpŸ´Ş—`’ö¤ó¨j›HP÷ +?DĚ:Šz›ÂřšźĘĚQŃMé¨č­=rĎúUeńb뵑RŢ+ŤkŽo6ĽZ 3Ârąq˛×bšuÚ¤3 MÉŘ$šb‹L!źÇ< %Ă۞-7ôS4÷DK'c-Ě€Ł{nńĚ*sEŸslËŤž śĄŹ4€°“tźBRPE{ESČřYřj‘Uzm5śë;ÎVÍ6ĐGÁîů´M@ÝLa–˝˜wüTďݚÜ÷ž_ŮpR ÷QEcqţpZ`(‡ďľě˛Š J:fŹŤëĂQŇRŠĘ,HAl_Ń7é Ô~uŠő|*ž„,ŘYp°¤+˛Úá•__[Ľ>|űäüÜ,­úô €˜'67k<îĎT@łVÇ$ěWƠ̏ϬgÂ÷ŽŻ & ŒŒg¸ çŔĽ´)LžŠœcH3bpBf9ˆ”`Áł €yČ˝?čž{š[̢ZZ^ s–jOt§cjK™é=ć߂ÓíăÓŚ îoü286…It°]bĐ  IäöÚ~ëŽ :5íŁŠLič8’.ß}žzĚH=Ìőş<“Vӗâ9“nt›6}­–őçJÁV€ Ű }éĘ^ÓĘ]MTťICMo°ƒc¸uëVp° ›ˇżrL•^Ű{ ýĎĹáĘ(ýßöý>šŮ&Œ¨:z‚ľ”z¨É{ř5śDGËŁ! ˙W°ďľ/O{L J‡%™ě y †_b4ö?ÄŮŰ­Ľ]ˇëŰ4d"›¤¸äÎőŒŽÜŤŘâ’Őž;˛Ÿţ×˙‹ďӅł'ŠŢ_sQüłR ”§Ž~šÇ¨Žłźˇ!AÖŁI E‰Ć‰˛˛˛Fs +ÎyžeP“u‡Ů*ÁCrŃt¨Ńřč‰ˆ„Üšë"†ë|…C&KľÚ F…ËW"gdt¾°ť€P™˛bŹuXtp'Wœ&őţţAj zăƟłĚ ł‚­Â`^]yŔËb‚”}ohv9zż°\˙ťžƒ4<şŸÖV tó}ş|őÝźy Źgž:/ú&;œĆŽs #œďpIĄhŕPH×éŢŰ­5K VŁiHţžj5Ĺ5  ’¤tżOŰţtŸRËiő†3ŚÚ"Dť´´Ŕ÷ŁŃŒ@“ŃŐĚnO íöpbFŽ;0ŠŘřU˝…ušžâk5â@ĹÍÍaúŞˇ§žşÄ˘sPŕ ţÇÄ10ž^źxŮpŔżl ĘŃ$%ĽŞđ|RŕĄţĐßŕüolt>•VœŽZ­JŸľ)łck˲ö&€š˘ EË&ĚŔ‚ďĐi)U‚ZCuKŕ !ęŒícĽďĂŠR-Ź#ĽŞyy-™ŹĆŸ–[Ćv‘r†}#EíÔŠSá¸qmDWŞ/ˆ ߟşç"â÷\p`ƒ;f̐0 đ÷Ŕţ}œÂˆůŽŇ˛00Öř‹")žm‡@ŐÍ|“Á)3+Đś¤7ĺŔAy9F&‘¤ˇ€Ő™mn‡źĆągIřqP{ô 8ńĘŜƒ¨+î)›Ľű>Śé)éßtyž§Ú“B㜌Á NŚ5&qÂó˘cîE\cļ́ꊭĽçŸe˛])•S}´Ü5ZšŚď‰¨ŔęHÁe&( ‚+"9;ŻăYSáźmL]ľÉąăguŔ¸ƒ]ƒ ô&pÝ%u' é%hʄĐôJ\‹Žgç4[-Î2šwăýɌK{i@Á ѨŰŕ{´2Ýňu÷źC—ď]9Śa˝4SŞBioƒ¤Œŕ"čB¤bůÝÇAS€ş ’ňąůÔ|ĆX!ŠŞ áYÇő‚nú°jB)ŁO™.Š–’¤œ6 Z-zÝń›ö}ź×y†SŇWD›¨Öó{íKܔ•ť>}Šv¸ë)ülMǝŠ×>ű*Úd_Ľöؘ*-gČHH&Ĺő,§. 6ş|Hq~SqgŰ9]~M~ś&Ůí.ëEđĹ'űú¤2ŃßűŢKôío<Ë~Ă}.#×E˛jŢ8ä-%Œƒ°ĺ'`ՖÁ DÜ´˛˛î˘_kŹ2uNŒ>ĺyIÉÉڑ„pp˙ˆrú\Äo‘Ž8Lˇoßuëoš¨ů1š_Ü ;“+ôęŰÓ4ťä"k[p*2f34†Řń†đĺâ⠍zzl1J‚h b”áĹ{¤†`˝÷jôKÔŰŰÍřĐŚ“ľD#ë ĘĚĎĎpÄwddŒTS‚<›d+ÚÔąŁśZk°VÄŔŔˆťV›4;yŚŽŃßţݛ46>LO]<+X “Ü„ĐÝLľ‹ \Œ –MxKĄ‡¤ŃG5‹M óîĂ0;Ž›őĄĘn@Ç*dxM›•ľmÖJ€!ŽsŐ_߼Ľy_qPD8˝Ăáw˘ČaŘg{˘Q§ ‘–ëd°#Ök,‚ËŐ!\Ÿ8ŔëUűň_)ÍaŻ5ĽŤDó¸úŔ]2_ŠŚ‚˛Ź(äaĚMłQ ýÀ•”™ôŤ˛T  P˘ŽœVׁâi8ˆ ÙŃÔTŇďąź‚#_d Ž…ŇŠŠŘ-ÖŃh7>#‚†sPÁZœţb[˙ńâĹŔ|QÁLüƂ–­&ÍL? ;wn: Y Z"™˜¨ćÁI n{ývžŃ‰ď‚€Ž­*€ě´Jfs•8m/”ž‘}*œažc…_ŹwLÉĎYâ$Ăi&Ý™Ŕ Á˝h4 ¨+ú!"Ňn ý-Můٍš‚s/ŠŽ/đš°@(2S '‘1)ÓUy֘łZÁˆć‡%696íOčG śéőM™ĘZI™+ŠŘ1;ŘHĹňËčœŮ ϊ ó‹¨CW­RfӑÇéčŃĂb3‰:eAsÄ@‹ŔBŮŘÜö×+^Í< G Œ(˝wzM4bM§ĺ•ŔĆŔ2xFŐĐęP˜kóŒ’jQ]š8z/ląę˙Ę]ßG“›mC ŽçeŠ(łL+ý(› €Šj/Š^ î3DÍńť2ÝpĎT Ď˝–GĆłŒmaűĘPÝ.ëKo›z„m)sMÇÖna0öáZC_žöŮSI{íËÝЧa?hJě§ Î33ĹˌďgP§pľ”˘†Ž„ŮdPBŠDÉŇÄĄcô˛™Śťs}}j–LĎÓÁătéÂĄ+0bş0­¨Eŕ%ýÉxvFü!‚;j1 ‰?~9˙uÜş‰=Œ×GäTÂ6,`¸B –7˘śY\ŽéŔ˛zăƒş=‰č“¤XNI5ƒŻˇĺœ“ŮŮ|ďqŻUl–vĂ)òK‹ tëć5çěn0ŤŔIçŔľ—Ş=ëŤëźX8.0ę Ŕ|Qr 9ôTR€N8žF¤sžłrë  ‚>ˆ´8č)ƒĹ˜ÄÍóÜ&×GŮÄlPP*`Îř~Ă”¸Ş[)ę”٢–ĹÖű”ö%9Ńöŕä&Ql`žtŻŁ'`MtüĺŢGcC8.\+Ľ(°6˜ĄRűBűŻYÚ'RH…‹őű´ŞTZŢiq˜Ÿ‚Ţ˜/˜ş$Îx3zĄ?uúôI–ëăľÉpĹ†I›ƒZÍ_ă\Ŕ70Q6śŕ)9qzÔ¤†ĄÝLÉîű†sY^Y `,Dň1Fm}î=#ŮZŻ SÔWÓăR&9”ŹvT!Ęăďw„ĚÄ޲9ĎĹZJYŤĚ ­Ě3D ą-<›CđĚ7,‹ôŐcÁóŽB´86Ź/ŠXňĚŁ)ĂEK¨cŐűŒńŚĎ Lc˙š^ÔčwîÖĺÍ-Ú;͆´Ä^űę4­`÷iӎŐ>] ĎVŻ}šŰcUŔžPjkšn‚> ˘á )UôK“,é łřoWŰőKťëWŹ[áwLć-öĐďý΋ôĘw_ŚcGąŃ$tć S•YűŔDöíYŠ@I#bÎ hu¸ŇĎŞ3"—–V˜˛Bˇn?ŕôžţţŞ€î?+V‘Œ–šzĐžńaf˰΅'{sŤéŽSÇW?ýôŐktÎ öl`˘’KRŘdŢ1σa… IkëËAˆpddœŻĺĽNó, Źŕ§—‹!Šš"EP%ĘĂĽ°a$8p”—[^žçJ3Đa§A8°„H 3؞[řˆÎŽOşŽjévmýd˙‹ôłó˙€ŔzvcÜťB÷ďߤɊ_¸ăo8pĺ4íß7&"vŮŠÚL4ęRŘ-HfgRPD—.0Ct› tŁŘó:šŸÝjw¤’’ë'ďź{•ţňŻ^Ł+×n kÉ]˜c§ž¤c'/šÍôQHÉL Kً1g?ŽŽ9iqžÓ´ 6ËŹ’đAętśDqFPÉő!,+l"˙ź%çŽéžTz“Ú^jZÍŻîöYeľěÖžJ/žs8+š˛Ă%W}ôXÁ =­ĚƒĺÓßŔ"A0‚j<ř‹s‡ "œ/]ŽœX°Zŕ4Šcőŕ\A•/°Ő* XvĹ­ƒÄÉÉ{ĚLáš&—šĆ_”F¨ć 4(สއ”„ jŰm 셦bŇ.U¨śŐ.€.ăŰfvţâšáQxeh'e*ف§[J™$2’+ř-㣠Bڐ%óč;żĎ$?žv1‚ӞРäĹÔç oçčç܃ŐRLƒ ŰJđŔD ˘Ž†§ź™‡TŻČ°HS}4e¤éÓĹ8Í̧)X—V‹Ň9]*Ę>½“Ş4š(d|:Č%ŕ‡˝C"PLm&e‚ÁţŔqĘöĹÎMœÂ4—^ešž€ý”S‘ő×Sď Ŕšu¤sšçK;` „ĆeQąŸ´JöSÇłDBŸĚ„mD(D)A @ĽŠezü@*ö‹ř'0gŹ LĆ€˘x&ńŒbLx˘ZIxÖą.V<Ç`žá9W&,ĂŐ­€njďĐĐwŔfA˙Pś›‡ţ†íCW MÇ(\‹šŮiÚKMTMŤěKŠ,ôÚWŁ}sű'5˜NÁř^űrśÇXýǗŰSč>\ÂƀČëÂŇrˆlQ7pág›]]žOôƒdhŔ꧗Ÿ?Oß˙ŢËôü3ŮЄ1˛í@Ş/™kÂzmŠöSw§ˇFŁ2‘˛é˘*‹DY]]ŁŠűótëîjˇrQŠ7Ä6,@u Π;˙ăÇöŃŘčDŒ(âo;§zyq•Ž\@ˇîĚĐÝéœÖśr*™)ÓPß&5s10˘iCëľółQđÂ~Ŕ q“ëţpšÔɨ㼑1ŕsŠ\Ś‹ÝIŤeG;‹rŇ¨™^Łk1i1°ĆF'Č ;#ρ<ë“WiČ€Cΰzzů*ŮžĽÜíăŐŃ'éýĎŃk寑‚703ľDSĎ\|™NžŚ§°rëúť_źKc#ƒtéâiŽžTń•0¨ë~L0#l’ę#, đkk ''Ź•řE`­ÄN˘›ą|iąńßčÚú&]˝~—~ňÓ_ŇëoĚΆäbÇhhŠ\e6R­1ÜČÚ͘÷ŃHÇq×0ľÜ˝˝ĎŐ5FÇĆDi{ÝÜëŃŃńx^´KSŁ>é÷Ůř…úŢUöZű"”/b[Ýceü>gçc0apŹóKéČjxáم„ĺŃP ÔŐW‚t›ľşÖYSó˜-XŔŐf€ctýúuŢîɓ'€„ßqeÄů!ĎmÂ@‘e;ţťrĽęŔkĚ™)Ň ‘-üMç>m27úĺIŇvre&xŔ†2ZeNjÝ[Ľúňl<…3´#S%ՔąśX&mÖIŰ`7üeТ¤ěĆLA˲âőlЉăǢÝč? N‚3šâ¤)r\BޢçîŰň%Ń9ţô)ÎŢđ(.ŘÍŠ÷„HËwciVŽŻWʁ.JţŕöŇS\2‘ŠŐÎ0ŤšeŒ3źúĘZęw‡2JaĂéî5ßÝ6 üšˆĄ3 ź7=łČ/6˝ ňš ։(Ř#22Ü ŁG&¨Ćšv†#cŰŰmĽiŃÜâ:Ýžý€&gÚ4˝TŚÍí-?Á ĺ´í€”{ 02ëlT Ô;Ô¨lš@É6­‚DuŽH42<(•ŮŃÎ;‰&@r]şLě;(ˇ+29ö7%g”gŁyÚŚš˘Ä<Œ›MÓ˘Üůł¸^NŽ‹Dږł3rˆuĐđć"˝źrŮseşkFéőÍ}ô—ő3ôăý/ Ţ Ś ąĄVŸ2—`ĐôŃÁ#gh|˙Qš}p›f§nĐĎůUÜÜwţě :¸B´pź"uX‰á" :)ăÄ÷ÉB°; >^ g×sąˇśšź'Ş4ĄďăuőúúáO^Łkîo(É\Şđ}ÉJ5d훑ńƒ442Á՚¸uEĘÉú‡"…ú‚¨ýŃ&%-Ń@ϰ†őűúECG´rDg§ÄžÇÝą4˝ąŻÍÚ˝Öp-Saž^ëľ/şIŠÁÖŽ ”) žKEżŘĄ Џ&!š2OT„R"uŔé…ÓëÚľkź ž`Í4€)ęLhYfÖLXă氍ž~ý—6Öy@Ř6Ě6D+e;̓"œ“Ś“0Đ çĚ47ƒłĆBٕrH`'Ÿ™0˘Ů!e}Ŕ‚1˛,ŻUT(íuD45°ë6‹11MI[ÉĺS` đ+AXŃřˆÁ”îtŸT—$m)(aź¨,3|2pýŹřOŞsĽc˛çÖřƒ5Q!ĽŠÉWsňՄڝPúXË@Ă Vö‚—–2.ű4'đ$EnŔő­ƒ÷; n"”0VP‹ű™OGŐY$+IU@ayآŹ!Ç3šRJĘ<隄>™Šâuz˝YßĹW"’’ż›ĚޑԘۅHČc˝ŸÚź’yǃŕÖ^kUI‡´ÄŠIÂü‘kÜpž (ÚNčÇjłˆvŽžąlhˇRŰŞťb)Ŕ,ţ'€$¸_7ą@SŐ{Áţ $çŔ)Ň˙´úO ŠŕwŒ? •¤éř.häxńk°PT¨ß°ŃôDe˙i™evœ=ÝÚěŰSé?ĘJĂu@yu‚€]V*őô1zíWo:—PvSšîľ/k{l ŠLä6:gÉRuŃ05xY’‚65jŠHFşĺŕ㉠_…†ÜD‰jBižöÂôíoý,ušÄAăœ˛&R0ŕ}´ýŘçĆP°ńxnĺŕŒ‰)5*˘ę°Fz ü ůűßó ćˆ&Ą‚#i‰ęHŃ(˙ŽýŰĚý¸“yvŒŠńúĘ?i˙Đ)ˆôx<Çú”žô¸ )Hš }IŞôČgf_đź$f`Ÿ…#=11ć˘ňűH );qˇd4ČÄÝ% $h˛ÄÉQP…ŠŠfœJßî¨t]3Űcó JG˜=ś#Š´P†X°,@ ńą‘¸'B›Ëŕ?햁O¤{l3eßÄ~› "ÇY…X<GƒíŘäˇ#€W’ ˝kô9í/iż‹âžđ f Ry˜ iĘν{÷xěŔX1iŒ`ł`LQýźÇxĄ•żôţcť+˜=ëÓą<žwăó‘Z,ŤŠä/АJžW˜*héók‹s›œźĎ ŇÜÄFŔýIďíĂlŁîűońűŁěŤ.:XaŮÝśń¨eˆvßW÷>śěĂ~ëţޡ˛ä ¸w¨Ó,ÓŔŕ9ZŮŘfcĽ‘ó”Y‰ř-§Kƒ70&WśpB.˘bQîĎMŽyŹş{ĐÁąVÉ!îĆÝ|ä6Ł”ÁĺČ8?üŤÎůF˜şsžÁl¨”+ą|4 g ś\ôŁ˝Î×mÔil{™ŽmĎRŮ­?_˘w‡ÎŇßúF*Dź5+ZFňWĹřA"8ţ(]bpE€˛yąO¤ ˘lź8rň"8zŽ–Đ܃[tůú}účĘMşxţ+Ę^RÇY…‹˝-Rts6sÖƙž™wƒá&—XÄŔ895Koż{…Žßšd‡IŇvúř58źźŠ;°Oę÷âŔĽRŮ â ´źH,Ž!Œ9Ž”ŕÁ,Ž†Ĺ Ľ6łOĐ/™ďţӈ1G–(SŻőîŁďÉbäůóÁś‡†Fů=ś‡’ŰZtż‰e°‹@Š%K{WáŚĺ:a,ÂaC$N…C{­×~ŐŚL 8ľHEŰ °Sć Ćf-ƒŹJń׊?D¤Üs×řĄMĹ(#hą´4´.Ä%á8!ňĺU€WőVVVÜÁx=ýŕž LF!XľEb"°"Z-qÜeF‰§wäyÔăP‡^Á`¤čŕXVÜľYvN_Űk=”ÚĽ e˜Ťĺq¤–Ÿ+$ĺAAxĘ$Ä~M*,ŞIŁmĹ?璲¤ó‰Ů…eBÂbđ@uąQRÊ~NżŰą=żŃ4D0t đäD&jt˜dECTdŒzŚ˘őç%Ç'c5_wÎ5Žl$ ÉĐЍ:;éčŃCŹ%ýٌ˛P<ăBć°ƒ¸Ú]NUcJPşÝ(ăŮ&6XŚp>q”ől!ś˜™$:}̤ٚÂoš…]ľ*ék™×sIN€Rfää1r ­74¤Ď""}<é˅ %Úm’–Ç€’{ĺ&§´ĘžŢِäďsnŐъA<ßçÜkßţýĚ&Á3Żé;v,TŇ´"Ő[AŚ7n\Łééű;‚œÚa„eŠó$"ô ’„rČäëÓ[ŒˆĽ*@‡]‚RŞV3=v¤(3/ď¨pj›1†ÁÁvœÁbl2С[ĐĆđAşSs´1čä+î-8ť<`ťšT˛D;ćŻtŰ ş{ą1ÍCś“{°¤[¸4¨“EđĆĆˆęuX˛¸ ääÖ@• >DcH_ČJ‘ůâ퍘ňhÂ1ÁŽ*3¨ďAÖksŕÖf;˛1ü*Ú7ô¸5c§@)ôúŁó7Qʈ”ę?^ç…A”Žhl2°WoÔ8ŕVM˜×2S¨Ô“nSő]tűAx×kĄ_ŽŒŒ–<72:ž)e“s‘ ׈ה‘´'8Đ b!aş–O×űUśAŸó8öůӶݎĺłlÇě˛Î皟őž˜mčXl`ˇŚě­ö˜Ň(…”Lâú#ŔF5Đą|C؎¸hĘ0hƒtćÔzúŇÖ 9wöŁęÜӍ'ˆZߎ‰|Gó…30DšŰn˘vĆ!*ĚÎ.š‰b“Ł/pŽ7˜!"X(pŚUf;Ŕ0Dĺ™QwŒHÇÁÄżąší€“9š_n9@f•Śg—éî}¤ šhŠőĽË1€‚&buvf­†ËM|çöRN•ě>Ůö<ŐJăn9hWœńä&{ŽdĆW*ČRăQs…cڎí•Ů,0Đ`4ší"UÇ͆ 6‹ Ź›TÝńh.Đ@{Ó}ߥĽú-tśéčÖj:cç;ŚŐĂ´8zž.› ËXÜ5u앑Ąz$‰Ë¨č{|Ź9 =kk+üƒ+,§j¸^žCAşVťÉë`;Cc¨ĎűęŇ,mŹ-Ҳ3fŢšJű&†čđĄ}\‰éő7>äÔTĄÚr`Ú­;Stůęmš›_ňĆš°yú\l`ř€s>]_ŤScp„ŐĘJ €‰?ďމ1‰ńlÖAÎ{ťĺ…)8ˆňĆ ř Ô5Şűŕź5M'äęůw!EcÂýÁľ„ń„}!bˇ˝˝)U šŰź(îCćiŠ{­Šţ„:˝ 0!•ĘW¤čE¤zíÓˇRHŁĂť*hJ1GCßSBŞďŁcMďáČ8Ä7ˇś Ë(#Őb“…H6Z ŇŔ Sš?žSĽ‘ÁV‰4™ź;,<ťÉ,=IóÉCę(}lbĹ|nű€Š”ž5̘Č} AŻ ö˛ąľ)`yŽ€Ä™)1{̘ŠOť!žƒÁîÊÂThňؙ{(ňĎŤRI¨”2„ü=`S*ĹăľIšP0x=[AÇużťÓ}ŇöĐ´œňN˜ăňN§đť:Ó|¤iŸŠYo™á }„Ů ŁDˇóBęóxڊg"ňšëú|/ĘÁšĄ\Ń#Ů´M˛tém˘˘ŁˇËšuŻľť›çÁŁNY(ß?1ýŕžr°Œƒ%eîoUN[2ÁžŒ6%…{ft˙q•ĹÜۗ°ËŰ Ť+ŤĚŔ eđ,Ŕ˜››ĽűS÷¸ŕ5Ëâý‘JMm:yň>}†&&D¸•űżŰ'ŸCzŇYœˆMbƒŚWgöćĘááţŤŐhŚ0 5žm-ľ,Ű6íś ҅TŤ‰ŸĎN˘e“ĄÇ‚sB*OżîUSašVöZlZ–[Ť‚ĄÚ śUŮŁ>bwŞđĂÁ”^뵇ˇn?§×öN{lŠmđbiĽr‰L˘ŁepűëŞU\gldˆŽ=@ÎgFÁŘŘ0=rŔ)Ăl\ 8ńŃOÝ)ă„ĹCłÍB˘` @enn‰A€) ‹Ť>•C `Ö.Š”<b<˜)cك44ŘŕÉË.-Ż90fž)̋ˆšsƒî͑jňŕřˇÚš9)¨˛Ž&ú4x%bN‰¨3,;HśÁlm[ÔGÓd:–úĘݙšČeJôpˆ‘§ˇMét(ȉhšT˙ÉIę¸ÖvĆnk›ö7çiŔ4+ŐQęÔhlk•ú›ŤźÔzŠN­ţ úťĄ’6˛ą.Ž‚3ÜY  hŞî"řJî…ő†…Y×ݢŠ ÁŔF1“cťľĹ ˜,4Äł^X×˙΃áŠÉžZ-q:^źÎú*-ĚŢŁ•ĹzďÛ8YĄŸţüÖĹá|ö¨őŔh Óđř §đ°Ţˆëő ‰˛V…Ĺ KíĽ€aˇ3bb Eţ†ŸVÓ3•(ć)ČV*Ao€+ôŕ‡M”5mnšMľxœ'ö͑DŠý…mHM­Ň(fˆŇé-0]ŃŘ4ßp$s !ĽÄan8€%gŃGň´ËŚŇ öJëŚúŠń,NFπęľĎŇd<ςNÇ'EĽ45FE"ŃđŹŠ0­.ŁMZöVƒ "|ˇĚ“‚„Ř––MŐeRşąj+ŕ/mmm•…iĽŮŔö“’ Äüü"*¨Ţ ˘…Č64_ŕ–eÓę5¢P=,ňŔtI„R.yúCƒŔoeŠTBV=$Šíxśœm9p< +[ˆĹhIěx.Q蝣‚ťDź(œ¸őĚ ˙YӌԹîf¤t3bş]/eőđ÷‰ŽW<†Ě3}lâmn ˝×`IP[ö–Ýţ}űLŠz§XŽě“T"ĎţhݛĐCőúń›@(i6áZ —]Ń ěžîží¤,ÜsI“9Î0›ŠOlŽjEö­<[ĘĐѠߟŒ GX/”:ĂTHg[Y^áë† ÖŰv6áÔý)şsç6Ţ´*cŠ”ÜOcƒ ‹ŠVűéVß1Zm!-EX(¨–„0´K††}du[ŽőőŚ7čœ2˘7ĹzĂÚ$÷„'_v:ÉM3…Ž[óôsżŽ‘ˆT*“Ź =ýęŤő‹ţ N0?˜evÉŕ°WŽŃŇÂ4o÷ýđ‰}|Íą 0PpŒ™˙N@ѓŮÜÚŕęMˇß­MŃ8s%N"bąÝr‘X<†Ë0V B†*f[3˘/$Ń6† C3 ÜŚł`Ź5‘űÜi3˜Ĺ|­ ‘ęé5MŸ"ă"ţ5˝ 6ŢRÓ‰rçş˝Őf1ĺ˝ÖRŞŻô5|*ő@•^űLm'ëîÓRť9ęťýž6­ÚŃY8SʸRýR’m+(#ď%éĚęHŔ}?ë~9şž‰Ř¸ŒkěEŁBćÂţr?Iu”X’Y˜qČü8ˆy†ÇO™ß1ŕŰdđW)&îőFƒƣˌUd&7š˛’3’ Ď@¸ÍsŸbÓaÇ?ÁŇ{´Ű=Kű@d…Dŕť0óńšëa# ´ŹLq}Ň嘍¨ä7>Fű÷ďc 9ŇŻó´_ŮxO#hţ)4ó°Ď‰ÝňĐž­ç…3°ZŢůnóü§•€C"XŰ °˝Ţ€HeůRŘ4`[MA•ÂńËgw R7˜UźÎď‡öćŐŃoŢźÁ"Î&ŕúAOYfĘŞ)•:žÍ#)´XŐtZc¤;pŃmœÚxXśťěwü‹}0(ęöăĆ ž~Yh(ˆĐóż‚BpźişlO'đ“%óeŽľĚ:ÎŰÄ{|‡†ďt,`ŁËŤ^ öŃÚ,#ć÷•h=ç¸×z­×Ňö˜˜*–'őfŤ|đz6Ň.^8Mă#Hó˘ŃąžTU5ž¤‘ŹRĚ.FJ’ +LFBŠE$ Š;›LŢýóΔ}euÐ[,”§“7„f‡‡¤‚&ҁJ7RPćöíI™¸G óó4ż°D3łó´j¨ T`´Ň×a͒RŐ9˙YżLŃP q1‹v0lžăjJŽ´§í:㢅E9%|Ę9JíUŔRŁž’súmżX\„ Ľć:ݞ§‘öm:đäA6Čc3HTŚ­JúFčAzöbP—[kśŠRj:§áށőŽv4Tů\+ƒĚhhcÂś0xjŐ:ëŒŇršÄǟçŃśŔ÷YtüMş#ŰĹÄ űˇŇ'Ľ–a¨—k’ÇküDŻL肀(%,ŽhaYVF9}§Łâˆ9”óëŚzę}2ţAÖÖ¤ě"*°ąşěŮ+Ž r ƒ ß1‹Ç Te€Š*?ő÷7ŕ!z0ţiáőLIŘ+ˆŇ:}!ď@ܲÉë#]JŻEať]ćq¸E‹A.OĐt[ÜŻńL ˆú­b}tšödű,ŽpŻőÚçmÝýMÇAPÔ Š!ž˝0Ě8öę<)]_˙Ş3­`Ľ‰HˇžđűĘĘ*-,.ÓĐ@CtMR/šÄ@u=ë~hôÓŔš›cšš_D@ĄĹ㋊÷Uä× Š2wŹÓ2ŽSîMŮ !+{ŕC‚¤cŢÎC:"^Âôéx (YMt¸L`ƒň>ŕâ拎×Á?š+”˛GôŻ-˛N$ő#OR‹­°lHő‰űÝm›ş?땲)‡x‘‚Da_)8ŕƒH‹~ŕŕAalIĂ$iOŸoD‹U™(˝/a ý­Ăŕ“”×JÇ3ąŔü ĎŢŔœRśĽŘŒOc2Ú/<Čm’Äiżˆ“\Ť‡~SÄs˙AÄőĐĄĂ!p`ňăË;BÄĄaŸV}uĆů@a  —;ŢpŔśƒö Ňćf%siڕ,uĂ*á—`Š,ĹL˘ŽT7;ĎöąŁGƒľVßŔE–’ž+Ľ˛ń›Śřhye|§Ľ’(‘˛ćŰ Č e Ëă;ľ4őPľ›°- @üž0?ËÇQ-QŻőZŻőÚWŽ=śôŸ<÷ĺćül˘•HԘɐ/$}C&ŕ臕‚i#*C‘N QąœSz6¸Ň§ô<˜Ydă§ĹU6x˘Ď|I=DCPby|tČŠý\ţ¸Ń_ă”$L∏,--ÓíťÓ\JíÁýIVý^pŻŚ eͨŃküńĺ ętQÎ:TëƒümZ¤TD#S ĽuG-ř­ľĂW×Q#NŒ šr>`¨XŞän˘ľŤtzk’SHîN€Ř⎥EkŒ”*´•őŃzyś€2eJŢpŁ×˜řtÜ6;śę&É&ŻŇěR›Á16ŽóN2~r—Ň‚Ę;\Í&wçÁYŽŢ´Ŕą˝˘;Xwہ(\J$*,žDľ‹ !ĺšpţ{Ţ7mvpjő†,›Yo\FB÷Ý­[ €%Ǐ"•Ř ˆş!J   RiE¨Ënżrü/:+Ç؝Ąž#*š4˝q™č|Uź ÷ď–č0`˙ëkŤ\&YŤůčĂcťöe}ä%QEËT`@"Ĺ "Œ,=vYžźąkŘiâœ˙îĐk˝öš[Z2X#4}Ö[äTÇ ÎX%pjđX)؆ HÂiÂ:ŢF1XM1‚3Ľ ´ŚľźčëĘĘ3ęŞŕĽUcTXUŠ†¨ź{a vœŚ‚¸Ú”I‚u•Y˘ú&9ǀŕčXEdđâ :NKęLĆěI?t{Ű^Ô7i>&업jý¸—eÍ(H%`żüŤóSTQĹPĐ^éN ÜÉ:ˆ)żéýTÇY˝nsŘvŔœd}™eG JYFŚä}„{xЁ)Ăž"Kž¤4=şůو/¸ŐÉmˇĹşBÄ×€´č$¨˛Ĺsm˝żî)yVP}‰CY´ĐyE+%ŔšîŰ&ŹK˝Ú!ÍŘaÖězza֎Ŕ•źÓŞÂâňU^ĎӇ~(ĽĘagpÚˇĚ ŢeţŢf™ˆ4ƒ1ŇďŤvá~A:ĘSŰMnyÂH2;Ů)ézR%PĘ^C¨ĺ”ń=Ž×Ďźj'iŚňqJ_šËŁ?`Ŕs˘c@Ş—‚up.Z! żkĄt<Á˛ZŇ` ö{ëÖ-ŃpÉŰäb’=PĽ×z­×ž’íąU˙aąąV› ń“Ä`|t˅á kjęCœĐ…•ÂÓRNQLmk›Sx–—׈˛ŔaÂČť„B„FXĆÔĺƒű ŢÇ%ő;‰˜ÄXdöî}şă€”ۡoŇüÜkŽ`ŇŔdcLŒřÉߘ+݆ƒ¤§GŇ0єr7IgÎ`u€ÇÂş‹ôqe˜"˝˜‚1ĂŠ2Á€Iň˝=…¸”qŽŒű\ˇMęo­ÓÁÍ9:ŘY˘ SĽť•1š­ŒuNüşí#H_”kÎpv`ŃŞ3t֚e“ő-ˇ …60$dߜfă€ä—Q)ˆú¨ńÁĽÚ/;ôœ#•ŘčŁb}}ĹVƒbŔ˜há7cŘ€‘ §˛ÔŒłƒËŚń:Ľ…gĽ`؆¨NąŞ¸sȀcE{с;0‡†ăĺćk—X„HكěH°Řo"ƒw_Ąs&ˆLÖhh˘ľƒ‰!EĚú€q ĂĚ&š6ş ř‚éׅ­ŕ\łpŻŹ’”ERîçď%%JXakŤ+|œzÝŐřDůIQČzŐţ>Ϛ!)›í#SŃ5Á™ t1Š×z­×ž€†gśEhaňčb’¨ˆ-*v(˜ 88ˆ(c PĆ]dÂUC fžc˝ ×üc™wȰ-DŞ--D`ţÜŘŘâůQ*Üył!8,§˛‚a* x“™,-G9gNűő"Łĺ€ÄšÓ”–šő ’IĆĎQ6‹ç:đ÷i•œŻŠĺĘźż A’BÚaĆJ/{֊í>Č\đXNYÁ  ŇżqnßÉJAăq?ϨČRąčćcńéŞáŕSÜľUPľI´sŠ­`%V'Éř˝ľRhęüű}FśMΕ6Wrlú´§ŞŻ6ű6–e-ćSľ ëAC،×ĐٙÂSÄvl\+§ÔŽü¤ŠČ @Üs„RĹüŮÝDž…yššœdö ć@O ¤Úd%ĎöčŕĄâŘGł™vű^Á˛C‡ÓŮłgY@Ŕ~Ă{}ś`Ş5ŽG+ĄŠP5ÎCS•á˘%•160óԗgÖ}ŕ7ʧ‚í ŚHÚu‹Ť á`˙ĐdÁű‰q×˙r¤ }Eňz­×z­×’öx˜*Vœv ÎĹŻwŇH=‘É4‹QŸ°†g‚A ”•• Ś*O=˜wŸˇHrLŰ\ĆXTĄgÎr@ʘ›0…šÜ_Ť2+F™+WoŃĺ+7hrň.-.,0PłĽŒjŞŚÇÎĎĽđ^rÉK< łćIŠCŁ•M¨WhĘ3*Ů ŽD&‰Œ›p`˜@eÖ¨uNŇS›ˇi3룍R>¨Ÿ ŰGhĆîsÓY™śĘ5Ú*U‘tĂú'âźŔ@Ú̍ ʏ=6ieŰMšíâğů*ríĺ80i/Ź:<ËéȁAšœ^ákWˆ†y‡]Ž[î&~|ĽŔXss÷ů;8ňCE¤S.փ•p<ś6zbđľÁ Ă€lô:ě Şós3źÎАTë ”űhEJÎ}úiéH†DS¤Â'¨ÄهČTáŹTŒLqe  ™ŒY;Đ_ÁžEäVŒţ܃Xў´¤˘˝Á˜ě*4MŠR żkiC˝ž0€–—tˆŤvŠ Ŕź¸Šeđă…gĎť}rœ Ż0ç¨ÂŐZb=M/ÔăUÖDŻšę {Žąď´š˜öłŰˇoә3gxÜŘX_ĽÍŐ5ęľ^ëľ^ű*śÇ–ţĂ Ľj[L)Žx#ˆ˜9"ó˘M&#JEëŮ(.bśšM+k €@effÁ{b ą‚źŻš#F†ĄŞMîá =¨ÜƒRË58×bd-ÖBšqóÝž{ŸŚîÝáœUŽĚp°1Š"%ň$/YA”G-2ŢOSÄŕPăŁÄNvĆ9šœBÁ ŃĽ(ÓÂzÍ,Ž1Ôh ń2¸eŘu87ŠŐÉ˝6V艵Ű4Ž€Ű÷ĎkgiŽ6F×?†ČÔq†÷ze€šîďRÂüÉRÇÜHő "‰ w­,ĄÁş‹(äł´˛éŽaŽÜÁ "ŻěGÎÄśĘÔŮ^Ľ“GĆéÖäźZ˜‘éBj,HąŐŢ攎TfR2tlě‹ĘBЗŤŘd>şć™!”2Odűü;hb¨Ńš:˙ú9÷@W+@_€Ăŕ <͋Fő Őö2 ń1_žX@ Ąšs:Ďć0ʐÂ4Đą[e#ËÄD:łI†K|׃RŻŐy}€;`ä †žŁ}—â•/ćB“éKá9QcŮÓ̙ĆĎŃ%aш`ĺH`ÚÜY^Z¤ÁĄ!Ž@•™„C âPźŚDT¤˛[OÝśÔk˝Ök_DscĂČ8UŸţYç´l9Ŕ˝ýöߒucĎtŠNŤ•:qŠÓ;”şŻ•<ŕ(ASE˟ęK#Ńp‚@˙—TJqĘŕ`ieuŕĐŕ$ž:uŠŢ{ď=Ţš>űpčádcŽŽv]R=btÚâČŠs‹ů'ŤřĘy`Ů txü€c&Őű ä%cstJçýUéKKVX5Á&aC*ű¨"lE đA“€ĹZţŮď„Ç8)ÔĄQQŕě„Yčeż^ŢɃ>^K=n˝ŚZÍ/łT°?0˙ňdĐĽ˘śŽ€ú–ăY0Œlkßţ}Ô­×Ru˘ƒsgFHîç /ëî'łO|ęöRöšp™hEľE˝7%ŻB¤ŔŸ#|CšÚœuąO$V–é&DПőfź8qQů“Ř!ţŚŔ.Rćgay˘"EŠ~P˙8„ Čě÷ęcڊ°U`Ói°I* –B9baʈ}Q.ˇÝ_ }¸›…˘A!í#rm°ˇLXFî1*ţŕŇđAŞĽ€÷ ş0*ĺ4•Ď;3š77šá7ˇęŤ`9­„1Au™đö Ű)>;Ŕč~•árőęU:}ú4/×ôŠw_…Ö ”őZŻ}–f_Ą×öV{Œ  ń.ƒŽŸÍ‚ľD]Ž›”řă}‹—×8ýćŢԌCçW”é°1‘ű€>÷Ô öCCu:tpœ†ěôBđVŮ[ÎŘşsošŢűŕ*MMMŃŇü,-ŻŹşm.°Đ§ŚY0ĹSË>š,DĆD‘˛…ą˛*¤”Bž8żŚ”ÄńVƒ1QC[cßx;ĐOÝjŇĘŇ 8ŹŢG‡6fčĚÖ}jŘmşŰ7A7Ťč­Ń'ňsŞ Š)EŞ2˙“@ ůÁ0}XŻ3S˘ĘŠŮqŽ÷ć4mláó 8€fŹt“V7;´ t…šulŰíÓĐ̒6g¨^vËś+bŒZQđX‚2ËBÉčĆ;ô‘aÚwVâô ¤â ?,šsÇ=ćŠB’oą• zO/ĆýHľXŘěňš41ňc|nľI€ĄˇËö‰÷…ílom8€a÷ U|¸ú@Ÿ”ťĺ ,}ĄŁ9d˝!ˆvw}ŐP °ÄŽ A<7HKZ^šfƒˆŻ˝Vű˝Ä}Řäüüž3o÷p•^ëľ/Śđś•:e} ™8HSY-ÎÍŃžjF7‰fŻŃʑł4rę< ŒěŁív‡)M ˘Z xŚáô€–1Ž&)`4 ÇK?+•ăɓO>Io˝őVp’"X cNŤe¸˛´˛ÎsŰ ×Ö˝ó™Ć3EYؒl`ŃaŰ\qt9ϗY˛%ﰋv—:Š!‡ăńNn˙sIËä k$ë›ĚÄT Ż—•ŚůpJЎ–"DÔT çäAŸŽgűčőP†P Ś Ĺˆ~QMŢƒj YĎBQö‹Îq8ć<ʎ) â^¨(zbĹÁŘ$A ŘJ›k\[ÁZ`ëVX+KU7÷őUʞ‰aÂ< ˘Á!՘ŔIŃ1ˆ:p”„g"Ž|˝éň1Ś,á|ô‚‡-S˛ž ŹŚ¸Ăd 6Ôčxą\íO˘G&L­*3T*°+Q*ݨ7řzŤžŚÝ ¸Ň'Uv(2QÔ& •ƒ^3[ľW[ϖŇJBœzĺž5MÇЁ÷(÷ŹĎű~ŸĆ„1AŮk)؇”!-—Œż/Ž ďBŸIďƒ>Ÿ¸ ś(`ƒýâwTFPܤ>Ëq1`Ű^qwoŚ˙h?IÁčTëľ^űÄŚ2Ţ&/•(-WŢk_ţö˜ŇdŔiů[œő ĽůĂŹ˛ Jâ:§őĚÎ-Ńԃ9ŽÜ#Jă9;™ˆ(h4ŁŻ’Ńčč 98ÁL€œóíŁHŘÖ卡éęľ;tíʇŹĚŽRČ`¤HšŽwź‘ž“•%KRzL ”#EŞĎ””™R Ľ\T*H)ą°Ş.Sńůş0„‡‡úč”YŁá7> ĺíŒ>Z¤+őýtuüeĄňş}än;mĽü&IćśÉÚ‰Ącóˆ kʍŐH—ƇҿŮá …V×7i=;D#î˜ú'iyÓM F,ś%ŕ˘ö†‹zôľŠ‘mĐ伋j´‰Ťíŕ5Vëˇ^)ŘÚ #Q:wě9‹°šk1Únj•Ő•%6‡¸zŽŠĘ*ý;°YԸΣĄd4Äc2Č$†¸IťbŒTľ[Ű,f‹sknŁzč Œ1kHKJnż‚wš"UŐkŁ'ŮmŚ7ýÄ@n|‚˝Ýr‘¤ć=qţ$=sé”ÜœŃkœźé^mşvkŽŚçV¸Œń†ť1pfЗ…Î[ĽFƒĆĆ&tg¤š â$¤¨yf `ŤŤKin8C ›Â9ů3 ŠAI„F#š˝Ök˝öůˆx^šr…Dž~ň0UÜĂş}ě őWűhc~†Ö^˙+7'Ž=OŁçŸŚ–sä ,ťäÇuňš)ZâÎR0çŔé ŔSĐÔ¨SđEEkôţŇÜěL`Ňé˛ Âȸ.s 3f–W#†ń¨ÎN:QÂz#q†slËĘř3 ˝0ë|ŠP;€Ô>E¤”śŠ8͑ÁăźéđąIéWIQë€1y†#ëw€âz6j˝ˇ‹ůŠíŤ1 "1p ,AĎĐP[ç¤l:bvŽ__ÁvŤA\§ >,Ǖű 4tJŢĄU‡Mć%RqZ˘ %“\ŕ"b69vňĚ -çhË˝†–˜yRĘBŔC9›é@2ňóŞ_82‹“T\0e#XQK@Ď̀ –˛yŠ=§,çŘHl űLUЁý$Á úŻ°Ëľ†]vúÔI˛áşppÍ*°ŐĐÇú| 4ÍĘ&ŔŽ Ň™#KŠÓŞQ¸śD)LĄ^;Č üÂVp@DŮ Ę>ĂóŤÚ&x΢P‘Ô,w°œ2Ôđť~ƒía\Ŕw8TsEËŻƒƒ}ÜÁ1ŕýG}Ä6$ś1JK.cý­Maż=śhíclúĚ ô3ŘÔłzíó5Ă`ĺÚÚz`–öڗż=>ĄZ¨"ig—Ł!'ŃÍá#ôÖÇ."ĐB´dƒV—–ŮáÓŁÄ‘J FhěG&őčÄ+ ˘‘>ĽEëĹ×(ŽP•œĐdpćfP38äő ôܓ’śgLôZŻ}Q ĎÓőë×yě:qâD¨ŞÁĺL݈mŐćÇiřwţ!,s×/Óü˙˜ěĆ 5=A‡.>KËyĆă$4›Ŕ\› UCŕX‰‚H5tX+ka!up°4"ţâ‹/ŇŃŁÇč?ü!Ýźy“Ş>ÂDÉőřŁÎÄĘJ›+ďaŽtcŞ)č,i.ś\p•´LAąтŮ`-Rž…9ÂrU¤Œ§eĽ9ĺŃkĂDŕ ,DAŔśœ”]V°@ŔÄĺÎDď#Ó xéýńθžŹĺÚŚ¨cÁćČňTP$ÓÔnžbO) ŕT'—J/miüüě6١:w8wft,QWŕ@Ďqssۧćů^Ŕ—žäZřšˆĎ ‚-yffLÇ ÷IŢđŤ”ĹŇŘşż,“ëŠË*˘ýĂ*"Âńúí꼩דŇ%Ňŕ@ṉې2ÉÝ×!ݒŸŕ ŁÎÝč˙‡vυ”–žn óş:>jâ|aŰI?pvĽłt™ś%şgÉĽNyč‡&Ţ_ŒßůÎwč™gžŚű÷ďӍ7 Ĺs|ŕŔŢ˙ńăÇůyšsçî1@<ĂLp  W1[€ŘWëqë@ŻEĹŽऌ•ŒŮßCüăŽű¸té݃t)-ÍŹéB{­Ůä™ő<˝ÖkŸżanDć*ĚÂ7S÷^űňśÇ([bJ.&y\‹KŤ´ź˘@Ę"ƒ*Y&‘-ďˆ&E2ÎÝ>~tżĐkl “%ßZ§ÉŠş|í6]š|…îÝš%ĺâźC V„oŹ(;%Í6^7%+E}Míáýy@„Óxřs)äkjOLýÉ"kEżOA™rbˇ‹Ňľg*ŹońÖÇKî˜nňk°žÇâƒX‚ŠbŒ×(‰”TšV*4&4ĺŽŘYďÄô™H™–c;6Xy匯ŇýÜwtd˘Bƒ9Ý˝he&Ć÷{íMO)ŃňVĘ.4ToqeĽŚ›`=™ˆqęP4ˆa˜ËEGńA€)˜ŔÖ֖Ŕ2ď".ƒŹKÂƁjŸ(gcŁŒŇ2YĂgsƒ…qŃPŮUy ˆ*„ţ<Ŕ„}ąƒ°ć¤ĺĺEfÎ@Ü5e¤ˆ#wJ5OA ÎÁ6ăűbć”:˝ôÔaşt~żsTĐp.şÚŢb͝}ăƒ<Đjĺ(aNŠ™ę é*ýáß{†ţŕűOłČđ‡WĐ˙úcš]XslDiŰÉuľ…”%ąălÁH×(!ţëŻ7\$ł_¨ůkÎYsT¨űÔ­Uą×zí‹nxŚÎŸ?ďĆž!vv~ )(€!Ҝ5‘Ö9şU;Hż˙żŁ’[÷›óćßü[˘•9jď;Föřyf8bśœƒĹz îYF„óŚ2UÔYTÇiˆPÑĂŘqęäIş?5ĹÁMŠ$ÂA ŒÇÂC¤bzƒ8é¨Ô\XŚ…Ĺޞ‡ę4ľ>ŠäfŐ_ě—x-jőëĄń6śś éřôM ŕƏżžž""ˇU­R°M…Q­lƒPq¨”€:>Ȁ)!ŕľIX9ݎľţe§smîÓ0'•D Cƒ< ˛hôÔ𻦋đśźĂ†-ĂFRŕÄď(I%ÉĂśp.ĐQa@…R…ăČ´˛şÂsGٟ„nž…yVƒI"қ‘ŚJĽ ‘nđĂqL UŠ(€lđŠqäą~Ŕ kmŇWâžŇ἞˜Âů…~“,ß  Ÿô˜Ł.MĘ2Î~ Ľť˝~0 +ľ¤×śc‡…mĽ‚ža’×ěä;îK´âqÚ䝱ŢnĘě8tř?‡čđěüŔř0ôîÝťĚH¸   Ry°ŒVüQ=‰đlK`ŠÎ ú Äf•á‚ç}LŤáwŒ9Ř×ŃŁGxű űÁś5 ăœCӍH~‰›Ž¸›{€JŻ}э+ˆšgX˞÷ҁžÜíą€*âčćyB•žŰ÷fÜ=Í̕rY&x°R °ÄâŻČů¤CƨŢ_óibt 2ż˛˛J÷&§éíw?˘ťwnÓěôý TŤĆ@Éç­)›!SGZAľQ˛D+%ŐEIÓy˘ ^Â@ i=^SĽœÁ•,V¸bÂú•>_şĎMČO]đŕő÷ćhym‹yź˘˛0?Kn˛Ť”ű„)aäÜ´t.šFER'ZR@l!ڕŁâ@&šęmϤP–X2šŻXÓ°´°ćPÔ̓4:q˜Ťł´ěŔ–mTD"Ÿ$ĆĄť“´¸éöłiœáL4>˜ą8đúVN›M7)qtŻ˘pzüiNj§ăżÇ=0Ž`ŰpîfšRDOĘžŒc,oŒžBŃD‘ŞcXĎ'm…í#€’4Gž(0|4‡]ň‡Çř7ˆÚ2{ƒéôƒnżĺPqB6V–łXz&°‚r&ŞôĘ7¸k䀧M‡N7ĽĎąđ¤RŁ\­¨IyŢČJyUĄÂ3üÄĚ ăúQĽ/ŁŻ=”^~îM>XĄýíeY–WśX€P€-Cz†vUűO#œ çîŸ?”őUîͲVKŁ1Ŕ÷ çŸwUłčľ^ëľ_˝!âŒ4HN‹qNX*\ŘGźĺ÷6?{*^šäćAŽPď?Dľă§hÓ9?+ÓS´yý=ĘçîÓĚŕ8•¤ p€ř–Ű֌‹.g~OáœÁŃBØ ‚Tse` A ćÝ{ Zะ ؖ@DŹ]R ĽAźP’óĎęn†Đ@ƒP8|q\¨ö"’ €%o˜Óöă?Ň}0fÁI”hy™Vƒ¨ŹĚPĚ˜ßM´Î0t•J’B| 0QdřÔŇďňbYĺś/3Ź 8ěš~ě<€%Ęé°FZ'IńÁœŽĆ5ł>U×sd[ҝŕČŚĽ“̈z4QLL [Á§ó˜b%ŸP­GőQ’´# –$)< ¤ŔđŞxڊ-Y(7˜%`ОYŇĎÂT)3ĐŠ- &çᏍV¨ż{ ŻŇĘúvpz!:Šę@pn—׸ łyXÜĎłzl„łŘ!ѕŃ“ŁŚ aŰ!ŔDŔő˜œćČ|ńA>M‹+–V+Gh¸ßEȪ󴲁ŠMŽDĘĐđ†´Xf˜ŠŇrŰvĂ9ăuAmśÝ¤˝Ů’葨‹đńśÝ†ÚŢŕ´ÁÁ @•MřĚ:pZ5`ď :ÓÖÝqJYć^MA3š~[œ×î€TěĄhhuGĎřČźŽKWŤŽ9Ceœˇłś˛čŸÜS=ˆÍ 9Ϣ‘hjBS7%jÔ Ř眚¨0Pöém˛ú¨ňX4xˆ1לт/§ˆĄŻĄ§08„ˆ–7ňIn8îőуƒôŸ˙“—čÖÝEúéŤ×čĂŤhiYJ‚Sá<Ľ)˜ž7žŸ iQzUJGkjœŞĄÁ!w,}$Ú˝Ök˝öy@°9ŕä ę‹gQĹŁ5Aœ–M UçżÁŠQ‘ŮáCG)w ŇJ›ëd'ŻQó·ô`x•ĆqÚOćć“őEçA3ĘÚŇŔĂX€gÔ~œşo|ýëüý]Źh ilžľužcëő*łđx^őN:Zj#ʈ5Žŕˇá¨5Yú|ŞoĘđH;ź­Išg€nj„˛0§Ű^˝V óúâŇ OÔâšB٨%Ď:ĐĎ`Šň|áŮ/yŢ Á żw~äqź%¸qZ0ŘĆXŻŐ]×s×ÔŘíöÎű.sv5ÂŔFÁ‚> ˘Œ[˝. rőqŮk_r:¤čČę¸Ć•p/Îů–ᯋà†˛%đO`ťîdäÄëŸŤ˙BÉý&˛Č‚^č& ŰNŔ“˘$÷œ(ÁTvřĹuÓmďœç(aýÄ{ÂgŕţŚ,¤˝v:"('éË6lDqĚSŚŤ:>fX yÂdĽD f—cJAˇÖć^cîEj@<ó*.‹g@5UT„ZÇ0YđÜâůđĘş|ĂM ŤtűĆŚőjÔ#RucŽt  ÄĎQtVŁUY˘dôˆ)YHëŮMER‚0Ś´SoĽT#Bş(Š[UÔ9äĽĘ-Żn8°hŽÝ^pNđŹ3˜›¤TÜ’”h€ …emuŮ-ˇÎÎn%Ż ŰJĄ´ąŕ)ʎů•y`\‚Ş  ś—†ş┊ĆLŁÖ=ZXÁľ:Dƒýîx˛yZo"źĹ l”ŽNDürF´-ŃÂZŰ˝„­PŠVqFĂPA4č㠂łć€€-ń>V<…˜8 ˆ”–mă"˛<Ű[ë\ÉçŔU ú„Ác8Ş(?—Ż.•‚`ĘBAZF€ő:ĂŚ{ ÇÉ÷Ź\ e°Ťč8tŒSuäű m;PAŘBÂźiw„ö ‡‘Ő-gp°.B)gGŕνug0 ńq–=€Ç†˝ű šütuÁSĺë¸čwĎ *ő3’-Ń%ŸÓmÄ&üĂ+ťm99FǏžD÷Ë[ôÖ{wéňő.gΧkՁI(Ô̊<‰šZď =ŠÚç…ý9ďŞoŻőÚĚ&eLˇmă˘ĆúěqJ+X„}}ěXi žEЇń˝FŚąNĽęŔ 8ˆăűy<ŤnmŇćĺˇhőĆ;´ŮĽĄG¨16A뭜–ÖW܃]gv@8qŘ&Şa›Ř˙ůsçieyՁK ˜,ă%˜(R5­ĆyQâ0Çs؏q}Ő,ŤHercw˨rŔ€lHÓľ6Š’ę …ń°îőś8%ʝóJy™Ók*nœĹœ€cŮp炔c0l,„ą¸íu x nľ=€b˝vZL˙Ŕ ˆçŔGNjďó_Q6HěŐQÖď'‰ lş­%˘I+ş–Ż(ŻYÎiŔ0pŔ‰b @ĆjœóęęƒňŹR€+lϨŔjúďĹ_błŤaŸr@ä÷,čÜěćDpc§Ń |ě „<˘uƒ4ť­“~—ďę¤ŔJŞpšT•X5Ç ËT¨jOęڝQ•ČPń´˜ä*˛hl@ÔžŒrÎ(S|ęÔI9đÂÜŻ•wđ|âČĄ‰ę٤içΝăĎxpD+… Á_"Gđźá˝ŠńběA†N ţ"­űÖÔC=čó8FÝq`€‹zdŮ#š›zOzţmŻĄ=j\R{Z˙jű´ŕˆ2{€Ę—ť=PƒŽ”tŽC°LMŃJžńŇE‡ˆJî´sú``-,,ŇüÜݝ|@÷§fčÁômsJ‡LBZ ä䕇 1ŕÄ{é[R†UŮ&Ş“‚g?scWĺ T{úëTvŔüÖô=ĘŻźK+n@†nßĐÍLާúž#tâäiĘ…÷Ž=œł§ž~Š6Ý~Qjy}Í7Ü(”sÚ#Ęg,ßnÉ8ƒţ- ßg97&qö1ć`ţ‹ó*Î l˝>/–™yćiœ°4•Cćy”sĆ çgL-*™PŮÎc˜Ý‚Ô&T|œ-ÚöZ^efĆú÷劀ójG$"ˇ‘Ĺ)óZŰ?ăiéénúś:fú^˙jE%€}R„˜íĐɃ;M°+†QĄ, šr…ţƒm‚mŕ ö‰ +¤Î=Q4úełY“ڈ‚<Y.2<ĺlÓ*a`ł`L’*zí͒ʽöŐlœ7IŞy}şuÔ•’ăUI5}DłöӁɽö›Ý ¨‚ˆв€q'Lšš%gĽ,ëR$§\–ż%/<…fË]@IL˛T€Ö§ű”ĐF1ŤţFƒchôUűiqĽIÓs›4ˇ0M×o-Е›łî¸ŁŘ.šIŒ™Î-‰äG44$"ŒĄ` ¨ÍĄŁ ¸Ţ/é\9Ç;ĎŞćŸ%•sÄP(EĹJŠLj4Č؉3ňťž"˝źśĚZ)ƒ0ŇRrŔ@۰ čč á :fŃXn0!7[ŰA5ßřˆÝŇĘŸJ3—Ë[lLJIc*ˆňŞqŠĆŒ P˝Y…žK!ű{ŤĆ°[ýMŽ;Ś?QL˜ Ń9f!U’JÜá4j)9í¤ĆUťĂý™Üůoˇ6Y“F#[HEu÷b€42i˛mf×Ü0ĂűđÓ×§ ŠťoMŃŔ÷0ň[m¤hľ‘źÎ,–áů%ŸĄ‰ńQfzŐ!^S.{˝Ą.Ú´<04ŘčŁo˝tŠnܙ§őNԠўÖćHk+X§â ´}ţľ‹@Őëţz'Ű&ŠÎj¸.ˆţĹ_ü€óÇ_~ůe60?řŕCz≠.ňwv×ő`lţٟýýáţAĹśaź}ű;v”ŠŃČKż~ýđč‡/žř}°"ýF+R/<ŔTîÔ)Đ{ ŔńwŢĽď˙wĂ3Ĺ[0;žčň›×tĂł žŮ îłR‚ƒx)Q`O*‹DJ}„m éxŠż€ęl: ¤6@ĺăhs˙ ÚZ˜ŁÎÔ5Xz@'ű]˙-ľŠz˙m#ZđYÚ\osyÜS§NJ׏9ÔÄźŽ—*ˆÍú+žŇç#ę:W*°–úëŹ)á5J ŸRR€Ĺ“ )łšĆ o‡D)Tpy|sç ć+p4ĄÉ†cŰôU‚ZÍf¨€”e­*ŒóaŠĹ>5)$0 Ń (zŇšJç—¤˜t ?kŠŚŚĽt˜šÍűd wý&Ć'8Íu×g× Łsyy…ŻţĐĐ`´RÖ§ŽYEÂ8BmęüÇ]Aه'ڰ CE›@ď“Ú#ÍŚw˛VŇďă1÷­Ď ů†mRx#˙xV‘•(Ľĺ­CĹEŠ ŠI`DŢV*…ŁňĎ)Ößż훘i5xÖÁDÁ_(Ľ|x“çH÷€˘ZGŞ—˘Š|XËiécü\eśáyX÷ 5ĚwĘ~Á3„y‡őŢ<ƒEÄ ›AsE5XTäĚăö–)^î^ëľ/q˜‚TZ<ęWŔƗššó‰ëŤř;@î˝XŤ×Šíą€*˜P ŽJV)˝˛ŰwŢ˝ĚiËËK´ź8Ď"Š0$JŹŘ…ÔP'YŁYň7-}lDéžŐŇÇéçîžÂçlGJF߄.)lÍ1ĹC׹=˜Ý Šé%ç OŃ­ÉeZXÚ • śh¸IYÇÉ,+ÂĽn"ł>"ˆHšË,882ĆÇČŹďs|U#až ޘhŒjcnë2pŒ ‚ŽGiŠ9Ź“Ű6-ŻŻşß˜eҗUi CĂET[îX:rŹr|‚Ŕ=@$NŤĹÓpŔç]ţr_Hœ Dë ,^KGNˆCÔ–Áśˆ=BĎŚT<\űŸhÝWS٤LOü>ůJsWB ßĎX„Ů}F՜˘€Őąí lk{k“_}läôQłSĄÍʟúJÎq˘/Űlu˜9{}Ű9;•С¤o‚ \ŤW92†Á}•łW=ÂÚC(ť ƒŞTö ˘7žő:ÂI9|pH„ă<‡’ÍʄBŸČ} Ł Ńú‹ŰuŻÉ÷8÷š[ŽómţßţŰ˙žvQy0>^}őôŁý%&P˙żrĺ*_ ””Ä}zó͡řú˙ˇ˙íżĽż÷÷ţMOߥk׎zŁľJŻ˝öK`ř޸q“—Çoďźó(Ÿ{íÚ5ŢöłĎ>Ë Žă…s\y šńgffŚé›ßüŚť˙KŹ9B'Ož¤żüË3hŠöűďčŽýizűíˇ]üâĹ' 3ĹpÜ˙'Žsž~/Oü7Ť)Sc˝‚+ĘRIÓŇĎęhÁůQ:~ĘfJĹź…5'Ď2œ"M-tóÇČńß屇0~.8Đwúś[~…Z›ëTŢZŁĘŔ0Ń誗kôěSOŇňŇ2ÍĚΐ'Q’Ůá$ď8çuKĄGŇFDą˘ €ŃnlĆłŞ}VhhZýýËěŕŕ–X° ĆaŚľcŕÍ=+xÖńs•śSđýűB5,‡íBSE™2 ŘLŐmÔYĂŽŸ?ăx°M|kßőí!ĄÚOÓvc|žŔ…ý €cŻýúž=yś:üŒ¨Ć‘dWlsßPŸ<ş[‡Çćöu˜ěľ˝ŰËÝUCCć#ůíV“–ŘÉćř :çƒ÷ ¨j‚íęŹE–J˘•’*}“rLÉ)+ ĽÜ ˘D&ëUĘÝiB‰" ÂC&efᴗhznîLÎĐýéşzc†—[n{O}ö`†ŸH1hjdKŒ?šć˘…‚룑-5jkÉgÚ3ýáaşu_7š~M*Rę)F Â)ŘšŸm#ľTÄĐ+™řŮXôtĺâC’ËÝÉ]ÄcƒhŔZąTvŕJŐE_L“׌3t[ÄbąĽj-ţî’Év7ćŇţ Jű $]ĂTfčp9e_IBs{“Ł´¸ZŮAš âľQĘó‰hă@ŔYćĹěüu#ňÚ4uňЎž‚D„Ýľ ɡ¸‚ď۝*ŐÝßrć r Š{á˝t9ëÓhD§­U˜ QÇZm›őQŕ $9ôYBÇ,)֕ńU”4ÝŘlŃÝÉ9ZpŃčŐľmv@Ԛ¸‡k‚č§Ľ)ՙLqr/DߏĽ˝FU´>ň¨QşŸ˙üç F Ž×ĎţŞMfźĂ#yíYΟ?&Î˙ńüłÎľk×]T˙T¸Nú’>Őäë‰~ń?˙ĎĚ5"!x†~úÓżfÚGwďŢĄ'žx‚÷ Cűťwo’Á” pňGôčż˙ď˙_ôOţÉ?ćţůĆŻÓďüÎoÓ˙ńŸĐ÷ž÷=6”ápßťwĎďƍ̐§Şüf5@Đ?ഄ´É, s…ŠK‡NřDÓůJYşŇĂ´˙Ąż€őś‡Učt>IíýGŠę•l,Ĺ^^¤ÎĘ2enNž¨őÓš‰AZY\  ( Š‚œâ‹*°Ą)?Ž­Ő’Š3%ϲÓT;çĂv8|mœ‘ŰôLœ˛ŸÓяE\>ÎŮşź€;ÍřŒýŒ2‰çl°e›ŰÂVÁsśŕ€Kh˝l90§ĹĎŹJžľŠăŁ–vĆř–ĄÎŐÝ)z"T[.0ŮBО×ĆJ]nŒ 0čá¨ÂÁEil§ďshX[ß`Ń`Œ[˜3v_Ň>îYĘXŮľĹů 8‰ŹŃŰO?Çíě˛uó¨ß‹ ”MßۮﻎEŘ0q3EvHŹŰĺ|X$Ř\â6Ł‚M§“ď¸&íĺéľL@î9SżSű }ůŘŃŁ ” ÓJt–Č@ŸBżP&[ĘXł†~‚eaű`9u`Qs–ŃĘZřŒ9Ąĺ˘%•ëő˜>†9Ǣ,\0– _ِîÇóUk˜÷ß˙v<ýô“˜‚ 0˜­Ý̄O –@Čű‡?üýÁü§ňÜű>ŘýŒuo+őp?ëcśuSźŮلmźÂść‹z=VR°Rîď2ł*Őd^Ś žŐŢĺŢťíą€*­ź$LŽĐ&E„4c˝fĹO5îÄÍŚ3fš›ŒîEDŸüvźŕ¨jĽdQX.­ŘŢˆP-{Ěey}ŠPšŹÄőź‘VFʰ3lFF‡yňËÜk}łCÝ˜Ł›wĺrŔÁňÍ-ŹÓ6haœăŢŚĘŐšsÂy‘Ÿ|so~":•[ap´‚Ąč…g=”N8ž5 Â`jźkŠs8œd™ŕZ>âŮdŹZ­óoƌIK u đů{#"t˘súĹů&0H•AHÉ­TăiľpCÔpK÷WGh Q§ŃĄEZŰl2;ăĄF”-V P'W >ő Ž'é` ň(‹ …1uOѓHĎęʧĄBP]3šœJ~ăšĺ‰VázA“Ç–äœHTźŁ‚ahYŕŔßeˆđ ¸ăČH&ůţ@śË ţ”ËU¨tÜ˧éöŃĄj%çĎĚĆPľÝfËʉnns¤Ú*0◗Wi~a™öM@Ý‘­ş×ł@ ž,ŻlÓű—§šüqÉG†Űžbú•0Ö÷Íhäi_P Ç"â‘EZű^l˜ýŤőŻŘ¨’´ 5ö}äÜݤ:Jĺ–aN-úç˙üŸ…R™čë‡â2ś?řÁ˜ŠăůůçŸuÇóšZî˛AüüóĎší< M5řć7żÎ ™>WĐžy晧y÷Ý÷XŘ,4ěľßܖڇ`üR€[éö ꊌŠöuÜľ"š˛A4ĘĚՁœóĽb”şíŚOÁ‹uZ\Ÿc‡Ęa˛ƒű¨ŠąmÝsxě<;Ö Egc~쌭ś I&JżŰi¸c)vöÜßfˍMŰ-?×ĹšťŰ‘×kŁß1ÝŢćą›.öJ)°ý*žń‡ßs[tŚĽĚ}ĆéBZل‰-F)B-AŔŽ%Ř `Í`Ž [Ż[ť]-}4­Ď&Au˛äw‚ÍÁđS˛|Ëł ŕ\{.ťĂÇé€ÁˆĘˆ8J‹âýś‹M˛Ó!Kż×š5˝SaŠHöký~ ˇ;šď;׉;-žI4˝¤`OŇľŸŽ,iĺ:]/ˆÂvýŰKT˘*¤Őűl׎ lżÓ­X*~—žlŠ%¨(öמ}ôňË/q?–řĎE-X?ŽE—7ƒĆ ú(úwô#úť‚†  (ăIu–”ŃaY”b¸Š ö‡íęřƒšĎ)€~ź°?ŠĹúŘÎ  =§Ŕš.\+ˇČg[%ÚĺËWy|ŘzăĆ-Néýđϙ)Š9×c˛2zôj&e>踇öÁĐ[o˝ÍöĹɓ'źÓnĂ܀Ś}PRľk~^m7ŒK?řÁéűßK˛=Ńö•ʰŢ+X˙ƒĺŞ˝ KÚT(K\ßÝëfşg s3ց–ŕw<‹˜ozl•˝Ű˝˝;—šAĄD}%KŁÄ"š™§[cC l 9ĘlÔľ[uϸh Œ¨—g´4rśKĘN)”3.—$‰ú' žxP%+™<ŮYąGKˍŒ žÝqŃĺVN—o.Ńľ›ó´´˛F3s ڤĆœýJʁçjcĐkŔ—2nŠVHf„ý 弳ÄđęŁ( ŰĹđM€ŃҐHdźŢ\ŚěS‘:m_9+›Źőútfłâ`#XaľL5)XĽ“KÔçF ä}š—° |ĺţ΁MëŽŔ8° ż6BŁUN ÚÜÎů/rö¸Ńň…|›˝î ăŞD ҅łűix°ß]˙şâ^Ěbž‡olLbbŔ¨ĚU Ş]”Ć5Ży2ß D<}IĐŹ”%̖ŒY1ńú&ĆžhäÁRĐƒCÖřJ}áü°/0° D5 l›Ű2—ôl!2m:\śšŻě&\ƒ˛Ôn˝6hô-Ú6Đ1XeËÚú§­­mŃҲü‡œˇY*Ą*‘ĽůĽ-wčÎ䒻~(ĂéÓ°<Űévö ˝SőŹ!Ŕ99QČî€O;h5!;6J–ó‹_źĆŒâw¤í "üĚ3Oq˙řřă9R…kąb||‚^{íüŞ/lmÝd-¤ŕ`°^ŔlůÉOţŠ (oźń;FĐBAç¨ęŁęcœôˇű36Ę.\¸ŕŔœ[üŽ“}‰S†xb/y@Ńj­č"ŒŕŸýL˜7ĐxĄ=—źľ7ZQóIšÝ źł0yš˜O :§BĘ žşßîĄß ŸŔȏ"ć­°m4,‹e0>`yeBŸŤ\ią3f‡÷Q60ćĆđ*•fčéţę›^¤wßű@ć ޒ2 lâ;ëXř0ƒĺ1ó+蒟§$Qŕ­;ĽĆ&*‚xé>Ę]éş:ŻWʢÍâĽfűƒÄڍşůŘ;:âzX‘Ô‹V§Ĺ3‡ÔĄŐľŐđ˝‚, @GVJ€ŹĚkĽHŽžV$”kÎŰĆýpăШ{ţÁ$Ô@†žˇ‚8ßššy>×~f*î’dwŽŢ` ¸tbK˜đǤ߇ŕ…Řlaą”én œ˜Ý˜H]X܎÷؅U­ž+oLő‰hJTé~OA“‚ý´ ˜Ź'(*…C €‰)[ř&§Ž¤ËŔ–săőé3§¸€NRĐŕŘĄßŔ†Ŕ|€ý×góŢcŒ—(¸á÷X}_ËŽă;ŐţÁ:aŽ\šâćƒc ÜŕX˛č\ښMÚg1Ÿč˜ƒyQO­@ĆŹ7×ýśÖ ˇM_•†Š¤° Ξ=¤ô"}÷ĎţěĎé?űĎţ7ôďţÝŕ’×SSStôčśpďÜšËiƨř›Cmwß}Ÿ~ď÷žĎó>–ƒ Ćˆ‡@Œöü}đ`šv°Ž^xáyzűíw˜ľúă˙ýĂř̲˝zőƒ'i†Œ{‡†{yńâ…ĐWz-˛qOuM”i¤›ĄŘÝ´Š_TŮťíąÜŮéőŮśL]ÝrŃ!8°ÎaÜ7ěţf-N] ˇ‘ŽŞi/•źĘ;ľš”Ü%CIîřNPEŇx˛bZ"VY|ßÍHÉ|d ÎĚĐđ 9´Ľ!ˇ›OÝŚˇ>¸M“–Y8tmŁĺ€”Max#BóŹsfkŽPÖ €0FŔŠh¸‰Ż"F§$ąŃÂ}˛5#l‡NŮ)8FŰńľ1!rĹšŮ~95Zt¨€ 6ř›÷u8f}}…5H4ˇÖ~0,47XA4(MŻĹkÔçŽŐ`8Úć0üĺJE>BDoÉ­ŰÚ ×¨Úq†%Bĺ“KŮ ň”;6ËŹ!D,7ś-§ö ÔéäŃ1zâĚkpúË`ŁJcŁ"ĐúŇłÇia Žëô‹ˇnŃWîÓöVŤ`0é@¨.Ýľ5ˆ˛­ňőŮđ ĘTTkĽôě$íĚúűěou´ţ|c~9™˝Sę>.–Ău­×$"ʑev`֙Ŕ Ćsłƒ•Ĺčob?űvýß*ĐŠ!Ű$ťśÉN3?čŸĚdiś¸JRŐmŁŐ.ŃäĚ&M3ŕˇÉË}“ˆU?“DŽĹ€_Z\`° ÷”Ľh6űó(…>:čsĚqmFGÇčżúŻţ%S°˙ĹżřçœĘcmtra„¨”J ÄŹô°B:H˙ĺůýcbbœŽ?ćÓ˛JźĚŮłgŘÂo0d!<ŰdŕľĹŒ˜ôţ!ĆX†Óž}űŃľŸu8ÓXoiéYŃXr€¨Řý_˙Ÿ˝€aÍ˝˙WtćĚ)ú/ţ‹ęÖŰOŻźň=žěI[÷ŃvŠFöKz˙ oĘ*ĐŚ•5”şß$ľŁ˘ĎX&5ř´Jţ Ťb…űڑ#G ŰՊAř])âڿѯԁŇT.óĘĺyëěĚm MŚ>HĂ'éĹă9Ýš{…älŇdßlřĽČTĐĘrŢAľ".K,¸ŰƒÜdĄ$ŻC÷Ô pŞĆŞŽk“4Ő&ÚĽ PĎ"ş¤üőQ79Ý&ŘŞ#°¸W`(بůÂZ^tLR ŚÝá´\gcZŕPńuëĎMm‘Ě@6ăďĆĆǤÝuœőŃć9wÝq”§2/Xî]xYĎ깄Ղ°“™’V˙ÁGĎŹ!ĹNäÔmź›XĆ&ŕˆ^;J–/ĚP ŕDw_I8˘"’˛Eëd˜Bť˛DŠ€ŔŤT Ɛ‰×OŸ‚]ś“MĄ•ä8őˇ]ú)uÎěË/˝ÄŽ\,W.:Hx&5Őc8>ăůĹüń@ˆ2T”ËalŔ3‹gĎš,Ř€y,ƒmŔšW1\ež¨-ś‰}ăůÇvtÜÁKĹpą*̔ŘXa”Tţ4 úkcÁŔyüřQ7oďăkr—ÇĆy:~űˇżăŢĎч~ÄŔŽ÷­[ˇ9%÷k_{™Ż1–‡Ż€ů˙O˙ôĎ9ŕ‚´_i´Âßéӧܜ>Ëă4ö‹†u>üđCşyó=÷Üłlw`ŹŔŁéÉ8Ř`˛ŕ›ăŽ÷ŕÁýÜ?zx¨ýüQM‹€ÄЧć‘Ű}”ţJŻ}ůŰăŠţSŽ:#oŽZM]s‘yňyÁ.ČC.xNcf“ԝcၭ$ˇZR[RĄQP°P.6÷Ź˘‘Ee˝ĆJú]‚H?ިBĹL0pl772żI_Ÿ˘[÷ÝäÓtŔJ“Ö7ˇyŞ Ć žFáV™ˇ™‰‚Ă(ŔĐĐHĄäâ&—Ó­2厁^62m€'Ve˛h~|î×ôéh(ĺÁ™×źr‰lú`ĽÍ ÉĆú ˘bŽéAl“Ah’€Qá)ËRv2–{Vm”îŮ.ŞĽŁ†^ŤíśŰvQÄ|Ž`0Ńď^ÎpÍéěÉ}tăÎýík7čňő\žW`ÁÖö&—MΘ"Ywç;Ŕ×=˝o`Ť€9Â÷ĂŠœ‡O *’Ÿűk¤Q;î Ţ`TÁÁ ”z$URéX ŃG¸‚„sÔć8˝Hta FÂşé´]ŸŮjÓüŇ6W­â4ϾꯀäÖ]EőˆMÚlf`q XËp™hŽoŠG¤ŮvC@‡Á¤ _׾Ő>Ţ~fĐT¸ZŸGž˛Ś(:2{,¨~÷Ě3Ďđ{Ś Ě’´ĄRCÚŔHIŒmă㤠!jĽßĽ ‘JmĐ~H˙îśM´çŸž˙ÂCZړO^âż0ş`pĂƒţ Ŕ˘K—.öôT~›Śkjޏ+0śqYĆopbÔńŃŇË °Ŕ =" h,Z!đF#KÂyĂ:*†ŠQyŐ\P€FKˇj•ŐwŔ˛ŞąđýďŸţýřýěŽĆC6I'Œhłü-8ňâľÓQ„‰Rón€ä4ü^bś‰ŻňŚŠ ~­je˘HYyňcľ¤—|eŸ˛ˇ#T 7¤ Š0°‰×IÎĎňxŒ ̐đBtœóąeźˆ¤ b>Â=ƒCŽéHĂXÄwĘĚŘbq~ ŠF_•†k„y×` @ €!¸n:E׌Â÷ > n9€n|k˜7nJĺ$NńËé­ˇŢáy÷ ŹR¤a,B)ČX÷ýă/Ŕ0^°OĚ˙v˛,J Aŕ›EűX$ě”ÍĆ=Ś^‹M™†xđ0°$÷i ;Y;[šÚk{ł=ĄZT(pŽ"XĺšŰ4ŘŚ“ÓtČŽÓś3lŚĘ#ôA}”śújČáĄa•Ż”|jĹHƒN°p뾲g™Čd˝›Ŕl–EŔEŮ/"ŒWćŞ=á@"•âÎä2˝ůţ5šš^ăŞDĐI @é$›s5|Ňh÷š‡ŻćÎ՝IdĚ$"ƒ}•*ďƒuW`¨Ż,˛‘WuÇÝj7ŮĐDÄ Š:^™Ż~d3€:rěÚřÚ$lĄ}›1 č-(.?쌄J‰†Űtú„›ž<ÉŐi*ĺœ+ő÷ă `–™h$ÓßŰôó_źíŒČ]8ŠËt“Óţń:MŒ§‹çŇÇ×îÓř‹×éĂŤSnľ ł2XĎßł‚J1„†4 ÜŮMg€,nŹSÝ'Ě(1ŚŔNáű€Os–˘ĚƒÁ–óFŽő€X¸6 >ĺ¤éD\öšŁšmfFmnmĐôôÎźĆ4`!î?œóoK\I}bťUbPÍŹűý[5ޢΠ‘FtmGt`gÍm^CA'ö-gˆ­ś–řú)řGžŻů“ĄÄjďľßŕ†>ă šŮ{_ݛŘӚńZ Uvpŕ)ˆŽc•ŚsÁ!ÂK%ü ĺő×_çô2°¨ÖŠ ~8W`+iޘ~§@TĎÇú1Ć:0€qşoD1ąM8SĹĂ1€őďüýĺ~,ěÂYyÜ;óD‰Žń03!âŻC˝ ,0aĺƒ¨ŽÓöóƒPlôúŞ-é~ů˝#8!Űě`ܙŜýžMš/^Ύg‘`šJÄŹҡ 3Á†‚2cŇT­”@Y-\QÂ9[ˆWWúŠUdVhĂwŤŤë´âĽF=TŐs܈I~C +%ů'…:”Š˘k(ˆn Ě*싯 ^ÓIS­câő-Ü(ň`ě$ĎM~ <…VÔKvŽ Ewj“ ËŰ ’ţ†ÖAśzM<ř”wí7wTë"î7Ţę|´Ÿ)Ťý (8ŕp”5 G)  `ű ŒB€i¤qŕ7<ŤŠ-žU|V€Š€T°Í'Ÿ|’ŸqaEl…ç^Ç,ŁUƒ4 `ŽQ™W äâ;/žŽ´¸ö•ą 4í )6ˇżő­ođg°Pđ€Üӗ^z‘ţőżţżsŔć;ßů61Zž?6°ŽĐppożűÝßfV*ŇvţüĎŔ ˆj2ŠX°–čŐąŠ=¨¨U˙Č ráďţî+ôoţÍ˙ƒ.\8ĎëžĂ=C@ÜëW_}•Y4´ę5yžUGěd0Š֐úĽâďŸÔR]­^ۛÍ|Šď š›lw$őUňݞÁ#Gďů§˙ÉţęąšëTFŢ´hŢh6hłÖ 3 ŘVć˘r`AoË$Ä8cg –Ó¸ ŚU˰x;‹ Ş ˘DC5vĆ#h’TűŃj@ĺ(^ Çu|˙„ ţk[tďţ"˝őÁ4]ż˝Č ˙ĐLÔ;˛ŃŘÝÖ˙ćĆ: Ÿb[`>…ŠîRrŸ6˘iA…foL€ľÚŢŔŔ;<ź7ę GŕÂvƒĚöţŚd™gľäEQŮܢ<úöŤĽĄ%€ë 3[BŤ'1ŔăŁ6eŽl ŰßY˛ą“K°” ä™7,9vdŒžńüI:zxā;`ń¸ ĄVáű(ĽśCđRm˛`”tÜy|ôŃUúţw˙_v Ožß0ňtü†ĄŽßaDĂ1BÄz;hˆfę:\§$%VąĆMPÍĚe\tJ+ÂŤl(đäŮቶVÉéč„3:űxÁ€u28XŁą)%(wYV*\öśFăő…NĘüÂ:]ż9G?~ő=˜Y–ZăTCŘj5ˇŘŃĹž‘ŽSŤ‹şžÍăÄ\*—ýäŸ#2ޙö30• €DqB•é~Z"[yu˛IdYŽ/$ŠĆ_Ş#"ßK ŔuçĂq/1Â=Ŕ ŐőĐăEůáŐŐe?(áĂ RştǗťÖȓ#öWí+łö ˜#/>sœŽv×͗Ϭř#TzĚĹNV聖H śmghÎ/.Ń/ů.—źÚUz­×>gĂ#Ă"š~ƒg ’,#T|82SPy Ž h|Ć:iuMýQ֊ţ…S¤oMűA„ĎşV ŠeämˆTăšÖßąœ8̉ČĎÇ1üńeză͡@ƒŚ€mĘPŔE-ÔĚOšŽ˛›żĘ篊RÇY–(TÇąÂňáŠmĺX^:bŚŕë>Ꞅ8ˆIŘ dv :pjrIq%d‚6ŒÝ&9ďÜ;ţŹIąľćôĆÎ:Ŕ–YvbŰî>×YŰLŤ †”=ˆ"cşIŘéxlşÎCwjƤçŮ5ŚđĘÄô=_ľD„×3‡ŮNČÂąŚŠŃZMPçPžłý{ wzó`H ŹÄ>Ů"vwĐ$Ů@ř^íŮ/š”2Źdů\oÔNtĐFT‹çW#śÂˇżý-NĹł¤:GĹ€T<Óx.‘.Šg ă~S!g°¨ľj)á7°0 R*üxĹ6´ň–ÁňŘŽ+@ěOŮ2:ÁÉW]-݌ń/Œ/ƒĐˇ—çifęŐ+Ż ¨’n;ľËŇçŹŔKśŃ {Ôśťˇ˙i–Ű­÷Ď˙öö‡4Üűۡď08†ÔoŐ$ÂľE߸­ĺË+•Ę#@|Ă Œ wˇ¨ňxڞU^ůÇ˙—WW×7“ ŠëŔ ŇI œj4Q¨ž’çmďœJ¤œ5éŘ>EŤ JŠĽáĄşs˛Ç¸JŒŕUÉ9pđ05]čîäýđoŽŃýš5ˇ~9¨0łĄŇÚrzQĘćzǖÓx-.ůüga#„I:ˇI§/‰3îóę”= V˜pr.TˆäaŸmŸNŁŕ @ 8ŽąęŽO÷ÉH{ϊK„dDXlř"MŞŢđ:~â÷Lƒ ŰE#Ţ(?ĚŠ8ޤ;džú Ąě#bL’sćÄ8˝ä@”SÇ'DĹ €bĂz†lJ8´ńţ' Jj0ĺ!őĘßoźÁŠŘŘŘŚşsJ4Z FSn ýňŰô?ů˜&ď/°¨kŢÉý6MY´jŇÉ8` @ÂÚÚ3H†‡G}T0Č\JM.˘\Ł,-Ľ™űŠRNBnX—ďIĂĐy EJ¸ŢéS%ÖšYtF çόQZŢ85¨ő Rcˇ“ĐšKô Çčmݖj˜¤ďâ =źÇł˛źźHŁCýôG˙yúíŻŸď*˝ÖkŸŁĄŻŢşu“çB85pŹX7ĂSíę3 •&őRŕ  p€ÔńÂ:˜Ă`Qś&~ăj>nŸˆ†Ă‘B ž­z‡ýކŠF=5şš0Zőo…ň'˙ŽŽ\˝œ^ŔKq\ӑ]çŮ,˘aüÖ/ů´Ľżą?^Jć ŮwÉ`NfžŮIťŒKŠ#”‚*]w,řΖvÂ>h`Š]`zŘB? $ššb¸7 ‹u+łęYHh™Ż D]Ť Ľ¸[?ÝF'_ç}ŻËÁ—xoL×g´RÂR˝Q´c9™ŠՕąşĂsćfˆˇŤ^˜“*ڊ-‚'ÁąÍóp˙lŕđËÚ⾡ÔĹdÉť˜,äm( xŕ“~`w1ľŠĐYq.>ńýÁü>ƒxf‡Ó†gŰÁłPĎ'ŇvŒŕš`Ńę;JX˘ÚJx6ńlăůÄs &ś‹Ę2Gĺ{@ĎłŚwcŒŔ2 ŒČ˜˘ĺœń  Ć"uř°Ž–t†Łˆßńę8ŰÓtVŠĎŮç_%PĽ×öfĂýÇsđdii™űBę“a.ݜT@]š‚Őúź|(×U~ýmπ*żű˙ŻŻŽmlůŇżś‰GBĘćĆ*‹wöUëސą…Á—+áxđó?ËąčpšŢ#+ÓŃĂŁ416DőĆÝžżAŻ˝{Ÿ+Ä@ ."šúlsel[JĘPŘVJ­NZśŮxvÖ֊Cd¨ë•˝ z(ŞsRďłRćçÉšÖó˝oc}•A Cú‰á)Ƈjfčz¸†XŁ $•Č_GK>÷Z4=řaď>ĆŹh@Ą3R?Č =IňË1@TÄ:81H/={‚.;Ä ŠhČČ`8 aDä‰ öŞä5g˘ý˜Á”`œˆ›ŰxŠ›_Xfărp A‹K+ô×ýs>ćo|ýEáýŽ ó€Vb††ĄĹĺ úďţ?ŻŃÇWďÓęúççęB˙MźŸ!2EBŮ^˜›ĺű5Ŕy­_ӃjAÓĆ0ý ŕÖÇ}äŞ.eţMŁz¤`‚†hżÓňŐŐŁ ă‚T­elŕÚ@\ é[r%˜ćoË­÷BšŇ!řZfĽ,%&Ü+š"€ňX580şĐ´zȈëŻ|ý}íŮă=PĽ×zís4ôU°âh4đ¨2ŇŕTA3E(Đ÷z(Ч&`cy8C0ń=–“HYƒ„˛źÍëăy@4ZŤ )(ƒďt[p¨đźkÄϡŠV˘ÁƒS¨  ćŮIwü?ţńOxNĘý˜Ő Ş„fL–Čx/:+É"”€é5ÓďL‘áâą ŠLƒp‘Eó$`˘˝VŽŁ5úĂ_˙O7°R„BŠ÷Q›Š'Ńn,d}]ŚĐŘۅŽ Ş,ĄÜ3SÍ=[Á$ú#‹2^°ú#ś5ШÓÚҔVÖ{ JŻí™†~€gϏ˛źTŁ1Ëvď†ő)űÜ|<ř‰Ő{ Ęăi{ˆŠâ@çŔr*DÇł*ŒŚ¨ŢE‹tŽz­ÁeÓ(źŚ@ńĹDÍÎ.O֘Ä(SꨌxŔ`Ĺ~JY™PƒS“N!8Â(@­Č:¸M)K‡Ţń ‘hŘŘô†ČŒJa›'/]š-z. 5„ÁˆĆşAŢdńV@ŰĽ“ˇ™=ÁÚ. ë-6@Ŕ0čsrŤŠ#ţ؉‚ŢF¨ŹTrŃŃj…AŤĚőż'/ĽožpšŽĺŤ@ńͰá+is°ß˜>î|Ż]ťAü'A/žđ”3Îň5X[۠Ç8p˘áŠËÔENÁÄG¤6ÜĘĘÝş=é˘-‡ 3H[n`űŸţ§φڷżő˛QF]$ç }ôáe÷~ˆ'˙ăÇÓÉG˜1˘]¸^¸S3Ëô'ń.]ť5MK˛¨č0¨KSÂöČBŸ%ŇpÉ­Óä\T釀:0p­Ü*3‹ŠhDdyŇmŔC¤tí̃L:šKŠcé# âlp‰Ĺmî}>ĽK#‚ÁčLJŸîŁ-2T:~?^á™Cßsz*Q$šúŘŢĐ@}÷ĺŁôŇÖT)Ú˝ÖkŸ˝gôMŒś ~fĐOĂ!zçwŘą˜çHÁ­ÎíDą7ŔiŠ v‚T ßá‡FĄŽ%XNAM+pRâ*iľ ťpEEřŕ8Ľ  ~׊xa;Ř'œÄwß}Ť[,čď]c‘MŽM2†kQź^Qü\Y …ßu\.°ěŇľýbÁ=ćĚDsĆrI.'é+2;%xB˛ĹäéúÎt˙nşÎ‡’ŔLÂéU° Ć,.[m Ź^őÚme‰VÉ&íbŕé1č5L”îĺ̎óđ c˘íŕˇÁŠ=F@ž†^“MJE‹¤ĎƒÚ'š˘ ĽÍv"ćQX|ЇY*ž­X%^ß-÷쑔iŇÍBIAß Šzt›Ö÷ӄÂ2zŸŹ Ą´Űяőšűßpđ|}íë/;űä_!`Œi<Ť5´ÔšVŮÁÜŞĎ1ŢkęŇ{P6ËjzJ&c˙¤Őëçżá…ge~ą>žk<ϸĆ;ô9ďřŇßhđ=~ÇţUś@lŸAgŻŽ.NRĹlď1PĽ*!őÚWł)“[ç§O3ŻŁ}šez ĘăiTy,ŐBp€ąiMožHm'č¨8̏S"DxkRŚJä=÷iÄŕ‰vjLžÂ$Éd"nľĂ$Ďíć6ď€@č•& (&c#ĐyéxÍü…–ŠPUŁąĆ9ç \řœßŔHDčů—óVăA@™˛@s˙°ś)ĹŻ:Ă-uâ"Ë ´Ň^äcÄą€€ô)Vs ×\őRüĂ#ĽäSW,łbźk„ÉÝE (;ŕ^`”:0LOž?H§Ž; Ť’p˛}Ü LFˋk,˜cŻĺŽË/ůMݟŚgŸž@îsF}Fdžé?ü‡H€źpąV)Ďp‹‹Ë´ě€LöCƒ4;żDţçEcŁCô;ßűŚťcôÔSé˝÷>¤ŸýěuÎ ĐĄƒűéţč°1ňę/Ţ ?ýłŃK/>C/]â¨iľZ⸈?2B˙ňŸţ—Ěţł@×oÍŇÂčîţűRŃ2Çô54PÍŞĺú(Ň`pÎ0p‘*FęÝ @’•bE'ÁŮhĂԄ{–ŚäĀWbĐĺʖ2Ařopp˜—Çů!e Ď XW"ÖXöűś¤ŽDć#(s]Ögďá0á˜P ĽŔ54DS•Š” Pgö(Ö UěďŰş×zí›Iœě<čO=,Ş%Z;nŔ‘`qňäIv¸đůƍr9 =$HSśJ–QZ­Hú“ Ŕž‚'ź“*60tPQë7Ăä˛Ů€ é˜î—°‘Ľ“űš>éXĄŇOü:Ţ;Ďx `šéžŁéPqĎË /߸žXĎ/žm0V¸Á3ŹŐŞđŇtŞÖŞ_ء–_ ˘˘§86,ťšęěŸÎ6핦ÁÜ^űj7 Ś˙şZ/pˇ7ÚcU˘ڈ ~ g0Â9ú%'¤dáł4śˇjÇ)e^^źoCôPbE˨sۧN5si=łEÓ\8…†Ó/„eÂ:.Éwžĺ^+Ä[7Ö×8wŰÔČ›8Ÿ6tM|ô(#Ő P%÷€‹0DĽ[€šGdT1žÁ ´ĎŽsŒAŐ<ŕ ču6ü„"+‰ŚE°Śő@ü5WëÔXýĹq ěđ ¤ň Ôč°Q .{pߐ/k,kÄ0łŚíĹć$WšŐlťÉ-ú›żý%8~ˆÎŸ;ĺ@ :=s‚Ž\˝N?ţŤŸŃsĎ=ɑŇKĎŃůł§XďäŘŃĂXi8 ŚĆtńV ôŃJ¸Ž[›ŰôÚëďŇŰočśuœŮ-Иyĺ•oÓO~ú3ç\Üs†ć-žŔ_yĺˇřźŻ\šAo˝őÍÍÎ҅'.°¨Pߍ-úđÏݵŰvű?Á†EÉ]Ó­ő ś=ulŒţĹ˙öŰtíć,ýík×éĆí9š™_!ČhÔ Š^ZúSœĄÓƒ=´oß!ţ ʤĺ0ĺÝœC^’”ô-NÁ)iůiš1|ďll´*á¨_tě…ŝ ž×ţâţ gw-p=Đo6XO'óéIšĎ^á{Öě4ƒFD›žÁSńĺ›(`:'P€™XÉ( §˝Ô"˜BÜ? ¸]/JĐkżJöZ‹&ÄďŽ`9TbŔxŁŃâS§N…ßŕ=÷Üsí˘!:qP™(ĆGĎœQPë‘Ő_Ťá;2š–€ő5ęĎ_űÚ׃Uڞ{ţ9zíż”Ńdťąé<Î6AÉVp qxĂÚ ¨ĄŠ‘ţ›P˙÷e<ëÂď4y;ŕ Y$rNGA ¤ żgl‹Čž˛3“%ŃxŘɍփ'5qř-drZŹŽIú2˘ţ™I,gRmš" RSĚ.ÇJ–‹×Ř…Â}`ʏ¸n^ď-_ß,I2i0&:ZŮA I÷ą|žŔPńú*šVň@J×K',Áˆ"@’2Ml˛ŒŸylżŽĹëä˙z¸Č_^›ŠKďą × sńBŰç‡gZEeq}zÔ¸Ąea;áŮÄóŚĎ*śƒg•ü6Â$ć @Źó{ż÷{Áw žhQŚ śŻ +žküŚŐhTŁEDÄě`ZJš’„ăĆľŔ:ËK ”Ł,řŻĎ÷üŇśdíŮ˝ökhj'ôúؗż=P%+Iś€9×č”gąxƉ˛Xjľ~‰œ;`…# YŮkpŠœĘâ>#M§â–‘?ÚRŞ:#"šę 2S+ŹÎ_ĘBD#W’[Z嗤âŹqŠ…ć  ’‰m˘źDY˜jhŘ)ZV9Ň*}ĹoÁšĹďÜněçߍ\Œó9Ż­.łŁăR8" ŰÎ Š?–Y ¨€Đ_ŻĐÄh?8@c ŃGctţĚA:~d”žă@@&z2Ośˇśéđ‘ƒnâopÔlĂMţ33s´ä˘#ŤŹrÎ÷ŃŁ‡řTŚÓ§óyďß7Aăcn2nđĽ펚χ1uçÎMťmœ:uœĆĆGůź”ćý.ÓÜÂ2Żsţüú—˙ÇĘĆŐűďL?őuZ˜ŸĄ§Ÿ~’Nž:Á˝ĺĺş|ĺ/sŇmóčᏑóă˙ ý˙ţôGôÝď~Ă:ăö×Áű¸4f_ĽDO^8HçNí§Ż= ×ŢžE^ž¤Š řDÁ=†v‰”žk$×Hú ň&Ń67äxŚJ#3\Ş@h´C„kŰ>uĚÄŚ•ŐŐč+ă!úrâ…óţ~ŃeľÝ€˙-¤ťx0!e´ &‹ĺc´C‚s„¸×0,ZČIÚ-źw`‹mÖëłx Ľ¨ÜD;Nr–Ľ'XrŰn>Ůäq×QôK˛¸ ˆä™ýŔ'C‘‰Bń¤Âúśű¨ "@ţÎ{ę°XĄ “œš˛QŠŹcâ<—{ŕ¤Ó– ’ö7})#%ŠU›&O•ČDńWPnFHńÇ@h1á{ěѰ‘ŽűOńJF°*"D +é2aN•ďŔčzá…çÜßq~>U+Ϣ–ĐĹ{CńÜᚰÄw`ˆ`Áń´DĂóŤÚ)x1.@çŔlçřńăĄ$2Ŕd0ž`}€5Ě0qĎł–[¸ƒcÄ~ą-lĹÖńDA fđĚŻ/;@&oŃ^hšž P…5cÜőę9˝˝öE7<› şí‚^“V`˛~ĆőĐç5}, ŠVʁ2G¨ŕ“€ hŠf@.łÇ€@łEš­ žxkľ•ęýTď PŽ(čr„č…0eĽXQHŮP5%™ a0ĹŔ–óôi,4Z­s:ŇÖć:u° řŕsIvîS7|őüo;~rÍCôKTۆóyKeG ‰ăMšŻ—h˘…şôƒÎĆ{ˆ˛rĄ,Q‡Ěknฒ8901ČĺÁDŮďޟ=šöřœg/4'w‰Ů¸ss 4;;ǚ(LpN߇]ĽŸýě—ôÍoź@OIË+ŤÎИĄ…EgP9ŕžťÄŕ;ď~HżřĹ´tî:|Äműkżlln;äøÜ0˜%Ă §Œžzâ;łŸŢz÷&˝űá=şqw‰fçÖ\V‰ÜăR2$Ś$‹ú‚5"Źy.ľČ´K bô!>{™ŚA÷džɻ`ŒŮhŕ†ž Ž÷­ÎIąá;Ű-îo čÔJ^YR}ąţJ_5Dľcä<:<ńŒ|ďČ#ŁĆ¤FăjíG„FnŻőÚŮŕ„XEő–n`á |çEƤrˆÚ+5ƒŰ ^Œ8RxŻZ*X–Śç€Í‚1ż)č˘ xŻUđŕ0hy[üVc&ĄD­uŹŔ1ĂYƒ#†ea9üŽď˜“ĽQř§žz’ˇůŢű°nŒéH#`_‰8‡űR ,ŽŞÇÝ;şÁˆŇ_˝}[ëiŮ1üqźcjKźAű$ó+$ÚW rřźo{A{z¨0ëŔ§?§Płý¸Œq\°ł č“ţť<¤Ťšâ,\˜daŰvŔľăűdß2Q8ŻÔŕFŁ{娲h)egişRî5-l`„v’´Ÿ<¤Gë{eŸčőÓŔFžĚ…PIŽ'Ď)œžâĆ)ř‘ŽSœB_(t*F—Ma;ĘjA ó3Ď<ÍĎ*lŽĹ˜˝$Ő}šA Dń\ôPf ŽŹˆ_ăwŒا2V¸Âd"TŤŒ4̅؎€ ŰXĹłĎjáźPýgŻ[ԉÓâËËŤ$,ďzHŐîľ^ű< ă$ž'芰ćű՗Xů´Ďúgv[öa ĘŁśŤ!YđĎO{, J.Hžy˜wÚífH}Đ\gIǁYŚĆŔ0˙'ßÁa-€#$†LdhÄT ŰEˇNY+|š‚šÔ#Ó¨,ĚʰĄ ˇ‚cßÚrĆĄOapĽ$ŽłÜȖ¤Œx,>ł}R6ĚDŠfőpܚ“]Üw'čf0¸’GZ+ﳂԎA6FZÍ-6ÎŔ<9vxœĆF4č@”Ń‘~:}lœîâ˛Ç™‰Ŕ‘ń‘(LŠ÷&°Asđŕ>6 ćœŃüăŸüő׍ôâ OťÉ<0ÁQÖ;w'!?ę˘Cě Ç{||”EaӈśwůęMNżkBKRâžg^ŁßţÎ×٘˜˜Ło|ýf­Lşă€XŘÓOžŁAˇR~^pűGdgßÄ(ݟšĄŸżú Bˆv Ÿžţ)zĆmĽÎ<˜Ą×_› Tą¸xń<Ý˝{Ëßż?Í}ćŠ'Ÿ Ă‡ĐŇâ*ýĺOţ†Ţzë}úÚמĽăGŃá#âа\_‰žůŇ9zńŮ3ôţÇStůú´X&éÁĚ2 wTl™jˇBřžYË ˜--g´€ĺ”{Ýô;0DJžň#|– ĺ­Ů°óĽ–a„’M@GrtiľŁc$Ź—Ř˙5Ľ})JƒF„UűŽÂÍZY)>'Ţ ™ôZ˘2Ó¨éi6qtŔRéE zí×Ń0^ÂY‘jtĹ& a9jDZ+ó¨ĂŁľ˙ąœ0Ő7ÁxŞ  œ$MсCĽě8gĘDQ†#žúq30Vđ›2e4mŒŹ‹†}!ržŚ˛j´=ý,şMmşpá<ńHQŃt9ęQ›)u{M`ؒ°Č&ŸŠ°Nlşa~ą6Ž_ ޤŰ5;7EÉ62l9šE†FĘv ǘ0îzÚhm؄QËńs=_>œ čn 뤧ž™)0đŮZJHžLRqu¸hƒE6 ŽkśY3ŇHB’îÁe­řT+NTĂ'})čžóg[´Żăç˘á­}ÉFOrßť›MŻĆC(tż”­b¤ 9;ć‰'.Й3§xب•ľVŕ~¨TV=œĆťąŔNMľS†Ć|~ď˝÷x/žř"ݧ@ šjŠ´ź˝Œßń\cĚťŒŚať°đŹâ3Ć˝ţĘÂś0î( ËŞhśVŇ BĽ=„9(¸ë¨ăŞ đöě„^űUšĚ›~Öä™É %ç]űÜ­}H `­ŕ×<âˇÝŽC‰ť*ŰŽÎ `ҔćÇőŹ>ڊÍ( FV3œ$˘0JY•ů-ăÁJ&>uěä{” Fę^5*ĺŞ,kńăMYbşD;aŤŚccô„Ĺ;a pĐI­)’DôPJK ކWŔ@j§‡IĎ@*’Šyâ|¤ěĄ‹úUëd“2ČĘŘ Ők˄kF6&•’˝™Á…đ[݃U\=01@Ő>CűĆéÄąý Ś@Ő{JĄ‚ěcmmÝÓtĚ @ßŃńŽ_żMďž÷=÷ěE-=Ŕ;R|îÝťO7oOŇɆ?˙Żţ—żď&â_PŃ ěÇxń[1ü HkÎp~ý÷čŽ[˙âĽ3tęäq6˛żţľ8ůƒŻţŹ•}ôŇKO1psűö§čLޛ¤ßú­Żłs‹s8~ě]şt–ܟĄťî˜._šI|šn@:~⍻híOœĽ•Ő5>ž{“÷ůÚ?v„şó™™™§ýčŻéćÍ[.ZtÉmłžîI“`~řŃ5şuű]8ڝ›œ?"h0\žú(]şpˆÎŸŢOwŚ辡nӃé%f—X˙’{ŁÖ$& Žî7œ)|ĎUuÜruTmňĽ<5{*ÝÚ+|ßÁ3Đî´H҇Jú q_­p4Évĺ¸p,`Štź -˘‚*ąuʃžmŠŕ˛œŸ˙! Žřeľ’ΟY#ŃÜ8PI.żľ‰°Qx†:,ˆÜdLôśŮˆc`ĐG_ŐPćÔ§œŃE9ś˝ÔvÜ{­×ĐşĎÓLňœŚŰƒ :hu¤”ýĄŒ<˙",] B4ŠŹ‘pĽő‹ŕşD‘a\¨V Ć-ß fŸŚ`9eť-Y´ mŤłŚŰŐT$ݞXÔpˇ˘ÜŘ÷SΚÄňÓÓ3>ŐŔă(Śčóڈ1ř‹śăMvkVÁ*+śk;6jb˜äţ6~íޛ‚…Ż ŕ†Î ŁŃ})$á¤ŔĄÔ)l׏ČR\Łëx­ßn˛ôŽfm×fýŽĂ˝ ŽK@!ĂL&4^ţY n˝Úˇsęf2ĆţnĂźŠŕ Ŕ—ř}ž+Áł4̐|ag]gžňDť—ń‘őó¸\Œ"Đľk—¤ˆ2ą_:@)?gϞ %ŇąŠŕ3ž'<_Ý ‡>÷xFńLjĹ/U#Ý`ĆŮłgy¤Š¨-śőđĚ*c ϝVÂrxŻĽŘS°ëaŰ:V`=|ŻcʆQEŤĄ şmmäk{FSM2MŃÖk…ëWč—Éňh—> ;ŕ“ŽéQűř4Ű˙¤eÇ1>ę÷Ďť_÷öő÷ĎzÓž¤`ĘŁ´TtœLĺa ËgP~­dů$ ¤{]´G­Ÿś<‘ř4 Ć>`éŢ߯ł=PĽ”U<Urˆš‰Q4ágë°|ډ´łNžÚ!Qy%/‰NÄW *;'¸€ü‡Pˇ™Ťžg u|U4ÎóőĆAžä3ËŕšĹé,p(ƒ8ŹŚIE˘~˛uÉ †cŠźq0äœĺX$hbؓGgœd˙`gô×úhb|€Îž§c‡Gi QŁÁF•uQ†kř1ž žÍmŠŹ„hťń/zŒ70ÚçŔ€yzăÍ÷Y{ddtŘmťŸţčý}vFňřÄ(SÔű]§d#> LÓUŽ^ťEżxímúúËĎşI~ŘÝË>ŇúmŞ@Ł“ňƒéÜů3šMďXšq‡ďסžő¸čęž}cÜŘÇlĽZ)účŰT؀÷ƒ§=ف‰rćÔq:~ô0MĎÎŃí;“ôŽVŢ~玌?q”Oű‚Ű/Îű€QqúÔ \spW_}“Y<çΝq÷ޏ:wŽƒƒÂňÁş•JÉŰHŇqj}˝đôşxv?>>Fď|8EőłŤBĺ×nll"0kCú™öEÜ3€€ŘŽŇóĹÉŮQd˙ú´„Dă)c}ÂxŘlŠěim^ô٤cV ,ůŹŕŠęč§ZĺˆS œqťś˝Ę÷ǣјĚDš7xEĂČí! âóLž˝ś7š>Jk˙4]BŇ1Ëa"˙4“÷n†8-lGŮ#xöą=eŸ itY#ÂpŽTű΍jŠč÷Ę0á*5žTŞŚę:XfjjŠ÷ЏDŽŒV Áň ”ŔpÁşŞŰ€NŁ–jMÓ°O8dš~€yâÍ7ߢ™™Yo0‰+Îźşą…0žRpŞwăn(8a(eę%!ď+@"ŽŔýA†dÝäŽůotÂ*”*ţ“ŮÁĄHΓśŒ L\ŠvžŻŃkVÜŔŸî­żŐÚŽŐvVşßľ$ľS˜)rh°ľ2ţ›îŃz4Hُ‘™b˝=$Źn@E—Mˇřüěâؤ(ÝCž‰c(Ź×˝äťô~$Ľ ůńŕäÉôěłĎ𜾏šˆÔwBşŘ!xvđĎţޞžËŽgĚ*eŐńű… řŮTŔCALeş`üÂ3‡ő0^`[řMS5˝GďńłĘŹUýAXVŤ ŤNR5mËĎĎÍ8§bƒ&Fj´×š>kÝŇ=ťĄ×>kK™ŸÄ˘ĐČۇX,Ö][]Ł}ăctěČA:t`‚ph´đ9zƒ’K-3 %“* šˆ˙l1Y§0!•č¨Ű>҂nßžG?űŮ|Œ/žqFǀ‹ š}S'Wb•S™Ą*´YP™hlT4bŔډƒBĐůăĘ Ęě+m׏~úóŤT°ˆ)s fd1‡\ŒWH3a§ák„ţąžŽRŠË|ë¨f…*I>=˲Č1ِJv‡źvŮżŇâ#s&Vř&ď6!˘ë@J ÝNú—đv Ç"Lšâ`şWŇz­×ĐÔA@j˘‚řˆçŸ`l QŇojďç‡}÷¨uSvÎ'@ݟĆBéfűtł_T(żŠŽTşÇ•Ö˙x4UHÄî:y‡4'E¤ČŞăi˝˜j)™áşŠ"95QWF ƒ">‚^ŢI§ĘŮ"â/Q‘źpD;ś€•\e7ů#­ەҳqúÜVü>h(—M`„°Ö ŔˇźßjށĽĂZ&˝m ,qĽ"lW0Ä °MöĐSOŚ3'ĆݤTĽ~aŁÔjŮ_âÜó9ű”"¤Îüŕ?ĺíAhé9¨D°´źBď˝÷1 ˇ?~ħç8ŕÂôbeF9| „ِ4yÚEOéÜٓ Â`ŮŃŃaúÓ?˙ ˝˙ÁÇôőŻżŔ“ůÔÔ}:{ö4=őäyÖ,ŠôU¸ňĎ_˙őŤtŁ0/źđ$ë’Ôę žNB%aĹyěě‰'Κë[â´\?a˘řkç `D0_ă}Z_ŰtŰťÄⲸ×ÓÓó,X+Ő-Ö8mŚVŻşčęa:ä–9sć8]ťv›>řč*W˙1Š\žg )ST ƒŞFHŠBšZˆžg[…Źěš(÷ČUZź úO˝&z>Źd"ő9š`,4 ćľE€ŮŸ'WľjśÄCíŻ÷3Cdßo‹Śt„Bjšęľ˘ÁňĺŢ 7l‘˝c3˨ČËú4ąŽwăq~vp řĎÖŮ@ūՎ;–~ajůçISÜ>ÝÔĐkŸˇuGzí‹kÚççźčâ@Đ AĐC#ÂÝMç(-ƒ‹gÎŃgÄ%Ň\ @Š2@¸,ąűŒď5R” Éb4-oŹ:+˜ƒt[)ÓEĎC#ݲ˝~ý:ƒ$ßůÎwx(Ř´ŕ48q"Dhá@a=)ŘöD:ý^*ŤUĂqÂYĂő…‡+űĘ+żC˙öţ<زě:ďך÷™ůňĺéŤÖÎ*EjşĽ§­ý€Uęă:ߐ3÷ż=>ä‡Y€”Ě ˘z1G5öĽ3ĐXÁüä:bËąßbîăîĂ<äwňbžĘĺ†k–™9IžäĹw% K˝˜Çb¨‡QäÉ[€ůó;s9,×%˝Ô•Ďčh›DśÍ>ú.ƒ÷đ ]Ä8“śˆź,ʤ˝ÇZßëwć,ďőkÝŻ5ŠĎ"G÷7:B˝÷Ëý¸_˙„ÄzĆ:§č…ýuh´Öý*_ ”ľĘgŻÂzĹÇ:۟‡XwŹ×#]'ĄÚύ4¨L Ÿ\7+•n]~‹´‰l哌V2ô*PbWžTqP,;SdÚĂŰFqَƒ'ěXÜE'Ź|ÖNĄˆŁ;F|Łr˝~_wİńAŮ-ܓܕ§•A ¨cÁ˘şŹ„—`2b{wí˛[ď˛Űětđ„PÇăăÑ}Qďů6ŤŠŽHh~ćřćĂ7şÍŽ][í÷˙‡ă@Ę]wÝęďú;śŮґ›œ1@”-[6eJ¤Dezz6œpLŰö[l8lâÉsaaŃž€‘_zÍ#ţěÜšË.…kˆźËeďŢ=ţ"đŔˆh:Űśm˛v„—ęŽTlpŚČńwŢłmۡĐh˝ť!mßžŮF`9´ĚÁ Úu<âóô‰n%šČu2ćŰ.öúÇ`s.€805îb‡n呞ú—íŃ'?ţ€Œ%^ţGo=Ŕ•íšç^ňMrdŞDö”\@ Šă—=§Ĺşn!“`p•ÇuďÔĄšřBŐ­ fżCĆqÚŹĄ§„kč÷fuÔäęFŸ5¨^ˇŢAšŤW.ůç&6ćpÜe4-’>¸'Ë ö‘|4ŽťU7ťôd`FAŐKq•.uż2{ÉëGh敕^磞0˜/]şč/6’ŹgˆĽŞGtş§C*{ż˝/“Ó§Ď`pŻ˙ÍF•—ó46bđËЎ"ŁëňËN‚…šÄžz\ëďAjBÔ6ŘęëHššˆ&‘2Ďö~)Räç|lŔXů0)nŽVz„%Ů0hĂ#JęĘ獋lË (02ŢlH€’‡B!—§ß|Fôƙ6hŹŠŹˇlF8 ÷Ýw˝\…p–@­ < ?ëŮŽđžë7ƙ =ęD[ϡÝvŤíŰwƒ;'Nž ë]Œ°f (çS\œ„{Ti}*á†$h˛č™=ŔBók7­‘ŠP%ŚI(4Ť&˛žĽŰfĐS‚+}†|˝Ú°_ľ|VŇ÷H`Qş*3RT`QŠş'űş7óžéŢ9ŗýH|އŔŤĘpŐU>(#uű éSé+żŹĚeŽg-Qheîă{ňb- .ĚmŸ×UHWfli~ô$™XRĺ~NLú×Eš Pčßűé/wžţű%ˆĎÜ/ËVâ;1P׺ŸąđJˇ­§쏮ĎĂŤÚŽƒš2ö—ĎšĹÚĘş#m(ĽFžc)ť0_t]@˝8ČIn!¤nŢu“‹OăśÓJBœœ"Fű/‰şÖ˝yĘHFćČȸ+SS—ŁćG_œœÂŽńbؘ7n^îÝş—BčC,iűF×Ů2i'pĹAŸNŹ ƒşN†,§›6ŽsŮűďÚg7ŘnëĆG\7dd”‡ŰNQy˘ÎJŚuukTsu*€[7EĄÔP>ƒň öUw—š˙ţť`˜›_´[€ŕá3/O9ó‘ׇş'% ŽĄ]KÁ¤—WbÎöP˞áUű‹Ż|Ó]îť÷Űžsˇ‡ľcÇNؑ›PdŢ^yő-;sć‚ÝuÇÍĄîC.Œ{÷]Gm*9ü'á}wĂ>Ähçm÷ž]öČ#÷نőăŢţn‡çŰśńőŰÜęÔŠ“žI˜œÜdűvĆĐÍ+Ąó†Ú ˝‚pÂţÖ/}Ň˙䣌ž°Ą?cO>őŹ dôČpË>ńąűíßţџ۟ţٔ‡]&˛™•á‡ń”ŃWíĽË-¸Şś×ÓCS#|źŇDźŃŢ5ӒhĆX]Y†nś7ăÄţhU 줍qĺt~ôRĄœňťa",[2˄űb ¸hÔŕ:6Ć+uƒVë§Ň7y›öůI[7ęŽHˇĽ›Ć*s˘ëĚŞÚD+W„‹*ŐUýŕJëJß %ć %ăd6–gOżk ëBŰśŮĎKúÖˇžĺŕ€c‘Ŕwß}Ď~á>IÍ<şb­V֋/žd˙â_üýŁô_xŘń/}éËöńÜ^}ő•°9?ę,›ďçŸŃ7ş¸Ňeńŕđź(ŸŃ_úĽ_\ó”Ą˙?V”äÖCOŽ2eâošľ C%ć䵒ÄŇäRůA’60Ě?éHXă…wă€ĎŮ!]ë~0š€ÝňţFGrŢ˙&FÔŤaýFwC‰Ý‹…+ŔXzpZcË÷OŒ2ź’ËPxů둮¨bz ćnC.´9œ™(:ĺMďéh§phjxg;áÔvůčFŁ?Ď(äł´źŕî<<€‘‘¸yĂ [ˇ!jĄ$7Lë(ÔŐÍa˙Ź9JßaÜâŃíDQYlNgtcůxތŽp*9nťwl˛;îąŰě˛Éđ7Z)#ĂC2`\ľÚ)ä˘UVŽŃ8Đ rá˘ýé˙˝ť° çć›ot#÷B8¸ß6…ş ÜuÇpś„CSÝkܝÂuü'_ń>şůć.ĆşoßîÇÎŒůöwžňPƧpňöńž×Żţň§=şÎ–­›í×í3ö'˙îËö­ďš˜•3j&&Ś]ŻäĆ÷fMÚžź´âÚ*°f&7mtú˙ôéłöď>kƒs。ť Ňö­“aąÍţ_˙ő˙7”?mGŽvˇ™;î8Ŕ†é÷Öő(R貴–ťĂ]dâ6 c`>ąQęÄć°ÔBYť)9翇+ŚŚěŐˇĎۗţň%úä;Ťn#âC˘Îű¸ˆH*žÚÉm,Žš–ƒ0-ŤňÂ# ‡Č¨áš!Ű´yŤ×g&lhŽ„ü7NnňçŻŐF?n‰%RÁČ*ąŤ’vQlb:…­r(híĚréäţŇ"8Öé°Űć-ŰlSUp•űyI¸(°8?řŕţ";sćŹ=÷ÜóöľŻ}=ŒĹ;ěw÷?´żüËŻŰ7żůWv÷ÝwúgŻ˝öşłPNœ8éQ xQ=zŤłMHßýî“öšĎýŠ}ýëß´_˙őĎy1<ĺb~‘ /ÄłŮć$÷1Nž|ňiűâ˙<1 v{]ţť˙îżwpć×ýóö…/|Ń c@ŸÝťw9`(ô[żőa=8<VRŠ˘´1\éľúDÔwÖMmFŢ/iSđAAĎ`CJô{…/IŃ}`ŽP†ŒN˘yÖb†0>Ľ×¸Á¸€ůÎwžă'ݡŢzkŁďó20ć¸ąŚ¨ äGyb,ďźóŽ—‡ÁőđĂű÷kĎ?˙źé#GŽd€…ň$\‹[ePO AE*‘ہ˜5ô+Ć#ĺsÝĄC}LŸ8qÂ٘ŠŒ$°˘ŠZŤ˜ ÝŹQŇŠÔ‰ą—Öř„2dvhy]˙°€ďţşÜm$ĚzůÖű‰5L‡tmłqśĆDo5Jř#íWŞ>č ϨŠN¨űŰS Ţ\zĘ,űźxńýQ‰ńŘ5@ł$ŐĽî6yÖu/“ë+]ś°‡ĄÔ‚ô‚+%Hdýí.˙ŽÂwů’ň9ä2Š~RťšŽýěĂ=č.ÍĚAĆ?@%ďQ朢÷0?8ŕcžuœyüÔSOů<0gą~3/^~ůegŠ.Y†Ië?÷Č%Fó’:^2_™˙Vř—ůĎZÂ÷$î%/ž§ž0Ít˘KťÄ@ăoîŐşÂZß1qOƒŔľB—úĄ]kÍ\iŮ5AÍA¤AúPŠaĽWŒ`žIc¤uOÚ"Źý`†lZ ýěĺÁ~HŹ3ąCd”áÝYĎ$`Ż5QŽD”Á˝:ŹQ=”‡tŕJŔDuŕCb¸ŞŽĘŸ5Žő‰˝˘öד6ȅńzéŠŽ ¨’7&`Ľă{xĺä’#ݕ¸éćkŁÖI;…GŠ'é„.f#…&L4)ź1ðAƃ˝ĄÇý˘ §ë€śZPę7x6ŃZÖ ÜN;ĆO"-n¸ÄrÁĐśťŻ´[ľmÝ6iönľGî;`wÜşŰY(хÇŇ@­óď€1ss1.ŽB„ý\čPďÚr˜ÚÍÁúěßúdČëťöNŘLśÚ]Űşeł÷ÓďţÇżáĂhň+óźÓÖ cŸA 3âî]ŰmŰöÍ!żMö‹żđ˜ýˇ˙ôŸŰŮsçíÁ—ŚÝŔ{äáűíáďńÓŮŃąáp˘¸ŰţđßüŠýqQ>ń‰‡Üđťtiʁ6ß˙ăÎPůęWţĘĂűšÍCŻł¸ÇÎ_8o/˝ü†ožoťíˆë‘\mZíxúşŇą“ÇŽ…ÍĆ9ۡo͂‡<ËŮŮĹđ‚?gß}ﴃH0iĐ8˜탽růĘUw)"Ôówv­YŠ#1’ot㘪ڣśźN^V|5ě'Q ČÂĆ!ZĆęÔ̢]¸8kO˝°hĎżüV˜ě—œiˈă6 ő'1:(ë×oH@aŹ ŽfQÇ$Rü)<źů煉W@)5>. %ŐsăĆIŤ'6şŕîôôg]†1O1!ç(Ž›@šďt“ 2cŘÇ Ú.u'bŻř˘¨Ís Ú˝ŕEô ÔfŔ!’3ťÂ÷ŒÍٟ‡ôř㟰Ż|ĺŤöOţÉízœŹóóţÁj˙ôŸţ3_ä_~ůűŻţŤdĎ<óŹ=ýô÷}ÁÇäÔŠ÷|ƒ}ď˝÷ř˜$jĺ=÷Üc˙ÍóßÚç?˙+śön´öh)˙Ó˙ô/˝źżów~Ó^|ńEűű˙˙ŕL ěßű˝ßˇ˙ňżü/÷Ťîâ2H1é%pľý´LŃůýěË|˓“’p-ă>"tčôZ”}•Żč>œóŔ¨ÁŁ.b}čÔŰCś§yŃĉ6FÚC=äcF ‰űtŞM~şü)›vP'6@ÜS…<?ȏűˆJ“‹ë=ęůRO 0îØ#oîĂäcŒĎDa–ď8π厝îňą půî{ď:sea~!ƒ×ĽQœř!ůč.‹kb9tűţ@ gWFpË,… â4˙ˆm"HCúďŠkŤ{Q‡|ˆÔ÷GĚť2[ۅĽJŮ6m]˝b$p˝eÖd‚앤(ۛŰ/˘Ű„ŇlÜPŕ`ď?ĆQQéž }fÂô\ëR–WžíŻőť]ă3ľCeWĽáĄťÍ˘ěŻţ1Ĺ{ţąGńĐÉĚMćď؃Ěć@ Ćß3˘{ó´Ď ƸÜ{XÓżň•Ż8ˆ›Đ/˙ň/űsŸDgĽ@_Ŕt ôäoށU&ýćńmŰ´Ąeű÷ląA¤AúŃS 9™Ěki¨ĹďśŸDä2ôĎźeî‹ÝňAÁ˝—ů[îBăéťńéŚ}ÔJ}$r­ű劣2J— ţ:đˇÚQ2ҝâ`¨tůéT˛¨TUe×óńş€*ËË ŠŃ?ĽwdŠŽNl“v6DŤÎn>édJ~WN †+!ŽIĂá”wžQkť¸9ęf×! ŞM›ś† ٜ ÇŽƒľâ먨<”\‡$–‹˙űRŘt>e˙ř}.ëa)Ăi4÷Ą…‚Öî>D˛ůßţ\Ą%śNŰÝ9bˆ_´^}혋śÖMňzóíăÁ{Ánżăˆ=x˙=aC>çg"ÚÜ€Ž{îš#6cáĺ~%œbĹNžx7€+÷†Sě=ׁ‰ ž–k0Đ1ŮźeŁýîô뤚^ܧm)|psĂ ;휣‡ŹŒéŢ ¤čé'.PkÄÁś• ˘LÇĎýş´!í"tłË.R¸KMĎ,؅KłöúąóD9NJgyC˜ănľ;ä}s¸îœMO˝ëŔ‚ˇ““qĂ~›âˆ~9çđHCTSfGl,żŘň.)–Ä`㼉˛ę4V\ÇcÆ >Ž\žh#a‘„Ó­š9”Îô,˛a‚!˜c)¤ˇE7!iŠDiř7Ě/îA7eËÖíyÁň{[M„‡Ÿ'‰Zž%›WNé?őŠÇí_˙ë˙Ő_ncÝ+2 0úˆ %wPtĆ8Đ]ťv‡ď ™‰ŞřÔSO;Ŕů˙ń?ńůňÖ[nj^ŐÜďtÓďž{îśßřżíŹXZ¸ ą.Ć9TĽu˛ă߉ÁÄÚ#%†É\çeýĎ˙ó˙â@ËŁ>|Ý|Lړ(ĽŇ.šVŇK{Mľ/ý0/r@Kiˇ`Dń|¤wŔŘă‡$6œN–ĺ s„ŢŠ€ŰüËŘĂŔ#Ř)ŒY‰\b¸Ńv€ ~ř c‹ńƒ!ÇĆE mfŢ`DąžcH (a3C™O?ý´_‹AÉ㈠yË­A÷Q Oʑ!§6¨Pw^Ÿů̧˝_08Ç.œżŕuŒâ÷ÖXŽF×śŚ‰Ÿ˜)UůˇYóœ2ĄxŽĹub2ˆU›A)= ~ŐëŞRd*چćm/ă˘Î űęŃSĺňK(—XĽkęŢč7=]ĐÓ ĄWPĎçk€jWß4ŘĐľçF?‹Dš4ě¸Óßś~ EG}3H“+&"gĚżgżX2TćNźŠîeҤyÍşť#ě}~÷w˙cόMć˙* :sP€˘ćN?;DÚDĚgŔî¨dNă&Ä<â=œㇹ(€…ü˜o”…A…ĄC™Ň@R¸dąXo˜3bi“/ó’=œ˜eĚAĘŔXá^ę @+­˝×tRM™|ĎÚD{˜ă[6˛ţčF¤Aş~Šv}Išš0™ĂţMZ˙˜‹Ź#Ň5Ń!ŒŽ‘PkLŕ‰ďĺŞٸ&¤’ŔÍů2˛ ţ–ť÷¨$ąOäŹ2ЇëXgřLm•;ÜĄYGY§UuOˇ:DŚŻřWëŹňůHE˙Ava~ÉEîqK‹a‰ŁńŘNˆ\|݊á;ލĹ´œĘăąÎa.“;EÝÉ/ب‰ąœDg[Ž{â/ŻŃ1żjú˛ľ–S´…/Ç_„l´mCQśl^ďhű}wŢ`GnÚé‘^8ie΍ˇƒ{–\Ä-u8qň={ĺŐ7mçö-á%łĂ™ ű÷í˛N‹˙흳ĎţŇăIĹUԃOt@2lў‘|ş455›CaŽťűˆ-†“ďżüúˇl>Ÿ˙Üg˘p`§ň#ľl*iĎĚ촋ĘŇ?[ˇmrÍ"ŕŔ09~ü¤ ˞|÷Œ>wÉŽ^™˛Ă‡„ş}Â&6NxżánđÇüa{Ň>ů‰‡ÂK˙ o†a=đŕ-. ťircŘÜŔ öÇ_řrhߗěÖ[y›˜„JDÚł{Ť3+85˙WÁ¸űüŻ~ĆÜxCëÝľh֙ÓaB̅Ç }ŰŃĆEĄÇ>)v€žő/ 7 kdŢÇK§3kŻ=?­œĹŸŁŚË/{fvŃŽN/Řš 3öŇkg썦,„gÚ-6š<çČFšÚ?úč&Űźíž0/†oĄÓ1FťQŒ™˙ä–ÓŞň)žĆ}G:<íĄĚŽŃ˜ďÝ3*(荺f~Đ,' {ŇŤW.űsG÷Ä $ióíučĆ•Gݍ 2F ‚¸Ň|_ß°lRű™Oh!‘YÔkI‚YQČ~í}ýő7Â)ý[އŒo~fffS¤ŹMîvłëßř+˟˙üŻşűυ Ý0$š¨˛Ĺš ČňŸ˙ç˙×°ŠÝćă;öÝď~ĎÇ0†Avöěšp xŔ mրW^yͅ˘ošĺˆż¸8Áď˝Óś˙ čůdzţżđxl¸űź|ď{OúşŞĎŚ– ÷~\ŕç"ÉņgxőęTXóś\ ÖéÎJ âO1GrU4R$ƒI‚łÚXQŃuY 0 Ř˜źúęŤnD1Ţxŕ_‹ËűäŞ#U} +ĆľtdňŻŻ-á”]ů: `!ač̰†`ÂVassěŘ1gśÄĄä‡ńE^¤qݟńĎä˘đÚkŻy;pĄăD_ÂťďžŰEu1ţž˙ĚłPžěŃî`2F¸.ÖÜâ9›5šůĂć].Č@̍~FBĽë+#ƒ}lІ‘R_sil„ŢŇÓ[˘1â­*]pý–˘~Ö ôƒ"eËö×}yőü]~nR‰@P•ÜŽ›ďbŰëž:˝ď2ăXGˇ`ŸTÖß6€WUÔŤdą¨ďß<ęrŇ? xËě›ňž"߲ĺżĚł#ŹF”–ľZZ%ԋą,áVëäÇ5ĚM>T4 4‡¸–šƒ+G*Ź×Œ{QŘŮwÁda~0/™KŹëĚYćBŐCů 4Ձ%ë ßS>sS@ ß)”˛Œ"ň•aD(űlĺGZS¸+ÁśŮą}Ť]˝xňç!řĎ ŇuHUÚă7nö1ʨ9ĚŮĐŮ"čÁ{ZLľţ}‹dŮGîDýy(ćżÖłţzđNçŢţč;şF(Ł_P,žç^š-uKVd“Ř'ö˛>ĘĽ˛dĚPţ.…mëâ0äz¤ę|^Yď{%Z¨Íżúi§ŸĄôĂ1(ťĘMŸůÍř/Œł‘nX(X7ƒ#ńD=)ËţR…‰"O(iÄxľlź*uEB­9U‰Lć$ŠÍ$‘Ľťŕ‚°[‚áOžŰ6Úíˇěś[ít`~˘^‰Đ6˜V:I /ĂÓç‚áňźÝ~Ű!? 'xg/ŘţáŸú yčÁ{ÜŅz\źtٍ Űn˝ŮvíŢîn-DÉÁŁţѡżăQaäÖ8ó×ßz*;]…pŭ֐=ůôłöÍo<á‘znžů&ťru:lDß´‰`ŒÝuç-ścç6gœ 'zż˙űčڏ?ţ°?"\ˆLqçˇxˆáÓĄ h§`°Ý}×­ałp3`šüËůoÜXü˙îŕĆ}ń˝ď=kţçé.>ŸzüQŰś}‡3eŽ;nď:ŃÁpĘ~ř›ëC),h<Áż6ç˙Ÿö{ŽŰň‰O<ěŽX´sóć6zý¨PÇrČŐyčĹq@˙ł)`Ŕ˘3\:Iäľ˙$Î#51Î:0QpçY°ËWçěüĹ;ńŢe{őÍs‰’@9˜-Žn.űőËQ˘˛6IŢU{[¸äv>Ti&Ô0­n§ÝL#n%‚•"RiĂÚ˝'˛YĚzOäâŻUŸ `ŽmöÉ0šćfPŒőm%7Ł’đ„VÂH‰>ăů:3Vf=‹šNV˝ŒËäžaݐ}ęĄýöŔ{=RͨGŚögŞg؀b×|é]ô­0 _-9٤ŰZoˇě ŮhâO;HÖŞo?z/׹ţ-˝6ţz•őÓŞŰłn]c3_5aşëş{ÍvRŒS b֜7ŢxÓ]„Ę|úOc&ĹG5ĹSăS˙>ýF& Řö‡ěOŇPŢ´ęť”O§Aíž?.}Ëç”!pCFPIďŐ&‰účJ@‡Ä$ošĺßŔ(L+ůR§ČŞšĎžŐ¤(Âť˜5Q¨ŕ†"q毈{ʓ2pԃÍ×ŇO:Éfí§Žä đ°G]`śđ=Ÿ+”+ďNŮů † ĚňĄţŠ0 ăđ—yŃřĘ+ŻşŔű•,ť.ŃĘJ•ŰűkŒ÷ÂÄ-HÝQČSÁbéÉĄę|.‹źŠz¨ŐŞ˛­dLŘH=ŔM3ŻŤâQ~~­űKpFe—÷–őjš[} ş­r#ZóZłkiŽ”@O˙wőű•m˝ŕԚyü€ű‹ęő$ľƒ÷ÚÖJĂřşýśŰ\7ąŮ‘KÂҌy˘ŠŐ\a<3/qGăţŚ›nň9ËüĐ<Ś s…1/0”šÄ˝Ě9ć¸X,ÔA˘´ŇQÁ‘aĹ|bţę˝XBűȋşJpZ‘ş¨y)lŞöšë°Ňˆ Ć|v€(ěś.ŸÇŞp¨őÓ´' }Ř}Á ŇßtbŹbƒŹ[7ž÷ˆHroŃľÚWJ[e-í!b§đ˝´”úóa]`ž‹Á˘uCŽ>Ň_cQĄţkřĄž\JwR?EĺHXWnCŇPaÍăđ‡ƒ"ĺS–ŁuMyčCü„5ę‘p ÝĐcĐ YI?ôÓ-~ęâßüZ1[íMZŚë¤ŠRŮřú [ /Ą™™+66ş.GńÜ]q#pČCşĄ ⤉ŇjBÖjUғ‘Y7!ŽŰ š\ž, ŁÁX `ĘĆ‰Ń˘Źˇ­›×ť°ěm7oˇĂwÚşąwă)OFŹŞó ů_ ŔĹ[ÇŢľ˝ťw„ťÁ"6pĎ>÷‚˝6u?tˇ żźpşƒE†U@‘ ësĄ]…ďs;mÚ_|éu8ÚoŰò8@ĆŇמeO=ý|/x‘Ú…‹0>ÎŘoţćçÜ=g}˜X¸âœ;wÁžxâi?q˝ëŽŰŔ36ť3öŘŁřä;räPŘ|ž^â'"㥝^â‡]Ÿäžťołżřň×(Bă)7,éłŰoťŐŢ9ńž˝“qÂ3Đf玭văţ˝)P ÍÎ];쌃{sxĎŻ~őŻí/žň › űčŃ#śirs˜X‘ŽýkŸ˙á:¸Ď_ş î}ɖĽ>˛N˝â@J>ćzFYźśNL‘ń&ĘÔtQŽĚ9ĺĘŐy{éőÓöÖ;ó) ă ǁ”óť4ÁŮĚlČbŽąŒhœ0•şĄ˙ŹsÚëjU0 ZDÂA€i6ôďB'ę<>Ó _ĘŤ•Âv7Ń{ÚÍ)]]÷ Âßa̧1؛pÉü @Ł öÉôÔU΀& WŽČ˛Gń[דo]w{€éťô ˝ŠîuŠPŕş?G†š‘“ŽľqěĎçý6˜ńŤ÷<Ĺ˝çŤ_}Οş)F őç=E#!FŘávǎíِŃ)ËĽˆKpňýĆyńRTů°uˆšđ`ł˘ňYOe(‘Ż44ŮŹx¸pBÎćĆFŽÜ h Ćů*R›(NʟviCBű–ÜpÉďç˝ĹďÜǏî#O1_JJ°ęÍiş€mĚ0ŕ<č÷ A_—ŹÜîźóN׉Ŕ¨Ô ×Ę<ű(?(•Ź[ŐĆşÇPŽ—Ök÷ˇž+Á(ĆÜ׺v-6I Ô*Őś~Ö_˙Uy˜­zז MŞO|üă~ČÄŢAŔ ‰yĘÜ`Ţ1ćk?ŔńqĎżš/bĆ1瀠żř‹żčă”ĂG>c@(D2?:‘ł đ`ăšçâÚ ÂwŹŠÖĽĘZťYt’+ĐGaÜiŒzĐŠĚ!AJĘ´…:ŃNÚ ĐäŽBgO{×0‰A¤Kb>âć/0Dď}ąVIb{HťD€‚Deßď°”Źšőˆ§Ů2´g›N˙5ÚGŹĺ–$ŔD7%XTÖE*ŹM\§C2öhŠ~&M8}ORY×#]÷Ču8ńÇh]'u#ĂŁîn`ŐxžśN,‰Í!ŹŮj5‚˜2$ýáŐŃ AŔK×#ö´œ.5Vö­›×š+ĎĆ üžÁŽŢe7ß´ÓľRZ)MŤjŢńUŐRé=ŸĐÂ{ëíwěK_ţ+ťqßťëÎ#ś!ź„NÝżowx1^r¤Čş 8ťsç6› ×8J?#˝Đt;ž{ţŃÁ@”¨ZCá%5cß{ňYg—ÜqÇ­ gçÎí.> S…ČňGôEűĹĎ1”œtJ]§˝_ł;şę÷9čA7ŔĎݖÖD¸pŇ`Ż„ Ÿ1ÁŁžŽŐÍřśŞQôÖůZ^ĘÁOOŰŚ­o•îk4NÚÖču]ťEßŃÄs8ŽŁ˙‘ŁDőU•Ý–źFNĄQ4ř ĺĄ¤S}*/UĆÁ ýÍ$6ż÷ďţŽ˙~=•Î? ÉçF0Üq™:Ö^X+2^Xwpńb`í;Ź?ŒšÖŃű1YŽ•Ř,̅ľSFč˝Ě5ĺ‡AÄ:ŤÓdŔ ‰˝<Ü{ď˝™5K=›ňć3ňĆ Â(ÓÊ ‹ÜÄ2‘ŤO2Yŕ @ ůh`hQ/mf¤č/# †5HFĽ"–pşNý1̸Ná^ůŒ$q\6ωüÄ`čBŸQ6ŽGDQĄî€4'Nźëm…!š@i}+Ą’¸ßˆż7nĽśŻĽÎTˆ^Ă;^] L)1ť6(`×F3Ş’iŤ×Ř~㿎ŻÍt)€ž:×u/8ŇCó¸6eşîŤOekƒ8ńpĂr(枏ÝŁ<Ňűq-BQ&5ůŻUv˝ę—ž˘S^Uţˇq=˛Ź-^Íű’9ƒ6ŐŃz2Žƒ˜G€ ,ƒ„Ď˜7Ě伈Z¸¸1ž{ěąüld¤?s‘šB *&˙*ŞcĆ óë8ŃĹ-I§śĚ)ňć>ՋϘ“”E9Ž„Ńźe=á_ą_hŸć6óP7$ÖÚ(!ĘřţéŘ Ň ýč)îíă|*™¤’y˘ˆ¸biŹu€ľŽزœ¤”—R?"ç’m[‚2‡ű˘tęUŽŘÓbÉpÍewrŁö‡f.5YJ†K™Ä˛űHiŞt25lăë7úë }Nӗ–Ą8ŽFĐ$É%°] ˘x§‡—uˇVŻq*FKraŞěĐţIťűč vçŃ˝v`ßśđňvZv+ĺ! ?P˙";ꪘkXD°Ľ•ţ¨[íćC7څ‹—흧¦oŃ_˛Ü— …Íö–Í“Ži‚žŠ\$`ˇ\ yťÖ‰‹Žť;ď‹/žňšh{ôžŠěłąń‰Đ7ěP*8ˆ&ÔY‰>ögĎ^°Ă‡öŰŹ‹ŽwË˝÷Üj_ţň9ť:5kíSgíÄÉÓĆ şűÎŁášĂ&6Nڎ§ě˙đßŮ_|ůö‹żđ ;|ó! ʕŢŔ8ĄN„EŢśusWv8(ôç_úšłKzčŢ~ěó¨=Ÿýě§ü%ŒĆ eěŮ˝Í_Ş\‹ňéO=ęL•ńÄ0Ă é7ţögÝ%n<›qáĆš˙Ör§î*šQ×##9EÓŚËü31™—:6;N’/ĎŮéłWěâĺpŠ{nƎ “qj!ŃňŰŽ ĎÚÚî×í¤ˇ^đ1˜Ů4ĺŠ]m= ,Š–ľšSÉöYź6Rç–ňÇuhŲQ×ňHă†~ ‹VĐ'‘ŐĽ¨D1çdČmŠj0˝§ťńšź Ű ýM'őƒôĂ%i ŔôÂ8ÁˆŕeÍÇLi'Ąđ5îv€ž{YßؗwÔ@ˆ.=b|ˆž+š­6HNԏMǁÜ(ât™żYŁŮĚPo@$Öpš ‘FF§ŐäG9´j? ٌ ÷ ň`ÁŘÂPĂHT‘hŚ|›eź‘F™„ňˆDˆƒ‚Ö÷‚™r¨—¸ĘmI‘K´IâoęJY\}ĎÇň邟°^`“˘ëóöĘŐđ|a$v ŕ dyřzi€ †5xBU÷1JęşđňYsô1IŞUESFÝě+•l–U.?ý…io´FÖST_5ŁéQŻQżÄrŠűę\˝OŮš š?ű/,ňÉ}\ô_ŞsŐŰUk=™•T7WéĆüôŞŚPĺ9¨Â%çĆýű]3OŹ/šł ĐcĂO™ŒOQÝu‚ëyĽ1Ě<Ŕ]†ńŮË7g€…10ĂO\—†3pÁwŒć( yaxHă„:h ă{’@ŽĄţ|.vJÉ”ŽsŒz‘óŠvS>őç~4Ts´.)ęÇbŻ˙¨2HƒôăHňĘčg’— Šd°hícDזŔĂÉGߗ׌íţS‚%¤”)Eq×Bt/I‡B Ż(?e9ú|ÔŽňĐ@ß čՁĚőH×TA vd1ľ2\ˆĹ ƒÁ˛¸8ÍXŠ';(˛b8…Č>­¸é(_Îľ3Z6>Ňś˝ŰFlďöĄđ;ě•%#´ŽŤ TÝôoź @ĺŐ×ŢňpŔ°AvşÉxflŢ´Ń6„— /Ô=ťwÚç?÷i;uúźEۡÇ€ UvqÓn)€Árîü%űöwžśí;śŘ÷ú旼Ţ€™“ž—ë._ž`ď'Œň Ŕ š#'ËrűśpyĆëÇ ë˝ÓÂŚÎA˘ĎýęgŠÜMî˛ŒĺgŸ{Ů΅ő}÷Ý€šý^ti"ÓĄë"ź“ă.{üř-öľŻŰýűaŻLnÚl{oŘcżôKŸôg´wĎ.Űą= č޸ˇť4‚ůIič34P~čżß}gC ćŤÓÜvŤ•M-=ŃVb8T­aM>1˛GRßŐuł)Ť›ďă$‰î/łóKváňŹëĄ\šNN§ç]döä{˝>ÔUx(€ íj()óeP­ŽĹdwą lt¨WŒ•ć´Oc( šGć‰ěŽV%Ą˝Kiă k¨/üNŸť3áťHUłŞwc™OĐT‡ŞŘôFu=×܁ůŁJ_řŇb4ěBÎc˝F@ę|~Gŕ™ń)KţĆE+a­bîeĂ"—S5U­Ż-Â8HƒôłœĐۨ_;çƒ%Տ0)˜g€0U0Đ $§“!ć¨ŘüÍu:mć{+iŞ‘6E”Ĺť„přŹ4ć¸wŘŁăĹĎšN‚wşŠďŮěp ýŔ"1KoÔU'ßäÍé6ď~ç]xđŕÁ,îI[Ńeŕ^ęG§aœźÓÖ/ĘÔi?@’NŃéęI^rY ąšťýöŰěśŰŽşkě{D;zďTÉMué9¤iJď3ęŢÖkź 苢op4÷WýŠMxäb@ߎ1^tM l—@OńX+şďÚV,ö~嚙De×r—émĘuVűęäÄ\Ś­íT޲Ö5ýŮŚWV˘?îö˛ÎÇçwÜîŔAÉđ`źiĚ0ć˘křŐ $j|ňˇ˘ćpc“q̆á(p†>ä~¤ŠÂŘÇ ŽŠÄgŕt”Ć׹†p?s’y$÷Ë€ź)z”Ć÷r_5CZ,Ě%Ú˘ë°ccđRo˛ {–•…KLeéǔX;bDÚ”ĐÁB<@É ‡ćrÉ^‰Ză=ş(ýŒz(’Ž&JA\ÖŞ—ďCĘkXó˘2Úŕ”‘%ö_ćS^CťXgÄ^UčeŐŠŹ7‰ďK •˛ýŹUŠ&DŽGşnš*Qű¤kĽŚF(F  ‚âŚŔĆqd´GÉźÖŃBLęÁÄßý™ęÓ¸-ÄĐł]ť6OožľâL‘}7l÷źŇśG†LۍȪč:@rĺĘTŘrŠ5c[ˇlrÝD\ŃáUö @î,‡­KŁ•‘¸Špš(œŠÝ|řF×?A(–Pˇ'Ţ=e§Ďœ Ídx-Ůołç_x=œ€Ü^N¸ôlsŐ7Ţ8f_˙ơdq홖Ý{ďśč'ˆ›:dQ4/1žőýRj1–EműĹfe‰* §Ń‚ěäľGn‰ýuR>Ź3ŠXŠÎJKUűƒ˛NÚ˙ˆÁŻő‹ňVŘhŒ?lş> JtEłÍďöd„:k%źĚÄZJÝCçÁŔnEPŚDŃdčVIEoS Ó3œň]´ĹĽ•𒛜ƒv‡Ó‡í6„‹Ňb`ŽŘmGovŔââEâ_ÇđU°O!`­T…{>ŮW._ą§ž~Ńîźóˆ Ó:“%\OXÇ'ŸzÖ7˘ˇßv &i8™;mˇ9ä ÎžÝ;ÂËmCxYołď%€ §íő7ŢvŔ—ÝťwÚg˙Öăڋ‹ G %N>Š%qŘ!oC՜ŒZs:Ú0L,Ď9łć9ŠŻů:ú;'üؗ<{úqÄN­ĚT1 Ź÷4w°q¤hş^@J™0`(Vě6čH #Ę˝ÄsĹ ‘č¤N‰fHĎM?äţŁÍ ˆ„7ĽŤ˘uKF÷a( ŔQ$€ÂĺEá›đÎ$ęČF‰çtžúł™’ĄG9|G=䚡ş’ôH07nř†=Ţß{÷îńwŃď^xń…Đţ™ź‘ԝ “_ŔEľžĆx)üüm #_ůƒĆ[sĽ!U4îGM]{ËíaąXŐ[Vm}ˆL_yýďŔ:šăVśšiRŻÝŽ€$•Ó<×eúËŻíšl›|řQŚŞů§‡M”ęnŤ.Ż<Œý˝÷ŢăŔ4fH(š†EiŸhźË…`Bs“qÎývŒSŽS(d掘!ÜŤ¨<Œ;g8”YşŇ1WřzQGʔp$ Î° Ő/ůü!Éؘő˛… ~ ŔB™Ě5ÚIšy„{a˜Ń˜e\[FěP¨wš 9Ťî:×Ň }”S?D‘ţmGÚ$Ź#Ü'÷a c—î@ríŐ5fTŚöbŔJOI*eÄœ°*•ŇE‡5QŒRÖŽëf$`Ďýźďű1e,袺 PQÝĽk%—č둮ËŇWľ6žĐc˜ŁČôĐK•߉ŚÓqşŇ˘Ö Á˝rq†Ĺ“ůvŐDţQb^Ÿ°pŤé€{ĎĽKSvőĘ´Gƒ™™ˇ}7ě €ÄD8™žđăH9pŕ;pă šÎn˜†|  +cĂÄzt@ňżúŽ 'c÷Üu[xŠluŕ†SŽ{ď˝ÓÁ“-[7ťŃĎI؅ómçÎ-žëââŠmÝśÝ#˝řŇŤŔ’yăÍwœ9r÷ÝGč˛#‡Ázű­wěŻ˙ú{6씆!W <Ů0ŐÜôíŘľck^nś/ýĹ×]ě–>?ú„ő™Ď|Ě_’ŢÁş™ÜČF|$ş…Ă@Ć<şMeCĄ_&6Œ'$4FZh%Ëź*v`Ҹą&ŘCYvW"ˤŰĐŞăłk@šóř„ u@DöROŢ>qŃŢ9yÉĂ#8‹›ĎÂBD% aŁÔ´ňDęvŁkX ÁíĂ Š0˜›ľĺa6Őc.lUĄ­“ÇaĚŔ5ÎzJ!šŤčˇÝ°Zކ=% F{ťź“.;tą„sB<žľĐgƒ9ľÍ:uXä–.ş Ż‡ňöE`$˛E0B[Š<É@Jx(ÜsŁQTF7°†mS€Gd€‚Ž6Ż,gp%ŇíÇb´ŞâT0_^k3;Hƒ4H?TŠbŹ+yăŃĹff‡˘ô°éŔpâGá%P)°!Ž• éĄü너͇NÓů^Ž b°(˛‰.äAŸXžÂ-Ëđ$~¤Ű‚quâĉ>W ÖkňÇ(dÓ#J.Ŕ‰32ĚŢp/Iš|ƒƒW E˙ĄňĄîzeY…›Ś ŽQČube"–á˝Ę÷ŻźňŠ˝őöŰąľe Zl“†9Q€$%X˛ _ü[œDŘűšÎŘŒňߪš×ş}Uu>Éď†\wËëy˝FůÍáRz×ő˝G̚>éa{öTĆV+}í­ÍzűˇżA}čQ~‹§÷rľşd×T`cn޲ŮĆÂX`cž1f$ÂĚďb11Ä&ĂőŒń(°ƒň‡ŇběŚ0NǸĚpŻhĺV(`DĚiŹ0‡Ĺ(Jţę_Eę,¤ŽŒmž#ą]X'ĘđČşOer˝X,2ś¸žˆE|G>Ź9´•y'Ę ^bń™ćż­Œ„mĎő‰´1HƒôQOʏ‹Š!D‡*$13řŒuGŕ†ć°ŽŔŃ/+PVŕ{ "r’žJ –”,=-b’Č G.ŔĽnu*Y,Š˜Ć÷¸Ež_yr'V˝KĆM^YĚÜRĎĺz¤ëŞ$vIě :Z*"J‘¨¾͊źÓ#kĽîŽúŠRVGOahĺâďM.AéeƒĄM?vœ ^ŇP,Ăç'ß=çvŚŚçěĆ};ËckŘ`&×ĎŹaŇD öťöÜóŻťfČ=wą‰áú ›™[˛ƒ„¨IčÜ[o Ékvăţ=Œ`ƒ:Ŕ“m$šÝ~ď÷ţŔć˘îëoœ°Ľîžiż:xƒłSI`_|35ź ď¸ýÖp˘ą×ő3ĐŁ9pă>ťaßî„dn´ yŢćműó?˙÷^˙ŰĂőÚţňg?ę4lŰśnrŚÍX¨{ťĹKsgč‹aQ¤eŇŔaŔ­[7ęě“őă‘ÖCUśł8’?Ăbď…&Jt*Š<źą3BjKϡqÁɤĚȞnÝ.ż6Ţď^ś7_€ĘŹÍ`ezf1_‘Ţś´źľ?ę†UĄMHł!Éhg>SŹ“ŰK=îívŰz…Z„śOǐɣăD0$2:ÄĚh%—ÜĂbxaK‚ŽĽöJ7ďÝ"{Ş›ďĎni‘äQœĚu“ĘlhFSי+#cá¤k誌B=+–űżňyC/GPqu¨ĺ:łbZŠŞgÜľX˙nšŢbľ¤…‹Íe;€(´™ç5ćýn˘tůBžžĄ0VŰ Ň ýŕőňreǎËî5œŘ`hIĂ@cˆČ6\ƒČ&„ľ °C';rÚpȟš|¸Nš,ráá>X ňż&o60"tjŽ:`ˆ),,`†6_lŽpĂPÁĂŐAĚň NĽŰÜ8­'_‰ę–ŽE:˝×‰8×P&m8pŕ€Îß~ -v F%ý¨Łü´Šä>ňĽž|‡–ďzňç]űmˇŮž`dŸ8q2ěŢÉ5˝ŕ"n^­b‘Ä_ÖݜżZ˨;t˙ZŹŞęäSŽ5ą„k˘-˝Z(Ő5Ę+J^pôżƒĘĎúÁ”x¤Rĺňë°´)í˘žXsŇG%0SŮęHLÍ@Y ĺUç=Ď˙îťî´űîť7ťŔ ˘ĚżŒ_Řară‘Kó‡1Će|ÉíŽĎől› ŒIéđ˘ë0öď$˜,ŒqŃÜedČĹMš-”Ł”íöď¤$هú<ŰKĄRő™„˘ŠŤŒ/i Đň“†="sƒz~ěcËîyԗďY›č¨΄}ĂâŹ Ň Ň)Ąe)ögM§ÔMŃűľß­FkQ ¨°č߯Ă"ö׉m*­’˜ bŒäTę3)/~XGthSžU/š;şˇĆî ˜”u—ž?bؖnÚşŚd߉yť&Ŕ˙L×T‰Œ…†9 Ą žVK›„tţÝŐé`ŔŠ+îŠť#´ŞvÔeiľó IUwÓ^ v<ęł´l :pŘ XÇĺô.Qžffçlz*œ|MÍځýťâéTŇרł1\Ű+Żži/źřŞ3UVVýşC‡‡é„ýúŻý’żwîŘć.Dľ ˆţIűöwžň:ěÝťŰĂ$łIűß˙'żmăëĆm{Ř´˝ţĆ[ö§_üš˝÷îI{ôá{#ĂexĚ+­tęwĂ á´d[dśÜyÇÍöWý={晗müŃ(:Űn8psäČ!Ű´y‹mßś5Ôm!hžD*Tí ĚŇⲇpf --­8 ˛aýx[ö[çý ‚VŒ‡ŰŐ Ô†Ć˘k•3&ÚĐ>gŹ“Âôv2›ĂňŻdĄDƒ=†:ćgjjÁĂżřÚi{ýÍs6ż¸d ‹gĽ,-uœń o'†ƒš4€çÂŔŢýYľň´ĂÄ̰&„â:ŠYťO×ÇZ7Ü73;ĺŽO¸ś[í 6T™}Ç.WŒAú>öMÜTǐgUňv×fb5 ä‚kŐČYż~ę=í֔UíeŤ†Đ^Ůrš?S!ďĐ×Öupˆńán:°ÓM mic[7‘°|Ţ%ahiÁ8(Sá-“Šm”ŕ`Ƹ{!Đççü_Ć)쿡˛>*éz-źƒ4HýéwN8C  β!ÁP*]qx˛ů`Ӏóä“Oş!„ĄĆç\+ş‡˘xp˜(ÜËŚfĹőĹŽ¸ńG>%"ךë(ô"§Ú\‹ůÔSOůŚÍÚÁçŇeáwюy•â¸ÔƒśHs…21$ľ™ôő:E"ĄÔW†%yœ`ŘÉíAť^x!ť7ŕBË QŒ€ÖcÜȏh/ÚTn †ó÷‡ú]đS{ Rę‘ę>`ĽŽ•Ä É0Cm=z(ýřĆ*ćH-wŸŞçš’%˛ÖҜ°ˆřŻ@‘XéěѧUySSnmÖ ­bŁT˝ż71{Ęë"ˆłší’€!ZĺT7ý”ş'[íßzX+…;%śô}÷Ý•ť›ˆ|utŮaÜ괖ąŔófěŽč$¸ AŽ1ΘaLĹ † Ŕă™Ď™SbR1Ÿ˜ʏů"”ĚGßćŒhěÔKŒ1ňćsňá>ĘÖ|çZć߉yĆ=2Š˜/e$ ’(ő”É\ ŢŠ*$ş>ý@~$ćsˆ{ÜŘnŰ߄ëä ŇG5šíŰŞz´NôĂ|( ¨ŤöÄwŸ´ë펝n ůośőëĆ<|ä{§Îڟüťż(xنMŤhĘ´y~~1Ôi*|†Ďěfť%'/źđŠkľđňhřô㏺ŤĎŃ[oňč<ăŁ1Ęŕ â{‹KË..ť´ ^ĆáĹLčä­[pyšt Ą=†V˘tT=Ç\Q÷ •ÎrIŐí.¸ŃŽ­X]œŘĺÉä=:ˆË^źô݃KL˜n7oş˜>yŞň$Ź›Ů*u5,ÓËâuČĐââ ŇÖ(ĂnŘ „™é(Şčełp9›Äi..ž]Ő*gşÄČ;]3哄w[ú’NŸ8ůÂąě@ƊÓöƒ;ŐXÁŞÂóh%đĘ}ň"RPľ;ü>ă€K]/; äĎŹÝÎŽU˘oŤż<8i1$¸šřÔŞâÚxvŘM›éR…[›ö–/ŔQ ™–.„E|~îRçÁĐY?ü‘‚T"Ur9Ÿ–ŘÔŠüAŒŤżéôÓ\ןĹţü I§Ee˘msŹ-ŹIlnäÚÂi0›'1;¸–Ď$T+÷Řœ˛łńŕ>jœŐé @ɢť|ÎůIťŒ-šç ƒŔŒCÖG6Z”)ý1h8eâŢawß}ˇ.—#Žă•#Òü¤ĺÂĆJî”I}1fĽgÁĆMm—ëu m´ĺsňĄýr_ \KÝřŽ|1ůŽëŮěĹh|-{íľ×ü‡ňzč!˙—śQ_ęÁ=ôů\!Xg̍.IņM쿪Ÿ…ŸňŞg^÷ą\˛;NÝÜ×?â ŚîE_z•~–Ćęßë2]ŸÁ•:=˝M]Ö˘Ąą^@%]­<’óoqVÓŰöŚŢUOCű§{]ö‹W]zbbšD7óę,ž5ϒ¨>ěÓŘ#ĂüM>Œ1Ćŕ"ăő‘GńšŔďšü-Ćó‚q 0AŒůÇ5Œ?Ć۸ďᢝ×jžF׀š Ž0çĹH(!ż‰´Çdnźˆ"°S§Ň´‡:R/ÚĘ:RjŔ\")÷!\K™ÔőŘŰ'l´˝hŰ7_ŸđĽƒ4Hő5HFzkĹ$cĐ^ †Ő€ ž´(Y %" D :1OHĽ Ž˜žŹ % R–Éu¸ôň˝+Ä`˜"† ë"ĺąö˛žŠěRK…śR.uCślƒę'pI N:şç°á'œŞđyUü­ß[Ĺżúi§ŸĄôƒĽŸČŚO˙ć?|đB†/ 0ѲllŻ C#$Ša:73ĺ B\˘ć§é9ş iG1O@>mŮžĄŁ'Űnź2N"ę×rv@Çî=[íŕťmß ;ĂËg< —Ffš,Wí öU{íőwl×ÎíáÔjO¸g‡°“á!ďÜąÝŮn衪,űÍo~ĎžúŐżň0Í>pWŘŔíľ…`´=ůä÷męęŒýúç?ăB¸““}ďÉçěË_ţFˆ[\č–5 ÉúpÍbž÷ÝďŰÓßŃî¸ăűŐ_ů”ƒ:ÔonnŃ((1â͈Mnœp ĹäC}psiÂ7V›*X@DëaKâ.=+wę&pÂJ=kB˝kšůR؄OÍ9ˆň̋ďÚš „7î:؃ťĚ\oŚŚŽú3őPÎ Ŕęg óDá‚ů1YNMÝ[ÉŧJĄ…ľQk"HՉľĄH=–€“ÚYňŰ^ýś¸0ď€?1äqr12ËîEŃO/*qN0ŢĘ(@Ëî_iˇ°`xŇˆÝ­z¤(; œŞ’.łąŞśVm űĚÉPV0zZWy: ÔI‚ÍiAŠZ˝á›Ĺ$2‰`‰‘ˆݧvŞĘzú+‚+˘Š7ťĺ¸0.{4Şuc•ýę§nłÇ8ěc1jď ť^M¤V=e\ŻÔo ĂÝÉâĆx̕nk˝mܲ/źŁ=/*Ú@tA¤ŸT"ě;V˘Ţ6ôÔȌ<`#%עl(Ä}ŸďxO†!ց l¸0„0$rU.|NžŇ‡Ë,i™I“˛0ČJ!MŽyóÍ7 ňŘcůš,a8pŔ'OÚŔ˝Ô—2ŠL•ô‘|Řë:†˛|ĺ•×Tş€ëÔRdpöŕU°„ Şň{NJőą$żĆŘé9ű°>`Śn@˜ŞJ2ć‘ĘëĎă•?Ť˛ OYťŞ`¸” ŐŠ'/ąHŠüĚ vMmůł~1\]ˇf*Ŕœ’őÜS˙*şą=öč#îęłÉ÷ćŕôGäVŁhYIФ1ÁľĚ/@8žżőÖ[}QöO<ác°ŽÄ‘¨"÷2G0$¤]"@9ĎŘdœ2ÖŞÄŚáw‹Ô cE‚´4ԗ6đ™˘Ewçx’-p†ű¤˝$W;>GóE@Ž\ô‰RD˝h“DŸ&{™`€62€$yáüٰůŸ Ŕʲł´Zö¤ť/¤Aú›N‘Ą9m˛=äŢRFühĄëĺ #w>EŰšč˘C‰Ööł]”§  ™\†g¸!Ö)Ÿ—nA:ŹŐ5b¨(ʏ@ňZľWĚúC0Ť^r/–ŚœúŁß‰{ÂZýHh*ůÄc†ł’~:é§[üÔĹż=gĺ#ęfׅŠ"ĘłNăM‘eDᑋDlct"M§łě÷nœÜęĆjˇ p°Îăřoš`k~°ÝĺD•ŞlnaĹŢxoÁ.N ہ]YoyŁ´ —LĎÎŮâń%ťzeÖőVnşi݇TJŃmâ)Ő6ű{˙ŃoŘ÷Ÿ}Ůžđ§˙Ţ“łç.ÚM8cĐbaaÖë8ąqkŘéŘĽ3️ö]wßf÷Ţ}{8ٸŮ]s(c> ˙âţŘţőżý˘=ţ‰‡m[e`iŔRԚ錄š'lÇS|îˆeŘżÇ}ä>űż˙?ţßާwÝuŤŸŹcä1hűś-˝ŃQy1¨Ňć$‹´ŐŇůˆş(­ö°‹Ł.yDˆ0SŘkm˝ňiVm1´.ϲV¸­0ŕgíԙ+öňëgěű/œ°ŤSóĨc&îbâÎĎ3!ŁžÉŽ]{űhÖĂ4ŽĺÉ)áלEUęŒ—ŇiS;§Ćﮕ´y*÷IŽa˛ýÚŽx^á{Ÿ„iDžœş‘őD(a~ˆ45u9LÎuŽtăŔŒˆlŤĘ‘y˘ëZËݚV\˜i)ôႃcăH™œÜ’#Ń R„ĽşSřCĘ˝(ŽăN 9 zž>Ŕšjuk‹­Ô7…ü.…zΆçR-Fž˛fsZwŁ›OܘĽřö pjšŕm+őAšŸI7níŹßRůřŠáŠ;ËîšĐué[żaÂ6O†>ˇëť5úÉ&R×{Ă7H?éZ'&|Ă˙ś˛ŃuŻłÁÂ÷Ş”P-,ŒzŽ‘ ,ů.p=` 'π/€:ąÂ¸{ýő×MâŻäI~Ť•H§„çŘÔpÎ÷ä‰a řńšĎ}.ƒ;zŸS>mŕzňĆ8ät×Ţ ÜËk+FŸŒ4ţł†śÂ`aŸ ­10*šö÷Ňnú‹Í$?Sh8ęA0‚aŒ"Fű•Ż|%oÖȟľ—른Ŕ…{iueČ5”Iß|“×ĺŰßůŽ˝úęk6;Eţ|+S>ë ŁpŁ)@”k3ąš7ň5AŤńĽďËďńôW7ƒ;ĺ?M={ď´\_[ŁüşnŹř,oޛűʨs…´‰nU­žď“,Xř[^ Rĺƒ˝ď…Yą‡ŰĆíÜçă\cR@ÄáÇýžK^űMŸW űÍsglI˙„qŠh>ú¨ƒÜ÷Ĺ/~ŃYP°ľ+ŒqŽ×fP?Ą — PJ}ŠŔ Üí$R-…ršFbŐԉüŠ kó‚{öďߟËÁ•PŔ‰ÖĆ;ůK;†uƒ{iť„pi§Ęę DUi~lI‘]€H­ 7L’ŚˆôNXG$ś]†JÖ!†tXäÖŤ0ČÁ-ŻÓ>@,ţˆ;b °fP.ë‚@޲\1lxŻr?ďâľ"ř(?Öň˜­üĘúÉľ) ÍOxšbĂŞO”ßuy^vÝR4^ŐN@ŠzÉŽFú’(îND—4ŒŻŰ gޒëÂ߁SÓW@˛ŢÝ~ZněFƒŃÝ.şŹŰ"ĐćŇŐť2˝l7ďˇ-“Á¸oǓ’vˇ˛Ľđň˝teږ^_vVʑ#ű톽;=´˛Đ.(w ăř˙֎7 ŽĹP)w ҍ;šiÚślž´Ýť6ŰŢ=[íÁűďHz „,Hŕ萇Kž˙žŰíŮg_´ó/ŮÎÝ;ACHGŘ\;5Ĺ:‰í´Ł@ڕ˗l6œpŢîE×ĺŕ}Ž÷"=”~aŮÔíÍćÎ]GFźcŹNWĄŠ[‰†”(UB3ł&Jüwy ŮY{őłö­§ŽŮĹK3Ćč| ŔfωNLÂ͛ˇ{ý„@<đ,q˝šző˛ëœÄ–xŇ$áWňŽŕʰ˙usVz6U=čfOCźÜŃŕZ/IŻGî3žˇYdž$Ö.@üĚhţJ8ů$\čđˆŸhT:ę…ąłč˘Is^ŢHbˇŹ_żĄqGŞ#ˆHřjŠäSÇA‹TńÔFˑ°dř€zv“ËQŹC^v>Œ‹ ś´Nv;ť  u¨}1ü5h"ŤŚĘ'€ÎŕT˘éĹÓíÔ ŔĘ,›nÁ"ęýť§§ź~ôÉää&>ZÔŽmüěŚ˜2HS)Rjǘ`S$*Ť"†0wuň-Ŕ‚Œ16El@0 ™żl.p]ŕw@Xol@ř\a˜ ŘÔđ=§Öra3Ć:‹FŮ$ć;őzîšç|S÷kżök>_¤CB~häM˝ČSë ĺ’uŔÂďX¸çȑ#&­ŽŹŔᏼÂZFţ|†HšŹY|V˛Ř° ˆóCÐ " ú‰rţŢßű{ŢÇäř/Lęsűíˇ{?'śŒQ€$ţU}Š…ž˝íčQť#܇vŰ3ßÖNa|&€JCÔśŠIŽBV0 •V3Vꞣ2!r7m.KHB/=¤Čłw[ĺBTÜÖľ>}–Ş7Ç~֊žÓ!Lá§dŤĄ—"żşqŰúÓÓîşi–ƒ0uŐN6LĺH ŠŸł/Úžc[x.ˇú˜P‘Ř,sŒgNâ™ 1§#ő˙đ‰épzO˓}ď@Iěě(ÔŮÎîCˇŰń>ÄlqľŮşu2œllwÖ Ž9CÉ ,€0ÂCúÎĎŘW˙ýˇœŢHĺ›ož)źŒn yFc^..,;„Đ^+ öóöÂó/}ńŘŁ÷¤ŤçMhgţcpüńŸ|ٞzú×s9tčĆČ,HîH„ž˜XoŁ#1BRŤUœ1őmŒâ.şô/fyi> 6 J:ĹŞFЇ9öÉĄéŘüâ˛]ž6Čçgěů—ßľç^:e‹Ë‘IÔĐ)“ËË҂׆—:BĂŤNeë:˘ &ZY7-܂ř ă]~%}KĎPš,rci"ŃX-LQĽčżZXf¨ÓÚ-étŇ8Ęíh077ă ęEŢhřŔ:qaśőŽ]ŇßN‰Ęf_ž”ˇ3@RHčüÜ,şů&6őg‰|žt›ągqĂXy›ÂÉYk‡Ž´+60ó>ŞŞw<ô¸/ՑůăŕĘĘrŢ|–ŽBŠřăŽKĄÍ퓪qő) [UÇUYŔKmŤé4%ÇĽ—Ń"JĘQÚ– ÜÄúľü=´ž7ڑ›gcžó†gǸdĚJŁ„ů Sž)ó °Dzć–ŠXřœqÓ vÇÇ?ţńě†ĆXä~ćĎp†Ď(q"v–Ć ůˆy&ŚăP:@ ď̤žŒCĆ1óM§¸Ô›˛¨;ůpŸGPL€%esM­KZL”ůÝď~×;\Gš2n¸†üšžœŰ -Íu€9ô1ßÍL‡úNą c6p˙¤AúSd¤ľńśŐăęC*#í°N(FéSşđ”Q{ú]eĘüúÝ}äŘď$ą\Öi5•Ń‚ĘüX?aóąž—ŽAڃ ’űm)žŰčg6y˛V’$âÝߖŇ=ˆß}ôя†űO×#ňP˙ʙ(+iÁF°†‚|ĆIĽoqÔÂHŽ Á>‹!|;îzŔ˜Ÿ›uŚ@ŰQť`„vŤĚZ‘ §ĘŔP˝4Œ…EŰżŁm[&@Ó0zk>ffçŁöÇܢ‡^>|aăś°$ ߤ (rŕŔ ö˙ňííc'Ăn6ź°fěŕ{mĹY‘Š‹÷ DiˇlŢňœą§žzÁĆF‡í‘‡ďśu„ŹŚîăś°Řľ]ť˜sđ_7^\lÓäĆpmDýŞVs˘Ól”šš9,p5e–—ŁďÝ }’űÖüŔ€‰B}—Q–íĘŐ9;s~ĘCżňúYťte&M˘¸iYNŃb¸ă:Ą€ ë(“BôŒ†čŁ™3)†źz>°<âó|q‡_ĆĄMUÇ+oA;âz'„HÜśŐĘz#•äŸÜjťŰYŢ×ÁIŒv*Ď;EΉě’Čvň¨R+ß4%——ŽçÝʀIŹů°[ ĚKŒňŽ#ăF MŐjü őLYHl˜X}|łěLX"‚œ ߍ…•€p¸‚ˆĺ˘3œŮ!şkŐŮÎűżn˘Ëřź˘Xt}ié§=5†×ś™ďó?.ă@Ź2Ńő0``ąi ážç36RĹç=ŘJ뛎yĹ â^Ö2NĎoťí67°85‚-˘“ …S”Ę>ŕF!!D;eœaĉŠŹÍßq2OŸHýŸ$×$Žă>“Ú QžŔŒF˝;U…ţŚůŃ~]#Ŕ…|ač„L§k°D&˘~?ü°Ĺ$ů‘Ë5IŃ\čßßţíßö<WžöľŻy]l(K'‘…šŮY3™2€š_!˜˙ä'ÂAƌ?vÜN>ăŕnťž–Zbj˘÷€óU˙ ëYęjFU*3ľ›uĂ*i@ŠüĐ~˘Jë}vÎYő‰ęö$Ź>@)>Ďy­f7ĘĺťEľ*՚[ŞŕŚXřĂŚÍ[6;Óâč­ˇx˙óě˜K#PPz"Š‚Ĺؖ€, ƒDĽQÄóf|ńŹů V?̗ßú­ßĘľ2ڍ€ĄôKřÁ¨xć™g|^2Nj2؏ô ř[F…jňœň)ůDݡ0Ľ$I°"í#i (’~cW BŸ ´i9S:ŇéĹęQ„Ú#đ‡1OŇÁ yÖá`g~ş<¤A¤>1Ż6lXż |P$Źu%KD€…ÜnjX ¨ŽëwRT2~X+Äţ(AąOÄ´cíäg-‘YŽă˝ÍúĹű“ľśżěҕGëkmÉ´Q[Ä<ŔËú¨wr–^ ×é`ęz¤ëÂTyřł˙Ç'ڧg…‚ń­°¸!uM‰*"KŤ…Đ⊿˜ 2˜ýß"Ť€ˇîŇR|¸ŁŁă…xŽš/ši˝ƒŐ˜ááČZŮł5<˜učťDśJ<•!nÜeű÷ítń×ö„ăż|yĘžţÍďŮóĎżâz(°O˝|řđÁŽě /œ‘´Ůňśń˙ü×aƒ÷ź}îW?í×iŽŒ„SźᗦK˘˛žG!°˘öÍl”œ:i“Şz–§:ęú…ŏŽ\ľËWçí܅Y{őÍsöö;=Üq‰…%äşI §Şb¸ă"´•Uń,ë‚y!ßgš•ě’’-˘‰C_thJY“şăîF˝R,ť•¨Ć  a PÓɛ(ÉÝĆ*18šÍm\I0!´>>="QÇ5W tăžłJŽEq_ŰJ<ߞšţ/vG'…obÚX1Ů"()pźŁl%ČR;K—-ók ë˝%üN|Ł0×*Ř&‹îVÖÍaŻ#H$@ 0°iÔˇGr6bÖƒúę{š MlľO=´ŔT¤ŸÚÔŹy˝N>>Ěsn63˝@¨‹ž'ÖÉÉc-ŚJúÖç§/lřN'5§cc€a$:>“b?Ÿ‹™Ąp‡$`I`R§Đ´#Iŕ LŽUXňĆ ÂhR8Y’„-)—:*3Ÿ‰r,Á:iŞ/÷’Ÿ@ I=ŢÔi=÷’t˛Ćučä3 I×ĆČ͈6Ňvڂa čDńßđQ}IŠž˘(I˘:—=ÔYmĹĽOäN¤M'eQśęĚľrS•H0÷ń|N÷ÔŠÓvůŇewЇu‰ô(iŕŹUÖťé]żŚkN?Ž3™ZEV=ŔcdťÄďłźmqMń¤ßŽ.Ŕ5Ë6ëNVłXĚŢß0oć c†gxôč­vçwř{Ď-‚ç"˜rŒj 0v¤W¤Đă/ŠtĽ0يNÁřÄŕv‡6íúNú#bJIďHâÓ ă͸ä{Ɔhó°`¸^Ě ;Ëí<57ĺÄ\`NPąĹ¤Äý Ő, D'ˇŒu˜6Ÿüä's?qŻ˘ńCâ>îPŠą-0JîxüŞTéPí ҏ)qˆŞć%X ÷$˙ XžˆÜ‚ts›5NőJý’Ŕ SK”űZú)râÖĘ×uzĎ ĚhFżŒw/ JŮĽŒĘć˝,0GL•˛lÚB›"ŕ´aMw(ĺ)í ëúGƒŠ‚ş´ŹMAtăˆn-ížSůĆ@ޚ“ âÄŃ)ĘJ×qF›‹vËÁ”•ÁŒűTU–Eó´UŠ.áÔějł[ÚśiCŰ֍"zË œ´MůB;33~Ÿ Ź•ÍîâcUtÉŮ´iÂ>÷+Ÿ´›íłoçé€ŢŸvÖĚŚÉ Űśe–ă Ůŕ ˜ůš)ť˙Ţ;žŢ™*Ôkvn&3j˘qÔM GÜŠJŤÄÝjŇĐ{ŠďčTŠžzîM¨q…Zî4×@LěîϋVk1ü}.”3ZNŽťŕ™ aƒĆČƌGI’Č.őĽ íö†4Śz7éUĎó)Ş*Ąş›O6L•AúiM%´\ű•DS-i­×JŃ9n:şměÜ~´G9˙Ă&Œ3"ŁąIť‰DWËlŇ7`Ó"a[RÖß҈ŕ36Zü[jÉčtžüušEž´QýB;1ˆy&œÄKsĆOĚëčż-ý 6rR(iň= ú d˘úD`”BěrŽIÔ†ěڄŞ“~ą´Á•;u:pŕ€‡ăĹxĹЧ~gĎĹHDsłQĚ´ťÖšÚ7Ś–Fśä5üĘDěĆŘlňŽW]kÖk ËmÇŮĄz§”Ż×0žŕ’0IX˝dŚä*TýŐh>` dl^Č(‘p-cđě4â^%˛¨¸—g.ˇťRXVśČqK|ÎxCße@É˝M‘˛ČO'Ěz?s@5§ôcu€Ď"Ë6şe3îč›|0—-́Şr?˘,šű ĺZęŠČbôlXÖžŠ°Ąî\ý‚A¤zb-0ÚVÝĚč`=`î‰Ç”v‰\_=‡šŠőInŹĽ+ SŽrbéIČV{)é¨(œłBľK݉T–ÍZŽý€[Ę/í?­łľ%ŔݞË<ĺ–)[.@ýŇ*_bß|Ç}=ŇuŞmŔ’l\ăŠaIë$—” ż^l‚tŇŢj5Ź•xmă“ÝrF­Œóĺĺ(މXiť%jSţŹe&˝ĚCţ3óáAîÚĆ ]Űľšm“\ eń€}3=Ŕ•K—§Â‹űFťaďW<”ĂUÚwŢâŽ;ßúÖSá4ëMűţ3/yš7ě ›4Gëç“ęˆÝrËMa{kĎ)eŐÓUUţÉ'Źîö„;˒$2Peq3âmŞŁűÉRQpçš|e΁” —gě˝S—í…×ΆĎf2űĂý”••ĹȐŸ!ÎĹW'˛ń: ¸_EVoi|["pŚŞ)~ôąGíŕ}œ*,8c”gD+z–…c$Âů ĘŐL.eüřáJ¸‡ď¤ ń¸;…1Ľ{SšV.yŇháůK G 'y ´cü‰uBü˜ĺ:ľ# YŻËtzčĘí‡rš'žăŤ<Ďh;}B>ĚĆ*}ÁŘă~%”A^2ĐÔ~ą]˜Š &=Ú§ľ…ëÂĆĚÄZ¤A¤=ŽFƗŘa’D`Ía–l’@  ĚÓ~wŸ*ŮŃhtđĄ=CéĆCŇaŽŢ™rM”–‰Ę/AÜYX/ĹPé×[)Y/Í-ŁšgBŸ+ŢÍ´ŠŸő"0EŹ>1ľ_¸éú€*ľX ]§J{Ş˘;…ű‘Ću/´“Ü$ÚĽ#ľŞĆđÖ ]/čřĐÖšpęRBĎÎśŞšÓœNb<Čú]âäíRx¸3•mŸś][ĂiŮ:"ŐΔ™™Ţťh ‹ËŽźqOxX›|°űŔ yŇř—?ű)ťq˙ aƒtŢvîŘ6ƒÝ-ŕe5ýQ-mź Ľ9]G—ˆ´X°Qjg2˜ĆŒi~!źp/ÍÚŠłWp2oWŚćíݤœŻżňyľ1KŔˇĽţĄOäVSéBRR˜ű?ű°y–÷^‹ů#`Żťô÷Gé9ôťčô׏ŐűćĄń)O,5˝ěË$šýZ€JřâŃdž>üŤ•:ŕöYn¨›ŒQ|1lbČPăšůh@ÝšW Ÿh˛:iâ3ů2ŁIÁŚJ'ăŸ ÁŹ(?”Çfđ@#y˛ŮщIş.sj‡…—-Ă:–÷ŠůÁć€F}$Ł™öňŁr1Rš–ś`¤¨`ňš6‡€3ü^şAIOEIPúNşb0D—ßŘWŇĄá:žťăŽ;r´"úŠëäţ$—ő˝¨ÍÚۡ_¸˙vť4=Žż`/żűŠ OcúRÜÇt˛ťsÝËHMďťĚPŠëká×LYTś3Ţg¨'ź_7÷ěŤ>(sQ,—şŸRŇógĺďí'ěć°Iżĺ–[<Š"›eĆiĆ)ώçáŽ( Ȓż˝N*ĺfĆu2`<1?řŒąJâoéä(r,#î/ŮGŇ)]ˆ^Ę%$M'ÂÔ ‘$Vˆô}0BČ[‘y”j)›k(‹1Îý ő,Ś–HęÂŚţ6|Fä Ć/ő՚E[Ör/uTšUvÝŁÜh˘› œ•p 9űsś/¤AúI%íO˘ýł˜ßečઠˆI˘=óWaĎľ>‹š+ BŽŤZďÖb‡”ŕI m ä(oąXŃk“VS)Q–_5r!ęg›”@‰BEÓţœ)Ł (˘Ż´ÖŤ/ŻGşŽL•˛c[)2NĺnńÔÜż/摒0řąrx8ShÂćĺŽćG Ľ„$ÄMĺ Q'ˇŠŇ~~Ącď-um>ěëvmŠmËĆ(d['wšłg/…A€ڌťíŮ˝Í#ň¸Šť‡ŒŮý÷ßaĽĐ[ٞÜIĂىĽŃPŹb˝ĽQČďLúmai%œj-Řš a#w8>uöŞ?yŃŚg—°Ýx¤#ŕĎ ‰şśÝ5iĚdœŠKËK馕˜%ŘQéËŹoSUŞR‹šŇ°nä敁‰cŮXjŘş>žô×%ŕ[ŕn^#ib×Ö¸ÉtԙĺíMřžS4ŠMФQ] Ąw<ŞîNăcăţóVü„|9r‘˝ŇJ“żŽ­`ŁTš˙úOúňž–ďŞÔ/üW+ÜuRż^餞ig7Ş(ě4VÔcƒ„¨Ká¤ŘĆœNˆť ÖĆ=¨ZéeŞÔ˝ăU§•uj@ĎóąëłHý´¤×^{=ť °Ą…şć}÷˝ď=i?üĐp<˙ü vó͇ý%ůď|×nťí¨Ż'ďžűžo°éimž'E2ˑ+˝źá†˝?lřYHźég^ˆ<ňpn/Ęc}Ł‚~ÚŤ°yýI/×cŕÉČY]Ÿ•U€ŠŘb~”ď=k!ł>h"ĎčűÜő ÷ `ŕ#ŞŤNĆKŠ\¤Ý úŹ,Xdhr †âË/żě›ňEź– ˜N¸uŠÎ=ň_V$ž'QäÉ˝–ühC' ąĘU_Q.uŚl%ň¤Ni +7!ú@u–[ŽÜřCšúĂN!O…’ŚŽŇœ ?éÉČç^6ŇŻPĽ’*Ź.څŤç‡ďčę\žÚŃoď$ÚE[¸qRęÇƓďÇ׍ű|^kňůąsVďëÚ7ÝgŰWśŰôťá˝~ę´]e“4đ<ś×^Ź}c5}l=ÓĄXî‹%˝ALŞ&ôs?J“Áą\Ö`¤ô–чÔԍǞ޳Ľ¨­UB¨ńŕÁžć>űž¤OčsEéáů**Ž˘ěđ}oi ÉmŽ{Ľ"v†˘LÁ€aœ“7ěňd,3řL÷Ę}Fš{Đɸd|$•ë‘Ä&Ĺ(›KáŇš—rî@ĽKJnC$ő‰ńČ$…AŚ.ëRBŐҎѺ§°âÜG9\§ľ„Ď™äGż“JĐ@J˘•ÓSWb$ŐKé Ň ý)şťĚçĂćs9§ź0§őž—e :čˆ9+֋ÜdJKy­€Ű2ŇNÉNđł•ő†}ëJy`XćÉľ˜iSÉ$˜T:´KĚU]Óď¤kYŐŚňÚ둮¨˘TŒ„:Í-×P0ýŻ0źé¸˜KŽŹ4†|6ĘƃŸ¨p…ČCó s.x S¤ś&Lł¸ÄdýűpÁՙ,LĎw¸2bëÇĐZ‰÷NMĎúf‘×K—ކ—ýŰžmsd­ÄZ÷&Yt%‰†ůë Ŕ°ˆ‰%—”Ô'Ý:ßç˙v›ƒ& .=WŽÎŰŮ aŁvę˛]şN8ŚÂIĘĽ9;wq&L’ĽžĐɢˆG§•¨­#Ö¸}tS˜ßf×0Ţ÷zŃÎů•št*7’ę,–Cóœbë ˛(ÜsŁe{"ťk)bOÝ豔Œ#gâäëőˆ#¨3ž˘>úL/ĚĹś„ţ –Vv—QÔ Ć˙<ĺ‘Ů)M}JĐ +#= …Ž H]°ts$5š˛p#Š ÁröĽß|ł=ÔNĹŚ1šôJš mßşçD"š~NlŽŇü(8ý”›é@2ż.†źWŘ pe‘ë`ŠN°(@E!§šWečޒ,ÝĘVčh~gC&—¨’Ö,ˇ+ţfÓČ˝äA˙q/ŸŃ%°B;i“üŔyڌm"*Q§8uěâ1{ćÂ3QűclíŢoë&ÖŮňúe;€ŢĂč°˝÷ŢŠ°ćœĎš4óDjHl̒BRݚúĹúą5O2RŽýů×´E{fJbĄô섊Ďj^˜­1‡ë|„Ö܎ĹËś?ěTÚkťnšĹş-Ÿ÷uą5¤?3:dč3yŠxĂsŠűçÜ{ňétŮĐ˜Ăł!EÇ ?1łxÜ+wą()…K°Ž{%˘Ë˝”Ă˝şŸňtŻÜÜtăvéŠńG{4NšWŃ3hƒÂ(srŹr¤ßB^Ľ‰kÄîŃZ$€F ‹DuŻ~âş7ĐT¤Aúq$­ąĚˇ8Ł‘( ˝[őŽK2Ű8:0O‚´ůĺ[˛YĘ|y‡k?#WĂPŃľä ÍşÂ! ű€Ň.)E#ˆ­şöç+ÁY˝ íźVč_ąYÔWýýř“N× TŠsGĹ66"Śb/´ ‰|W-Ł–lDm­ĽČ8íl˜g#¸e–ĹA}sť’Nc"Ăbaa.Fr0§í˙ć‡SGŕÂ? e,„÷ÂŮKáä1 –--Ű:9dhÔbdĎÍ/ÚĘŮKFT#„l‚ľ˛Ý6ŹOч<ËÚERWşŮUGşu’ÍL›:n4şV€K7F虚ˇwN^˛7ŸłŠ™%ťteÖΜ›vwŸZŔuc’{Tj te†ŰíĆŔŽŞ¤"‘Ů%§NŹmt†ӂÉ_öK(RŒXÎިb+JăÂĚzĎ8ąK¸Ézí u=YĹw|ě - Á\I÷ÇICĆajŹs}ľC耘! n´şaŠT ŁJU*$Óľ=›ŔŃw˘ŕĂ\YIu…1ĺ> ÁiźŠÉAşˆsć :x?ßIOĆTĆPrËiÚXtŁ•˘~ ;ˆđä ˘R…Ŕ]ŸUظájgÓéű&JTÓÔŐôîĘ~ž€úœS9Ŕíۡša-!Ź+WŽúi—žôĺ°q=€’~˘_‘E7ďsţűŐŤ[Ăuü^D4żńżňń˜Bžbœ^‹ÎfŃlŘ+[ˇnqaÝşxذgĎn{ňɧí7ó?đĎ~Vúŕ–[Ž80EŇ܋í]g<ňýŃýI Őť}Őýk*ßpˆ&Iŕ­Dé ÇÓŘfĚóüx/žř˛I<§ÝťwšSŢGYTĄ 6€*rŃĆC:ň9–.ú­\Rh§\ ä­°ÇXŘôŕš‚1¤ˆ!ôš"ˆ(Œ=c쑸ƒJş.%ˆK>üŽa'Ęýţ÷żďŸĂŃé>u@˘ ”4MT?ň ~b§P'Ţ?I”ř ƒ’aĐ 'ő"?ž‰B8“´“Ű‘hÄŇŃěč×)5VtR(ŁWućoú•>W(HĘĺ^úŹÔYĄ\úŐ}Ö`pöüY{yůeť°tÁÖŻŹˇűwÝo;Çwú˝çΞK˘âc nٲ9ˇ`ölȇr-4=ă‘L\@Pno˝ ¸5얆zR­=›űĹńŹęž;ęş|?6E5݈R7˝ďęć~˝˙šżŃýőht€Î{– ĎjgwĆśľWŹ}á„Íž~Ă&B?ŽŰd›ś ›˘€,}ŞqĽ“T€úCŠ Ĺő<_1Šˆ{EAčf<ŇçÔMM [Ęő”ĄĂé°Vcˆ¨Ľq B\Ď3–řłî<‘ž@sxŘÍQłv?ĺ2öĽD;ř)#„QoęČ}0ŃÄxŃřh#QIé%‘dTąVŠn/‘ZšáiŇ˝.pšŇŽq4iéGN.Üž~ŰŤŃDnܛ5GçpĄIîť mL*]÷ÜÝvHš˙~đ—ÜPKF°_Ďľ PaݔvS?;ĽÔ;ÔeMSTźŇ֒ }Š÷"ˇd íšŐ=ův;1:—X2r9"iˇ–+}ćVKď&ÖĐpíňG T‰)‹s&÷›h€EP énÄ â?ŠŠ˘’&Mň$˛QĂĂ[\É@Md ťqÚ –M/*‚ąö¸™NŞVv#iĐľ`‚Nôk1Baż{K×&'†2ӆş?qÚŚgĄůÎŰ͇÷ŮĆÉ V‡2Wxżťq˝˙>g§źňĘŤŽüĂP‰!\ÇrD Œ\ .(â_üâ—rž?‹)žšÄP˝¤˛-ŠŕŃNŕđű5ą˙D-ŹÓ§Ďxżk@Ówôű:Éčwű9ţœ}÷ťOŮË/ż’Ł×đĚ|đž{>ě źq͔^‡Ŕ‰ÂRžšˆ"ę.kł„Teäđ;ĆáS%ŠÉx’:žŽ'Ńżrý‘Đ!Śes y–eJ—:s/mÁH|ňÉ'˝.œ\ńlK°Bĺ–FŤX7ŠęĂuŰŁ,B?+<,ĎQců‹Ĺ˘{ĺVAÝč?”ÁçÜŤp“ÜOd¤Ó÷b>Pgř P’ ×Q?řüK~°PřNĄĹ@Řśc›]í^ľ—^v0ĺ茣VŸŽíř ÇíÔđ)ď)ĘŠž íŘ^6Ú{ĂÁ ĐnŁnÍĘňŠż Žxˆč)w•ZČꁞ‡aQJ@Ľy—4‡!:ĘX•€JݓwžŻißFđüÜM*Ü´)€(‡’˙ýđđP˘šm#ŕ†u6ć¤]>ńśŐD"<óś-ž|ɖ7n ›˛ƒÖ›°]űzAó°ú W7Eř)ŁRE7âĹ P.×3Ÿ`‰žóIl,jZ˙ĺ¨0ßüÎ<{LâĘr+*AŇrYAé˜HżGÂÓĺ˝ŇGáš)RďÍOŘhź“t’żÜű(7ş–ZfĆ d¤üM˝É“šKR”˛ęąoœ –ç/˘W;Hƒ4H?bbýóC‡ń8eSaÓ˛VLĎLťÍ#&ŢčبŰFžOJlö5'ąöÖń.ők€*áZ騤k={xw(˛÷ÄúäJdQ~[ćT÷ąŃpcçý4JP‘Ąh—R‰x@ÜÉěAlńÉpÄŽeëx€źíă`š=nsmŹG?¸37?çďöŮ7ŐYĎ×#]PĽńgŞ“;F˘I8_'đ$ž‡$OÜ*ęItóD'F "WŻŹ$††LÓĂiN—†ó ćČHtÂ@Ÿ›Ÿ HÝx ç[¸#ľšđžą>ľ-,…ÍîR8ĄZ˛-ó]ŰšŽVÜTĚ/Ůʚ˞ś˝ÝŢE iY•"•CSťut!´óĚěB8ľš˛7Ž]°c'Âćí╰)šł™ů*t˙źœϊˇ}(íöP\L–Ó< t=UŐ¸ŐŃ(Žá…Sߛő bmD|Ş[°Lb4Ą*RÜP'ĚäÔČÚ6UăŽE†Ítd]tŠţ´ œh°Ë­FjĎÎđX‰âCí4é(ŻjIěWÚ.-ş]ŒČ"ŠČ\Ihe\ ÚE˜ç|r×Ďô¨%ˆ ˆĄžeTeТŽ§Zmąq(m|eÄŽ”-ŚžŘyČ zĄ|ćú_$š)Q>?|§š"‘Z"Ť~r!*Ý 5ÄĘĄo¨ŸkBͧč M•A¤KęÎ\ľ•éóůoˇEx2 ­Ý “n1Ú é(Ř2ű#ěĄf/_á8Ř&śnł!ż6ŠÝžŃ& v× ďĹšY›ÜŢÝh/úľć:¤îbňë,†÷Z¨Űа—]Ž[śwű6Űέ†VŚ­ val˘ńćhN f!ě›6oŮjăí°[šJďŽPJÁé`ýŠăÇlkX7„mI+Ő×ßUU•Y;~m°‹§Ăűƒ† '­ľ2ÓŘ?fé űú,J×ežŇüh0˙F0 •\afHɰĄ“8K.9ÂŕźŔŰíaưOoxčÇŹ“O|r1JŔ eűéżÄX[+)|ŻÂ:w śE7oŕpÓsË6żÎň óÖŽm\?”ŒŞ•(`;…^¢‡Nfƒ\ŐĄL6ÎBűO@”E×E9vň’˝úƙČFYX˛ŮůegĽÄđQ3ŽüńOvb8ÇĄ¤Ôš˝ ,Q4ĽŞ8şI[F€ߡ ş+†PjŤ%ć†ňލhuID…§˙օştýäbĆűnș#1”äˆj݀7bżd—ĄH ĘýĚKY‚ş.¸ę,”f2Ti" dˆbž¨5×PżNwČ 3ňă´ˇňÔMHR[Km˘[U“gtي˘Ęň ˇ\Kú7‘ĺÓn%ˇ/i CĽňôq%íÔ,ŠĂ­‘äŽÖ2 ąMˇę×JěœX^CłŤ ƒNž€™FťG8RéÎÄçsáﰙjcŒ …ů6ć.5g㴔YHr]’űŘĎ °ÂËë™gžsĐăöŰosƒúŮgŸ cë¸y­űöíľ?űł?÷ 94H~Âś7†ß_uđÖ /=Ť‡zŔĂŞŔbT‘Ďţ­ˇŢâeŁ%Â:#ëűßĆĹ%޸oß ?”1˙Ӓ߸M}á _p͘żř‹/;eW\Ž^}őuűć7˙ÚÝŞŽĽ§RĽľ°LQ›`hÍkËÔŸŒüňz ]^¸p1ĚߍáŮ)čŤÍuÎőÇ2PB6Ň8ńÓ˘d˜UĹ)2F3>`l‘řq”\ËuPlňĽ_ ţ•ť ‰űAE—¨ť´_šqřŒ2¨—ô)t/ †Ö.ą;fIV¨‹€ň¤dÔq/›8Ř)|& ˛JĚęÄ˝bäč^ÚĆ˝\‹áG](Gá‘%’§0ľ:í—5ŸKƒU§őňíV›Ő_˘´‡{Ľ{A˝ő\<ŇOxWž™?c/-żdĂÝaűŘîŮśÖ6[YZąwŽ˝ă×Ŕ4P$Œ~iˇP/1˘;ЎĄ‰ç,ÚL¸‡öěÜšĂëő/Öۄč“ţžćÝ}ěřqgvL„{ażpčŕŽGˆŕÍ5çQiŚÂ)çź.îÎRיj˝¸°čnŒGŽÜ6Ę[üţ3gĎDvpxOq‚šú1턳vmŠ7o¸ávom‘xŻXÉ 3LŸÓ6öDćVlqtŇvß{ĐśŽ˜-ĚڅÇíĚ[ŻŮřšcśźnÂZ÷|Ěşˇ;c$ꮄ>ˆ!yŞ?)‡ö>űěłţĚ H`ϙÚŹpÇôudŐ gąéšKlSiš„ă:…§ ĆăVë(î|'Ɨ€>úQŕI9OuŻ^Ԑţ–‹uŕ3…§ŻaŻ1–ůLŹ8 /kĄäŚ'ĘÄŁNŇ´q€g!APeéǔÂÁ5܈ł„_˝tŃş­phwăa?8ÎűJ˙Ť3>@ëKłKśý†n°ţN8磼¤œť@í{lLôât)’ ÁŚŞ—üúů°NźőŢ9j Ůáđ^^7šŮÚcÁF ďĘáp_{¸!;†zĂŇż—í‡nqÁľeu¨můŢącśăćŰüÝŻ˝ĆޖCđÎŰąÇ&6o‰ň}×ę€űz¤ę|^ë÷VńŻ~Úég(ýŕßŔŰaÓcżúzâňĺ)_ˇŢdXËlNaťůw/(z‘ľ°”„r†˛^†˙b,Är(\7‘…ŃĘ÷4(•˝â.-qŔZałá†weŤKťÝDÎĄzăc-ŰšeÄvm˛ńŃVŘ<ʎ#7CÝž`„šyđ—gíí—쉧ßv@ey !lNĐgY‰}°ź˛Ů(DŽ őgCCŠ›Ů‘Ü?î3ffم$ϝ†şP<źVbK”×S?ąHŞ‚iâśsŤqs0h§GŇ3‘ĆÍrz>ca˘ ľ›tmŒJԇUp"[¤ë –\˜˘^˰ƒOn˜¤úÉ­&ƒCil0HjŻçÝŞňŁćŸÎJó|׭ېň_É}Ř´YŕNú&Šß:‹†ëŤć.(8¤çŃn\ŞšĎZ m×O5Q寜ŚEŽăFŃ\܀Ž§ U•˜) ěÉ`R\8Ľă}œýÓiaÝD]#wšřL†ŰÁr{ŲqŁ2ÍE_bŤ!ŸÂ¸E čŠG â2şyă†QűäƒűíţŰ÷¤h4ńů5L›ŞçôţzĽşĘb¨ńč›ÉfoqqÉľIş­őśqËž°žŒZŠŐC;`”ŹU_ÜGR=0ŠľÄŚóŸ˙óßwă…MčďüÎßńÍ/ú äËF€€ç=@4>Ó3ĂE…* JÔŇXô|䋍ŐHłćsú—|ésQ´ů›űVúƒEÂť‘”qÎsĂTčżkľS§¸FŹV‘nú“ŒoÍ鲞ŞW ĆP'ÜłxF×j#ωgY ŽEVĂBf?é](Ác #…GŚ]î€ ‘ĚťAF cŁ #c‰vń×Ęř– &Ƥ" ČP;¤ˇŔ˝:…—Žßc”IGC8F‹Ž.ٞ›ËĆ$×qŻD5ɓĎaŸđQqh×ĐĘ}ë­ˇź-nGŽń|É_̖Řߣ>&O¤‡"!Nňŕ{î“. ůéYˆŢ, JîIôŠ˘%Q6Ć$u•QM$ŕ;ć-F1†2mڟĺbä@Çö­~xńôů§íľŮ×lçňNŰŐÚeűśí ö°—Eąˆz“őxB](‹ßk“¤ŮBýxö´CîHĐb0Ń_b?É]c\âŔ$Ęä^€[€—íŰwřť›1rń˘ÂzG]žŮ /ź`=ö˜÷™\iÄp(6y<>Ç §}|Ś(šĎÔ[ş7SÔ#Ćĺ𼨏˜? Ń˜şr9tmś‘î˛M]ţ¸/şčÓ0^6Q'ęËă3ž m¤/¨‹ÜľäF$“úpż€!ú‡~’ż?ýC_(üł\űäňŁČZĚIîĽ]”Ëó§ýŒOžHCŢüűҝwŢéóšąÄłĐ3+őŁ/ľďăYPw>“ťuŁ ­0ÄÄŢ):îU˝)ŸƒĹéËď`evŞ Ň ýűvć‘"âiΚndť‘ĐZ/—TÖsi‘Ĺč­Ă=ěŰR8–u‚w‰ÜXŸk—^ imž ő€}ÍÜa­‘~ÉPĄ‹RŠŘę=Šźľ^öç]F˘ž.˘?2RH]4őVřdň潣›ţzË;vĎrt—ý‰ƒ*×Ĺý§rd|,QN„Ă?<˜+ˋQ”ŚłbrłŔíc´ľ.łBş.bŰöS:G#kr7‰°Ę0˜xŇ §@ä/,ńŮl('+ůŹŽ ÇH7śœ$K\˛›N cţ‰% fĹЈ˙}qjمlŻĚă˝uŮ^=>cožsŮ.^šłĽ••¤ď_ ŔÂJňećĺq?Zˆžj€ľ“@ŠXź~&&&Ý@ŸžşężWíĽSČ˛IîNɰݭў1ąLşH˘ěNWzĂZ’Yw˘Ö‡_ßYÉ'4UqĘŸďˆSSSWü´–ęOTPPú<ŠlŽOím Ľ8ŮŚřźZ…~IÔPɛŽđýŸëŸÜˆ"’ŮD1ęŚ1䢄›ˇĆ0Ůeœqę&ýœ*…Mö1ԉžá˘özŸu,XC‘šbĄ×-ÜËxŽ ó3ycHřgŒŹč˛äˆ#aÔy죍C‚Íy^N‘Ť*k˘ODđ‰ĹŹJ€“Ć˝L•ş5pő­­qy’[BGLć…ő AŤ=h­Č/žżąŤęŒë˙tíƐçP Ńüs”~1/&ţĎÚý ź>jéýúřƒ€)JË 1ř~ĺń_ P!ůNĄŻŮ¨Źř”×FĎ}'_Œ/ć)ŽbŇJ`كäó6­}ŇR‘ť ĆĐsĎ=ç˙~üăĎŔ0ŽĂD§č$@  s˛ąÂŕă„Z÷JLV ‰RĘ-zaTĘEĂ^Bˇ÷Ô]lčcü Hü–ž'Œ6NÖÉ˙Ľ—^rq[ę|Çwd †r¨7yaŔń#=“ŁGz˝ĽůÂ52ľ.Ro>ă@…*žÝrË-ŮmâřńăV ăJ÷‚~XĂŚO€,éśŕţăŽë×E†ÉذY8cOŐOŮîjˇŹZ÷b×.,\˙\ÔBI žíŚ\6“Ô•úQW1“y% ŏŮg?űYďúúë_˙ş× ă™>w!Ăđ׊ĄŁgÎؑ›îC Ł ł‰:𜤱ŁH:ô!ăŒ~ b}Ŕ˜CŒ›z ě*Ć Ÿóüň ”A^‡öĎi3ă–Ć;ůP?ú˜¤6´gĹó'îeÜ üŁGĆĺš^ČJmë'ˇŮĐŃmâŚ;mĂHxÎďžigžđűvĺľěx{Ł}ę÷÷Cěń÷ëů çíBhëpŞŸ€!Ú*öôJ(›š*ö Ó’Ę—!Ăs” w:ě,Eë˘Ţ´—űDäć&öýGţ:‰Śżš†ßat¨ň\ä&(M$ĘćŮI|™2čGšRŔ”ć9ýɜôŠ€Ă˘=ýôÓ,e|Qś\a¸hÉLœPí ҏœâ!̔ŰOÎĆHëşö偍lGąk%VĎďbŞißRFbÝâGë…DŻu`Źź#ădŃ× Ţ˝źs%¸ÝîcżdŚLbOęp†ś(z`鼢ş—Ţ9Ž+U€/ýyó#M§óJOŢş^tHő“NׅŠňřŻ˙_ž¸:=ADNŢ!BKXÄGWrGDwŠĆˆŒ”Ÿ•tâ(]>óMVťŐčL˜ő¸ƒDŃŕ0#v–úP!ę*ĂCryy1FĎy’<ʎӰşÎŚą”ż\n\¸´<=N )NŰŽ1N‡ý%‰1-]nÝÉ8 Švó门Zd¤Ťććf:…E–.r“iXu:9j¨§+)ꂗ™˜ž‘P 啌ĘŻ“K‚ąQü4…Ę.\`¸ÝŸéŠź‰Ţ¸ą9ůo% Jş!ĐĹ(Ď#Ľłę#}’Ň~ýľ›6äçBÄÝnr˛扞_)N…éfó† ?CňQˆŐ$H:Ž“ÓÁ¸hŁ$ďH^ôňGbÔŠävSE‘Yňh§°ČÝ$6ŰőhJˇ$ĹfgSĽĹú;E?ąoÄ6iNtň­°Üu™ŚëóiżĆuÁT‘›Q•ĆœĆCÉ ˆn[›Ř°Ë~écťíĄťˇ˙\0Uég/é$f-W é\ P)“"v0Ď5•ސJdóýŇű1Uxçđ+› ­släëbäP¤ ik`ČĂX€­€a*÷4k›ÄMš—żËđ•Ř* ƒ#’śŃÖ: / qb`ëôيúQŒ66yěä_ęÍľô=÷’ˇNďi}‰áL^Úȑ'.%|[ ő m/žř˘ˇĐĺŕÁƒţ9"刾Č÷rË0`óIÝŘňĺŞ=ԛűé…ŚĽLú‡zc< x!ęÍ˝b[`üĘ]…ňK׍˙˝ůޛö̕gěĘĐűŘćŮÝ{ďöw;}AůÚř)˛}ĄzÓW2°Š#†ťÜĄş™{y†Ćr…X ]„łŚŢž€RŮ([\Ç ť ¨Ĺçü.ś×ĐnîĹhǰfŒń#ą_ óˇ´AÄ c<ŸúŒg'˝šQ}½ÚX+,§Üf¤"ˇ7>'OŽ+‰üI|/qVˆr]űĆ7žn›F‡lÇxx7~÷ĎlţrČ˙ÎOXgË.;|˙#śa 0Ëö^(wDî“ţ㉺kÜó#Xę,W1ĘĽŽ´U Š„Łů$7B ?Óˇ$ć%÷łF(Bㄾ 1ŢĹ6Łżx6Ÿ˙üçýYhž–‚ŇęT—ß]Œž“‹›tmč71ˇŠ*d3c‹qÄw´—ňTěźtÁŽ\8a­î܀Š2Hƒô#&Ćę™3§ýXLłvĐP†5f^2Gy‡1ĎËëľ÷/ ÖÖ­mEKťV×ëŔƒľúcű˜Ż)ĺő%@"Ý1)Ę=ƒö[ý Çľę^‚$% ˘şS†ęŽśö_݃ęö ÷ŸOüÚ?xŸ\wqU]çî"Ë+‹áÁŒ›„PĺĘ!JÜWQ§ĂęÄigŔ„TĆî.=°R3BF­ QŘűgÖhąÄ{ƒĄź0ď싑D WHBůƒšœ€ˆ’ŽďŔZ!Î2IZčg$ŕŚ1RŁń›dҚiˇÚ™ňm&ŞyŠau§ ˞? *bKa­şÄhˆŔE|ŘňË-ă‘ń‘ÜMĂa(iqtş D'}¤ˆ.šÜzœĽ˛Y*mg¨„ X„|vŔ':Í3ŤBcĄ¤ű7!|ŤäĆ™7ŞcoÍ¨Ŕ•ź5˘ŰSUeąV-0@€ °B=Ľ•€) 9!Ťi,y„’%g̸XďđpbVEpGăÚł“‹[FVM™§qó)ëCÍš[˜˜+ĽëZ;- pÓhÂd Ś[g—ĽŐš*Íxń\b{ĺ<ÚŢgÝ´°ňŒyž¸ĄmÚ8nŸ|pßGĘýáD"ö @•NŇËžyT=›’“ô’†<ä:ôAĆĚľ@•¸Ů‰ íĚLŒĆĄ0¸p-OŹ9Ľç„Cěž{îqcJÂą‹É“vq , Vßä–I;żrŢžsé;ścd‡Ý?qżŐKľ-̧p–ĄžÔ>ăšđ Iԉ|…|K‘RĚ•Ď‹Ďĺ˘A˙JWĂ[ŔŁ/Őbv0Ś|‰íËu*›Ďép‘Ůţž›yƒËQxëM[şpĆ&_űś-ŕ&źçî9`Éíśëƛl$l\ cŕ|čoܞˇ'@A'¤”ÍßÔC sD”wÍž§ÎQËDsv(í•h'żÓ?ôŤ˜Yô L/Ź€h?üpÖpásžŁ‡BM`učŁYŒ'žŁÖCŽ“‹2šVƈBŸ3ÎäžÄźĄ|éĺ0ŸážÎ^=mŁíĺ¨2Hƒô#ŚčR˝Ëů˘=@ćŠôԘŸ1’`;Ëôƒrg‰ăů]/@˘dżˆÍÂ{Žőý†•~€D×+ň P)Á]/FŔ¸DÁKž~×&<:×aVy˝úGďMŽĺď{ď˝÷ŁŞ|üó˙ésó ČŽ­îwqqÎ)#…H ÇŽIŒ ­ŞyĐB¤%VEd$ÔÖŁ˝’ÂíV ¨‘qŠë= ŹŽˇ&j„o–ŤčŞąDبΊGŢĘ Š&ä.ůFŁÚsśŇŽn.ˆč6lšVüévü%Ł|ô]4›°ŠŮ(ď&m—2UrĺŠĚÜE\‹ĂúpĄůa=ŹgŠř$L.EUr)„ƒë"‚„QťŠcQ_$ěČBT—găZ0## (čf„~Ć%``llƒżTŁŕ­ő´ŻqAiec_@˜8Ţ­¨Łq$A"jůP#ľAÂF–˜6Q§á§R6ŕ yŕŠ5<$őýnkhoÇ Şč02<’ü݇3 ׸1ľ›>(!ň3Wťę„ůgu]€FfrE;‹>\ÄHň(Pë2ŰĽU€0zÎbŞČ-ČóO€R ¤DŹąÔ„IóЊ,ołť{-űs8’›wݞO%M•‚P­łçFˆ8˛eŞ ŇO$1Î<šJxÉK;Jkŕťďžô5֛šo°*7BlBđgć:ąMřŒ Œ&ːŽĚKEđŃƋżĺ^$× ˜źçŘ HŔ+CÝj٤“obÜ\'%‰ż–Ú.ÜOýäŽ@K0 UhŸ\ꤧÁ5˘×bŸŕF)öDkĺĂ­“0ąř^ĄtŠ›ÜŠčŒ~ęŹ0’\ŽÄź`EßÁž_7nçfÎŮšB˙F]˛: Ó6úQ €ƒ\lxFbçHPU ýN(›k)[ĄĽĺ’Äs†uÂwÜ/F,ţ&KbˇD!íZ›oîgœń™N/Š7ëŮPŠŠJĹý”Ăłűšú  ţĄÝŒ?…VžŃ-z(‹ýŞŔŢĄîÓ0­|œNš‹îţ ř؟›ľÓ/g­éRnŢicołů‘°Ů_7aŰ÷Ţ`ËáUÍ˝˘Ť3gПtpčú@ŽTqŢG CăFmá: šqŻčřô‰€6š)¤3ŸŃž_ů•_És„ńËý2N¸_"תŸ@‰L+´š.üŽ{ő)›Ď Ü+×4@ş2 ŐŠ÷Nڎ-cśybxŞ Ň ýÓdrrcţ{-FˆöŹŠŹ%(!`ťt÷њ)­Ź~ĐŁťĺ}Ç:Úó‰O|˘'ÂY ¨(ęĂ;T"ÝkąkĘëę]ďzÖ;ĺÝπŃzKýůŽwŘZ:*ýŒ„űĂ{죪Čý]€ƒ•βÉý Ł ]Žś:%Ec‰a;˝#L§ńŮ­8še°B÷d]‘$†(v€˘†AĐ•ACóÎ'ß­(bë.I#Ðn=ţP!¨nŒhč°uXbăŘv/żi•qܰqô"hG"ʧ|†,/6öP#†ű°ę ÷;ÔÎŔ„Œó \$0*† îö°&h3÷t[ÇÝJT'ˇŚŽUfD¨Ďř—I]LŞ,&+ƒÁóG,ž˜_v•mĘŔH]„ÄÔ¨Z`Uĺq$—%żžjuŽŇ‚éő‘ů“N¸›Q]ołYŽŒ¤~kęŘíő˘VM?+¤öČBŢG€VŒOE"˛<<NżćgS€áźYŒe´ňÔ‹H@\>,ǖ׹’Ć‹ĺ9%ŔL€LRŃ[Hz=ľč?běŢ˝ó‡b1 Ň ý ],.şÎ–6Z_Ż\Á@ŒŃ]¤ç!*, _žĂhŐIˇ€ …ö•°ŠŒp‰Ó– ÷•a‰uÂ- î#_î•ëÚ´ yśóF ĂG@Nńa§Čg“ÁüźŔ Ž‚ ٘–Ť‹ć¸€ŒX…Iř!7š]”c_aąS0śĽSĂFĽ<‰ç{šQň’Á¨ m’V 'äĽ \B¸G@ƒ´K0>ĹÚPŸĐbHô”šW`RYG DĘ!Ú#÷ ľIk¨D}éO›C•­ ›ë‚lÜ`W;Wí…ó/ŘŠšSvÓČMvóÄÍ62ߑ§ a1T'ąĐeŘD܉!—źlp•:Ţ^ň[éDv˝EQz8”ŽG"9EˆqcÖŞĆ NĚ’ë­Ôя;Ö3FʁYĐI°ÝŽ}“.ÖH|™EfNbHD=Ž0ÂVşŮČĎ.Ná÷×G‰žç­ ŠúÉRԜÄĐčF¤•Ý_Ź!’›–SK78ˆś´¸‹FPś[ z•D@ÄYMĎĎŻ­Ĺ i€1ú[Y1ô\3ŕ“(m22ęz% ësî]ż~Âďa,şkS˝Ű™y’>݃úOÚ?ŤĹĐIŹ”ŞÁ%KFăąiC %첪š€÷Ť3Şbťpľvżč%ďK[= d´2œnb˘Xb(şnE€\_ujW‰ŻŠýSŐřřŔĘuˆţĂ=Ł =`Ź Ňž˘‹á’ëŠÔrÉł^Ăو?Ĺ`L˛Ia-—;‡„*eI#•ľL`X•‘ĉÍLÉƐ˜Śfĺ.#JF–X0rOĄ šÚĄž$ ׊MÇﴅ #DKŸ``J WlŒ;ąF‹ˇŠ2 ńT6WŞőťýöŰý{ę3vęt]&ü‹AHôe>—ą9$>*Ś?äMýxžżzŢ^ŸzÝŢ]|×VŞű…­ż`;‚a 3EKAÉĚą|¨‡Ř;ŇmĄß¸Nú%˘Bkł(€JL[\‹ű‘„K1ĚšN§–$ég(Ęc€űč;€Ęć^"Ń'ÔçŔ~/}(ŠBęŠjN>[^¸W,%ěŢÚ'‰aďú—Í.Ÿ+t°\ŒČCšW_*´5ý…a.×ęĽ>–‹ oéŮ( „)‡şSgš/‘ń‡~ ŽüË˝ Ç˝œ˘CR†ćz;b(<°\ˆ¨u׌_à ׈$–÷ˍMăĐçnąě‘îü¸ľnźË6-ĚŮĕÓÖšpĘνó†-…çŢ͓;÷ŘÄţCáH4ˆ.ůBŽX%X&7 úL4zę)Љ9Ä󠍌MR)Éý´CEŕ ×Ę ˆşóoyšÍ˜(ç4÷IŒ™Ä›JbÉú”זáżRčl¤A¤GbŽ œ¨"pSî>bv”€ŠŢer‰d>ë}ŤuŁŞšĂgŹŹ˙Ź3¸üč°ńZe ás˝óË5˘˙z­÷Ňf“HşęÔςŃ{‘u]:-Ę[nK%hSś›kÄÔžá'Ž‹űϧţööĕЙěcÉő!ż­œ{݅č@ÝäŽ ZŽ€Ž&5‚ąéŻlčŽÝœ&lm0Š“BE}‰Ńrd07‘Yz݋Ž3Š˘Š™$1ďŞpېš5?úŮŚč5UvUię-ŮLŽH6Ź(œuf ôÝĄo݃Tał>ĽąjÚ*}ŒVą ëŐMěˆ*ëŰԊbc[’J*Ý_ĐŔ2 –Ž>‹@„˜8ÝȜȏ%M€Şč+ËB˝Ň­i†AÇ•ĘŤ{GÂĹMě*6Ù}"Áa+ž…"o7÷†Ďú¤‰3ě›@roŞ{Ɠp‰’J\% '3[Š$޸荪Üď'™eaQšł˛’E„--61twיSĂɧÚťÚ劖˙ö¸Î5óŞśćyLŹţH¸˙”÷éGąí#MXőÚ>BŇ ý„“ćął—W+o¨gs˘O/xä>ÇP‘¨*‰ŮX‰ĆŻ($6VĽvŠ<É!)|ŞÄ>1ĹHÁ âwňPRúb ȕŚ\ôŇŚHlš3đˇ˘É°yŇ)ş˘QśŘ´Geu V!Ÿ PÜ%D+ńM}Ž6ëtJŽ(ŠśCý˝ˆź%ŔŠMŞN˙ůQż]š˝do\~Ă.ubx_Äh÷oßďĺ\ ʘ$˜On9bďDMŹĄěBAběó;÷Ó÷ęʑ^׉-Bá˜yvş_nOr?’ńLűu‚'wŔ‹ď|ç;^€ÖVŇ‘ÁM>J•ą“C^ “"ÇȝDĚú]ToąT‚™v*Ô2÷ʝDŽ&¨%Éľ­tU˘?%hŹűĹâĄ^Œ9ióĂóvÓäMśgxoË.Ø{)Kyӟ )Cbœđœ¨ƒŒcé…p-u8%÷bńʓ$Øú–@ƒ"#”~éę_EDâł^xÁŻĺŮp"IŸŇďx$FKž˘Ról ÉLŰ‹œšň9ů)ÔĽ˝—ĺţÄçr[aL*ŇĎ@Da´S'´äMžÔƒßšN˘Ęô›ÜžˆRAy> ÷͆Ÿţ”8Ž\ฟú(lq‘‡kÝí'ÔA, ć…Ř6x¤O#Wwy }|äîl\˝l—ŢzŐFćŽÚú0ĺWNźfWŽżbu؋ԣ8=rťŽŸđý„ižÓNîtb| ’Á@Ó˜,:ů•>mR¤>“\š¸ˇ†{Wî<% +biýřä; Eň;}"íë – Ň }TS$8laŽ‹}śpĄ5Ÿy0—Y ľ˙Xë0G?źływń“űf?xQ–ٍbZoű˜ŇÔżzgKçIí(žűë&ˇÖ:•Ń_ŻnˇŰó;ípÝ3ŘĽéÚľĘřI¤ëĘŇË~Oœ~%C5łLJÖHÚ°?Zm—ćÝČÖgţˆş]ËQ„ŇťDBă)]7Ÿ6 …ĄČ˜iGcžt×(ŸJ ň&cśÎÚ&Ň fә¨Y‹ Ń­B°n\—ę̎)‰™R)|pŹŻX ¸­čű,¸›@Ľ(J¤g'ƒ-bbŹ_7áD ™+#ŁfI÷$ť×äČ?%űEŕ"aŇ źŠ @ɰ)ÁőłR2PQ™„†u$FEŚFłáráâaďO܀km ÍZš&¤'ƒ´ťŰ„MśVdgÄ6‹ ’XD?ęĆÍF FtżŞ{ܡJFˆÓÎÓ ŽÂ ƨٜşďŹ?ąs%ŒÜ:˝`KźĂńśn ÄXŽ(F—ŸĆVQ°9 ͎&Ɛĺá óń„q8$îxŔu(ĂRŃFJúŽüĚeř+ß'Nř÷28eóŁ ˙ĘU¤Œ*€Ť aaĹfŘşmŤ-֋öĘůWěüây[7´Îöíľ=C{l¤=b3ó3Y$|ˆ„ąMżKÄS}'Pa9P0ő˘|Qĺ"EŰéYrĂQd c‰őb€s¨áäC¤C"ŚŸ#@HŸÂNá‡zŇG ”PŹ€ąŁÜK•iółĎ>ëíVHfîçsąsHô“„wß\+Oă]cNŔuWXem’ЧN_é?Ő#‚>B[‡źĽ]ăBł "šE‰Cš¨"c x›Ť q­ž—H˛Ćď˙ĆŢżŰvÜ÷XŻ˝Ď㞁‹7H@I€/ Ä7eˊ-ˑ˖=qƕRj2NbŤâIĽRŠJ%•”ÇI%•?Rĺ¸T“Lšf4c—4š‘%[J˘DQŕ[$Á7Ađ ÜîűŢł÷šőéîOŻŢçžÎ}ŕދţ‡çž˝W÷ęîŐk­ţ}űűűţhdźßĂG†{ööťĂŽ=„íŰÖÉç~öýŕé°6Ź+VżŽ}ńĂÉaM3ťáśpz÷MáĆŰîˆë2Îů˝đăšr€R…nŠ—~;?ź÷ř-ČÝcCě Ÿ€ô2Kăa(ĺ­΂,4kÖěâMÖ´ Ř2ˆR3AdÚq_Ş?‚Ő‘ËLž‰<xďq×á45!Â2ľÎ‹Ź¸ez3†J-Ö^żÜË(źoČň¸a܇31a{pĺUç9zší *‹Č0™ČR)z"a.&ɁěłĂ›@ŠiYˆm[ßj39úó¨qŇÇ:'Hz\LÎŤŽbdN„PŹńŠžf$ĚŤ´Áąáńë’É%Ó ˘ś§1–8ƒĺř•|‘g9ŽŞ+ E†1L ۤ h˝¨ŹĹ‚8ç,‹őŚXń•˛ł5‰ B´ćڏýáhŻĺľOcFß=ƒF“ pH ›”’Ů”É ¨Ů,E_%ďěw<ë3e\vĆ(ZßXŠÚĹđŞS'ău]œI7Ž7íL›Qt8†iäk\ÜĚJZthúx “i^ęťfőŞĐ4úBI-Ě÷Ó ńŮ,ŇŕNĆż×Iš=,ôK@Ďą(“+TN| PRƢßÜژod‘ßİZY] fýŠ™GœëW"˙ëtœ#Ă=2,–˘ČmÎ\ĺXŚŁ Ć´đPŹ™eý|}şę˙Ż7Űl Ył­ŘůěÜúŒPV' g§űdžAR]1w—uÜ1ĘÂ&`ţ˛P’Ŕ˘ƒňëÎśĚH™'Gył™žGß~Éź`Gsş0S‡Â…ŽśŽž Fť9šĹPSřĘŹ‘˘,ű€v ĘQżťę2k°:ľN1ýăs™ hVÜpăŕTŻo űěOżđt8¸ç`˜ŽNĂC7=ް3ąSŽ@žW čeh}˘=ôľ ĚöŁP+Ÿ× ‰™‰č/ţăQ;ú€ë˜Đw(Ű óR^րNąŒŽ"žœíŘĺů^€ĘHĘ @aGü `FÝÔŠĆ m˜âsç€Lę8ґ7ăešv˛Ÿdl ™V™óŘń›cuŁľ˙†916€<ŠÜZ7eŐŇẙIHz]ĚÓŒăŒÓW €ş¸ž‚vô§^ÜsíŹ÷ĐŃcáčtGXđ]áćaž­œćç}áŮď?Â÷żVĐŔCěőŽÂKÇN…żr,źáî{ÂĂü¤=œ˙xÎę¤Đ­÷¨"ŐęŔx2ď8ÎT§ôÉÔâ::ęţzć50ó,5>3űÇzŇޞ9Ö6š5ť¤ĆýźwďĹ§Á6cşÖŹŢk>77ŰĚńxîq6axÜwß} Ą€Ú2čaV ŞëfëˆT‹qŸŤ/,в YĚž3f…I/ĄY1 9,&&ŹI,ƒPŔ•1“ËFdfĚKż ďÁánfŞ”z”€“DŻ]Ž6lÚ=Í`— “ RŇJ™Ś ňłâxwÝ"Ű&ŽoD BĎę~[ďČ2ę3Kf ŮÂ"…9/Oä›8Ćů흎$j4 Fšf]ʐÓe–F0lĆ+šÇÂ@ůRťşM4N ;Łf3U;éźCڧq\Nœ<žiăŰňšŮÇ´Ůyě*ĐŠÔIVťGÁ&ćÁ,)ÍÜ_Í)ł JgŇ02I<eÂjJé}:g âúÄë>Y ŁžQ"t] ą*K•öN¸^1•;§¸Ył‹1<ĚŔăNą 㗙›8Đ8VîbQžg#ŽžN šŻýëEŹU=Î[kSŕ,ů9ő#Ő×wž ŸÜFC;qŇYhÉ ¸dLĺ~DÎ~lä~ĂF1UË$çâ|Lkš^%¤ŤËáLÓîmń\°•˜O.ž{űŢ)&< 5ČÇ.ž#Sƒš5ť4–ÄX×JȆYJtŒ ƒ0ÔGć†ÓjX u-ÄĘo3˙ŕâXł˜2Ă Ÿť›Ď÷8ę<ópÍ>B{LϋąPBÂúIńĘń|†ŁM8fNQĐtyńE:uüM;MulŠe`łđĐfęś]î~qł°â;œ=™=Ś~ŽËsΧfČÉaƒá™çž OŸ~:œ\=>xďĂ÷ź1lۈăőÂó/Ä:h+ş78Ü,üYd ’Á˜zípŇiż4îZD´)9\Żňá5•ÉÂŘ) ËydŰÔá_žŻpô)ĎšŃOá\Œ m§ď” QŁ…ÎÁNg ćFcÖ!™ ôSÍ5Œ ŽÝ—žôĽx<;ˆjâČB"TI Ă~d‚`ĚŘ(†šÉÄzꊧbďxÇ;âąuznŮÎ ł ÚQ— •a5†hŠĎ#óĂĚY˛V53IžŤqŁ÷[-ɸPžű,;w…CóIXÝySŘwdÔÖ÷†÷üő˙ L‡őĐąç~^úĂßććrÜńڰă‘÷†ťöĆl„Ď ך úâ5ĄĎ\{ŸŒ?í¨ŮCĚ5㴚IĚ%Ł}žP <Šç@˝ľ–ÇĐΏEPĽ%ĚkÖě’ϑí9-;Vƒ Éť#‹Ěő|­ăf9u™x.ńlăY-“sšL}C~xĆř|œę3gí1”gb roVFśŽď2žcśŤ>×ňyj˝9žS˛}=DzËĺ´+ŞL̞ýŤżs’@ťĚ!+É)߈lŒytĆSŘĐęŠâŰ3Ȁňđ‰řR ¨Ĺ9ľcLŮ,˛3 (’Ů"‰˝2†¸$6ƒ÷˜îŮsđY Oé3“Ĺ4Ç]ů[_Đű5˛*‹ç%lŠ›Œ€O Ł1ŰČé¢HĄLáTLƒ;ˎ4ńqŰ38 E*;óĂg0Ô5űŻžKfăäçź%€C;Öşő^¤ŠtžhĚO'‡ŁYJC=É SčF![ÐҼŇ÷ć>ÄË_ei¨Šíč-łŻ5bm€ €L Dim\ˆʏˆ}‰7Ö<ŒiJ?ŔË5+M˜Đ-ęhȘ˘Ů´3ë(4LŠáÂTšŒá:ôaǎ¤űÂu?y*íĽp›ÜşÉ"jÜev ˙†ÂučăüŮŠč2•ĆŤ:œŕ#‡­Ô(ęeżT<é^ËY=6@ӃsöW˙Ö"Śď ˇúŠŐĘíG,­Yłfi)Ľiß4* |ƂIĄPEîS) KrʌŽsÇF5ëʼnĹYĹŠ6K ĺÍča˜a8ä|G;q’Y,Ń&œtžŁ^k´vňŒŚíçgä. AÓ>›ŮŔp:ŒóS^֌ťé†Ń^?4ŐbaŒ¨‡^ ĘŢÓ4ŻMĂ_ůařâÉ/†{śÝŮńH˜ž˜†#ł#ń˝Wg/bě)¨›…"a' ­ňS‡‹ĆĘ"D§çgqJÝ2‹mLÇŹcÎx>PžóűŰߎç`ü9žóXžó fđýÚ÷ŘcĹţŇ.Ŕ0ľW¤8×K=5NSp´š^œ‡öcôż.Ϝâž_Ýe}ŰŰŢV˛ }ík_‹ídސîŘtŔ|gĘđz^ËîQDŕ‰:řţńÇ/ Ę׌-ęQcŔXAÓBCywNŃ/ú™$YcDíӑríCܘaüźĆ–§œmŕR€YĚryĂϸVo~ŕ-Ążůś° Ć؍ˇ…ů÷‡˝aĎű?˙˝đÂÁýĄżéÎ0ă›Ă˝źkظŮ× ‚?´ßĚ<ît.DűÜŐt•Ÿ˜™JAiŸôăúđ7ăǘĘ|qכ”ĘąĎ TiÖě’Řy0†ĆÔl 7|Fy| "ÔÄĂjxŔîăý˝™­lĽ$dzŢťsÄ25…w"ϡ5˜˘ Ř7ŢÝźołÝ,ôÇăëú|Î ¨t•ď´‰pšŹ;Ďťęo˙}A)•?ú7ţń“‡- šÔl>Ké`S*ĺ¤S˛ASמ‚ި Đ2ŠôYĆđ‹ŽLĚÓ§Ş‹šDIÇДܮ ¤ř‰Ą:Y”udŘTš'Јe`ĚfĽ-ü$ŔaŢ9ěJ6ô[gšĂƒNgŃQœbŢILÔö°]iGdÇ ‡zj¸Kç(–3/Ç1Œ ˆÓAáłÁ¤žĽk˛c™OE{8nĆŤ “IŽ{Ś7\ b:ęéâ˘ŔŽ!=‚C]ˇęr=ÉiOš$1ţ˝ĎJâŠŕoĺĐSméRH’‚Ç€H§N'U}€¸•LYO!AÝÂÝX„žź˘šČ ÝŇüÁžt­Ś#¨”ë3]'ěÚňý–ŘW+ApÎzwď\ yß=὏Üu]¤TnÖěľ2ćęţýdbŮY„_ÍF˘“Čý)(‚CäŽ3ŽĘý ‘Ržű˛îĆ[^GQő}ž,ŽIxŻ<đŔq¤ÖÎŻNŽÔ\zů‡z(:^8sfbaW‡gНźiÔ[-"Ąîzs~ËłŔ”X.ݍkÍŔęň/´ Ăyĺ;Ÿ˛~¨w}ŰPţ†ă{ů{?ü^xęřSáđśĂá§ś˙TxழŸ†ƒp…16‚5Šuň7íCC0~?ňČ#EÜ×đĆM6™ŹO1WSţâäË`ěe0Ά<™­I1Ř:Ý1‹datuĘáÔŠP^ŕĂlAŽ1óHvŒ ÇŐ4Ȇ˝F)D+a¤ĺňô•vĐ.@5^`5áŒ3ç(Çř źšđW‡6píIM`Z1N‰­‘*œ_ƒs›Ýˆ9!¨BűÝ1•ŮĄ ĺeQŢ´œ–gź"ĽĘ{OaœŕNýCűNŸcCĺ )˘íŒ÷ŐÇ?ţń"LmxĺoÎżž: 'żž{öGaăŮď†é ?Ýáýaőíď+7ގ퀿ű(Ź%ĘÎÇŘ) +xÂyÝÍö|´1ĺz ţ’RŢp?€7Ë3V\AĽ[oš)źôü÷ÂüÔ+-Ľrłf—ŔŽ=ź)ك{Pmž-2 ę(šÂsŢËY{°ÂRŸÂ´žgÜ|ŠA‹ĺТq‘jŢٲZ6+S÷KÁwžËف6T<m“[gZ\~Ć ďÇ˞RůЁ*‡_ô¨ńЅ˘Ä˜ŕŒPMW˜`řEÔ ÉÎăJB ‰0ý/Ž/;|‰ą˛R&RBěÔ@I`Bš@Ą+Ü<ďćűÝt2ÍŹŽQÄv:IńŰ äčB-kęßžĚdیÇ%§=9čǎ‰; ŰňîBŰ8€ cç˘ĆÇ|źŽqrMRŞd…Ôœ8†–ÔĄ?ŠÖĆ HťúQ,WpE`jŢ €äžŽ3ĚÚ XľžCX"€EpS(W•Ó™iţ);ďÇôÉ}Ľú~^Ĺ(Ÿ(qŇh{¤lD}Ńk)Ó5ƒBś!ŚĂžNĘω̲ŕú§6Ľž(;Ď zGw…'aLלŘ32Fú ¤ůŘ%™ęŽ0ŔĆv Z”đœ `#P‡Čsv׎=Ř#ä Łß°ƒşnM­Óp `)r<ÍTăŮĚ{~źACWŠs‘mÇpd( 6ր×đäÉăq~l‹aVŰS¸ÜlÔB2$P壏ż)<öö76PĽYł‹4îKB8qqŚXŒČÎ0eŞşfNqąƒÓǂ „ăpŠÔ8”ˆNVv"5dđoœd˛ÂÖŔ9q°35ËáԍCK˝:ɔ7ÜÂ0!Šş,Ür8Ž~ń, ˝œ“ţŕ¤É‰bœCÝm“Ý"ťÄě”Wƒň˛U#}œ_g’ă,5evďĎ|&üÁ Üö`xĎmď ' ď¤c–¤úü”g|Y ęds.SGÓ>€ Ž ÎľěÓ?|Ń7Y–7Ă ç”Yă{ŠňŒ יëÂř2VŠ÷Ń.˜”wW°ŢűŢ÷=Ę3ˇp­—ň´Yǘă/Ú!e›vŃOŽ猟á1 Ó*ţkš]ţMył1~ÎŐş<Ź}Î0$`ĆqŒý€a |˜ľĂő’ĺĹůl dţŤâźŕ¸o}ë[e=e(íĄ­Œ5ŸQŢ(@3Ăí(ĎőŤőohťáE´Eíďëş<ÇÁzBć=ďyOě“ç74ÍyÁ\9zôHŘ{ăŢpűmˇ†ŐŹ)ôôçţ,ôßú|ŔŇÝq_¸ăď{oGOž{8—Śź Ďoh !3ý¨¤řľŮŚ,Oě?óşdÜX™„“GĐ/œh Jłf—Ŕ¸gn¸aĎÂgfé“m¸Źš˛lĚyőĂĐ@{ôŃGăťm™1˛™q.ž˝˛*Ďçžĺš ĎóËLtçcŢ´ÓçÓůĎ&žÍžĎfC× ¨ň"SĹŹ4,q*SŠÜŐ JäÔŽÝJÁ•i•F €bŇeÍôIN—0’Ů|#2xpŻ­ۙ˜ 5¸˘ă›”Ę“%&Ă$ęG̊ČŽČŇPX6d 3ŹF­“Ifbdš°k]yL čŐ°cçî"pVDAł@jf˛Ö ýŔŃů’2eťeƒ$ŕ§+̖ŮRš;k_Ž–qA›bێ†5˛/e°ËIŻefEǸN+ůúŽÂ´ĄŒƒŕ “¤„‚ปşë&U_ČǸE™ÖÖxĆž0>„ŮPőؕ JĂyc˙ć}…ňľŸt ⸥…’ŚÓ4_âÂ2d*!=ąŢé$-ćy^ŃMVŕ7Uڮԗd‘Rěč+Qȗň7î˝9(X\3KBuý‹Ö ×>ŚďĘ™lŸ.Œlž‰čt™TxŹ„’§‚^IŔ&—°xĎÍű(ŒˇľmYĂŚ+átŒßÎí+ᣍŠŇŹŮ%ąâó'ŮԈŢwü“…Ęý­Nó]çË]yţ-…WíţÖIć9¢‡ ŸËîE8ƒóS‹łËbŒg˛a 8Îj§˜žǒsBÂżic-äJűůđĆT°:żچfpćĚ$h`y >Çp)/Áš Ň$óœ|úO‡/řrxqýĹ𑵏„G|$ŹLR¨ ゙ÍĹňŠÉb,hůáü°řœ1Ł<Ą1˛,čă&¨ďÓq–Ýáçflňl:\ÎĎľŞS\SŢl.€_˛C>űŮĎĆń~ë[ßZXŚĎfüëôĎ´—s›H]Ú!@Ŕľŕü|fynŃ9†&¤ÖşTPÁÔsĄOĚkŃmd¨‘9ĹâŸë ŕ‡~ uŞOS—gü٨ßó3†jĆČ01łŸ3žwć ;ô‘ë'řeZo™+˛ťÔÍŠÁK5‹?ð(ŻP-ĺkqhĘˆáčü­żőˇâqjĐ~ĘrÇ猫@íź::ÔőŔ›ďýđŽ~ůťßżđÉprßóaçío7žó§ÂŽťßfĂ{ý…}/ĹuÄzŢĐ3Smaœe¨~ĘPáüœ“óŤë„ŃS73˙âsĺЁ°ďš§Ăd~ʁ*͚];xđ@5;ű ó}°ř ƒ#Íí“ńžćţĽœ SÓ˛ťŮňó˙›'÷8XvČWV֓>I?[:]~7 Ĺă5=tŒŐ¨¨˜$§NÇ­ĺ0Š$“Rďćwe'H‡×0ˆÉta űöن”ŠYąÓĚd˜Í'¤“Ž~ĚŇä6óNÜýďç°X‰ě”Lż a!ąÚéc¸Ď¤Ó‰îĘyj-ە˜ ŠÍ†“äН••iůÜĐ&oN Y üœúř=á=×)SĹ{°ŽłYł 1ůšňş™ţłcÇöRÄçî°ČŔ9S@SJ, $ӝÎbú^ADĹ(qŢ)oœ˛´ă}´ˆÚáŔŠ˙Á˝“ŻăOŞZUœ‡vŘ6.Y†´PžcjUŮ) uş .ť¤ĺ;Ó!ňźŁ 5ľ—2ҊM)lJ\=Фşřä‡ńˆŻťś…ŸœřIřÂË_wŽÝŢuëťÂĆŃ$rGČŁťdęa~06´ŐĎůLĐA-Űo&ÓUÂD`ź­Áů¤mŚĄe!h˜–BŁ,”ÍîĂy̎Të§°4e.ç6„­‘‡~8‚”|2„H1dţ–ÝbŒ™x\Sž2f'’9!hdř‘YŚ)ҜŢŰĘ÷,ĘĺU|VlbŤŽfćcIž|ňÉ8gÉđ¨'CˌUŇĘeXPc-Č$@ÁvnÁ°p-čőĽQĆÚté´GPŇ{ÓtƂ2†u^Uš5ťtĆm˛gOÚ41ł÷ BâËV Ëú<¨Ś,‚ňÜëIçquPŠÍĐD_uˇÎńšÄ3FĄĄ‘ç*g&9ß˝çˆ1әŕ÷šlhĎőŞ|đçţă'K"Ÿ)ě$ç´×‘Ł@hŃč Œb2f™)G×ĺđiiTbdôEł#Ľ >_Ó˛ť?/á:Ó˛4ŹŁčpt#b¨ĐčäwšL_œoëáŸ)ýcr‚M̙˝‘…rŁăĚŐÚ:›'÷I-2š1ŰQvr +RĽdšĄK˛T|¸˜ô1,%58”óđ‡}I)„G`@MŔœkĆ6H’fS*€*Ľ”N úăŹĂČäč Şë=^çQ;Ľ×ɏ€[z1Ďó¸Ö€G,“çĄ`<NÖ˛>KÔA™L Ű$ęăä:ʘećĆb:ęńˇýœfÉź,lkćSn§” ëSjٰ^’Âń¤ŔĎ1+uřŽÇ˛\úľsÇjřčűŢ{ôŽaAw=*}P#Éëę ͚]uXžĎ_-0W[ß÷…ŠÂâGö L56t:YšÓŒăĽfˆNb“jQpčšP“Ĺ€i˜‹7œKG”Á‰d‘%;ÇŮź‚4Ôc(÷›L ž[˛7ĚR @@›Yˆá°Y^Ś$ĎĹ<Őč ^ŠČ:ň˛Ż•]@ˇÜzK˜ŽNĂłűž _{ńkᥕ—ÂŰVßŢzç[ĂöaƒCńŇ:N\vmáü†pţY§B]ŽcltΊÇó3śô•v°jCý|Ǝ!זżFÔš¨2”8?ăä{ŐĐ$Ů0\~­ŻšÂĂüM[,O?š~flQřXÝQĚţV$–9$Ăđʅ,už$ŚđZY+˘¨p˛,(Ɔ’ÂŠÔ kƒąS§C‘]ę†Iaf)aü¨Wd%ŽOś!E3$ę&ÅĎ(ŤÎwŒ>śĂÜâźf"2|L6X-4Ë o–dS<Ö4Ň ‡ó~Ń^Žcr˝dt9ˇ¸.fŔ ->/ř÷}÷ÝWîuúGů8.„ݝ:^ćěěĐËaíĹď‡ţ……†űaĎÍáŘ´źéáG q:‡wۋű^ŠçߕËËNĺü\ľ™Ü˜RCF'Ž˙ł?ŽO8nťiGUš5ť7´ŁÓń˘Qâťs3#;|ÎÁţŕ˝ýÄO”pžeFG]ÎçťÚSf—[>—ĺôŃgŃG<ËůnYÖDÉăůxvą60,˜çΚÎĹožÁźOÍÚ¸|žĄ˙׏ŚĘÁWŽ'ĽÖýH˙6˘€!9ßIŤ$ Ńö†Őôوm%‹Ľ‰q*˜ľ'9˛ŠNf3ű„ŹÍâE•1 J—…K“ĐkýBč€Á˘ZĽo™L&H°˙ÔI[a­jËôٞąaHX˜˜}Ś+`D‚—°#)ý|ć2gúůh`ˆĐ´„ĺtĚö/!F…IĂMC{Mń[Ř0óĹLI˘ üm âȆ™Nłƒ1πNNcÜu ŕÚŽ22,jʙ‚ʆ‚yüřYÁď×Ö×ň8ŽÄ90 掀],ćŁŔmŽF‹ś(|ÜW×b¸î§7 ‹óÚ×ălś™=1, Şű|–_ŤyúeR̐•ŔľiN5-Ł)á3Óř}éfĐČt‘ r|"XÓ4^ÁwŮ ƒŒĹÔFŇ/âÓoŘţŇO˝9ź÷÷\7 Šl9^@ôŠYł‹5ćޑ#8T§ĎHQĺžfޙ:óY*PsËwŚfž*„Éç§s<‚şÉéäoŮ,h!Ũç{‡‰cM ,HCű‰—ƉeAĂNŻĄ ´‹>ř0 ď>ŽĂy“CÝ0dđÎŤěľ7¨Sś Î)ĺe7~áůé A|÷ďŠéśiŘwz_řöĄo‡Ý+ťĂَ>ÖNŻ…ý/§ó œ˜Ĺ†óžţcœ6çtźYŹrCFwé? KţM{NLGÉß8 ŚäUˆ•ńfŹÔ™‘ÝăB˜ĎëŹ2‚l\ ĆáĂţp…ÂńK{ ŻRý ŃA÷ZSžq >M5CÇörĂ9yĎ­őgÔ5Á(ŻnKzÎŚů)ë…ęŁOhĽp­ crŢ?ďüĄ}ô‘ś°[ P#Çď1ÚŻx3ĺwPŁhfx’…!hyĆÉëž6ŒÖKyÚÄ<Ć8†ţ3Ÿ™—‚7œöý’é%Ë2~FYuPźŽs ŔQHڐ!ÎÇľ=<ÔÁuŮÎůqV˛8đóßýf˜ýŕ›aş˙ůp|e=Üt÷}ĄŰ{kxĺÄé°çÖŰĂŽ›n Çshý˘Ÿj™ů‡ś:żeîđ<Ř˙ňžpç­;ĂÚäTUš5ťHKlť™->ĎSˇ×?őÜö‡g÷$÷&ôfⲖń7çŕ™á{j3ŰĺöŐ ‡)ÚëlBËĺę6rźţL]÷kłsE)oXČ@]čÝŹ ÇŢ˙ýרňą_ř'O<ôJ<ŹS1¤KÎt폪sŇežĎ}ĆœĘ M˛slzm 2IYŽJJć<żeÔLŤqśü ]ŔŽ‘.—„yÍ`Ô‹ŁĽ¤ţäđg†GüŽ ŚŠö|Ě/CÁj””1˜d‘áů‚@ŹŁÜŕ‹: ˘/+q!˛âÝľ]kÇoˇ1ě'h2kftŃ'çS(ŔPÓÂv ŚŘ—ReH!bŤ“Yř+~8<ńžűŻ PE´yźwď#łŤYłK`Iüm‹“ÄŐq(ţűŽ;n/N0LĚČľśVvťĹQ5”d>"ŹYďç‡E‹Şý:@˛A¤ř"`ě–˘‚s¨m"œ*S:s>Ű8`ŠUlęÇŃăÇđʛu…vÉHPű…s, ‰m ^Ώ3*Ȥދ;r:§†ĐŹn[ Ďz.|ë…o…CÝĄđĆľ7†nx ěŮš§„y Ńqg 9琝Âyk€A§Wa×(ԙŻmĺXłŔĐWž3íĽ,*ü6œ‹śpnƐzqîeXP'cĆ1,˜ażĆČ<˘ýŒ…`€Ššé}ć8YŠę”Ó.ŒĎer0_¸~jş(Ňë<â;?3<đš Sk ŕŠsÂoÁAŽ—ú1ÇÂZažŠ™ú9żapŽ!ĺ`é¸ËÉŘĆxó™ w5Ô r~ą“K9çŚ Ç*zëßjŘđšéŽayo™6”ă9–z1úČščŸÁ(âXĹ#GYdŐję°¨dNI˛0e˝ś‚“^Ęšƒvű".tüŔţpŕëŸÇ^řqŘś6˜wÜVoź9ŹěŘŽąÎÖÚ;vߐ3@Św8×S­ŻĄbÁ>p8öĘΎ6PĽYł‹4ćjbł§ç–ýfÇů[& ÷$Ď÷}čC…uśPQ˙6;çQgM;“Xě'ă{’rĐËe6+çćĎ-őޖĎW|–ŞĎFžC<ßký•3ľËYâ.;¨r~ňşk‚ "FÓŃi“ݐtSR6–x_g/ŽŠvŚ D[ĽŠqQʄŃiĺŽ~GG=^ţƑ7Ü!ąFÔr!KxO(OP˛8iOL("ť!ćGú‘Ş”ş3)ŔJbĂLb[іáoÂ* kräDqذ89‹Ŕč<2“,kűXj6G*“ôX暯 ĎłÓďP{Ó Ď Đ•ţNp6ňr5_Úy [Ó)çФ$„|•Ě8Ó1ĺő8f9ĂS0äŠ+4Á/FvňŘŚÖi(*\ßXŒЌS˛ Ífě~ŽçĚGýBhUć&-ŒˇĄG|őINÍ2Đ4KŒŐ02lşĐvOyň\Ťű#ÎŽô ×rűĘjaŽlt)Tn%3‚‚Ě0ĚŽ/ c sž• :ö%Ý'ĄS`ޤëçw]-X;bŠGToV,l÷ŽíIˇč:0ǏŸÝťoh€JłKnIű`Gqz—9)ô#1p†g   ŕ‚ŕƒÎ#óÖ0 Ůq8p:Ń|†ÓÍy(o?ŠÁň CdUĄ^wé)'cĹđő78žc â|0˜Ž6íä1¤Č~SžśëČRŚGqą&ۂŤŁHŽ$e9Żŕu:v(ě;ź/üč؏â~ŕŚ„Ý“ÝáŔË‘CIDśçX2mł`ç¤ÎZ Â´ÔĀ›Î×̲se ‰l­Á#ŻÎ9@‰š†qC΋ƒądÁüž÷˝Żˆ´*žëÂÖńăw}˝éăG]ŒŤ<ô †Šá;˜@}• d¸–×vˆú!,Č…LmlH  çe {vă÷”G†ë s“˝#k‹6 Pc@?h‹•™*ÜmD¤œ ׈kËřšĆY&‹Ě "j92“ŠS"YJ čÖ÷$×F űŕ|aČdń>U˙ ŚĎs‹ú ć7s€17D‹1Ś<Ÿ™•ˆş9ßΝťÂéa-wtúőˆ{ŕ]áơž7ܰ>€•?y&ůŢ×Ăá#GCˇ{nÜVďź+lßsSž<áŕáĚaI2Y˜3Œ/™ŚN ëěG†őČ,4kÖě˜ †I.[ÍqSÍžC=öX|ǖ7r겉M{¤ĺË]f€,Ÿr2פőϗËŠůÂó×ÍC“—8ő(ÍiĽcM˜‡Í€Ą2ÓIaŹfG7)N´@ŠŹuQ"LÔ'­›ČöČ¸ŢœQf,ćyń´’Se ÄÄcťÄn)7t—93œŮ2–Mu×Ś0Fć#(Wƹ̕P ëp:™5֊”$w˸Uç, Âc­ř1R _˛˝ůD ęĚcÍ!̧i͈ędŞt…cŮI™ł§@•C§Šł_Î3űj8•š) c)`ć\łŒۇ‘9“€É4Oç%-ł!\.RÉţóąÇď ďyä×ÓąU\VP…sÂW\ ™ýE*Żş”ł~`ŠpĘTaçœEe 1žZF‚á@îţ×iZYháXޝ!ĺY†NýŢ4|…>G—íëášĂυŻ?˙őÁ <nÝ~k¸gőž°gמř“2,ŕM†ě0†jԙN ÁqÁĘ9Ë3C|NűŠSz2}0ÔHśďjú„ɢŕ;ô=˜U#Dև)˜d$qNžc eŘŕ„ !ŃFĺüp,ů\GŢľ4źfôşčW݇¤•ˇQúa†&Ęs,ǘÂ[€„ďԙăˇYg˜“{f,Rƒ„s™6œž2‚‹Ž­Y-¨šD_ԅ‘ĺBÝüDńâ̚h’‘D]ôŸzicH˛‘hk ]/ďeYW´Uđ…š`ć Âä SFýŻí˘NﳚÉE˝>œŁ2Ŕd*Sžţ˄‘™fťę `ŠPGŞ˙jZgžޏÇ ëÇÇĺŔóáäpßl ŻÔS§‡y?ÜGˇÜýڰvÓíá•#‡ĂSßřf\óńü 4žôĂaQx¤1Uš5ť†Ď½t&ŤÁîiŢpcĺŠĺA_™‹ĆÎÓęŚ.BZ(y4ţ6,IŔyÍçHĚtF¨Oń[3VŐaEôIŚý”˝C˝ŒŸ ’pź/ęĽđC_cÎ%ŝąQô1@¸1ŹGG– š…Źߓ†v1Ţęy8ÎlD‚`ŢVŽ˝z)„đpaşp~ÚA}f H̢Íôƒăj-~S/`¤î8ďÜscŘqÇÂęC†é+‡ÂĄ>v;ć'„ĂĎ|#tĎ~/~i_X™­„G>đѰîy§;긴×hłf—Ä’ćÖ Ÿëóqý*ă”gď_Ÿť›—Ë€ĎC~\gœO9ž9œÇ°Řs•Ă|†ńlRˆ˙lĺęňIÓ3ąeŠj›F–\žve‚°ŠĚÍŽ˛ÄZé3řŇ'ǐĚ5 Œ†Đ琋1űMŸđäu§š‘ąŕ‡˜Îxcv:‚+=éťěؤdÇŞ8é:÷¤Mžt…q‚ŠůQ@úĐe†E7†Փ&ŚEžL+ Y6#Ó 2)@ §i÷‚´Ćü˝6,3ß$žk{ý颭Q€†PÄkmG xŸF %gJędŐčá<ˇW“, :]Ÿ&p…ĚGŮů_Š2.…˙Iă’ÁŻ4nĄ„űtÁ– “ĂóvhŐ'ŚFj󤔉 J™ńZf”t}BXcwk> ““§ňj2)Ůr÷•Ěęr=ݤ+Œ—žŻjŠ % ŤŠ—3ó#ł=ňĽ‚8w‚€N(ŸĺŤŰCśâÎĘFźnQ#¨h¤ŘÇ ÖĽž‡Ç˘Ďm4t,ľ#ÝG“Ź‘ChW­Ő’4zdtÍÇkVÍĺëË1Żteš˝~Mzęƒđ,ćóeeÎw÷U-Źúx™%:€†ȊPż‡JńKʛĄDŃOL…żqĐyžąŕ"ÎZŔœ{u?tć Sq,Xř(ĆiřŠa9|§xŚ!1˛/řÍš %‘@ř íĽ,m`1fřŽÎk˘Á˜NbŚÁ—S˝kGd§üĹOţ">ĎnŢus¸Łż#lßŘNÎŇł] ÇĆÝ{ʛž§XpŔ>Đ'ÎŁłÍçô]6cfš[Á*Żĺ<ż_ÁÔĂ Á ÝPżEÇşS5‰ńČŕ‡úG@°Ä‚:PşŽ™ÜÔâß´‹ăÔA¨—>xźş÷şu ćsţcn(–,%ÓcÎ'ÚĘxąłĘ5 Ý'Ć|Č3‰: 71Ź…sq˝\÷†$€ä˝b¨ýă8@ƙśRöë_˙za-áPĐAžçšîXŕĎĚ?†ä`HȢźîŠ1–œ€‡2”Ľof8â:p.ÁHŰ %^çƒv2˙)g f…se˝.˛w˜{îŤqĂľUSÉ{ż 5đN#˝÷öáźĂşÁţŐĆôlÖěRXLÇżk`C+Ď žÇŠžŤé´XQ—ă™ÁłFĆő˜apšl}Nő8Ögł€ý™˜&ţœĚ"ŘfWó9]‡&mÖOY–fřŢŹŁ$ĆXŽű/§]P%é6`]ŀ"ëZ$f€ÔwÝGĎ0ˆ/ŔŽÉd>2B&Y§$¸Ď,“œgżŻŇC{@€UŤ)‹,)Qd7ł04Í ĎŹrţG­‹ eŒű’5a;RSç(2ž;/+ $™CŃ=™! ýl^2ÁôaMА-•ĎÇ,@Q`ľŸUç)Wf+‹i°üNĐ_~’…^Ów9ó Č Đ˜&íۏ‹ŒšYöű—A‘~aĚöňuć_Ó *PÇ<‚t‘UYéßăxO輤KłŇ%Ą`nV@„¸˜ôčş°bÔĹu=t¨ę›źŻŔžna^ Ć$ݚ1›PŠŤŤÂšBˆÚ*)2˜úÓ}É4$Ă&T€G_í‚'&•i“&űĽË@UőiRśŠˆŕ0Ţ;śďˆĎÂCG…ořFřńěÇáć7‡oz0ě]ŰŽźr$f÷‘mŔřpej|`Œ‹ L`>w×ŢŸBz‚/ęŇČdQ´ÖRľadĂĐ>ŤľWĚś…ôâq´ňP\;ęD{„1â<¤äĽ^Ů1#s„ë ~Š ‡ěúŔx˘QâŹô×° ĆIpKKFŮ›ÔtYÖjqžDĄŕaޚŐư+@ÚI˝ßřĆ7b=Œ9Œ ć˝ŕ!-ô‡vŞoCűŕx4tGŚ‘aH´Ažgé#ó”qäĂИű´ŃëëŃŮ0Óm°oÔ] 0snęaN ×Čp*Ăő7Ŕ1ÁHŘiƒL0łjńšăHůšĄ‚9ˇÔn2ݨ€Źz+ęń9×S,ŘL\† ĆĐąĄ'N?~ĺD8vóÝáî 7Žsd˙ áđžçĂţ}?L1÷ě a۞ЬYł‹ˇ¨Ť¸2şę5 ƒű&(?<xś-3M–},ĹŹyń ^Áń÷2+F`DÖe}žsąMܨŕšćfϙĘ.÷S›çVí§nďfý¸ćÝy%ěŠ1UúěäNCÚůŽ™{Ěɤ,` 1ÉČŢëBV—>‡Źč„‡’A§ŻœŃ‘vŕO…‘…2ž `BŔ%Q™6bˆGlkíŘGwVú˜’Ľ&‡_,˘tóĐ"—ĂMüwŸEjEJčN@1‘Y1ÔPqâäńŘÖxŁMşŔ#‰¨ŽíçŘ óźóšbĐV +!23ňřXG-*,đ f‹ĄTăÄ36ŚŃđIĚ^4]‰Î?ęŐľútĄ ‘bÚ§ă^;3ŢĎjÝ$ŕƤpŤ.ezŐŽrć\™dtuX8ĺk„äôŸć1twšĐ ÄŘRöĂĄ°EŹ:Ďź;i+‚#Ă*„BhÉ M˘U@ŰřŮÎy.ŽĂęZZ<ĹTܧsŠk△öΒÇVgÄJ"' eŒ‹OŔan@°bš‰ýœ/<űĹ5kv͚ôYve1b˜ôŽlś,Œy6ćŠŮkÔŻ¸Đ󧰈´ŰSeü°‹ M ܃î^+0§óŹ 'Žb¸ďYącNŽç3łÍPÎđ 'WgÓpĂo¨ßF}f+Q`×Ĺć.šáj§đ™ŹS<ŤćO˙apčd×!1{̎máĺc/‡/ţBXíWĂ˝{î {7çńŘ$=• †9>Ô!ó€1ćzp^¤˜Ŕ‚­Ž}@’ĺ#páçœÇŘtÍLHŽ1ăĂâW‘]Î)őçp@œoXü&ÔÇ1ǧ ôś1;2ČČ"âo™#ô…ń´}f2˘.Ę{NÚŔř0žžŤ…­ ÚC2%¨ƒž ĐšŘĹĐčŁ˙&T‡ž1/ČîĂuĐ0Í6ÇŢĆ5Áčłz@ô…žĘ4rçT ,‰>§zÔî‘5Ăą€fS‚áBY5\`sŠoĂw†âqź)Ĺ+~ŤcĂ8fD߸Î\iń˛FŠĎ{P=!çŒ@˜á[|Ď{š‘ˆšË1‚,ôO „ţÉęń~be¨PÎsĐwĂâĄ[łŐz<ˆ'Ó>ôV†uČ1ćÉ÷…ŮśÂ̈́Io Řá—B’'hÖŹŮĹLu×őĆ3?źCynň|ćYĽśv& Aö÷1÷ˇĎ˜s•óGmmě|Ŕ EfyĆřn> R˙PÎ÷ŠL:Ďwś˛Žßx>˘˝Üve4U˛#üj ĽÎ4’­ŻBZćI§Ä”.łK抄ĆăGđ":ě1ôd#ÖÓĺ]w—ÁÓÉ(Žęîât}[LÓĎç9őryZ€‚.dˆHĘcřϤfŠô† „RV B̀NrVG;:҅"Čjö> ŠŹŠ¸XŮHŕPîS ’ƒNˆ)|ÓšWňŽQlR[RHPĂŻde†LWDJG` k~ôڊN`RÇa2Śž÷e—4-6OĆvmĎ;!!^ۍ…ąÁ”1ôgRRŔĘ<Ç*G`ŞO!†Ľ#wă"ˇY49¤g"P”çu­ćěDqQ˛ţ4/}J:#˛–œŞ‹bĂ ( ™9”çĂ<‡ŒŐeÂŽä|™ÔŒ˜âúEpEŃ^Żý‰Œ“ůF‰̚L§ ÇE@)ŚëN¨ˇÚ ŽS×M^Ő'Ď[D˜ť1Uöź Ű;×.ţŐmýy~–ż9‹C˝BÖ3ŸĄŽóЧ.ťź“pŽz–˝Đv_Ż–Ržœ‹őBíwlX`ݘ9çL–ô&Nf°}RvŽĎ×ĚäáΏi’ ˇŔĂq5s Ú)h!{Ł 8]8bçîžÚ :ĘŚćXC63S żqÚd ŕłČ1˝Żl 9Ys˛jĚP☠¸°{衇bĚ,DۨŸąc—_ŕB‘NÚpđđÁđěžgĂs“çÂíŰnÝňP¸iýŚŘVœYwżLskă*ČB[˝NM|§xíă;7ŠĎXÔQˇŹÁÚćÎĆBf‡ŮZ …1ą‹MÚ@{e Ŕ ŕX>w‡Í°'ŰŔyŹ‹4،•á%dRŤ…q4­ŽŽ˝mraÍą€˛K˜SŒĽNľâŚĚ3{ǑşŽ´sĄ7#h&¸ÄŘÂPĄ YĽ]8°˜mGśő1מL1­ŁOôMí™TôQ Í9Š(ŁĚ!Ca¨+E…GÓă´8ö˛ą%čƒ@!í{ôŃG㸙‡žq}ԑQGvý1ŰçekƓ™{"ÄTĐyYD¨1lŠńt|čƒÚôĹűL†’ŕ,׎{‡óp­iťá2udĚąž<=ŽŰ°&™Ÿ8&ócĄYłfoI}c(đšÇ÷)÷­ď˜Í˛îÔá0‚ż†ÖĘÂŤËiő9˝ß)ŤŸPgýYT–Ëú ’…)“őLeësRNVŽˀ̙Ω~ cu%슀*)ň$ŚŘMÔLSë <„â0ĆДŮFIĚăĎs™řŻůź°HfQgÂl9Ó¸c˙*‡7ŸMgš:ç†>LˆžFÇ}ľ˜Â6;°€–é “Â^CÂü čs;'  Élś‘Ű—Y*łYM(Œ Č´*3KGy÷'1)BtpÁŇ"ţxtŽq–†txH]2+e6Br˜Ô$‹˘Ęԑ*=Ÿ÷el4 w2J>Ë ée§-;ŕakC[fó•ŹÍ4U)ňПó rĂ1É!M4ÉL‘ŢĹk’Ćf ‘Ńw]OŹ¨ęëe¨×›×ÂŔ] V„´Ă żžf×čXqB•š§ž‘ đĂ٧_Gę X0˜F™B)”kŁ€Žöi’YLłů:—oŠiŰáz¨˝C[R&1ĺzé2X•Îąř0ëŞ ĐçżfžÍgůúÔ˛k›ĽŇ÷5š>\# ˇhß˙ţÂç>÷ůaŃ| źűÝI>{â‰Ç ęžę:7`ÂyňÉφ/ůËqţ˝á w„żţ׎NjŐţđGáá‡ßRhŮXĘžqjpänŒ÷9÷řg>󹘎”šű—ţŇOŔ3¸ťźpß|ć3ŸvďţÝ[JŹYRu^  }=xđP|ćÔĆßťvíŒ÷×áĂŁ†Ă™ęâÚŕ|ÔŔĚř}ýňË`8€:ęu(.‰ł'8áN”"´–ŐĺsœľŻ}íkąŽ2óÔŹ-Ě;2łü“+ŰƔʶ‡ĎT††ÎčLb,z`-Ȉ 8¤Œލ"™Ô+{‚ňf’Ą|ĨŽ—M “ÉŤcăoÓ S/cĄăŤPŻ’hƒ ƸČúá3B~pěi‡Ů”tˆmƒ Ů%ľăKYLŃ,á9Ăyî˝÷Ţ8F2€`žčDŤĺœUÄŘë¤fía>qçísóD@MqTÓ=Ó?ÎőÝď~7^c@ úŁřŹi8Š_f†á/2Ądůpęős>3•ł€¤Ą5|F?h &kEM"çăé.Şş$Î>§ý€]ÖGdŽŃÖ§žz*ÖĂ\eěeęp.2qĚxĽĆĄDŚ5ŒP Ó LcÎcÚ #LŃáZ‹ÉŒ`ŠŇRˇ`œ÷‚˝ s~Ů,5ăńĺX™IÔAÝ´ą,LŻŁ‡CłfÍ.% Š]ĺoŸ…§6cĹ,—ĂÔzŁ­>Ż„]Pĺôé“i÷}>2’0č4:ÍŃAŸĎŠ8Ś,lLŹ„X&ë_Ä2Ů1Ĺy.i—ťŽ8€Ł3;†x ŻŃčhDŒ:8ĹĂptłpjho ŻYëfń<“ *¤>Œá.ĽŽh™őÁÎ\çˆ6FŚŽy¨˜9)„¨7°T&ł1şähӏČÔ@,€ţ‰ç&łÍśmŰCͨ(é|ç}™ó^Ń Ä\˜V}ęsŰşŽf-ŒŹ‹˜âw’Tůű̉J÷}(Z+*eĆ´—Űˇíˆ Ů‰¨ŕ|:;˘ÓrŽ^S€ŞŰœłEÍć aJÉCIîďéL3ć_&‹žń2˘™Ž}żŠ¤pŸúÜ+yÁyŞÄ3Gúš™Ťş’-frŞ%]Ń*!L9ľ`Dœ76Šă2€Q÷݇ěÍR™IE2ť%dR q"mtHL€fU ĺzŽaL%Ô.,2o#i¸ĎDCűş°ä}y-šxčF–T˘N§4֛=°żő­oÇĹăűŢ÷ŘŕT=áßűŢ3ąÜý÷߁ ›O?ý˝¸ĂĚąipÇpžˆ/FÄ,VÉňÂ"Ÿ]ä7żůţđß˙÷˙śdOyć™ ŽÇ˘#Ϝă<Ď<óý¸hĆĄůć7żů+ĺ/çš3–ůÄ'ţ(üýż˙÷rŒţcjŢçž{>ÎŰ Ě㎭E(˙ŮĎ~.üěĎţLl÷SO}=*Ě?řŕńĽűÝď>_F”˝ž•äĚ4ţ[Ę<Ř̸Ÿ"h{úô9_Đ0[¸÷–őUŹcc–Ÿ ăî9÷.a fw1 s‡r\#@-ԃÓĘ$dDÇ׏"fďa>‚@ԍńç74„Ĺ‹)ŽS[Ä,"ęˇHϕmÁ\Ĺů¤˙:ĺ:í ťŞßâç§mœ›…”ěCŻ _úʗÂé=§Ăя†7Ź˝!3ŕĐÚŚ~‹cţŠO}*Ž),Ăwë54ƒń’ľ€†ĄŽăˆS­ž IŰP‡ĆŘ ˜)ÔËńz"ô[Z¸,&Ž›ŽÔsĄ ö—qč1,Ă)ÜĄ_´‹qä7ĺi ćuŇYˇ ô×kl;­/p'eÖ,,ç†×ăFƝ~(â[3ˇ+ÎĂő˘<§)ËXăÔĐĆ/|á ąŻüŕcÚŞnL1ćéşMiŤ"ĚfóěS–kSßűŚs6-˛Ź,uű Żc ŐŐ1ے÷ĺřĄ>ćšú@ĚeĆQ֛ 4*˛_těĚrd֥̀äf͚mÝ&•†ďLž§źĎ_ĎĆąŹi şžĆœ‹i˘ž“›4˛EÎG`–獊ŰϖvšD,KšŻŮ-ç*+cŇçáuŞŕŹž8q8fŢIʆ΂KA‡z’Ň'l>ď‹ÖÇG11RöŽŕÔŻ…ŐÉZŇâčş0 ĂŚsFq×ŕEMa&´cP’Y*„WĚűž8ő8ČüŕĂŞHŽ˙öLiÎĄ>™U…Ssúfž4‰6J*@uVâŠ2č2ŻŘNńEĆÇŹ8ؘŕPĚuJ6ây“Rb{d6ˆ“œmSO˛ɸ“&:úc– 3ΊDDěw:×4‡ÎD‘Ô~LßĘŽvÁš'!ŘN&ŸE6QJĺźđ3ŸEíG#„sŚqHs"4šÍ4̆¤$`'°nž)aˆ¸îÚś}źĄç9íôtĚ$dŠí‰ťŇ˝NvrŚGžZ¤oD‡‡zwîÚ&ůšĎ(S=\FfSYQÝia Ě#•/Ľ˜.!T}żüáß1ëOHŽ#&łş Ý Ď,ƒ]ŒçJÎrňä° =nŒŻB)L+g22*eäŠ ŮĆF OsnËnr\ŇCkĺš]@Š0› •4'PZeÓ2;věŒ LŔœĚ@“?ů“OE€âSŸútDžúŐ§˘áÎő‹/îĚ7G0O-‹nŘ_,H9öȑŁáK_úr)Ď=wGf Ú_|)˛b&†á>Ä Í´•öƒâú<ňČŰăËň?řáđóŁřŇýú׿Ď cűöą Ž @ě§>őçąmßţöwŁł/Ľœ:Ěŕq=  áŠS€ݜń¸ˆĚ q6K ˆWJ—ĹóČZ“Pß>,<v¤ŕËN1Ý/sI}ę5\ƒś´á´˛€Ŕ)Ǚ”IŔ=*kA-ľ_ × ^1ęp~Ó {ŻËÄŇĄ7>Z`Ŕ"{ęĄčPŤž/˃6ĐęgÚ_4 = ÜbuW÷ʆgŚĎ„Ă'‡mĎo űî ;îÚîźăÎXăC{ë'˙Ɖ¤}´›óŤë˘3jŰX:ôŃŹ-|ď})s˘Îîchc•Âú p'\OƝ:d-ŕˆňy-HţôO˙4÷Ą}¨°j†‹!-ôC˝ Y ŠšňCfc`, ÷Ąm† Pďƒ>Ż—z1Œ…ľf?âz¨CC{)7śň††Ĺ •ŹĽÂź0ݲóKWŮ8Ü3#°TgϢĚŮXnÚX dÁűßůx.úÇ1ôGŞ:÷#˙†Ůd˜ýŹő‚ {”0 —ĄY|ŽŢ çg,Ýńľ­Ě7έX´óU`ĚP-Ăő¸Î†äÉPĄ­uÝŚdçš šń”zŔŸ]\‹C÷‡ţôâœ[ŤťYłfçaÜkǎ-ĎSžƒ˛ÎÎ~ŁÉóNpƒßuv ł*‚"ŽhĂů†îȆă7Ď žAZÖM.Eă7kłĺ벌Çó|N§…¨pš­;Ďťęo˙=Š~ű3Í?*€ňXĺM{ăÇţÇ˙äÉIqw4†!ʚ˝&;ôAÇ<{˘ Ľ&­“Óńc €”ČÔČL—¤2"V:ľ˛OL ‹QWtÝiĎ;ô%dŁď đ1Íťň0*8†óډ¨˘Q—Ł c!FŠaE—ŕK—Y8ÉĄŸC0V˘8î(’şěŁÖq*ó؆í;vÓăÎg2BŃZI;mkz×G@$:őó1Ôgd˘ŒŒzڙ˜9ɑŢŘŘČĺç âŤ%|e>ŠÚF!†Źl,¤Avü&~oôąÜśí;3¨Ó.ł/â5Ël ´#z:Pk!eFŠl™nÔŞ‰}J4‘ńAűVshžă ďňšFM”’ň;MÍž°;y"‡\­F‡4…ÔdP)kţČŢ0mvČ7ŠO“˛ ´mír(Ňt2˛”ćóqîDŔ*ƒAԞʩ  WKZ@“EŸ|nÚKší9›‚!IçÁ™ďĹeT|  %Dm5ÎĽśŻOÂGŢ÷ŚđŢG°/VŁ`î4 "oŽÎ}šM‡ˇďÇ0:2>Ľ ěܝóÉΰ{ď]őj݋ĺ˝62Ô&…˛­“f¨„Ďď­Íę­Ńu݇őöŠuÝé*@hÜ5¨XuuyÔřV×Űsmg{˝YÝßó9î,G„‘ůućyży=}ÎđłR!ŚşuÓď–Ä>űŮĎĆë„Sgh‰YFpúÍţÁ"ʔ˝ĺůq÷œE!ĺćT˧Zp‚…‘Ě…eYŔĐ>ţŚÝ2:ŽqZlUBĄP\ˆ†đD›#Ż„}űÂ3Ý3áöľŰĂťnzWŘ˝mw ËüĘWž{ěąÇ‹ ˘á:œ~'ĐsŁĚuĂ:ěN=cDŸq~ŐĺPŸ†ă c1-˛)o1ÎO›é/Ş ă@ů[Zj{ř÷żřĹ ýVԖáúÉ(‘ĽŔ؇Îyex†q=aŸ`*†öx0ŮBÔM{ř‘ąD}ÔÁux÷ťß* đEş7eN5D…sŃœz™´Kö cGH m ăüîrové,…%ďŽĎžŐ0Ƹ'Ďç>ňúđŽáůŁšvڞő…{`ZĆޅ–%Œ—÷Ű2k÷\k#îK6zý—‘ó)Ëű0ӚĄ2çĂŠÇŚQ~ľ9yź)şŹáŃ뀝*˘ąiדĺS‘1Yežt)Ý-aSÔY ;śďŠuĽž&FLbbLĘř­ćigg{,kX‘ ƒ …ˆJhڌ”4~‘QĆ< Ă›QŰPt_RF#Ů YŒŹ„ů˜‰HśăˇsuwƒQq%ŽůtŞ8p(jö01ř c玝™•Estţ*˜.tΓ• ˆŘ žMŚ“E&FžB7Oa:ŮŮÄŘĄžÝťW“>ĚŃĂĂÂagIşœÉiň6âX$ B-€Ś.¨9Ă=Ç/‡9ÍâKţTî œ Ôĺk€.ýDŮľkOq‚ç€áď˜yIP¤Kaaab+qçk{\äĐžÓ§geN„ŹWłâѢd&Ĺé?5´pŞŰś~Ĺ(u—Ăœ×g2Ů,‰10?§úŇZ;]+ťŽŘfíő™V7ŢŰŤŻ^ÉTJXx(a_ůč×ÍBé|űyî㺼ßç_ §ßăđŕÜŕ|šţ˜kŒ“ĺNó—žôĽčČąŔzםŢUX+fKqW[Ŕg Gˆă1ęĆĄç{>ĂÔdÓČę`îx/ŕx˘€“Ƈ6+ˆęł‡śŠ×Óf*^ž!2Cř ę,ŔŽ ăʰťň'áٓφ{ť{ĂíłŰăčx<űť÷ď–"ÚÁ˜qčcí 3žRšÝe¤.Ž@ çyá;ĐĂ~Č2üPś׀Ĺ2ě&S\?ůä“ńS'm0,LĐ@€Ę0(ç- ߸ˆÇ>öąĹţĐvYÝ9ôÝĽHŹ€Ě łOqţ:4‡>rÍhßłXÇQŕ~Ą>ŽŠ€Ć|ŤC‘gúÔç\1e7u0fŒ!ý¨5Ú –㘠av&~ř„vЇ(/óĚţÝ{ď˝E˜śĄ9‚4ęă`Üc\w>7Ušý0cmdNéđ˜‚\V‡ČŒ´‹{όDŠÝzOš>Y ć/uPƐ1žă:pš#óm÷žpňč$ĚCł+m>Ła^ž›ňRškHŘ´u"„fo\Gî/Ţsźoj@ĺ|LÁnîYÁřs™Çř”Wwś˛nčSVŚć…œ—g ey/ŻmĎUVŔ6×kŞ+eW„Šňџ˙GO:rŹěüă Î˛Ó/đăˆă ŘâŽď"”˜ ‰ĺĄľ€iŃݘ+°:†‹–2Қ˛PkvTŠ#‹uad¤~X.8Ń´p âźĎŤ[9™ÁTÁ SN \:’Ú5ŚQžĺĐĘÁčq"ş -KD–a ˛wB &ń˜“1m⩒j×ĹY˝óÇXÉTç|–ąŽ —ŠEV#zBÎÚÓĺPœ’NZ1Üš,‘EŃ]~0“Yfo˜ąČŤC†˘3ĐEfÓjáWôÍP$3C&Ž—ąhČĚÇěI5Ë ËY€úÜÇŽ´/eűü‰Z?…‘3ŤÄ|gąÍ].ŚYoĹ%Ů%#ť'fŃÂ÷Őšş2>™Ć¸5€k€c‘2ZâÇ1×P%^+XPvf¸Gňš r×ŃlH˛™ ˆ’€ÇÔĺfŹJgK×gXôm›†>ţŚđŘ#×&Sĺl;RŒ=Çálĺüł|>ĚpŔ­PŒ)Šv—T/´MśË{@{-@.GvÖĺĎ×.źL` …űl,\ĂËŃ&Î÷ŇKű˘ŽŽĽÎN`€Šqů 0„ŇĂ?\2Ξ.˜ĽÄ75FĚăN3˙V •yŤśíRŁ‚2¤fĺ<—ŠnůŽyF?̨b&"ţĆi5ĉ28f8‹Gމě”cÓcá;§żv€űűn~_Řťkď&§l)f™‘1’ĆíĽJ„ĂM[¤Gł4l§TÖçŤ[YtrŸ™ÉF°€Ó^Î)P¤žçPë„ń¤}2ăH1ÓÇqí<…e#h!ăĂyڃ,X ›Fń[ľ0pÔsŽľĄ$ŒƒétĘć¸ˆÁ!wŒdű0Š‘R?çá|Ž˙ć{ŽgŒÔęt߈f'­Šűăç J";ÂŹ9´ƒc #˘ ŢwÎ[Ž!őŞ“B}fłbwӈúE^ÍŽCżMÍ-°Pk—Čěrޚ*œ1°ŸůĚg"XB›=˙X?ŽľlڀüĄ´y#;‡żů÷rf1ľ¨ƒă죌Ebé×O1ڑ9=)÷ý`,ÍňcČ)cářqMabf<ßńŽw”P$ćżÍňÄܤMę×p}^9t =ô\X›œjL•MÎďŚ^ýŽťSԍŽ—óřBĘ]ęuAćś]Ôőmë‚ń|Ď=÷“á~üq|F›ÚţL,bݧ$ヌQbĎBS—5ä’űc|_/—]đ3Şš”tă6ŠĽá7g;ďryĹźŕĎćdŸ}')NëOޔş>˜*Ř<ß´1ä†ůá7Já+QLąśŽ¤Ćĺ4ĘÚ¸ă:Y€Y) ł`<śŻRš$<:-ŕF@¨ô]p,“óšĂ(Ž? Ek EÂâĹÍÉá_ c8R_Řłůź8˛€Š}áŹÂĚqźJVœü0Ŕ´űWEˇ2ŠÍ†ź°M‹•ą1Őn ęËĂŔI,UgJ62>lc¨ Š4ô9´Ľ2ËĄ)yÜU§™ž•kОł”ýCŞÔhé ;)1ŇůşĽsu弊€.ŕč}Ú20×÷#Ŕ–ŻUš™]Ňĺl>”ń:DZȂ†)EŮą ŚIaÚřrëžúq,jP¤ľU’ŚIJ—MqÚŔý1jÓĚ Sj˘x-Ą;¤Ó íP§E˝ć2Ŕ `ŔŰ|m–u„ňB'_OEiyyČDâ÷,ƒ W*>ńľ°Ä"Kő­eÉ ôńĺX),Nk÷ ­Ĺů"ö›Yr_ŠŹěˆÓĘŔZúZ1ŽXȓˆżF[Řń}ç;ßQœĂ+i\łä$?w÷łťďžgpß<´ëöËŚ1“՗Ł#ć.< !5.p¤qVšnPbë]ŸĽŚVá_'çMđ‡S–ň#€čŽ˝‹"’9V‡^ö‹˛ Áu3(Ď5ĆîËÚ)\kCwĚP¨żą:Ü7ß?<ňĂpďę˝áŽéa:żWÇEcA›-?qâDѰŔšĽn΁ K íڞČaUIxVM ţmĆu@dup}MŰŤ~‡é*e˛>ÂÜ ÔÇçęßđ"žŒ›mcüß˙ţ÷ÇcqjůŒëF[eCÔş*f¤Ń!S„ąĚŠĂPžÍ~Cyž§˝ôK]Œża˘ĐއÎ3ż{  œ3Ţ öbŽh+Î;הţR—‚´:ä|G ÷˛@ĆDYĆAĄSuCÔ'áz@çŚí‚a†nQőÖ`Ćőř`Ţ. ☕H€‚š @2ă&¸HÜ|Gßhלk§&‰i’MÍŹîíŁĚÉ÷ž÷˝%tćĎţěĎbű¸Öž‹ą5‡s1–jĄĐv…‡ů7ăÉ=Ľ†Žăŕź5ôţ*ĆĚľbž˜J›ëŞs€6(q<וą5Ý8}ä|j9ďĚĚÁ÷ŰÖWĂ §ŕëÄŠĐl4ÖrĚ%ćÎç?˙…8n̟÷źçÝ á[5Ü e§VĘzĺöŰo‹Ď0Á ŮMjI›iő˘6Úş`ńœ<ňH|Ć ŕœK“DĄvőW”-ˇ Č,ƒ e3ΆŤÖĹŮĘʢăĘŹ].ť\žÖBĄż<˙xڍ‘užeŐŻ2ÜtůÜWÂŽLřOHL˜ ČJt˜wĽđtSň‹>ŚoíœÁY7bƞÎÔ `_ďčDVƒ&°!ř’Ŕ "Y”5ďę›j6e!ŇńíŞr!e’°>˘íľŽ M(ŕF¨u°1‹ůe E—ą€ĺĐçL4ł<čÔÚČLŽtŽĽě;‰™°!ŕşPk$`8ä§7NE†B1z0)ź¨ďkĘxc¤6ë˜Ë¨HŒÇ>öuşše‚Óż*:”œy˛ +;)őÇp“´S˜Ň҂8-đc'łsňďÔßÜţnLę“i3- JŃßéűJą{Ň;W6f…é2ť¤d“*ó¸/ěç%–¨ć;cŘš++EĽzZBłŇ5 qÜ C¨0Ą6ĘçI§fš)€™Ąĺš˘ľ22búœŽ1°×“>l¨Ý“„›˝~ĚE™Ď+†˛Ĺ{ ;°Ź\żIoĎÂkÇr¸œf֌ 5Ɖě;żýŰżžüĺŻdąÂ”UćąÇŢłĽĹ€s-é9mí‘ÍbAĹßýÝß%†_ţĺż>őŠ?TűĂ?ř˙ł’ňöJŔÓ'>ń‰¨IŔůYŒ>|4|ăߌcĹęJ[ş†Ď†ßú­Ĺ{a }ń‹…ƒI{ýĐCž*>řRXrŇVbXLľF¸ţ\?dœIꣁÓeśŽ•MĄf‚ƒ;ŘN˘‹Vęŕsł~°(2œĹě$ę4$ćԎ˛â=ćť #œJECe Ś0Δ˛ő蹣áŮž '§'Ă3GŸ‰ü֏ßńńpÓî›ÂńccÚĹń>ƒ8}5˝° ű¨ŕ+ ,˜!ôśé R^ÓP+ĹEY Ň>Ŕ ˆô…r,0Ýľă7cÍżŐ˘ń9Íç,‚KĽ\WžglJʺ͂VśE FP@= žăZŃ3 q­\€rMÍ@ĂXÁ"‘­x`–&ćŒZ-fr2Ԑvx]Źč‹)Ş ią<íŁn)€ęçxúÍń†JqíĚFT‡B6ăťHV†óPEfç:“˙6#•` m .ÓK3Ž>ĎůLgÁ6Ů/†|ńoç‹, Î Ÿń§cm;)1ęŚƓk$(N9ŽĄŒ”~ţö˝Ŕ3`GÖ>SgƐ:ÁćóÂĎ űřĹ9$ečš)ˆ1ÁqQ?Ĺ03ždŁßރž#ź˙™SŒ?ýŹ˜Bw}Ž śnŹĄ~˙ßřͨŁÄÚĐôÔď˙ăÜŢŞ™jüBšţűż˙‰đÇüÇ1tňńbXŰţýâ!ezťđőŠ âVűtőŽ ~<Ź ~늭 ?˜‚{÷ŢXţĆęk]3EüÍ|ŕžUCĽf•Ô~^˝Ć­żS׉çQ˝:ŸĎĎXÖߎAˇÍŁ/ߝąŹÚV“m1†xô=/PĄkľ줰tĚÍž˛řS2ÝL`ŠŔHفşÉFX[Mşó ԏ‘1ŚŚţľ5âk×Ë1łŮ|ÁůEI€VÖČJ% ZƒÓŽbXŽcrxËúpžŮ4íź'ŃźQ׼śüqźˆ3Š˜&ZlŸű4Żnœm'3ib–ŁęzĽ—ř,‡őäśw“˘“bx—€IŠ/^‰ ĹiY3Ë(Ç;1Ů.a]¤Äž÷9UvŠc)mV@ĘFփ‰ě—éČô鲞M—*ʤIfj¤Œ;X ÷éű2§ĐęWú˛ƒÉ,(!ăÇquql˜ş,ôw2ńť<ǧÓ1…uŕR*ALž~6ËçJPb" LÝęĎW" trą4ŽB´9Ä-‚Pa|˜{ď•MŘoןĽ{lkýbú›żůßĹČO<ńţHWe1őťżű{1´ƒÝŰ­,4’tز‘5ˆěBią~0.NţäOţtXDż8€=ďřŔĂkAVáŏ& K?Y ˙Îďüťá÷đZ ŠĎ~öóqaů7˙ć/D0ěk_űú°đü“đšĎ}>‚d—ŇpPˆIǙgAS†‹cĂߌťă:˙:ă޸ňĆđŚío ŰW’Ó ¨˘`(ç6űNŇ˜s¸ŤĆ\âsĘHƒ§č…0ďé‹aCěhą€ŁÝ€:2GtĆ鳟™í‡6˛hĹš5…L‚˝Fę­pM!(K{9ß3—dp0F0”ĽľĆ˙Ž…vՊĄ~ƂkkˆÎ1×Ä]pòŮ|ńY¤ )őÓgć őZ‡Ą'4ôS ć”LÚţÄOÄz ;2¤FAQ[ĆBpĂő N„u P‡Ž§sŐP03Q?eĚÄąŠ¸Ň…]­‹Ď9žqóţq>s×KVsƒţ)˝öÉٜlCĽÔžĄnÁćăĚwŒ'u›i –×ym8RĘ&v¨ĚI5ź—i›SŒ‹ÚA˜éĂHd É2SëˆkI0k8ĄCüfôÁčűPÜĂ`}Ď{Ţłe"2Žçý–6b^rîC‡Đˇúnřô§ŸŒĎ€‹Ç_PsíBlŤë'íj]|îsŸť˘ë}ٞ›™@‡ţ‹ŹJď_Ÿgc™ÔLćĺyŚńĚY7ށŽev ĎßK<‡ęŒ=ç{nużę,Cőšëy^łTá9VFb]öJąëŻXJĺПŠ)`ÝiJŽ1 E ™€ľ‚㡒ł˜„œM†{sŇ˝šÇ/d–ČtźHĄ[äÄăkÇłO Ńőc,WČçJĄT9Us7îüëயw1#ŮkdÄœÔâ¨OBŘĹj7j­ˆŘĽLG!d?=ťť]ĽQ˘îĘ,:ôŃ7Ě\͌ZĽ;ƒ™M1ďÇô°@ăK ‘u‘Ćpg€ÔĆP˜ ę˛ëL ¨3/ RşĚD3ŸŮÖy̐Ă|0œdD/ŐđS ó!Ą*™ÉŃO†sƒ|NrČK—@“éŇg=ńڗđŹÚ3/@IR˘Lb%ɐ1 F6LLÝŹA?Áśrĺ2 ˇŽÂR ‚Ě}¨ŘˆĄ=)Ľą×.ąRÖ˝ńzL˘XQŇVłyž4f!kÂĚó\ŤĹy€Ć‡Q(eşn—Ž3ŔVL[~ęt8•AŽU˜LFAĽxÁFäwœąÍ4žúZ|ážăDЂĹëýŃÇ]ź× §ţÜĎýŐ¸@çß\?vĚxŕDŒ%żĐݨKeX)Ý󶸨ӑíűńšsĽÍE ‹J^đ,0żđ…/ŃÖËa‚É:ƒî WL› ŕ8tÁ,„ĚęáN5Ś#M˝.¸ÜŮÔ9Ó 6=Ž™…ÜqŹIY¸&ÁXŕX™í…ŰăŁÖ çą_.Šö˝˛/@žüad}~äö„vܐt"^z9–ç|˛uş.ifČŔX,ęĚńgœß†ÍŹfĆ í0ź„ą0ŕ\Œ'ő Śđ˝ťeęqČÖŃy”5&s†óšťgúc ľOřL}ľEřm˙̖dz_ęá:ą8 ¨‘y$¸#K†ď­ƒsł¸§}'E›9ăQëdŕčüű2ľ.ÇŃž§Í´şo?řƒ?ˆĺécj(ŚÓm;;ć™(C…qŁ ÇŐ“ńdĂŘ…za†ČžYĹľ4ˑ j3 şĐFúG_Hd—p˝7řŰŹK˛Äh˙[Ţň–ÂjŞë0|FćVŮvČŹbœŹłÖ.ŕ˝ 5ŔŠzGÇQŸ!݆qY‡ĄŒ“ú4Ňď !â<´ŃgŤě'ţćˇ!ˆ?›‹6PWÍŽ´ýœ×ąu-3)†_͏…fŁĄŮňĺ/9‚dŘbŽro°ŮÂŚ Ÿ˝vŰmˇ†Ÿů™ż4\Ë=ń™Áu}ë[î叽ď^Ź­ F[]]+ěľÍÎQƒ Ą›•oHŮlĚęňĎ׌*—uK&Ýčô öŹĚťž€OsY]?^„I˜šŽ$vN1ć9Lh2†îŒ o‚4gd€œ,nşÉ4éܘŽÚrES$Q+ŕ0Ÿ—92^űYa‚8_Ćóć*r{ř3Ľ•î’ŠŸw“rÍj+Ú3ě&@Ęɜ‚yś’^1„šąś:^Ó>TZ­‘ž1ëŚlĆ9+ˆ×ç{¨ UčQłEëăBôĹSś 3\iEţÚ¸f0 >2ěDýůŕLß\Â~^Ť…“ĆŽ:qɈąÁdΖÄËőľ0wîĺçž{>ŽčŃŽp9Œk c§JŞ+×̰ …=qdR۞+YK!ĹpĚÜýÇNtćůÜp3™˜fאĚtŞŚśC ÔŢPHŐ*CdaččÓž˜Ćwxîí;ś/|oß÷Â+łWÂí+ˇ‡{Öď kĂ'OœŒ .ĺ闙ŒlŸQ‡Bťf'‘bV7î15DÜ˝Äŕ>DËMĆć Ŕ‚Xhˇ` ĺeEPžú*Y<‚´M–ŘŔç:ô|O€ŒĄZ+fä‘-B_\ŘŞ[#€C]´njśRýĹă<Ľż†šăČą´—śËRĂ FLĐĂ+>ŤÓbB0ŮQĆ)äÜ\49ď,1—ÓŽÎuÁĘ]`qăľ Ł9“ůŽă™ŽĘůšďŸ1ާCyCyfÔŠ—ĎÇ\/Ôá b˛ňá~-çîŞM@B_t1R§pC.†˙Ňn~b%„Á‰žNj&Evde‘ô ÉŽě ­+Ű÷ó¤őQł¤ŒzőœtŮiž'KHi€H!“Ł+ŔA—uC ň%˘Ż„JEŃfăäěş Ô„Š‘1Żú™jydŕÂđĄÔnEqS SQäWt/ąĆ´şÉ!Oŕ‡´(Ú|*§ďM Ť)2x˛ó܍cëâČЙ¨’Y>~Î˙OWĆT†šP÷Č´™-8řĺúU˙J㑎ٶž=ž ˜ŘîIő°YԂ)hvŇ<÷¤ŒLçKrŘW׍´J*‚‚}_ ą2^‚A1 ÷ĆŘĹEjd†(VŹVJ nL ¸Q×ěO ÷é @6­B´ćóš,Ő9ŽQ™{0“:ƒUćIňN§Y÷&-ć`EFR(—A›fĄ8B¤Mšoˆ E _ë… ťeđŸˆ‹ŚÇź0^+c‘ůă˙$.~üăç†ńJN˘"iŻĹxżÍN §_˙ő߈NxJš{:.ňÜŮž”ćŽ÷ńăÇâóÂŁá܃|5ßPœ-Ÿ÷.ddg˜őEá7C8Ć4˛|Ś fVęĐܝŻC€Ě˘#΢*'9ľłú†mźtřĽ°ś?‚*ëƒ3ńž]ď 7oż9yĺHkU+Âô°‚ î¸Ó u:\ňÂß, e ČސńC›1‘\[ęhžă;'šë@[ ]˘C˘ÔąĐYl@ӃkÉą€b\ÚÄX3FŒ•Ůo¨ËT×.ĚÍŹ#Ç֜ŸkŽP­uČÖŃŮÖš—ƍ™ÍÉě>fV ŠŇ #3Ś\gŽaʍ›11d‹ż KŁ?°#NdI™ůFÖíŁ/|OۤĚaű(ӉqçÜ!üÍ12ˇęĐ1ľU\“X‡ŕ„Ą`j­˜ĺS“†şm5ŹÎ4䜓ăšçľj ŸĄŹĚľĚ:ĺXęsKF ÇĘôâ{A'ţ6e §SHŘŹGÔĹýVłĘLYj9‡iŞe8Ń6篺1Î'Ćęď|gaŐĄe^ďĘđoŒżkÖ*}ůzęŘKa~ęxh6Z׼ľđˇżýđÁŢŻϚFçüľ^ĆňÉOţIź7/•xîĹŘŐş.ŕY€Pí•Z`fłYśeچĄ3<9ţ|Ćh™éaÖAߑgŤŁ>żĄĂŸÍv¤­žËag‚ƒşĽwK˙Ţěg6OąźíM=ţ+§N›.ŽĎL’ž€Ą Ď1ÍŹBŞţKf‡ˇË! i\ ƒ˜‡ÚşĘůŘ&‹ÝŮýkad_t!A ëk'4éV$%ú•XŸÂ­Ë"MŠ/™ÝĐ÷™I1jŸäŽ ‰mŠŹ€ą˙5zh†™´ˆ˜,pʤt<&Ł­u%›I +šŮlפÖ ¸ ľFĘ錔¸ľ 2 ŚÔížtŁN_BU8”şÇßńőş’ĹvCÎ$Ô÷ó\2i ”ŻcĄ˘Ua4}}}lOčŤkś(š\ƒ֞Äsç%“S’…€9ô†7Ü9ě~żŤhH\IăyŽŇ>/zBDŇbó]ńŢxăŢpŠ›Äź!óÎŽ8çw÷HqWÁrăĽÝUwGËđqÚl¨Y_|¤ăÉďZˇÑ´uĚPŮ)˛Kp0ÓPŘľ{W8pú@řćÁo†WN˝öt{Â]kw…=k{ÂĆŠWŐa¸ ;wţi‡a(˛_drčÓYaôEÁUqĂPdżđ#ŕbę^OœNÎiŚ#łű0ÎfFźá:á(~€ ‹Dć×Ű(Ž— ag ĄŻ ˜šÉA §ŽƒśŠĽŁ^‰aöĎż­CƒuŘ>4ő:ŽőuA ‚vĂPÁąPOĆpÚÍźäş tȔ1KNŔsąąYč‡Ŕ˘Ą.Śźv<8Žrőü0ôEF‘4xCŽÔ˛CŤ(o;8}¤´|Ă^Lmlť(/pi‚ZféQSF—Z˛ lƒá`݂ZŠ)ăˆËF3ô‹śxݏ.“Ľ…™uŠď9ŸĚÚńÍo~3ś›ţ1ś˛‘Ě–%xÂ<§ź‚ˇÖáäŇvÁ\ôďŽ=8,O]ľkl+낋;_C€Ś“(óČb#$ˆçÓŌ‡á}[5ď§| <ňČŰ/Z8×̘[­ăę]콢ë ‹{I˙AÄyËu3üČTéËśŕCçßÎCu’ •\$<ŻżS›ćÁL?žWÔ쪏;ßň>'—Óe/?+j Ćö+Öí3hł~k˙ěŸýł_~ąŔÁ™­S(÷›ü„°*~wŸoŞLÂŤA”•üƒ 2ŢďýůôäĄĂGÂČČHa4“ĆŔ¸ŁÎGî’óô‹‚śîŽŰˆĘэYYşEĐ ~x§ě2őn|$ÂČXYvlçu*ä*@&9r]&í˛l”ěJIcœn ,Ľ°d¨MzĆžĹ6vc?ťěŔGçŞY4ęěŰœ2˛)Bjí3ˆŇÇ]PČ: HRŞă”ÚxRÂvœ Î^J™uzá‰7|uú~qŢÖlŻá¤ô-KłvůƜ͊Πl›Rt‹s`ěÇ萢ŤŘ7ĽÜ¤šK!Œ€ÄŢĺC!d€Bŕ¨+pd(1NčŹĚ ÷éFŮ(ăőʀʤ+ŔMî0Ő^Ś•ĺňœM:<“Ї~Ó1Y|lŒY´úšŹŽĚď ćČ ťÖĂGßoxĎ#w…ŰYźŻĹŰĘԅÔkł€Ş_ŚÖFĎ&9A§"¨0Ÿě {nş{_MSL¨˙ń-ĽTNˆ˙áœNľ/ב´ĹŚŢÜĘXP.ą.nąGżŘŃG4wďޛ’vÎk¸¸eź`ňđRŻŮx,^pb/„‚z)M­$Ŕy0Üël2Ç/ľŃwX*€\.Ž]$qN 5 ř §ŘjÁ5tŒpŽt‚XÔł€¨aNşcď‘´‹7~ťóQžÖ„Ŕń4”OýžüöÍö…—NźvŻí÷ěž'ěęvĹPłĺđŁ> ŽĽ}‘B<­Úk Ç šĐ~ÚĄ6ˆŠe]äéÔŠc‚@˛ Ô"Ąn™ jc8ćÔ)EŢc°E{ƒz9TĐŃ0㏰ﮯĄ(fmĐ §/qÓ"ł:¸Ž†cę¸ŔˆĂůŐÉWCFć¤učüŤŐR×ÁůtňŠĂTŐ˛EjĐÍô˝‚K†nÉl0„ ‰zÔą1“’!eÎcCkvĽMŚŚź€˜Îc…™1§^tÓVÓfs­içažęĹ9 ăç‚ő¸đçžńş 687h‡NçÔůŤ…9}q{OŞ!d_8i›uČʢÔá}+ Ĺ9 Ľ2äŒ6Ęlň>‚áC=d2rԚ:2§ĚĹą†bšQđÖžDĄĘ“ÇĂË/<&ócQ ăjY`ť.¸S§ 5Âtí‰÷ŇĹtËl-[5C¸˜ ĚăZ c+–2“m˜ië‚ŃXŁÝxă"ŁŘ9äó›qć~X8×=V3L|fňžšĐňžăř÷VĘűnŞĎ>Ŕk ŽŤŔ÷ŮĘm{bř5 ž-) 7ňĎ,,‚,:ä5ŕ–ţÂ& Ë•ŃT™¸Knë•ů`‘ŇÝŽFaҤYr*…§dŚÇBČNčłZ׎ń4d'9‰aáł(~šxÉiΙdşúó¤´1 ś–°˘yZ¤,51´f@íMÜu‹˘ş4=ФŇî‰@ĘŚbßřßźˆĎ&@˘ Ą„L-ꑌ ‹ČŽék‘TŻş)uˆ§’YB&"t@ź9ęĚ1 pY-[,ăäÖˇoyP–BNć9ŐrŻyß<Ěs8Xšn‹ă[JefÉĘÚJŚĹnävŻ•ÔŔT÷/S˜Œ7şI ůŐŞÖś+‘Ą8n–y3#%ÖÓ%ąŰzfź™CŠ QŸĆ19ŠÝpqěň5î’pI!gadvĺ˝jLr)Bć˛Jşn“ŒÍűW§ŤÁ–qüóŽv7xd_M\ÜĽTĚĚásٕ^‡ŮĂČĎź— ‘Vm[ťĚŇdH“×›:œ—ŒŤsÂôÚ\3ĆÚqT7ƒžJ%“€sËÚ0´ęş,ĆOńRÒŹCńUęÂ4+”ş ŚśŚ-c†ŹÉvđşp.vçÓĐ2“ߙŃÇÔËÔM;eŮP?Ÿ)ÄčwRŢšîjŽĐn'S|—śrœk3ćŠĚŔľfd^՚4‚u†źŐ÷‚Ě0ƛë& ę8†â¨sRߓ‚–”ŻCÜLaN=˛Oh'sE°Œkćœtţ™}‰s™Q Óg ×ZĂ u2t‹:0ľă̖Ůn'S:đs鞿@ţk˝.ä|­młuóˆűú\eÚşŕĘŽ –ŰáoAZßU Š×>șę¨ ™S寄]M•~ ›ˆš*€Ţ#Ó¤›Œ;Ró„gq’q—!‘úĺ‚U†G íÚMŹ1ijc ăPҤ™"ŮgŰd3…bÖŁéč ÷łV"Ű$]f˝Č‚1(é_ôQXˇŒI.×UcŸŽ.;öłčä?~4–A#†kŕdfÇažtsI7Ťű&K%NţyŽĘĂ)ł4VrJâ:ŇČRŠ„kib7 ň*ôŰçóĽE˙t!$Šä(Ďup)§‡N/ţIĹʨ˛6e0Ër}RNÍOć…á°xYI×]F –p°üňŠ!ÁĽ¸( I[%j˘0׺•\˙F<3Bą%-ől^Ŕ=´2&]WÍËZ#¨Oó$ƒYŢ'óň"ÍŕJž}Yřcjń4•zћr˙ň€gœ˙}NnÍŻáƒě|ěRˇŻ,(ĄÍžmw‡—?5kŕrľMôMčů$MłTÔĆÂÇŃx`věaxčĄ/ËőÄŮbÜ8'™Î$HV/°jť\sŒçÁÓO?ŸŰo|㢐 ťŹgZhÚžKŐęK"s;‹Î‚ŠqöN•֏Că肞ťú”‡ęďî;ŠĚÎW‡ˆČžđů¨NKAr(Œ€ŠťB”Ą-ŠĄFQĚSƒó×íĎ>ܸíĆđś=o‹ě”Ó'OG0€cčőS'Ď9O.WP…cqćú“âؓc­ž†N¸;űfA05oÖ—ď¸o ť LG°Áp5]ŹCVc'ăAV@ęx˙űßď5LŕÄ0 Y&†\Ő4cGť9×Ý%ŻťŒ#56 -áČĆŕ|\>7̉~ŞÍb¸XMĎŚMŠó:÷` ńpźyFđ×IadÇÉóŠŻăÄi÷úrŹÂÇjţĐ_ƕs#ź Ć0$őBŢd1 ţ1j€Ć&;Ă5!L *RÖÁźáźôaqŒăźřÜđçß).lý†ÎqNţ6Őąl›:Ł`Ą ,ß f]‘!d¨ĄUŤ:5\{ÚÂxú|ປ˝ Œvp­¤ůĂŚ˛- JS§÷“óǐ0ŒąWwĆ N>ÔŚ9~,A \íkěRˇ‘÷'ş\ 2é¸9¸ŮiŇü?›i…\ęuěŠ_|!ÎqţÍüťëŽt-÷AQp,¨?Ţ+÷ˇuÁ\`$ş8p`žfzĘß5 ~>€†€ŒŮvTůw택­|Í$ô=íĆĎŮ@™ş<Ç×ÝjĄœŠŽe@Č÷đ,G+Ôß^K`劀*ýŇîx…fťqgžšĎĘ@LD˛ÓŞ^ ˘ŞŤ}WhVʼnĎŔĘČÚČéuţsxČ4;ńöY 5…éʍN‘&TnŻNľŽgzĄÂXȚýrßËĆrÓéz)âŽ~Œ‹[Ë‹œy¨_ԁéűQwĽ0=rJÜä4gfÍ$3múPŇ §ąhŠX:eLrZęŮ/!•K;Y0kRŚĄ•­ĹĎů)ŕpül>:úXd[ &čdKÎj‰Ůˆ ؕDRc†™ dÉ6ňڍc™BW ’ęݘmŕ*…ŇĆk™‰ľ"Ěń”‚šŘ5´c “Ą=ń<§7ňü ˆB]ăĂŚËs­6HQçóH$p1†)ĹůU!ň“8/óƒ2 ÷­Ä4ËÓşž7ĎĹtäôÎË Tş§2׿:|)†'…4ž]œžj-ôĺ|aů|]Ë۸J)xw.ĄĂéřŤo!Őuă‚fńaťő]+Ćä+_ůJ\ŒüĹ_üEűä8á\ýđ‡?*Ši÷o~ó[‘Ćî ĎBoxy</ĹűRçyć™ď‡÷ďţ}řЇ>Ű½öá(†˙$ŃĘ1Nů3ŸůLřkíŻ úÝwßţđ˙0‚D—ú:ňýä'˙4Î52 <öŘť‡…ÔOb[XŹ!–Çýɂ…cƖ…ŒÚ|~9ô|Q❎_ţĺż…čŤe~żôŇË1 5ôpéű8*÷Ýwď–5r6łYŚ˘{ϙĺGí 斻÷´ç\G‡‡6É0ԉ6üBçg‹ůŠsFy~Úč›œ;rf÷0‹Š`Çé\EQŘíŰâí´˙Čţđ—‡đţx¸Łż#źiϛÂ-;n‰ĎŁ‡–L%:‹Ś€Őáô /ô•ţVĄN ečă8 îĐ'3ę(|ç÷‚ ô2´[6ƒN8çĆáˆk‚ 6â`˛¨0…şuú‰Ż§AŒŤ ęFź–sQŢPÎEŚüuœqd(CÍd@˙h‡`ˆa[î6RÎl6\cù̺¤SΘ é„ pÎešvóďx žÓ1ásţÍX 6zř7×ĐLF\+ž;$´:8/ –żŘ` Š‚‰aFžL2%´Y{¨_Ń^ƕsÔ¸Œł ú.¸Ä9T˜#čÄÄü1üËĚ:‚8ôĂ{Ę~côŐ4Ň.úeË`ŚDö^—ĺbŠlÓIă\ŞŰÂqfíRWá[AGÇY Ôâ;Ž;eżţőŻÇ{Šzi“:FôÓ,DÖ!˜äýçó‰c /3´É6yýŽĆ{žqUŻ °Ëľ.řžÇäóŸ˙BY8qjxÇÝßË ŕ˝1ž§š&Œ+šklhÜ|3!]'c(č}÷ÝwIľC¸>€%ŸřĆ'žx<‚œű‰'ޟ3:Ý™Ź?úŃł1M0Š–šw¸Ţî˙éŸ~*2É.őĽl낳~ŒëCďKEa}/ˆ`ŸtĺůSë眫ý:ĘňĚ$ńLCžĺŒŃ|~nćşőP‡LÉ3ľŸ9ÁľĺÁłů˝ď}o|žb<× !]^?_˙L•ŔœÇéJDfÉaM¸É$:sŮ Ś`}Vłč'›ŮětdPŒ ‘EôR@F@$fc˜yĚēhż“ĄlɎi¨BŚ:aÁžDGX`zL28’üÍÜÎĚDčŤĐ—ô2ß ÇíŰwäłY”…N'+č˜eÍŮ6U†˘0ŠB–’s<]A€†ČlaAÜM€>gJě™ĂK˝ělŚ”Ç)ć6Ç;-1ÉÇ"¨w%˛ţĘ|~:ÔâŻ}aÍte\˘ă?”’5)/Úm{ŸÇ*∙m&26–Ë…źŁşhaəXÍěŚSqÜăŽcÔěoýތLŠIš„šÍNfpiu-*~;§|¨ĽßŠl  ĺašGÓINÉ @1‹óY`"ĽwNq’\“(œÓť[ŕă1•´z*Ąh˛d6WŸŇOşn‘"’ţۛŽAš†€­dmšž0ŒBXfv% măԉ4O†2ŰśďˆéQk횫qáTŰ2 ~ąí=z49Ą€=´/üŢďý~|Iœ<˙ü‹ĂËőMń…Ă Áxef†@ĺŢ{ď?—ÖŇŕĹůŠOýYœ3,Ň˙äOţ4ď¨öQŽE;/,´~ă7~shűÍĂg÷DžÁĺ0ĹżúŐŻĆĹ‹4 Üs,öëˇţm\$źýíoO=őTxôŃG†cţ4 ˙â(~ěc?gÚIšă>I;éłđçţd\Ź}÷ťOÇ6ăD~ç;;âgźĐŃ\`wţ—~éoEvÉĹs‘žł †SÉsJçYpÄÝ$ăŠ*óL§Ň´Ç8K8›î(›y†g ;p8PĚĘÓw'u˛Ů­ÇX$şCnL9m’MŁňů“χŻî˙j¸sýÎđî›ßśőŰÂą#ÇÂł?zśěöËt ~ŮuČĄťN+€‚ěÚ"Ó琚ánučlŞŐÂąüÍÂO˝îÇÄú§…˝:+‚ąôUaΔ‰âǑMÁuxěąÇâx1&ÔĎ}{…1ážfą/˜Ąx(ß9Ś “ šéĐŘxxeLh“ ŽŻó€yÂůÜP`,™CŚxVËEÇWMY2fŸĄ7ʘS܃´Ďe{˜ev'1É\ŃVÎË|5äĹyhhL)㦚śœ‹sşřg<¸çęđ łTP÷!mb>9ˇ)Ëř 2O¸v/3Ovń§?ýéls^)Żc% …6rí¨Og„ăkĚşĂxČţâsŽ;óăÚI]‚…ęäx?qÍ/dŃ$‘Î7’s0†œ_ƈŔ@“࡝ě×>đŘӉŤ÷Ă3WPǝpţ]ƒofÖRS†šY´mk1űĎěäńkbM€]úuóähZ™/żő[ż=ź7nŢ!÷Fö(ď>˛2çĐXázłé‚sÎz“šÓš~)M€9ň䓟-˘×źď*_yĺĐpßź)Ţsüüöo˙ťx˝ßôŚ{✔ą)­­ În2mŒzC¤śł1U°:„włÔŮç*Ďťň×~í×âsÓlgÚů^Á7ÎfŒ?ŕ#?żţëżŸażř‹żXÂ^]S\-ve4U˛ÎˆÚiă<…ŔZ‰NjQ˛6‰Ě Ă'˛Ż(ÁÍvň$ ƝĽœŔŠÚ'IUýtNŇÎ]čV‹cřnÔT1Ź(†5ä]˙ĐuEGŁłáُŸçŔˆăyblHtÓP ­šýĺŘą#ĂD؞/]—f™ö4h"Ňńb8ă‘鲜ůÓM“+ű%;ĚDęhuňÄńú!#e‘˛–Ď=ON7ÇđCšŁG0khűĘ41262UÜPÁ…’ąŠď h0qŒť,BÜׂŹQş&];ŃXŽyŚ+)äj–SwKsĹp§ÂŘéşqÓ1W…óéDfGj›7b<ćtZ¤L)˘°ĽB¤ô 4‘ý’X3ęÍŹlýˆnÄyş˜lÄ´á]WPfCźřwLy=ŸDFCZ´m‹őŢD›–őM–_t]7>ŕćŐ\Iai5ËŤ+l–€!ô(L„I ýeLâ ÖőéîíFEş/ń ÷R٘Q)˘¸9ć{ë;RŠŽŻÎîvv™>ôĄÄ0‹'ž{ꊯGX˘‡~K\¨|ĺ+_ÔŰóIľ|Ąë<Ş>Ďs^đ;;v pI*ÝýĂîóƒ…@Ű?ţńÇküôÓß] ˝TK{ôŃGăŠúYDőýJÉBńÎwž#>SŸ~:eůü翝~˙ .ç"{ŸÔˆQěˆŕ § #i!šââoŒcřśˇ˝uXŢÁ}á×g3SǀqaÁŁó¤Ă­~BlçĐűaüžĎuXÝŠL1¤ĹšÇłg“:X´Ź<ů䓱ÜĂ?\œ<…+ í0,FbČŘĐ†?|ćѕ#áÁɃámˇ˝-ěXËWf‡c}+ó†v˛P˘5;°BŕÄţöéÔť ¤ęĂ9xbÉâČâ öŒ ă ÁňoîUCŠpÔ‘ÍĂó9Î˙VÂđ)ÚÂg>ř`źnô……?çĽ}0=ęëŁn‰Bťœ•ú˜ď˛#pƜ:ř´‹˛†–°¨—˝c¨Ŕăe¨FŽ çÄńәçüŠô˘ťAď~÷ťKßŐŢÁs1.°ĽŚG-h*]°úeZÉq.sN沛4ŠĐň9Ž ˙ćÚňě0L…9Ź^Š22ndt žđ<‘ÁĂščߗžôĽXá0´ĹűPĘP4LFăĎ °Ő!j\DŽ60¨Ó]kÚŞ^ ‹ďiY;† ňRżâĄfČŕzP/Ť}$ă…ůŞ– ÓNÎcŠpwvůáşQŽëMß ¤ÝfŻR<š>ɜ2]´ťó˛ž^~ů•˜hr Ź °Ëą. " <[ŃVťőÖ[§˙cq]Ŕs…ďžüĺŻ,„>°Ž{ôѡ ×î–đĹ/~1nĚ$ÖŘĽ;ˆŽ `ƒŔ¸ŔŻJá‚âĆ mâşóžűđ‡?×>+–C….ÖŽĽuÁűŢ÷Ţ<šňëćóRÍ+ĺ ÍřäűëčűďBěţčÂŻţꯖAlŒJ8?K‘ú#Ó .˙gögĂľřÔ\ýRř™Ÿů™řŮň8\h—ŇŽ¨2ĎŠo“ł–+! „t)Î6Şro$ąÎŽ+€€Ž MA­űČ0yˇE§?í0ŽŒ”¤WąRBƝ|z^—+ݨᲹ‘œăĚLbť˘Ł28łźŃ‡ŐŽŒz,ěúVLDş 0„ę‘`+1ˆś=z8–5ŤďÔܤ–ĆąŃyŽ!…č̃á „‘íŁ6ŠLŠÄ49ř´#ÂîWZÜ V$€"…MKšyqÄy ŽoŰëb̡mŰą ›Ć{Z/ąM} ÷‰ ÝBWu:řŰĆĚ6ăů˛nL/˘ŮcČBĚ]2”ŤĎş9}WƘýÉĄŽ;wĹëwX€KúŮöáXƒ<śCݞ(n+˛1˛tâů2 ’šjČY_B×Ň"q#"ŠĎ0ś  ň•(‹ŽŔ ;iłžB…2ƒŞf°tÝ8_\”.)]™łęÄ$0s`âÂt8ßĆńt ú.Űb&†œ&şË™śňŐŘžm5źáŽKxVËŘuŻ=ĺ7ľc|nŘƸ›ňXě×ô ĺ&“s]t XÜKŁ'­Ţ‹/î‹/z)Üůȇ‡EřŽźp/]ŰĐlŮqšĺ–[Ď Ý?Ÿ6iî^~ôŁŽ‹h-ŇĹi)Yěę<ţřű†ż‰őłŕ#DčĂţđ°8ŢÓ^JŘš÷Ţ{"ĐôÓ?ýąÁŮź7îţŠđýď_=ŢőŽwF 4ßżúW6śÍ°‚Ë1§œďyĎťăÇ!Ľ‹˝':3,&YT‘fű–[nŽ€”äؓďˇpŃĆýĹB…Ĺ™ş,ŞëôÄľ8›˘˛9p¤e/ă=mş[ć¤ďD\Vô™şaQąŰĆÜa᪏šľLv&ĐůFxöŘłás/}.Ü˝ăîđáŰ>f'faßsű ˆS31řŸz裢Ź|g†úĂšĚĚâłGŢě%”7$Ç]ŞÄb=^SO3`8›Î!ƔëJ;i‡`’ąâ>´ œ~s<á>$2"řLF!?ôƒń0˘ü'?ůÉXÖ4É-˛ Ç؁Ց5Çţ:N˛ÝÔÉŔIvŽđ7tlÚ¤X°cKű0ĆÄŹH|O}Ěeža2vplxśń\°°2ÎúP˛v•%Ĺ9dŃgĹ`šŽ˛t8ŕ‚:~EjŠS&ĎQ-€ C’˜Œ?c Pč,má7÷„a@Ô+ĂI Ą0ԇa,Ő  NőYh‡°!5cÇxɌb|tvƒ8FCyĚ*䳌r†Š ö (ž…Ľě1/6 cš8 ”÷u­CÝĚ+ƗÝu5š¸Ţô_f„!Buř˜Ě5ďAëŹ%úh cG@ňЏÂęÚôŞ\`[]œoÝč¨đěLŮČvǔÉ\7€zր„ŇüôO˙tĚëáÎ;ďďxÇ;â\ćůńÎwžk˜#ˇ•ĐĄsŸ3ł*Í™¤>ž|ŕ§âü“EEYŘśo}ë[âó”wďBށ”aƒč‰'žˆşQÜwĚßsŮůŽU°ki]𜡽->kŽäş€űń…’™Ď2jë~ovík†˝Âśfż“áşYy?ŻËţ;żó;%ƒž™ę.ÔdňLŮJĆ*}öů/˙e|p/])6KwŸwŐßţű‚S*>Jř@ [ 2‰ –Ĺp™t’Q śËŠ”C?f…3ŐlDŔ`šĂKbxQŹsR„hűš‘jçR ŠI™4ŇÚŚY[ÂŹíLlľ_’.†)ŒCfg”Pž/ WS p ?Ča0šd„ş _uUrHÇ%ӕŐ<đű4iş8ńđN)’'Jeť˘R_X !”…vbé˜ZX`c^Pí‚ ťJ§-tçŽ])¤ĽŻBxBMÍý(F[MŐÄSrůđň〠!”kC&#;# ͎/EAĽŽ…nC¨ŻCçĘńciWPc}m=†á(”\*](a5:%“N—˜3ÎC›,(¸ËÍG&O ]ÙŚlęKČTWÄă|Y80łâ΢‰yŽůⲝąÜlVR:ú5ótM˜Ę/ôăC†zšŚ|śš3`jŔ¤ŒMŠ„úżž: oŕćđW>ü–áĽˆŁ°^R'ŚEĘ(xőZ,¤ź–i, ‘›ĺE31Ë'ĂśÝĂnřÎ[â3fšlĘppôŹ‹”úť­"ă>ÎuLʲíźÇŇűč|Űŕńu{.ÇuëŤçřf‹ŔÍÎYŘlç1VÓ.Ď3žÂŚc˛đn¸D”cę;räp ˙1Ť‰;Ă2 tu4Ý˝Ś,‹Kuć<ŢçŒYD…UźÔl:8˙ľŁ‰łÄ G:tş¨' Ôad?źüBřΑV_ ďÝőŢđŔí$p|6/! ʞP§´O'P ˆ>b8‰ę\řú.ԑBŁÖK¨ˆ!MŠŁšőPF† 6ł) ”đęÜ(Śëü3Ñ!`2 Á”Âń°ä|\Gç´ŹűĂX´`ÜqNr\°3é§a3†ä=ţřă%|KŽóƌńÚŮ™ ŠčšFZŔÇl[\kÎO2FčŁĚ"&ž3”ËŒJŚ%×iŞç"Ç*ô즖ٟ¸v8[´]śőŕÓGdôQáZęTŹeńoć çŁĎÔËł@€”r2q˜LvçÝżüĂázŽ_ukěbÖzŽ>oX^Hšú=s!cÄőbóä\̅ú7šçÜlSńÂ× ¨ŢuΰŽĺvľuÁŚ-Čéśx?›Áí‚kéS(Ľ!žrm0* ko–lá|ŰĄnÜVSPťńá{öW~ĺW"Ëú|lx^]ö”ĘWTůČĎ˙ݟ<řĘŃĚFI™E˘vˆOv˙Ÿ5$"đ1ŸgŔ"ékp`ÎxœŔ!9ŢŤk녱R;ću„çËŹůŃM xËeŚG,wűť ň¤›hĹS—3§Ěƒz%Xʊҗ°%Ř-ŁŚÉČĚHYÖŁ~FčFf†ĂíƒÎL5€Şƒč,‡ČŇI`}˙‰L˜nyőB–p'Ó hMdéÔéšGЀ$•ÄL0´C&Œ Y#Ś+!Ańœ“œ )_+ƒäřw#B…ĹŇ/Œg]n’Ëůů8ňß]0Ňő^˜`Jě‹ČrnHú˝m=euG;`JvF<_ŢŘç9—€˜úĄ>}ÂŇçÝŘ6És8˛Ž2›iŞ&Ë<ĽMŽËÉXJ×8+n5΁ŽIŃW))Żs6#™:“jžç ŠZ(ůä0÷¨+ĹÜŻÇăçýŤŐŐŁŹí´zIôá ˇďýc…7Ţ9ěÎ bčŽ+yÇŘÔĺtÎĎeő‹ĐĹSbŔÍb,îńaĄxętöÜ|_XYŰ–…Ď"+Ń<ĎoaTżäÓßń˙ĂšvÎfž|Rʸ­/ň–ĎőęEŐâ3çrÚr{–Çí|Ę\ŽvÉ6żKÝŞcńTg'ÁŠŇy4TDpÁL* Wš!GgŇ´­†J`8kfJQ3DaQžÓqÖŠÂqڟ8}w ;Ş+ë+ᚣĎE픢÷ŻŢşyu÷‹úĘÎuv&q†qި_-3°P䎚†ŮnÚHęŠČh 1d2żŻjPĘţ zPÎ/`‚"”á;œdŽ7E0őCáç°68ŢôŃîÖ˜J’zĽЍCŃS54dˆZ†ó͘@{hЉ7‘Z2UpxůŰ´Źę™`˛c\,/gRÓE§]PJA`™!čÄJD&ŇP–6ÚĘĆĽź˛´E6‡ăâŘĘ\aŒ$6űŸ›ů‡ë%ŘĂ߆dĽ ‘EWGaVĂsSm3_ŠÓś2ć€Œ™<a˜Ď˛hh'ma ü?ĚjO˜!ăh }5 y­ń#ľ^a,…XŢź(ʤ†ŒŔ†×ŽńôUˆqVWG“Šžic OŒDÎÍXp÷‹ !g5 ÍžţE_ĂŸ>S<`ŒŕVĚPňň‹áĐKτíŰV†ŸmWݚťŘuÁŜł^Ď×/łľąI@ç‰@žo™sçónŽăoý‚űŃÖ›Ÿ{#ű/ŠœŸéÜu™ĺże.ƒ2çSď…úO˙i|–žĐ(őe#“ śmyžŤ™ĺ{—śüóţĎË{älkÝáŘëTůř/ü'OzĺHv&s;ĘÓ$”4łńD ‰EŁ"k„Œ (Ěç‘ů‘őźťƒNB¨41`w譗:'Uć"2[ E q™Œ!5fĎ)‚˛Ůé]ˆÍŔM͘ĎGćŽjtúç61V˜":g†É N 1IŠ "’`ě˜V9˛t,ž/•Kz3”ëmiJŘ˨MbƙÄŔ H‹ř ˜dfHÜńŒNůZŠG@D E6J_@Ź.ˇšbSĐá $€b3 úłu‹ě”t#ĽńěÔ^1„,ďRÉr™ćrdŁĐbĚRXs&kśtéŘ†Š qbäjł’ŻUfęäÁtĹr˜ęËl‚é’˜HcŚŞÇ:„EŚŽó,„‘Ín´}ešŽšÉ9SRšoú ˆd– ó€ÉlBkkëeá;Îťy™ó2nFoXźçźĺćíá/ýÔ}áţťo‹/Ov×ă‚í*ڑÂδ+•ô–NşS]¸á–ű†ą\/;Ső‹ůĐůĺgéĺ7•­žÄš][S%ĽgÝ>8Q8<:v8j:M†H˜ÂŐě6Ěœ őP0ľ:tÎL•ʆ ‹&9üč4S/Ν̗ď}˙{a˙° =ťy^™źÜń`xřö‡Ăśľm1Kš$5ŤD †ó*ŇĘß.ŒXéđ*^ŞŘ(ŽŁ)o…AÍŢc؆:!2(¨CçťîŤĚ5Śe ‚ĺb Œčݔ…šaŠaŽUd•~)NJ9ľYĚ #ŰFqOAœŕ0˘†8ŃVŮf…áňĄ†\g“PŞÁ3uĎGŒް 2pý`yČ14çQ,YD@ɔÉÎŻĚĹ}ĽŹóc nęÂ|ń:Ërá;ŸyÎ÷Z¨×9M[ 1ăsße”‡E!ŕÄwüp^úÉ߂łüN`ĚM',@Âyč;í1ôƌM\Oď“|§žܢ:3hÉjQ4Ř,+Žçœ˙žďZWę1Í7í§.î#~[Ç0we¨8śjřPO­Ed–Eže=¨ŸD[(ťˆ>q=™ł7ß´7n´<˙Ło†iˇ×W뚻ŘuÁŐj>Wi˙âćě•1UÝĐmviěŔý1\[ĆbRˇl5Š –őçłöBęř˙â_DćV-,[—=Q×ĺZfšŽł{ËuĚ"ÓZüxĘ"^ű˙á?ßVŽœ¨ŰTĘepe>€ˆş%Ťi Ř ĺr]Ű řÂed“äqěł#Ÿ™)ËPÍÔIĄFÉŮf,Ö ŇîM9Ë‚Ś”ƒmŮBü—°4ţ# %Po~^Ćyšľq>ÔŔZ?)ý˜b˜ŻW2㆗bÉ„6ĚĘZÖAÉ T賞K!Ŕ” hwŇ™ą›ÇMşZŤ.m‰‘2^ ľ\F† Ť‘u•ţ”žĎL ČUĺÎ !3œŹNiœ4wƔЉ‰˜ł#‚c‰7-,­dFY™’rš“9fĘ!IޓAVĹdKNc2đ9ě2î\oźuGxß;î ˇßvc܍"ƒM­ęŘéŤë…šÚ”~GĐ)Óŕăçˆiîv×vÝ:ěÂď Ś.×V†~Żlż´‚­lÂŐŰÂś-qßżúłĺďęc6;ţlu\ŒďšÎ§SÇĹŘĺîC”‡îÝ7äđ•yœ{Ã84ރGź2̃´ómśœŰoť%ţÓÜ>ťĎ…Cv2Óórmx>œ:™ę™mœ GţNiPůšăö[KŞŘ}/&ş?÷tĘř˛->łnťďćaaör˜Ÿ˜‡˝űö„ÓëĂÎWˇŻd*ٖÁ…đžîHŮľ4ŐmżśϏƒŸqý4ö‰cčŸżáÎŰKJá?űĂř̢Źz%ŘúPOÔŰ ĂČ00Ǐ éX<ň=}Šz^Žżvh#}Űą=ą4^|áš,Nž-;šh†ţŕ™pď›î‰Ŕm{î'ĎÚqbP¤śĚwƒNŸĆôxzSŮPn˝ĺڏ°}áůŸ”]CÚrĎÝÉů~ëĂE§™ô”ź1˘œ)’™Ôubî?œ+Ž×°;'ƒBą_ĘDëôÉpňDzďĐ.Ćĺ†=9ähčuŔÜŔ˙鏴db\žîÇqÜ/ę颚Ű<śeĎît0v”áü†*)˛Ę÷ĚŠ(j;”Ľćô¤ëăőâїW("Œ/ăBý Ď*´G§Ęő;`›Ś1§?"\ŻťŢxgxř-Ć1!„ĺËńĹ86„ÁŹŽLb?víÜŰŘĂy^zą€Ř´…qäţ2e0ߛZy÷Ž;âýĘub\÷í;URsوí’*n{řđĄÂa,Ɣv1˘đń0&Ǐ%p)ŚĆ^e3cö^x~Ńh‰BĂXěîUęăÚńœ¸iďía˙Ëű sňÄąpă ťGĆŇpoĐf™5œ#†lKŒ,ŮE\Ł“'ś•ť›öŢîżďMqýń“Ÿü8<÷Łď„˝{ŕimCŞŻ…5v1낳ٙŢŃő÷›˝Ćvů¸3ŐayČŹÓí—VHöB,žËć§Ď Îië‚sĎož/ůą0b´KŽă˙řÂÇ>ú‘¨ETű›őx\ŠgĐaŞüęţ˙{ňÔÉSůßWŐőŐhŒĽ‹L Ŕ—ĚÜH4š,ČrřD–𕤤)1ŚŢYă9-3†G¤‹”Ú0Ű6ďFÁ¸š`„*MUnŽČmš#KŁŤĘ9!˛O]tĂvj}v)żšł E­‹>kŤ„PtFĘËĄ0’¸m—Y Š21"⇺³¨b}ËtEAĄć“î†Â,ݎŒąďľńâӍ@E…9Ă˙ܑęó„ \—yKJöĄGmgŞĂgńŤë[8ňŒu×í gíĂćcŕ}úęq˝°>lֆĺ㖿[źgďWˇŻţ[œ6Ť†ăc”č Óź=†Ü­•ó˜J×]ž7äA ĂKÜÇÜ9÷yJýfmĄţž28h/|)iłŹí k“ľČžŕ8œnĂKĆ÷÷Ź„OX‡ěʸó/[„ť _ˇEĐGa=ľżő=ć4 ˛"­X ă;ë7Í­× ç–Ďde*#sđÄké¸,™Ą=2eřˇťľRĽÝ•Ł-ušŰ:.]çVPƒ`?Cu\Ăuا´ë~˛ˆŒFÇźŇËâXÓnˊńúÉÎsΖe,|­ŒóZR§çtŢš°ě“í`† řîÚZgAŞłJÄ0ăœ)BÚ8緍˛vjVőÖ4y™Ěţ #Ăąľ-^ϤM‘„Ą“ŽŐörŸšNZ­1çiĹ;Ś Ţc‰yśŁŹźFő˜Ô@ŢŰÎ[3ÇQGVŐsşpšăĽů{_™JŰ6×I QňŽ=Ÿ9Ţu\^ç.ë§ăÇűwł<ˇŽ5v=Ź 6{ç´uÁŮ׎ĺV×›{9×]ö/.FDÍŞ­ľţţüqř­ßţ÷™V~ՅšÉJ&Ĺ˙ŘJ=ýčn˘wôó?÷łágţňÇÎXší{îôú˙yúŠ?}r6;Ugú}6;s™ńć gŔGĎuދ9˙ĹÔa›ŻT;.eÎÔöË}-/ĺ8œąáܡ|żÔZ+xŐçPǙ~oĽŽĺď7łÍ^ž~îď.Óv'Y§&Q÷Ś™rž4}|P^‹'ly% oŠîç™čÎq•ő{mŽË_hż6[ä,žř/žŽóŠků˜ Šă\Ç^ČůŻÄx\HŮs}~ŠűđZ_ËKюŤőZžV÷Ôk5/E;Žöůx!v>}Á6Ť÷rôá\ŸoľW˘Žĺş0Gp^L2ËřZ[`·ś.h낋šwŻ–{ör<ĂţĹŻţ—á[ßy&\ ö–ď˙Ë_ů{gě7‘÷żýĂ×GřĎöëÃčʤ3jÖŹŮĹY˝J Łqˇiš5}ş0fUňťŤuńT?X'IÇ7„Ă׆˙&kŤ…úîŤŢaĹüÝŹYłf͚˝žěz[`m]ĐŹŮŮmßKRr’kŔö˝´?˛čĎd“é;Ž ¨•ĘçMhąYłŤÝęŏ‹˘˛H ă‚jünń¸ŤŐ–Ű–QUx\7/"ĆîZՋ'Ź- š5kÖŹŮëÉŽ×5ÖÖ͚ŮŽ?ž˜ůó*6ڊ@ö™Ź›\G  q–ýüę~¸6kÖ,Y˝Îč*-ĹŸpŐďDmfu{ÓâhqĹĎ¤Ë §P/œBłf͚5köşłëyM€ľuAłf›Űľ”yňlÚ3ÝäĘ0nލ˛‚rvĂTš5ť&lygjńwxŐÔľ´xÂjÚďň" یÚŰvٚ5kÖŹŮëŃŽ÷5ÖÖ͚-ÚľvŸ-TŠëŽ#P%ek ͚5ťĆĚgę™vŸŽĹĹć˘É×űŹęÜŹYłf͚ť^×X[4k6Úľv/O_/ JLŰD͚]“śŮƒőZ^8iöĄ^Dů;íX…f͚5kÖŹYe×ëškë‚f͒muކówţîßúČÇÍ7î=ëąňÇţőýŻbĆ­‹1tžÎhWčĆ˝2 JěL{5kv­Űő˛pŞmyUÖŹYłf͚5ŰÜŽ×we[4{ÝŰçű/ýň˙4üőżń7ĎëX@—żń ˙“¨Uôk˙ĺ.ĆÎz^O JłfÍŽ{˝.ÎÖď;ÝŹYłfÍ^özÚş Ył ł|äăń÷˙ń˙đż ßůöˇÎzěC=ţĎ˙×˙{řČGú˘A•ŤÁSĽYłfÍÎam‡ŞYłf͚5kŚľuAłëŮś:ťoÜ{SüýÝPůŻ˙Ío•ĎŸî'áŸüŁ˙háŘď|ű›ń÷ŢĄĚĹŢMŠŇŹYłf͚5kÖŹYłf͚5ťŽě•C‡Â˙ű˙őŸ…ŻíŤázˇk'ułf͚5kÖŹYłf͚5kÖ쪡˙ç˙ă˙ţń?ů߅ˇ?ňŽp˝[Uš5kÖŹYłf͚5kÖŹYłf—ÄůůÖ7ż™*˙č?ůOĂŰŢţ諎ůťżôóńçz°Ş4kÖŹYłf͚5kÖŹYłfÍ.‰ŠĄBčŔĘß˙%\ĎÖ4Uš5kÖŹYłf͚5kÖŹYłf[śöGá١<üśČRŃVţ÷˙é?ŽBś<řPX[[[(węÔŠđÝď|;Ę_ŤÖ@•f͚5kÖŹYłf͚5kٖ֬í“ôáţćß˙§˙Ëśđš!><đŕŤŒĎřîóŸűL¸V­*͚5kÖŹYłf͚5kÖŹYł-ŰŻ˙›_ ýđűŁýépÓ͡źęűľőőřűӟú“…Ď?𡏔ďŽUk Jłf͚5kÖŹYłf͚5kÖlËśąąţőŻýŤřózłŞ4kÖŹYłf͚5kÖŹYłfÍ.›:y22R`Ś,ŰÉ'Ăľl-űOłf͚5kÖŹYłf͚5kÖě˛b´›'|öôwżŽekL•f͚5kÖŹYłf͚5kÖŹŮełƒ„/|ţÚŁ=›5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XÓTiÖŹYłf͚5kÖŹYłf͚…ÉäځŽ–ś6PĽYłf͚5kÖŹYłf͚5kvďŢŽťZÚÚ@•f͚5kÖŹYłf͚5kÖŹY¸űŽ;ĂľbWK[¨ŇŹYłf͚5kÖŹYłf͚5 o}˛õbWK[¨ŇŹYłf͚5kÖŹYłf͚5 ď{ěáZąŤĽ­ TiÖŹYłf͚5kÖŹYłf͚…;ď¸5|ŕ‰ÇÂŐn´‘ś^ ÖR*7kÖŹYłfÍÎËţÍűďĂďţÁŸ…çž{1Üyçmág˙ňĂ/ýâ˙(4kÖŹYłfÍŽű…Ÿ˙+áÉĎ~)Ěçóp5YhăŐb TiÖŹYłfÍ^Gś˙ŔĄđĂý$9r,ěÚľ#Üs÷ÂM{o8gš˙Ď˙÷ż żóťŸ,Źü˙˙Ő^|qř_ýGďœĺˇzŢ×cŮf͚5kÖěľ4 ˙ŕď˙­đŸ˙˙:\FŰŽ– Öš5kÖŹYł×‰mlĚÂ׿ńÝččcüćo>?›í{i˙ RŸóýĺ8ďëąlłf͚5kv5ŘÇ?ňDřĽżů×ÂŐf´‰ś]MÖ@•f͚5kÖěubǎż Ďľ}űö_Ô÷[=ďëąlłf͚5kvľŘßřšżţç˙áߎá6ŻľŃÚB›Ž6ká?͚5kÖŹYłf͚5kÖŹYłWʐ‡zsřÍßú˝đé'ż^ C” •Ť)ä§śŞ4kÖŹYłfŻŰą}ű}ŽÝzëMőýVĎűz,ŰŹYłf͚]m˜ń˙/ţƒl|î _ßřÖÓáGĎ>>rÉĹla¤ěŢ˝+Ü}םá­oysL›|ľ‚)ZwŸwŐßţ{RýögšVňĎÚđł:üÜxú•§Ÿ }‹#nÖŹYłfÍ^kťTBľÚ_űُ6ĄÚK\śYłf͚5kv Ź›†Ő=oF€ĺŕđszř95üläŸYţ™W?}őťĎľÔ˙K˙N§ g8ýŇż¨ŇŹYłf͚˝Î­ĽTnÖŹYłf͚]3Ö@•f͚5kÖŹYłf͚5kÖŹYł-ŘUšŚJłf͚5kÖŹYłf͚5kÖŹŮʁ*͚5kÖŹYłf͚5kÖŹYłf[°Ş4kÖŹYłf͚5kÖŹYłf͚mÁ¨ŇŹYłf͚5kÖŹYłf͚5kśk Jłf͚5kÖŹYłf͚5kÖŹŮ슀*?úńsa>Ű͚5kÖŹYłf͚5kÖŹYłf—Ű&Ó+Ă!š"gšëÍď͚5kÖŹYłf͚5kÖŹYłfדľđŸf͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹYłf͚5kÖŹYł-XUš5kÖŹYłf͚5kÖŹYłfÍś` TiÖŹYłf͚5kÖŹYłf͚5ۂ5PĽYłf͚5kÖŹYłf͚5kÖl Ö@•f͚5kÖŹŮ˙ĐŢYŔKQ}qü"‚ ‚"ˆ(bbяî;$¤ĽťIiAAńŻŘ… 4*%-J¨Hüďď}ZŠ-éů>xđ@‰Š*(ĄŇŻßk˛fÍú9WŽ'dęÔIB!„B‰{hŠBâ•sçÎÉŽ]ťdüřIňĘ+ÍtRy=päČU¨€cǎ˞={…Dž#ސ6mÚËG},ǏŸ˙ţűONžüC>ýô3éÜš› 2\._žđř˙Ůśm›L™2MŞWŻ-6lB!„B‰o¨T!qν÷Ţ#Ůłg—GyÄË2eçΝňĆcäzŕrĺĘJҤIŐúáÉ's ‰,°8Yźx‰ç;ŹMž~ú)}ˇXž|…|řázż×¸óÎäjídŠş=zÉçŸ!„B!„ŸPŠB✢E‹ĘěŮÓĺíˇgˊKäŃGőüöÁëäĎ?˙”k \Jzôč*7Ž“aÆHâÄôŒ‹4ŤWżçů ĽŐ˛e‹eҤńFѲP2eĘäůíŁ>ňů˙ŹYłĘşukeÆĚ9Jßž˝%eĘžß,˙ţűŻB!„BH|Á™#‰WîšçiذžtďŢKż_¸pAvîÜ%šs?'ĺĘU”ŁGéńŽ];éů­ˇŢVW˙ýoƒZšüő×_2oŢuËN˘D u˛]śli)Uޤ*G~˙ýwŠTŠšÇ¤]ťÖRŁFuO~ůĺWŠYłŽçű A$[śŹRĽJ ĎąqăFkš,`ńÎ;‹eűörúôI:ľźđÂóRŻ^mIŸ>˝žÓž}GsޗúŠŁˇŢšŠŸˇpáârńâEý>}úəóqýÜ˝{O}‹žŐŤWę3X>|DăÓXĎŇśm+“öŤéDÜünŃŤWw)SŚ´~ţő×ßdţü…ĂäĉjĺńčŁYMŢT”üůóyţsŕŔżĎ~ôčQS.•<ż˝ńĆyéĽeĺĘweđ࡞tϘ1U ŹqR×-[6'uęÔ2i­ Ÿłf}D­‚@ňäÉ5ˆĺ~eĺS î¸ă)Y˛¸¤M{Ÿ´hŃZ8qŇԓOݰĎ˙Řë×čŃ#ľîMžâĎ ČcXů¸áŇĽK˛jŐjy˙ýľ˛gĎ9wîošűîť4ŽMĺʕ´< !„B!áAĽ ‰wŇŚMëőJ '˜€ZĘ‹ƒJŤVmcŔýá‡ÍúÚ´é38đ5š˙ţűu’Ž|Ŕ'ŸlňRŞ|ú駞Ďɓ'“|ůň¨ňŔ“'O•Ůłßň:Ĺ \U>řŕCU4Ŕňâĺ—_ň(U0yEđ[(‚śnýÉKQ°eˏRw‹—^zÉKĄŇĽK+Ď>űŒ™TŤßĄ4°+UěVP4DEşň̟JďŢýTĄcqňäyů⋯ôUĽJeU"DŠ~ýxňŰČ'pÝůěł/dÝşŤ.?°lr ”=ôüöŰoú}ÓŚM~•*vĂeéŇeŞp;vě.]şIݤ[ˇžžň‚bĺ|đŕŁlşęŞćŤN@öŢ{kÔ}ŠgĎîR˘D1Ďoë×dĘŁŻç~˙ýˇQDÍň(y|2ěŐŤŻ—ő Œü‰Ö(ŘěőÚb ‹0;VźZľjn^ľ…B!„:t˙!ńbŠŘI:UŒs P bąd̘QőîÝߣP˛ĄAƒzRşt)Ť‚•bW+ (\ěq1‘´(T¨PŔˆ>űěsŻÉ3&ěőë×Őř0J>}úŠ%Ož—=çaR ŕT6ŔšŔzäȑŤĘ_J€g´Ŕľ`­caĐUPă@A„‰´ĽPuCąbEÔð\ˆ˜ #]÷ݗFräČĄ÷ ĆŢ˝żČ‹/ć5i.f}4ďż?QhtvĽąóčŁW­B Řpžĺë‹?ţ8ĽÁrĄř€Œ]Áőő×ßz‚úé&Ż:x<Č_+6 ‚ďžţúPŮżż~GÝ6l¸GĄ‚ëB‹“wß]ĺ3}ǎ“ţýx*8ˇQŁFńö‚~‡ĺŇŘą4ŤťBŠžž=ťyŐ)Xë\.x„B!„܈ĐR…ÄpˇřţűdęÔéžcpCȞ=[Œsq|„q7 ("~ţůgýœ0aBóŰXݚäȑMw•+VŹR—XlŒ9Z'¸PpŔ:“u($,Ľ°+_|ą`ÁBĎgLD{÷6Ź/5jÔÖI<#pÁvŔ>ř g2ôÂ"ĺÇ}+UěV*‰%’^Čí3 … áĂGŞâóM›>×tCyňÓO?{ÎłÜ~`-qöě9O^M:Ů(T2i^4nÜÔŁÔZ°`QĐçw îÉşÓŇĆ-Hçd0ŠŽŰ%T’'żŞÄÁÍn€‚iÌ)ę‚Ôľkwľf˛ŔvÄPb@éņÜŠ˛dyX.\ä9†:8gÎ,ľ‚ÂnePfA˛té ľ&ůâ‹/˝Ňːھkéç &›˙ż#}ę{ćĚYý KÔwKů‡ źPŚĄ.Ź\šJÝŰüqř°ˇU,Ry$‹”-[F;P*eĚř Q„Ý%„B!„ĐĄR…Ä9˜„Ú'˘vęÖ­íÓR. ö¸›7oö|Ćd˛reßnpťÁ*ţÝwß­Ťúp“půRŽ&–Ĺ,+‚ĹĽřńÇŤ Zľ[ľłk×nUŞŔZĹRÄ Öîe)>`uł}űvݲĘÄgą€ťŇwúśđŔÄJ"Äş|ň‰*C>úhŁ'Ö &÷O=őä•4_UâŔ˘&sćLúůśŰnSkKŠ—XQDÄP EĄ’*Ő˝§ƟܢîM°Á Öíۡq}­łgŻşŮ×qDŹ]„`!d)UP' P äóú•W[śüä9†2‡BŔŇć‰'×gx.€¸(v,ĺ¨V­˛OĽŠ˝ áڔ?”řb÷î݈lٲišCĄę×o¤1ˆ[çąÇ˛Ťr V_„B!„đ űšfT­ZĹłbďÄéBrę”; XĽXn/%J”đG Y(8žřâ궻ŊS ŔÚŔ“$–eHžĂmÇ I’Üćů +!‹ŰnťŞŕ󾔳N¤Kç}ż´iÓy>[ykžÝâŢ{ď_¸­ďV˝ó&ˆc)Đ> ŘC á!C†›:YUŢxcŹB!„Bƒ–*$^xńĹçő;¨ E‘"…}îâ”)ŻNÚa}í™ƒ‘7ď˺㠔؝e÷î=ňíˇßy~ćúrűíˇë$ؚD2H ,đ?°ÁŽ:púöŰhŤ(ođĚN w!XŻŔşĹ"Ož<Ż ‹XŁ X/&҈cYBŕÚĽJ]U ŮóęČoĺ„3 /vcr*0ěJä[$@L›éÓgyž#śGŽŮ=ßa‚8' ŁJš4i‚^;ő`÷‹`ů[œuâđaďü°ÚŽŐwťK ܊°ŽĹŇĽËŐő@1ƒřÁŔśł7zďF4iŇ XŠ]ZŹŕąpľxîšgô3&Źď˝ˇÖs([r玎›Ľˆ¤n#™3g’`Ř'ؚ1j@îÜĎzí¨”+W.Ďg¸CYî'8ßžŁ\CG–ƒv4˛\¤g‘.2"lš‚;Ţ(‡˘-xΜ9ŁÖ)v‚Yœ@9Źˆ/bř PÄ5pńą@ĐÚŤ –#^ŽAPT€‡Îěőˍ /ěő1Y ¤ł˙ťáůą °ť^ý÷ßĎg¸R͝;Oƍ›¨–Qˆż2iŇxSďxšÝĄMB!„BB‡–*ä† P„ †\Z´h%ĺʕ•óç˙“wß}×ăbœ˜jUzk‹­q-J”pˇm/\”` ÖŹů@'ˇŘáćťďžóÄ΀űČâĹ <.0ˆŃaĹrŮś-:í‹/FďڂXH\0,°•˛J•*)Ó§ĎÔ8*ÖË L™2ŽóJhœX´ ݚ6mŽą^vîÜ­J‹5Şé;,*° ľ5AǖŔ( ĹĘ?˙ü+‘Ž4(›%K–ęw\żTŠr’>}zľÖ°Çv’ǝěÚľKŠ)nŇuŮKÉ`ŃŤWľ$‰k $´ĘţŔRŻ^#əó1U~X (,,wŻ^x^c˝œ:˝Ă‚Ób*Ô]+ř˛Ä]™;wžn˝ KœŚM[jŔbäčZJŻž}{kŮÝ{ďŐ´ <ÁŽTíۡ•ß~ۧ ‹ăÇOhZwďŢë•çٲ=*„B!„ĐĄĽ š!ŔJü€ý<Ű/c_X‰Ě›7ߣPAĐMěŹbn3>jî2ŊšSŞ`"‹I´”%SŚLóLŞ‘.¸f`bkákkd(SvřąÇđÁâŠXŔ˘ĹXągœU7“mKÁLÄí ědwzőŐĆ^×ŔäyŒíŁm9 mÚ´ôÚáî'°°OîĄ8ëßżŻßkŔ•ËŠPĽ , ümIiňćÍŁŰy[@遗_ÖJˆc‚ ĘĄK—Ξř=PŠÁR {ĐZ;ˆ…ŇłgwOŢCĄ„]ł°+ĽPAŕe¸Q{‚" V,pńÁ9QQ=żAĄ‡X*–Ť•uÜ%„B!„„-UČ Cć̙dΜŮF‘˛P]nŽ9˘TL^Ł˘ ĺGŐŽ,Ń ”bňöŰs=ǰ•Ź3`k ° \z–.]ŚîPR`Ëç'ŸĚ%5kÖđ¸yXŕږU ŔšVüěđƒóaŠ0i~îšgĹ-ŘÖٲœx6_JüůóɛoÎ4yľŔ(€ž‘'NhlěúRŠREýÝŹ[WsćĚŐX0ŠS§6Š— RŤVMs9Ů%ʸ€Áćý÷ß÷ä%CY˛d‘"E˘TÉŕ+@Ź(˛`ů‘.ÝýFGƒô†Rž‘ Ył&Şŕ‚rĘ <v4Â1ä™Ó˝-*Ş yö‘ęś…çF ÜrĺĘĺL]/w ;ȏ‡ʨ[_#6ω'%iŇŰľnÁJ ËíuŠ4”7ŹYĐ.Pćř}ŕŔ×TІŤP'aÁ„: ë”ŇĽKë}!„B!á‘ŔĹńśďÖ然wë•čĘ+ń•fzŘb#ĺůó˙}!„Xƒ]ŒÚˇďäů>kÖt݄݀B!„B˘1‹™p8e^˙™VŠ/\y]źňşd{]ś˝_žr űgq|VhŠBČ \6ţţűœW,X¸PĄB!„B!×*UšÎÁÎBŘŮȊĽ°­oŰś­…B!„BČľƒJBŽs°ƒ śFđXÄÔx≜Ҵi“ˇĽ&„B!„YS…B!„B!7ŒŠB!„B!„rBĽ !„B!„BHPŠB!„B!„TŞB!„B!„„•*„B!„B!a@Ľ !„B!„BHPŠB!„B!„TŞB!„B!„„•*„B!„B!a@Ľ !„B!„BHPŠB!„B!„TŞB!„B!„„•*„B!„B!a@Ľ !„B!„BH$B‎;ˋ/ćőź **-[ś‘Ýť÷Čľf×ŽÝšŚŁGĘľdőę÷¤xńRiœyo˝š7oĺ9Ďޡo)VʤDE“ΝťĘáĂGźŽc˙ďË/ç—ňĺ+É믓ß˙]ByŽĹ‹—H… •ĺäɓú˝bĹ*zěFÁ™~róńý÷?H͚uĽ@Âňůç_ČĎ?o“2eĘ˗_~Ľż0Hşwď)ąáüůó2xđP)Z´„W[źŮY¸p‘”+WQŸűŻżţ’ë‘"EŠËűďŻŐĎĄś÷ţůGŞTŠ!3f̒pAŸŠ~vďŢ_„\[z÷î+­[ˇ•¸ÄŮż€`}P¤čŇĽ› 4Dnf"Ń&DJ^sƟńQßÜŕ|žąc'ř”#­×äÉSő<7ň&!ˇ ´T!qƋ/>o)-ô3„éˇßž+mÚ´“%KÉwÜ!ˇĽJ••f͚˜ FY‰kěyoqÇIő“ť–-ŰĘÝwß-ýúő‘D‰ÉÔŠ3¤}űN2w0áU]k… ĺĽrĺŠráÂ9pŕ ,]şLę×o$&Œ“ŹY7d͚UňçĎ/wŢy§Üˆ8Ó!y†źť™‰Ďúz­Â$Ož<ŇŤWwɒĺaíŻPć2¤—Hąr坲nÝz3ĄyMx ƒ\o,[ś\fÍzÓ¤s™DŠ_~ůUŢxcŹtčĐVrĺĘĽ}ÎőN¨ýU’$IĚD8ż<öXĎąšíÄUڃ]÷ˇßöIő굌RkiČľ"wîçäÜšsIœcFęÔŠbô/ńŃ…Ăľďb[|ľÉ땸¨o‘ fÍjR˛dqýü믿i=xýőAžąëŢ{ďńœHŢ$äV‚JgÜu×]^o|.^ź´|÷Ý÷FxxYHÜáĚ{;X;yň„™@MóLŇŚM+5jԖŸ~úYžx"§ƒâ+[śŹžëäȑ] .$:u1+÷ƒĺ­ˇfŠž|2—žnTnôô“Ŕ@ÉxęԟRŹXyüńÇôXҤI͊nG‰$GÓÉŇK/˝(ˇ GŽD[żUŹXAnťí6šľ˝C Ýşu !7ńĄťďžűźú—řęƒnn¤6y˝*^Ó¤IŁ/;=”Q~8sŒsɛ„ÜJĐý‡Ä‰'– Číˇßî9śjŐjŠ]ťžY‘‰2‚wU™=ű-Ż˙@Ó¨Qý+]0çźté’çwhĐŰľë .,011â&ć¸GŐŞ5ő-Z´–cǎMë'Ÿ|*őę5ş’Ž*ş‚kż/Ž˝óÎbéŮłˇş6•.]Nć͛ďóZ0ó„9äɓ¨ů?>Cˆ˛X´č57Ç˝`2étŻąŇł`<ǂ ˝Ň*/źđźŹ_˙×Jl˛dіC(Ÿ@@XiÖŹŠěÜšSÍXÝŕËlĎ?pŕëúL(׉'Ëŋ=ż#QP^yňđÜ+P}ąLčß{oTŤVK]›pM”Í›oÎńş˙?nŃsą’Jú+WŽ.~¸^ÖŹů@˙3m_üţűa5łF˝ÄŤ_ż×<őҟŠ?Ž}úé&ý wźđ|–‹V˝ź\ܜÜÔe{^ůĺ—~ëë’%K5ňć-¨ďü?ń҆çž:uşYń*ŁuüŤŻž–ożýÎSŸ›4i.ôüçďż˙Vłb¤ éĹyö{ ,đŰG}ŹćÝÎ6ƒŐŢśmŰ{Ľăß˙5ĘŔbšv'0ƒÇ5@ŰśűěsŸçZí˙­ˇŢ–-[śęgËüţ̙3šÇ%J”ÖëŔ’ĎŢŽŹç…K ÚI׎ÝĂÎ[<ţƒó ,˘ýŚU˙‘žĄCG¨âé›0aň•˙řŻÇÁ@ýh×.zR˜/_!ýč™Üäúř?–J•ŞŠËĘĎŐž}GMꄿ6i2xőŐfZîčO7oţŃëwg…ś2eĘ4íGŻP(#íÖóëyőőÁĆş` Î͙óśţéhĐŕ•í/6ăV ´gĂ˝Ž\Ż`™P†7uýLNpí‘#GkÝB˝C;°÷óöz†~ugϞ˝žßŽ~gϞUˇWœ~íůa?ŻéÓgjŰBĄŽXĎčk̰÷/ĄôAöź@Ŕ¸(/Nœ8ĄĎ‚4!mžúŔ~ŘŹŽŮ8őă2ňČ_ÚA žÄMę?ýՅPű"ť›q°q#œüu3Žƒ`ň§˝žY×Ü´é3OU˝zmíŰíěŘąSš6máI'ú}´K˅Ńáü‡Tސx˝×_j4Ýy,!0ů6l¤éŕËaqśšϜ9[qpęÔ)uIyîšgŒâažě_S˙üľk?ô\łYłrď˝÷Ę´i“őwȝ:uőÜwÝş *@•/_ĆcÓĽL™Ň2|ř¨€i…s׎=Ě`_@˙ÓŞUKnjďu„ť‚ šßćKýúuŐť“ÔŠS›A}…~nÚôUý óTđçŸɆ ĽoßŢ2jÔp9~ü„ 5L‘–’%‹™IŮ,#ü4Sá “ŠHX*C‡Włw7沏>šŐ(a’Šb%\ć̙+iÓŢgĘ{štčĐ^VŹX)ăĆMô:Ę#˜ŸÎ›7G2f|0h}ą˜;wžŠ7môÚ0[.Y˛d Á×züńÇ%sćL 3fL‘§Ÿ~Jrç~VËńšçžőy^˝ĺż˙ţÓú3cĆT١ď@Œç Ć˙ţ÷‰:ôť>ßÔgA]éĐĄ‹—ěˇuٞ×pÓđU_!čÁ•ůžté"Š[ˇ–ôęŐ7`ŒožůVҧżß´ŰyF˜­äQôďßGŰ Ž;dČ0ĎůÄ׏YkžĄÖ÷—_~ŃLÔúxĹűAYˇni/ÌĐ;ÓLÎjßʖ-#_ý­9ç¸->5eqÁLˆŠĆH_ťv­eٲwô3Ú ží5xÔaüöěf’›Oű_ńŹö_ştIɐ!ƒ~Ć˙0ąŔśmŰnëţF™4AĎEŸć|^\wذ!Ňącű°ňĘĹ6m:¨Ň×A %7ꆕŻźŇH•ŚH_Æőôxlę1ÚJďŢŃ×_šrŠ~÷÷Lnóâôé3˛uëĎŚœŹŚčӦ͔nÝz%jUYž|ąšü÷ęŐGc*řuľM›öjÂ>}úsĎöÚo˙óĎż~ŸcâÄ)ęöˆ~ y&Mjż }˝Űž+Pě Î5oŢTÓQ¸pAm_|ńĽţŰqË_Ú݌łá\×, 'Nwĺ9'š~fxHĎäOÓuR;tčëćÜŚĎl&ăÝľOtÖ3¸ąŚL™RŸĎW ëü;wi]4i‚Z4iŇĚë|LÖú‚!CĹßFӗ.ĐcÁĆ ˇ}=/Đף ßö'  ÍˇmŰŃ´ŸŁŚ_fúËZW° `qŕŔ“§mĺá‡6יdŇ>X-YǏŸä7íÁú’`eőŸţęBlÇÔ@ăF8ůë†päOwě6mZŠűÓceWeĽŐ§A)Ó˛ekš˙ţtš÷]ťvR%ř_ö{˝pţC ş˙8cýúĚJÚ'ú+đÁŽiśÚ{­ZՍRuž™pí×ţß úhÔ-\ŰęëP°Rî LdPŚPž`˛y$‹éKvč¤Î‰żžŢmßĺÔš il´g+™2eňÄ܈ĸĺ+ínĆŮpŽkJë8ÎąŇęö™ě:tМ—Ů3ÅňŇÁĂ^?- `@ť†ÂÎę“Po˖­ |đĄŽÍ倱Ŕ•śxńâć^ßJƒő‚Žnű g^ üĄTEź3_`Af÷îÝŞ°Ář H‚u‚ň r¸#Yŕ7F[@ůK{°ž$P¸é?}Ő…ŘŽŠĆ ÔŠPó× áȟ YłW=y׺uK]‚üˇÄ+Ţ5cŮÝŚ ôň´GôŁ7ń{˝pţ nĺMBnv¨T!q‚WľmŰF?c@EǎU‘ącßđtśÇŽ×ăżüň‹ Š{ö쑌ŁMřnbŐ Ył–ňüóĎé°f âۡo7ńĎj’k0ÝźŠ÷^Ő~ęŠ\:¸ÂL+7 ]şűźÎšçž”F9đˇ„Â]wÝéQ¨Ź‚BÉaƒ?„:źVŽ\é9+,“Oűíř ć+ŕ,°z k™ ›UŒ)Ą%XáŔ .9sz+ž` ‚áZžšéÓ§‹ńż@őĹ"}zďçÄďP ˜@Š‚´óç˙3Z‰+  Ŕ*Ú'ŸlŇú’/_^I ęě‚>„u™xfKŠěˇuŮW^;)\8ĘŹ:.5ŤíUuűĚ3Ϩ˛"¨ĎćV{˝I’ä6ľ"ą€pťuëOŚÎo6ĺű›iżżj{@ݰ@›ąc€ÉžĘ2LÎJ–,!。V•*XMţňËŻeôč‘)Dí+ŤwޙÜsí+˛nÁÄ{ FćՇ!6ç?ĄŕVŢ$äf‡Jg`Ć>AÇjV0`ž  ŹŚOŸĽ+ŞyóćUYłf{ÎÇŔ o˜ęÂ4ƒ)Ląą{†%LÂl´]ť61îŐ Kô÷ýzƒ=V- *ă7_+ďöß܃â /†ď2V%á:ॠ—pĘ$X} DٲĽŐ|+Ţp/‰Š*¨ő3ŽŔ fdÓŚMŞ{űíyćX5żÖ1žž˙…‹>Ž]ůœHánŢźˇä믿1Ť°ßŤůö¤I“ŐœŘ.¸ÇřĚc˛„ŕ}pۂҨqăWCşĘžđđá˙ꍯt֟›Vl€ŮzŠފE_ŤÝţTçƒĹ6 •?ţřCcSaB ‹‹™‚Ř7nωM]vÖWřeďß@­TZľjŽŰocŇš~ý‰0ß´ésS7ťčŞ$vŹ&†şÚU觞zR>úhŁĆ:@,“HNĚ1!†e,źěíą?.^t@m~ţpŤ˛ƒ˜čŰ" ,°ϸqŁurł{§ň͙GÁęq$‰Żźxä‘Gô™ě–,˜DúłlAě´•-[~ň:’@8ó26}Ȕé!ím&÷°0‘ˇœiw3ΆsݘżÇ<Î3A™ KXŔqSP^Č'_ő ă ÜN|°ÇłŁ?Ĺ↽­Ă2#Üń7\|ĺÚ‚ŤúuĎjŞ Ů n6pŃĆ8ˇ ¸sb{ß`q6Üô%ĘŔM˙éŹ ńŃ…šżnĆńpäĎ`dÎü°ZŮĺ7ÔÇłgĎEô?„ĐĄR…ÄpOÁî xa@ÄÎ|°N , żgʔQ'Qř ԇ Ž“B‹íŰwht<8ŽÁ ƒ\–,ŃńJ•*ČŃŁGäľ×Ş5 ރ€^ŚiX<á/‹{ ``°hçđľE0\ŹvcŐł#d°˘Onˇ¤NĆ¤Ťšżşʤe˖k\ ¤Ž+:t–%K–I¸äȑCó˝oßţ:ŔcĐGp\(°Ę•ťŞlŔd}ǎ]Z~ÄŕwŽčń(+Ľ/ pc°Ćy0­őtąÁ3Ą|ŕcŒmW1qđG°úŹ*FE”QŁĆ¨ĺ&Ýá‚rÜ˝{Ż Ť–IŽŽŘ ;d@¸DzQŸ˛d‰VBau B,?† ă:˜8 vę6ʨgĎžZvö´;'6uŮY_Ẁ`wX‹|G˝„rĎ (Q°SҊ|ëÖ­gX“XŤŹ^ýžN˜K—.%ą%yň;ŐÜ˙ţýZ—jÖŹ.ǏԺ‹şE%vîŔ Ş[°š ˇ’îÝ{kŮavxřđďf^Y" ,ĄC_ŠňD_Š@˘vÇŕ?Ni?ˇŠ`ő8’ÄW^TŹX^'Ɉ[…{ îĘ1ăüö;XEܚńă'čN;(kŒ%ÎɗgŰ ÖwYVs?ýô“ĎXU˜ŔUŻ^ŐLd'hCűŔî:xkRŠq˙v7ăl8×uK8´uô‡Vpâpž })‚š˘ă?˜x#˙¤ÓYĎ0FĄžaÇ1_ý ,jĄëÔŠ›Ś cáčŃăôúţů§„ňěĆ 78ó.ťX’ÉP@šŽ`Ćč—Pv+ěuőîhxŽú+âŐŤWLť›ž$P¸é?u!>ú˘`ůë”k܌ăáȟÁ¨Xąœ*ą#ę#ęńȑoTpşůš*UHœńĹ_IÝş ô…­äV­z_ZˇnĄ+" {÷ŽfŐ⍳‚ţż°Dą€@ÓŻ_3ŕž+uę4Đ ŕĚŔďwęÔÉ*„śjŐFwuŔŔ0~ühŠcTTAUŔœľ~ýFňtĺ$đýEŹâ4lřŠşÇJĺʕ4R}lŔ˙1řÖŠS?ŕŽ)δ -„I¤eĐ ×5poçÎ$\°"ƒU&FDţŽťč.cÌňŠÁ ÂĘ["N™2UWżfϞpĺiF (Ä Tů–Ř= QŁWp>Zʗ/ŻÖV_‚ëLŠË”)ĺľj Ą[;şÁ0“'O&őę5ôbśƒXX™Ă˝^}ľŠnى´2Đs‚ôA Ap?é5Œáߌx0ÉĆłvîÜM|0ƒ„†z ˙ÁΉM]vÖWhť(Œ­a-Zbʤ‹źü˛ű2ҁbßne÷Ť¨¨b^ń#ńŸH€ ČŘ lѢyBČľ$I’۰Mŕ)ó‚)|~/\y]źňşd{]ś˝[~söĎâřŹ0P-!䌊ŹĐ`ĺ “?ťBüú랈¸ˆë˜šĂUéîťSݝˆ„ÜNď[ßĚ ŰČ'Mzť_ˇćpţ) _Y;?rłCĽ !䌝FÁmę駟”śm˝ÍĆą {qą; ‰P–pɐ!ƒ™ )& }űöKślŮŽË`"IóćMdňäiŇťw_u™L“&*T6Ź/„Ÿ`ö.]:ĽČ|í—@Ž\9Ő=Ęߎáü'RüöŰoAÝ% šY ű!„B!„Bn:čţC!„B!„rBĽ !„B!„BHPŠB!„B!„ …8âƒÖIýú%ţ()VʤúłöŞÇŽ,Řť>Đ ADAĄBEeٲĺNœ8!žŽŰŹ"=5kÖőşćŘąŚeňäŠz"Śű;Ď:věěuێvčĐI~ýő7×éuާ@ÂҰáŤň駛<ç`—üöŰoűbü˙ŇĽKRˇnCiٲMŒß°E("Áă…Ďnů裏ő?؆ŻdÉ2Ň˝{OÝUǎ•&ëőňËůĽ|ůJ2sćlM“?>˙ü =˙ÔŠSn’°,œĺ€z„ü°§yâÄÉZ>Gőşţ_ý%ĽK—“QŁĆˆ[ŐSäĂęŐďyžc{ĂéÓgJĺĘŐ%_žBšGăĆM”ż˙ţŰď3.\L^yĽŠ×uBť–ŕZӌ͈ńŽ[źxÜöűďÝű‹ßs~ţy›”)S^žüň+šŢčŇĽ› 4DHüý؍ úŠ÷ß_+7 ťvíÖžŔŮ÷ăZćŇÚˇo•g0vîÜU>ô×Kم“ç+V‘Ĺ‹—H8\O}y|Œo7Řr !$thŠBâ `Żż>L4¨'íÚľ–3gÎȜ9sĽI“ć2oŢIž<šů>ŰsţoŒ‘D‰J›6WwgI”(‘D‚óçĎKłf­ôž;w’ÔŠSÉ÷ß˙`î9VΞ=+uęÔ6J–jFQP\χň  ×_$<Aa+M‹)î–ńăÇƸOҤI=Ÿ_|ńy3hĄŸ˙ř㝠7oŢRćĎŰőnöűüóĎ?˛nÝ“ţn2aÂXy晧ţ7a„fŘQóűĂ×ëVÂď˝÷žüôÓĎňć›3%A‚ŽŇĽH´ ’ÔŤWǤç_YšrĽNňGŽ&Ď>űŒ×ůC‡–ôéÓ˅ dűöí2fĚxšýö$Rťvä˘Ŕű+;ör€˘äíˇçš:ÖN–,Y$wÜq‡™5Ö݁^}¨Š#=˙1b”$K–\Z´h*qî÷Ĺ_JÓŚŻĘĂ?Ź[N:Ý(öxĽXíéG˝1â ůᇼgĎn*k׎“9rȚ5čł_ }ćϟ_2dH/äÖ&Ňý!á9˘eËśr÷ÝwKż~}T>™:u†´oßɌďoj]%ބӗCöBŢ"Ă MŐŤ×2Ę F†{@Č­N›5k"ĺʕBâ*UHœđÎ;KĽjŐ*fŇÝČs ďŚM[ĘćÍ?JŢźy$kÖG<żÝygrHíÇ"ĹW_}-4Ę՞íăžx"§Üv[bý Jl“‰—‡Ęh&ź™c\ĎM:qű9šr=aVIJĹČzŠRĽ˛¸Áy¤yçΝ&oUŞXç—.]JƍoňűeU"@‰4aÂ$MƒŰźŢž}‡*Tz÷îéQ<"E˘¤˙ňÚkđ˛ĐkűÚL™2iţ9˛EŐ>óěETŠN9ŕ3Ęáťďž—K*ń˜‘;]KjÖŹĂ* ŽŔäżeËfjĺňć›sôűôéłô˝I÷V ďžťÚL\˛z)TV‡[ˇn)ǎjŢ ĺ,UŽ5‰'Ötß~űížcŮłg“şukë¤ fѰRŠUŤfœ ɸ?^°`˛óÔSOĘüůs< @A—'ĎKŚ\VI(Ź]űĄ*ťđ\Pڏ1G‡ŐVťvÔÔ˝\šŠj%‹ ˜†Ď›7_zőęŁçŔEí÷ߍâŻbĹŞR°`łâřšüűďż^×=|ř°Q°śPWźŞUkĘ{ď­ńüćËEč“O>•zőéů•*UÓúȝě‡6ŤËŇ“o¸ţÁZΞn¤ągĎŢęśW/<‡¸ ÂĹÍrw[˛dŠÂJ÷˙ţ÷‰ZpáşXuĹ}‡ Š×(Q˘´źőÖŰK+\$ńÝjß?ţ¸EÓňË/żF,¸–UÎ{ŐX'ZŽX-ěÚľť‡V‹¸&Ü&ŕBŠ+$pӏK߀ƒ´<í@YÜ Á+~ď ˇ˘9sŢÖş Lœ ĽŤUŤVeq}­›8oöěˇ<żYy˝iÓgꦄsŞWŻ­Ęü@lٲŐs>Ú"ěřËkÜí eˆś‡üpÖ¸ĺVŤVKÝŃżůćŰ .!‘xF\ςß[´hmƍcŒpóuyđŕĄZçPża×ç˙>űěs}\÷ťŠ?^xáyYżţB$Kv‡žŰ-Ľ‚ĽŮI\ľGŕ&Ď­žőçÂý#Pߊţm÷Ĺ őÍy_çłY}9Ú ^hwx.üé†€Ű ,Ň`I‰˙Á-+O;×`ĽŞTŠaLź­Má[ĄBe͓ćÍ[y\ŇÚ;ŹYQ'p”ęH ÜôߨŸČ'ä1ę)܎-÷vˇçřĘŰ@m=X^X?Iď‡k 2\"PĄŢ îĂőÚiB_łaĂFŻtĄąÜčzô襋Ivěc>ňgÖŹ7˝ę%Žá¨×yň02č—ZgNžüCë >۟•ř€J'ÔŠSS'q­ZľŐAÎ9ŒOrç~ÎL"7žW46 V• qîwřđď’*Ő=:Ň5îšç5…œ?ĄN´0pˇnÝĘK0 ,Uœî=ŠRĽ’‡zHĎń„F˖-ťćć˜´ávƒô:&74ϒZę×o¤n?Ą(B+íŐŞUUňÇŠtĆÓO?ĺW¨ô&S… ĐĎQQÍa}@Ą ůŐŹY UňŔşeŕŔ×t‚ĐŠSWŻóVŻ^ŁĎłté"š˙ţ´Fŕm/[ˇţ$S§NÔ˙aŇ6oŢŻ˙@9SĄBy#(M—˛eK›kÖI…/ °ëÚľ‡Ś}ćĚiFnŞ‚?ÜĽ|qŕŔíwŕV5uę$“Ďƒu•ÂŁi 4 ‹ůŚÜëj\%LˆňĽmێŚÍU÷śQŁF¨ťÚP00a{íľžf4SvîÜ­ŠŚĚ ÎS÷CôAÖD+śi…¸dɒ1dPRĄĎ˜9SDŇ ęú‰ÇŠk$„e䑽?~BËkذ!F°nŻ8ęËΝťôؤITÁܤIłBt ‚őcnÓ*SŚLSˇUÔš3ŚJárŤÖ€|ĆġRĽňꦇ4ÂUC;piÓŚ•ş#<öXvUAIä L–Іŕz:}ú“íľźáriǙ×xÎ6m:ĺČ1=†ś%2ڎ&?˜ˆ•-[ĘLHfhŸ ë¸@Dâaů‡‰Nůňe´Í—)SZ†đžáćƒUçßkŔ€ţŚOÔŠSký°Ç?9q⤙ÎÓö˝dÉB“ćÇ´-9̘1EǜܚŸ5ůąBž{îY×ĺiQ¸p!ÍkÓ7ŢîůíĎ?˙ŇÉ}ßž˝MŸ>\ëĆ` <7Ú;\֑žňé˝ý-šíżĂ ‹!˗/–AƒĽŃÚyćć 7m=X^Č[ľj•i7´,SŚL!sçΗ@Ę#¸ŔÁň÷Űoż×ú‡˛Cţ,˜_e Œő‡ýnÚߛ:ŚŁ\:tčâ‘Ëíc>ęYŤV-uanäv `ą!rĺĘĽuŔ­Ÿ“$šö yäւî?$N(T¨ vŇčô†ŠÂ•ß"K–‡%>Á`3iŇ8Ä1„v;MšÔf5ŁŞZŤ„ťšp{@TW nž8}ú´8Ţ4Zó˙̀%á!fýúŒPüEȞƘźŽ\šZ]> °8-N‚U(Ä/ń~űëŻÓ^ÇęÔŠŻŤwüń‚@wĄHâŤŕnfw9Cž}üqôdŤp§ę&+UŤÖđşö™3gÍł’PԏšM_( Ř% ŔąăŒc÷Gô+PZbŐ~Ϟ=Z&v0Ąą°ÜűŹÝ✠XőO<î5ĄÍ™óńWg^L<6lřHśnýŮäď~ĎNg–źŻśôÜsĎI0bűŒhOPţŮńgýhn> .`bnPŠ|A‡úh>6sćL^çäȑMŸ-Xa‡U Ź4h,ÓŚMQ™Ćmš}éöč&ĎaU‚Î[ m,YĘ;5P…<źŁm =@ÖsKÚ´Ţąë0fŁ^úĂmyşuĹţLčă![Ąďۡ_ßąČa—琙3gö{M7ýwślŮźž?ţxíqžĘÍ9v‚ľu(Żńź—­ ÔJŤO –GŘĐ`áÂĹj‘ K0ťb @9mŻťč; Aۃ 櫟zęŠ\ş˛gĎ^OŸœ>}:!äz‚Jç@xAPЗ_~I}šąkC8“űHÉ24ŕ˜0!ČjǎíB˛Lp Uˇn]tŕƒß5VůBÝ‚vśˆGĄË 6,A— ÄÁj‘/`†üŰożé9vÇ–â,SڇTŕƒű|ŤąBsrŹp9ŰPňČM9`•ĐŽŔƒ96\¨œÁ~bҌ2fĚ(ŁPiŚžÇ0!eW‘;îHŞĎćŤ;Üî¸#™Ď˙!`ÉK™rĺ*АëkUĚÎɖ-Ť¸Šě>,%°Lmťvíc%ĚŚ˝íÚĹÜÎÖíVŇd'’îxČěȑ/_K–,ĄîHŤVšßŠéóľMo¤ˇîDZ\¨°’U[˜GEÔş)=w°6aŽN°Ň*ţúąpÓčnĘBˆďRž|9ľČʘńAłú?[bƒŻşçŻ>ځ‹mŁFMtŠ•gXĄDý˛@;sZfłÔŒÔ3úzŚ`燓nëňÂyn°xPNăš1;`9Ňž}›°Ó*nŸ1XžC–ĹNěŠq;°l)P €Q‚oŇţ .T5jT j.ąé{Â.-NË\mÄm˙íŹW.ÄtItsŽ…›ś.nŞj°<‚bçÜšhYČRŇŮqóü„܈0Ś ‰8XEGp)§Ÿ?4ú˙ţűOœě¨řaÖ¨Q'ĆÄ >Ě'ńŠ4iÓާBWć̙T Îv‹XUą„7ě ŽB%ś`Âśk׎ĺ agܸ şÚL ` ŔXšÄŞ"Žk .Ĺ$˟ I0!ƒ˘ĂfÖđîŐŤť ˝{÷PÁ(X`R'°bXż~cŒzk”żľšŤ´§?¸eyŹ}ŔDvÓŚĎUă˜N¸=a…ŐzY~ç–{”+(rştéT‰&ę2Űş¸uëVŻďˆ“ńČ#žd°žp{Äůdç Xˆa% î:pAL%§{Z0řŰŰŞ˘Î d‘H+€;ę|Ń?˙üK/“čH={vٲĺ'Żş˜(ű÷ď÷X,ůu–l˜źYu/ŹŞFr Z7éƒRejťÂůĘ`´Eg݃"VĽAt<Ą*:Ą†Ťú€ăÇÝNJńę,Öě+Î菂]üţűÍdܸŃ:ń…ľ‚s˘‚Őd䓝~ř!ŕu#ńŒ0ßw*ćឈpóuĺ ‹T;č3P-7öX`OĐž#Ĺ'şuëc’Ÿ(QB2=Ü4‡Š›úî&Ď ć÷ߏxľMÄ9uęOŸíy„çĂd;o!öš ž#q…Űň´ŽŽĘBXÁɞ§/^ô­ôwŰc×=ď´˙¨}˃>Ň9nÚz0°Ř„qÜY'žůćż˙q›Gp'źďž´ęj5bÄČqŠŕZk#ˇoß>'ŹśçkĚßźy‹ĘęÁÂą˘ˇĐR…DŹźC{ŽÎôĉă0ƒ"üÓ11AěˆP9rähŒŔœéŇĽu5 ‡R>ŕˆŽłDLŢ1ф9|XCî!Xř š9sŚ8QĐă×_!´AjŹŔ &żˆŘĄó…r›rüGŢ}÷]č`Ţéœd[i‚Š]%°kĘ ƒ%ŇahäČ7¤eËć)žÝˆ7é&ĚVYÁllíÜšƒƒp€@‚ŻžÚČc ŽźCŕZ°ŽrëÔŹYSőÇN¨W0E=CŹř;Ă źřâ ju˙gř6#>ňkÌY*@ڃčÂĚJ?|Ľ!Á§&Ýş4ŔŐ Â~TTÁż˝ôŇ ć÷ľŚMS…ÉŮłçt˘ÁĽRĽ ŞX‚5âx@h›:uši‹ÇĚ3˝%ąaŐŞ÷500ę”LjĚĚÚĄCgu_Â3Ă} üŠ}m))SFŁ|_Ż‹‰1 píşëŽť]§Â1<%…u„Ű™3gE\!‰´ôiQQ5đ ęv’Š$+–Wë.9ĹśčPŽ"6ňmİĂ$źS§nf%ťŠZ8aërÔ+ět…ţíOGŽŞĘă¸JŇżXmĺΝ[cO żÓŚőmBë-Ä݂âřöۓjż€&&Nœ˘î˜ź˘ü ŕD=DűAŒLbłÍ3žeńâĽëĄ~ýzÚîă"XÝĂ$ “lƒ+\‰‘ţ?\weŃ$IŘyň6‚çb!éý÷רĺ/@–|9ńQ4¨ŻuwôčqÚžŹqË9ćĂU c>ä*§ułԟÜ*O>ůdź‡ „J'tďŢU'ŁË–­”É“§Š G ÔÖä2¸Ęž#Ŕę⋠Ňúúő4¨¤/ Oš4^'„P Ŕ/Â;Ě^C ”hzÝş b_šrŠ—_t `ş™9s&ľŠˆ-Έď‘ĎÝęr“ÄÁŽ9 .Ňm“$šM@˜őűŽíiBź”=‚‘YĘLJÌŤ[`âXĄB…tŇeŹLÝňĹ_é ŕ>¨“­[ˇĐU%(|0ŘŁ~@0ľSŻ^ľŕ°Ü€°Ş‚í´ľté’>ď‘ěQĎ @ń„¸p/Ăý, Ě#p2Úń ue žÎŘÝť9•|V]ƒĺVšáŽcOC ź‚"AK!`ű˘XąbşóV9ĄěB["BBůN:YˇšnŐŞâ.ŤBmüřžąV"ŽŃ¤IStBKôĽ HâÁŠ'Ôk(yPFž€ŕ˝ŤC´’“ l™˝|ůťâ(ţFĄŰkwěŘĹԝÄ&_GÔĽ&Riľ€u ؝%ŇĘIĘ2e’śY"F~@ŘmŰśu@ĺ-ę2vŮ@Ĺdôôé3:ńC›˛b$ŔbÁRíqfâ"}QQu‰­iĄÄAĐFč´śúôňeŽ \!äĐĎ3qĹ8‡Ĺ§ Öx˜¤Ŕ?6`ĺ1Ÿ0ᇒc úflłô?ŘĄ } Ú &4čSťwďĺ9Á˙ůçoŁä~[Ëç @+ę¸?"ńŒQQőfÍzKŰ0⌠@&Ę*Ňů`Ő9L2ąŃż˙ž7÷{Ěôˇ˝b$Á].+؝ (xŁËߎßŃ/b—–.]şë¤ pľâR„›ćPq[߃ĺ9úV(łQ_°ëâśAYmßýýŃȑŁÔmvܸ1Ś~3Ď8Ţô‡Ńă5ÜV}šˆ†K­ZŐ5–W˝z ľîÁ:ĘMyځ5,,ŤŕůöŰóuw'7 fäě´ë ””ęÖě ˇý7ŽíŮ󋑵^Ő<._žźĘŸĄžcጭťmJ”/T°ŕ‰>rîÜNÁb y~Ő˛ĚíÜšŁů^GăÎX‘2!t˙ýwAcßuęÔÁ#ű8Ç|ČGXEÚÜ<v˝‚…đ˘EóBŠcHHlIŕâxŰwësBŰťőJtĺ•řĘ ŞNĚ Raé !$ŽčÜšŤŽzC`¸Q(R¤¸™w 9čě͞‹ë­Laî!oŐŞĺ1‚Đ]knÄúO"Ěá›5kŠ;í¸Uî’[§´[".&Úëׯ¸ŇđzŰC1°vmhą‹ •ŠŤ˜E›šę.›sn°° ëlNH|bƒą+Ă)ó Ěű/\y]źňşd{]ś˝[>ŸöĎâřŹ0Ś šáůő×}ŞéžQŔ–…ˆ€m*™ß\oe “X¸Đ\o pŁŐY  BĄ7(FŠP!ţ€ű‚Ĺüń˙ÔŐ17s B…B‰ čţCnhß&ˆŘ†íFţĄŘ>/ś;¨Ülią¸Ë>ËÁ‚ń^ nÄúO" ś64čuyúé'ŐüŸ@é†ţqa TAܧ—^zI]" !„>t˙!„B!„BČMG|¸˙ĐR…B!„B!$ ¨T!„B!„B *U!„B!„B€ť˙‚ţůGŞTŠĄ{Öߏ`k˚5ëJ…ĺóĎ݅!Â֐ŋ—’™]ťvˋ/散GĘľ K—n2hĐšŔöÖŘĄĂ-؊qńâ%*ۡďĐç.Q˘´ŢłiÓňÉ'Ÿzƒ­ťwď)äƧwďžŇşu[š–8ű*ÔŰ *Ëɓ'ő{¸u™ÄŽëĄnDŢĹ8˛wď/~ĎůůçmRŚLyůňËŻäf$ŇmČŮFodbű,ÁúŻŘp+ȡájß ň0šąĄR…Ü$I’Ä(ňËcĺ›L`ń|'Ž“§Ÿ~Ęç9ĽJ•••+ßB ť&MšË… ¤S§ŽŇˇooɒ%‹tíÚC–,Y*äĆÂŮ'üöŰ>\8pŔs,wîç$Ož—ĺz"kÖŹ’?~šóÎ;%.đ•$&×c݈+R§NĽu.C†ô)nćz×m4.qö‹‘~–H^ďf“o#%§ŢČőÜšĐý‡Ü$L˜đŚŢöńüůóręԟRŹXyüńDސ¸+b–%ŠK]=ÇóĺË+=ô Œ=NŠ-"wß}ˇ›‡rĺĘĘőƓOćŇšś\u#ޏďžű¤K—ŽBÜq3ľŃH?K$ŻwłËˇáÂ1‚ÜhĐR…Ä 0Ĺí×ď5)Y˛Œ,XDÚľë żüňŤçw¸ŕ5}úL='*ޘů>X• ţ°›śÂĚŻ\šŠ˛qăÇRŠR5uaxűíšzßöí;ęő`NétŁYľjľÔŽ]ßhżŁĚőŞĘěŮoyý~ęÔ)5‡.\¸˜š.X°PŸĂîröěYyýőaę:QŹXIuŁřő×ß$p­¨WŻŃ•űV‘YłŢ”K—.éo¸6Žƒśm;řt…Áw?yň/žőă̙32lŘH˝ęÁ[o˝íő?üŽrÂořO›6íÔÍÉΖ-[=ů„´nŢücŒűŁ^Ąí ˝¨ď#Fź!ýő—„ËŚMŸŤňŽUŤć1~ŤXą‚ÔŻ_×äŃUS[Ôą!C†kűjŁ‘hçqŃćâ˘Ŕ5Ńv?účcýŻł­ĄoÂ}œ}\+zöěí7­¨ƒ•+W—źy ęűÇ˙ĎëwuÚWŸđM›ŤĽ˙C7nę)˕Ëm;Ýąc§ş…áwäáˇß~§yjwO –ö@3ŐFŢŁŹwďŢŁßCŠHŁŻ|@6gÎŰZśxŽşuʆ =˙s›7ĄśKä?ęôÔŠÓľ ŻĆ5‘§VŮÂzěŕÁƒ^iqÓśŹ|BZzôčĺe*ďöœ¸¨Ářá‡ÍҲeMęÁŔŻkżiś6oŢ|éŐŤžÓ°áŤ&}‡ĺwků!O?˙ţűŻ×u>ěIÚ Ć {ž:]„‚•%ҁ{˘ Ł//]şœŚ řŤgž@ŮY÷Áó˘tÖťœ€|}óÍ9^ă—}\A‰žlϞ˝~ďé˅}qƒŻxž÷Ý÷ҨQ˝', ŕ‚bÝÓŮFƒľŸ`ůĺ–ŘŒ+ţdĽ`ýÍß˙-“'OŐôăŮPú3çő‚Ľi9r´ćqž|…´˝ŰˇËˇnŰáŹS×C˙ć›oCrĽWžń7N’SÝ´3\2až<T^rćq¨eDH|CĽ ‰8/^4“Čڃ=f:ć!2mÚdIœ8ąşŘÁä̞=ĂLÜ™ ĐF3ř.p}ŸÓ§ĎČÖ­?›u˛ś™ű̔nÝz™AŚŞ,_žXÍ)!au@¸Â@QŠRy#̖f͚Č̙łĺĂ×ëď$:vě*ű÷”áǚUűQ*,~ýő7ž{B¨čÔŠŤěÜšKŸmҤ ’4iR3@6óë÷ ˙m<{ĄBŒ2eş™ĐśTĄc̘ńú{ťv­eٲwô3\1VŻ^!ŠS§öşžă8hÚôUý “Qđ矊`ƒ˙Ž5\Ž?ĄŞbÜżdÉbfpœeŮf*Œ@ŔÄÜšóĐÖĆäŃ4ýŽóç̙ŤéE™(OóÂéŸ>uę Sţ­Œ€°@{,ť WVŹ[ˇAŰňĺËh^”)SÚäő(Ż˙ťMŻ3}Áţ‡zŮśmG#t5ÂÍ0“W#ä‹/ž”Ü"ÁŔŕţÚk}Íugš˛ß­ţƒf… çIçΝt ˇ”"VŮśmťôú›ß&hů5kÖÂÜűˆžaŚM›öňŔL§˜óŰËŘąL>]  >á?÷Ţ{ŻśĄ_Ó{ŕÚá‚X*0Šőe‰‚úôĘ+$sćLžcP€1cŢ0“ŘN˛~ý­ í<ŽÚˆt˙ĐśÖ­[gęÎ03á™i„OLô‡ęoŊ5äF@˝› Ăożý^ëš/ 4żńĆX˝×ŇĽ‹Ě$Ľ–IS_˘&PöŐ'/^TÝÁ”)Íľ‡‹?ľS¤ťeËÖr˙ýé´\ťví$&L6Bđi×i .R%ęÝ#d š.\Čg>L™2MëoóćMľ˙)Q"záĚĺM¸ížôéď×>ŁJ•J%K˙ţ}Ěx0_Űߐ!Ăô\ˇm “ĄC‡~7yőŚöƒ :tčâ5wsŽ“Ř֍`ŔUŚUŤśňđĂ›{M2Ď=XcŠ?ÉëźŐŤ×h{Eýş˙ţ´ÚgnÝú“ůĎD˝7ňÔ)3`˛VĄBy-߲eKŤeňŔnË‹  Ôr‚â}5”âţę™(óq¸1ŕ|ôG˜Pc [°`‘ČŰjč~˙ýˆÉçˇTÉć&oÂm—éŇĽó(×jŐŞiCSÍÄŁ„G‰Yž|939ŒVĐšm[7 ÔŔů OŸžć:•ľzîšg]Ÿă$śu#čŃćáŽc2ٸŃ{rž'ĎK’+×úšjŐ*j…&Ú(^yóć5őâgŻ˙TŽ\AÇ€ňÝťwŻNśóçĎ#n˲TŠRž> ZÉłBűA䑛ö†ű ĎčßżŻ§†ÝÔߊj-‡1Ő)'@™%b_ăƚ5xŽ*°JD?UČÔĎ´úZşôŸm8”ö(ż‚‰qşŹŒs§OŸöô/5P ô;ȗئůĐĄƒ&ż2{ňnh°âđ'@íĘ-(Ń!‡”Ĺɓ'TÁ*ĄČ7ÁĆI_yJ;+[śŒßtĆŚŒ‰¨T!q”6|¤+Ĺě÷˜pŰMăÓŚMăőtÄ0Ür×]wz0pŰm‰UŘł°V'ě÷ć•n´{~K{8Ŕ2Â;& Öd„[ěX}˜łżV”,óZ1”7áśK´ ä+&bŢőń6S.xžťi[˜xŰ'ÔH7Úę­Ľ0qsŽ“ŘÖ 7@A‰•iLŞ8¨}‚ÓBóžűŽöÖÂĂ]w]í{Ń_˘íŮəÓ{âŽzŤ*_¸-Ëtéîóúß=÷¤4ůńˇ¸y†Éą˝0á|đÁŐzJ_r‚}lň5Ž  0É —‡ÎŹ–1͚ľ”çŸδá§ŐÂėRĹMűąęDló+>äG_÷„Ô÷ßo6}˙ofŒţUŸÉé^nšĄ\ęÜšŤQ×1yŰ(Úsˋ/žđšŰaĚúňÜsĎI8„"߀`㤡í,}útˆŘ–!q •*$âüńÇęŁ ZnŹ6A˜€™éľćäÓ§ĎŇAŹpÁźp֬ٞß!äůZńqƒ@ — 'öÉÖő&{Xń(T¨`ŒßěŞ`fš"…÷j\¨ŤdÖ`ęď{°ôZB…“`˙Ă}œ÷ňu˙Řčz Źs|ĺƒó,Úľkă:Öj]¨dϞMýŰaąâ\U…đ‡UL–3gÎôZ‘hç×S› Ö?¸;Š ?Ö­[o&OŞ"+Ňţ€ Nš4YM¤Ąü‹dŰ ” V]$L˜@ÜŚ= œc˛ąbĹ łzZÎKŮŰ:ÉvévéÄmŰşpábŒ˙Z– Ąœ nęF0 (ÄłŔĘ Jő’%KčdiŐŞ÷$ś8Ë9{ˆë˛ô•&;֘›k„›ÜŽHp)‚űŃ'Ÿl’‰§Č AŻiđr˙‹KŽ•üˆMXä‚Mɒ%UٸńŤŽţë&ÍPF-[śX>űě ­˙pK{衇düř1>ŰS0PŻăd¸KĄî8‰v›2"$>`Lq E>r䈌7ZͲą !.RDűgWŃ80Ć*ĐńăW}‘aqŸX{/Ź‚Á´ĐâŃGUŸtLv0q°^X•đˇ-ŰŁ1‚nŢźER˜l†‚[Ěśéƒ‰Ž=˝ˆÝ€ĽLOí`ŕÄjâ%ŘŻ_֋/šN ž13ěŔ,8é öżGyDcb؃[¤Ů^ž‘ {öěz¸GŘAěÔ€´ŔÇÜžň†I…ý;Î=tč°ş XĎ!¤ßZľ {)SڈťŔä&čXUtC$Úy\ľšpÖ?¸!z帤ş1|ôŃF¤UvŸb˙ţjéŕÁsçF°FěŕŚ-8ű„0şˆdÎü°Ž¸Ú'RČďłgĎšN{8 fĚȑïÄčá‰NpćCŚLŠTĚžřGuss[—â˘]:qŰśŕÎh_ĽÝˇoŸćž'”sBÁMÝĆúő鄎~pƒ22”˜,ŘşŐ;vú]ôˇžˆDYşioślůÉKÁƒ8ű÷ď÷ŹŇű’vŻľŽáWPpżőěÜqG2ý{0d,PüôÓĎęfˇ™ ĆęË'‘j?Áˆ”üŠŹËBÄëÖ­‹ş”@1ˡÖ5nҌ:čĎ`]7Äā;,ľÂ}$ꔝ~řAâ7ă¤3ď#ŃÎb[F„ÄTސˆKěa2 ĄĘŽ5™2eÔN“YD˙ÇŽ&0-÷_a°ƒyĺkŻ ô’0Ĺ ŇŠS7]ĄE„rlCŰŁGo#¨ţé󞈝€Ŕoˆä-;Ź@_CŢş6uę4FĐÚŞůęK˖-W+ÜÁŇ:tč,K–,s} Ź׏YÝŹşÔ€dČ?LÂą[V]܂Xř?&︂ž9wŒ7˝ÁţÁÂĘiĆęâÚ@PŒ$˜HĂäź{÷ŢŞ@‚Đ„ŔÁ‡˙n„‘ĘzNŊĺubƒŘ7řń^Ì畖J•*eĂ­ƒH+ę-Ő!8¨Eňäwš:¸Ç#Tc7˜Űg;¸>üšßtěŘY'7hŸîˆzŒmÝŽE˘ÇU› ‡`ýƒ[ Ä:ä`B ŸpOŔ˝PĄ0AOŕŚ-8űX`‚ƒź 7€ŹDP§°ŰňőxäČ7źŕ`iw!o¸;8]6,°Ň eóŕÁLٞ2+ćŃV>áÔg>Ŕ=ĽzőŞfâ3ÁӇÁýýXƒuĹ-nÚelqŰśWčДQϞ}Í9‡<őԓ! nęF0ĐÖŕ:€˛¨;Üžzőj‰ŤV˝Żc Ę㠂Ł×ŞUĂ繑(K7í ýýŮłg4ţú8Œ?bŠńčĺ—_Ňsœr‚ĎwëÖC`€s\A;¸‚ ˘Wăryh7x&ĎÂ8ƒkŰËăŘ]ő ĺ€zEN–,1•P‘j?Áˆ”üŠŹ9 tlEŢ#ĎşuëéĽ( ÔšIó°a#´ż‚ ÷X¸đÍS|ČcH/ Caƒ2;f\ăfœtć}$ÚYlˈř€Jq`€čŢüë×o¤AâZ´h*ךîÝťJÌčŽŘÚ >îX•ą€đ9vě(í¸aś‰­PąRl÷!FŽvŕFѡoŁ1U…Dôˇű:ہß,˘Óc۰á+fňÝQQĽwďj捺ń<Pc›Ţ`˙ÄmôčZ÷u“zž‘ÄŞ#Xy„ŕ€­9lňm˘Ç-ďcÇžaŽŐŕ´ˆŚ@tüiřS§NÖŘ­ZľŃ/ 4Œ?Úc.\ˇnmóźаΝ;ŤÁęěţĎN`Y€*°š4tč0UěěÚľKë(‚ëš%í<ŽÚ\8ë܂˛…+ĘQQž‹‰V깍ś¨\´h‰IGĎDËM[pö ˆ‡€UDĖľá€|Eý„b{kŹ&Kv‡ë´;Áł Ž&q˜Xń&ŕ–‹˜›‡S|ĺvި]ť–ĆnĐ ąŽşžöZ?ŸîUţpÓ.c‹Űś…xpŸA}íÜš›îŘ1räP݉†›sBÁMÝŔŠüK/ĺ3ůűžĎk`Agáţő}Y$@D°cäî`ŽNW‹H”Ľ›ö†űL™2IÝ.lĘXŽ÷†ÇeĂ)'@y8Vš;Çl={âÄqWŹ€ Îń *Ş *fĄ”mŢźĽŽ7VR€ąŻ_ż>F1ňŽé?čÄ_›6}ĹçsD˘ýŤ‘’C‘•ˇăƍŃ]č˘űŮ!jaő_nŇ —Ş ŇŤ îĽâ˜1Ł+ TKČ0@ŐŤ×HWÉŤTŠd4č‰tĽ•ľu!$rÜlm>âđk‡}ǎĄY‚]OŔœŤ}Ř:–'đ[‡ AҤˇ‡í6BnÜÔ ´Ä1ᤙ8a݈ pq›:uş.< .ĎĄCżË¸qŐ* đëŻű‚î0D‰TŞrhüűőë-SŚLŐXđÍ̔)“ӋíśÇ„˜ÜlmŽK—îę‚ vźQÁö˜]şt6“ĺů2yň4=–+WN Ž—ť‘ë7uЏVâ„u#2-ZXƒăbˇŚhˇĎäňŇK/i\4‹ß~űM]ś !ńÝ!„B!„rÓA÷B!„B!„ë*U!„B!„B€[*“›ř—bš˝{*VŹ"‹/ńů[$VŠRCf̘%׍Wż'ŋ—’ lˇˆ­Żwz÷îŤ;Ü܌¸Š7×ăó߈ő,\¸HʕŤ(E‹–Đ-goVŠ)ŽÁ%ă lťqAž|ńŗúۗ_~%äúŁcÇÎÚ§řťšŘÇlc‹˛Ä [—*UV:uę"?ü°ŮëŰśm÷œ‡Wž<¤RĽjş˝ňĽK—\ÝűzŰɍ͍:V *UšĹ€śrĺť)’$I" ä—ÇË!äÖ wî猐ţ˛ç{$ęÔ˛eËur}#ŕ|ţkA¤Űńľŕ—_~•7ŢŤÁǍ#wß}ˇDLűő{Mn% *`&ĎĎˈoČŋ=ÇąĂÖȑŁőw˝ńI”(‘ ž3gśźůćLS×{JŠ)ĽE‹Öf˛ú~Œó‡ŹçNŸ>EjŐŞ.łf˝)3gÎvu/Ží×/7C˙OČÍÝ!ą"a„^çÉÍOšreĺVćVţHÝ+@Ŋt'(;:vl/ľkח%K–JľjUő؂ ĺřńă2~üh!7ٲe•ŹYšň-ŤźôҋFŃň Q¨’çŸNҤIă9ťŠ=ôPFýœ#Gv9qâ¤Ö7[Ösl'„÷ĐR…Ä p™=ű-]=ŮéŽ]ťőř'Ÿ|*őę5’üůŁôʚŘMQn&ćŻcÇNđ|?uꔮD.\LM!4bUŇé6ńÍ7ߘĐzŻęŐk{™>Ăü÷‚É4Ě[qî×!‹Ë—/ËŰoĎ5çU5Ť|EŇT>űěsŻ{|÷Ý÷ҨQý?V`&k=Ďůóçu…Çóĺ+$Mš4וYˇ Xšß¸ńc5ۅů8҃4śoßQ˘˘ŠiÚ?˙Ü{s-+ (,UŤÖÔüAšŽ=ŞfŔ'Oţ!ƒŐĎH#€ép˖môšČӁ_—3gθNŤłÜđœ0SĆőđü(›PMűíuĎ˙ć›sźę ҇ç(Q˘´–O›6í<őĚÍ5ýŐ?_őÖI°üÂuŢygąôěŮ[ÓVşt9™7ož×5Nœ8!Ýť÷Ôk”,YFÝ`{fŤ^Łž˘Ţâ9_}ľ™üüóśŇş?gÎŰz ÔŁ ^‘?ţŸç÷iÚýŐ)ÔÔWŤ~YŔeyâőcčĐćzÇô&LŽ‘ŠrĺęŚl:ęď¸.žťMc ţ×ůđĂő˛fÍšvg˙hlŒröŸöüŘ´é3ÍklAţŘٲeŤçw\cóćcÜůc=úyX˜ŘűHˇ}‘|PjŐŞ!S§N—?ţřC•)łf˝eƨú’6mZ=ÇMâ4ÍÇ8‡ç>wîœß{kS‘č3ířsóĹąO?ÝäůŽ~u"oނúnďÇěéöUŢţî¨A]Çkúô™zžwŔ€Á1Ú¤ľW’$ˇÉúőž—-ŰŁŚnœ X–věc{82Éß˙-“'OŐë n Że°cÇNiÚ´…§î|űíwzťť\°öâ‹řď?Ý´1ňc ţßŢ/âú¨wö<˛úaô¨›'Đw!ż­6€űęű 0@"K–,&o˝5ËÍ4đ,ŠS§6ƒů =ŻiÓWő3Ě{8`ʢ­<üđÚWC† Vżüńă'I8@YĐŹY šóÎ;eâÄqňÚkýd÷î=šwną×•™3§™ÉaS­OxĄ׃ßř€ýĐ6AŸ÷=|řHĐkŞÎzëÄm~A((X° šÇ|Š_żŽ*1Ů0ĎoŰśŁIëQ#8 3up„Ć=řńÇ-~óÄí3c%ňíˇçéu—,Y(=ö˜Ś×˛ p“ţ)SŚiÝGžĎ˜1Ő(0 šÉNMŁuŞXą˘FĐűOţ÷żO=ç;vĚ´ŐďĽL™Ň1ž m +§XĹ56Ź#(ł%ŠŞBŐ)”[ _Ű´é Ę™aƘö2Y'NŹĺnŹn?˙üK•7}űö6e3\ű ҁĘeçÎ]zĎI“&HҤIpÚĚž'=yńÉ'›letÂ(}żóäE°žĆMžťIw(÷ą3|ř(ó<ŻČʕKÍĄŽ˜‡˜˛ýÄŐó[@"E uC(Y˛„ŠWSLYF— Ž‹ďnŇŹÁuž~ú)ɝűY͛çž{Öďs9Űz ţÓÎÔŠ3L=ke&› LűĘŽŠŤĆłM›öňŔôY;ujŻm˙Ÿţőüů‚g¸÷Ţ{ľŽbě€âĹŮGë‹|Ѱa}šëŽťMÝ~ÓÜ–Üwß}Rłf ݞ ĽßtC°6‰>3 ü‚{YłfMdéŇEF)[ˌ—}=ŠFˇĺmጨëőwȐAF ąŃ”á‰KŕôÄ9ƒN6>,ˇß~ťśŃpU&b`͚ľŇĄC;Íă—_~QÇŤža\hٲľÜ:ÍĎŽ];ŠRýŻżN{î鶽؉ďńގŰń3ţäG䁯ţßŮ/˘l dœawüć›o%}úűŹ:Ď(Ŕ*y”,ýű÷Ńv‡k 2LÜäëő&›r­Ąű‰3J•*%e˖ń|‡–šXą"*ô,Y– HŸ>ý¤qăŽüéąbđÓO?Š€”>}z=†ŽŰW,†ž=ťëşvílŇRQśoß!Ď<ó´Ă@ƒs’%KŚß!Äa€Á `ţü…fđîoV¸ňčďuëÖŃŹÚŔ7“×˙ý׏ ’téŇękéŇwtP‡4ϘYĐĽKG]QŔÄŃ-¸>ňćŽ;îĐÁ4gÎÇ͕JÍ}|¤çΝ'űöí—GÍŞBiŐ=B4Ě~ąZ‰“˘TŠR™ëÜcŢďŐĎŕĐü„đmrÚ¸ńK—.×<íßżŻ z`čĐAŚÜśiž[ÇáŹ+<’E .čwŹę .`Rƒôř–oßžÓ(¸ÁˇeĐkúŤÎzëÄm~á:E‹ÖĎ8—.]Ą ę„ůÝťw˲eďaň~=Ç_=śpų̋cpxřáĚú“SL.VŹxWë@°ôceqÁ‚EFnŤÇ­ü‡y† é˝Ň„şěŤN!/1^ťv­Y͌Ňck×~ u×W\‡äɓë˙ńťu _é@™ýţű]}ˇÚśÔ­™3§ęDmTŻ^MZˇn§JД)S­[Ös!” Ÿţý¨BÔŮ~!`Ł_Ŕ„âž{îŃcPj”-[A>řŕCmČ‹5kÖẐţŽăV^ŕ9ƒő5nň99ÄN¨2Iˇn"ć´§ohÔ¨ËE›†Ě„q JŔ>}zy҄ňiܸ‰çžnۋřď-B?áO~DÝóŐ˙űę‡]ĺ^XYýişté<ĘüZľj%řTٜ)aúçLzŹ|ůrFŠ2ÔoşŽgٌk •*$ÎHŸ>×wĹ‹ő:öÔSš´3ŢłgŻŽ.cǎ:X a ť˜B[X>ĆvK•ťîşÓŁP¤öűíˇ}ŞXĆýÎ;“{΁5 &“Vh֛5kŠ~ĚPÖ`•ÍŘ vîÜŐmuĚďšÍ„ ˇźřâ  HŁ%źŰnKŹˆ…ľBm™b‚ƒ×ʕ+˝Ň ŘX“-'¸° ĺŔƒZVX]”ťň‰]( ~˜uĺńÇóş9ť°‰A“šíۡťžŚŻú珡žp“_éŇy?ď=÷¤4őďoýźwď^S'S{*őŘţŒ1Óďî™Q'2gÎäuNŽŮĚ3îq•~Ťî;Űcž|y% ¸uěŘĹ3Ůx˙ýtBîV˜÷—Žč‰ë2Ÿ ëy7lřHWSŘŻV Ŕj#Áę@ťłˇ”î‡ôŘű €źÇDŁjŐ^ÇŃî8䕘đ@@D^”*URÓqK tc’î}˛gĎîő=gÎÇäă?výüŕţűÓJ0ÜäE$ú g[ÖZXŽ4ŔR YcËŢ˝{Lú÷Ş›Ÿ ě°@žýüóĎę*ee>8xđg’čŚ/ň”]9rä0cGR/KpúM7¸iSąí3ĂĄpá(łâ˝T*UŞŞ“ţgžyÌŃW•ąáŒ—Áú6mŻ˙@śŔóA†[śŒż$”ÝŕĐż h­ęŐky}ϓç%Łho#áŞL‚üÚşő'UÄîŰ÷›iżz”źuý‰˝˝ îŘďᶽ؉ďńŢ"Răg¨ňŁŻ~ ČÁPŚYJŒ Čsœď]~ˇřB€ű\߲!×*UČ …?K7ÖáóÝ)îöy/ 0ą„™#ĚaŢ?qâ#˝Ś(‚eËËgŸ}Ą‚ŰŔƒÍJŘC^+‡‘ VQ *㡝îşËç6¸1a5ďŮgŸQÓ|AŤV˝'á` ;qI { \â’HäŇďë=—Űg†Ŕę<×n…,ý‘*?X6@¸Zˇn˝¨žTEVÎÜN:G1Žp_X…`öŠçK č…Ť‡Kcĺâ`bˇk×.Ów đ:7P_Iš˝ţřúěů#™Ć¸ě_‚őŸnâPřjŰžŽÁzÉ×äÖ˛vˆ-÷ޛ2Fţ‡ŰoĆ6Ď#=ĆřÙN(źćÍ{K݃áz—ŒI“&Ť ÚĄŽ—qŮżŕ~WƒĎ^Š17@6‚ű¨3-, 3ezHÝ~:wîŚ}‘?Y .@|%LŒÜťdɒjŮиńŤbOˇ/y(aBďú×íĹĄÖÝpۊóĄĘ×R&şÓAČľ€1UHźi΀}›7oŃć~ iŇ;4€&ˆ0áľŔj%ü™ŹË–%Î@œąţšXY„ď5„/ëŸĐ‹Łc˘@Ŕţ駟5˘>Ěz'LŤBVŃüYąb ú¨ëk:ëŸ"‘_<ňˆŚßĚfÁęąŰgƄ+SZqÝŹYłşJ?pXÍ8ó ŚéţęŽ/a ő Ö0“ţ裍*$Ú-̂]Ă_:đĎâËJŤĄˆ3nÜh5ëÇęœSŹn… ňąL0Ałˇ;Ź`[i´ňy%ÓSO=)2dĐßÜô5žU@ ÷>`ëVď¸Č?ÔaˇĎÉ4F˘ń‡›ţ3ČÄą§“0űwäŮĄC‡Őßş\„ĐÄĺ.Hnú;îHŚÖ–%¸2X›ŠôÎhK¸ëřK'âuěß@­TZľj.sçFż´‚š†ZŢnú—k\(.\¸¨Ö9v`Ĺe zŕ⌘1öXGq Ź7múÜČ?]ÔíŠ(XíŘ­2g~X­~ě“qôgϞł=CčíĺZ÷nĆO7m,˜üčě˙}ő‹(çýű÷ű´ä —ëY6#äZCĽ ‰70 #ˆ+"…cĺÁÜFŒ)•*UôřLb%J L °xíľž€g>őPŹ č˜ â{ ŽH€žš5Ť›•ő‘:b‡ĺËWHŰśtŐ`âŠŕëżoß>T0pdÉ=Ů6l„ôčŃ[ŸĎťpá;*" [\ĺβeËŐg÷D ł:˒%Ë<ç¤NĆ¤sŤšŠ‚L™2šü <‰ç@€°ŐŤW{]7yň;ÍęúR}}ˇSąby#Ńř4Č#řŘ"VŹXĺ1 †łŽ řfˇn=t ˜ çĘő„tďŢ[CĐ@@ÎÇ×řŃiLŽ‚Ňś›úç7ů fP  Ł>ÁÚ ţÁ‚şyf€<=zŹŽÎ˘} ż\š2ŽŇ:Z˝zU3q˜ uy…]8›Ă>ąăŹSe˖Va ;ą󅆩2vĽ@{0čLÚ L°Ń,Őˆ‰ĄmiA›´ď‚Ő­PŰ̟;uęŚyŽ@‘ŁGÓ:˙çŸzĺú,g^¸ék|á/Ďýî}Ú.â†ŕ?˜źa˘]fByţHĽŃM˙‚źŮ˝{ŻNşÜîrÜôŸÁ@ú dB{AEü¤1cĆyľíJ•*EĐťĐöĄ„A°[Uőž; YAPĂÁMbš.!h;~G9̙3/ŕuƒľŠHô™N`Ą€ŕĄŠ>ucŽÄë@TĔÂ}QśP˜ŕ ÔňvӿĨŰhgčߑŒŘy°sçŽăĄœĐŻÂ˘6>Ŕ¸ % vťAţ˘žwëÖÓKaUąb9•#°{ž őräČ7ź”%ᴗk5Ţť?Ý´ą`ňŁł˙ˇ÷‹¨č/ürĆË/ż$‘âz–ÍšÖĐý‡ÄđE$|ěHƒmĺƕꂎÁ÷äÉf¨žťXݰű˛Cs=vě(ÓáŽR“Lřó"¸U\Ź!˛:‚Üa;@ŹNÁg;9”*UBÇd˘_ż>*A°‚š:Ň5mĐn@cǎWóWDĚϞ=›ŽGyśAĊ‚•F ä1U"ą"•V‹xЊŕöůÝ,núËD †zőš˛ďŞ;F¸ÁM˙ ”óŘąo¨bÁi‘~ěr„]Ť,đ S§N6ýŇxSßۘ‰úe™0~|OżŽĄ°tÁŘxîÜY 7}â!ŘĺřńÍ„ŠŠĆ6@ŢÂuÄÁÚT$úL_  1bŽ P,bGtîÜAWë-0Yƒ;Đ /Ä3vďŢĹӏ…ZŢnú—ř“üşu¨ľâÎ fϤIă5nE  ´lŢź™n­ E,uâÔ7ČŘÚˇaĂWÔRąyó&š~ ôŃíeœ§EŰ@a!‹pÚËľŸnÚX0ůŃטkő‹Í›ˇR™–TmŰśŽ¨éő,›r­IŕâxŰwësBŰťőJtĺ•řĘ KFP5§<ţż/„ÍśÓäłeË6*Čc šQ@˛TŠRŤiç­Ć­üěq V!ˆ­]ŮXąĄu붒!Ă,ë¸áTŹXUˇ°´v“"„Hâ”é°HUĚŸŽBb‹Y€Áe§Ěë?ó‚?î…+Ż‹W^—lŻËśwË7ŃţYŸş˙ žőę5’aĂFŞi8Ě1a)SG2ť‘řő×}ń˙VäV~ö[¸+ŔuqjÔ¨&„BˆČpeʔ—E‹Ţ‘¨ť,i’&˝]cOBȍÝČ V3úőë-SŚLU_iřeF›Vöwľ%óőbŔŔ´ÝžÝĺ­Â­üěˇ]ştWWX¨ x!„b'cÌfŹč,sçΗɓ§éą\šrj`ÖřÜĽˆBb Ý!„B!„rÓî?´T!„B!„B *U!„B!„B€JB!„B!„0pťűĎe!ä[Ë/^JâDŠďŢ˝§ÜLěÚľ[^|1Ż=zT!„B!äŕ„–*„B!„B!a@Ľ !„B!„BH¸u˙!$$~˙ýwé×ď5)Y˛Œ,XDÚľë żüňŤç÷óçĎËČ‘ŁĽTО’/_!iҤš×ďĄ^Ďß~űTŽ\]ň珒W_m&?˙źÍë÷UŤVKíÚőő÷ŠŤĘěŮoyý~ćĚůTęŐkt%mUdÖŹ7őzö˙áZvš7o%cÇNđäÜx6múLŸ׊^˝ś|őŐ×1ň j՚ú;ŇpěŘ1!„B!„*UHÄšxń˘´iÓAŽ=&Æ ‘iÓ&KâĉĽkמsŚL™.Ÿ~şI†}]ŢygdΜYştéîĽ4ĺzžřűďdҤ)Ň­[gýOúô÷KŤVmĺȑ#ú;ƍ”J•Ę˜9łĽYł&2sćlůđĂőúűĺ˗ĽS§Ž˛mŰvŁ é/&Œ“”)SšóZČɓ'cÜo˖­ú íÚľ6ʢzlâÄ)˛té2éĐĄ˝Ě˜1UҤICq,XhFĹeŢź9’1ăƒňĺ—_éó*TŔ(SŚ›tˇ4ů´XÌ/Ą2uę “­Œf<öXvéŮłˇüóĎ?úŰşuTiTž|˝O™2ĽeřđQB!„B!$8t˙!'Q˘DF91UwÜq‡Ť^˝š´nÝNN:ĽŠ‰C‡J–,™ĺ‰'ręď]ştT땄 †u=_ŕz;ś—9˛ë÷ž}{KĺĘŐdŊwĽI“WTń‘;÷łFёF行ŞŮźůG)Z´°|÷Ý÷ňĂ›UńŔč9˝{÷”5k>Đ4ŮŮž}‡Zą4múŠT¨P^AqK’NÚKá…ôŘ#d‘;vČž}źţ_ŞT))[śŒç;/Ŋ‘† ëë÷,Y– HŸ>ý¤qăr÷Ýw‹[š5{Փϭ[ˇ”÷ß_kҰSž|2—ĚŸ­ĚŠS§śç>Ǐ7Ę ÉB!„B!$0‘RŞpw â6|$[ˇţ,ě—Ýť÷čq(:@ľjUĽsçŽRŁFyţůÜň šĺĹ_űzžH’$‰dËö¨ç;6?ţ˜ěŮłÇsěŘąăŞdůĺ—_Tсß2f̨żAů‘:u*BĹş†e…bąk×iĐ ąÜw_UöXüöŰ>UŹäĘő„×ůĎ>űL ĽJúôéźžCéQźxQŻcO=•K.\¸ îGO?ý”¸%mÚ´žĎ÷Ţ{ŻžŸ;wNß÷îÝ+ĺʕŽ‘>B!„BšÉ‰ˆ#\÷ŸË>>SąB”?ţřCęÖm(Ë—Ż”‡zP }úôň:JeËŤ%#––-Ű¨Ň œëůî;xŮąť˝ýö\!rúôɛ7Żş ˝üň‹^˙wÁÔÚ š>Úă^NŤXÜ\O8ŸÓísB!„BČ Š/=FXĄHÇTálŒČ÷ßoÖ¸%ăƍ–5Ş…EžĘ™…Ź1 Ě@ź¸ÚěÜš+Źëůâż˙ţóşbł PmÖŹYőűęŐk¤Zľ*Ňž}UŠŔŠĺřńŤąR˛gĎnžŸC‡yŽAá—{0×ňŠkQíÚľ4­@÷2¨e˖ŸźŇ…ç ,lŕ†dgóć-z=¸č€¤IďĐôY@‰cOŤp-óľƒ`ť„B!„r“Q˝El—Ě‘˜>Ž‘[Ä&Áʇ|ůňÉž}ű<;ŇX 6B#íÚľ1ʁ¤˛hŃb—r˙ýéÂşž/’%K&ŁFÖř)ˆA˔ӧOKšrŃąK2eĘ(›6}nŽ™W’'OŽiŔľłf}D‡5 \wşwď-mÚ´ÔsŢyg‰|üńÇR¨PAĎ}Ź80-Z45JœŹvÖŹir×]wiŕ×ńă'˜gK*>ř üďŸ¨˛$Y˛äÓ^ż~]éĐĄłIc&U"íۡ_FŒ@P݊žx*pÓA (`îťď> dk uK­Z5ĽG^Fš’EňçϧąasĹÎŹÓž#G• 2!„B!„Ü \vyĚ5qľűĎeĄ[Đ- Ź|M–,Yf”dŢźŞp°3hĐkf‚žŢ( şIÆŻhL“1cFÉ=÷ÜÖő|‘"ĹÝćźf2dČpÝRřđá#FÁ1V {÷Ž’1ăş#śhĆΚěňˇËaź;Gü|›¸P@Šw’ –ďţîě8!„B!„BŽÜXŞŘż‡űčš!.• ‚|vŁl ôY\'„B!„BČőI(n@öϗ]üčsĈkeD(V+n?:F!„B!„ˇký}Ž7ë;ńĄ˜HÂ÷Řl›L% !„B!„rcp9ÄßÝZ Ä›Bė"Ľ‰% '„B!„BČÍM0Ť7ßý‹(‰$ţ% •'„B!„BČ­‰Ű@śĄžqâSŠÄÁo„B!„Bšůpťýr(żE”řVŞXÄw|*e!„B!„ř%ŇʍPă°Ä9×JŠbОƒŠB!„B!äÖ Iź+S,ŽľRł B!„B!„„Â5SŚX\/J;T°B!„B!Ä×\‘bçzTŞ8Ą’…B!„Bš5šŽ”(NnĽ !„B!„BČuGb!„B!„B!!CĽ !„B!„BHPŠB!„B!„TŞB!„B!„„Á˙<ÝĚčî(˝IENDŽB`‚kolunmi-bazaar-7b9c8e1/screenshots/library.png000066400000000000000000001677771514314607700216250ustar00rootroot00000000000000‰PNG  IHDRˇDBYÍ7-tEXtCreation TimeTue 10 Feb 2026 08:02:03 PM CETžŢË=tEXtSoftwaregnome-screenshotďż>ďhIDATxœěÝ|uúÇń'ٸ4ŠťSo)PoĄ-§´ŔᇻnrČáÜĺpť;ÜÚĽ…5ęî.ńd-˙y~Él7›M˛›&ÝÝôó†yÍěěěěěn›NžűüžI F%َłˇłˇłb!܊DJŠDąh Žł˘WT…]Ń$hЈ]‘•Ây~0€˝'œŕ*b!W¤ُ=źżŽŸ !ŞëĐŠtďŻs{;ô‰Ť‡űP?Jëáž:ľ7Cُ0ևł-ęViëĂŮśÎí­°(”ŤŚŰU­@Ý %ÄŞévUëęÔދ ąâÂx\MĎ€Ş…Ű?Ť4„ĺPn׊ú„B ˛B ˇ¨â¨_5U^Ő´NŕUgę3 Ş)¨Şn]8!WuëPľPúeUd…rŐKŔUĄP8ŐZáÎŤzŽšÖ`ˇP›Ŕ—îáźş}։şƒŞ Ą‚Í÷$੠ă°[iˆ÷Ő&Đ %ě vťÖ¤îT7”°Śp+Řr|ÇŰż„°ť…3ў{ýnë'Ą…Töśţű őą5Ş‹0(”j­ŔĺŞî‹˛>>ČóĐ``τÚ@>0Ô˛×UUąU*ĄUsIˇĂ˛§•[ĄVkUu;pň˛âŤx|ŕsť €šU4ŮÁ”ŃřZqR1Č* xlU•Yu^ĹUŰpŤśŐZUZţËö8ŤášžššČ{ƒĚýĂ-ŻTtUőœţĄV`ŕ˛ÚCĄ[Ą„Zö°,R9ôżőU Âç*y–ýC,ń[ö,WrU|ŐÉ0Ĺp+ˇŞ śBvčd9$xŔĺ_ľlˆ"ęG°ŢZţU[Á‚-”e6Ű‡ň\ĂĂŚN¸UŰ`+°Ë!C-‡ß¤Ç“X>|lœ0$ >ŤžňŸěĐĘmMŽňšÇoŠ—Ý!—'`Ţ*ž/.`šVמö܊ XWS/-GIĂŹOž<őž}{ LKË蛔”ĐÁë-m,‡!`ďňĆÇÇít:Ýk ó˙üóυż}ČT) šŠËçv¨egAşlWuiś,ä l(VŖř=8ÜíBéąĺlŮUZ ~ˉĺËŠŁGnüöŰďœŃŞUËÓŹ0ŤŠ ŞYa×öM›6pÖY}oňäÉ;­UERhiĐeWpšý–Ci>ŹWaW(áVMĂkjďl%ČisćĚ9ŽOŸ>×jÄ šćϟ˙x˙ţýż´nĘî!‹ö°E;ŕ ľéźH˜ ćĂ ˇŞŤÚ Ö[+X°ĽCSˇnÝz}VVöY€˜–“łëíć͛?.e\:T1XŔeUŹŞŠK¤Ő[5…[áTmť˘jŮs śŇrrrîNMM'hŠŠ ?ËĘĘş[Ę*¸ě€Ë#›Ď^iqŤˇÂiÖʉź}Ű˙>˙ËżzË4Ž×Š-‚-€†EóÍ}¤üR–ůçCţš‘HĹLIü։„Ţ'~Ž–'UWrů÷ŰňUm͚5k,C@ §Ó)%%%âršÄëő ˘W||ź$&&Jrr˛$%% €?Í}ŹügсřŠTŹÎ˛s"˝íŸ)•JĹ +ěŤ%VWšć:;Ô˛÷ën%Ž5Şqż~ýŽ€rnˇ[rrr$77ׄ[[ŃO?#ýŹô3ÓĎN?Cš˙h$eŐ[vՖ=‰TŽŢ ęşęÉÇH°J-hIYŖ~Ľ—žnÝúK[´hq…HYľ–$ˆ}5˘Š T°e˖çÚľkű˘ľX`MN)라WR ě˝Ř`^¤ęŢ[AŤşjnUŐHŢż‰źÝg+ٚ˛ŹoőžözK› ŘçiľĎŽ]ť Gvvś$$Ôśăhhâăăś[çÇX‹9ÖT"eÁ–˙ýݜjců áV8 ĺƒ zU’8yňÔa[ŔVPP hXřL€?́ŚN:L‚M ÖË˝ÖÂůz­ŚîőU]EŃѧOĎA eĂľq<ýLőłex"€XˇŁŔ+ŹuĘw KdgaĂę™fýˆŘ!Yt܇~V[ŠD˛•|4J‰—&é{ZßÓ0x<߅|tŮîyލq8ž ÇčňžęŮÓäA“ĽćŤ"–úÍ%`}Ş ˇjJĚŞ ˛/ëh­ôôĚ>`ѓ)4LúŮnˆUNOŠlŘĺ‘/çÉťżJCőËJ§Œí—*'˜&ű+)ąžSŰęňJnąWÚd;$ÉąGEB1KƒŹÂÂÂ*ĎĹ4äŇIC/ÝNŽ´´´= š23M¤;–Ő&Đ z(ąe`ď­¸*î \ç ˇ’’:€U[ Ÿ-€XŚÁ֎‚RyofĂ śl_XŢžHC.ýœ÷EĹĹŲsçΰždÔmő1úŘÚJH0y¸%Ró•Cɞ*¨‹šźŞŞ¸|М×[ÚXD|ĽďhxřlÄ*ЍÁÇň­.) ib•~ÎúyďK´ +??_jKŤű¨ň<(°ÇVUĂk­Ž.iSŐÚŘ ˆˆůóČsĎ˝ ‹-’ćÍ[Čřńcĺ´ÓN5=Ô'Ÿ|jî?á„ńrŢyç˜ŇkąeΜšňŸ˙üWfϞ#ťvĺHăĆŮŇż˙ţrĘ)'Ëţű÷¨‰WSž}ł¨gŸŁŸ÷žŇKŤŽjLůÓ}čůsJJŠ„ŠŞ7Ú?GÚăHyO>ÍPúrí›YQAƒ­K.š\~˙ý)((”UŤVɓO>#O<ń´o˝/77OŢ|óm9őÔ3äË/ż˘úd0cĆ/ň÷żß.K–,•ş˛hŃbůěł/šˇiďGy\.˝ô ™8ń;Ůşu›y˙ˇlŮjnëß˙Gý?łT§Ä-؇ě+Ÿˇţűˇ'[t_{đoj(Q­3¤şŞÜ Tg—s ś´"+Ř?ŔZáqƧIëÖ­*ŹßśmťÜ{ďÖýËÍ7ß ˝ző ş_˝"Üȑ‡˝OżŃúé§)ćj}­ťîşŤĽśvíÚ%G=Ö,OŸţă5ô<㌳eĺʕňĐCȨQ#ĽĄ:ĺ”Ó%//_5ʔ?|/č6 ,”YłćČ~űM“îÝťŐ¸O LŽ?ţDłüňË/Hűöí*móŻ=$›7o‘ôôt3ćP¸Ź^˝Fîźóv>|˜ î=ţř“ňß˙ţĎ|‹|Î9gYWŽ”ć͛[áÖůöۉ&´Öż‡ęĆŻ g×ňĹ_ZűţÄüq8âőjOŚşsĐ  ěżĎO?ýDÔÓЏoЧĎ{čЃĽ6f̘&őĄ.*ś‚í333SÂ؛˝Îíi^MMŔˆŠŒVf-]ZuĹÎ… ĺúëo”PtëÖMúôéă›úöÝł ëI‘NëÖ­Ԏ[J+ňiđĽzx€š=kÖlŠ+çœsś{ěŃVĐ0@P˙t(˘l=űěSrÁçI›6mĚĺËŰśmkn?ó̓ć~ ¸ćΝňž_yĺ5šďž™ŸŮŮYćjQZĺyÍ5כŞ?˘~Á[W¨Ö}ÖAEtgIu]šE°ˆÚcŤ `U÷5ŻňqZuâ‰'H(îťďéؑ‹G3 ´âââL—|i™””,+VŹ”œœÉĘʒ=ĽŐZ:íŠŇŇRsź{ëqąĘŽČҊ­>}zÝF?çłĎţŤźüňŤ& Ľ˙–Űí6_ęÖ[o2ýřô˝}ěą'ĚsžýöťV=DęËžö9@CR_XľQS°Ľ#ô‹Ů;ďźÍw”››kžÜŃ/„žůć‹j÷]}jëôťÚVnť$#˙ ˘Š6ŚWŻ^UEÓŞ›7ß|].šä"ŠkÚĐó…^’qăN4ĂO9ĺ yýő7L%™Łň/e?ůäÓĺîť˙YáńS§N“ÓNűŤyěůç_\Ą_”QŇÇ˙řăßş›ožŐŹłQˇĺĺĺ™~ScĆiŽA‡o5dhVqiuOŸ>=Í{?{ö\Š : QOúéç ëľ?Ĺ}÷= 'tŠ\xá%ňĂ?úîÓĄłú˜—_~Mî¸ă.9î¸ń˛té2sŇřďż)guŽüIćqď˝÷žŻÜ´iÓÍănşéVyőŐ×­?ëąÂ›ĺЧž1ëxॠÇöůç_JCĄÍă•EŹÎQGaćĄVéé{ŻCUzz†™kŘtĹ—Ęťďž%ˇÜ˛ťŞsáÂErőŐ×Ęa‡i}văäśŰk×úî× ęË/ż–ÓO?K9äP;vźůlô˛ęJ‡Ű՚“&}oöqÓMˇ˜ű´‡Űľ×^/‡~”yä1f˝ţŮ´fÍšě˛+eÔ¨1V(Jƒ˙ű MM=@őËŮůóç[˙ŽÝnžčÓ`ëÖ[ď0ÁV°ö áě; Áň¤ZeKuuy‚-@ÔŃ~W§žzŠďʈJƒ­űîťŰםŞQٞoŞtӃŢ/O?ý¤tíÚEęƒţ⍁EFFŚő ůQRTT(/žř˛źôŇ+fčÔqÇăŰV+L8 …Çßu×?Í/Ů:épŠ[nů{­šßk ˛nÝiÝşůEüŽťî‘_~ůUö5x ™×ĺĐÄ`^{í ٰa“´lŮJÖŻß =ôˆâćďŰoż5Ăh5tŐ!pú­éűďhýYÉ0Ő`EEEňĆoW *ľçŇ'Ÿ|fNPłłł­¤,Čůőיž€Fű~锘˜$ŁG7œ^kzUDU]ŚjѢ…™ďÜšKBĄ=Ó:¨ěφţݸńƛĺĂ?2'ţ]ştśNřۛű–/_aBĂß~űCú÷ďg~n|˙ýdłNC+őÎ;ďĘ˝÷Ţoýc…lGJăĆMäłĎ>ˇ‚çżWzއ~Äúć<ŰúYÔ΄XÚ Ì_­çë íÚľˇÂíéVŔv•lܸŠÂă´żŸözKMMąîŰ(˙üç}&đěŰj:x˙ý˙”6mZ› .iŔĽÓŠ+Źó•–fdžě;Lu’'ŐWCy"NC­ëŻżFÎ<ótY˛d‰ů%¸GîÂ.­Ć1b˜ 8@’’’$\wß}ŻL%űnkĎĽă^1vţůçÉa‡*Gq¸ 0´aľ†ÓŚý$—]v‰ü㡛*ĽMČŰľkçű%YÝzëÍrĚ1G™_|Ď>ű<óKކ;w’pôë×× Xţe–ľˇŘO?Í0Ă­† ,ű 0^{íßV¸5KęSďŢ=­ĎółüÜ-3gţ&Ÿţ… po›F™Ćŕʍ3Ďű¤őg ło]‡í­pc­ ¸>x„L™2ŐŹ>|hmŔF-텥WGÔŞG §Ť˘÷Űۇęî•'žxJžűîó÷S'}˙8bŒů{¨ŸÓkŻ˝nÄÓO?M.źđ<ó¸|Ř<ćĂ˙cŞ?GŽ<Ąš={v7Ą˜†OZ]5oޟćrşýÉ'˙Ĺ,ß~ű?ĚžG:Ä÷wőţű4šţâá1ŒăŽ;Vî¸ăďŚÁďé§˙Ő\)R?ű. {[45”Żé Đf͚Y_ŹüË|ᢗjѢššđ\{˛ďH Ü4hţ9ßú…pš´cÇó‹îˆĂ%!ĄěŸ@ý%UŻd§Cő´×N¸ý´‚Ę_˙ţűWš­Vvh#{ýXƒŠĹ‹—˜őv…MM† +ëóÓ­Ű~ć8ő—Ů‚‚ ט1c|ˇ~¸ ˇVŹX%ű­ÂŃZő˛aĂFóíe}9rwľ”^ĽRĂ­ŐŤ×VŘFƒ.;ŘR:u˛ţÜŽ”'Ÿ|Ú:ž­˛lYŮp4—ŤâŸ6ŕl) Ou¨˘2nŮCUíáy …V6Nœř†§ÍăŤňÍ7|ۇJŤŕîžűNšá†ëŹ č73ÔtâÄIćůôgÇ]wýĂ4´Wďż˙™ü­^˝ÚĚ5 ÖĎńwޗőëיo6ŇáőÓ1cv_uÁ‚Eĺëv˙]˝ýö[ƒŤ}%Ný™ á˝†[zPý7M{Ú´mCbblĆD„[€ëË/ż’{ď} Ňzšőŕƒ×?ţřÖ/‡érÓM×K8>řŕݐĘë/˛^xŠFŚMŽuH\ďŢ˝ĺÝwߓPů˙"ź‚Ű˙›4 ëBľ/6°Ö > #ľ˛é?fŐ[¸LŕŰípě>%Ó?+×^{ƒŠĘëŐŤ§Š´ÓĐB˘ňœM‡1j/ˇß~űÍ|ťnÝzóMl8áN,8唓MؤC5ôJĽZ!őÖ[ď˜?ßvUTMV­Z-Ó§O7CľÓžP€6‘˙Ç?î˛îűÉlgä_|Ąďę›6 ÇÔC=*Ÿ~ú™´nÝڄęnę0Â`ěý…ËáŘ]‰J#zˆŹhj(Żç9ŐUXi˙Ç[o˝ÝœoŘ=śÖŽ]gÖiEWăƍŤÝw´‰ž# Ž6öśiEK m"]—Kś{,[śÜ[­Zľ”W^yQŽźň2kšEĽíí_N]ŽĐƒ)eWœÍ™3ĎĚu8ăüů ‚n;qbYĂi­fł—ťví,ű"ťˇŇěŮő×wkňäÉfŽď÷äÉeÍä;uęXĺö+WŽ2'šHýß˙=jŞ’Z´h&ĄjҤ‰f›Ÿ_ ďż˙‘Y§Ő\Ńx"ş'´/\zĄ†ŤŽşĆTŤ­_żŢTBŽ[ˇÎú{öšYŻŻł˛ŐŘ׌xúéçäţűËŽĽôł[° ŹJSűă) •î_˙é´}ű3ÚţÖ[‡“Şçž{Jnźń:+`< ¤cčÝťlߓ&Mň­ťçž{Í%ü/H@Uüż ćŽ;îö[fé¤ËpÝ~ű]{´ďH r Đ`UŐěŇ^Ż ˘ő*uZá´pábSŠýŕƒ˜ůĺ—_˛G—8śƒŤ &˜e;\Đ!pÚ;GŤ4žűîťJÓŢAú‹ůmˇýĂô×7nlHϧWyÔ+Ţčđ(mżmŰVӜ:''ˇŇśúKúŮgŸožÍÓ!›JC‚}‘]qŁWŢÓ÷#”č_˙zX’’}ˇuxăŐW_Uĺö:üôŠ+Ž6űˇ{ZŒw|•Ű7nœmŽCűIýß˙=eýYqřúf…ęČ#7}—4LÓŔTo7D×^ű7 ™4üŤŽV€éß§™37MÝ5dÔÍžâŚöđSçœsś ĘľrlńâĹćçŏ?–}Nýúő3óŚM›šżĎ˙ú×C˛ß~ÝĚçQÓ7éęźóÎ5 ä§L™fŽŒŞŻcÁ‚’™™!={öj˘çłŐ]ŐPĎťtéb—ŢăŤŇҀKƒ-íďXÓžŁM¨_áQă hpô—â‚‚|ÉËËľ/ˇ9Đeíeľ§4źĐYN§K~řaŠiĚŠWĽéŘąŁéÝŁ=”nźń†Jűűßo6=”ô*†á4:?˙üsMciý;'g—Šö6lhĐm˙öˇŤ¤u떦šľ6šţç?ď6•>ű˘–-[˜áˆZĺ´dÉҐŁ'|‹-öMŤVUeş‹/žČzžćV°šŮ /ۘ†äŐ Ô ÜvŰ-ćŰS C´ڕW^!áЋ4jTÖ<^‡^ÖÔ6Vé7ÇZőňË/˜žbúyę ˇRÚüýĹŸ“ˇß~Üźk°¨—öŢŤÉĂ?hţéßW˝*ŁŰí1Ą—^@Č+­ÜzţůgL6oŢ|ÓťN‡ęąôéÓŰlóČ#š÷˙Ď?XaŐ4ĆĽĽĽÖřüÚWO}đŕŚ׺ukͅ/ž{î™ ÍäŃEĘ×fŞzń˘ę|óÍćK˙ᇺŹëôž=Ůw )Š a}œßm{9ŢonOŽň)Ą|ŇKNiœ—mŘĎö˛;î¸S&MúžŇz˝úܔ)×ßvŰŚç–^u őkŰśmRŸŽ>zwľ›žœŮˇ—mĎ<óœ|ńĹWrŢygű‚‹X§Áíšç^`š‹ß|órŘaŁeoŃŤ/E ´ŽşęZLöčŃCŢxăU‹7•ľ˜ľĆ)OOΓ}Ákç4•}YVu?-šŽ–¨ô‚IuÝvCƒ­pŻžœ””¨ß¸ę%Ŕľ”LŻŽă.Ÿ<ĺ“×o*ő›—–ďÂY– †%ŹŃŁGË÷ßOŽ4H›CҨ5ôBěӊ%BfW.ŮóŔeŰĐĄƒÍđ2 7‚§žzĆTĄi°Ľ•b#GÖĎ7ÂąD‡">óĚrĂ ˇíuŚtŁT°Ż¨§ąiŃÔP^iE]‡[{ŇśŁ>QšhĐ´Qćňĺ+L%‹Ňţ;:L(°ˇ’ößŇ!N‚úUߕ[ű2Z{Î9çKqq‰ôěŮ]Žžúo{}[4Vn@MVmwK‰‹Ę­}E˛•TtjşoÔúhßH˝XJ]ĐódűÂ*á r €=Ôąc3Ő$++K€X§ýŚŢ{ďm„§QJźluy% /‡z Ÿ÷žBĂ(ۧ=eľbŤ6ÁÖ޲ď|˘ *„rEBÄ&>[ąŞIzźŠćéÚ6Z‡#Ú8{U4^>uƒĎ@,k“í°B89cPt˙_ĆöŤůĘ­ ‘[ú9ęJ݆Εu[}L4WlŮ–ö*=QŞë挈{ůŇŕP§’qŚÓƒŇĽGŤDůna‰ě,ôJC’–$2°C˛ č¸]D'Îú÷)Ąl(âžVąHűËę•íFóÚŤÓăńř.ž¤Řş~YĽ˙Ś;bhœ. ĺŔ^§ üő„ ‡žÓťÚ ĺ–öşôôtAĂÂg "…p ěu ҨQ#AĂ ŸĽ~Ś‘@¸""))I˛łłiBĂôłÓĎP?K€Há+61ZíŁ}šœN§ŻąŠÝÔŃI›Íڍf ľ@4 ܧ! A jƒp 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p SÜnˇ¸\.ńxřŕ#ůôÓ/ĚśW^yšÔĆňĺËeΜy˛sçNIHHvíÚĘ AĽQŁFiďžűžěż?SĽŠ-[śČ„ “dôčQćuDB^^žź÷އrĘ)'Iăƍͺp_G0ۡo—˙ţ÷ůë_O—ôôtYúó\ŽëĎMö6zn"Âĺr…ľ}ŮPIJ`ëá‡˙e…gHëÖ­$11њˇ6ˇzčsż\óç/p-Y˛T~řáGéŘąƒ{ě1&*((0C N§Ä }:uę(™™RWŢzëY´hą@ pŽPWˇĄC ĂĄ“ŇŠ­ž={ÝŚWŻžręŠ'›ĺĎ?˙BÂĽZßž˝eŔ€ƒLpŚ!×1Ç-ŠŠŠ˛iÓf‰5n|đӓ ę[¸?ר+Ô ""Ü_‚´yźŇĄˆŐŃűß|ó™;÷O —öŒ),ŹŘä^+Ăţň—+ŹÓ^a?ý4C6oŢ$IIÉŚ:J‡.&%%™űu(Ţ̙żËşuëÄívIŤV­eذ!žay“'O1CxtřβeK­Ç’~ýúVŘoBB˘tčĐÁ<ÎŢŻ*(Č—ŻžúĆ Ű6Zǖ$ýű÷“ý÷ß?čë ¨ĎŤ´’K+Ű<ˇtîÜE9d„ŻG™>ć矑őëיŰ;v˛˛áŚ"ăwŢ7ëŚL™fŚ /<ĎÝú܋¤Yłfć¸[´hň6JßËyóć™cËČH—ĄC‡š?Ŕž†p )Tn""Ü~[zUDĽ=śŞÓźyłňís$\ýűď/Ë—Ż/žřĘ –˝šcQQ‘Š"ÓjŽńăÇɘ1‡™pç›ož5÷ëëúꍯ­ ¤@Ž:ęHł†f'NްŸUŤVJrr’œpÂxéŢ˝›ľ}Ą|úéçfÝńǏ5űÝąc‡ożś9sţ”öíŰɸqǛ ś3fšçŐʕ+Ěü¤“N#<ŇÇÜšó|÷Ošô˝ůőÄO0SnnŽ žô*hgu†ŮfŕŔƒĚ˛[ú>ůĺWҤIsLGy¸u<ä—_fJ¨ô5j­#<ÂÚÇX+ŘsČ'Ÿ|fŢkĽŸ‰†iúzOúčćŘ´˛GC!˝OŤž”6O×ŔLò””ł.;ťąľßÁžçÖ !ÝţĐCG›0LiP´eËVó Ł˝Ž_żŢŚĘKés­XąB6lŘ`†Q†˘qă&fŘĽĘČȐýöŰOÖŻßŕŤhŇPŚk×ÎžŞŠăŽ;ĆT˜éëр+55ĹĚu*{ŸłL¨ăßÔ˝k׎Vhś:¤ăٸqŁő™m•3Ď<Ă÷ŢhŻłwŢyĎŒýúő3ŸGˇnű™ŕHégĄ˝Đ~ýőˇ*÷ŤŰˇmŰĆwœúzôłÓáĽz|ĘăńĘđáĂ|uÆ 3a•ö8p@HŰčű•œœl†°ęű¤aZ׎]BŽZ’pŽPWˇ1ĄoßžfX^Q›ÇWĺťďž÷m_͛77CľzIC­ÚůěłĎM…•$žiŕôĆoVzl^^ž œÔʕŤĚvZ٤UIĘČNfff…ÇnŰś]Zľjé ą”F;Wź`ffĹĐNˇqšBovxeA­@ÓçśtĐŚęjőę5&DÔĐFߓęhřŚĂň4|ĚËË5!Ÿ*ŐDƒ- ß˙ƒ ëNˇĺ™ĺ;wT곌Ck˘ŐU .2WžÔĘż;vZaÜGź/´˛ékŐíBÝFƒŹ Č{ď} íۡˇŽŤľ I°÷n"B+Âů–üřăM¸őÁÝŚB&Vć|řáĚžux۞Đ!w:´7Ӈ~dú/ <Čܧý”´ďR ­<Ň꬏?ţÄ wŇĽK—Îćńz<_ý­Ä­”ŇžYZ¤UUsćĚ5•bök¤C"żţúk+ëh§=şËŚM›Ź÷k‰„JŤÁN8a\ĽőţŐOVjúłŁĄ¤VĂéŸ=6­0Óa‰űĐÉŽŔSZŠÎ6ž|ň_LşaĂz™={ŽüúëLóç50Ŕ:˙ż'ěMôÜD„…R(úôém† —Č-ˇÜ&ożýŽ _´ů† ĺ­ˇŢ1ëKJœŇ¨Q†NŽ’’yőŐ×ÍP8Z•äršÍ3Ľ=żt(šö¤!ĚŽ]9&ÓcÉĎ/4Ăů4Ňp+”>4şß͛7WmtčŰ[Mšő87oŢbŞŽôý>üđ1fč¤ÝĚ?٤ISÓ#Lƒ$­\r:K$T͚57~wţďŠVFŮż(ëPJzé/đv Ĺ‹—šę=F¨C[´hnúšU|˝ĽŞÖôők%YÓŚMBŢF÷ŠŐyÚmȐ!VĐu’ů ő}ö5áţ\ ŽPšˆ 3 m.˝ôb|úé㊈:ůÓ0¤qă,Ůš3GnźńVyôŃ+\qŻ:Ú7ŠsçÎŚ š†Jz5< .ć͛o4 HTďŢ˝ĚŐń~řáG+<ém™33 䵂';;ËŁUÓŤęp¸3fÔřüť÷;ŮôčŇ紛˛ÉŤ/nˇŰTauéŇŐ ćúX!•Ë4s×đĘŚĂ5Ó!”úŢjEÔŇĽKM-}ď׎]orK$%%ŮlŻďŤŇÇčc5ÔIĂ+}ľW˜Oß~;ŃiÚP_ŤžćĎ_(§œňł­žÚčžI“ŮŚjNĂ&}Îęčąiő™Vm%%%ZÝëłŘe…Rť_‹9ÔfđÚ;KŸWŤÔ4˜óżkÚF‡=jĹŕ¨Q#­÷"Óź~ `5ö5öUWŘŰŞú(.`9.`9Ř09ʧ”üă΋?li˜­ ĐáqÚ]†üüÓoŞI“Ćfý5×\%gžyş6ýnzFi84räÁžFĺ5ąŤŹĘ•f¨™6/׆ńâ(múŽ‹îÖŹY&dўLZš¤AŽSÓ`eÖŹŮŚ•ö}:đŔeŊ•VHÓׄ5éóhż&›˝ß•+WËüać­Zľ’CĺŤÓĆę-[ś4Á›M‡KjĽUťví*˝§Ói…:óĽOŸ^渂=ŻVżi%š†5ú‹ŠîGŻ(¨ŻMŤŘ´˘Lƒ{ˆ †wóçĎ7Ăď4đÓ 9ýuŕ…‹­cM´ÂąNŚď–VNé>őłŇý9 &ĚҰIŻĐ¨=ÉôJ‘]ştąÉ]fŘ ŻŻéűiQúţj5WŮóΕ’’b:t¨yíö{H+Š´yüożýfúŸiE™~>ńńó>oßžĂT韏)SښS]?k; e›–-[˜×?gÎslú^ęŸE˙÷ŘWčßEűBŘî˝÷ŢWŹ™^†\‡3xĘç:•™Äo˛¸Ö ˇâĽr e‡Y 哞iężnŮÖ7ż5e اh  A@}Řľk—Ü|óm&ĚéÖ­Ť<űěSřÓ`L+˛Î=÷ě=ÚŔnz%Y;ŒŔf}ą9Ԛí˛&—5镐Üĺ“G*†]vŕĺ|IŔ˛Hđ‹ń€ˆĐ_€ęŤ?‹VŐ<üđŇŁG7Sé¨_úóœ` )ü ˆ¢WŹp=ýô¨Á†°ˇ0,1Ú˙I‡b›~ĄŔŐÁ0,Đ é/BĄ6{D'ý9N°ˆ$ţD”ţR'€ŘŁ?żů’i„[€ˆŇoűÓŇŇ{ôç7U[€Hă_"@Ä%''óÍ?Äýš­?żˆ4Â-@TĐo˙šÚÄýyMŐ- Zn˘FFFD9ý9­?Żˆ„[€¨˘ż01D˘“ţ|&ŘD› ĘčP‡Ă!………RZZ*€ČŇŤ"ęĎfzl˘á *é/P‰‰‰R\\l&@dhľ–N\­ˇQK‘ŇJýĽJ.§Ó)^ŻWőKţjo-B-@, ÜD=;äŇÉív‹ËĺÇc& ťşľ§CőçŹ×IŤfř5;řW Sô.~é`ăˇÄ,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-ÄŹxj)..Nf Tn V4ĐÚşu›lŰśMš5k&͛7“ŇŇRٛ¨Ü@­hą–[Jç‘(ޢr 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p 1‹p @Lp:2räažŰqqq’%=zt—SO=E†&‘śk×.9účąfyâÄŻ%33SęÓŮgŸ/K—.•¸O;l´Ŕž(^ ľnÝZŠ‹KdÌ_ĺúëo’W_}]űÂ-1çƒޕ˙ýďC™4éšő֛$>>^^yĺ5™7ďOě[– f99á„ńV¨5_žüň+ůä“Ϥ_żžćžE‹ˋ/ždŻŇŇRŮ˙~růĺ—I÷îÝdÆ rŇI§šížřâiÖŹ™yü˝÷> íۡ—>zĎÜ÷Ü%'~gžcđŕArŰmwČ!‡ŒC=T^zéeŮšs— 6Dţţ÷[$++ŤĘăÔ}źóÎ{˛rĺJIOO“#FȕW^&ŮŮŮćţââbů÷żß”ŻžúZvíʑ–-[ĘąÇ-çž{ś îÔΝ;ĺ‘G3•j7ś^ËĽ•žgǎňěłĎËĎ?ϐÜÜežűńÇ•źźü ϧšşŕ‚sĺŚ›Ž—çŸĆÚî˜@CE¸ ćiŕ¤5*¸`Á"3?ě°ÝWW3fŒ™˙ůç3?řŕáfŽá֖-[L˜uú駙Ť0Ξ=ÇWŃ5pŕA’’’âۏVl5mÚÔ,÷čŃĂĚ ‹‚×ćÍ[dűöĺÇr¨™§§§ËĐĄCÍňüů Íźk×.&Œ{đÁ‡­`ëJyěą'Ěz]§t8ŁŇŠł^˝zšĺŢ˝{™Śúţ?üp3˙űßď°^ËYŚňŤ  ĐwźĐŃs @̛1ă3ďŮł{ŰjxĽú÷ßß Ă2eɒ%ňëŻ3Í: ź~˙ýxy<žňu#*<^ű|îkO¸\.šđÂKM€Őˇo9đŔ­ŕŞwĐĄ„Z ćO‡+úÓćúÇ5_ .’ &É7ßLß~űÝ źnhˆ¨Üł4€ŇţU_ý š´Ď”ęÝťŹşé‡~đműý÷ߛyŸ>˝Ě\‡ř 2Řěă‹/ž2ŐYÚt^×éđžůóË*ź†.Ąňťtż:ü°iÓ&ĺĎ_v,………ňË/żřŽeٲĺ&ŘjŐŞĽźňʋŚŃ|ŤV-*ěˇK—.fŽŐeţ9ß,ëPĹM›v÷ÜŇţ]ü‰iŽË-7Ę[o˝î7lňg€†ŠĘ-1ç´ÓÎ4Côô ‚vSö‹.şŔ„SęźóΕŠS§›ěZĽN ,äädsŸMŻZ¨W2ÔaˆZľĽýľ´ňéíˇß‘… Ę~űígB§PeffJjjŞ9Ś›nşUî˝÷šřâ ĺÁ‘'žxÚ:Śi˛nÝ+”Ú,:t0˝°rssMĐŚCďż˙AIHHďžűŽÂ~u(˘^RŻüxőŐיPlńâ%Ś×˜^]Qék{ç÷­ýŻ3•Zúť˘mđŕÁ •[b҆ Ź@'I† $=ö° ˇlÝşí'/žřœę 4UQŤV­2Űé:íoeÓ KƒĽ˛ĺ˛+"ępԌtłl÷ĺ •îëć›o4[:,pٲer ăĺîťď”Ν;ËŹYs¤°°@Ž;îXyá…gLÖ˛eK+Ôú§šzăĉ“Ěcnźń† űՊ°‡ţ—vŘhs[˛ëŻżNÚśmWáš_zé9kßÇXďÍzůěłĎM¨wŢyçř*¸ !Š a}œßm{9ŢonOŽň)Ą|J˛ŚDkĘv:]3 J||œď˘^JŰÄx˝ťű'%%ęľvY“ËšôŞYîňÉS>yýŚRżš˝˙e X6–€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸€˜E¸ Ś”–– ęO\\œ@,!Üő-.€úĄÁ–˙šA€X@¸ jůŸXŮË^Ż7čý¨=˙+>>ޡÎ>ß"ä͡D%űDJçnˇ[<™ôś=Üáń­tŮápřć:%$$řB..ъp @T ľœN§ůö0%%Ů:šJ´–ă8ą¨'zćőęy˜KŠ‹KĚšXRR’ šlœ‹ˆ6„[˘†lieVII‰9qĘĘ̌p2€úSVľĽS˛$''›/ Ĺĺr™ŰZÍE€h/az‚dOe'PÖ7„‰’•Őˆ` ‚ô\LĎÉôÜLĎŃô\Í˙Ü ˘ż5ˆ(˙Fń:JFFş¤¤¤˘CZZši‘Ÿ_ŕ[։*.рp @Ä[EEE’ššą`ŤŽž}ä4DzŽćńě>gS\˘ĂD„°ĽËÚÇAĽ§§ÉŢTeő”ꀆĘ>WÓsˇ˛ćó^s›ó‘D¸ âěňeĘŢNřäżm°)œÇ4zÎŚçnzрa‰"ĆŽÚŇƤZҞ˜˜(őŠŚ€Š6T°ÇTU–ooKŮ>ˆezÎŚçnz§WOÔs:˝ ‘B¸ ˘ôdHOŒŇÓÓĽžTZUu_¸A—`ĺ˙Ř`A!ˆuzîŚWOÔ K.ˆ$Â-á?\OĂ-˝źt}ůt9çœ $ö~V­Z-I„[bR¨ÁVAAü´ćOy3é'ٔž]ë śĺYŰĆ{ĽŽĹ'¸%1+ˇŇúy%rŰo;dœćŘę+ŕ8p€™Ďž=§Âú?ţ˜UanÓŞśŐŤ×řą‚p @Ě 5ŘŇŢZŸ­ž+˙MŸ%ž$WĽýäŠ8KÝR_Ҋ$>ÉYi}Ą×+˙é’ŰhŽą>Ž>}zKjjŞĚš5ťÂz ľôž­[ˇÉşuë}ë5Óç8đ €XB¸ ŚUlmßž]ţˇńOů4éOŮZŕ–‚’ŠŐYVž$; =R߂UoyŠ“Ľ$§‘ź:+IŢřu‡9ÖPŽphăúţýűU¨ÜŇŤCŽ\šJƏ?ŢôňňŻŢš={Ž89ŕ€ţžmďšç>3ć(9üđŁĺŚ›n•őë7Tz­řşúęëdřđQÖ~˙"˙ýďÇ{ဘRݕíůŽ;ä˝MódbŇB]#zלě°&oůCvH˝ G ŸčGjQůAƉ3/CœšYfY$Nţł0I^ůe—9暎pĂ.b¸ví:ž) łtC† –Ž;Tˇ´ÂK+şŇŇŇL?°Ë/˙›L›6]Î>űŻrá…çËâĹKäâ‹/“Ü܊aÝ?˙yż4mÚTŽšć*ißžüë_Ë˙ţ÷‰ŔŢB¸ fTîř‡BZIôůĆ2-iIĽíňJź˛!Ç-ůĹ^kšţŤśl ™â.N–âíMÄS”Véţϗ$ɇłvšcpů 'ŕ˛űg͚5Ç7oѢš´mŰF:č@_¸U\\,‹-ö IüúëoeٲĺňřăČyç#gœqš<ó̓˛mŰöJÁ•>Ç]wÝ!§vŠ<őÔ˙Éţű÷“W^yM`o!Ü“C ĘÔMËĺë¤ERŠs|9ˇTślK’˘-ÍŝŸ.ĽŢ8Š7־݅Šâܑ-^g˛ő\Ž*7}çĎ$™´pťy Á^[môîÝËTbŮC5Ě0 ,ŔŇPjƍ˛eË™7ďOńx<ž0ě×_gš*Ź=ş‹Óé4SŤV-M0Ř ~Ô¨C|Ëńńń2räÁÖ>ˇš}Ŕސ Ş‚hĎ5œY°~­|P:× śŞnčŇP˝ Î]Ů"9YâH-–„Ô"‰O.‘¸=ިa™ˇ$Y<Ĺ)ڎVŮđC1ű×uU>Îz)/ţ‘ m–=;˜ţWÚK_›˙Ü~˝öru4l:đŔţ2gÎ\seĆ%K–ĘÉ'Ÿdî0ŕ@3×jŽľk×Jbb˘ŠşRÚä^ݜ¨}´5kÖŹÂí–-[V¸ÝŞU+3×á‹mÚ´¨o„[˘^(•K›6o–ˇsŝěŞv;ŻjiŐîÇ‰§0ŐL*>Ń%qÖ¤óřˇÄ%xŹŔK'ëâJľ…—őœŠĘ*őĆKŠÇaMÖ>] RęJ4ó`Ě~ł}UŠ\ńňÔLˇ<Üxł ľ‘ę„pi5ֳϞ`Şśź^ŻŻrKűduęÔŃTm­YłFúöí#))eá[vvś™żţú˕ö§•`ţ6mÚ$űí×Őw{Æ˛ŚóYYY{ĂĔ`U[yyy21w…lJŢYăăíŤ*^+ ňډ+'KJś7•âÍ-¤hck)\ßF ׾ľ–[IńƖf}ÉÖfâÜŃŘÚ6Ó졪`ËćH)–šŹÚ•$Ÿ.*6ŻŠ.†'j¸ĺvťĺŤŻž1Ă u¸Ą˙} ,ŹĐoK <¨ěxé×ŻŻ™´ŮüŇĽËĚ:?ţ8ŐˇŹáٔ)ÓĚĆÖ­[ ě „[˘ZuŽ=qĹćM2Ątą„ÂS”*‘âH. iťÄˊŰMXTÓ믉öÍĘĚ̐‰żóUmŮ4ܚ;wžěŘąÓ×oK{ěŃŇ˝{7ůŰߎ•—_~Ő4‘żöÚ䁒ՍWWŘÇüů äž{î“>řHŽžú:ůóĎůrŃE€}ƒţZbˇ/Ńy-[ďÂ-1#XSNNŽ|Q˛Dź‰5_ýP‡jeV¤˜aŽŽšÓévČ{sćꉶÚVo•őÝ:Ŕ,†[vß­¤¤$SeÓţ[/źđŒvŘĄňŃG˙•GyÜ\)ńЧ—QŁFVŘÇ=÷Üizt=ůä3˛fÍZšĺ–ĺ„Ć €}ƒţŽŇźy3éۡˇ™—F ݊ a}œßm{9ŢonOŽň)Ą|J˛&ý-2ŰétÍđŁW:š\.ÉĎϗvíÚÝŽŞFňvŐÖźU+äA÷ÖOŸšÁť ŇÄšłąě‰˘ {6ÜΙ›)žâšŤÇâăźňäŃ"űď×Î×\Ţîąĺßk+”ž[őaÝşő’‘‘ažÓó•Ŕö ’’‡Z3ýć^$;­É]>yĘ'ŻßTę7ˇô_–€eƒĘ-QŤş+$*íK5ĄhYHÁ–ň”$K¤9’\!mç-—˙-p™×h öDâ[ˆ&„[bŽčääĺËěřM!?ÎëL’HÓŤ&†júúÉÉÍ7˄XဘáđĘ/ůĹb%TŠ7^JÝ iŚçV\h•fÚ{kę§y­6B.¨ˆp @TŞič]QQ‘üV˛JBÉFňâjn*o›˛Âe^k †&@Â-1ĹrŠŠŠe]r~菋‚Ş-[\‚;ämďJ–‚ÂbłLˆ•nˆ9%%%˛¸h—xĂč_卢p+Ţzĺ–Ç됚›]R\\,€ĘˇDľ`Wt:˛°`˝„ŁÔ=—ŚŽ‹­ç–íĎőâríň¨ŕ€ÝˇÄÇ#[=9a=ŚÔMáVč•[jsnŠýš€p @Ş*´ą×ë°ÄuqN kŸŢčůqçŻrkuA˘ŠVS5˝7°Ż‰ž&4"Ç+IĄ÷Ű2źq5â ˘v8ĹíŻÚKĺ”Č›ÓwĘ˙ćz$żD@-%9Dúˇ9šŸGş4•Z‹‹‹“ÔÔÉĘʒ¤¤$Šëw–HvZ‚¤'W_ľ^Pâ‘]…niŰ8Y Önˆ)ž\  'Ž*-˘Ę­0Ă-OiŮÉŠžv=)…['<żP €:ŕ´žcššNdÎF‡Ü{dí.ýˇź°°Č\őšUŤ–upyźĽ2gMž$8âdh×,i”ü×˝Ü"ˇĚXž#nOŠ´ĘJG|} ľŔ°Dą)ĚĄ}UŁöÂ;˜ŇŇđO8ľb‹` €şĽ!×ćíyO šrrÂë Šöď).+´úeEŽ ąé:˝OˇŃm ś4„[bR¸ŐO"Ń4,QÂţąëPDP÷ćl”:ĄŐ[őĄ]ădéo…VNˇˇRŔe[zŸnӎ!‰†%ˆI…kۆ•ůmli}MşçWіRvŽÝňśe#Ű @(4´ŇӇŮkňL˜5¤K–Yo[XÁ˝ś4$TnˆQ1\BfŐY\-~RŸ´˙ž™•icůş ĺ듆W”WpÍXžËL[*Â-1).Ü*ʏhjşf¸ĺ˙ŘĎŃX28o NéUőЉ{J/ŁWLŹovŔĽýľt"ŘĐP1,@LJ´Â*gŰÇĹ{ĽÔ-y~xÍđ“Źcő*‰śFéÉňÉĺÍLcyíżEsyjOC-­ŘŇ`ŤśWJTúďšVli°U×WJʊ†YÉ eç@Í2"Â-1Çሗt§SœÉĄŸ ™pK˘CŠ7źpŤiB‰$&†˙ăZŽŤŽleMöa„Z:†%ˆ)úgrr˛4w†WÉç/PŞO^OxÇŇš‰Ç ˇĂŽŢ€}ဘăp8¤MFxMXă{ŢŁŽ¸‹Ă;–V“ĚkTF¸ ęTUĄdŻ×IĆŁ)Ü*őşCŢ6>A¤_ËDS­Śjzo`_C¸ Ş m4Üę٤…dćXĹ'†(Ő7Ż7ôăNŽwKżÎM$!ĄrĎ-- Ü#ƒœÖ­[I‹‚ĐŤ¸—D WQčÇÝłI4oŢŹÂş†j˝ňĘkňíˇBĹŐĜ˛Ëh§JŻ„Y)qĘuăâK­€Ë#Ľî÷ފs‹×ZCy’8˘C‚y­ľ ´6mÚ,?ţ8EślŮ*))ÉŇťw/6l¨ÄÇWü^cůňňůç_Vz|łfM右Ώ°îŮgŸ—Ë-II‰réĽűz­YłVţ÷żOĚň~űu•ącőmŤôř333dŕŔ˛˙ţý‚ďΝ;%?ż@Úľk[éž Ę̙żINNŽde5’ÁƒIŻ^=+m§ŻwÖŹ9•Öx`5j¤ďöďż˙!S§N7Ë<Ü—íĂ˙#6l4ËgŸ}ڏÝnyď˝}÷ëű§ďîŻmŰ6 ˛¨ÜSěGŸƒš´“&‰a MLrJ¤š‹CŻ ËHpĘ!}›×Řo+˜’’ůřăOdűöíŇŻ_iÔ¨‘ý.żţ:łŇśőďßĎ7őčŃÝŹ×áŸUq:]˛jŐjßí%K–V ÍTjjŠdZ}Ľ¸¸Xž˙~˛lŢź9č>׎]gćíۡŤ´~„IRZZjŽOĂ&­îZˇn}Ľ}´mŰśÂkąƒ2˝ÚdU-Zě[ÎĎĎ7ÁV°×ҢEsóZşwďfĂĎ?˙B<žčéĺ썡D%˙ §ŞP§k—NŇľ¨DˇPDE¸UÚ1ÄY?6ϗŽ:T\_ţ^Ôôţl޼ńS´jĚ˙ľčąéëîۡOĐçÔcŢśmťěŘąĂÜ֐Î^H‡Âęk9úč#ĽC‡öVXW"EEE ˛ˇÄŒŔ@'33Sˆo"MSCćçHŽ|¸ĺ*í’ÜrY’žž^Ť!‰ž\xáůž€*''Ç=Mš4ŠöqZń5{öÉÎÎňUpÓž}{Yąb…¸\.˜iĐlˆžV[é6ZĽCu8cUCůÖ­[göhȐÁćľ4oŢÜÜśƒ¨š^‹—VaéđĹŔŔĚfWvŮA†[éVȖUi[ݎěľlŰśÍLZɕ‘‘!"‹ž[bކ=šhż§ƒző’Ů‹§ËI“ŇzoĹ9<—č–RWd~ô•Š[Ü%5c‹sˆ hşKč;8hĽV¸ LO-"8xđŔjˇ5kśr8zô *ŸSßűN:ĘʕŤL`eOěŘąŁüňKĹa;vě”gŸ}Á,ëçu襣L(H‡OU’hýú 2mÚtSEŐ­Ű~ŐnűË/żš×PÝkÖŔ,--ŐôÓ Pű”i•—ćÍűÓLJ0­ yTnˆZÁ†ŢŽkѢ…ěďʖśĄ]0!ĽX"ĹYÚsg$”ČŠIăƍCzŞ“››k¤ĘřńÇ –|ÇçtšpK‡öěŮŁĘí4ÜŇáúÜëׯ7Ă[ľjiŸ@eĘŠ§ž,'t‚tíÚE&Mú^ţüs~Ľíěá’ÁšÉŰVŻ^cúˆiUŐ¸qcƒöŲiŖsÔ׏ ËŸž–íŰwȲeËÍíŞB3ÝN_‹ž)))ňß˙ţĎTpˆ,Â-1Éu4ŕ~ЁŇ}{‘d¤Ôü8Gjő=’źîqĽˆ+/CJveIɎ&Rź­™mm.E[ZČÎľ›dçşÍ˛kĂÉÝ´Mňˇí”šRRP$WőÍ❅5÷gŠO(•#ÚĺČŕƒúíqՖßÓ`KűBi¸ÔŞUŤjˇ×áˆ%%N4h`ľÁ‘Ňá’:źpŊ•˛kWŽi˛Œ6r×ţU:LrčĐÁf"ůÓpŤI“ĆfżÁčc>ýôsÉÎΖ“O>É\P :3füRcՖ­{÷î&°ÓׯW•ŹŞz,==Íź–Ν;Iż~}ĹíöThŞ 2– fŘĂíš˝N{/hÚUvxWË\Io5Ăă<Śąź×Y~%ŔŇ8ń”$—MÎDëv™żőÜĽžRńxźV Uąb,Î …““$1-ES“}Á”×ëwqőCu8bç´\9md'Saľ'U[ZąőŃG˙ľ‚­bB-\¸ČL6iSt˝Bŕ7ßL#<\z÷îezIiՖ6n×ۡО\ß}÷ƒYÖj'ű3ń§C"§L™jîÓĘ+Ő´iĹ^YzŸöŰŞŞZL‡ ~ůĺ×fťŚM›šŕJéBB¨Ő` ,”łĎ>ÓTťmÜ¸É —ÔăÓŰ5Ń÷Gƒ+mtß§Oď*ƒ=­ÓעĄÖŇĽKË_KSY„[˘šUÝ}p€,ýb˝ävpɊœ„j/ ˜^(%EŠâ*LOqŠ ¸ęJŠ×+N+PŇ).>N’RS$93Ýş]Pý­CČtÉĹ4@÷­ŽeՖVSi°Ľ´O•NJ+“4ÜŇauÚÜ]çjîÜyfű1c­ąjËŚĂô~řáGiٲ… ă4P ¤ć˙řcśY֞_Zń4lŘĐ ŰlÝşŐTŒk&Ż6oŢěűœíĆďöók¸Ľ=łôu%$”ý“f÷Ú2d„BˇŐĘłYłćTYVvœŰĚTv1ƒ SáÖšs'Yq!Źóťm/ÇűÍíÉQ>%”OZ‘hMŮN§k†€Çc&űJzŐőZ ˇěŰţstŢűS'ɟŇe}nÍĐ=qĺdJÁúśf9\:,1lqĽâqJBbŞ~ŽÜrnmrń)ŁÍř4@ ŹÖ §×V,ůý÷?dęÔérŮeűÂ6ý´żĽžˇhe¸^8F'd}ŠŽßnď˛&í㢗w—OžňÉë7•úÍí_ý—%`Ů r @ÔŤŽzËžxl˙ÁR8űWqśÍ­…ˇq¤‰+7ÓTj%¤Š+/SöťX\ENń”¸$1-Őúf šÂý+Ř:žý9ýčAž`Ë֐BŹŞ p™ 6h( &T×ĘŢŠS'9ś{?韥@škĎq“ńljsgś¸rů† &¤IœĂ#ő.Î+îâ˛á^oŠ”äŠÇS`ŞšĘjb‹eL‹-rţ1ý¤uëÖU6‘ß×/ဘTݐ=mˆ~l‡nŇu]ž´HqíĘOQŔp7kóÄĚ<Šong‘™*.w”:sä˜6[äŇăzJ—.Ť íÁ1,@̨jx˘˙U•.xŕ’””$_Î˙S­D6lk"Ĺ%IçHrŠ#Ľ¸ŹŠ|=(-u‰ťÄYi}\źuŹĹ9rjo§œuěéÚľ‹řż–`óŔűeˇÄ˙€+زŔŐ§OoIOO—ŻŚĎGˇlMh,ť ŇÄ˙šIyRěJŹUsůęÔ+ŽŔ+$Ćéq–Hł¸\9{P’œpÔiÓŚďřkŞÔ"؀ʡĴšŽN:ĘYäű)Óäç⭒œ™); 3Ĺé)ŻâŠ/•¤Ź)ŮŮŘ׏kĎJÄU\ ^Ďî*łx‡GS\"p @Dř[şŹ}tžœLĹ@´Ňs5˙s7.рp @ÄŮ äÓÓÓŃMĎŮôÜMĎá nˆťjK“ęwôę;ˆnzÎŚçnvsyťz "…p @DéɐžĽŚŚ bƒžťé9Á€h@¸ "ü/!­'F‰‰ €Ř çnvĺ–=@¤nˆű$ȾҎ–ś 6蹛}G¸ Ň(•Qe'C”łÄ=‡#Ô ˇDŒ}2Ä9@ěąĎá¸Dábဈâ›>€ŘĹš€h@¸€˜E¸€˜E¸€˜E¸`Ÿjˆ¸¸¸˝˛@ínŘgÔŚái]5IőßAÔÂ- Z4^Á‡  ęá€)”P+”mębXbuű°OČľ/Đ@hPdO{˛MUŰ›ÂÝǞlŽn¸Y† é›F:\ţú×sĺă?•hńĘ+Ż™cťîşĽ.Mšô˝Ůďşuë@ĂFĺ€˜N¸äĎív›)ŘăĚäŻŞŞŞŞöHoď7”!‰űÝ“ŞŽĚĚ šŕ‚óĚrqqąüôÓ yřáÇĚňgœň~N;íŻŇ˝{7š÷ŢťĽ.}˙ýdiŢź™ĚœůťäääHVV–@8¨ÜsB­p ś]QQ‘¸\.‰ŻüăO×ĺĺĺIAAAĐýTWľĽŃÇVľ_§ÓižťŚă őu„*==]N?ýT3wŢ9ň ϘęÝwߗH[šr•™Žşę ńz˝2yň€pQš fěI-{}JJŠ,Y˛DÚľk'7–W^yĹ:ľjŐJN9ĺ¸h ĽŰ†BŤ rrrĽsçNňŃGÉŚM›ĚúÔÔTšč˘‹dǎ˛~ý:+Tę´ÇV¨ ćë˘?—žŽƒ:PŢ˙C),,”´´4,˝ńĆ[ňŮg_Hnnžt붟\xáy2hĐ@Ůž}ťŒ{˘yěš5kÍpżťîşĂşo€YÝuWËŻżÎ´Śßäţ)<ÂÚGŽ<ýôs2mÚt+ÔsIßž˝M€Ľűő7qâ$ó=Rzôčnö=~üńśŃŠąý÷ďg*şt8ĺ 'Œ“żýíŠ ĎĄaeż~}ĺŠ+.ŤôúY<üđŁ2oŢ|iҤą\vŮ%rÄc@ĂAĺ€˜P›~UÁÖërçΝĺçŸgHAAĄdddČľ×^kŚÓO?]ž}öYéĐĄ˝ u´ÚŞŞŞ){˝nŁŰęc^xáł{niE×/żü"]ştŠtĄs°çŢř$%%ůÂťGý?+ä{]=t´ Ž4ťîş›dîÜy’™™i…V÷šít˝.xŕž}˝úęëŚ:솎•Ž]ťš éŞŤŽ•~˜l‚Ş /ůä3šâŠK右Î4ŰwÜ1ÖąŸ-Ż˝öoyâ‰ÇŹĐk” ďt8Ł.+ ô”žś{îšÓ÷|_|ń•,]şL{ě!>|˜YwĚ1GÉŠ§žišÇŰŰ.[ś\VŻ^ăëűuŘa‡ZAŮżMŕuňÉ'Ux ž=óĚž0Î~ŽÇX† jÖ{ěŃróͷɊ+¤e˞ǞrĘ_ĚpL5dČ`ků"SíŐŠSGĐ0nˆjUUMŮtH`°í´Č?üŃíüˇŃ`§K—Žňă?ʃ>(óçĎ—ŻžúĘT÷h(őĂ?HďŢ}Źđg˝ž,xŇ*ŁśmŰƟţ)§všŻ™źcşO jô9ôšěăTş/ jěăą+ŔüŮĎçż]°c¨)ŕŇc:é¤S+Ź8p€Š´R3gţfösÔQGT8 ¨Ç_˙*.{ééiž`KéűwČ!ˌżřÖ}óÍ3ďŮł‡lÝşŐ4ž×JˇO?ýźR¸ŐŤWĎ CDí簃-•-/˝ô\ĽăÓa’6 ç4ŘÔ!¤Â-1Ĺ?Úšs§6x…B 0ňóóMX˘Á’n§á‡˙5jٲĽ4j”eBˇß~[† "K—.5˝¨Ć'?˙üł´nÝÚÜ,XjÓŚ fƎëkBß­[7y˙ý÷ÍК޽{šcđg_9Q+Ÿ4ôŃę/íůĽŰi°ćżÝN4;\ ľZ+ĐCÝo毿ţŚ,Z´X.¸ŕ\ßU ő˝QăĆý%čcőľkPX•Ŕúťví2ŐnZ´h^!Tzç÷Ě\+ŠüiE—ž§Í›7ű9‚ILLô-ë{§6ô=ĐpnˆZŐ /ÔĐEĂ*mˆŽ}˛ěű´żŇąÇkšŸëĐł˛í<ŚňçšçžŤöůÌcÂ-ľyófłŸË.ťŹÚÇhŸ-ÝÖožůfľšâŠ+Ź Ëk0 _tč`ďŢ˝LĺزeËĚ6Ä\y啦˝ž†äädß{،žşŔŤUŤ–2rä!fů€úˉ'žjúk=űě“f†~ęÁM›VzźláĐĐlÁ‚…•ÖoÝşÍ 3Ͳ)TڔţÔSOömŁë_zéUůîťĚŐĂ}ű&Â-1!°ť]M5kÖŹ ˝Žîşë.+4l…^eSşĂ/ż˙ţťiňŽE‹…ý ťj2tčPSVRRb­ÔÔS­4sćLšçž{|Ű >\Zśl嫞ňďŃU› ŽFÉ_ţr˘źőÖ;Śyť^5Q‡(ŞuëÖ˨Q#}ŰNž<Ĺ ‘ůŞŚtJœöŕš8ń;ÓŰK{\Мœ™:ušďöwß}oć˙ű-Öű°ťK‡~ýőˇćńՅ[U=ǕW^#^xžŻ/€}WK•jj݁OjjšÂLŽp˙Ą‡*Űśmó Ô)==ŁŇv‘¤ýźŇŇŇÍą)=V­Ţ=zt…íô˜5¤ł{a…ŰX?˜3Ď<Í<ŸVoŠvíÚʉ'Ž—çž{Q{ě ůěł/äᇓŰożÓ4ܡévˆý÷ż›Ş¸Ş}ô‘˛ß~]ĺŽ;î2 ä?üđ?růĺ3Ős_|ĄŮF+łzôč^!زi0ĽUYvüPžăƒ>2ĎĄtÚW Ŕž…p @Ô 6<ą¨¨X7ÎŽZéĐC훥=ł´"J+JJœ’Uá–6ą×c×cÓcÔc-,,2]ţÓu;6¨ŻľŚ+@†J÷wŇI'ČŹYłMcvuă×ÉĽ—^$?˙%”OځX;ůf;Ž~´yşNÚwJ›żk8á/p˘˙\+ž´9šViŸ(’Ś´ňéťďž“ß˙ĂTévyyyŇž}{iҤ‰yŰqÇg:—V:ŽŐŤW[ĄÎߤ6žxâ éŇĽKĽő/żü˛|ţůçžŰŚQüÚľëL*r¸xń0ŕ +Ü9̄ZJ{Kiăy ƒtˆ ÝwË’č?4ą6ĂöĖ-[Íy~ń¤mŃ %%%ęeÎwY“ËštXŠť|ň”O^żŠÔon˙Rčż,Ë=ˇD`Á–?˙~[v°Ľ4ÜŇ!‰•Um•˜“Źß~ű­B°Ľ:uę$‡~¸ •´Ÿ”>`şžśFŽ)͛ˇ°ŠmÖń•ő¨ŇmҤŠUHz,ÚL+ĄŠ‹‹MÓv=f=v} v¸ĽŻM_c‹-+4•÷oö´Ä:†%ˆ ţŐ[ôčU‡j0¤•Zhi€TPP ™™|aQ ˘˘"ٸqŁŮN+¤6mÚ${J÷§W8Ô}ęţtˆd0z왙™f;=V ŘňňňeÔ¨Q•śKOO3Ż9°‚ @ĺ€c÷ŰŇŞ§`ýśü{V٪꡼•NژźYłf&„ĘÍ͡Ű%{BKóŰ´imÂ7­ÄŞŞšJéÖ[o5Őbţ´g”ž­č˛ˇťîşëL`FuŃkذ‘ŇŠSGšâŠKĺCŔŢC¸ Śh.íë ŚMŰ}5?­ljÓ&x3q˙Ą‹tč˘I:i°=ĽCu_Z‰ĽűŽŞČjâĉ•‚-›}uDeżF}ÍúÚ‡&€čąjŐjšůćŰLÍkŽšJşuŰOöś7§o–Á]2Ľgë´jˇ[´ąP~]‘'çŒh)ëˇÄ {Hb||œüńÇB+ •vîÜ)áHOO7`Z ĽMݛ6Mľk×ȞĐ&÷nˇŰěłUŤÖ’™™tťP7°ď–'Ő[D7˝¸Íyç]$Gy¸šúpU_hŐľ"§WŽ}oš¤&9äŤëúH˙öÁĎCćŹÍ—c˙ožľ˝GNÔÜڞn5bဘ˘†RUőŃ ŐÜšsĺů矯´^{fŐÖ{ď˝'mŰś­´~öěٲ'thâůçŸoz„€Ř _d}óÍ™2ešœqĆŠrÎ9g™/Šę“†T/×].|m‰Œ}bž|qmĺ€Kƒ-˝/żŘ#Ż^Н` @ƒÂú8żŰörźßܞĺSBů¤?šuěPśÓéš!ŕG‡ę¤Cí´Ąz‹Í}÷ťZ˘Îő$qăĆMŇšs'?~ź|ů嗲/;vŹ|ňÉ'˛rĺ*iÝş•ňhWoůWqQŃ@ähĎ­ęp@답§eořĎoŰä‚×KVj‚|~M9 CYŔe[9Enyí‚rňŔf˛'ślŮjújű˝ N())q¨5ŰeMÚŕX{°¸Ë'Oůäő›Jýćö/†ţ˰lÓˆ:ÜĎîˇ5uęTŮWŘŻU_ťž öěÍ/Ą4´zéÜî&Ä:ţÉůňűŞ<3ŮÁ֋çvŰă` ˘ ĂÄ mĐn÷ŰĘÍ͕}…ÝwŤeËÝ}ˇ@lČČH7CO;íٛNRVÉKdÜS Ěr^qY°uƐ ဘĄCí&đŸ}öYŰżűîťňţűďK4;ýôÓĺĚ3ĎŹqťV­ZIZZ}ˇˆÚF`o7”d\—žąÔĚ ś4T„[˘š–đkż-ë°źíۡKaa‘´oߥҜţ˝ş<đyöŮg%Úé?ţx™5kŽŘCǃ [Řž}‡yÝŮŮYAűm€č1hĐšúęŤdżýşJ¤iŔŐąi˛Yś_#€†ˆp @ĚČĚ̔M›6›Ćňʿٟ˝ŹCőzZĺ5}út‰vzŒzŹ………˘Y•=äPƒ+˙K__qqąő´“ÚŇ}hĎ.mäoż‡‘ ßdkĂل„:@ƒŇšs'šâŠKĺŕƒGH4!ÔĐĐnˆ:v˜x[çÝşígÖů[ö\'˝ň˘Óé’ß˙Ý,G;=F=ÖvíÚęUḊƒ­ę涚B"íŐ-Íč5XÓIC= ¸č!h~ţyŠ"ƒŤ%ˆ)Յ=:iˆŁŃäɓ%VčąjłY=öP‚­pŘ_Ńz•E=.=>˙0ÂA倨TUő–˙rŕ\š\nÉÎÎ–ŁŽ:JúôéSís<ôĐC•†.žxâ‰rţůçKmźţúëňńÇWX7bÄšĺ–[Ş}\ťvíŹcn,;wîň­Ť.Ř §jK‡iFrb(ôřô8SRRÂE¸ fÔpi/)­€Z¸pĄu;Ţ4÷ČtYŤşşwď&Ď=÷\Ľ`뀐ˇŢzKÖ­[oz`…#55Í<öŕƒ–ŮłgűÖësŹ]ťVޏâ Y˛dІ,¨ŇcnÖŹŠ zt¨ž˙}Ő[ŐŃJ°hślzœzź Q.Â-Q+°z+p]`ŔĽĄ^QQC˙&ó:×đd׎]Ň­[7ůňË/ĺškŽŠ°ßf͚™ŞŤ7ÉňĺËĽyóć!Iş˙•+WˆĂoö1xđ`ŮşuŤďţŤŻžÚTgzčaňóĎ?›Ę˛Ŕá‡z|zěá[UŁÝ<ž*k׎“ÇŇw;55E:uę$G}¤tčĐ^"AWßšĚဨnŔ•šš*=zt7÷Ů—N7n”>}zˢE‹ä´ÓNŤüh ôÁ˜ŞŽ™33W8 ľĎŐî­ťüôÓĎ2`Ŕů裏äˆ#Ž0 ӕV”qĆňĂ?ČđáĂdÆ ŇŞU+_ŔJ­p‚-N-˝\y^^ž,^źX–,Y"W]u…tu”H°.ဨnŔĺ?W[śl‘–-[šjŞącÇJAAA…}=ńÄ2lŘ0™8q’Œ1\âăă+=W0ţĎĄóAƒĘôé?Éᇏ‘'Ÿ|Ň E´é0Çă?^f̘aŽEÉ¸üŸŁ.‚-ĽZ(>x¸üĺ/'šĺ+VĘ3Ďúčż5CŹô=ˇÄ”pŽźźˇŰ#šš9f(˘lŮU[ţçpI„["BżáÓ ËžűŸٕ\.—KvěŘa­ôôtÓ¸4>žoę“×[j‡9­/ L¸ĽýľRS“}Ą–°eWmQ˝ ’ˇDL°€Ë˜˘=TQż)ĚÍÍłQjNśt[{Röáń§vŸ‡éş¸ňP+ŠB ĺßg‹` @´ ÜQţ—Í>y˛O ź^Ż9šňłtĄ@ݰż\ôŹěó1{ Öc‹` @4 ÜqöI‘Čĺ_Áf١m„\ľăN ˇ-ŞľD#Â-Q#XWŕ ”ŔE¨P7‚X=Qƒ-@4 ÜU‚Uq6œ×Ş-NŞę^ŕ ľÄÂ-QɮⲗmAęV°‹` @4#Üľ‡"úŻ@ýăÜ @, Üő+ˇP´ÄÂ-1…“-€?Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-Ä,Â-ÄŹxěÓćĎ_ ˙ůĎĹét ÄÂ-1Aƒ—ĄCŽ05FÎ?˙b™4é{‰ťvíň^^žÔƳϞ`˙ÜUéžc=ŢÜ÷óĎ3$TwÜq§<úč˙Éwßý ‘öý÷“ÍńŸ}öůžugœqśY÷ăSdOüß˙=eöŁŻ@ĂA¸ ćtëÖMz÷î-))ɲpáBÎLœřD#;ČZˇnDŤK.šXN8aź >TęR,źvąž[bÎ}÷Ý#;vŻ×+ˇÝv‡LžůÔôŤZştŠŮ&!!ŃŹťćšLČRTTdmĽ|ůĺ×Ҳe+ú(ë˝.”_|Y^zé U(ŸńóĎż$oźń–9ţ:XÁÜ™4i’hxˇÄœżýíSIĽ;_ý­Ywú駚ůkŻ˝nšĎŸzę)VsˇĐÜ+cĆ*;vě”?ü Ž´âH]sÍUňÔSOČűďż-˝ző˛—tŮźyłľĎoLP=Źűˇ™[­çźÂüőéÓŰšôčŃ݄m………Žąc•˙ýďcůńÇĺúëŻń5Ç?öŘcĚĐ˺п˙ţfž ]ťv– 6XÇYTënj3FŚNn…IÉäɓÍk0ŕ :´ú0NŤŹ´bîÁ–7YďqYHŚaU¨júŒˇnÝ*eŸÁa‡j晙™2xđ`SU a!Üs>řŕ]iÓŚľœzę& Ńá€6 bÔĹ_(x@…ÇeggK(´g–Ұć ϯp_`őO]TőîÝK:wî,+WŽ4çL)ë}ĽĄW0ZaŚśmŰ^a}II‰äĺĺ›e süĹÇÇů–ăââ$Ő=樣ސÚˤIß[aŕů嗙&ěúôÓ/ä­ˇ^÷}ţ\.—ő~^j^gßž}ŹĎç@sŐËwß}OÂÎgl–.†%ˆI‰‰‰žŕI›şk#sŐŤWO3נ砃4“Vjé0şÄÄiٲ…4mÚÄl3iRY…”V yć9rŢyÉşuë¤gĎîf˝†1Ú+J÷‘žž^ŠßV(ěPČĺrW¸­t˜Ÿměزʳ÷Ţ{ß ŻÓĐŚ]ťvA÷Š=ŹÔěŮsLŻ0 pô5<ôĐ#ć˜5üŇ Šú¤Ą–ŁüË_NçŸFŢ~űßf˝W›6m2ˁŻ}ٲĺćţV­ZšáŽW^y™ľÜ˘Â~íÇčĐÂŔuOYÓůš>cí–žžfś™0ĄŹ ~^^žüú믠áĄr @ĚŇa{oźńśéőÖ[äœsÎ6ý›Ţ|óm3Ź0--M~üqŞŮž_ż~Ňž}źŠřŃŤ#>őÔłňÓO?[Ö3äŽgĎžŚˇÔ1Ç-ďžűĚ;Ď\QQ‡äMŸţ“ŠŠJMMń × EŰśmM`vŰm˙0=šÎ:ëLkŠŚiýM7Ý*÷Ţ{ {ô9Ÿ{îE+Œ)kz^]#y ž´ÇÔwßýŕ{ŮCűŽşę óőiÌ_Ěż &ČđáĂeůňĺf}űöí­×ÓJ‚˝v­öŇa–:4TŻŹ¨Xß}÷]…ýjř¨txĄ6ý×÷§eËć˛bĹ sőԔä>ăöVčv’š_ËOŸţłiˆîÄ*ˇÄ, J.şčłŹ˝Ÿ´×’Vőh%Ń AdŢźůVx5Ă <úĘË/ż`úc)mn~÷ÝwZĄUW™={ޏ\Nłî‰'5űĚČȐ—^zÎ2Űśm5UJ71MŇĎ<ó Çß˙~łr¨ÜŹYłĚţožůFâ,\¸H–-[fśkҤ‰ 6Ä,kXŁáUu4ôŃféú´,))Ń Ł|üńG‚6ŽŻkˇÜrŁ\rÉEŚŞęłĎ>7!–ž_Ď>ű¤oŘ`ŕkoٲĽjýÓ\YrâÄIćľßxă öŤC4O?ý4S}ŚĂľ"ď˛Ë.•nÝş™Š°?ţ˜Ňg|éĽ[!ŘY’•ŐHV­Zez„}ôѠበa}œßm{9ŢonOŽň)Ą|J˛ŚDkĘv:]3P­{îš×4¤7îxs%AˆuÖńC­Ů.krY“7q—OžňÉë7•úÍíşţ˰l0,"LŻ”¨WHÔŤj/ąsÎůŤBC¸öóĎ3dţüfˆĄö ŤŞ‘< 2†% ^0,¨ábábábábábábဘRZZ*¨?qqqą„p @Ô ´¸ę‡[ţçZ]bဨĺbe/{˝Ţ ÷ öüCŹřřxß:ű|‹ @4#Ü•ě)ťÝnńxˇŻ+ĄVgŮÇG5ˆVzîćG¸ ’ˇDTYČĺ­USÝIT4ž`UwLÁ^?!ˆVz~˘çp„Z˘á€ˆąO†jsNTՉT,^áYzˆ6öŠ€H#Üs‚@Ž‹ć“Ź`Çf‡WU…\\ဈދ~Yţëb)äRU…ZÁÂ,.m¨Ú ˇÄ4˙*˝bOII‰x<ž¨šC*˝­—ŃNNN–„„˛̈́YP3Â-1ŁŞŔJçEEEňËşĺňŠwŽlNÝfýtsILq'JŤ˘f2>žż n×ERSSËľV ¸ź "Â-1É?čr:ňÓęĽňJň‰K,ľźńSâ=˛)}łźŕúA<Ť˝rHמ’””dî"Đ€Şnˆ Ő]177W>vÎIóHiŹ…ZůŘő§ěŸÓZš5kĆŐ „[bŽ˙pDĺtşdKjŽÄÇz°UnsĘ.óš”dh@p„[„x‡7ö†"VÁź@HˇD=˙!‰U[žy śüVmůWoQÉeˇÄ< zJ˝U=)ń‰Ň-ľĽ´Iʖ G˛$Ä9ĚúmŽ<ůn×BŠOc˛{IłÄLłě.őHž§D68wĘҢ-Rě­úŠŽUőŤ &Éűď(˖-—řř89č ĺňË/•nÝö“ú˛|ů 9í´żĘC= cĆ*_~ůľ<ňČcňĚ3OJßž}ę ဘU!Ş˘rŤ]JcœŮYË­˛ÚóřúʨĎQZź%X˙e;Ź)5]şĽ´–_sWĘş’Ő?|+´žxâiyűíwĽC‡örüńÇIQQ‘üđĂdůë_ϕ˙űżGdĈá˛7čkˆ§Ú @#ÜĐ –ŘŢ ś†ev‘8ëżőĹťdqáfŮá*4TťŐo¸5iűb߲VŒ5IL“i-ĽMrś k´ŸüœłBÖď”úđÓO?›`kěŘcĺÎ;o7á’úŰߎK.šBnżýNůęŤĎ$--MęŰąÇm&¨k ŻI €}ŠĎ-˙)ŮúoPfg‰+—ššdʎ˛š¸@\žŇJŰî­IŸ[AEIM1Y’*më˙ÚjK‡"6iŇXn˝ő&_°Ľ7n,7Ýt˝´hŃBfϞcÖéĐŁ‡É”)SĺĚ3ϑÁƒGHaaĄx˝^yë­wäÔSϔ#FË 'œ,oźń–YďďĂ˙#ăƝ$Ǐ’kŻ˝Arrr*ÜoďŐŞŐćv¨ű€šPš ć }J+főÝŇZJ˘ő#n}qŽ,Čß"‰ń‰rNëA2şI7Ép$I$ä{œ2yÇRysăLsLM3Ľmr–uŹ­d^ŢŠN¸Ăuűß~űCŽ9ć(IIIŠt˙ŕÁƒŹ@ęÝJëxŕ!+¤+'Ÿ|’$%%É+Żź&/˝ôŞuÔrƧɂ ĺ駟3ű<í´SĚc>řŕ#yä‘Ç­j˜üőŻgČüů äţűŹöřBŮ/„‚p @ƒŘPžMR–hś(ŤšďœśƒelóŢIލmŢÇôŕzeÝ Yl›§Ns˝Ľ.iĺ”Ó锶mŰTXżsçNqšv7˛OMM•ĚĚLßí‹.şŔ[śĄC‡HëÖ­Mż.uâ‰ăeáÂEňăSLĽ•VT p<ńÄcžîž{î“ŐŤ×Ty|5íBE¸ fT7L/°çVF|Š ‘v”›űmRWŹÉöíŰ%77W5j$M›6•ŃM÷“—×ü*Ű­cÓcÔc- ąą}¨\U˝W×]w“üůç|ßíSO=Ynžůßm˝’˘żý÷ďg&} +VŹ”•+WÉƍ}Ă5ŔÚšs—Œ=˛ÂqiĹŘçŸ)UŠiż*Â- C@8” sUD—[CžxIĐPDĽÁ–V8é\Ă-3,R{pyKM¸eŽľŽŻÚ˜m†Ž[ˇžÂú뎝Ú‡†_×_sĽ!‹áŇÜšóä_˙zX–.]f…s™ŇŠS'IOO÷…gyyyf޲e‹ kҤ‰T§Śý@¨ˇ4•OĽĽqA×G‚Vlٕ[śÝMăëç8ľŠjŕŔƒdÚ´éRTTd†Şţý÷7s •Tŕ°EnˇŰ4‡o׎ü÷żHǎĚúŤŻžÎTkŮŻMmÚ´šÂcˇmŰśGű€P1ţ@ƒxľÁm%Efňżú`¤hľVçΝÍÜVŐqÖĺńž~úОcÇNÓ$ŢăńřÖËc=a*ť=tT•/((°Bš<9ě°ŃžJ×ŮÁ˜ęĐĄ˝š"ă÷ßOŽpĽĂŻżţvö Ą˘r @ĂMظ˛|)J3üňă­Ďă>|˜œyćéňîťď˜9seذĄf؟VsmÝşMnťí–j‡feeYĄ\'yď˝ĚđĹ´´4ůđĂ˙TĘtŁ6ĄřáÇL5ֈĂÍŐ—-[žGű€PQš AĐ+"V7E›˝uź×_Ü˙?ĽYłfňÍ7ßʄ ĽcǎňôÓ˙gŽPX“G}ČôĂzęŠgĺŐW_79ŕ€ţśŃŚô7Ýt˝ŹZľZž|ňÉĎϗťîşc÷ Ąˆ a}œßm{9ŢonOŽň)Ą|Ňî͉֔ítşfřŃ*\.— CÚľk[ĺśv“ń`s6nÜ$—ݍţÇ̗ŁO‘hrÜ䏪˝˙ů.CĽuëVŚw–}ª摠ŽÉČȐÄÄDq8f€@II‰C­™6×uY“ÓšÜ哧|ňúMĽ~sűjSţ˰l0,@ÍăĂkÇ QŠp @ƒPZ[aQŹ/D+Â- B¤ŻˆŽX;^ˆVüv aĐ&ěŐMŃ&֎ĄOÝ( 7Ô¸nŁŰ@C@倁Ę-°Ż+rz媡Kj’C&Ţ|€Đ!3čvł×äÉĎśś÷ČiCZZŰs^ śńS @ƒ aQuS´‰ľăŃOCŞ×.ę-ůĹ9ę‘Ů&Ä ¤ëô>ÝFˇ%ŘĐđ“ @ƒ@¸ ręŕňĆ%˝%§ČmBŹYŤw\v°Ľ÷é6ş-4 KĐ0ÄZ D€ꉆVnOŠ\đę9úŃŮňĺőýÍúăŸc‚­W/ěE° A!ÜĐ Đs `ˇ3‡ľ4s ¸ŽylŽYÎ+. śţ:Ź•@CB¸ A(ą+ ĆÚń€Řc\žşĐĚ ś4T„[†%T˘W§f)fyxˇ,€†ˆp @ƒPZcĂ#pźĽĽĽâvťĹăńˆ×ë•H‰‡Ă! Wť 6—×#ůž)öşĚrŠőDâŹ˙ă’Ÿ(Ždł Ą€†Žp @ƒ@Ď­ę9NlE Ötrš\&ŕJJJ ëń;œ’ç)TŚ!ŸÓë6SŽťH2)Ň$)]€†Œp @ĂŔ°Ä ´ZŤ¤¤$˘•ZŐŃŔM-99šĆ*.OŠWś8óLpƒĐhXRâ–I™âˆc(,&Ît4Z UÝmöÖńFs°eÓăÓ㏠ÁVíč{ŚďĐPQš a¸úŕ1ÝZ˜ů×KˇHT*?ŢúďĹCĆK˙6Ýd’_ä=+\ŇĄŻ ŻýëŘ+$#)Ő,ˇËj.‘˘ďaŚ7…&óhpˇ4•¥Ҹŕ룄ď¸ęé8Ăi?dČ ÉÍ͓ŋ˒%Käꍯ’Ν;I$Ř—?˝*buXÁրňpë‹Ó¤ŔY,—;ÉwżVb}vÁ#’iLЉ)âň¸ĺßż’$GbĐý`VŸ-˜b­9—Éš]›e`ť^ňŰş…ś;°mw9śçpÉwĘçó§I›ňJŻ@Gő"MRůnßůíËňŸyßˉ}FÉÇó”7žgÂą§§}$9Ĺy2 m/š÷čK¤căV˛%§ÜúĺłňӚyŇ4-[.tœ\8xœä—ĘľŸ>!ÓWϕĄV¨ć. ­BOßËĆńi4$„[„ŔpČĺą~ŔĹÇIB\‚ľě•źd&GGĹJn‰Űo˘#^J­pËĺ-­ópËăń„´Ý!‡ŒSO=Ů,/_žBž|ňůôÓĎĺÚk˙fÖýöŰďňÍ7dǎҲeK9á„qŇŁGwYşt™<őÔłŚŇK—W­Zebĺ‚ Εôôt3ĚđË/ż–Ÿ~úŮT‘őë×WN˙ƒÝ=žfZ!Ű/kH++°ťőв÷s’_eŠ‚Ő$Ô÷ˆ%„[„Ň€†ňkv–H“”DéŰ^ňŽ|żôˇ áÖË'˙Ýú3WVąÖĂzî——VɉeÍó˝ĺC çßřž¤'Ľ˜×˘ŐfZŚC*/2Nnsžďuę}SVĚ6÷…ó…łKˇ4ĽĽ+ul.śBŒ +¨H‘ý[eƜň䴍fŠ´Î”öY)âô”Ę|ëX?R´÷–†':|0''׏kŐŞeůź•™ďھˡ}ffŮP¸””˛áv:ŹP}ŹN×\sƒYoWdmŰś]Úśm#áЧŚPćŰ%żČ˘-ŤäÉňŞ-ˇ×#—˙÷a9ŹŰ@×ë`yfúäÍßż–ˇhŽ*č)ő˜fđU9ąď(šă›%Í ›třâ‹3>Š´ÍŹőKĚkłaŠfŘ.ŤEĐ} hßłBĎ­@‡v Ď˙ô?ytň;rLĎarď¤×¤KÓśÖkšN†vě+Ÿ/˜&#:íoŽŇ¨ޛgÜ%C:ô6Çôđ䡼yzśĚ\ł0¤a‰ţĐPnh†ő•ˆL]‘'‡v͒m3ĽEz’üšŠHś¸Äĺ‰LőJ˘#NšĽ'JßVŠŇ>;Y´`gęŠ\)6ýŇë6܊{hâʕŤdőę5ŚJ+))I˛˛Ę™M›6›u›6m2ˇu˜au4KNN’’§ÜzëMf†^‡Cš5k*5w ˝şŸÓ[uƒü˛Ş­M t|yՖŰzžeŰךJ)ú÷ć˙{&žfMŻJVJ†éUuĹđżTšO˝ŠâÝ^•#ş –ÔÄŕ•f/˙ňŠ™kvtaríČÓ¤6´W×}G_*Ď˙üąź?g˘ő磍ďŘôꎷ}őź\ţż‡ĽQrşœ;đXS}ÖľIYą}ƒĆ8¨}ëĎůA2{ăŇŸ‹+% !Š a}œßm{9ŢonOŽň)Ą|ŇńÚ8ŰétÍđŁa‡Nڇ)??_Úľk[ĺś^ř/ۡíĺ7ÉŸć}l§&ÉrH—LIrTţqˇ9ß%_Ěß%őilŸli™QůŞ|ZąĽáŰŞÁŻřŢř 3ŹOƒ"”˙˛}ť*úžęT•5kÖĘ#Kő™únłˆ|g“ĎDŁ—ŽB§ĄMow™á€‚WYY)_Ű ˇ~Ü[ „Ł †Ł‰ĆĽř}) ř$ŕs‹ß•ŻîYo> c„[ Nz÷–v"|ř~Ňš%ŻŹ$Kc˝$(…ĹďŠÉČŇZ9rŕ9ůˆÉŠîŞL][€­ˇçÔÄLÇ{÷î-_?eŠŒ_řŠlŘđi›‹§'“š]›Š­JןęßżŸěšçЍ¨h÷\‚.؊p @AĘvi(tŕ¤n§ßŸë`˖Nu´–a´p @ÁH´œÓU[ű™nçZśW{硸LWR´÷Uúí|ÓŮ..@k„[rŞłNŚéˆ…jĽËŚC‹° äęů€p @ÎiMԙiƒm\Ş˝P+_×ÜĘć> GOšk7€ź@¸ gěŔĆĺrK<žŻ×ÓŠÇśuőDŐŢ}ů¨+@Ž$ SĂ)jšF¸ §´rťÝ‰DŹpŤ´ÓU ˛rŐÁՕ)˜ů(Ž˜Žz@> ܐ[ťś\âńx¤žž^ĘĘ:nĽ?WśĄUža‰ ßiíŚ5œłŚ€\q äˆA:|>ŸÄbQ‰Fٞ=ěç+Ä⪐ß;ŘšhÍŚľ›ÖpÔ/ň[rƞ’Řpůeóć8p€tŠ,€žĄ5›ÖnÎZr‰Î-9áěTҢ¨š{+&uuő€ü¤ľšÖlZťŮÁÝ[rp @NŮkné())ą Ś: ƒ€ü˘5šÖjZłŮőĄ€|Ŕ´D9ă\€Tżůóz˝ŚXŇV÷X,.UU•€Üӎ-;ŘҚŽ-ů„p @ÎiqdÓ+jŃT__'ĄPPz÷î#~żO°ăE"QŠŠŮlŚ"ÚÁ–ÝľĺŹá —ˇä„~çA–˝uGv'—^‰gýúőâóyĽ˛˛Ň šV!ŢĽ=Eë˛xä လÉp9™ˇ§*ĆăqëĂZëII$’ć\{({ €Îq†S[ë0=ćj ľJ[ZÎuśśä Â-9ĺ ¸lvńdP‰DÂWÎ0KjtűËĹô5Q#Ó[[ňလł‹"gČĺěŕJłěŰ6B.€Žq†S™Â­ô@‹n-ůˆp @ŢČÔŕ^@9.B-€î‘)ŔJ_5Ó>äÂ-y%SWú‚óÚľEQĐýŇŻ€H¨ nČKv—˝oKşĐ˝2…X[ňဟ•>Ńy =Ú @! ܐ÷Ň;ˇĐs´Â-…b ŕD¸€‚E¸€‚E¸  °ć@Ďb…†p @ŢK´¸z†[\Š@Ą!ܐˇœ…•˝ŸH$2Ţ€Žs†Xnˇ;uĚŽˇšä3Â-yÉ.¤t‹Ĺ$›ĄˇímúščghĽű'ľŐáőzS!€|E¸ ݤ‡Z‘HÄ|{XR°Š+Ÿľď˘°č!Zƒ%Z‡EĽŠ)lj1żßoB.ľ€|C¸ oŘÁ–vf…ĂaS8UVV´*ŚĐsšťśt$˜/ƒFÍmí梋 @žq ä˜Höh. ­o}R]]E°CZ‹iMŚľ™ÖhZŤ9k7ČüŐ §œ ĹëƒRQQ.%%%€üPVVf–ŠhhhLí렋 @> s @Τ[ĄPHJKK śňÖhZŤiÍf×oŠ.šF¸ 'œÁ–îë:ŞźźLŸěZMkˇćĹç ¸äလłŻŞŞä7­Ů´vÓňá€œąťśtaR]łÁçó ň›ÖlZťŮ‹ËŰÝ[+„[rJ‹!-ŒĘËË…Ak7­áśäÂ-9ἄ´Fzyi­ÝěÎ-{@ŽnČ ť˛Ż´Ł­í( ZťŮuá€\ó äPs1”—Ë%( Zťi G¨ nČť˘&('$ť\zi*ŒËFW“+ĽcÇJŹśÖěGÖŹ‘đŠ⊏”˛˝ö€b@¸şdýý÷›`Ëí÷˨;ď”çŸ/ÉhTVţęW˛ň—ż”%—]&˝;N\VčľĂh’Ë•ńŽĄ×]'ť|ë[ďŰýŽť¤3|ýűwú1š2ň–[RűŤ÷;YvíľRqŔ˛ďŒP Xs tÉZ+ĐRƒŽźR^xĄ¸<q—”Čđ_üBúœrŠ”íťŻ4|řa›×Š}łÇ—ˇËĘäýQŁdŮ÷ž'ą-[R÷'‚AYţŁÉ{ÆÉŰÖó~0fŒ ͒‰„šăòV5÷ˆ#äó믗™ĺĺ˛ú÷ż—βŸG§ö9oϟ:UÖ˙ăňŢđáć=.8ýt‰mڔń1öçůČ Ţ.-•™UU2ďÄĽqîÜm^oóSOɇcǚĎôŃAIĂěٝúšD7l…_ýŞĚŹŹ”÷wß]6>ôlŻŽ~֝ů|śĹ—\Ňü37Nâőő’ŒĹdĹO~b>Ó[V úÎŔ˛čâ‹%VS#ۃÎ-Đ% ďżoś}Ź(Ý^O>™Ú׊ŠéÖţß˙ÉâK/MM }úŠŹžĺiüřcŮ祗L÷•8›Ÿ}VĘöŮGzźl~ćYţăK"’áżúUęšt­Šú™3ÍZ_éÓˇëó}đ4źűŽ”í˝ˇD׎•M=fÖs˙ýۜťeĆ ůôěłM¸×˙ë_—ŘćͲé‰'ĚĎhÂŇĽ­Îýôœs¤dÄë+FˇšÁi§™s\Öí.–ůVp¨kˆéÔÂ+x[růĺ­B¨Žččgݙϧô=Ż˝çń${=ý´yŻ+~úSYńóŸK`ČŮĹ žę­Ÿíş{ď•Č_ČŢÖktáč4íÄID"fßײxś4ˆY~Ă fĚ?ţ!ՇnŚ3jTí+ŻH퍯JŻ#”a7Ţ(}Ϙş­eŁn˝ľÍó5Ŕ™°l™řwŮń0ÚeTóüóĎmüčŁć紂°ÝďžŰ,ŻďSŤk‘%ššRçętĆçgŁZáĺË%´`YŤŁŸ‹†kliśďôéR1a‚ ‰tŃüíŃŃĎş3ŸŻćšçäókŻOY™ěőÔS6ŹŐϨďgČČ?ýÉg˘•[˙śáč4OE…YkK.{Ş^ś"ŤVĽşšœzę6÷‡.4á–v5Xˆv25YPcËÇD8ÜęüŇ=öč0Ř2Ďťh‘6&מ’Ýw7á*?ŕłŐ -“Ţ'ž(ž›n2Ý^zŐ@]ÓŞňK_2 ęť|žÖçžpBósZĄ•v4ésęČćç˘Á“yo#Gš`KUNœhËoĘĐA•­Ž~֝ů|ÚáĽúŸ{ŽTx`ęxżŻ}M6=ů¤|ńç?ËŚG•r+ŘÓÎş.Ŕö ܝçr™pBťˆ´űŚęĐC[Ý­ëUét3íJżĎ,úŢB§Úi“†JI+4›3y˛ç͓ĘI“L“†8™ÖÔJWÚ˛űw´š |&ş†XjżEęmĽcĆČóç›5şęßzËü\j§O—/nšEöŸ=[ź˝{o}.ÇçŐŹ”,~.ľ-Sˇ™†čxlgeółîĚçłmś‚ŹčŻ~%ž~ýĚíţVčĽĎłá?˙1Ó=őłčúc:sźŹeűĎ  Ę€.ŮĺŇKÍV]l\ J–ßt“ -‚VRyĐA­‚!í–ňššĘ˜ŒÇĽúˆ#̨Ÿ5Kš–,1Sďt) [ťî*ăfΔżůŮĎWuoż-ëďťĎt4íe…}­`OßoźąQę^{-ŤçČćç˘ÓUÓ˛eć¸Ňi‰MŸ.]•ÍĎş3ŸoëýhWYdíZY|ńĹŠăşđ˝.Ä?č˛Ëd_ë1ă[Ś)ęż':5 ŤčÜ]˘SŇj_|ŃtâčT´E^hB3ÝĎ ´tm)˙!&ôŇ`Fƒ_ůŠěaaÚŃľô;ߑ…gžiŚĽiR÷Ö[âŮĐ Wě)M‹›PO?§Ž]•°>Ťžw]Şę°Ă˛zíëčç˘aaŐäÉRg…PŸsŒT|°šÚ˘Żoߌ ÷g#›Ÿug>_ÉčѲÇý÷Ël+ÓEçľ3K×őĘt-Ż <`ËˇŻ´Xj>\şŠÎ-ĐeTiˆĽ::NŻŚ§ë(ł]4]ip2ęÎ;ÍÂâőď˝g:…_u•ŒůűßÍT;Ö¨Cý˙çdë~˝R žťç˙+e{î)­×Đnjşí6ÉWÎ?_ö´B>] KßoÍ /HŻŁŽ’}_}ŐLĹËVG? ÇZQ?+`RÚŃ5ęĎ–’Q٤Ť˛ůYwöó•ZĎ5âć›Íţ˛ŤŻ6kíný;0üç?7ŸAݤ¨Çœ{Žě3}:SŔvqeqÜĺ¸mďť[{xZ†ˇeř­Ą•JŻH$:KŔ!›FĽĄĄA†"(ŤV­–ŠŠ ńYľÇă1Ňůý>˝Źs­5˘ÖĐËmÇZFźe$#éŘڋŠ:÷%mß`Z" á á á လrš\€ÂD- ¸rLk˘d2)( Zť‘kČ„[rĆţŚĎĺrK<ž­Ý´†StoČ5Â-9ĽĹŰí–H$"( Zťi G° nȉ­][.ńxŸÄbQ‰FŁ€üŚ5›ÖnZĂŮőäလą§$6\~ŮźšFß´fÓÚÍYË@.nČ ű[>ť(jîފI]Óň•ÖjZłiíf[toČ5Â-9eŻšĽŁ¤¤Ä*˜ę$ ň‹ÖhZŤiÍf×o„ZňW Gœ ę7^Ż×KÚę‹ĹĽŞŞR{Úąe[ZłŃľ ŸnČ9-ŽlÉdŇMőőu Ľwď>â÷ű;^$•ššÍf*˘lŮ][Îr‰p @Nč7|dŮ[gqdwré•xÖŻ_/>ŸW*++%°h)@Ňş,‘HH8śžlʎęąćőľJKËRĄ–3Řrvâ@ŽnșL—s‘y{Şb<ˇž1ŹľĄĹVҜkeoĐ9ÎpjkŚÇ\-ĄViŤ@ËšÎÁ€|A¸ §œ—Í.žěJż=ÔâĘfé1B-€îaš˜ž&ŞsdZc‹` @> ܐsvQä šœ\éa–}ŰFČĐ5Îp*S¸•hŃ­ nČ™ş¸Ň (gŔE¨Đ=2Xék˘fÚ€|@¸ ŻdęâJ_p^ťś(Şş_ú ľÂ-yÉîâ˛÷méAşWŚ‹` @>#ܐˇŇ§": çQ{(„[ň^zçz€BC¸  PlœˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°ˇP°Ü ‰Č¤I‡šą|ů Éľßýîó^nšĺĎćvmmmęýŐ××Ëö8ďź ÍóLŸ>ŁÝó~ř‘Ôk^|ń7vF„[vj~8ۄCS§ž&…ć•W^MíňÉř+|ű‘$“I3ž˙ý¤ÖÖŇ÷ňťßýŢ Ö:ž^hOI<č  2yň$ł˙駟ʪUŤś9÷Чž’Ůł?’/ ňˇżýCîžűžVçŹXąÜŰoż}Ź÷YbaÓĺÚk`îkhh+ŻüŽźóÎ{Ösě/Ç{Œ řĂÍtHČ%:ˇźŤŽşÜtD­^˝ZÎ8ăĚÚSşčünťE‹™sŚMťŔtsÎYV0łÜtvőë×Ď Ć~$ßţö•2`@łŻšššä§?˝IślŠ“Ł>2ő:Ď>űźźýö,Ó)Ő ×î¸ă.ł˙“ŸüXƏßßt<ţ…ňŢ{Č|hÂŽyóć‰Űí6ÝgcÇî)óç/‹.ş´ÝçÖn´>šcö'N<Č ĹÉđáíϼ܄RßřĆů­ÎŻŽî%÷Ţ{—™Â¨\ÚŃőŘcËĽ—^œ:' É=÷Üm=ĎŽ˛dÉR9ďźoČÜšŸXŮgćýi(Ś^7ÜđéÓ§œzęT‰FŁ2ränšD瀂7nÜ~f;dČ)//3űÚ}ĽŽ>úhłŐ.ŁłÎ:×t'56ÍÁś”””ČĐĄCÍTBí˛úĆ7.–çŸŃܧÓű˛ĄÓkkˇ˜ýëŽűĄsĚ r §Č† Í1 ˘–-[föl‚-ľ×^cMX՞3^3áYßž}RÓpO˝ôŇśëniw—[ÎótŠćŚM›Rçhǚ[jÔ¨‘ć=ŠĽK—ɈĂÍtĎxÓůőüó/˜ŽłO>™o:Ŕth‡ŰńÇ++tn(ZĄPČLżÓEĐŻżţűr˙ý÷Éu×]cî›9sŚŮÚa˜ł#ëÍ7ß4Ý]ÚÜ|óŻĺ⋧ľ МěPȪ鹁HďŢ˝Rˇu˝+şF•NŸÔî0]”]­Ył&ľv•NK\ťśí5ˇtJ˘ŽŸĽź^ŻšR˘=l/żÜş{K?k]]Ů×uÄTuu•™–iÓ÷dż˝ ăÚľëĚžvqéű{ôŃÇĚ´Ę_üâgÖĎôżrĚ1G™űg͚%Ktn(Z:ď_˙zĐ,˛ŽZ:…Ď^~âĉf;xđ LéÂo}ërsĹž}›CŸ×_Cn˝őv+řYeŽfč´Ë.ĚöĹ_4űgŸýuł†–jşť†@^xüá’nřą|đAŚÓęăçJ˙ţýäČ#żlŢĎžűîcÖśşęŞŤeď˝Çš5Ž4x˛§4Ś{íľ×M§—N|ţů§Ĺď÷§îťĺ–?Ëţ󐙚¨WC´ipwîš˜Š†úúęĚ3ĎhŘétÎď}ďű2f̰i÷˜Ž6zôî˛rĺJšăŽťÍ[ÚmŚkx˝ývs8xĐA ä[Š–†7wß}ťš ˘^ąđÉ'Ÿ2Ą.¸nwp 8PŽžú*8iČ´hŃb9î¸c䢋.´ŸryüńÇÍ´< ˝œŚN=E&O>Ř Ž˘ňꍯ›×şîşď›Ž-ţ¨WWüÚמ*7ÝtŁY ě­ˇfš5ś´ăéŻý?óÜŞýď˙ţÚ\Q­Ző…0]m?´ÍĎdOIœ4ibŤ`K}ůˇ›­ŽڟĂvěąÇšľÇô ‡˝zU›ĎݟĎi—]™×^˝ú sű¨Łž,żůÍŻĚžŽÇuď˝w˄ šĹđ_xáE+(bŕן-ä’+‹ă.Çm{ßíŘÚĂÓ2ź-C˙ęňYŁ—őÇóV`ÓŤ"ęşX˙ó?_3^&ӧϐn¸QFmŚm@wňű}“ŹM­5˘ÖĐő`b-#Ţ2Ž‘tlíňű’śo0-‹p ‹i‰čLKÚA¸€‚E¸€‚E¸€‚E¸€‚E¸€‚E¸€‚E¸  $“I@Ďqš\…„p @ŢK´¸z†[ÎZ‹  @! ܐˇœ…•˝ŸH$2Ţ€Žs†Xnˇ;uĚŽˇšä3Â-yÉ.¤t‹Ĺ$›ĄˇímúščghĽű'ľŐáőzS!€|E¸ ݤ‡Z‘HÄ|{XR°Š+Ÿľď˘°č!Zƒ%Z‡EĽŠ)lj1żßoB.ľ€|C¸ oŘÁ–vf…ĂaS8UVV´*ŚĐsšťśt$˜/ƒFÍmí梋 @žq ä˜Höh. ­o}R]]E°CZ‹iMŚľ™ÖhZŤ9k7ČüŐ §œ ĹëƒRQQ.%%%€üPVVf–ŠhhhLí렋 @> s @Τ[ĄPHJKK śňÖhZŤiÍf×oŠ.šF¸ 'œÁ–îë:ŞźźLŸěZMkˇćĹç ¸äလłŻŞŞä7­Ů´vÓňá€œąťśtaR]łÁçó ň›ÖlZťŮ‹ËŰÝ[+„[rJ‹!-ŒĘËË…Ak7­áśäÂ-9ἄ´Fzyi­ÝěÎ-{@ŽnČ ť˛Ż´Ł­í( ZťŮuá€\ó äPs1”—Ë%( Zťi G¨ nČť˘&(\|_;ßúmíŔśˇ¤čC˙Ř+ĎJ1K66HěĺgĚžďě‹°-ˇ@Š˝=CvqíNdDç€Â”ÍTÄ"Ą\€ĚˇP°ˇP°ˇP°ˇP°ˇP°ˇ H}÷ť×țožş]ZZ*{w\sÍweôčÝŠáąÉ“–+ŻźÜě×ŐŐÉ?ţńOšüňŤä‰'1a:Â-(b•••2fĚčÔmÝ?ę¨ăĺƒ>”C=D ĐnŔNÄëőŠËĺ’@ :öä“OË<(+VŹ”~ýúĘŠ§N•iÓžaî›?œţ´mžGC˛ř‡Ů˙â‹5rÇwÉŹYďH(Ô$ăǏ“ŤŻţŽŒš›š? É}÷ý]ž{îŮ´iłěśŰšä’irć›űŸzęšűî{äźóΑ{îůŤěˇßžňťßÝ, Â-ŘIlޟ٠n‘#†›I=óĚsň›ßüÖ ŁŽ’ƒš ~*?˙ůŻdčĐĄrěąG›sďšçÎÔshőӟţBN>ůDs;ËW|Gú÷ď/ż˙ý˙JII‰ şŽ˝öňČ#˙1çüöˇwß}OŽťî6l˜r=/?řÁňřăË.ť 4çlܸɄcúČáą—_ž.3fźnö#‘ˆôéÓ[nžů˙Ľ:ˇN:é™8q‚ §”†Y?ü¨|ôŃn•••ÉţűK=^ĂąĂŸ"gŸ}–9ćńxäďż×t„Ůkx}ýë˙#ßţöUR[[+˝ző’n¸^ęëëĽwďŢćţ‹/ž&űŰý2oŢüT¸Ľ!ŮĎţЍ¨č Â-(bş źNTN=ţř“rŮeWĘ_ţň'9đŔĚńőë7Čc=!K—.3S/^"ÇďşÍsÝ|óďLHu睷ľ:ŽÓ5Dűä“y˛rĺJY´hqęőěűçÎýD>üđ#Yž|šyD"!áp8ő••[ş„p ŠXyyšéƲéÔŔŐŤWËţó_néŐďžű^9í´ŻČa‡M‘]w&÷Ţ{ß6ĎŁëbéšYýëÝ­B¨šššŕ‚‹¤_ż~rôŃGĘĄ‡~Éts]uŐ÷Rç\sÍu&0ÓľźN:éDŮ}÷Qňo\$С`'S]]mB)őôÓĎĘYg}UޏâŰŠűuýŤ>}ú¤nöŮ"ł.×5×|WöÜsVĎĽÝXk׎“‡zŔʎĽ^ýÔý:5ńÍ7ߖ[o˝E&OždŽi÷W0č„[PÄ4HŇpJ555ÉěŮÉ /ź$×_˙}sLťş4|ŇŽ-íňҎŽĺËW˜Ť!ކ†šîşʨQ#Í1^¨´;kŻ˝Ćšé‹:ĹđĄ‡6ĎąbĹ ůăoM˝~UU•YçK;żt]Ż`0(ˇß~—¸Ýn€î@¸ElćĚwĚP>ŸO† ,ßůÎrú駚c7ŢřCůĺ/mÖ᪎Ž2ÓujĄííˇgÉŞUŤ­˝Őrᅗ¤Žëâńoź1ÝL1üőŻ)ţómfzŁ^W\q™ˆÝ`ÎÓëöŰo•Ÿýě—rţůÓĚë_~ůˇdéŇĽvŒX,f.ţĹʕĹq—ăś˝ďvlíáiޖ᷆Ď˝"‘č,˝:žŽh4jşƒ†ŇŠÇ‡ŚŢŠóĺśű;uş\q^§Nďéç/ý룂âűě ?6SbK׉Ť˘Dü“÷”Ŕԉşňž„Ÿ}_˘oΗDmP<ĂúIÉé“ÄťĎp Ť.üT^zéł6ćŘą{JwŇ/Ŕt-NýMťşu@:żß§ë“ÔZ#j ˝ęTŹeÄ[FÂ1’Žm˛ĺ)œű’śoß(HM‹$ funؕ”şĎ—ŠżeM¨ŽD­ßŻŐ‹jÄŠfu~8ŕ—ş/V‰?ËŠvጐTĎ]'¤+Ťó]ĺĺR*(l5ţţqk'nn'k%üÜ[¸ĘúšČ%ń%kSçĆ—Ż—Ć?=%ĺW"Ţ} ¸]łË.­đÉ+/žř˛šÝÝä=P<#Gd}î:OB6ŹY‘őů[ÜM˛yXŸŹĎ_ˇK_ŮkĘúükVZď)žőůůŹČoÚąe[NńeëZ[)‰¤4=:SčŞ^˝zÉgœ&%%p͟ż@ Řn(HţŽÍúÜýůäÝ׳>ŠŤV:6ëóßż—ĚŠß’őůŸźóşĚög׌üÇg˙Y‘ß⟯—ΊŻÜhýOBč*˝¨‹ŽˇŠ—NQ$ŕPlˇ¤ŔiSĹťçž÷…'.ď"2űe튎1ß,!ů4šY>:r?Y7b@‡çŻ<@Ţ8hœĚŞÝ"Ť›:îŢZťr™Ě~óEóžVgŃ˝ĺÝcŒ”œ>UP\ĺŮMmý˜€ˆ‡˙\ś€bFľ   šü~ŠřĂoÄ3ft›çhxt_eŁÄ]"ńXLşýײnŐ˛6Ď×`ëe×r‰ÄD"nŸ<|őОvלŽUƒĘ]ž)aëÜ&+§úëĘŐ˛:jóüľ+—ĘCů•y/1ë=ýÍzo_x۸4ŘŞ¸ĺf˝ĚĄ 8ř&w~˙!{ ÝÁ¸ż ¸VŽ\)P ¸Z"€œŘŢŤ%ŚXAQÓcOÉúťo“Ňúˆ9ŞôËôp­Ě DL°ĺäöxdüĄÇČž“ސţƒ†™cÖŹ”eÉY2Ş\˘ń¤Ä.ë˝é{´IČţ3>–q3çɀ/6™ó×îŇO>ŘŹź>iź„­_{‰D󹺔Rĺű3äPżk›çŸ÷Ţňáë/˜`Ëɓ™öË1^­Ţ˙€iߔ’3O#Ř*6Öż$~Zbó˛[Î;v¨”wŞľĂŐ§ÝcÆ ňČ#I8ą‚ŽŻČ°a䍸Z"€l숍%nȉn ˇZ<űËsZÝ~ôőĽ3*Nţ˛”xds¨eÂ*{ť5čJOío=–h9ŻüݗĽę˝—ĽłN?lżVˇOźń_‚"e\Áű^‘čŹOŰ=ÍwŔ()˝ô8qůřCĐ=4ŘzôŃÇĽŠ),Çs”ěľWökŒfB¸ ;"Üň Ŕt_EŽËîŢJ´ě'›÷ŽýxҕÚĆŹc˝c>٧t4˛ˇuüüŠŠ_"€aeV%_9XÜ%ú÷ÖwOÉÔńŔ)Í}t‚-Ŏp @Q5¨W‡çœřĺ*Ůăˆ^’ &Ź—ýVIrĺ šŘq[ť´ZuhYW˛%ŕjŮ gĆwo™ÇÉhB>ˇ¸ÜQ)I$%ÖgœTWď%+6>.5[^Ŕć?jœ¸úTJđîô_*)›v”řîř* dŤśś6ľĆÖąÇ-cÇvţâ&ďˇě”†ööČč •"á¤I­’šT%“2.šBf|śD†4ŻĽłBŹXËúZą–)‹ąć)‹'xË×zď*žJŸxĘ|&ÜJ„­;Ü.ó|îH\źV*ćľB2ŻË#ýúœ*‘d\ë:ż&Š—oüH)żzŞů÷P ;­]ťN˘ŃÁ€˘F¸`§tŘÄ ‘`BîDs°śś‘ćëôŕ;ň ÷ék ą-Űxj+2"Q.g”ď*.Ÿ[ÜŻxĘ}âňş$V•¤p%Ź}—Çmޞae]fčęI•˝ŚJSÓgdwľźíĄ‹őOŸ>C–,Y"^ŻWƏß_:hÂ6ç=öز|ůśďç’KŚIyyyÖçt†~‹üĚ3ĎɆ ĺÔS§ĘˆĂÍń9s>–÷ß˙@‚Áěşë03u˘ŹŹ,ŤÇÚ|đ!SČkďœv‘´ÂË{îůŤ46ÍeĐőůís•Ëĺ’Ţ˝{Éá‡&Çď*;’wĚö]P€śěšç˛űîŁL-Ŋßpv:ű ňIßž>I6̧&ŹP+jŚ„ š'jäK›ćÉô˛}SaV"­sëT÷`q™ëxXKX!Y,!Ž„vl%šŸ/Ůڤ.ă‘Úq‹ˇęd‰oź]zÚË/O—5kÖČ 'o…EAt•””ČžűîÓęźĂ;ÔLU°Í›7ßbzngÎÉV]]<đŔƒŚŘրʶxńyýő7eʔC¤WŻ^2kÖ;ňřăOĘŮgŸŐácӕ••Ęüů Z…[+WŽ2˙LŇíąÇ9ŕ€ý­ś ™=ű#+8{Ö í.2W~ l(vü–P”úTd]ŹHK&öK˘!n~şŹ˙3‡†[ŃDó4E+ŕúJĂ{ň–{´ÔIIŞc˞˘X÷˞ŢrIDâf˘Ť1Öź —ËŐ|Ź).IkŤĎłžŰ ëuă-Cüc¤şr x’[¤§„B!ůôÓĎdęԓeˇÝF˜c›6m’>šłM¸ŐˇoßÔ~Üú îpŔřV—óÎćۚ5kĺůç_0…ôI' }úôiużţź5p:tˆ|üń'Šă~8[}š.íÚJÖĹ$Qomu4갂)Á„”G‚rňşw$qI,*fŐmÔ%#âe‰%$ŠIź1*ąúˆÄś„%V–x]Dâ ÖĆŹsăąÂ˜¨pĽ‚.‘ˆg„ô$ťŤiȐÁŠcC‡ľŽÍ&œjËÜšŸH,KL]9gÌ×d˖:óZŻžúÚ6÷WWW§7§7JEE…YôöŽ;î2gƒJ[í=6]UUĽNőNYú~/^Üîc5DÓnŻęę*Ó9 0Đš`§Q) Y.Ía–׹VBš§FľƒK×޲FSRŽnúHžóî'Ť|}[-*_nýę š⊈ř­‡¸­óÝú|Žći‰Ú˝łFĐÚYI“5ÂÖóGŹՑ´ëę%ĽŇs"‘ć)„@ u̞B‡ˇYÇJičĽë]iG–ßďĎřźŮœăœú—i`[ď7‰Ęťďž'SŚj˝żƒäľ×^7kkuÖפłôuuŃÜO>™'<ŃLyÔ.łaĂś]°}ΜšfšĽNKôxÜrňÉ'ľ Ôä7Şw;ýqq…â’¨[Wź9䪋ˇtoĹM7—vniW2O(&ç­zĹtk5ćέŚxRqi°‚žĆHL ×[áL]ŘlCM1Š%ŹsŠ€Ë„\V¨N6‡\ń,CŸŽ˛ƒ' ˛lMMMfë źœ4ŕŃŠ˝Ž­lÎ9ě°)fŞ_ee…~řɆ.ćŽöŰo_ł–†Pş°ť.öŽS;KĂ-]—K;ČÖ­[gŚ(ęóf ­4;÷Üł­ńu™8ń y≧Ěc:ˇěĆb2Ŕc…W VˆâMˆËăÚďëâď kÄŹ+”2‹ËGŹ‘¤ěß´XŽ ţA֕níR*)9PŞĎ7S ľ#Ëçv‰;žľ ,Ö`i˜ĽĄV0a\IÓĹĽŁ–łsK‡#ÜŇľˇ´sKĂ­ kŒX”e˛OOÔH}řS‰řÇˆĎ ˇš›Ŕ\-[Ii~šćp+ÜŇ­ewoéÖ_"ţd]ę˝zŇ:“œÝKŰă裏”éÓgČsĎ=oŽ\8qâ7n?s_ccŁlذÁ,´Ž? Žô>{].U[ťĹľŠ÷”éœî¤]S:ĺń­ˇŢ6[˝âáQG}y›÷ۙpkôčÝĺŐWg˜Ť-zUIŞźźĚüœtJ#€ÂŕĘâ¸ËqŰŢw;śöđ´ oËĐ9<>kôŠD˘łtarŃhTL‡ÎöxäĆŻJiÉÖŠƒĄŚ°ÔlŠO8&_^źIü淓Ai¸ĽűVf:ˇ\šjšš”ˇ†&SŚsË,.ßnéˆZÇgL$Qs•đ “Xš­§ôXżđôšZŚ%&SÍôÄćN­P˛šƒ+Éą{¤"ů…y śúôŞ”Ç4ż`SDÎüĺ Ÿigľ^éX—Đ/Ÿ:󀝇ßď›dmô[ó¨5ôĘWą–o ÇH:śöBĹÎ}IŰ7čÜPś4[…[Ľ%3Ôü]w‘îĐúYtzŰ-ŇuÚź§Îú,€ěpľDEĄŽ1$ŃhL ]43ŸÂ-E!™LJMC°ŰÖŤĘ]7ŹŚ>h> ;LKP44؊ÄbâőxM@¤ëY9™ĎGhĹÍ ÜÇⱂç ˇIYj?Km}Pś44JS$ż§*–ř˝R]Q.˝*ˇž˙@iš˛Ă´DEĄďŕR,Šéł@O#ÜPĆN:FŠĹž-€ěn( űL9Iú -…ŽßĐÝ­Ďr˛˛C¸ (xź>9ú˘KŻAťIĄę5h¤}ńMÖga9DČဢQVÝWžüÍ_Ëţ']$^Ű\0ß%“" ĄˆěwÂ7äˆKe> {´(*.ˇGF|œĚ}ţď’—x‚aŠol’ş`“4†crë“ďK.=ńłłĽśžŃz?Íďký–őžęe÷É'  óčÜP”Ş3LO1fÉľ|}_P¨ˇĽýNşP啩Űe•ŐňľËŽ—\Ë×÷…Ę•Ĺq—ăś˝ďvlíáiޖ᷆Ď˝"‘č,‡xŔމDĽŚfł™Šh[vזł†€\"ܐú ŸYöÖYٝ\z%žőë׋Ďç•ĘĘJ ,Z Ѓ´.K$‡­/ë­zŹy}­ŇҲT¨ĺ śœř+„[r&SŔĺ\dޞޏǭo k­Ghą•4çÚCŮ[tŽ3œÚZ‡é1WK¨UÚ*ĐrŽłE° _nČ)gŔeł‹'ť€Ňoľ¸r†YzŒP  {Ř_.ŚŻ‰ę™ÖŘ"ؐˇäœ]9C.gWz˜eßśrt3œĘnĽZtkČG„[ňFŚ.ŽôĘpjtLVúš¨™ö nČ+™ş¸Ňœ×Ž-Š*€î—~DB-…€p @^˛ť¸ě}[zĐ€î•)Ä"ؐϡä­ôŠˆŘąľÂ-‡°  gf(D„[ň–3IJ÷šJ"@÷Ë´Öi[ËD@ž!ܐ—œWEŒĹbÇÍĐŰö6ý\tNú‚ń'ľŐáőz3^Ńň ဟ’jE"óíaIIŔ*Ž|Öž‹Â  ‡h –Hh•ŚŚ°ŠĹü~ż šlÔbň ဟa[ڙ‡MáTYYŃŞ˜@ĎiîÚҐ@ `žlll J45ˇľ›‹..ůĆ-cZ ŮŁš€j´ž!ôIuuÁ@i-Ś5™ÖfZŁi­ćŹÝ đW#€œr.Ż# JEEš”””ňCYY™Y*˘ĄĄ1ľŻƒ..ů€Î-9“l…B!)--%ŘČCZŁi­Ś5›]ż):¸äလp[şŻë8¨ňň2@~˛k5­ÝšŸ'ŕ{„[rÎ^@žŞŞRß´fÓÚMk8Č„[rĆîÚ҅IuÍŸĎ'ČoZłiíf/.owo@ŽnČ)-†´0*//­Ý´†#ؐˇä„óŇZéĺĽP´vł;ˇěšB¸ 'ě"ȾҎśś 0híf×q„[rÍ+CÍĹPB\.— 0híŚ5Ą€|@¸ gěbˆš đŘ5€\#Ü@Á"ܐS|ÓP¸¨ĺäÂ-,Â-Eíy?–Ş€_*­ánY´>ôș•‡Č×M@a#Ü@Á"ÜP´‰„üłôüćQÇÖožjo>Â-E+njóžp;÷Ů~óÔqš}Ö3ĽŃe ݺݺë¸Ką˜\uL_äဢUßPßć}MM!‰F#âóůŰ<綗֋Ű["[XxŕfÜrËoĹď÷Éĺ—_%ĄP(ëçřüóĺ&[šrUęŘ#<&'ž8U ט– hDW žÚĹ"ţé,ׂ‡E ‰DB6mÚh…@ţN=žśŚF† &.—+ulíÚ ňŃěyâńnŠčvť[öÝ-‹ÔťÍczjZbeeĽŒ3:u[÷:ęxůŕƒĺĐC(t„[ŠÇgOIWyë>—čÚš˛Ĺ3Đ\‹EÍ"ôöÚ[ÉĆ ”>ó˘ ühޏ­pËíu›­Kˇwëcn—Ä÷+ž˝ö•žŚë|i˜ćźşăŇĽËä–[ţ$sćĚŸĎ+‡6EŽžú*ŠŞŞ’gŸ}^nşégćźÓNűŞěłĎŢ2jÔHyâ‰ćŸľvt]pÁyrĺ•ßŢćľĺźU^}u†ů™Žżż\qšeˇÝF˜ű#‘ˆüéOˇÉK/˝,őő ˛×^cĺG?úŒš›@śˇ…híjńmšßĽŽ­”%/‰kó¤˙ţâ÷$PR"~ŸĎt[šÜÚu塍eënĽ4(Ňf-Ÿß'ŇŇ´łÂ˘-—_-C׎“]}Öyf¸ˇn˝îVÇôq 7^+žO—˛‹.qtu§Í›7Ëď~w‹Œ1\öŰŻ9HŰ´i“\rɡdâă䎝ţ"Á`PţüçżX!ÔwĺžűţOŽ>úH8p€|ó›—Ë=÷Üi‚'í<Óc÷ÜsŸ<÷ܓRZZşÍk%“I+ ťVšššä÷ż˙_)//ˇžďďrŃE—ĘĂ?(}úô‘;î¸[ŢxăMë=Ý, {ď˝Ož˙ýëÍýú3€ln( ŽUoËöňŹ}_Ü{ž+@Is¸e Ÿn™Ë [Ü&Črˇ„ZÍÓ =^ŻlůĽ$‘ŻÇ'ń5keÓy‹Ôn^ٲ Đ÷K"šŠËž%Ýĺ嗧ˌŻ›}í”ęÓ§ˇÜ|ó˙Kun=üđŁRVV&żüĺĎRWnüĂţWN8aŞźýöL™2ĺPéۡšMˇÚÍeď÷ë×7u_ş?œ-óć͗§Ÿ~Lz÷îmŽýüç?ąž÷yţůĺěłĎ’ŐŤW›.0;hűÁŽ5ď‘` @gn( ąŐłˇűš;’čúOE*‡KWŐŢř3‰oŘ(_'‚-‡†{ď˙—ž$ţqűIwĐ寞ú;f_ƒŁÇR.ťěJůË_ţ$x€,\řŠ —ě`Ki`ľëŽĂdÁ‚…&Üę }l86SeŐŞŐf˙Źłž&ßűŢľňŐŻ~]>x˘Lš4Ńzż“:ƒp @QđÔ­HM Ü.ľŸw9܊~śHBÓ_wƒ-#‘†żţ]úüé÷Ňt: NC´]wÝ5Ścę?˙ůŻ ˇ’í\YŇľÓ#űöí#÷ÝwlűžĘĚö€ĆËSO=&o˝5Ótzýěgż´ŢëšăŽ[ÍÚ` ć~( žxŁtßvĹb͚ľň‹_üĘúođ‰FŁć˜ţ÷t„Ź˙ţŢ`.ŞŘ>tn@žioŞ`g͜ůŽœ}öůfčŸzęůÎwސÓO?ŐÜ߯_?šçžť¤ŽŽN.˝ôŰríľ?0ëmÝ~űŸSëpihuÍ5ߕ;î¸Kžő­ËÍąC=DŽ=öč–őťî4Ç.¸ŕűB͔ŘŇuâŞ(˙ä=%0u˘Î•đłÖFoΗ„őďˆgX?)9}’x÷éúĹ;Ćäɇ™zgúôRWŢ´i“wÜÉćŠĹŻżţŠô$˝xĚK/˝"G}¤ůŇŠ;éEbôK0­—ôK1çjŔć÷űôŞQ:ÍESţˆ5b-#Ţ2Ž‘tlíoýű’śo0-@Q[îqÉK|2× ”BV@0$‘#Ăq9!ă ňŠ[żÜډ›ŰÉÚF ?÷ÄޞžBrI|ÉÚÔšńĺëĽńOOIůU§ˆw_.Č'ÓŚ]*ŸW^|ńesťť.Čüm h˝çóČoËýuô˘~îqË_ËÜćžÂŚĹ´#5Á„Üü|­Ě\] ýđ=Ęäşă{KďržD÷ю-;ŘrŠ/[—ů‰¤4=:S*ˇ ŻŘNéŠí˝Rq&şîĽŽąů裏›€K—?ŘkŻąńp @QÚěvÉĘ}­‚-§š>ˇŕ‘p_žúi“Ě]•Ţeůá Őrýń˝¤W™[歎ț‹šč.Žňé,Wy€` ÄóĎż˜qGąŽ’’€ ¸ćĎg}Oъ@QZěíř×[Ř żVu źöYs€őC*L¨ŐŰçNŞ0ÇŢZL¸…îă›Üů5Pü‡ě%€Â Wδż#ŮW ŕ7×ʕ+ŠÓěÔҡž¨‰Ę§Kƒâó'ÄHĘ'Ť#ćř1{•ŚÎ9jĎRšsFƒ,X•÷–5I(’°5úŐDd;ŻůˆXÉW&š…âcóVdužwěPsĹD`gG¸ (íKČűŹH&eˆŽWäđÜÇuň‡_ˆË[&â+ˇˇD<ˇř=[c0żˇyÁšâŸ[¤)X/á`ƒœ7żV. ‹ź)żęd Ţ÷ŠDg}ÚFIéĽÇ™Ç­ 6˜uˇÂáˆsĚQ2lŘ0€bŔ´DEé˜pLJt5řvŽ[—dĺˇ/l+/3㖗śĐ#ʰŞěâc%0ub›§ř'eß>A\>‚-@öě`ŤŠ)l‚-”PLčÜP”úXÁÖ÷#ňŰň@Ć+&îËŮĄ¨dë…yA™űǨx\.ŮLŠ×Íwč!.˘x°¸+J$ôď7š/ŮŮröş%dSC 9*—Â1élßËúş¸xÜ.3MčiţŁĆ‰ŤOĽď~A$‘”˛iG‰ďŕ=P˜~őŤŸgÜďiľľľňČ#™ŠˆÇ{´ŒŰů ˜@ž#ÜPÔv'ĺšĆˆ…Č7~¤”_=UÄú÷XŽţýűɆ ȅeܸýä¸ăŽIÝgďë}öš=eíÚuĆś5Â-(Rńx\^ý Y¸°yqň˝÷ŢK=ôqťÝ‰Dä•W^•O?ýL&L8ŔwŇoyŸyć9S”ŸzęT1b¸l}/ˇŢzťŮżä’iR^^nö—-ű\Ţzëmózýúő“)S•!C§÷ţűČGÍ1ďwčĐĄrä‘GHEE…tćł:}ţůryüń'ĽşşJ.źđ‚V÷͝ű‰ů™ ×ëqI>yă7eéŇerÔQGZĚ—Mđóć›o™űzčaijj’^˝Şˇy\]]<đŔƒ2hĐ.Ň]4¤JˇiÓ&yęŠgŹ0i°œqĆéÖ{ée…IOHCCƒš_ĂŚˇßž%4AŚN=EęëëĺÉ'Ÿ–Î~Ötxég_˝ú‹VÇ,X(eeĽŰœ晧Ë׿ţ5óź‹-ĘřYH÷­o]"\p^ť]YzŸžóÍoöěő– ś;~Ë€ĂSúș#GŠß@ >ŸO\.—¸Ź@Ä­[—ŰÚoŮZˇŁŃˆ”„$l…%á;ú‹,“źF­phž|ĺ+§ČŽť6_ćťwď^ 5™ý}öŮ[ößœ ąŇ%“I9á„ăečĐ!ňńǟd|~=Gťœ–,Y’ę’j‹ve˝÷ŢűŚăiúôŠăÚ5VQQnŽŤ]v(wÝőš9~ŕ˜°IżmÖŠJ§Süë_ĘşuëdŕŔYÖLď}Ĉ2ţ‚T—Ř–-[d͚ľ˛ÇcL¸ç¤xčż úšK–,ľBšÍ@G´†¸ňĘo›čYtn@ŞŠŠ1Sőbą˜Ü˙żŹĐč˙ä“Oć™ŔJi°Ő–ęęjŮmˇí>˙ňĺ+Ěói€ôţűnÓ夁Ö{ěŃjşĄŇ÷ŚĄ‘MĂB˝m‡GÍ÷űS÷—””˜mz¸ÔŃgM§á–~>íÂŇÇ(íôŇp­´´DÚ˘Żłzőj>|W?čÜ€"ÔĐĐh¢wß}OŽ8âp ƒňĘ+ÓĹď÷ˇŰe•­D"ŃęśF™hh¤—?ńÄ㼹ąąŐ}Æ “Ůłç˜­1cFËÇϕşşz+dЎÜ?ÔtWi÷VďŢ˝ĺÍ7ß6ŸIƒŹíýŹťí6Âl-Zl×Ő÷°ß~űšŠéî˝÷>łD˘fÍ}?ňá! {4p:ě°)ftľyóf6uG¸Ľ ĚëžĹ‹uZâ،]RápŘ,ňŽŻ§A“ŮAŘnťŘ_^zéyᅗĚsjw—Ý=uđÁeăĆMňď?dÖÉ҅ď˝^uévV]{D‡×):…q˖:óy2­§Ľ‹Ë7ż˙™1ă5yîšää“Oůp ŠPŸ>˝ÍÖŮaĽűéWě*}žN8ŽÝsVŽ\%Á`ȄW:l÷ÜsŸY¤]ŻX¨Óĉ™éZi—”vP)]űęˆ#3Á’†QşĐü{ď}°ÍB÷]ýŹÚąĽ Ř/YŇĎL5´Żŕ˜Ž˛˛ŇL—ŹŞŞ2k=˙ü‹Ýúł°}ˇ éşYŘLŸţŞL™r¨™8{öG2am>fŐŞŐfá÷ŠSOÇ#ŰK§ęUm6l”—_žn~0 żŹ_żA~řQ9äÉfąv]'KCŹQŁFšóľ+죏昩†p͜9ËL_Ô* É3Ď<'_ţňáҡoßNVĽÝfeee&0;ţřcŰŔމDĽŚfł™Šh[vזł†€\"ܐú ŸYöÖYٝ\z%žőë׋Ďç•ĘĘJ ,Z Ѓ´.K$‡­/ë­zŹy}­ŇҲT¨ĺ śœř+„[r&SŔĺ\dޞޏǭo kE×L$’ć\{({ €Îq†S[ë0=ćj ľJ[ZÎuśśä‹î ˇřË@—8.›]<Ů”~{¨Ĺ•3ĚŇc„ZÝĂţr1}MTçČ´ĆÁ€íÔ-Ôu5ÜŇwĽíóW&€.ą‹"gČĺěŕJłěŰ6B.€Žq†S™Â­ô@‹n-Ý(™śMßĎZwOKä/L]–Š‹+˝€r\„ZÝ#S€•ž&jŚ}č˘nýcn{Ă-g—ótIŚ.Žôçľk‹˘  űĽ_‘P @Hfy,k=ľ |R2ˇ—@Vě..{ߖt {e ąślg>Ô#Ńö„[™şśŇď'ŘĐeéS°cjč&ŮdD]ţĂŻ;Ż–ŘŢՕŸiľĐ-ťza€n–hăxG9R§tG¸•ŢÁ•L ˇŰU“H$ű t‚3IJ÷šJ"@÷Ë´Öi[ËD@ś4’ć€+=+rÚî?ě˛ ˇœá•ý‚Ž ÷IÚ9öŽG"ą^݇p @֜WEŒĹbÇÍĐŰö6ý\tNú‚ń'ľŐáőz3^Ѳaý-ˇÂÚÄĽăľŮ“iűÉ6î˨­p+›ő´2ukŮӝŠ\źąą~^uuŻńHľ"‘ˆůö°¤$`W>Mţ)ŹzˆÖ`‰„ÖaQij ›ZĚď÷›ËF- [őőőó¤u¸•HŰvś‹+ăýYŤ­Lśsż ˇćÍ[řž@ě`K;łBĄ ˇ*++¤şşJ€őíĄ›b  5wmšMíĽ5˜ÖbZ“imŚ5š˘k@ś.4yPzç–-›\)+Ž,ďs9śéĂíŘzZ†ˇeřʰFľő ń9Öݐ‰ł[K‹Ś`0(eeĽÖ(äžÖgÁ`ČÔgöÔEŏÚâvť6y˝ŢŹÝ-Ö[#jXˈˇŒL\éksu8EąŤW0LśłŸŢfŚo6źvíş˙¤q.o[ĺ[yDk3­Ń´VӚ;Č]\ÚҒi¨ŐVˆeëÔúZ™dnezĄdűÎ7l‡[‘sÎ9űAMíZ8ƒ-Úî^ZZ*%%%€ü˘5šÖjZłŮő›"ŕNó́ŹÝˆl ˇœy‘HŰšR§ĂŽö­ŽVŻO?ć|ƒ inE_{íľššsçŢ" ­ƒ-ݏFŁćvy9[ůĘŽŐ´vk^|ž€ Ŕś4˙ŃHš§":Ă-gnÔÖZ[9flĎ´ÄL ›sZ˘3ÜŇů”MăǏz˖Ú 8hk{8–ŞŞJ@~ӚMk7{ypŇÜGókˇIśŽŻĺ̉ÚZW+Ó˘óYéĘŐŰş*˘˝ŸžŢ–nőĂhZ×Ôż˙?„BÁ'ŔNĎîÚŇ+đ¸Ýnńů|€üŚ5›ÖnZĂ9ťˇ@óÍ}¤9زwćCÎÜH$ťŤ(v¨Łp+ŮÁ}™FzזsčBbĄęęęŸŇÁ@i1¤…Qyyš 0híŚ5Á›ć<š÷Xť!Ůşźs´×˝ŐQ×VťAWg§%v42SČeˇ Ů—{ÔôŽÁJň~ˇ`ÁüąČ<°sŇoů졅‘ßO×@ĄĐÚÍîܲ€“ć:šďhÎcÝl­ÓyP{S:ÝľeŢCçtĽ{+Ó´DűEZFý¸qăž8účŁO]ż~ýí„\ŔÎĹ.‚ě+íhk; ƒÖnvG¸ěœ4ÇŃc'”•Uěă÷{wM$’˝Ľë‹ŢČc‰DÜÍWIlllAƒ ǚ5k¤źź˘e .—5< h%Ź˙?݉Db+‚Á†O>ůdÁűG1ĺ iY_]ś^ą­ŠˆÎF¨ś‚­L][Y%ç] ˇœˇ]ŇšËľ2^^iťźëjç= ëÚş€`z0e_4ĐîÎJ˛œˇł ľÚťˆa‡ź’=}BW†Űö 9÷Ň:˜˛?”lŮÜŮáewkšÇE2\č>ÎŔÉy•Cűv"í¸sęaúUۛ†¸ÝÁ–ęL¸e?q{WGŽóíá °ě}‘m;žÄqÜFаýœŮN"mßف%Ň:Ôrîwhe31Óívu5joŠ˘˝moŞbGksI†­Ťƒ×@çľ.9ťˇŇˇŮL;ĚŚSkť‚-ľ˝ÁŤýLáVúíLA—H抈m˝VŚŰčX{áRz8•ȰŸM˜•)ܒvö;ĽłÓÓ9§)v´öV[S]§űv˜Ţš•žßŢ1d–ěŕXzçV[AWśVˇuk9ug ”mWŚc™öۛŽčĘâ= łdÇۚžŘ^x•)Čęön-§ííÜręLW[më9œŰôýt\mKfy_˛ ێΑ6nwYOAí­‡ĺÚÎm[ŻŃŃql•Mç–óvWˇí=gˇčÉ0ČŐÁ~6ĄW{ű’Ĺq´­3ӝűÉ,îkożŰôt(ԙ.Žl÷Ű;€ŽÉvůśöwXˇ–ÓŽˆ\¸íęÄă:z´-ŮÉűłíČÚaÁ–ÚQP6WلYX=ŻŁ.ŽlnˇuŹ[ydÇéĚzY„Xš“í‚ó=ˇŰíČpKšzŕ>ôŒdÜ×­vt¸eŰŃëgŽ€Qw‡L]§ŤÇĺ*ܲu&t" Řq:TíđP˖ëpËFpPxrjŮň%Ür"čČ_9´œň1ÜJGؐ;yfĽ+„p ČČ+@"Ü@Á"Ü@Á"Ü@Áú˙W ßsßśý‘IENDŽB`‚kolunmi-bazaar-7b9c8e1/screenshots/search.png000066400000000000000000011525521514314607700214100ustar00rootroot00000000000000‰PNG  IHDRˇ…˜í&-tEXtCreation TimeTue 10 Feb 2026 07:58:09 PM CET†L—tEXtSoftwaregnome-screenshotďż>ÔÓIDATxœě˝€%YYţýTݜ:§™žœă6/l`— ’D$(č'†ż"’UT‚‚Á ’…%‡]v—Íqv'ďäÔ9ŢŞžóžşuťşçöôí™ÎýüfkouĺxęœçźÁB!„B!„B)~B!„B!„˛HĄ¸E!„B!„B-ˇ!„B!„BȢ…â!„B!„BY´,qË!„B!„B™/l,`˘pD1‹B!„B!dᲠυ"$QĐ"„B!„BY|ĚťĐ5ߢŇtöOŒB!„B!dp5o"×| FĆ%ΟéýB!„B!„,EfZt˛/qţŒ3ע1 ó!„B!„BČě`ĎÂźe.E#cÓ§ł,!„B!„B™YěiLŸÎ˛3Î\‰EľXSý=Ů4B!„B!„2łÔ"bMő÷dÓf”š‹Ś#bÓXoŞýB!„B!„É™nü,ť†ńZţžQf[ŞEČŞEܢ!„B!„BČě2•ĺŐTăÓźfŒŮˆŚŞ.4m:"ׅŚB!„B!„ÉŠ%^օ„Źéˆ\ł"p͆(4k­éţNśŠŚB!„B!„1j o_â9#Ě´4™Uí÷R.cÇ@!„B!„Bưkœw1‚V-bWľż/?fŽ šN%nU7ŤŹSmű¨a:!„B!„Bc:îˆîŻĺů[ľ‰Tî˛ŢmŐşî”Ě„T‹ľÖÄńÉć™UŚ›UöĂó„B!„B!—F­ä'ŠZî´É,ślÔfͅIţž—jšUŤľÖdOźB–9Éú÷UíoB!„B!„25š\aĘŐhź‚–ńB–=aÝÉ,łf܊ëbĹ­‹ľÖšLĐňŽťlâŻ1Ĺž !„B!„BČô™*ˆźUĺ×+nY¸°Đ5Ů>˝˘ÖDÁŤf.FŞUŘŞEÔrcÂ8pžčĎôɎ…B!„B!„LݍdM÷ŠXđŒ[Ć'š&žfÄMqş–[śju;ô Y>T¸źV[Ő\ !„B!„BČěP-ś–×jŤš°U‚ŁŮL\ž–}MtKœ–›âtÄ­‹ś&Z`ů0^Ôňy9ž@ůwâşč’H!„B!„2TłžňŽhUTCĄü[ň &ĆDŽŇ„mX“ěϘ0~Q׼ĆÜ2&L›*––ŻĘ bVX~ďşëž›víÚ~u4ß ú×X–݈ńnˆ„B!„B!dnąLÓĚç‹'ÓéäÓO?˝˙‘[o˝é8"WśüëŠZŽ$ăŽU—h;ŐDމĺ§eąĎĘÓ]Ž–[^aËľŇň{ĆĺńČ­ˇŢÚř…/|ńuíŻQbV3!„B!„BȂF‰]ý]]Ý_yĂ~ůżîşëŽA5)GĐĄËľŕ*zĆk >_-הbW-âÖTîˆS‹÷ [~ŒšFŸ|ňÉďÜšóľ!„B!„B"ríÝť÷“—_~ůˇŐŸiŒš,şn‹ŽŔUkĐy`šć§+n]ČjŤZl­j–¸ Fz{{ßQ_ßđB!„B!„EÍđđĐZ[[? ǂK\Ť \ŽŤâdV\ŔEXoM%nMÇjŤZ&DWÔrE؊8‰ž „B!„B!dIÉ¤żY__˙a8\ŽŔUÂřŕó3-^˛őÖt‚ľW "ďţíçšźÖ[:pźXlQŘ"„B!„BYZˆŢ#şʉáčA^}ČŤă5%xŚľÇ‰ż¤l‰&ˇäňĆŰŞXm=ţřă/Ą+"!„BČň%ŸĎ#—ËĄP(Ŕ˛,…‹iš…Bƒ „BjAtĽ˙¸ňĘ+˙ă­ł\HţöjJ6Ć YÓΖx!Ë-cšÓ\QËÝŽWÜ ÜrË-ťwďţ}B!„eGąXÄđđ0FFF´¸Eaká#÷Hî•Ü3šwr !„ZýGt 8Ö[ŽŐ–;ç[oM¤ÖižÉÉ¤šĽ–´ŕXlI7Oěôé3omkk{;!„BȲBŹľD !‹Ÿşş:ZqBЉžžžOŻZŐůY5šRCNÜ-ɤ81öÖÄóŔ乡ŞZu]ʏ5Y yoy7ÎVH őŞ§çť–e7ƒB!„,ÄÚghhdéĐĐĐż˙bŁ›BY.˜ŚŃŻž/RŁĂjČÁśź˝™k ,_UܚN@ůjT˝ÎsIźëŽ{n °E!„˛üHĽR K ŢSB!ľ :Đ=÷ÜsŞť&V‹ĺ~ŃL§ËeŞčő“eQôíÜšíB!„e…¸#Jŕx˛´{*÷–˛8)•J•ä.2îĆÁ”D">ŸŻ’LDĆ/•mŰ´tŚÎŠh{~1aú”L&nMĽ˜M&dMLë¨Ĺ­X,ą„B!dY!g˛4‘{Kq‹B"dĽÓéIżĎ"rÉ ˘—,'W4˝$‘+‘Đzl šnt1‚VŐůľXnMŒ˝eL2oⴊ¸ ú×XÖ´39B!„E ­ś–.ꎄ˛¸ČfłH&“ÓZGD0âń8Âá0.żßżăĹ-`r-ɞ0ߎ2Ż*—sËťSďßăbp)aŤ„B!dYáş9Ľď-!„,Ä kşÂ–YWśq1”ő ‰1ś&sOźhf*ÍÉdč2"!„2möî݇Oú38pŕZ[Űđň—żŻyÍŤuLá˙÷˙ôü_ř…—ăMoúmzMY\Č{ţÍoށ§Ÿ~##Ł¨ŻŻĂΝ;őűžcÇB!˹غXaʋlCęĎaÁ5™äՑ.ŮŐϨazľŒˆý$Ý̈2řËC°<Ôçó…A!„Ě1Ňŕ}Ë[ŢŚă xyőŤ ďxÇ˙ÓăřŔ‡đĂţXˇ´4ămo{+^ô˘ŸŤˆ_dirĎ=÷âŤ_ýŢţöˇaűöm˜ äyŰż?^ö˛—2Q™žž>Ě&ňnć3˙„o}ëۓ.󲗽o}ëoĚHP\2ž––BY¸Čwrpp3Iccă´żŠÁ`ŕ:ő3ʆ|y(–‡Ry°ĘƒíůőŔxě˘bn] 3–ΑBšXÄ"k˘°%|ýë˙×˝î5Xą˘cÜôžž~üéŸţšš˙ źë]0Šč!YÂnžůśŞóDťďžťń—ů)˝ąűýß˙]\,CCCřšŸ{‰˙ŮĎ~zI ô×˝î8vě>öą?Ç-ˇÜŒĽĘ ^đ˘ŠőÎ÷ż˙ŞËěŮó4~řQüřÇwÖ$nyďůWžň%Ź]ťćźeŢ˙ţâÜš.Äbq%žpŮ\ďůÄś$ŕík^ó*ÜvŰmhnnŇďňwŢŠîŐ׾E—đöˇ˙ćt6üŕ‡¸ăŽďŕĉ“ę˝3ąyófźöľŻĆ•W^…Ŕ[ßúv}lńY0ÇD!˝ëŻ.†¸łÁLXlUŰf"‘Ŕ4™h45ă\jˇ´Qă4B!dÎWÄjHŹ˜Ă‡OşžXßźăďD-HƒWܟÜa׎KK,•"NŸ> rqˆ°% œ7O„ŻžđçqíľWëż~řĚoyËoh÷ÖoźdöK9WŘńőŻ::ÚuúrŽĺď~ôĎô|¸öíŰWóśżđ…/ᓟü:tX‹¤Á`O>šď{ßń裏‚BYčHďld-–mVë<ž&3Ž%Í´ĺ…-B! ‰ą•JŸd^ë¤ë‰uÔ+^ń ¨…|䏫Zń…ƒZ†ah+.WřşüňË´č!"§˜ë‹‰ýĽ"ÖZ2\*śmë㝫ő+ŽE–XlmŰśľę2b•÷ęWż ˙ůŸ_ÔBX-ńˇŠĹ˘śř~÷w?˙ó?§Żí?ţăgő>żöľ˙ÁUW]…ŮbšÝGBYJ̖ÖĹ0•°%žŇ1űÁžWuäÔëi###ŞnűŘłç)|ď{w\pŰ3§vF?vkš5YL.B!dÁ Á¤Ťą}űvlٲšęźkŽš Ÿ˙üżă-oů˙0ÓH@OqŁzŮË^Ą]Ü~é—^‡˙÷ĎiK˛žžžqŚěŻzŐkńá˙ɸő%NÔk^óËzÝ7żů7´U‰‹¸ŔÉú?ýéݕiďz×{ô´Ďţ ăś3::Š?úŁ÷áöŰ_ áűß˙!–2"hM´â’˜X—]śK_űGy 3Aľ{ \čz‹űŞŹóˇűřýß˙<ű١ŕŔƒ|V„Ÿüä.˝ŢŰŢöŰřűż˙GÜzëóđĽ/ý>úŃOčéâ"YíŘţűż˙K /ˆ+â…xîsoŐżO=ő4jA\P …źĹbúWÄŚ7żůWŐ=ůüÎďüVeYyßűŢ÷+1ü—Ô5~ƒnœ9sś2_„*‰é'ą˙^úŇWŕőŻ#ţúŻ˙N=Ăzž4"¤q!ĂÝwߣˇáž÷‡?Ł-Ĺ^ůĘWŤűď”G;ďxOŸ>ƒwžó=ęYy%~őWwŢůSB!…Bá‚óĽsvďŢ˝x÷ťß§żKňMzĎ{ŢŻ…­ŐŤW]Ňś§A5=颴Ľ™Š–Ka‹BȂCâ]Iđxopxś>ň‘WbWŐŐ9=UÚ…éďţîo°qăĚŇţ˙ř<âń„jĚž™LŸýě?ăŸţé_t晿řE•e/ťl7ޏâňqëčC˘Ů2ˆëäťßýGąc:H,˛Ó§ĎbŊ•8uę”ÚîăÁÂrăÚkŻŃż3éšXZŽ÷ˇžő-%ÖěՖFň,\čYńňĚ3Ďŕ+_ů*ÖŻ_ĆĆ&% źXO˙ŮĎîŻôŘ;v\ÇţAďůĎ– ŽžÄŘş­­NĐójnŞŐžhy˙„}ěú~ýß˙}SWú×­[ŤĘŠ•zŢńăÇńđn<ńÄŐó˝C݃u¸÷ޟŠiďŇË _˙ú˙ŕŻţęSúXEdkhhT=áßWBŐGÎŰďßýÝ?čžsyNDÄzÇ;ޅG}L—M+WŽÄ<¤ëîîžqëÉóŐŰŰŤž›š×­ÓOjÁ‹BČňf*×Á?űł?Qߗú{&— GE{{ťöL¸”mO“ѓf+ üá?ՍJqazéKŤ[Œ˝ůÍoÂmˇ=W âwÇß֖÷Ţ{~ó7߂|ŕ}řöˇżŤ—ýŕ߇UŤVé€ň.ďyĎť´Ű›XtźńoŇÁË% ôúőë0vďŢĽíĄÇ%śŘ}÷= ƒß_wÝľXN\{íľř‡řŒˇĆlRËőŽŻoPbÖż(1+Ž˙žęYqIĽŇÚŇpÓŚ•iëÖ­ÓŐűîť_ *?ú‘“ ô–[nRbn– uu ô÷čŕń“CxéííŤ,_+ď˙iËš{îů™"ÖĂ?ţă?éÄ˙ď˙ýśŔžřĹ/k /qaţĺ_~­^ďoţć﵅ĺ˙ţď7ń+żňÜpĂőhkkÓ÷GD1ŸÄşJÄiąčóňĆ7žAgvţěĎ>Şˇ-ńŰ>řÁ÷ëiŸúÔßęűzâÄ ŐđhŤŹ'ψ”s™LżńżŠŻÇc=ŽĘNB™[R@ůŠ:@%ăíÇ?ţŞăäô÷EhkkŐq,Eດmϡ!„,iÄćȑ#Ú=h``@ť˙=űŮ7Âďw>âvtă7膦Äڙnüi¤z‘XN“!aăéŁý¸Ś<¤§‹T-ÜpĂuúwóćMú8%[M*•ÂtšýöŰ+ăĎ{Ţó´Řrôčq,7ä:666č{!üELœ jšŢ"tšÂ–P볲víÚq–𒗼Hť*Ţyç]Zܡ8a2Ńuą˛k×.í*Y%xüdüä'wV–ŻßőŽwę ‹?ţzčÜu×Ýz~żř‡ ]9„o|ăőŕĺÔ)'!„Ó#~Bťƒž;wNťHyăÍ~*⣋ër|óÍcY6'Ëşę&GˆD"úYqK„.B!d*¤>,IS\$)K °8e"Š[„B–,ßţöwđ§úççMżő֛•h0~ú'?ů×J0ŠŠFë;0žň•/ŐP^büúŻżUť‡IFĹ+ŻźRˇ–8Iľâm›fu noOš4žke9° žŤŽz~ôٟ(ńâáYˇŞ1ńzťbŤ0gĹťž‹¸1~úӟĹý÷? „ÝŁ8yň¤Î"(։K ‰Š'b“—k$.ńůŤ_ýo}˝]Ť¨Š8yň”~”ynşé9zë÷ń1=OpŻýßřËÚ:ϋk!÷w÷i|÷ťßÓ=ŕ×]w¨oĐn„ŐđžßÓÁk‰Ę@ô„2ż,¤€ňň}¸…•$ÔyĎ{ާ˝Ü[Ň9#ÓĢëBÉvźßž…ÂÂ;"B!d†ˇŹjˆk×D$>Ńl¤Kvc<óĚ-VˆČđ/˙ňYüÖoýŚo;oyˇqZ(Ô.L ŽĹٓO>ĽŝqďŢ}U—ýᝀćN°kg|ăĆőXŽĚEÜ­é^ďZŸ•É7ąňMâsŸűźžöâ˙ü‚Źˆ^ "ř˝ěe/Őď­TÄżřĹ˙ŇVn"ž={_ř—đîwżů|‰D˘+k*Äň_ţĺßđŠOý öísŢ!šwŽőœ¸‰ nR ŮžÄč’appH[ŠJϡ ÖsÂÇ?ţçÚ l÷î5ƒťíŸţt,8ü'>ńWÚí°ZůE!„LdŞN“÷ż˙ĂaKÄ,d\Ž÷˝ďC—´íů€–[„B–,“ťt§Kf˜ţçÓNű÷Ô RÉ6'żo{Ű[.)Ĺą+Füŕ?ĐăGÄ -ńtÄęăÇ?ţńyëIđhq‘{ď{? ăkŐjm"YĹMęË_ţŠVŢ×׍ă8U ˘˝oß~źńoÖ˝yŇ~é—^…ĺČ5×8âÖ#<ŞŻG-Đűß˙ĄqńŮÄ˝ń=ďůĂI—ŸîőnjjŹéYš/~ń‹uPůüŕGZ0}ÉK~K‘ˇžU˛šÚřć7ďŔţçőŕEÎ],°D았"Rq—ż/„X€]yĺĺxüń'uP÷––f- ‰X(źň•ŻĐż’ŹBbq‰ĺ˜’â(.§Î6śë_š—"´ýÍßüÖŻß îÉ}Sö¤ Ż{ÝktůűďżűťżŻĎCÄľx<ڟ7B!d*¤>{ĄŹ†R'ٰaƒŞküqĹJKž“"lI`ůŠś˝Đ¨ľ 6΄B–b‘J%UŁuD ^E]q‰euЈE‰XĎäóÜyçÝÚ-I˛ŇHŒ¤ţđG:ËÝ;ßůç­÷Gô.ůN˛ę=ţřăľîo~óŻjë䆇‡đkżö&Ěşżó;ż+Úu  ŐŤWăOţäĂKÎe­V$š¸#Špą˙šÖ‘XX"$şĂTŔé^ďZŸ• qÓMĎVâŚă'Ž—+VŹŔRDzŽĹ"ęSŸúžűÜ[tfDŠp‹ %Áß˙ęŻ>†Ď|ćďu–Cq7Ë›¤a2>ôĄčD҃=<,ńřJZôzç;ߥČ b]%Âöí;€‡zT‹ZŸüä'°mŰÖĘvvîÜŠĹóx@‹q‘HxĘýoذ^űłžu…îA?{öŹś2üřÇ?:.˜čëëĂB@-q]”€îtýď˙ţo@.q%„2ĆBʖ(H¤™ť!–¸űO‡`0 =ŽŇť$Śd’§XJĺÁň śç×.oÂ;Ž ăş%BY˛Üzë­řÉOî:Ďčö۟{޲ňĄöşš‘Ĺ‹X,‰;ŚkšäţNw+§ťîşKť|-ÄľVŹĐDŘK1 ŠžÜWď~ôĎđÁţąNsN!„Ě ) ź ý3-n]J؎ل–[„B–4(S2Ɖ%‹ 1p.żü˛ób+Iü-qqŠÇă dą’ĎçľĹV&“ĹΝŰńž÷źKÇq›/Šĺ™hšE! Ÿl6‹d2‰™@ęÉáđÔîő™ Ë-Š[„B!dV ¸ľ´Ą¸E!‹‰'{Š1eĹbëb­śćBÜZZ9Ą !„BȂĄ–ě“dqÂ{K!‹Ľ.Ĺ;AÖ]¨îˆ.ŒšE!„BfÉ\8Óą>ČÂ`!ځ'„29âN(eˇXpŐúm–˜´"jI莅Ĺ-B!„2+HĽ˜âÖŇdŽÓŔB™D¤’L‡n ůBĄ€RŠTIž$V𞌈`RÎ/Q˅â!„B™$ŠTĽňL–rO™]–B/"Z-t7ĂéBgyB!„2kÄb1Ľď)!„…Ĺ-B!„2křý~ÔŐՁ, ä^Ę=%„Bˇ!„BČŹ".l Bžˆ‘{'÷îˆ„B"ěv!„B!łŽXűÔ××#ŸĎW‚ŘşlÉÂD ťA…)jBYČPÜ"„B!s†ˆ$J!„2“PÜ"„B!„B!‹Š[„B!„B!dŃBq‹B!„B!„,Z(nB!„B!„E Ĺ-B!„B!„˛hĄ¸E!„B!„B-ˇ!„B!„BȢ…â!„B!„BY´PÜ"„B!„B!‹Š[„B!„B!dŃBq‹B!„B!„,Z(nB!„B!„E Ĺ-B!„B!„˛hĄ¸E!„B!„B-ˇ!„B!„BȢ…â!„EEąXDĄP@ŠT҃eY°m„B.Ă0`š&|>Ÿü~6!„,řŐ"„˛ŕ+›Í"ŸĎëqB!3‡t¸B&“ŃbW0D8Öă„BČB†â!„‹+jÉ@!dîđ–ż"pQä"„˛Ą¸E!dA’ËĺN§érH!óŒ\R&GŁQ„B!B! Š[„B"jŃZ‹BŇѐJĽ´ë˘ˆ\„BČB‚â!„E2™Ôąľ!„,<¤ăA\ăń8!„…ç !„,(lBČÂGĘi)Ż !„…Ĺ-B! qE¤°E!‹)ŻĽÜ&„Bˇ!„Ě;¨˜1ś!dqáš'„BćŠ[„Bć‰ÝÂŢBYœHů-ĺ8!„2ŸPÜ"„2ŻHĎżdá"„˛řň›–ˇ„BćŠ[„Bć éígوB7nEB!džđƒB™'.VŘzúé˝řć7ďPżOcxxőőőŘľk'^ţň—bçÎ „2ˇHyFA!„ĚF Ó Ďßî¸éůu_y𗇠jhČç €B™ŔĐĐĐ´zűKĽţń?Ť„­oOşĚË_ţüćož>Ÿ„BćÓ4ŃĐĐB!d"Á`ŕző3¤†‚$=zą<”ĘƒĺlĎŻťÄ;Ž ăZnB™ŠĹâ´ÝX\a+á5Żů%ÜvŰsŃŇҌžž>üä'wá+_ůţď˙îĐËţÖo˝ Óĺř|đüîďţ^ň’Ÿ?oţńă'𖷼]>иăŽ˙ĹLpđŕ!|řĂ‚wžó¸ęŞgB.–žž^|á _ÂC=„ĄŞË´´4áyĎť o|ă0SHy.ĺşßĎć!„š‡1ˇ!„Ě …BaZË;ވްőń˙~ů—_‡+:tălŊúď}ěĎő|¸öî݇‹Á4 üŕ?Ź:ď?ř|ž™ýt677áĆoĐç@!Ë}÷ݏßü͡ă{ßűÁ¤Â–Đ×7€/ůëJű"fšé–ë„BČLAq‹BČź .†ÓAbl bąľmŰÖŞËlßž Ż~őŤôřˇžu.†kŻ˝‰'ÇMŤ„Ÿüä'¸ćšŤ0“´´´ŕw~硰r%Ĺ-BČĹń˙ńyüń˙’ÉtÍëüđ‡?ĆL3ÝrB™)(nB™ŚŰ’ŕń‚¸"^wţž=OăbčččŔ† ëđýŢzřáGTĂ1…ŤŻ/nýĺ_~ň'6nÚţçńŰżý˙*ww÷h×׿üUzřŘÇ>ŃŃQ=ŻŤŤ/xÁ‹ľËŁË<€ˇżýwđ’—ü~őW _ţňW˜‰ŒR•/}éËjř l{|ř‘O}ęřűż˙k46ÖëáţáođÉO~ź2_,¸fŠ[„B㠊[„Bć…éŠ5’Q[˘ľľĽźü0.iœÝvŰ­řń<ŽĄ&.‰×^{ ÂáŚËG>ňç(ŠşĄůˇűIœ9s˙üĎ˙VuŮG}L aÁsžólľě§đć7ż ˙ó?˙‹Ďţ?A!^îşënüÇT/‚Á ślŮŹÄôżĐĂć͛ô´Ů„"|äźc—cťví!„x1 „BĄ¸E!dž˜nŁěĺ/ŠţýĘWž†ýűT]fßžýřęWżŽˇý˛—˝— _ř<üđŁH&“¸óΟâyĎť}RAj"­~ń˙ń˙Š›o~N:wźăńo˙öď „Ká7~ă×'÷‘ü‰śÚ‹-düO˙ô1›Pl#„2_PÜ"„2/Ô*šěÜšżđ /E6›Ăťßý^|á _šsçtęůłgĎé î2=—ËŁŽ.ŽUŤ:q)\ýuH$â:°źˆfĎţóŞ.‰D0008nš—‹Äí’ő›š•ŕöRź˙ý„ˇźĺ×ńo|łęö6oވ˝{÷Ž›śwď>džBźÜzëÍxó›ßXu^.—ĂĄC‡UšřGzq™6›Lˇ\'„Bf ĆÜ"„2/ř|žigÖzë[C[Eýß˙݁Ďţ‹zđ"V’lppď|ç{đ—ůQ444ŕbđűý¸ýöŰńŮĎţ‹v \ťvMŐĺ.ťě2}<_űÚăYĎşBgU” đmmmz~6›Ĺ{ßűŐ˝ŻxĹˑJĽđ“ŸüëׯŤş˝×žöŐJűÖŹYëŽť§OŸÁß˙ý?hqíúëŻ!„xyÝë^‹|žp^ĆÄwźă]ă–űíßţ˝qO•œăbrB™Ř˝B!d^¸˜FŹó[żő6üő_˙%nťí1đëFšX0HšűĎ~öÓÚýFâZ‰Ŕ544„‹ĺç~îú÷/xޤËÜtÓłńú׿_ůĘWńđnĐţ•Ż|Ee~,Ă'>ńQœ9sż÷{€÷˝ďƒhnnÂ?řžŞŰťúęŤđĄ˝wß}/~çw~˙üĎ˙‚_ř…—á×~íM „jüꯞQ—‰DŹću^đ‚Ű1ÓPÜ"„2_5L7<ťăŚç×|ĺÁ_$ T@ Ş7‰ž„BĆ!Ů˙FFڟy°DĐzםލă̈›ß?üĂ߂B–:==˝Úe[2˝ TöĽ3@„-It0“ÔŐŐiŤWB!ÄK0÷ů0ԐWCą<”ĘƒĺlĎŻk’ěDŽq Ĺ-B!ó†ˆP–ea6mŕFkkë¤VR„Bf‰ˇuąnŕ„B–6ˇ!„,iŇ鴎IE!dq‡FA!„Ld.Ä-ĆÜ"„2oHcˆBČâ‡ĺ9!„ů„â!„yCÜXŘ "„Ĺ”ăRžB!óżB„Bći†B!‹)żŮIA!džĄ¸E!d^‘Ţ~Ći!„Ĺ‰”ß´Ú"„2ßđKD!dŢ …Běů'„E†”ŰR~B!ó Ĺ-B! éýƒ „˛đ‘ňšVˇ„B ˇ!„,âń8.BYŕH9-ĺ5!„˛P ¸E!dA! &ş(BČÂDĘg [„B~B! quńů|H§Ó°m„BćɊ(e3clBYˆPÜ"„˛ ‘T @6›Ő!„ůAŹľd`VDB! Š[„B,ҐKiT‰Ŕ•ĎçaY!„Ě.RţJl-ŠZ„Bˇ!„,x\‘K†bąˆBĄ€RФťčşH!¸J9+îŕ2ˆŐŹßĎf!„ĹżZ„BŇŕbŁ‹B!„âÂÖ!„B!„BY´PÜ"„B!„B!‹Š[„B!„B!dŃBq‹B!„B!„,Z(nB!„B!„E Ĺ-B!„B!„˛hĄ¸E!„B!„B-ˇ!„B!„BȢ…â!„B!„BY´PÜ"„B!„B!‹Š[„B!„B!dŃBqk‰cŰ6!dą`ć–™„ĹËLBŠů.3ÉěBqk 2ą˘ÁŠ!d1 oy5W–™„ĹËLBŠů*3ÉÜAqk á}YÝq˲ŞÎ'„…‚ˇrašfeš[fÍVĺƒe&!d1Â2“BjgžĘL2÷PÜZ"¸/§ü‹E”J%=ČßîďÄe !d>ńV&dÜçóU~eđűý•ĘÇLWŸ‡Y:ö§jxČ…aŞ,BȂĹ0a@pěđU(†oAŢ׉`0¨+•Ĺ.ąňQ­Ě<š6pGw ÷ö°ÄB_^5ÖŘ6#„,`|Ş(l Ř^gâ9Íź¤Ý†h~NĘ̞”w‡p°×ęŁyËLBČĆTEa"hĄłÎÂÖV WśçŃKĎx™Ićنé†çowÜôüşƒŻ<řËCP 54äó…@fˇÂ!=fš\Fń4ü#˙3ýCBČbNJ>Ĺş_ƒí_…P(¤{ل‹­xL,3¤lüĺ3y|ýL„˛ŘyU§ďÜÂĆfĽĚěNúđíĂ!`C´8­2sO_„˛y˛7‚ÖčhMe&YXPÜZŕxÓ1ťƒT:ŒěŁXŽLGĢŕEF m˜ -ťlČ<‚˘˙•ăĘEÉČ2ŃÁ[fŢŰ?Éś.XHŘąÎ%,KYúL§đÖËV+C&lĂ[ÎTŮţ=}yźuĽ1­2ó`/t„ĺɁˇvŤ–™{4ˇ î‹UÉސ?ŠĺÄTíà ͡iiAŒi YS´e–4FáXĽ,4Młjecb™š¤Ę†Ş^pűÂËPŹ"„\ ÓÇ'đç ^Ɣ땲ОV™yf„‘K!˓łŁć”őL˛0Ą¸ľČp* {˅jőŔŞÓ`×´! y~Ť}7Ť‰^ĆÔm™%aér°–řn™Ů—7źŤ-Y}ţ•ó 'B™ŒŞ˙Tĺ•w9w~•uĘŰéˏYL…[fŽć)nB–'RţŐZĎ$ Š[‹ˆ1E,‹,‰ľ´˝‚V-,ŁČB˘&‘Ę{hrăeBťeŇiKťT9ß U<źef%KâyË×(jí°úş“­G!¤šiŽgš[¨ťżŢÂ~\Á?‰ČĽć•lLťĚd–D,×Ér€–IŹËL˛đ ¸E$S SލU­-:•ŃË(˛đśKŞMŤZÇ( ]^‘kš[qM‹Z„­ *“ü]uۄRMĘ[p{-]śă ÷‰‹qżj)òšę\ĚťÁ˛…,0(n-2–ƒz|! ʉ˘ÖTżŢuŞm›ycB{Ăë~čmŤ\Țkâ:•M/“śL­.6“Ěq˙{Ţ4{ź˜e_@๸B™ŠŠEVeÂŘt۝oxćM°ęŞÖK2Qŕ*sieć"Ľ–sflVBŚÄ˜Ě­‹ Zm->(n‘Íd–ˇ}yž°%˙.Đ^ěoB悪ą5c1ˇ*ÍۘTŕrÚ=ö­¸ˆ‡jăD-{rąËž°˝óöC!SpžĹ–]ůq zĂłŒ1aŔxwĹq ŔľËĽIÎŮžÔ,¸,ăÉR˘ÖŠŁd Źňî“ene…”̡Ȃb21j˘`užŔUeţÄqwK“폐ŮćüNvcÜ<ŻÇɘxua7DąâŞ6Ÿb×dL"lM&jŸ°ţ¤îЍţ7!„“örLü”*„.ĎŕNŤjň븖UĘ^ű"2áҢ‹,yěŤj”Ë,÷ĄČE ˇČ‚g2aËľ,Ëwm5…=I;vâ8!sĹ8WD×˝p\źQ—Á4ĺôď„ĘĂXŰÇŽ­2BĆs!aK ”‰˘–ˇÎˇäš¸-BŠc‚&öt˜Î´rY_´äŁŕjWśg[Ëšgc*j’J ]“ő-Ëv˛”+3Ć˝žÓIë™ŤŽŞ".2‡PÜ" †juŽÉ„--dŠĽ’d´°=â–}žąEyv•ýTű›Ů`˛ŽúJsĆ0ĘňśÇŠË€ĎWš,ˇľŤ˘iŽßŽWŕ˘őօ˜(fĄŠu–ĺů-Żă ]ă݉bÖ$â Bˆ—ZŹśÜ_=n9Bź‚–­';óÍęWe[ËÄzkBY;•¨e_ AHŐ8;,ËÉRŚJeŃçnP°ĘË“”7UE.VFÉBq‹,8źÂ–wš;”,ťň+mÍRѸôxÉŽZśw˝‰Űf%…Ě#†1fĽáXgéś Ć„.śäš6Ő>żóLűLGwń™ă]7ë ŞřTMŘňL'nçYpaL첍4”!ä|Üď€WԚ`ąu^D{̒KŤ[ćŘoEÇZ†ĘZ„-ݍ5Ąœśíi ]„,5*ú”Ç‚Ëö–MśGěşŒIŹF˝1aËcĹ”Ě ˇČ‚Ć+jM¸ŠEhË­bŃBĄč[–ÇrËŇmQ{\Ěçóę/;ăȜ0Š;˘Gŕ2•`ecB—ľ|JŘňŰŚťÔˆśŞ=ˇŹ7\ˆÉ;“[ÚÔb}ŃĂ÷#ĐJ8BȜá ĐźéÍ7 őŹ9&"p™akœŔeă|÷DW[úœ'lM"jŮż( Yă>ŽšČňŔľĆó1ak,ŽŤgšö|‘Ť<_/†Ě sĹ-˛ 8Ϙö¤˘–´9‹e1+_°‘ËŤqsě@‹ZĆWśěrĄëiżbźĐUmż„Ě&çyŸ lşíĆV—ʢ–ŕóYęYďC1w!%˛Ý5tÉmłŢŰÉřĘ;Ë]‘Óö[,4!sŒ9ЍřáGÚóc ˙â{PŞo+ëY^aŤ\é3ÁŔx÷Ä%ЧLžZز=ÖDAk˘ŕPÜ"ˆó˛śbŹbęöÄVD-Űşź"—QŽĎN(sĆ \ʐ’9€âYPLVw°í1ÁŤ(Z–#le˛Ş_w šVžţp;ÜŮ[ż[ XŞ1íÄ ›™ƒ–Š*˝?"‹ăÂzs=9óedFîŇSB†ź@Ŕm`Uë ŹCÔBšSąŇňŒ[%Ô˙÷Ÿ#pć€~—‚Á ~?‹JY/‰É¨Ă­ŕš[Áw™˛|łž_~˜ĺ@‹Á3űuš4đŚżňl•G*ăËÇJkRjśěr‡Ćxk-ˇě/rٓXs˛řk7w‘Fš~iŒwO, ]F9ţ_Eűş€ŔEČ\Bq‹,8ěJošg€=.˘ăŽäK46ނpÝUˆú°‘†r.“AĄ0sîNň1’Ćx4Y\H%Zž Wœô›‘oźƒƒÂ_ČŔďsÄ,yœlŠöXĹnGMÁ/ČD“PŻ™gŮ1ţđ˙iaK…BŘśm’É$úűű100PٔܧX,żß_i€Ęť,ËZnŒ.Bńŕ–Ë)k|>2ŞNŕÇő<){¤\’ň)yí/83mתÂk‘´L—ŐŹś&śĘą]1ËöÄS´ěąd!ś×š^a˞t߄,:Î+ŞÇ4<‚–i˜şvŠEôrB 'ÎŤGěŞ"pŃz‹Ě%ˇČ‚ÄŽbYîŠZbľ%.‰k˧Ę×Тś×ĘĂŰ3(âĆŃŁGąjŐ*D"LW ІT˜ež4ĆŤYvÉşcń%ëĺr9˝íp8Ź+藂lĎd{ÚćĹóĽJĽpŕŔÔ××căƍçYîěۡO Rƒ¸öÚkľĐč"×_Ž“XÝ`qוk'˘ˆüĘ4M´ĹVĎşEŸóě;ćJ'ZĽç Ź7LʸŢy=•ŒGÔrČÇÜ[YRî™Üďl6Ťď›÷}\Ar˘%!„¸H9!b•”%étzÜt)7DŸ(zšĺŽ[Oň)yőËë-ˇsĂ.[mޏĺů(h–W`ůɅ-K˙m[EuK°KEGč*[ďęńňśŞYqŰ>!‹˜q ž¸c‚–ü˜•– ÓÓ§äÓŻ-Wؒwę<K`Ľ”Ě1ˇČ‚ĄZ'˜kľ%hË-]I)ÇŢąk‰F|ýë_×∈ď}ď{qüřqěßżuuuZđčččЉT‚EüČçóXťv­JŚâąÇÞ={𲗽 ÍÍÍřď˙ţo\uŐUŇCSS“ގ일ĽˆF§ś!ęÉ'ŸÄéÓ§qË-ˇ ŤŤKlGś!â€lG9ć•+W^P“JĽœóč訜vě؁S§Naď޽زe VŹXĄrmd?rmdţΝ;‘H$ôßł…ˆ˝˝˝şÁ!çÓÝÝ­ď‰ËĄC‡ô5lhhŔ˝÷ދŰnť­2O3roϝ;‡őë×ës‘óäžJýÝwߍM›6éAޟ+ě–ĘĎž­„-ŰçXléwÄpĆ'ÖX§˜„ÉŹś,Ťâ–č=זRîËáÇ˫ž_Py¨„r!D¸Š:]Ę˙jL,c¤|r„xůKj,ëYʎ–É`bŹ­ŞÂ–kĽĽÄ,Ť˜W˘VĹ|V!Ť§ŮVÁcľĺÇŞYnŃj‹,&‹łĺ‘7œéşĂÎ hQË „ŕ FÔxPé[A=͜θ<=Żô( sĹ-˛ ą'Ô)ź;"Wůל—dCD›śś6]ŃE#KdéěŮłZôqĹ.ąjmmRÜQFD'ŮćÁƒľ¨%˜X ‰…˜Ě—m‹őP{{{EˆšJܒă’Ć˙‘#G*Ç "Ů#},r>^äšńKćM<Cg@ôésŠMţ–ë.ç=ś=ŒeĆščN|Gœm€LFUłĐ˛K Ć ŁT˜°3„….ŸäC “Џe—ĺąŢ*/¸œz8&–ížřY•_UÇaË*d°:–Âmϊ"ŽW—ŽäË˙ŻZćó;@–"UĘĂ+EÎߌŠl ?Ţ?‚“ÉhyŽú§ę´ËśÇÇŕ˛ÇśGČ\@q‹,(Ü ńăŚUínĹrü­rćÄĽČK^ňmĄ´aĂ-‚\yĺ•ZôąËzD(r]ÚdşX+ՂXx‰ŕ"VC"Žźâݍˆ)˛M׼ѹ˛ľűÄTČş˛=yDôáJDŹ˝čEúŘD€“^i٤Z–u­•&CÎk͚5Z|“ă”óńjóćÍz›rlbŠ%B–Ť,çýŽĺ˜/96˙^řÂęó™čB"ÖXr<"níŢ˝{Ü<9VąZ“{ çăľ^“ű)ÂŁXŐÉ9{ĹJGƒąľ;˘#꺍ăźö‹]îÁg/ŮdŒ5bÎłÚr‰pDĚKuŻ+źî‘.nb 7ž™ćKř¤ëëň@Ţm7éĚ8ěr–D]në-=đş&.E&1÷‹Űjš–]-Ť¨Žb)ŽâËn÷ş%ťp˙žtscٞűĹ-)_ĹJÖugŻśžŹ#ϲw5D •íˆP*żňlyESé‘iŇQá&Z¨öÝrĎ_ŽG„\čâ;=&ýΚ–[ÚŃ_–-ˇ×ŢľŇňZm•+Áâá\V!‡Xxęř¤„É‰‡}(FáJgsŮ:Rf”;YÝoŸ´čšHćŠ[dÁ2ąńîş$Úăć;•őKľ<"d!ЍXcě]€[yw\+ĺÁşĂń6Ş'Žť#7 ĆâŁIŁ­ ęëßş Ůs§‘ď邿žl1)ëTŇUZ(ô÷ŠTsˆ"2xĹ278BłUUH:W ˜qËœźâĽ¸l‹K¸Ä P‰Ĺč ł’,čŁ(ń;ڎ!‰0$Ƣ('PDłÎÎNý<‰…Ź$žĺdyٟ¸Č?ţřăxîsŸŤ…-Éę+ďˆjň,ĘŻŹçş˘‹ő­l_b2Ęśer,ÖR)0—”Ë+ÍlbO‡WŕZv=öŘŻÇ5Q2#ĘP*ćÔ´ółIď91Ÿi¨FťÉLýÉ>u‘€#('‚LćQ,ŮŘšş^˝3“_Óď9‡ľ­qœHăňőč̢ľ>¤çńُý˛v<<Ť{N á×nۈúŘůÖŔę=8xfAż‰Ť66WŚk7_‰_§Ţ)C ŚdRtß9×ZÔp멄̡ȟ3™•Ö„Š•Ćű˜{˘ł`8ÖiB–"Ú"Žĺ‡=AȚĚbb[fŮľm.ˆëރó/â8w×úÉ G^ľţ†&Ň)úáSx3č4Xěb†ÄŠSBGah(`Î`L-"ˆˆľmŰ6íž.ăň]ąKÄ%É*+ą% ĆÖ­[ľ0%“ddË3‰Ĺ( @Ä"k׎]Z°aěňË/ׂؗžô%-ŽIG’ˆY"rÉz˛ŒL“ĺĺW„+ÉÂ+îڒ5V\°Ĺ5]„-Iz"ÉK}ôQŠą3A•ňjŹ—Ŕrˆť5Oo¨íuÍt­ˇ$pźdFŹ’jťľ.Œ§”ŔuN Qń :›"Č-Üľˇ—­kÄţÓĂXŐՂՖ• „Ěę–č–eăé“Ă83ÁŚŽ>wçQ\śśQm׉ °ź& ‡Ç ę,ÜCéBUq+đáOżúŢóʝ㦋E¤­Ţ%ýNšď—śˇĘÖ[n‡+ dnĄ¸E<çyŮâpĽ‹ëv6ţš÷ˆ\öä"šžŢý ńYźTÄE­l‘UvÜSId y˜ţ€SĄS÷ÉP‚‚dă˛ç°á.…$‚ ˇ73ÄůYVE°’ňB’uHFÉ"+–T‚LsłŐöôôhńK„Žţţ~-VÉ3.ϒa’¨CĆeo\CˇÄjKć‰E—TŽŔ%V[bąĺĆx“íĘś$;ŻěSŽĂľÖ˘ĹĘ aO(ˇźÂý2ŠUlůĎsIłŘš8Xş~ţő))ÁKÄŤŐ-1$"~dň%-nÝśť͉NőĽp˘7…qmá5Élżţź8ӟA˙hżtĂZtgP b$S@X‰´g! …×ß´˝#9ŹhŹî#ÁâżöŽ›‘ËO°vtăŘyŢ-ŘnŚDÇjë<×DwœO?™E(n‘‰§óíźé^ë-Ë[—#d‰"•ń‰‚nU‹GƒdÓĂ[ĐxŐňąF’4Č3ŮŹ ˛ŁŁs{}šÓŠÉˇž9÷¤óŁúŁg)Ćq-Š_Vĺ+g8˝;0ËvFFYO°ôß:Ť˜vΡÔzś^żâJ ćËm4ʕuł|ŒśĺlomËV\żíwQkžŕ1ťîf2Ěçsá kŽë΅pę Î5¨L™q&y÷Äfǎ:–Ń3Ď<ƒîîníć%.Vňn‹ű— rOĹKŚ2›/-™Y–ŤŔ~Żľ0ţoOžmB.˛;=ŮűVvIœ˜Őwl} ^dv ¸E4ăÝqž;âTú–+lIŁsž]Šd˙g*K 6*qLćÍ­Ŕ.‹‰)…˘}‡qŽď۸Žíˆ:Ç,q [ƒˆ7J´˛|jAUÜřLmudš!5ŮWވĘ2E5ßl+Űđ9╩>ŠfyžUĐfĎv%#‹Šď˙ĂOdńšŻĺ Gß}Ăšľxőż†Šç" NËJö렘˛1Sť4œgJ_zÝýTyřÜűa;'w‰ąiĐÇf”­ŤĘ‚@ĽJ]Ů˘Ć †aÂę|˜âVœo˝čůŰűKŚIŐx-ç_L˛$ó›Ä3’`Ůâ˘%1†ä–icHp ’™ŽÖ3ä<칲Tž°XSŤ.sRCý°f nZ%ł§úvxƒˇť&îžeţDńŐ×-ËZ0+d*Ş”WËôŢ]Жߵ´ő6ÂůˆréLŤÖ§ÜżHžĚ ˇČ˘ jh Ô˛žźjt `°ŻW§höŽéÚÁÔ˛-W–p——ćśźDő-IcÇUk×"‰hqëBÇ+ŘŔŢł(œ,$şŃáÝEĺ¸ ÇÁ@e9'Ś„3ßÔÖQöŘQ•1Š2Ü÷œ“w}÷œő!Ô­jF(ƅČr8ݝDát™´›7šˆnśVV>eáÜże‘;[€yMlŻŒ8•áV8ĺPDEóĄďéę7™DŐůŐŕWB—VłŐĆ Ő,eŐÁZe! |(–ށXĐ.ĂŠáÉ{Š<ך4ԅÜ]˙Šźú…Xߨu# –Ú rÔú!@íĘŇń–JęXĚP~ŸÓ0,-ʢiąs@.ŹiušqyÔ|˘é‰u˜ümz›Ś!ë¨ýŤ=ůüAřˇÜ˙e/€Y×<ľUČŹ1EŁPŹąž~úiÄb1mľ%â•d‹“÷Fb šďüćç0["YLŘN9'eƒúŹžě:ău8üÓď ;:tɢŇő×_-[śháU‚ż777kÁUbh>}Zϓ@óbmxđŕÁŠĺĄ<ł6lĐËČ3N!$'ŕą ĆšOŮü’2ŒˇÔŇőn=ŮŽš”š‚âYpœ_GťřBR ŰýO=‰üÄGŃuö ĆĽsš›ŘË=QdđNsÇ˝=đ2ͧ-­TšvŁóŽ-"“í—íƇţňŻ+Ö"Ó;„B&Łdë ŚŇÇ.b•ĺ:÷Ž;Ÿ÷|d˙–+NéŢ{cźÉkfšç2fu¤ łœČË­ a;ŤŁľ™ŘÔĐ+†C–ŁU™~ŒʢđÝ"ňĎo@}̏ÜýYŒî´>‘…őĂöŠeŠđǕ ŐčĂšoe‘ż]‰HęŹí¤…şËL¤ŽdhŔPBWöʉş­>D:|úęlZo"*ĄN b9Ԇub|#˝•äC,{Sâ•sP÷PžÍ~ËçˆQŚ˜ŇŠ{ĄŽĎçˆj–í:Qş -–3š†oJÔÓňUY|ô•ł¤Yĺ śéžbAÇ^Ř믔¸5]ĆnE­ŹL§ľ÷E2I#Q+ ˘í–ŽUh5A’–/drœrxýýĆ[ię€?—ĆS?ý šKłö BééččĐą˝˝řÔ§>…úúzmm(íęŐŤő3,ĺĺ›$Ϟ= ˛Č`Y3%^WEŰ#xB.‘qď”GŕŞĚśY%sĹ-˛(ߨŸœ‚jž>y˘Ş°5QŹżýąiZ 0˝ÖOFE'Ň“śÖń#N ¨„tjžqŽ‹Ú§žÂ@Ş2"4™ścéăň–…8ť0ޏć tngɘi×řŹy壾sÓDeËŻź–^(Śu2MDޏĄÎ‡­j;%m`RźD”@g¨ë2„U/m€•É •ś1řŁ ŹsJđJe`6`ÉŔh hĄË>’Fş1ŒŇÓ)˜#Ǖđ´/ł]‰[J@+S˘Ř‹ăw(‘Đ,`ǖ(śnňé;5Rˆŕ÷ÖxĚŞč“ㄸđ”ĘWŮůë뤄(ŰTwßtޏśĘqí÷Ę⑳Œëp(×Ő,_jőżŇŘ=2LqłaŇ'ţ0\MD’’:ŽZ*ŰёĚ=“ĹÂŁľź™îý‹ÓH<[~ńuXwŐMČ€m+pâéG1ŘuÚÓŸ~ˇÎţýű188¨Ĺ-ąqK-°DÔzňÉ'ľĹa[[›.›Ä˛K\öeš]n6DB'c$•)ßOŰcmBšD΋mO쌱Ŕňă;` ™M(n‘%Oľ"^akܲ~GŇži"^Ž`áŹ$šMٲËgęED€ (aŤ!Ü_0€žlhԌŇřýČ]Öט™ĎľsU4Wd2ʖ@Ž`枃+¸U\üLŻUטOŁ+ĐUŚi 4Ë jLŕ[vjK6Óqšq@­Tcވ):žL¸Ĺ‡ÔQľýŹÚ_܏ČUŸEdS…˜ř5uzrĆqI r]vĐD˛+ƒŘî jłĹŒÚΎˆŇ̂j7!uÄď/§ö&ńşôA­Œť÷Ś“}ĐÖÖn"gZîB:Ɨś—3]‹YŢqM”Ĺ-ýŒ8kˆŘĽ­çLçc.×ŐRÇŚď•ĺ¸*j×EËŠ€[Ƙő™C(H‘˘ÖXŽn,Ź€úNÜţŠWáÖç?žx3ú‡3H×%đÂ_ţ˙đ˝ů¤˘Rú;a-”T9Qš†ČuňäI˝Ixŕręԩ󖓘q‚^bą%nľ.k—ś˝lż-öÄŘ?ö˜;b­Éˆ!Ŕöxzxʎ™o(n‘ĽĎ8•ć|ë­J%(ěG8AF5.ÄÍą[2§BÇM‡|r4'Wýź ‚žFrĂ(erŰőb zť’ĆŰ0\ť-ĹR™\y%¸”ŒX¸€)ÁˆKČ[amifçe*żšéWÇ*ƒlŻ`ű•Ć"qŸüĐz‹HPJjŽDË{°+ťŻIŻQőJؑbĹŻĹ-8š‚ë˘x ;bÂ×RłýȞSÇRÇáWBX"ŕÄÖ Şż#>%ú¨ăOČ=ńÁ."×]„óÁŻDą|WćΨŇŃęÚ=KWEĜfćCËqIŐn‡vI[ŻIcRß݊yžcáf—+džśŕBy_FE,4Źňő3\łčˆ}bČ&A‹]–#‚ÁŽ›ˇ/ĆDƒĚ "¸1ŒązІŸ –/ŢŔí>Ÿ_wH‹Ž•ŤđŹŤŻÂŻüưaÇ* ¤ 0 Ǝ›oÕk“:ń˛§N ë™ŽŞ˛îT:‡´*÷­˘篨 ¨˘Űďq‰.ąbŮEČRĽęťŔr™Âm/đ" Š[d™ŕéą+3Ö0P’ƒzZV(q*‹b>ĺ鍰܅+[qć9|řA YCČ&GĆĚpÝ˝ÚvÍ=ű^Œň?{œ§äŤˆT/F•Ŕ•ĘK@ň0BÁBvÉl‘Në>€ —!ŁÎ#•éAH \ą`éě0‚áVÄcm°-SÍO#kVTQ‹[Ň <_ËŃ[ŞÁ58˜Ćš3Iu<ęšřmD"N|Ş@§Ä››PĘŮČF,œŢćC9´4úąúŞ&%ZYŞjńŁ.Cdƒ­”vŞ/ĽŽ1¨ůÇ )Á qmĄ%›uúP’ ‡j˝lÎB*™ŐÂßpžlyW"X9N™Ú˝ĐrÜ>E,”hYZŒŇÁŸĺ*VŐO+WÄđh^]ˀvß4}vŮŃĐFĺń(ßwĂpÝ;•ˆŚD;łěhj”]GÝ',lD¨ŘE[ˇnĹÝwß­ÝžZ[[ľŕ%AšE$•iň{ć̝=‘,/$qˆi×e‚ohlB[{‡*}ČfŇčďëĹŚő¸|ÓZԅMDě"FƒŁ8™ďĆąŢ4şN4ă/ĽQżöjŹż˛×­ ŕĄ~„‡Ď sŚ]'“8ٝĉŃ4’:ÁŰ„Lž4„Ě|—ČƒâYśT„'P_ׂ€ŇQF˛#°l×ňƍgĺ˜M $Dˆ4 Č 3: ,č0Sś7֘Đ2=‘klýŠ{˘v=ô! ÂŻşî#ţ<"á jDĺPČŠ†ŃŔ1lYӀţ=¸lÍf”˛ýΞC$ގ1kĄwčÚ ÄšĚ #“†’]j+*č˝őžZXô#"n#JÔ "UÇŐQ ?jŸF˝’ĐŠ˛#Y<Š„šÍâć›°yg3|Úę̧÷kňĂż3†\Ą„ýóÍĄ-aâ՗Ĺ`•€´Ć@ӕ úúˆŐšĽ­Ńáőź81ťBgąPH\”ÔešeŁ.Ë1jłĆ€‘6"bIü"ůmhhŔČȈľ$‹˘üЍ!ą‹Äš‹V[Ë)ŸƒŞ<ŽÇú; ‡°bĹJíz(e˘ÄXÜóÄŁJx/é„×Üp nšýŮhkiVeLţ¨\{Ťę°Č /]@iÇ&4năĐý_Ĺ3¸Ë_‡D|=ęWnCËÖ+°ćš6­Ěŕcßw÷=:>źXĘńČžĺšÜď–Ě“q‰żĺ"bŹĚ“d ˛ž<ťn˘™'ÁéeÜ{ž‰DŁę{'óegŢť=Ýˇź_y/ŞÁ÷ƒĚÝŚČL"ďrN•V!7.u_>sšÖůÜ2‹ĚŽgƒó™Oř–“%ÍdEl%ć–úIÔ5ŁŢW‡ţáłČ[Ě ĄJvI°EĊŁHRĘ   zŰ%ŽV! ‘r#)ŘšbŮ}̀eÚzťĆyqLk/đ]ĎuŮ˙˜ë“ żĎDP|ä”ç+*ą+R —(ęăMˆE›ąmóÍH čJvٍ„™Ć°_ D+”€×¨Ýä2Vg†OÂVâPAc}ŹE B–gż^—źZĺ}b­PTď3œ,úS§çIT,KżbĐrňtÝ=iŐřT*u‰ˆjĘaUƒĘÉ:8:ZÄžƒiä×+ąěŠ&üę%Ŕť‹¤ŃĽQ]čR1dŇ҂’Ў×,É9ą°´É–ŁLÉśĺ¨M{ě3-š ąÜrR  0ŰPűóëcöůMu/ HĽ ú}ÚMŐ éaéăÓÁéMkĚFKOöĆښŽľ™/ÄKrďŮł§ň.Ó­‹Ô+ĄłšĽM‹ŮbuřЁq’K˘ą7=ď&Źß˛ŽěÚîCP­ÓŁ˝šMYŒ2Řý’Wă쁧1ŇߣýČ ôŁoŕyÚÄcUƇ×!Ń´áŘůÖś+VŹŔŚM›´Ŕtřđa-BĹŐöϝ;‡+ŻźR Q§OŸÖB—ŁdT”ń#GŽčuEź—[Ľ$ŘźŹ/AćeY™'\sÍ5řáˆm۶鬋˛Žë†+ß* V/ű—oWwwˇ“ˆCýíΗ퉘F‹Ě/|ţ.)'ş{z'ąg)g"ŞáRňP˛ĘěXœ–qÜ?2PÜ"ˆjtbJđi7Ťôid­JJă("V߀T1Ľă0I¨´š—5 : ¸YňéŠb1‡áTţLQoKéěy'nŮq]úńB5ˆú‹6ďďRűF´@<B°$ćgěíĆHx-ôBŚ”@sc'ĚÖ0JąBvƒož:|\‰tyÔ)Q뮓űpýęËĆŸaz\0k=rĂ /ĺ#9˝y%mą ‚UP l2ĂT›HȧD.[[](a°ľ%Ś­˝ŠJëBÁR0%şĹ•(ć3őńÔ:Á`YzÓ°F9@łĄE-ĽÓ!â)NÔöŠąĘ.¤’ÁĐЁá+°œłś==˝ĺý‰@×?”ÇŞŐŃJ,.KcIsŠPŇîüĺŔ]:Ë˘ŠW˛ůl­nŮĺc0t@zżÁŠöbrâĽO‰5}} ý|×wŸßíWîƆ]ې—VQ•NY4ýŞ ¨ň.‚*[bí+ąëůŻŔƒ_űW yĎVJJęÓĂĐčŁhiiASSă¸ý i˄իWcÆ :˜üŽ]ťđéOZ‹Q]]]Xťv-6nܨĹ/YVŹ嘼Á×ŢŢŽ…'Éś(‚”¸Ý>üđĂz;7Ýt“ÉDĐĄëůĎžwe[˛ŽgŔŐW_­ĘóˆnđĘ4ůÍľťăŽ;ĐÓÓBČâEƌžŢž‹śdýŃl u‘™i†JY#ĺĚT˘•ˆ÷b}-É4!KŠ[dIs^)O–ÄbÔD$E_śÉ`V ŠdŃ;r%%śČriąj*gˇs„‰ąœ|X~˘ŸáŮąë†6íŘ[÷G÷¸ľ%— á2?ŹĄA9„14F^}°sľĎŐ0ٍ„šR´-ŤŃŮ(Ç}ňăH÷9$‡áˇ čÓÁéáËw-ľä<éËŇŚj¤ŚX31’ĚŁO5ÔÄeĎ0K‡ňJhŤ×fKĄX›‰›Œőu$1ݐ)˘Ľ9ˆPP‚0‡Ô¸:ZŸ# –,K YĂKŽŠX(ę Š0őş%ËÉH(ăľęD%I€h•-´lŤ,h9Q°*ńÎô}p‚ÄŰś#FůŐ~óš’j:–ŽŇ´”@E*i"$1ŘÄĆK,Ŕ*–o†žž%ł¨-ÂńËĐqžĘsAY|ŘŽë2ěIEOíĘ×Ј՛ˇĂ5âôšř˛Ýˆú#z~ÎĘcxtš‘Q'ćcXsŐ­8tĎ÷ŃwúŘůYß*űśÎűވ…•dL—Y×-PŹ\ĺ÷ĉz\2#Ę<‰ 'Ž‹"dIƒOŹ´Ü㕆˘X^‰%–Ě;zô¨śÄ‘Jś!VŒ˛ž[b‘%ې,ŒÇ×"–Ź#Žş˛ź”Őň+bX5Ť6BČâBĘy÷ÇM+ZřçťÎŕíĎ[­˙ţâ}çpůš8ΊşŕĆśNôe ůt؈ŞçÝ}`/ž˘Çű2Řw&‰—]نž‘?ţ¸śÄ’ňjppĎyÎsđ“ŸüD đb•*吔U"ÜË4‰™)HšEq‹Ľ Ĺ-˛äóŽśS#CŞçÉR"–OgÁ+iŤ+KŠůRąźś ŻDfžXeë&qÇsĂ Xîś ÇĹm‚H5­ăŽŻKţŽŐĄŠs L%ÎŐ)‘Ť.ě‡EńUëŠoÂÇş‘člF! ŚTKÉW"’OŻ-š›˘8zŞ„l>Š=[Cˇ´ĺ•9Ξ+PËąĘeéîÍŞŠ†Kčޒ-Ą 5i<ë˛:U!*Š}ČëKŹÄ,%ÄůŐž”Đĺ÷›ZÁóů Ź[“Pżiíć84jĄ.î׹°††sŞÂ’QBVMMŇ@”Ř[J82‚ÚŐ5†~9ËÔÂ%´ 'ÂŚĎôiaĘ 4_žĺk`ŤóEÁP@ťR$˜ˆ^Ş U ZfXť?"ŽŁ"h‰Hh9×Ö2Ť0žÍrĚÜÄŇMĆ%0>­<ҀojjŇeą€‘FşcHî2xßYfL\>\č>ťß›#*ŃéQ .čGŔôé’VŹAGŐ7¨Ou ĽŠęŰŁÄ}ţPxÚł<“űöí;ď›#Çđă˙¸ęˇh˙ţý•qŔŞ?´ćýűűß˙ţyËҸœŒJ˘ž„,j&žĂƏööă˙ťuUeڎÎ;6ŠcJźęU˘ŐÁs)\˝ž^‹UőQlnâPW Ÿ‰+×Öáń#8= ɑŠčl cTŐ§nÝބÉüÚä;00 …xł\Ö­[‡{ď˝WłĹ2U\ąŻ¸â B–ˇČ’Ś"LŘÜüʢUą”ŻdԚ•ý6ǂÇ;ţ…cëz-żÄşÇTUKD ŤœŻ2ßŇń§źËę^ţÚťň)'p•˙/qĽZ:6býƕJ21pć$˘á(šVoAD /#§UďĐV_{ŸčV„:uŽ" É9•Ô˛Aäí<ŹBńPęmS˝d†9ć‚h;™˙KŚÚÜĺe™lÖĆفźę+˘¤ÖNú00hŁ>abď3<6ŒĄd Ă#6V­ )1+Œ|ÁÔ"“ôäĽÓ9œëÎceG\ H!tސ8bš›CUâA{@iBôőgpüdJ7°vu+Őt97qy JƒąX›˜hJćBmrV"äH”Đd—ŐPĂ=sŔtH5ŃxšłýJŒkĐ1ŔlKŹąŠH+eŤ[őJ†cŞQŞ„-ŁŹvZbfIA[,ť<œíŞçĆVűWˇEWŔ˙aa#÷Gzz/ťě2Ź\š=ö˜Ä5LîŸôbťŮĹJE,d¤'™ą…ˆ0Ô׃G~ň}Ě6S‰GS=‹S‹tS/Ë睐Ľ„p“N×l¨ĂŽUqm™ĺ˛ž%‚í+bHç-]WÍ,mąP▸$>wG“^Nj?A5?SŽj™{ a]Ka˝ěd\~ůĺÚ KÜ éhşĺ–[ô7XܦϞ=Ť˙뎝ÎťÖIźAYşPÜ"KGR¨ZáÖńŽ”¸`EZ*KXÎl5Ń9K/m×äZÉÂJĹ1üŚ“P݌^Z2ş”ĆĢ˘ŻvaË9j'˜źWĘŹLӎ…JlIT6ŁÄ!$TyŹąM[;‰xRČ#öĄ­. ŻˆáœŞT4!—Ę"V´'TĽD-™Ďčř™Ěˆł/ŸYËҟiTNł–ă-–,űJąˆŠ† 䢌Şl„Őą5&|NŔő` %&ëÎáéŁHÔEĐŘŔšž<††łŞ§-Ş*'&˘‘žuy:ţ’śš)!ąU]{÷8ӕCwoˇ\×–}•Š%Ԋi9ÖYŽa…ÄĘňi‹*%kÍŇţƒm•çÜŸ>Ńō(d˛°ĐŇ„/¨Î3o öŁN*nś¸úžˆe–QžqÚ QÇÜrŸ0%€ÚcüÉÂEŢ 7Ä5ʗłC‰(*ż2_*űn˘7 !„˛Ôď[ŤęÜéîéŠÔU˝Â–Đ čßpЙóĚoŒŸő0ŽęPqĽ;ýÂUm¨7ƒąůëí76ŽłćraK\ !KŠ[d‰cTţ‰d#nm!_XÉ%äŹ"ʞ…M]°™â(ŠJŒđ~!ѯĎL1‚•×îjT‰E!äŠY=Ý2To”Š>’ęĂíSŠNś˜ŃÂWÔ…DďĘŠe|f;‹R_ =Ö´’†˜Rťî•r&>%R•L'r}"ш°äO_Š *’Š*‡úP ÚĐŰ?ŒÁÔ %ž8ŰioŠiטçşTăÜƍŤÔ9eë6Ť,ĺ1­–cÖ1̊’ɇ-Ô%üTbÔHŞ„d JŃÔŕGß` 'Ďä‘Éš8q:Ť1[ż|÷ÇÝ8r<WżxÎőě?<IŒÓݓĹWż•ĹŽ-źîŁčęÎŕą=i%†´0´ecĹź§2y¤ŹŞŐ &$[džhéăցŕ!Ů# WŤdůľĐĐ1¸,őʘZľ3Ős#Ž›iUt†”@˜/ůTOُ¤Še#A­Y–Q°ďG^<%§¸şŞ Pű*ˆŰĽX˜‰˜h;1èƒ,|DŘÚťwŻŽKl!ąÖ’ŰވĺfˆsłĂ‰ĐE+B!K‘°Ş ­ZՉLډŃ7Ű8WM\,"†I@BČ҆âYhQˆßŔΎ+ĘŕđĐAX!­ą6źtŰËń§żŒĄě°…ę°ŽyÖ5mŔ#§îCĎhˇjŔšŘŢąťÔşžž'Žé,yŤZÖĄľY}܇Fq çi„Ő>śľďB"”Ŕ“gFc˘]Cgśüđ4ŽWÜ#ÍJ˜mťc6JĹŹBVZ€“4|#C¤ŐßvNÍO#­ćgrQÔG8vŚÇĎöĄ3P,äĚ‘Kç4J„ˆFë”PgŔ,'´ËŽzŽKg-‹6Îtčę+"•Q"DT‹đÓ=yuœJ8*šŘš9ŚŽ‚Şh˜hlˆ(Á ˆŚFżž ś,—łđ_>ƒx܉Õ͖JJjůNœTj™:Ř­›Âč*ęřVw˙,‡‡ž(˘ŽÝÄ ßT[ĺG˛& j(*1ÓöŠ!aő[´%†R‰× T*Ićs&„],iůuj7ĽĽ pýéB1‘żňJŕTëDŐ˝9–ňi÷Ĺz%¨Šhћ“@ů~}ĽCł1bh,lä”@Ý(Ű­\— B!dš! ăqZBBˇČ’Ćő řCXYż9%îˆb#"WĚG˘Š Ď[y; ůBŘĐź-Ńx+ë:0ƒXݸιÖĘĽŐúď;‚ë×ÝŹ§=túg:Vwę,śśmÇúŚMÚjŤ`PRâÉ3}ёčD“/ˆLoíîg†Qé łţ0t–Ćb*‰ôč Äb×ÁĐK°ĐĽĽl1HŔ§D%uœů î|b%Ţ•Ztŕđq<~ʤŽš€|2‡ŢĄľ9?ÚWď@\ t–rîä tâ¨Ú°ÖA*™śa)Ýi`H„Žę&šhm20šĘ"¨DŞŃ¤­Ý;KkKşŤ.o@gGCĂ)œ:›Ă𨥅˛lNbůô5Xľ"ŒŽž,†FJ¸ďĄ%€ĺpć\‡3<çúZŐ9§l¤ÔţóƒVÍA˜Ĺ%ł>¨†€ÄŔ*čő˘~\K‰[r하eu ś•Ą|Á‚žˇmŔف"a‡Ť1$î‡J€‹uČXŘÔŰśŐ6ˇ&ŠĺűV@KČÖqśę‚–v{ÔěEőóY̘¸ˆ 5!„,}¤Ź×sB– bu>Ńk„ĹĹ-˛ô)ťŰe•ŕSŇYđl'žVÉFڐ‚%Aĺu0xŸî… J4ýϑşFĎé ÎĆľ[ 8+}ځ_^ŁŠK>!a_#ŮQŻ!ԌŃĚBÁpŮÍŻv 1‹­r„&ËÖqœ f)ľý°ے×Ë*˘Ž"Ŕ +Ń._€‘ĆH}=v Ľa%Ę)ą,V3¨Î*7ˆ@´`áÖÍJľPćQˇë5Ms9DɈ¨ĂT)ÁÇď7”pc(ŃŞˆŢž˘‚ŸˆŤëŁž|ÁÖ.”úŞ.R&›Qbc ń¨ćzJ…"2é$ć§\âU+ČdňˆF ˝ÍĂڝ0Ÿłąnľ“-1śô>WľQó/šľH%î‡:űĄm–Ý3ŐߌĽއŒrÜ65=ŹŽ•ěJžÉúŁ—)XˆŐ6|"fůÇ”$3¤ě­ä^f9ą€ý|‰WŹÜWj[‹o-ďť9Â!dń!ewo_ŸŽťL§ŢFČbŚX*ŞzvL'Đ!dąBq‹,yܸQ†iCÉW:†Vž˜Ó˘TÉ(á‘Sŕ†ľ7ĄPĘáĚĐ ô§{ĐnVڗŒ.hˇĹT.Іí<š”0ôÄ釵ľSG˘C ~Ä1mĽuvř ÖÔ­A<œĐ‚ÉŚśMŘßľ}ɞi N|-7?˘Q x/Ó2J:3RB^ \éhvĄ€b!`؏R&+•TZ•¸*ŚŕSóB˙'@6§3źĄbž`çFąş1ŞöĐä4Öu${ťLžflG¤)(‘'¨J• _‰F%÷¨MĔ0ľjĽ~Ľć¤ł@ksLł¸ůŃÝ=\śĐ ÂgˆŘUDWĎ(Žż*ЧJxěÉQ-j]}yXť.Ęö›ęĂąąeƒZÇĚ")iąJ‚ś×ŠÖÝ$îőUE˘łĘ§ď+•ENűLýk¨űÝ"ĽˇúD@§‰€_{r*ŃĘŇBŸ#jŘ:cI•ˇÁTU”KśŠŸ Ť, Ö،Ě+be×Ńсśś6œ:uJgGloo×٘d@ľ"‚K,.ÉޔL&1<<<'ąH!„ĚR–KFĺúú˛œ째E5ˇČ˛ Ż„ŤÓ甘Ԗ8šBC™d†ű1”:‡l>ÁL?2Ĺ …€'ž8ű0úS}:V—Ź˙t׺“ç´ľ—Äáë›vĽ^î=ˆ’dÔöłCČZ˜JLÎáXßadŐňůbśœ}ą6ńĽâˆXśŢ޸ ÂÉÚÖŻ„ށR…Tţ`QÉ\TâOÔ@J wE+€`>œę…é*Şw*˘Y€éË$żř|HĽŐqZJpk6łœ!˛’ ˛Š˘K&ŤÖÎŘJČ2ľŐUI,ÍJÎ6caɞ¨D­Ś ÚŇJâ‚Ö%ÄÂËŇY×t ”ĐPŻDşb[7†ŕ÷ĺpŽ'‡@ĐŔ†5A€^ŽÂ–ő!œ<[RB—Ą…"Ş|"TiËąX”™+ęlĚ#„Ě.ƒƒƒxúé§Đ×ׇ­[ˇŞzFŁJÔJI˝JŐŠz{zôˇ  :4EÔzţó_€ăǎéuD՟w™'âŘśmŰąbĹ B™(n‘%]ţ§ÇmÇ*Çi08–6%”´ƒ˜g1Ň„v ´Ý‰.ĆXƒC4E%_ȲŞq+ ežŻ`;â˜=kzŒ5eÝJĂŠƒ!Ľe唠’WkäÔy*y V)Šc=Éś FAm§XN“X>ŸJƒ­vOJ}-Ë.xÄŢ*˙-q°$8{Qkł—o"˛Ô¸§Ď$12Z@ťłöJătWV‹JF [Ꞙ’ÝŃÂĐhIMˇpědťvÄ!ć`˝}9ôć‘T"X˙`%4CjŸńÚŻł_[aůœ j;Q5*ąĆ çŮТ–íˆ Ž[¨>1Ÿ~ÉQ„@š!Z޲­qAů%ËŚ­…1'֛sąŕˆ‰"$–ŹŠ #YŘČ}ńJ2î{íZešY)B,?H$0×HĂů˘;L!5!uuuÚK\ϋǎ„ľuîđаŞ{ľŐî† ő7AžbÝđ°zőjœ9sFýŽA}}śُE!łĹ-˛ôŃőŰÓđË[)*vÉvçŔ2%С­q.dîˆmWb`ŮĺqËç —u%኎‹ß˜H5­C.ďĚóŹƏÚ9$FĎ(šÄ‡ŚDÎ%Ď ˆ˘šŽ=ĂǑěĹćWŁA +#ÝĎ`uăJ˜ęĎ ŸCCʉúœTӛëÚľUQĚv⏙^÷¸ňţ€Ú)u 3Ë9ćHČYQÄ-ŮTP)o'ĎŃҔæő%45ĆĐÚjăĚšaœ:“ÇĄŁi –´Ő—č"lI+ą’ʤK:°ü}äĐPÁć !¤2ó*‘ČŁs…7‘ĘÚHӉŚŽÍďS÷ž¤ďŽ×%–\"&şz–DĹ2E¨t„?7Ś—Ľch:––ëĐ ;§ş ľŒTtE”4ÜeÝőĘ×LołöŹ”dţŠö.SÔZžˆČäş*B–---z¨éčhooÓb–ËÚľë@!dn ¸E– 3iŠ,żăB¨ĺ1ĘąËB‡›ňÎý1Ĺçź,iśˆ[cΏ(ŘăöçîËľźŞńhË˙w„7œyžAÄJ˘ÓTşń˘ÁÁGąnŤťOáúđXߓ؈+1\ÁĐn´ ›EKܧś1ŠŹšŁĎŕęu[”8֊}ÇSŰş˛l‰VĺlŁrľhErŞ‘ľbâQ ąÁ‚RşR)G% ř-5řqŽ'‹Tş€ž>Ç*ĘďSÓş“Ú]Żą^Ä0G4lmVë€G ŞWÔ@g‡[ÖÔ| ŮlQőŚůꏆ)1џW‚—ł]J™ĘĄfœ„’!QîgŠ,(ú˹ƥĎ*[ú9çËçjŮÚňM\/ľčej@-^iK,ÓɐX’Ěˆj;"”JoŽĽĆZČ*ťl:ž‹ŽFČ,B†Ĺ‰¸63nßÜ#ĺe>Ÿçj^++VŹŹXó˛˜gŢ 4@7|‚Éҧ,$8ú”Y1w0łdŁ2+–5Ź1FWČ2ĘÖ_Z ˛Ź˛uă{':Ľš&Sv'ëbʎĘBpb`9ë;ŰŮErú)Mń`M‘FD•ĐŐšj3F†´L䲣°ŠJąËĐŠÁR˝ě=„–†XŮ܉ádˇŇdŠ8‡őm*çi••7öV­Č’÷˲ŃŇh ™Q–ÄSŠH8€Śú"Z› <öä î{$­WŞ‹ш€|%›+´‘¨31:ęX:}NœĘŤíšŠxđŃ$NŸ+!4Đ?PĚUJœT‚ŇĘvĽ3ĽÜ8VS㸊JŒ°’ŞČ:Ҥ+@şŽ‚†­ÍÇÔhQŻ~F*n…NÜ,íĘYvU•›˘3*ŠŁŤĺXh•Ô‰™ââč×faZĚŇϐÜK%€Y>n‘ŮĂyÎĚr9vţ;mť>Ĺ ]vNY^ȏ•§´š#sĤďOë]Œ…çdď-™]䚎śśčʎ´Ě%˅@ €şD=YĚPÜ"ˀ˛PQqYsB~ëřH’ŮN” SŮ)•ĄP‚5ÉpŹv* ż1ąŠ$ŞRĐBQĜ€%Ă1ĚQKŻç [^‹­J+ԆWKË/Ú:ČĐÂJ$SÂO m ZóЉ:ˇ¨ý´keĄ)‡í›ŽĎjKŻM—Á'ăÍ6Żť\-çˆ+kŰśŤeü(ŮJ$2Â:(˝U\Ücś+WnjL%ľ4ůU{IZčîGoT @VÉҁXˇn bxTíľOÇĐVW<ˆ†„3J°’ÎÎŹş!Նíěs6Ňśc5uśťˆžA†Ôu>z˛¨—mmöĄÄFc˝őŤ $ ËŐ&§F‹TNX÷ʄň˝ˇ(óڝSĎсŕ—K-zîąLÓϋśĐ˛uy˝€$0M'Ľö{t„OŃÔJZ䲴°f{śGČl!ąc$łŁ<ł:˛ŞÄĘ{žJ§aȸoW$h{:_ţ”RItűPč륰Ef71„dAuEbů[Ţ7Š„,㵎t­­dş›=U–—xKnG’üín_ʃŻ­­}ią5ŻHy)1ő–ƒ¸ľźĽ.Ov~nÇýDŚ˜… Ĺ-˛ 0Ć,lŤ"֘Ś3­(–3J¤˛UÓR"MIâgéDyâŁčs˛ăNě(ŃÁ=^ 0ţźÚlZ‰6Ž›YyW^QKďrÂßľłQÍD ‘ě|z;Ś#ŚHfBŤźÍ ­D*mJTRóΕœĺýFH[Éß>ŔôvřZŚŽdű´ČRR"ŽásŹÖ*Ç9ɰúŃBŽU”Ľryąˆô>óc`ŔRż>œ9›W•zS‰kzGT㠟WçiŠFśc=řQ ‹™"ÄP#°ľ`Ś´1U §ÇrârŠ[#Ž~|ţÄIM ~„fí ^Ë5Ĺ2ËŤXeĄÉ(eśH>}=TQi—ýËt„,Ó,[ôNŚHą,ń™ŽťĽÜł|e´›§ˆ“ꥲ°^Z$u­ż(l‘š`ăƍXľjRŠT%s—^?řáŰşÁ֎ňłhŒ˝C“•Y—2ßí0¸Ĺ؄őĽLŞŰyę/{l%ĆE3IX=@q‹Ě:"<8qBgʋFŁZ¨ҢGOOŽ=ŞE.ů[Ţ)i ž>}ZgŮ‘K‚‡ˇśśę÷ďŤ_ýŞŢŚ[Űśms˛é)Áë™gžŃÓĺ}”íČŻŹ?222HýGĘK–şĐ˜Í嗗¸Ą…ç–*ň͔’ Á˝Żň<÷  ŤŤ§"¨-]ž­^ՉH$B3ˇČŇg|x,8ň‚gśšVˆŞß˘_ G ._´P‡Ěüęà o],ş ĽňĹ\eăF7DwÜśÇÜk>ä˛˜ˆPeGA KUvxs„6Ău!4룟]D)gkńʙahEţó)%((=˞yZŒŃë;‚VQmĎô q†óŤíEVKĽ‘>[U’lÝă)ßÎD‡dR—Úßšžz<ŻEžş¸9‰MڤtĘƨT¸ŞÔ—08di1H$qôŤƒljTËgm<ţT=ýęÔv%ćUŠh9âœÚ΃ŤFG;Ö˘&´…•ikÍĘ ŚoTŽYžn:ޙíˆWň+ 2âjiůôő~XeGȢZ ¨ž­€íŘÜYúJŹ-żzś,mÝ&)4Ĺ]:†ź:vÉxV 0OČě!Šě%Ł—4¸Ľb›Ëĺëőwęč3Ȝ95.‘Ä8Üé'ÎÎlíil Ő÷­łŽ–ŠˆŹX…br}‡"sň$Ĺ-2ëČ;"ďLwwˇn,Ęw\޸D|rc+É4ךË—ĺşşş*۔íɲň•ő\ä˝Öâ—w:™Ä%qšŒËÎJĐś—ü9‹(+ĺ“dú”˛Ś`ǎ˜tůáᤒ)ěÜšcI déCq‹,yœ¸đŢ đFŮpŔŠ|-ßÎ.‹9ĺ% „Ĺô”‚Q,Ż/V8"Ź1PĘĂël8Qźr…-çwĚRŹVĚňzÚĺÍp\$MĂ#6•łđéxaęŕŇ%ŒćsJČrä/ v^ĺF[ůĐ Ł!ĐóÝ6ĽĺŠYp,\Qkljm• 84biK”›\ž€x܏€ęëč,`˙!qC´”¨d¨_[ _ڏ€Ő+hS;<~*‹hŘD4&ÁÉçł´…S8ęC\M)Šů>D‚şú °3ú$PPb¤ˆO Űk=hĂŹXUîuDů°Ç,őQYÎÂpɏ“™0(Ŕ*†°Ô˜Z6ŤÉKhŘX.¨‚ŐÉŔ(ФŠ7g—ƒó;V„ާŤľ,šn‘٧ˇˇW‘2ĘJŞ\RţšäYô Wîߍ+MƼ۝lyE˙=?AŽëŹzď H9TÎ2Jq‹Ě "NM´žö~óE‘ĆäÄébÝ%ĂáÇ+ÓDÜ:{öěyËĘt e ó‹Üš§łÍţýűőŻX뉀ÚŘبÇŝU: ło˖-‹ŢŞęÁ#C¸bmBŞNř­Ç{á+żJíő!ÔGýL3ELŐ {TĽq8]X´â–ˆÚ"bçóyíň'‹ľ¸"‹¨Nâň,.Ęł‰ˆi"”ćócވ}ý}hiiĹŁ<‚ľëÖi!7‘Hčy’1‘Ĺ Ĺ-˛¤ń+AiÝƍ¸ú†gŁWőTŘĺěv^!c"ĺ¸ßc^3žTn uĄÉn[§ź|Eq×-˙Š(śaËVÔ×7 &Ä_Đ_˛ *LŁ-¸*hcńhjrG]¤SËŁN9Ý]ĄĘ˛ĘçälSjU2–˙gc1qPł—čgbA%Ąťęâr% ÚHĽ-CŤ.f"Ł(™R˝tŮźĄ3>ţT§ÎřÎŠ;ىxT JÜęď/`í*ŸśzzĹ} zýœ!”…†zSUÄmQÍďk1u¨ůiTF#ŞÍvÜ8m_Kb”9Y0Kek--,’›˛¤.ƒb~Xž˘łźŢ *qŠ,%pęúŞzJĺ8\b­gš~ńND9=€^Îk%h‡#ň ‚ŮŔuŤb™Ĺ‡˜žĚ-"&‰ ຝÎb•%"Ç:%0ˆeííˇßŽĹąćqăťš‰ #Ú"8ٟÁ‹ŻhŠÔĽ_°ťő!t6…ĐŸ, _p꼍›ĂHçJރÓFX ]2]ʏ+b÷ş×˝§NŇăň–aĺʕZÜr“GĚ6ňË~˘ę™-[#nŢź§OŸÂUW_­­ĘĢĚ%*=˄,bآ"K)Đ×m܌7˙Ö˙CoO×E§âÖÂĐ%Ô/ĺ#&ǨÁrKO^ÓŤPnz\w\÷9˝\ů˙ĺŁs×.k^†“ ăăfY•@ÍUv\śŤd|kŽHž@-+‰‘Ľ„Ë@Du˛E#N/ăđh É´cžT‹+ Ÿ˛ŃÚl˘Š1*ň~öŕ GJęăoŞŢ;G$Ëd Źěđë,ˆýCRęď€ßFB cÔ§÷•J9‚Łˆdú>i7ŔÚz8Ş7të @.SŽqćX‰ÉyűŹ’ž>Ľ^ÚZĎŇ1˛ÄÚË.›[•Š%MŃÖÜ FŻÝOË*ëH\#w\T:ąÄsn“šÖśFŹ „Ě4śYüđž{t=ŹŽNťlÍ&˛AÄ,q_$F’KKK 3AŐaů‚ÝăĎA„-Ął1ʇĽŠ$‡ÖŹYƒů"Ś„*WÜę\ľÖe‰Şë×oĐ˸Ϡ Ďa‹çů#d1Bq‹,i´đĄzL:׎Ĺڍ1_xÓ}O…ańÎ&§ˇn‚U-\ ژć>­ęą:fńżŻĹž.R‡–Ś EŽ"c–НQBWI‰Ea?ԐMÄŁJěę20T0QUš’ż¤D0ń֐´ řrEK}ˆ•¸0j0pr°€Ţ>'ťlC œl˛B6J9`H\Ő~r’z]MóŤŢ°ľ-ëŚě ÓBS˘ţŤ^łTpâ—UŹů”xf-7v=íąëkcĚĽÓ3mÂtâkÁk hLpô4Pô…ÔůDAČLă–;K=ĺ9!K [óƒ4ô%ÓĽ¸ŠŔ¸¤‘ ÚËě;!™š—*ň͗çW÷űŸˆÇąsÇ6t÷ô"—ďz(ńXí󪡌˛f’% Ĺ-˛¤qŹeLmZ.Ă|Uݏ‹ ˝PCS扨%ǚ/äç-›‹{Ýj1›–ůŤ[×á•?÷k8¸őYČä˛ZžoHŸ”0–Ú–Ňéü>ɔ#t™NrB qÝnçCŞ ¤JĐn‚>Ÿ“%1›-)ńĘYNťWÂľ†‚VŒňy8YKŽe]{s'ŽÝp=jAť@‰Jůi<ˇŇš2O'Ë6Ž !dúH-XcŹTB:"v­[;–d„̡ȒƋäwžÓţÖ*`xy>ƒˆNGt‰Eâ¸jǍرń %6Í_g$E$ŠI[HĎĹbτD!„B!ó Ĺ-˛äq…ŒZ‚rfłY<ýôÓ:řăęŐŤu0OIĽ+qd;ââ3<<ŒŽŽ˘YćI@Йf2ÁC2­9rMMMÚ\^RG‹ďźřĚKŒ†”ăkkkĂÁƒőtYV,7$S‹œ—řŕK,IEÜß߯™J€ËKAŽM(ŇC-HŕÔčă”AŽťXŤš÷JŽQb]H ůŰěrڐ}É ÷ť˝˝]gł‘űéŚ˙vSrËu”ű-×Zžy&dy7§X€É˝’ë+™$^†lKÎąłłGŐ÷A2ćČuw﫜—•sĽŐ™ Ü÷‰–„,^Ü@Ô´Ŕœ[2™ŒvIäu'ËŠ/Ô××/ę$„PÜ"ă,’ŮD*4"jˆp$&é"šbHWW.żür-l;vlVÄ­ÉńDÄ­C‡iER÷JĂUŽQŽĺyĎ{ž÷˝ďáMoz“>VD¤ŃFD˜őë×kL–?yň¤ÎĘ#"ĚË_ţrĚ%r<" r=E+•ƒŽ‹tćĚ-É9Š8wĺ•Wb6Ť-7]łkŠ&×Tމ\#ąäÉľńđÉ'ŸÄŠ+ô5<~ü¸—aŐŞUzůÓ§Oc˙ţýZŕ’ ą+6Ęş{÷îŐűQRÄ<ŃvěŘĄÓ@ł"AfyŚĺ˝çóEȅq…`éĐđ Á:‰‹›yx¸`—‡¸ă҉á†@,ÉťŐ÷acK3üfíď ě!_,`_W7ŽŤNžL>ĎŹ‰sŒ\oéŔœÎ5×ËÖ˛|š.9›HÖ皢ŹÎÁąĹƒĽžI|ÔĐPB+ˇń ŰÝťwk -$¤˘*~˛¤Â*bņ ´"B“s‰ô¨<ëYĎŞ4ZĽ&§—)Ż|ĺ+ľx"ÂĚŚM›ĆĽłĄKÖńhóćÍZȑńšFž›nşI÷ŒĘąoܸQ—§X3‰`xÇwŕ…/|Ąślš-¤1#×MŽŁ‹Üg9٧ bU&˘›< RŃásíÚľNœąŐŤőz"š.Ž2OŽťL“gIž#ŮžtnaR ŃĚ' ™ \AިҀaC™1ä;)ß׉q1]Akâ4a˘°%ƒ[O(¨ďÚóˇnÁ뎺 +U‡ţžŠň?ŕ_íö&qóË4‰%yB [˙|˙ýxTuDĺ@ć÷~N‡ď˙íßáǟůěKŮxÇמŽg=˙vĚ&yů/âŔOďšrš?~ŕ~DëëP+R‡ŠŐ BęTR˘xś8lęÇNöĄŁÝڏE.)6ĹËEŒäw>ŞšˇČ˛G*0bĺ$ˆĽ–XáȇYÄ ™çŚŃáHÄD˜pE ŠĚŠ%’ˆ2łm!!•oD’AŽM9ÂW$nđSą’éňˇ+ԉ"ç(˘œ+Ž4ĎCÚ_~DH’ë'B—\;AÄ ÷zżúŐŻŽˆqł…l[DžZkXWn¤ČńşŽ†r.rßĺZN&$;wî÷ˇg„Ě6ň>mÝşU Ź"Њ +ĎŤXĘ3,֝ŇĄŘE–3RŚË ď˚5kt#^žň}—iRÎťßzŠȡĘÍ 'ßTůˆ›ż[ŇáTP߀—íÚĽ-ˇúÔˇśP˛pzpAľ-y՚ă1DÔöűÔ{(_ ąň ­zőIŞ}ŹT˘ŔŐkVc_wŽôö"Š:ÓČŇA‹šE%Yš~1—ä_v’*Ť§Á.•§a›R2Ő¤ Sž _@ç]–ĽUśgVŚIćÙäÎ;ďÔő¤|P˙J=Rž)ňÜËó~ď˝÷ęăÎTŠI}ZŹÝĺýú´ÔYĹB^ęŐb­.^ňŽÉ;%VňR—–°ň=’úč|ÔI ´*QRĎâ’Ď Jf§]ׂŽ1˜‹cŠ[„Ŕq÷“XJňvSçŠ+˘T`ŠĚJĺUŇ@”ĺe\>˛Œ|¨ežˆ1sěSÄ)ŮżT&äW*rĚ҈•ă“ śÎş()1ć˘$9^‰i%ËČ´ůŔ˝vRŠq?ŚRّq9FŠɸˆ_ šç‚Tč¤á#B\kšöîuË-y†YČ{/ĺ’42ÄÚPžSyŽĺš•˜pňţšĎ5!ËŻ­ˆżVš‘çZrÉ|śä]qăpĘ|ׂÚML˘ÝŐ˛%54¨ďŤŒ›Jlȕňş’Q‚ŔéA´Ő%ôßýę;VÓˇEƒň-QűL~Ą0t+^‚(}ç(Ô­RĎ[@UB{€ě¨Ň´ÔóŽcřÜq$6^Żţ ĐECM/dč؆bÉPşWR=?ęيˇ¨ua˘ŻÝ 3ÔŁ~fŠSа%ß yţ%$ƒtŠHĺvśĘs/ß 3á ĹRż”ďŒ„k¸ĽRǖ:žź+2.ďZîAOŠĂRÜ"dqă~̟HJq‹,{\ˇCoEV¤ňęVx]—9™ďZkÉÇŰ ‚.Ó¤kސ ‚4Xĺř䘤r!Ç ÁáÝʃ7  Œ{ƒÔËß"ŘÍg,ŮżŰî x-ż"šBăBBLě]ł|šŢ2îuM”ńš|™ yżöěŮŁcőɸűĚę˜@ę™eŔdB0ÎZ[í.Ţď’÷ť*–Üîˇß}ŸÜw+Łś•SĂ=ę[§„–DMńVI‚ő­[§:lBbÁĽśS§žqŚ73˛­Ă iakH Oœ9AZm-9 uŸóPyCç”pĽęt>őlE[aœV7?Ž`Ă  eJÇPȤá_ľ] Z5äákŰ ;›Fač8üázŮ!Xą6Őc¨ęŁ‘Ě4ۡoזZnRĽ+ޏB‹…Ł<ď>Â}ODĚrë " ťď•ÔévíÚĽ…aA,ŮĽŽ$Ď˝„Ąp; e]Bš(n˘&/Ő˛óUűčǐáş#ş,FK!7žëFéE„Ĺ…ˆÜoŠWd1áş]Kك"!ՑFťX3ˡ´Ö8ˆŢó‚ŒKă]„-‰_óŸ?‚sĂ#¸jÍjÍéu$%ó9üěč1RnŰcÖˇĽ'tŔ.Cž‹hćаEđöç" "÷ł{~ůËA!ËŠ[dÉ#n’†X˛°Řśô Nje5.•…†ćB!D$6€š.\%}iĄG&5ŠP(ŒP$˘ÓwüAÂ٧ăEůuuÄr6Š~íŠP♾ő:Ś) K  Ŕç3k3$ËÄÉCg‘IKđÍJ‚hˇţăěĂŮQe˘íql°Ç/:n|Ě%¨ĚôşR¸mő1´v6#9?&V5FF†púÔ)ŘVÉIkžÍ꾼SÁZXÓA$ŐéŹaúôrRI“Źr!ŐžSšŹ`Xí7˘ŤÍčő%㔭łfÎ摷 XrÝmCä řM´śľŁ}ĺꚮąlŰćoŇBfWŘň1ă!‹ë,żČÂĹ/Iú‘Ůű4ěŚ&řT3ÖԀĐ+^ŽÜ߆/F\ÝűÜ3Ď ´zĽŽą?óOHwv"üď˙{Ă:˜--°%ĄĐ#{÷W_ BYÎPÜ"KŠîßż÷w‹îŽ.'C˜¨ü ŇTŠ:PćŽënDNJU¸b÷.Őô!ŚD•Áţ><|˙O1Đ}Ť×ŹQ‚ÉJĽż”hîD˘Ž ‰X uńÂ!'ŰK*­*–dLôi„\ž¤+"FYt)ŠČ†ąym+L\XȐcüޗďĆýß݃L&ëôŘÁÔÓËÚӘUQŞÄőĄ¤ }ŢĺeőzC˙gVdŽąýë,P"ô)‘Č0 ¸˙Âąnĺu¸ńW(qďÂ×@_~ňƒoâG?ş!őęÚ;}N †’ÉQDÂwýŇ´oY_0S V.RrvF‰WÉ´6ť7Šôôfp:܁ő[ÖĄGݳޞ~¤•ŕešuÝĂ(¨ĺϞíÂńî 恏ĺœMs]ííÍxĂoꛎ_6ĺ5–!Ÿ+¨kâž'pÍÍĎGckťž§­ĚÓŁX˝v-VŽY‡VUW ¨ggdxőęŮrŃő°ƒŒ˛źĄ¸E–<:敯,>‰e’Š$#%XDâ DTkovŽŰ¤Ś0”LŁAU@;W­AźĄgODP5ň6'|ؒČÁ§Dœ§ž;/6rJäĘ.€Œ´ˆ¤˝q wJK{Ë+˛ź:†ŠăŢh×Iق¸ Ş1í.XśşjląpŮsG”¸˘ö“ńŠíšHfŠˆ+量7˘)ݍ×¤ÔšX°ě’ęŽ`°W5Nc4Ż("Ż´ľ / śĽzŠÍ˜w¤QZÂwţ5׏KŞFjMÇ­5"BU@5˜}jżVŁ™r(bp ĽÄ9*á*˜@ŔrĚŰ,K‰f9%ԕLuL†śv“ ž•E8–@(ބŐW݄şC{”0YÄc‡÷Áoľkh›jœéËŠôvméDFÍŠ’ŹĽ)Ž––DCąšůBąśQ4Ť+ :ޚëze bA'süżD#zžXŮÉłć+ťĄˆ5Œ ~@Ď ‡Búř%™UNńNČ| oiT‰…–<Ł"XőőőéçŇu§rĹ/ąp”qŻk˘ŹçZlőööŽsÒżEč"d9"[2¸ß—ÂЊJ„QKU(`Ë{¤Ţšb*Š?$ůž°ţ-Š_$Ş.’,+¤ăě˛ënĹžÇBj°‡÷íÁ5ˇ<]'Oařţ0¨ĘÜM?˙"U}*áäńăčč\ĽËîZ:ň!d9Á(Yňč*ڈbUnœUĽ`dpŔ¸őÄĘ ŐӚÉ•HҎm[wâОGąľ)„+Z|hŰčT˘D1§„Ş´ŞX8–IŢk ŐH,j7Dů;W(˘P´´ë ě70ĆYí\őĘôŁhŐĄűD5} '†Gż˝łŇC§äŰ"dŠS ůPŠ&đԏęÔą™ę8Ľąi:˘žú kR˘Đ¨ˆ7%l)1δľřbŽő‘áúܕ#ŇŰvmǛMĐ}ş…Ě žâÇť2J(,čXdňw߈7ř;člj!ŽT,Ąa ƒŤú3(5Z8 :ŻXi`ËŚMľt œX§NKő^Ťĺę#łڕNV,ŠŕT:…Ěđ0˛Fƒ#ðJ„ĂJ°kĎáěń("ą"ňŁa—K,ĹĚrPyłĆÁLşˆžsŁČ&G‘*ř1œö#_2Ę׼„lÁĆÉžŽ÷ ŤcŐ÷¤UUĘ♚Ô~ňő(­ %ƅÂqŒ*ąqdpůtZťzüĄ€:ţ,t4‡pꏓJItś%°çĐ9ÔĹL$Ô=gżXsc e2¤Si'XŞ 6804.ýŮSçôůŽŒ$Ëë2?°‡ŸĹĂ|gň%sG_o/˘á˛š,"ѨÎ}`ß>„‘yÍŤŃžj%FS9ô<‰SǎâŞëŽC.Ÿg2B™Ĺ-˛´1œřI’L\í|żŠĹ|ŀś˘ …bČeŇHŹŮŒŃd őŞGŹŻˇ'u\ '”č˛'F[ŹŤ[ąjít žÁHj-"á †Ž/9.[Ŕś ˆˇF‘;W‡uŤGqr_Č HjŒĺc´jŹ\‹+ćpÚF˙°i%jeóŽcŁ×âCîC `jČš06’FőŰ?ZÔçź;TÓ×ÁúŸzôQun1íŞh™9uŸ|‡”VĚ  SÇW@K]3śŻmƐŞF#ڛ˜m¤ˇTâ´:|CJ8llhÄĆ ą˘cĽŹ=îŞĆ$‚…2?Pä"daCakyqôţ‡Đú‰OâÔĺWŔżc;n|ŰŻŁ.‘@tăz„ăťŃÜކo~ńŤŞî9ˆĆş(N8%|ą,'„ńPÜ"Km}¤-j” UČ9ńD|*Q4 Nś@őw]źA%r‰Ą˜zŘ÷4†T%"ä3qĹş<÷Y›°yU⁌Ě#:ň F:ˇbŔ6W*‹ÄžĘ•3‹™>qQËémëLd%qO,Ą(ÖXVcMÇí¸BÇW‹ ”–‹^ć7ühQ={+ëâHÄâ8Ž„¸#§O˘>ÇÖuœĚ‚jŸáCĐďʕ+QËő ᤚ‘Č äŒ;҅í[¸'UÇŤ3}ĚZŞ+i‘N,Ćją5*Š…%Č{^‚ĐŤs-”­śźÁŐuúsĂÔŽœV9p•ĺ7SçX´•č(×1ŹîAF GÇNĄžŽƒC)}uőȧKhŽ‹¨t řˆXŃů%p˝kVF‘9T˘eV Oł‡:O%R>ôđýřĆ˙ý7zű{ŃÔ؄x<'ö<ŠçÜx .ß}ůyYŒY¸ f6œ YXxĺG§ŞbÁ ŹŁĎŔŢľ ‡P’}ŤgâÜž~ÜřÜçâżňZ{‘yƒŞă|Ś:—ÜŽććFv’% Ĺ-˛¤ŤŠx} ZWŠJAzNE.“TÂDĄXÖmž=ÝÝčęďC4ŇÖ[â^¨ăeŠÎJĽlm\ՌÖ­çŠđ ö¨ž˛˛)%¤œ9ŒžĄQ˜>2ůźŇ…”Păs‹‹•Ržč¸#Š âW˝rv9ŽU-ŘĺFůŸe;Ě}Jj‹ŃŽ>L>ŸÝ;vé¸^›Ë*9ń˛Ň™{ü<šg?Ž˝öZźäE?‚mŕŠ}‡Ńßö8RÝäŇ͐.Ŕ„ż+SślȧÎśŒ­śd˙ŃP@ŸĄłŽiŠam‹˝Ł%ôô…ź­;Épn*qK¸°_ k@^M7ŐaŻŞ ŞŽ˝Ä+Ş“M‹p•S˝ĚJąÉŠkZRË*ńN Y~CýšXŞ­Ý *‚á°jŒK%Ϙ˝ľXąœ>sZ÷´;–yiœ:sJ ŁZÜJĽ“xć™CHŢp“ś‚a\-˛ĐpŹ'J˛<żbš%lipŽŽęiňˇZ"f™ĺ¤Ž!äâéíí=ď=ĆŃŁGÇYs‘ĺƒ”ˇRÖĆâ1]s畗kë ×^ţţŹŻŕŠ=OĄ­ąŐš)ńˇr…’~Žę›ZpîÜ9ŹXądq!÷ýĉS­LÂŞUhjjĐ ăäÉӘi†‡GTu” J‹,5(n‘%|LN~CżÎ’(ޘ9ÔÇCXˇś Ą ‰úD=Jř Ťe=ů ůÓ8vЏLJâsÔńçrFFŔ.K2ޜ& ÁÇ1˜3PR˘ÓîMhމ•Ő0ęŁęZXЙĽ! útě°ś:v4„ać`ÄX "8’ÇÉă‡iL¨íŘčÎ"ŤŽgLÝĽĄXĘŁ!*ŖΆTĂ\ŤeAŹlë@ßH­ő­ę7aśpţĄP1őĚ´ˇľé Ż"˘śˇľëŢ÷ŽŽnmągƒŇYxHƒhDUjĺ׾Âr]ĄDĐňşEÉóîĆsq] !‡+bLDŢGąœ¤xź|‘„CMMMˆĹ8rř0zOŸA|ç帏š÷íC<ŕÇú­[¨K ›É 212šÄ°?6nÚ˛řU÷O„-)zčmE}ó͡*ą˛ Ž5žŒ{9x𚛛ŃŇŇŞ„ňíE°ző]včdF:ˆUś´ÔËIĄPČëzŤ¸ˇŽ\šR{HŚoϚšj‹LČbâYŇŘŞĎŚGí…?ŔŞ5›ĐÚŃŠc[=°Ÿ¸Ť6nC´Ľ ÃýŞňpěx=ÖďxĐƆMÍ'â(fU#ŻäSâVÁHţ`A5üJčŐ‰°ŞxHP7Ő`(aFbXI ¨ŹŞ´$UŁQÜ­Ĺ-GVQʤ^RŸž`É „¸L_7’-ő°ňY˝˝˘Ú‡?$ĚKh¨kB$š@Tý}ÍÖ˰}ŐzŐ´:wŮ^Kk žýœM¸ůş¸ď§ÇđýďŽGŠ zˆŠcRše—EŰɖX‹˝ŮÚőëńě[nĹÉÓgu Š Eă>%zÔ5K#5đ—tʈXŔ§Žš„Śş šŰ‚J4Q‚aŁ:Ć~%ëŔ–˜TžÓ_ĆDę|•˜Ř?’ÁĄ“}ę^JCA‰yęÚçó4#ęƒßŽH¤Áh—Â8QĘśÇÜ4M'îYJ„Quڕ vŰ-ˇĄsĺ*-„”ŔMDđĂ˙XoA„‰Ă&q‹üţ@ůžTźČźrĄŘYbĄE™=Ş Ä:Ó2ß˝e‰ű<Ź\9fyŐžb…Ş{nRuŠ¤î„˝öŮĎQőşhĹÂF,ýVŹXŠë&mރÍݎޒ“Ť‡,2ÇRóńÇÓ1c››°˙~ěŢ˝[Őóş3¸PűVKňřńăZĐŃJDqśîťďgččXĄś—Vӆu§ˇĽňźČ˛’ČIęŹ"˘I(‚ŽŽŽĘ6Óé Ĺ-˛ä ¸E–4":řToˆX‰ĺ_},ŹRQUręWőnTß{­+ÓÜtrőmXšn+ę:Ń…–¨č#( „P¤ÁFąQU‘čkaÉV╸âÉGHDŠ`ˆďź|ŹÄNúbęÄÚĘŹąÖá 㮝ËÖ_ňÂÚŞ˛ÓŐu%ěč̏jAqĎłsi¤šZ‘=ۋî{îBśŤG[‹0ęwďBëőφ ¨sŔÎ Jt öŁ0Œ‡~ć+;#–÷+ĺľÂUť•FOOö>˝WŹŐiăDĎşMéE&gau[=ž{ÍíŚYR×?‰be[ÖŠc8qěŒˆƒTŻS)aÂĐf^! ПPźŤ:B:ŘHŃŔh:‡\)ŒáŹ…muJ´+"/‚_ďu}[10:Š~ŐuI”ëË5čę>‹Q%ÖI%cÍŞľˆFcJP,9.\ęYIŤÔŐŤÖčëćóűpęÜ)=żW ˝ýÝڒnËŚ-ęœÔs(Š]c8V>É<`”3¸B6n2˛tůĆŔľxľ1ąCĹQUďPuKUż‰‡˘č@ośń`[ýëńĚŕIŘŞŸ3aDq˘t Ż*˝w&DޘĂÚp;2vélmƎ(-š€Ó_ťv>÷š×!DŽ˝öúĘ<ý˝VíťÜ)ŽăźJ{F:ŤUŮ Ą/N:‰Ë/ż\ť;Kě>˝$•ÄíJĽR•}%“†śę‘Íft}vě dŠAq‹,i¤Ç"‰#ŠÁV•€LrXk ŁCƒ:4S(A>Ťz;űŃÜš 'Ŕú­aŒ¤%ž“Ž€lXâI‘U‚FFU<ęŃJ`MëJ%Ȩml%ޤ”pSÔ╡c>Ů匇ĐńťDě*hŤ¨Ú-ˇÜ ŽŤ ŐÇÉ6U!`ő!SŇö<üťű§čL´ še%Zw\[}¸N9†3ßý V?†í×^…h8Šăk­[›Ă[ŢzRňzôťktoĽ-Ό˛K¤UsŒ°žž^ěŰwP‹=!żŠĎůToCÉ,b?ăźŕç^Ÿú`ň%ö°ÔyĽń9×˝Yý]Hű/.~€-.EUHj—ˆz.t6Mu.ápŤ×ŹÖn‡‡>ƒx,Ą+­Í­x葇ĐŢÚŚŽşú:}Żä7QGFŸ›ĎćłJUףë$âѸŽXĕh'Bćoƒy2‘‹ jBf÷˝óžgŢw‘ďßňáĆȕ'$ěEE”P´Šşž'Ą6Ĺ× IŁ`—PAęŞ3`úą#¸Q#Œk‚ťPŸ¨SWFwJćüyÄÍČâ ^ŐťťQę÷˙ŞNҁŢŒJę‰R.Čx߀^^,iKˆu–ÔUŰŰ;ô ˆ¨5‘ŚŚć î_öáĆö"d)Aq‹,ič,“NjQŤuĹZlťć6d3JŔŔ-‚ŘV #˝č9sm.ƒ ăřá=čX˝ýCíC´ŕÇʈ OU>$ëŸaoňă†6úńĐpBőžĹ”XćCAb@ŮNyۉIŻ3ܸ.†5gK4 ';˘1ÖĂ"Qľl[21`Аí‚V'˘_ä%–ěۡOŰ~ř•'ÖjNđčrJŔFmk:ęĚʖ”čUƒŰoëĂß[číŰş÷pŹ‚][E[,â‚JH׊HČD˙`R OyԇýزşĎžör%ú4ŞůYXÉ^”ú“xęą˝xě‰cČçŠ8Ý=ŠQľlK܇ĆH˝=ƒČŤKY 5’ÂýpŞ/ÁtFgˆČXŘž*Ą?Îf؇†HV I6‡ÓęžNĎ2EŽs:Â‘c‡ľËa"‘@sS˘ęúÜřœäfŕÉ'žŔ˝?ť>ö¨ś<{ŮK^Ž›nx††‡t\"é ‹E#XŃŃĄž‘‚Ž ˆ%—iúteDŚ>{ÍJ•ŔŻAuŽšL 0Ł"™܌¨î8!dö™Ě-QŢEž‡Ë‹öHKe\ŐŘP6 GÂďdˋůŁ•ů Ÿ'܂ßo;ë‡ĺŽ2śčRݰa­î@uâ[š:[b{{kĺŰźrE‡5MhžŁŁ]ÍkÇĽ"ۖ¤H+WśÓr‹,IX’%ˆ uŞŁmíVD›Vbŕ ( %ţ„ŠoĆPrJŰ÷ŔĐšůJÇşËFc} FĎ ŸB$B›żRHg䷀DK^ő¸řĄaěëـPűzíÎ&@Nü qíóUŽi‰[ZsʧJjÜ4œ^œ+ą{×eɎŞé†ŠÄMöˇaű:´Ťs=”TÉ\ZÇΒus% ń8Öo؂u6+Á숎 –Ďç´őPą˜ÖvaŚś8łŤ1ĂíMŽM(wĂT&­3Ş…ë‚čęÖÇľcCnťb˛É<ô3ô;ŽŃ“§Ao˛ „ŽŹÎ”˜ÉqôĚÚv´ŕÔ@‡ű ŘߓÂÚć Rjݓ})ôŒäWς¸&ľ€vŐĆf%ęĹԇ:†ĆśfŹ‹Ĺ+ć0äÚĽłI<çćgŁMő I|ŹýűčĚUr}zş{tœƒ‘ŃdsíŇúđŁăôéSxţíĎÇĘÎN=ţĽŻ~ +:WčŘkV­Á•W^П=IŮ-ńęę¸ĺÖ[”p׍Ÿƒá‘!´´ľ€šD*Ô :nKKK‹~gĹÍ֍ű#q=ؚŮAŢ=7ЃK}}˝jÔ6âäɓ|÷1Ďý˙~Ďţĺ×Oš\T=ÝÝݘM^÷ńż@)ŸŸršHâŇb”’KC‚ŔŻ_żśüŢş3ԋÔĂQŤmËg? Q@–*ˇČ’F‚€ˇvŹĆ5Ďy!Z:4Œ+ŤÄ”<ŇŁƒv‚/Fb XťýZôwÖëtŸ<‚PDgYŐčÇŞ†8ZŁ˜ĹaXĽRů ĚÔ0Šš8óX†ťÂŢúÔŻÚÓç×nrňĄK|ćŲŠPt>^ľ`—šËŻĎôU\GS#8yć ˘u1í6§öéî‹Fâčܰ Żźův<|˙ŁřJ¸o°ĂŞąšWűݸj-6ď|üą°ę TÇdą˙@ž€…OýmŘÉţçĂé:#•51ŠsŹXÄ`:ĽU!¨D˘őá੠>Ś„Ŕ6Çđg ˆ¨ëRÇ/CQ]+)ˆ’ęXc!ÉÜXBfԇLލ>ŔA%b ŠkčG(hŤAZ‰s†j ;îŸGş28ݗÁĘŚ "Šv_ő|4vŹĂtĐąľşÎá؉ăhmnÖâ–kÖŽŐÁ6Muúj-6nÝş ÷ţěŹî\l!ƒűĎCSC“Ž lŮş7Ţx#úúúuoX6“ĹŞUŤ°úŚU¸çî{`)Pz6¨žš}{÷ëěH`G=™c¤,ëÄL&Ł˙–„N–Ž˜şÎž=Ť…/BČĚ"Éőë×ë÷lďŢ˝•ébqĂ 7஻î‰'@"üOeYçSő€ˆŚBś’ŻAxş‚ѨRѢS.'‰Ž@AuÁ07ˇB:˛ĆOńĆá"dąCq‹,iÄő°ŠuÖmŢ­Í~ÓJؒĄ÷Ô%>Œ"Ąže% š Ně{v!$îzjz@öĂÃ(™EäŒ lżíˆ*Ś2Qœ9=ˆ˝űşq왾ţ(†ŽďEŹľ–-2‘ĽEqU´KJâJčŤýuÓ˘’XRiGËąŞRŰ=qň,žňă¸ńŚŤąuăz°\––L:uőMxÁ~ ‰ĄQř“6vÚ'đp.‹3vĎŰźWnߌS´)ľ”h´Ÿűçľ(%W@˘v•ěň~PɛXsÜ-mCŚ ¨ŐEŕRÚRJĚÉŤăĚĐÜGPÍŹSB[{ԏьZŘŻŽ‹ uMăPb–Şř§ÓjِĄ@M <чžĄźúçôľˆWOŸvőłtc!™+`ĎIq;MbŕěqÄę§gś-ç—Íĺ•8W@:“Ö([ŰZŃŘÔ¨Äöíú:‹Y8Ć*%l‰ŕ×ŇЊœIo˝éVPýęőˆEbč.őhwÄÝWěÖnĽŚ:Ç]—íRĎŇŠV AUůŐ˘§qąÁ™äyk­žž>ýˇźGRV:)Ă „Ě<"Ž<ńÄçM?zô¨śÚŤI˛0aăŸ,učM– ˇČ’FĘęa%J;}}gNŠá8FúÎ —M9ą 9U…R‘tjçŽ> 3@óŠőZ ĐBW}‹ę+)ń'‡BÉĆHVDŚ~Üýx2ƒ#hđYÚ gt  كýđGbZ ąĘY÷Ä=ĐVFŤTŞ9ݡnhŞj ”ő˙ ™,Ží=ŒPĐDkc#ÚÚZ VĚőuőşňŐřŹÝŘ|ĹUČ Čz~Ü>8€ÂĘvl~öÍhXÝŠÎ˙(ÎôÖaÝJnť%…öÖgđÍoŕńŽVçfjIËÔŃ˝ÄĚWłĺ–“ŐĹDCԇ¸Żl3€l^ŽĄ¨…Ŕ>g7âąžzŕAěHŽ(Đ´‘OŃŇäG"SD!PÔ%ü°Ňy4DLäJíZŠf!Ś~;#čĘŞóŞă•ě1Ś‚zȆiC몾…ڍ]śŻv°műV\}ÍUJÄJăČ3G024‚uëÖęÝO=ą=ô°Ľ$V™ô´K`yYď†ënp*ęBuőviÓq‰że)!/™Ję ô2íç_ü"Ô×7hë­ÎŐ+qöT™käYü˙Ů;;ŽęüóúŰŢw%­V˝X˛%Ë–Ü nŕ ŚwH !! ů'!ô$$$¤I ”zÇtlƒ nؖeْ­ŢŰöžűú›˙ýîĚ};űöíî[i%m9?űé͛zgvćΚß=ç\ ý‚ œ{ 5 u‡PžAÂěäç?˙ůyŻs[ZZtA„9Žˆ[Â܆9§bĂh=zÝ' Żë$bƒ˝ČpT†Ă…ÂJ|J#¤ÄˆŇÚ˝I2WâK¨V•‚’LĽp€Ţ Ą. vöâŠ=íŘwr@VX%`lĕašUBY*9 _8˘óMQěŃÂ]€9aâO¸šwD%Ÿö ¨ýśŸ<…ŽŽN%nŐş9ˇč˜QÇŁćúk0đÄn%zĽŃ?ƒUBYE)RJK¤("­DÖwH•Ľ ŽKaĺʓřŔž ÚUĽ…$“\NY‹+1C÷ƒ~’śÝ)ř"%t”<ćĂkVáÍozę•Âî§śÂÎú ŤóP׏L•-”Č ˘DŞ%KęQŐPŻ–3ôpƒJ઎ZVËjߑC]‘OýýlŰéIeIcÜż Ýľ Ôß;ƒ…KÖ˘Xx”””˘J „Ë9˝ˇFÄ¸É &”çľ ˆÇëQ×dp8?‹†šř#%T ŐӈĹ}JčĘŞučŃŚö­4ŞŠˆő Ո¨sčíĆţśV5–˘Łwm})T(ĄŹD bĂń´cô¨kĎM),ąĚQuœŁťpŕÔ~,yŃ[€knCąĐ>˘WÝÁƒ‡´YRZ˘Ăcń˜ş_˛8Ľ„Ät:…E !ŞDКŞZ´u´éFsZŘS÷Lieššęœ 4~ ĐכÔ^`''Q­D݁Á~ô÷ äB@á\Ą=,EŘ„Y\s…™Pçž~6{čĐ!Ô×׍ÎЕ:/Ĺş-[śčůЃ"ŹXąkÖŹŃëwuuáÉ'ŸÔbŁ­[ˇęÁœÎÄmÇqšÂďsć'ĽŔŐÚڊ˘Ëő(vń¸_|ąŮxźîîn˝=úĄŕÄĺ<EĄŒâףčĜ’\禛nŇĺ˘8Ćý );žËyźn¸A/#Ď?˙ź>6E:ËÁőůYż~˝ęˆ]‚§Ÿ~§NŇ‚‡ŕ5á~y šÎPžךâŠ+đ裏ęQ i’ŤŻž‚ L?"n sŽJ7Ôׅîśc:T0֞9™´”ĐĹĐÁŒ.zZƒ/˙ňşfX~% Ľ“j~ˆ+ƒ RŽ„F{\ ĂI홣…%%ŹpŰxŇBZ‰N!ť}íÇ­ŞW˘_KSztŠZŮŹ›ž8cŐ6IÝ]ą)g—dKáKŽ@mi5ʘ`bx _ě=;y길ÂŐ*ł•ŘsRŠdAř4 bAşÚ÷bAŮăXťâĘ"–+‚agtF–ŐçŽđčĂÔ<<|Q]×p0¤Ă=;z†őźŇŞXŃz$‡|ęÚ)J•™ŁĆ3”ččOޞťpCęr;ÔŚ˝íŞŞ*їH!ŠÖ` §ë˛ ¨uRJ úmőaž.†%Z¨Ž #­~“Ă(ńú9Rn˘J|ëíďQFPľőuĘčY¨Î!ٌŹA  cőŞŐęŢ áŕ!eYŽ€OÄqřč4/jĆÚŐkuš9A˝ę¤1×Đ؀ĄěÝľWÝ'=°@y%ĹS ]ÝÎßY/Â9DT!÷œ Â9cí’2ÔF*u*šTeŁB>Őç™u:ZӐGuřŠN<Ú ™´˛S´ËŇD•}”pźÔýĘîaŚ/Ź:őTë-“ňë~OŚ^MŠÎÉ _wŞęu•u—Rö–6 ÔtKC§ íKŠWô@˘ŘDńˆ{8Ę'íÚDF´ĄwĹ'ŠC(Vq nGÁ‡ërŸĽ(Q2Q<żi;S˘ˇŮŢ˝{ľXÄm(4QD˘HEo,§ƒŃҢ“IŇĎă]pÁşÜˇă{żš S¤Ł÷Őâŋőń™j‚ĹíYîýű÷k//NS ăúŽËß .Ôeaů)ˆQŘâ1XvţfŮjkkő6üÍňđ7ŻŻ%÷ËcS„azqK˜Óđ…–Ns¨űJœĐŢV̇ĽĂÚ˛Úó‰/›T2¸"Ň%Ź4´(Ł#ʌ‡°ö¸ŇY¨‚QT.XŚ˝°şNFB­OŻ!-h(Ą&–⨅q$NRâV"•uj]K‡ *Fí‡ë˙¸ŃcH{PYŽQcrnÁV/ÇtŞJ*PY^˘GaĚdSĘ@˘ą0¤zĄř˛]‚ú5ë`×Ö)A-¨Í'ă8~ä Ź[ŢŞÄeöXśť_' Ńr{Ńŕ ^N*yäFiœ nĂĐÁ¤ş~Ʉ­ŽşÉ´Ţ>TRŠĹ2[ Oeęz†­ bV1ۏ¤˛Đ†K”8 âh[ %ŠŐV–ŠsSĆAßbʈ GÂ(-SŁ} "ęďĹÜW1UŔ%V˛œCŮ ŽeĂhH ŠżőÔÄ-K]ÆúFmuž:ŐŞ÷MC…žW=ť{pхjĂc׎ÝŘžýiíuUUYĽĎz!E0u ŠkßŰۇSްˇ§ÇŔ”ĹIAłžŽ^2ëÖ] ö9ˆţž~u­”! 8×W´áC#›=ĚlhđšgŁŔ˛1Ţ,3˜v#ŠyĹ1ŽĎú“nĂFˇ'|.¸\Ä4Aďâ}ĆLĂŘ4…šĹüu=bü›+;i0q%Z%ŠVőmEŠŽƒAd˔é0ěCźŐ‡ţNŻDYmÉ5ŻGŮ ŃŹęHő!Qľ )ľNX `)”TYč|>ŒhĽƒĂjYXŮbíʲ*ĽýŞěşĘ(N—7ŽúM-/ ôrýő×c: 7”7Œď+Ši§‹ˇ\¤č-fÂ)0†D(\yńž7Ď9˙ź'‚B=ľÂEŒŚ)™!â–0çŃ#üp´[ GˇQF‘kxxP{kŃŔ¤ŘęC0RŞ˧††á…•QQ†˛H"eՈFĘpęČóěQ†¨Oӓ ÍęEŹż Ľ5Ú3JKC–˘˜FşhÕkŃŁˆĺcb{GÉr€A„ÔŃŇĂi´BÇń¤“'‹Ł9+C .]Şó‰ĹjŰ úí8tpڕpS+ÇŔŠr^˝oöďqóŢŽ¨>ŚßŒ–¨fąŤ‚ŸNœžŚÇ—şś#ÉqmT—DáO  R S/şýFtu÷âWO>žá’Ů„ÓvL cY”+Ág`(†ßBß@ƒń¤Nü_ŞÚ}C ôÇáW×#ĽöŸP=ýęoDOźĄ!N¨FřšŞ l.­ÄTŕŇŕhYܢ~dŃ×ß§s:Đ]}Ýşu(-)ĹSOoĂ÷ż˙='Ċ5ş!2ČđT%p2<‘bgo_Ž=‚={÷`çs;pÍŐ×bĽ2†Ťý–••ękÂk ‡P§zî†ÔyJˆ˜pŽĄĹsޔȆ‚éE§€Ëpć ÉşĎ0a=ižgŇ­žĆ:ˇcO5{ ŮăÍiÎ3šX8OÇijjŇÂ/Cš ôäXşt)ž{î9y^ć"Ę6Š-S‚–úťˇîUÝ iŸ˛a¨Y“ŔđŠ Î9šěUvP'ŸWƒŞSˆ `pżĺÍТVşĂ!%z˔Ču°D٨6†‚ĘţQ…Ă­a$+UǢEo-?ŇÝĘś(QőwTً ţ”łMVařßقďŔsÉDšźA˜^DÜćŽ7cÝĂŞŃŐß׏Ź22*сŁŮő÷+Aj°-ë6b(€­‹HЏ€út)% Ä•а16öüX˛tľđŮgž€­™šÚjřle\ ô!“JŔŸ)ŠĄwŽ[vmMÚ{áx‹› ÝŇ^Uü/ëSbOÔihÚ6G TBO{7ţI˘%Ęh eΠźĚŒ2l”Š”nŐÓGŻN)Æ#ZJ :šť ••–*kĺľqôtŤ#dƒJ+ƒiP°ˆŒů⁜WW1eöš"MZ]ß΅?ћËßy ö‰ýˆ÷őbْE(­ŽBâŠ}8ŃÓŤĂB‰öS˘cż:VČďŒ.§–ZLAo@ý-cI%hĽti†âNŻw‚yźüJS+*mQmSŽlý "C]¨ŞšJ„KTOhgu uXą|…öâúĹ}÷âg?ű)žßý<*Ę+P˘î#n“VeĄ° i:ť;;Óy‚úŰ'~‹ýŕň͗áŢö‡Z ˆ Ťű"ĐnőĚtX¨e͌tÂźžX:żžúŚ EÁŠÓŹÍ2“ü–÷­­ĂmSz=łCI8ő›ăëäĄ˜ĽCąźĎšLë‚0Âxyďř|ŻGanФM¨Žł”;×"ôTţ4Ž~kűžDĂ"U÷'lPf‡-$úÔ˝P­ŞŽ|IeçôÄKEŃ÷ŒętˆWÁ.‚ęoEYłžu8ő| ˈ,Nâř!UOgJaůR(_@I˝ÚW‰­;`Ać"n ó 8śn¨ŃxdNƒt*ŠCóĘËĘ04<č$&WëƒL˛Ԟ )óÓŁ+֞I™ÔJĘT”)!¤^ KĺJ8F4Âäî)ôe2ˆŠáp” “•!ÄüžŹEQœhg‹*qnŹBe/Y•DmC=aÔ.Š+CE‰o íGÔąúB¨kR Tu.éáę—ĹőšĹmUž02Yż2šB°Ô÷ʍJK*)D:ŚÖ]@cKm§ŇXVĄćW×!ĆÁ!;`¤ľâ ÷X2mk/3 \LÖOÝjm} ŰÚŃŐŠD;k¸_]ÌŞbT÷_  !ÄpE +•VŁ şăjŸNŢ/–‚ëŇ[‹ÇT†ŁOBővToŚ#L ƕ¨¨ŽUß` ŰwĆ57cJđďÂZ}ƒ˝č@ii™2&c¸çžŕ7ýmímş1ĎżGB]ߌ ”°–rÂ#y.J$eŽ…a5QóąíŰżWm׊śŽVźüeŻÄŚ#RŐáˆ(žŠç–pŽ1I{‰ÉQB(Bń7˝´Œ×–ąŠ‚ďUŽĂ:” wÍś\‡÷ž ]d#˘/×ă}.‚ŸBŁćŃ#˜#ňźĚMŞ˘ĂĘöĘŔŻěʰ˛ç >tâx\ŮxK°BqeŁeU×iľË”Zn!Ľ:+—†`Wö P§lýQ”Żąn…ę°lóĂÎ`ŋú)‰"˛Žú”Aő '˙g Úv" ”m–őK¸Ť óˇ„9IT/ŸßÂ`Ÿţ$”A1ëřąŁjž_'%ç:mĘŔ †Ë—ŁŻO 5 üJK(ÁĽľľC5蔰ĽÚ|]JKöë‘ý˜tž] Čf´WEžăGĄ_‰,ľ‹WŤů) ö!Eo=Ę_qâ=šôęťëx%úOІh čkƒĺlŠYIK n>tˇFU/ř˘ťK´°‚ŒĽ ĘC,3mć!%„i-­Ą:O–"kĽ9ˆĄË|X¸$…cűƒJ ĄĚ—rý݊˹•Q‚S<íœcuU%ęjŞfřÝĐ0j .E(•E{O?b›ÂŇXßXzľÍšĽ áÇŃŐރĂĺĽ8Đ7¤ËÉŤ%*֔‡•pPÂaZ [˘J•@”˛™BűśéëÄk–ŚČŘׇŠaëdďźWŞŞŤp`˙A>ü$~óČo°oßŢQyP•$"áˆ:ç´;N:ť;pňÔ)\žL c–ĺË%DýՃ`ĎŢ˝xŮÝ/Ăk^ó%†F‘ˆ'ôß7đCÎ5ƻʋ´(\…1>…ś3˜:E_AFS(5ŸÇBϤ07ŞNĹHˆv§™ţ ŞWÇ1˜‰âđą(]܃vËŻěł(ꗨśăJÄjˆářÁ˘ą4ęš#Ř˝ľU•şT‡äĘ6Ý҃ď|ŁvkűüXą:_ŘĆĄöR-Iaae˝Ę.ŹH˘.GŔ i›Oa> â–0çĄ'ešxlXçžŇ!9ěÍRBE/Ÿ/ Ä%f…”8ĽfiľŢpŇIĎÜT̝eŤoŰŇÚTĆ‚ePQZŽHŔFIeŽ:óTe“ˆ–•#ôĄ´˛œ k”`Röś6v7•dąkTéV†ö,łTƒ1ŤĽŚŹ>'ő;bĐbWĚR˛š•V'´--rŮ!už>öÚĽR†QI2äJVj/ƒśHǧú ltwtB}fL´\qyˇ(d5Ő×ŔŻÄ<ЁE\ 8ŞGń֒°övlíŞ}ĎŁ&”ÄőkꑍŮjŢ:ú‡Ő5ő!Ś˝ÜTşg@7˜Ť˘A%…T%•E,Ś“öű9‡ RĹNd´—˜ßŃâ$ŢĚß5Ő|źIŽpX]‹˜j´ű–ö´z췏âČáĂcürúŠmOá†ëoЍ‘č$ňZđŠDP-ѿ㞆=ËuT Š÷ýň>\˛éíőUVRŚ=Î(Ş Âšbź(Af2˛éÜÁ˛8¸Œ˛AăžßVŠ˝{’H†QŐ¨:VQöÖ,š[ŘóPÚşRXE §N1ĐBâé46 ĘŕȑŽyq—˛ç,l}"ŠĄA6oś°ýńr ĽUg™˛€öJĄZŮNÇö%+K0°‹Š”íÔ”Ÿ˙\aÖ"â–0ÇqňÁP|ĐĄ5œe$l/Q…†’ƒ!-xٙ´ĺĐŇ á•)2Qcßj&Ô"Š?ڀážn>¸U#“3D{”82<Đ +X‚šĹŤŃĄŽď ôń,Ť¸Ţ36@ƒôşrŰĄ>ňƒ‘ M*,ŰÉ(–ń)ŃkQ%Ź%UŤsČ ˛ˇNí!¤DŸ¤ńÂ>¤[ű:™B0eDËÉvŻ/“…¤ş,ىäˇeFPœÜŔfňúă§:pôč1˝zĆ cިŽŔÚ5ką|ůr¤W,ĆE.ĆɎNÜsß#8Ú׃@YT‰[ƒJ°Rçę —7ŕ™mXXSŽc=+°?žV"Żqѐ_ CYۧCImu‘xi6č52ĹÖ3‡ >xä0ž}ćYí…eF’Ëo`œj?…c'ŽëźY‘hD‡”,iiÁ⅋ő%=v숺Ł˝V8ş"ß{ß˝xÍŤ_‹TĐš™ ҀÎ!Ň`„™<§sv.jń -Ę$ş:lTEęo\†Ţţş:me+…ÁŢIć?í:FuEĂI%J ĄŇ$ę3H&”ÝĐĄ:ĚB!d3~$6‚QŸęCU“mTWŞÎ֒ ŹŽĄg8xÔ–– :&Ó=ˆç– óˇ„y€íz,pÚŇÂH0B€I“q„ÔwV ZéTÎ(‚ Ç_I{Öľ°ĽýĽč •uň3ѓ‹#Ć1_*ďpŽ×•ęŞËĐŰ(Ňű°üÁ˘“‡sľ´–čĂHryK{’eáä!÷厠çRĽj}%l);*[˘Ä´n%ž$-ř+Ő|ÚVu…gVwÂ9O7DR 8–ło-fyljË.~ÄÄÜ芖3Â., w×38Ůߊ°ęM •EM&18œDďఓD~8žŰ6¨ŽůŢc]H+ĄíTwżţ;u ëëm[Îč“ÉŒ2îl'”0 ƒţgÉD –Çř7 űŚÖ((Qed™kęjĐ;ԋý÷ko+zőňrĄúř“żĹuW_‡K6\‚ĄŘÎăFŻŔ§ŸÝ†śŽś1׼ąĄIçvŰś}îźăĹzhkzz9+@Î Ň`„™IĄŽanŽţ@F/lR6Ů őޏĽăčî"IĄ§Ď§;IĘŹŰü˘~|űóŐÚżŞ!‹ŢöR$Şbˆůďđăř°_۝•ľĘN:YŠ`(ŚE ôpÄDŐÁwňp :NXčŃđSűUBX&+÷– óˇ„9ąé1 †ľW:•q,%ŽBÎŕČ̟r˝Ąâ–IS,IŤíRz”Ś•ĄĐĹPEăٔľ3ˆ””é°Gî×x9q7é¤24Nî×Ë-ćƒň +‘+ GқBéGƒ#nŃT1iÖGRž†3¨xfČńh2KÜ<>kFAIęź`YWČâ؏>W䞜[ścdgsšÁŠËšEtn3^ťLĆő’łą°"ŠžxŐ) ]˝( ˘g(ŽŽž!´ő"ĄŽ{"­D8–Eý=JTd2“˘ŤšNÎT‚`@]k„=žU–Ľ˝×’Qkq‹!ŚęoQYUß>”N!ÔŁťqÄ7&ŒoXЈ'Ÿ|R÷Žr`./„‹žY>ü –,^‚hI :ť:´gVĄź)ĺ•Xź¨Y‡?îÝż÷Ţ/^÷š×čŃäĘË+´Ç  œ+X_ńŢcČmYY™nP3ϖăIčύ~¨óŘI A˜VJKKősĺÍIÇy|;::䙛ƒŘŞ?1ŃgéLwź˛ Y§éU^“Ĺɓ~45Ś”MáSś0”đcŃÂ8^ňş4jŞ”­3tľEĐP—BM8…ҰĹ­ńć7őÁŠűő`;ľ‹’ŞďŐB"ŮŻ:Űü¨,B“˛mËËh-ft^U[n+Ać "n s†œ…Ă”D˘ş§Ť$ę§;’ö˘jD# ¨zž"ęĺŸq4 ŸÎb×-ĘvB)ŚĐË Y h1Ś˘şĂý­čďí֞;ÄČ!éD™Ä02áR%ş(Q&ĺŒč7Tt¸šĺHN,Ż ?$ÚsË š´íoŽL2Ž”ĺ„čQز]ďŚÜśZ´ĘŒň˘Đ°”pd§sžaÎ>Ýëç/.”’˘–éyv’ř[:?‚ĘZóG‘ލŔž‡0<4€çŽ´âXgŻNĎDôźn\Ÿp‰$ĹŽŒöƢY–Ę$őőšŁY&ş¨ÔŹ4ęT˘WF‡S Ş#j+ŐpW­YîőhllÔBVGG;~äa%FUč†FWw—ÚpÂŹşŐßü(jjj —ož\ďďčą#H)ŃôŕĄččěŔňe+ ‡œ:áĄN¨ŞŇމŐŐŐJ`-ף ғ nŽrȑ{zzĐßßAŚ>{˖-ÓĎ×Ţ˝{sóůÚ´i{ě1%vœ„0ˇHmDŞ”-SbĄe‰˛q†üčë-AE Ă •}H)›OY•Áʞ7hKeąfmRŰĄÉ:?–&t†¸üY'żh BH´fą¨9 ;ěĂP‡ľJ•92 ę÷…˛ Y¤ş3Pf¨NO‘ľÄsK„ů´Ş„9M@ W͋aé˛ĺʘčŐ"  şS¨ +Ń‹Ţ Î÷>WŘňšyšÜĽR!­ëädBu¤*qŒĄń!e—U*;-ěǑž#>Ôr`$Ő)Šd04BŹ_í%lĂŻŞoˇ‹)‘+éG -■óˇ„9 =ł.Ú°ďřÓ?ĂŃ#GtřaZ}üţ ú7”СČH+۲š°@7DP‡/úô>l%ĚôwmÖaŒ&!şăüĺCiUBŃ -ŒŃë’ ëPQQ>i™Y–˙Î °`I=bCq÷ŘvnôB# ĺ-–Ş\΄-:)×MéGÂ&-7ç–YÇxƒĺ`އšrl¸b ĘŮ8eVŻ^?ů“?Áć͛ľ÷ǑHÖŽBóâE(-ŻŔ†>š/šF_OŸĆ÷L_S“čŸa•z$Ë,/żˇŇŽ×FyŻQ,ÔyÍ,W´Ë:b$ťošá–˘„"^çrő÷ȖeQUWĽç]´qÎ×^mÁůfô:ś„sÖôÔ2˜đ(ăyIQ‹ÓwA˜>Ěó•ŸAzKέšIjĐŻlD%<%”=VŽlž’ 1 ĂýĺXŠĄŻĂρľa-ś1ÔD&AŰ(¤ęj­éaćm°1x,ˆôŕđ@)şĂđ+Ű%P1ŒĘ°ŞŤCY´vDѝ´PŞÄʁ~Z˘Ă  YAuÍ–ćž óŠí„9 i••U¸ńŚ[tŁÎô.2ůĄ8*žËihRc.&ŻčŔíťťť•@UĄ˝mźŰĐMœë›c*‡ÉIUL™›ZęqÇŻÓĂKŘäĘ1ĺă:ô¸0ż™ű‰ed/ćÜšŽ ľăyއ)o1 ˝=ޏâ lܸQ‡2ńú°Œć|Ů#ýҗżBçú1^"śĘßü;ŒxĐ9pËéýűđÜy­šoޟOţ>ĆĂxșéB žsńZš2°L<—ÚÚÚQׅe2הç^¨lă•Cźś„sMĄűÝ̓ś œ[řĚÉs7wI'™r!Š@cLwšöˇűŃ}(+B´&ŠlÎ0ʢ d‡ÂˆőFUWcZuî){ТW&íG6ésR2°/“E˝ŽĘËS¤” – áí­d'SDű•ŔeeńhGÖUÄĐŻŽ_A„ůˆ[œÇxĆxE†ăPź XÂů ŤҢÉΝ;ľxÁ… 4<™§†áËĆsŕudŮxmMů8żłłS˙-ř›×sppPß;üťŹZľ ‚pžÉŻA˜™x;ă„ŮM{o ĄXÇK•H•E_§ędj mÝe¨,‰+[AŐĎń †3(ŻRnáę ú;CłC2–A2ĺC…Ďƒ˛Ň!”DŇČŞýď˘T­űt ’L,Ď ;Á|ĄYciiJÂ(‚0qK˜—P„  qôčQí•C!ƒbĆ ´@e<¸Ěz\‡˘ףPCqcůňĺڋ‡Ók¸>EŠü}śźq(QtĄ‡…ţڐDc˜Âs>ËIA†‚ËiFIcă–eĺ2–‘ó(‰¸eŕu˘˜Ă˛:tH‹Y˘x](ţP¤ČëČ<#Ć{Ž×"RSS“ţMá‹×žűŁÉ2ršçĆmů1âœÉńĹż‡ńž›X6Ďš‹/Ö÷Ż-Ż)Ż5Ż#Ż-ϓçóoA?ž3ď.qK˜ °^“pCA„sG]…˛z“HZĘ6‹—)#Žůą”ř”ňŁĚŸEO:€H‰ęŠé\Ľ6ŇVeđ\w őDP$–…@F‰T É!RĚóŞ„,ŸúôĆKđôRôŚŇj×~ÄŐ'¤„łő{¨4€V_%ĄÉs§ ç=Âř)*Śsôbéäć:"n óŠ(YčáDAÄ4ú(X\ýőzoČEŠ)\žtéҜˇ”ČÖŹYŁ÷cÂé˝SlhÚT GĐĽ—^ŞËĘcąÜĆËeĽÂ˛đ7˝¸řMąŽ —™äĺćEiÂ/§ëEÇkĆ㲜~¸o^ sm(¨ń‹"§Y–––-q9ËĚżyɛůˇXNn§GHĚ ›ô†/NĆűŽÇŇŁŠż?ďžáľäľĺyR¤pÇuMx(ˇašĹˆfŚđbF:5CťPȔx”Âéaž=ď3d›â­57éę ˘ť#ŠĘrfuM"čˇ10Ź„­h@ŮĘ"ęoPu™,ŸPEĂaŠuÓ-Âą<üP„2PřńBÁŠ×Ř\K–ÍlG4#ˆQ<˘(Çëlŕů-Xzg™0OăáfršŃËÜ3\f„Lž‹ń€3‚żš/Ţ&ˇń›n!NŠ…Ďť ą6⍚ŸÍoŢÇź˙yĎóŢç2#|ąäó+pA˜NăŐ Ĺ÷ŽŒČyěĐĄˇłé<ć%á,‚ĺ =|OIY ™T]%Aԕ"eËŞşŐ—BYMR‰UŘ>ŐA–őáśĹĂŠő˘ťŻ˝2H§|z‰˜ęԌrTĂC6ăYlŽVŰ[8 ÁĘXčRś’?‹˛DĂvЌÔ×3 ŽÚ~đŕýŽM$âęÝëW6fˇŽš›ş9t[Őź‘şÂ¤>ńćýÓ ěí´2óřN?¤Ž˝zőJľŻé‹x„™€ˆ[‚č— …ămDŻžř1Iç G‘Ć]œĎy+řÂ9žZăa<ĘLÔÓ, fzQLaC•eă2Š6Ś'Č$żçšžď*ËfF2žrĆë‰×˜çt6Ĺ,/<6Żi’ö›œYĆŁĚxř‹Űđ:.ÎŁČĹűÜ—óŢ2çAĄNÄ-á|Á{™÷ łŒĄĚşŒˆćžĺ}nz`ĂŰԋ|>(˘sZ„ŠÁ÷3ŸݏĹçqýúőú˝Í|an‘Jőh…ńXV˝űJRśO‚‰á(+QöXڇh0 ›’!%< ˛Ó°”m bI$ƒćĹY„ŞéľĽ:(ʃJ°˛P˘ÖK¨j¸eš:HĐB&žATÉ_‰xý°ĐŠ–ü>ô Ś`' Ě0L^Ů˝{÷¨Ď^mŢrË-zYSSŁś!ťť{GmsčĐAő>nĐőČÁƒő6ěHŚÍZWWŤŢÝĚߌDŇdJ*^QQŠÚ~ý›"Öž}űpÉ%—ć:Á6Ù§$„™„ˆ[Âź‡/†'ăqăYĐ`FČŁčaÖÍ_ç\AĽÄăNlŚM8eošňCŽ˝7ÎWČĹ“ă+?<ĂëýV¨Üg ^ ^7oŘ#{ÔMšónĺcBL(nQLô"Ŕíš­Eá|CĄ•5ďqćîă}É{–÷/ dsďďUB‹ë™y’ˇKŚŸ]ťv™ĎÔ&Ϥ0÷řÉC ÷#Š­p„ś‚ݝ”VŘEUgiB‰^5–­”-ŃĺäyőUœČ U÷&ŒgD <ƒÁ¤úVë(ŹŚ,‹D—ę˜SżłJČČ$mÄŹa5ĎĆ ť:b–N0ŕ€GĽ}¸ ÂL‚ž[„GŽĆľ×^‡Ă‡căƋő;Út¨č1ýä“Oj;őe/{šŻ,hÂśm۰|ů ěŢ˝[wLąłŞšyąŽşsŁ‘łnažŰe˖*C*•† Ě5DÜŒˆů߅Öď÷šdźcWţbÎç\3ŃľÎ_ç\QhdÍüĺăÍ3ĄŽ…–‰°%Ě$ŘxňBŁ™ŒçEC[„3§ˇ´ń’ć&ýŢ);vç“ōf%%ŽÍ¸hŃ"ěŮłGžD‹˘V8ě„iŽ)ćä˘×=¨™;¸ŻŻ7Üp#::Úľ(f:çé­ĹÎnŠ[~żOm;„ .¸@ ^˝ŁBKK%ç–0÷qKAć "´ ÂĚGrÚ ÂÜŚŹŒůd+”¸ŐŒ7˝éÍN§Şz=/\ؔë`ĺôŃŁÇu}@­[ny‘žoňc––:‘$McöďÍ~a֋FKFżŞŞ‚0×qKAć 5.ÂĚBŽšÁ–-[ô(Ű玢-Ě,ř.niiFEEšöŹňů}¨ŽŞĘytŠ_+W.ÓWÓBHQĚý˝RěaN"â–0o8߆âT_"3Á°me>ől,ł œ&?œ ‚pnřřÇ?A(„3‚j•ţŒ‡I\„âqK˜óxtçŤa7ŐÜKĂÝÝh}â)”ľ,@şŹIwôFćĆéÄĐаNĘ^_WŁcć-˧óč¤UĎN0D(ĐÉ*š?čW/ƈęÖqřĺj>&ˆž¸ŔzŸţ`~?Ť‰‰Ëí\c ›ßxśF}uŒ+ˇŻˆëlg“°Ď ›ésfXî?Śř–=2ƒ+ŮúË{ďjz3Ëłşţśr_Ł/ú;–¨OłZ&Ă1 g>#4”™x–‰äÍĽ&ç—™Ńb9Ď,7CŠ›QBůmޚQY˝IčA ßŰfď<ćŃሼňüĚL¤nć2çr´wA8ۈ¸%ĚitCL¸gćœ'/˔% żoâ—ŽCÇńüˇž†•/}!Žgltu÷(ÁŽĄ­˝'NľkÁŤĽyjjkP[S…˜ZĆ$”L™ˆĹőň˛ňRÔÔUcÁ‚F§äú‹űőűœýúŹ‘s×÷CVčđ•ţž¸á\Ŕ_)`qX&Ź5"GO,//×ë°ąM1˘…s3Š"Ă(d™$ˇ|jjjô:ڜIoĽ(cỂɣůüp„DGÓeŘŘöíŰŃ­:ś„™‡4ţ…ů@…j3”•I’yav#â–0§É*#2~ř(2ť÷œ7]+‡jšžŞŞ …݈,aáËoGĺ+°ďńmt3ҚHmmĘKK°°Ší]čQŃ}Ą4Á† עˇŻŃpĎîŘĽ ćjŹY˝Á€Ý]݈ sĚhQף˘˘ -K!ZÉ 5cŠ›M"†?X_h|Î ٌRśŇY­ŢŒ:7î[k?Ł\–Fť=Yśą*ňśsD!ۈEůëćĘâ\?˙8ŁzÉ ?_fŸ“‡Čç”Áśœň"ë–Ë9ÜˇëáeŮY÷TŒ{šQĹ|ZÔr„6ˇŹYs‚>íÇż§ď,ŢŁŤĎݰü‹$DQ8ëhń|hHOSźâ=GĄŠ˘—ąáÍyô,1^[fâi‰p˝Ŕ$äQ&‡âoţȈ†ťşşdTŇYÎÖ܃í?ý٤ë˝ěďNJ‹7âlňż˙0Ž=űě¤ë˝ńß?†°Œ˜'Ŕy—/nnB$,QÂěFÄ-anŁdémO#ů_ŸĆLŔżîł@Őřąő&ä‡úÇpYŇJ GÂGĂ()u Á@ú)Ző`ďţCxnç-šXJýI$S¨¨,×BЂEÎ*{÷ĐßľŻśśěWŰ$I\xájřŁŤ[ŘüřT#քM†¸”¸E/kœĺÎDî #Ą€ĆĂ΂lŰxGš‚“ĺ NyG0ť6ş)ó¤ž[™¸ÁlăšĺÓRœs\˝ŠłŸŹjořj~†"XFéRuždmŸ:–€ß§ËĎ\ŸÔ÷¨ŤŮj™?F"ĺC0¤ă ßJëcd•Đ űÔvŽŔ;ĺ,„sÄđđ°ţڧ˝ąxŸ hA‹ŢW…žyÓ 7‚Ÿ3ĚmLŁ\‚P>cć÷ôôčg(_ôfGŽ`ĎCM˛–ÄŔŸj[,ż“ÎkÝ8ţá#~íŚ{ÍvÜĘ][Č]b9ÓVŽ˙ĐÂńĎQUŻ!¨ŇŁpŊŘąc6lŘ çľśśjďʊ Ô××kďCžCŽ?ŽK/˝'OžÄ‰'t2}Ţó杳dÉéÄáŹ"â–0ˇĄČĄ^¸ţĂGŠZ}İ(k*ë§SE­ĆœQĚuĹpŔĹ-  ” Ö9łŘ ¤‹<ż›4`ĄęiŠ­ŽBG{˘ŽÖ°aęjőôăoĂĄCÇpĺ—čQYBŞWfx8†íO?§ö˝ŐŐ9cĂVĆőđĂ|öy”]|!J×\XTyő ĺęDúç$\˄šHE'RĎ#pá*?‡—Îhši bí&Űçî™^)Ęžkëb /¨~Ú…2HŚ2Ęđ ah ŤDEż2FŐďŒSžpÔB@ý9ł¨Šf/WJý*9,ŤÖIٞ˛­ƒ¨./C˙P eT–epč`Ő5a,]‘@Y´ iŰbč ç SůÓŚam<´ĆĂë]"qA˜…Ţ‹|˝Ď¤0÷Ą(•Ýöy$}"Ęˆ÷¨Ę5 ‹„Őî8‰pi%üŐÍHwTlIe0ŕŻ_Ą;Čhs¨îR T +ŢŻżýUuđŤa•/ÄtÂ{ó!%”1T}˙ţýÚËЈY´E™§qßž}ŞßśJ˙Śm÷裏⢋.Ň×îÝť•MTŠ;F/^,!ž‚ œUDÜć%ěKŤp&O’…†Ďľ,5’ăuvn•V żŹŰ ŁÇ—ŃĚČd3Ę.Iéuü6,Kgh˛N32•Éęýs뺆°ŮçËß“<‡•á“AóâƒĘččFMm5Z–6ăŔÁŁŞrŻXąT}–Ąśś•UĺŘłőş{úQ_W…´26ŇýƒH…"HŤó Ťóî@çÉN—#OeĹIwĆëIKOn(SnYË`ć9á‡#âV^ö-Ŕý›đ$ćwÖs„ĄŃb×T„Iî×I”­ţž!?ĘjvĽÄ­€ă}•ÉŘJŕRĎ ­C-í‘EďŹĘkü°ÓYuÝ3°ýY”×e´X•ľ•qL#R@i4…úŒO‰ŒIüęž Y(-K)q,ëäZbA8}ňŸKAf&ć;ˇaG`ćđJ´J ­D(;„Œ/֎LŐrd;—żvű^¤Žn…oń°c=°ZŸ*!5ÜŻl“‚ľË€îƒjő(/Â*mÁtÓŇҢó3Ṙ!…* [Ż(hQŔâ4çŃVeŘ;=´č ÜÔԔłł¸\Ţ?‚ œmDÜ攳U•x(›ÂCAő"VďÚd"‰ĎíŤ:á÷Š“'ń?ŸüžÝž] @ xĂš’0ţçs_Ŕ#żůön¸óŽŰńćߍuv<ó >ň˙¤_ţ-j_7ŤžľU‰BŠÓ 7 }Ú0`¨_i(\8‰ş2Ž:†ƒűŁqAÔŁşŽCƒq<÷Ü^<ňč“Řré,iiV⌝ÝĘ0ŔŽ]űqßĄŚ˘ƒ‡ŕâŠJÄ6_‰Ÿ~í^źŚ&ŢŢ6TŹnŔţď|ÍGÚąô•Ż"Eäd°F ˝Fy.wÖĄĎÎ-÷~{ĎĎłs8bV.ĺ•ÇăËöc–ΗUJÓŁ*ÚeY¨ŻOęíjšžţśZfÔ=¸0˝ŽĚ Ż–Ű7Y|ĘÉƤôČ(gŇ=kľŽĘJŁj˙ČIŘúř ŸpĆ˛ ĚäYűŘ' ¨D°"›ŁXoێĚew#ű­Ż"pëËaokEźwŠ+ŕ˙ćSČźú5°U'Ľ}đěž@đŠu°:şčS6cŚńlGô݀ƴB/-~HCCØĺP„466ęoz÷nŢź9śNo-A„s…ˆ[Âźƒb”pJĐČ^x.R/áď÷ťn¸ĐIDŽDŸcęłKM÷FBhW=Q]}˝( ×ăDi v+q#ŠD+ęٰA iŐS•Yˇ‹/X‡á'žÄ`{7˛ŠÓŮJ ˝˝ ›ŞĆ!A˝=}8y˘M{y1„ńĐţ#hSĆÎOő 6\°GDmM5ʔá´˙Ŕüâž_cůňĽŽăŔÁ#:ý?ţ՟ăE4Łěš8ńßcÉŽÇP° %5uˆ%ëD¤ś~ňB{ŁGÚÍ ‘ç}5‚čÝnôôčH‘řEămgÄ´Që—¨öÍ|ܐYvî9‡*4ŢÁčĽeFqtÖQ˘–Ď΅6朣*F›ŽűľÝÜńL$pdž´=Éę˝ éá fA˜yX–%ĎćźBu>´ ÖĐ üW\…€Ň‡˛Ű­q¤&a˙>ÄÓÇA>†c°öîîz ˛5ĽH~ń+ˆ¨U_˙ ˛A|đŠʸ꘾ű$Ňű"x–“ŐOF MKAÎR óíéSR˘EˆC‡(!'„xÜI’lbäĚ w$TY‰ČŞ•ˆŞž+(”[f[#!xYĽ`t´w(!ă9Twu!Pb‰î´ňŚ-žŠŇ(ëk Ç; 7×"˝&ŒěÂÁCG1‹aÝŞ…řáĎ~Š]ȗ.Y„RuΕ8př(ŽÜ|1vďŮŻć/Ćgžü=Üúâ[qá]7á‚^‹xş]‡PwÉjD"M(К\Řrł]ĺÎ6ßHw"9mOž-+7=ŁYĚ˙éőřrÜŢMă Č‚),ˇł=ʙ?âQfœÁŕ&¨×RV^r|K'”ˇGvi;‚•O `މÚ2“u<Ĺ,¸űA.eŹD& ç 6”íۏ…÷ŢŤł§#lé2ŞfIiŠj@R+piqH)"ľuŐ(Ż,Ǣ–8u˘ ”hNžjU_6:z{qÍ՛urógŸ}ýCzĚçwďÓšŽźěD#<ňÄS¸ďţqÇí7#Öߏ#Ýl´ńý'Ń|ém(­-ÖĽÜ6*—u8’ ăÉä͝ĺŽfŮžŃ Ř5rîNȞWܲGFM4GóŒ’8Y~Ż‚Xf'–ţ{Znůt/60,SN5ß猦˜¨˜˜ů¸˜ƒKŸŻçXÎHFz;÷ÜôČr&2“ËłŽŕe„Y š€uó§PТČŜ)­ l.ăČV¸(d1…óâńxNđâ˝Ěu:;;'M>/Â|Ź\šR?7;wîĚÍ_¸p!ޏâ <řŕƒz:a~`ŐÖ ~â$ʖŻ4sô(Őöc!sÇmZ܊ŤzşLç|ľ\›"ë˜55şł5ŤśG"ż˛MŹćf¤ŸÜ ˙M7Baž"â–0ď°Ý|JK–-Ĺ%/ťĄęt+!čŸ˙ĺ#xĹ+_‰=ŞgěFՃvő5×čü[Ÿüđ?âäO~†#ŞÁ÷'˙ö/¸óî—čßżđßţ´;čÉđ—ď/‚jţŔC`ŕé°ŽŸR*SW.˛Jř(+ ëÇ=;Ťv?Œ` ‚şşZd•V[[…Á~TT•ăŚ[ŽC&›ĆÎ{ĐÓۏ!e$ő)QkŐňŹR˝…­]8pđ0’é4î˙ĺ#¸ů†k0Đ։t!´`¸?ŽÁŽnÔ,/Ś'ŮxLů(Ť,3ĚÎó˛ňůL†ŮvěËürOPů\šŃ^pV.זIĘnĺ\­ŠE‰NJeňů‚ŽÇW&ăäŔF—E‹gśN›EĚÎZHÄý8~ĚĆÁŁY,\`ai‹/śÄlřFÜž,×#Ü݇ń˝ áœ@Q‹Ă´3Źšťť[ UôÂbĆo׈eź´8ĎxsQăoŠaâš%SƒĎŃöíŰÇĚ?tčNĘm<(…ůAdq3RĎ=‡äŃ#đeč…o#¨zÁ"ýd8:ĄĹÁhT˝Üڊ@uĽ#j}䣈E#ˆ<ř˛őđ—”ŔŽŠ†ĂÄěG°ˇ‚ óˇ„y‡S=b)%ŇcHGbH(Ł2 c żA%(ąáFC3W=bţ öôňQLR˝fœŸÎ8IÄéĹW˝fŃHĂj~Pm—H&ô(ŒëĐŁ%ŇÓŞ˛źfÜu(ne•xeŠoNÇb ´śľĂ𣲲Ď=ż÷üě>ěŢ}ŻőKpńĆučTY N˖-F‹2Źîűĺo°g˙!<šíYěŢ{P­ł .^×˝ –żTX vŽ\śÎ3•Ÿ~TNyNeÁӃK‡şY¨,÷;ƒ‘it˘zkÔţs^(ŠlnÂÓܐůe¤x–ˇ(Ú%Óśďđá›?Ja÷!V,Îŕ˛ő45W_@iYFoGIĐrbS]ľŒ#ăšŢ[Čʖ|ňÂ9ƒĎĐŕࠞćĐěďt!¸ź_Տ’HNŸBĎ=šŒˆ,ĚĘ>­Y;Lë$ʧŸAře/ŐŚG’ŁeŸ< +•FvăúÂΨéC‡qęĘK°âż†Wż ËW {ř0Ň?‚ŔΝđżő­A˜Ďˆ¸%ĚCldCA9q ‡~đ¤”pEo…ťî~ąę% ˘şŚű÷íCOwă^[ƒĺ7߄UĺeččěÄý÷ÝŻ÷ÂâęUŤ´‡ó_}÷ŰßÖrLŐącX98€ˆďô‹ 2z’C˝Ę˜ŠPżBŁ–1T‘[<6„L2(ĽĘďSÂÜB꼎ŤózŕŃÇńÜîýˆĹcXĐÔ óm•––âň-›ôˆŽ~ľ&ŁoY´•e…#xěńíXľz…Z7ăq4%mNćÚÓöš#¸QA˘ˇ“3jG"Ěşű6Iĺ1ďĚ QŽ|öH.,Ž™-”ƒ+TEťČBë"9Uüű9ɲܤňśÉfźĆ|z™­žŽ÷áĐq /š­[ZSŘş={~™AUYő ~lÜŔáă\Ń.m†`´F„=fˆë–0ӑ†ˇ œ=äůš_đŻţŰęÎC†fRIœÜ˝ĺ-KPYU‡čuתž˝Źc(3Ąlʃ;ŸÁń7˝ ‹6nBę÷ގúĆFÇ>IŚT†„ŐŚ‚ ĚgDÜćZnP˝¤ťžŢŽO?ňô(ƒ Şş[ŸŢŚsEQ=c˙ţяéźTen޲[6_Šú‹7ŕŸ>ńIlÝşÉDëÖ­Ăţ毾PńčÏâ-o~łîÝŹ„˘ßݍFøădUůšËĂFöAă—âO<žDWg7ú{;đg-­bĘôő  ŹŹD—!6ӂʪĺKqŰ-/@UU%ž{ĎϰuŰłZ€[ťj9Žžj zúúQ˘„ŻšŞ ǰőŠgqýľ—aްlěyÎÚiúĹécÓዣOňšŇóÉŽhťů­<˝íäľr¸ ÜG/Î-ľGŽkŚ}ž)jDވf[Ö(/—ËÄŻ:ĹqPęÚţÔŐDÔšĹpńú zťH&š0Ţ~ ЌĽDRÇłÎɍć–SíËçˇ}K؛ą^\ˇ„łĎČ@‚ Ědœw›^sÖĂÁŞjˇăH Ů8Ńß{{+|Ą(.˝ć&„U‡$Ą-Ńsź‰ţn4Ž˝k/Ú_  ÓaD"ŃÜ>e0Aˇ„yˆ /›Q˝\g<=×ä@r~eŐüL:_ĐŇŢ=V0ěxůpT>őrԌQ ĎÍžő>•ĐciCÛ'Şx2‰$üÁÎŁĺ ´!”JĽ•ˆ•D0D}}j*}ČfbŠůÔüŹ^VREËâE:N$Fw?Žž8Ľ„ťxfçn”+ńkń¸ę˛M¸|óFÜ˙Ŕ#Ú ˘'Gg<ŠÖľmű4Ŕś|,ŻÇŻĹ-ËĐról!÷ČÚŁEťœŕ•E.šźÉϕelgĺ…6bÔ8—Ĺ”XÉZÝź]&Á|îXöˆ÷–ţ×ö#cč>‡x,ŁýI%tpÉú7[¨­Q"Ÿęm Únn-Ëš§˛vÖŤššÇv=Ô|mK8'HƒYaćQRZ†u—\…§ű5|C}ŘšőQ-pĹă1ô;ĄŢÖnžąŘ0Ž9ŠŚ… U‡äÂŞ3U:,AFqK˜‡XČřh^žwŻY¸Ď`i_űҗQížžt ‹šš°¸ĄĄh­˝=řŐłĎ zř€€ęŃT]ŁókEÔ˛o~ᾀѣ ×žţuČŚRXŘՃZ%$ůúpş0ˇWRí˟LéQ#‘ŇJÜJ%™đ9ŤD¨“ءoˇA<ŮÚŤ…–ĆšŹUçłrőrÝŘŐӋm;žÇŔŕęë‹ÇľÇÖ5WnFuU%Nľu`Պe:×ҖfŹQŰ1ĂƒÁŠU ôÔbƒ Ńt“kĽŐuÔ˘Vžpč8*šyšŔFG!´ÝˆE‡¨á&aüh窜N”Igľ[ż/ć8•đoŽŤ‘Q‘ľ=ůŔlw€C7ÜQŸOᐍňę0žđ•ĐšnË&M >%*ÚNńí‘đKŽn䈨N|xßŰâ´%œcx/3”šž–üÖ#yŞ•ĄŮ^Ä @Ś>s|xŸ73€=qD|žżTŐ5âúŰ^†žŽ*‚÷ÂĂßű!"_ű Tggę˝ďA:@“˛O#Ń(ú•]¨ě,v(ęAˇ„yIP =ëVŽÄ˘Í›a…Â(šd#ţěŻF‡šW=boxő+ĐŠ"[]‰oýěç8ţ›ßč4J/ýËwbš22Ę/ĆC;žÁ?ţ_)a'°á"źďOţńă'ěíCđT;쓧pşĘE Ô E&–‡ƒZÉd38pč0bCƒččěĂÖ§÷¨ĺ1ě;pWlڈkŻť 55Ő8yü”nœŚŐú4šëëjĐŁĘEƒşDEL8˙ôł;qáŕę+ś IăTk‡ęŒëđÄK.šH VĹcĺBžL/âÉ'ĐŐى§žz MZě˘hˇqĂ:|l;ƒaœ:ՊZ%ĚńťZ•˝Ł˝ĺ¸řŇKđäcżU†\ŁęŐ,E*•D"GCCƒîधZ™ęí\ŻöÇĺĆ+ĽčƁëfg˛Ž°ĺw´œ¸eyœÁ\o+;ƒÚú€şž>DÂ)u.QtweĺY}>ž@ęOçŚÖ2âœ+ď™réPHŒ …„sëŽzŘŐŐĽęŠÝ ćHˆ gć˝jÝCCCz™ ÓŸŻzŐAFa™Ł”ř677cďŢ˝úšćuOčܟŞ{ŹŚžIß+Н›W]…ŇúZtŤËşĹÍşsłźŞZ§Šƒ"ˆ ‚ xqK˜‡Řzź°ľ"JVU”Ł˘şCÝÝŕŕöCĺzÄĨ;˛Ą’Uş{śĄÎW”•#ĘP;+ˆžžÔZ>=ębi(‚ŹĎ‡¨fŇeeŞ;–ák§Ů8d#S;~íľvň3¨c—–Ň8ŽAoŔŻŤ:Ź^ą­­ÝXÁjÜúÂëą~ýZ öi݆UzyŃ𩯭FŁ2Ž˘ň˘~ŮŇlŰžC IĽŘöôN Łya#ÔzôŢ …ŚV=ĐĐâHŒśĎ +ěRŞĎłĎ<‹Ý{vŁź˛ mmXžbžńo ŽŽ^MŻTe?ĽӝĘĐß˝{.˝ôRüć׿ŃbŰsĎ=‡kŻ˝=ú[%f ăäÉhlŹGӂFTŠż×† ńŘÏ yńDKJźݏëĐA+$hš#.ږGœ2řÝQŐ +WŚqüx=–Ŕ—EXëG6•ER{s­ş/üY˝Nßö$Î÷YŽw˜ă͖Ë!fO-”RÎ \ü°ˇŸ9÷(„W¨z‹uŒ5‘ő‡ˆ[‚0˝p@Š[^(.׊÷ů Ő!$âÖüäџߋ†ŸÝ‹SĘF*Y҂Ë^ţT)kˍ/PKŻ×"֏żţ=<ţÔ3¨Ž,Ń#7WTWIEA„<ŸĘ œN žŒcőő×s\@D4aűŃŁ:Q}ů‘ŁX „_:…Ó…y˝˘>Őř ‡Pŕcęä˛b¸`ó˘hP†pCm)–-ŽQÇ÷ĄiáRÔÖŐęuzşű´Ĺ&Š&!ľMEyjŞŤqäč œ8نîž>lźč\~ů&:xÉŚőˆ'’čďëÇŕŕ08„ľkWíQ¤Łů˛JËş1…>z™YXžj5:‚ /ź˙ý뇴÷X]m#N:ŠË—ˆ'pôŘq\§Žoľ*{°—.Y‚Ł'ŽkŻŹß*aëäɓJŔj։S;;ťą`áBľý)őťD{‚ÁMÚîÄNA$R'n3šÖœÜ°HOĘ-ˑ œóÓ ń}zQeš+.ˇ‘TŇh×@[Ô}ŃgŁeąŞr7ˇ–18)dqH­m$Ó×NakL¸Ľ œmذnooׂkŞMŽ=~Xp9çü0EAÎ >k‡3Ÿď3zr‰˜<YR^ŽŞ;Ąnř^|7şş:ńÔă!¤ěŔ~e7ÝţŠ—ăÎ×˝Oţöqřł4/]ŠĄţ~‚ ŁqK˜wPhČ‚xzŰ6|ĺé'ѯ䅲Šr|ý[ßÔšgŘ{úŻ~M‰<ƒÚĂéÖŰnĹĘ-—#Źz\żô“Ÿŕ‰ž^DËJŃÔЄżúŘGtňů§ˇoÇ˙ęŻuĂpŁ3^Ż„ľţB™Ó¸˜§iH?X_ƒ ßB:•Őe)+/Éy\„Ă‹P^„?B¤¤F‰/żł˝Ăą’Š4JKJ°zů2UÖz;ŮŞËWUYCJPâȈJźťíÖ°yÓFŐ3@Ÿ2–zzú”ąÝŽDŚfD•(Vt™mGźĄŚFĽ–ĹKTš˘Xž|%jkŤńŽ÷źG{ˆ0l26ĚŢiGIbţ˛ęÚZ\yő•ş{ĹĘbž°´ľśjĎËň#Ą zČQ㨌ИpŸż°eME,rţ3€ŢfśÇŤĘ(ŔUş|Ž+—É—ĺSrbS]wŢbéÄř‘p Ue´u}÷bčm-âhëюěŒĎŃvźş\eËÎ%š„łďcӈŚw– çŽB!d“‰Év6÷IĐö\źĂMM8Ńމ•Ǐ๹4úŽţÖúßÇž={°DŮr š´MRZE_Wâń¸ęč‹@ApqK˜wh1A5 şcĂčU†c*“Öaˇ”¨DÁĘŻÄ)6ţBÁ Ę-†1†H%Ő!‰JâP˝g5jR-Ń9l˜ÜłßDş´Âu?˝Ń-żĄŠ’œç ۟Dž.@EeŠŢ7Ë +ą+TŞ…-zBľ)ŁččŃcZ댎 ŽŚJçϢQ”¨ŠcٲĹŘtéE:Wm]:?žWR‡@ö÷ŕń'žĆú VbhhX‰xĹŐšłŽxSŠD,Š=Q%pńřÍJ,ă źvUU#yŹÜż E7Âź[YWŞk¨Őßz`K7!ťĽó{QHr¤|žÜȉ–fą˜ňR̢7–v°˛s'`ť!ŠćœŒWËäËm(ŰŇőčRkłzš+iéyNvŔ§…-‹É^M¤ízŠąĚšQ#Ľń"œxŸIrxA˜Čł;?h¸pzţú]đÇáß{‹ZZđŻ˙úu$í0n*oŒիĹa'•MZĹqeç-]ś ˝=ˆ,h†0;áű™í ÚŰ´éËTÇyţŕŹ‡Ć„3Ÿ.´a͔'‚0qK˜wPFřœŃe‘,˘J|ˆ†ĂzˆeVúI%$őőtcçł;PZVŞĹ‰š-—:Ł‹)ëŮGŐŢDˇźđ…ÔÂGZ‰CLԞRBXŘ_ěÓś „2dĘAý; ˘ia:;;•ˆ’QâP%F¤K‡ÔľˇścߎĘŘéC,ž@{Wˇ쪹bĹR•€ŐÚъǎ"Š EK4Ć˝żř52|šŞßlnťőF:r{öŇŁ^wc%šĘ›Š*ł vç&œrľ=ăͤ %OĄ{žÉuĺx3š!>ŸMŃö›‘‡Öč<Î2L [+UíľWä˛ÜdYś›TŢöůrIćyşx~ßčÄő:oźĎ˝Śń üĎ_ý Rjťˇž˙˝xĎűދ šžőőŻăew˝ŐŐU(Ż¨ÄŻ~Hż˜ŸÜŠŘž­Űpşž[4fًðťNőňŰńěn=v•Ę€YšzšăůÄ9Zü˛0¨DśîŽ^%^Wß}čPŰuio­SJôÚč°zY–ŕ€zIVT”aŐÚĺ¨TŮĺ—_ŠgŸŰ…ç÷Ŕ•›7j!ŚĄĄ'OśŁłťť÷DSóŞ)”Ür5+ć° ťóů̕w°GmáůśFŚ˝ŢS:”Ď]aDŕrc›ůîžOă=mޤ=ƲŽgźšl×,kgiÎv$°tň|w{ŰI6oÎÍz: Ńäł\N'“wźĆrB ´[„ł f“CK„Ů Ejˇć6}˝}XÔźP‰T8uâ8v=ż[^˙fD”ČŃzâ$ö*;­~ăF\źbł˛)2zmFĐŰžĄĄÂ샃ˇœ<ŮŞŸďm۞ŇűŐŤWăŘąăXľj…^çřń“Ł„-ŹTVVŽ€áŕ}}˝X°`aAŞˇˇ•J ő.ëďďםóLoŇŢŢĄ=Ĺř„š„ˆ[ÂźƒâB&„?ŐšśBUUZÔT/šJÜzţšçŠDÔKĄJťg26*‡ŃŻÄ †đU¨ů!%nů”°4¤zUÖ.jFOwˇ2B˘z~2Ơ߯=ŽN;—’ľlUzi=˝m§ęĄKᢍëľŘŐźŘxRQ áČKYôőôăŔžĂčTB×0zűTëňO&ő:Í QŤ„¸őëÖčr>ůô˝żŢ|Žťö2tvöŞ^˘žÝš ŐJř ‡CČf˛ęŚF¨ďeŰÎyPĎ*z˝1\RčłFF4—Ćvźś;Łą˜pGŸÖěQkŽő޲§$e}Ž˜Őlˇ@&˙–íž—ĺćČr:â‰ešÜĐŸĺ$Ž×›eݐGgú~ĐîćŽ gYgr‡BQHX“ Â̅6ČŇeKÝ_ôbÓćÍ8xđ|Ęf`GÚMˇ˝•Ő5z &›oY˛DO766‰çÍ,Ľ_ŮëäŃGÖiPN(Q“śů˛eËt^LvpÇr볓ŠƒOÔÖ&ľ¸ĹŃĆŤŐ=ąuë“:_-C )^ét*j?œ×ÖÖŚ…,FŚpűAŐń}éĽ[ô<Ň××/â–0çqK˜wĐ œT‚Ôń#GáS=_LżháBt+ŁĄĄĄA{r>tXĽ%Q ,]˘ĺ ŠYGŽAP [|QĐ ĄŰ0]ů$ÚŰt˛ňŸ§ =‚ę…CąĺƛŻE 8ƒošŁîQČŠĄŁ˝ {žß‡C‡Ž"K¨—¤O ZFčń+f8GuMzĂמ}^÷ę—`íęĺ(U/ĂíĎ<‡ýŕŽ[oD0D$AWwŸzŃś˘ź˛^÷••WUn˓O݌¦=|Nž,Ű’ôrǡɉ`´ěÜßĆçńŘłc×ÎۉmhNÎüb{¸ÝršÉşÜ28B–3ĘĄwWîÎM˘y&łw˝ąF<ÎŹ‘˛YÎ舌`:_—›Űk¤Ţ=ś}ăTAć O ďD_| J°üˆg(A>ĽaLwŁI‘`Íá&ěOś"5x eV ŽŔŐWcëđs:_ěÂpú3CˆĽbh /Ôë 3cöŃëűß˙.n˝ővË×]:f}ڎ;v<ŤQZşt™śŻŰÚZQZZŞ-†§rŽ,ν˝=z‰DZˇq¸Œ)Jźb¨ŁÂ\DÄ-aţĄÔ‹Tyž9p}öł(]°ímíxďű߯z;‚čěěÂŁ?Œďç;JŘ*ņpĹƋŠ–ŕ‰çvâÁ_˙Y%l­]ˇoyë[u(âŃcÇđŠO|RZSĽłëOœDő™xL(ý#=j-Ýs“Éd‘N§PYUĄËČ_"‘ĉc­Řł{Ž>‰T’IńkQ/łűzeĽ%¸`íj-ŕ0,qŮŇĹhiY„'ˇíŔö+ÚŁăŐ/ż Ż~Ő8Ő։‡ŽŕĘ+/ĹćK/Â~t/Ž;ŤŽšnLrËqą‘j$‘ž:hŮ9‘ČxvyëMÝd𜝼ŢϘK2ÚĎ)7šĄYjýO!ĄźNďsś×Y>k$Ń˝›÷ËXś÷D}šZNRy# Ă`ćťn[n˛{ý­OŢĘY59PâAaţ´Ń]ˆš@%ÚR݈ ;“Ő˝›uţ*řNžŃ 5ż,X† Á*J*ÎŚQa—čtÉTŐ~Ő™bŽĎÓďTÎ-ĺhmmǒ%Kq÷Ý/ӞW˗Ż@IIԾ󥽪ABşU‡|ssłÎŰJ,Ž;\w2tŠA˜cˆ¸%ĚKčIÓŢڊă?–ÖÔâŮgžÁ~âż´ŕqřđa|÷ŰßV×#X´h!ŽÝr)ÖTV˘|ÁBüâ×âáß<¤]†—­XÜpƒŢ_đ‰'đ­o~ •P6xü8†’)ŘţÓ72|Á€N^oüŘšu§Üşu|ţ’ĽÍXşź55UčîęÁŠ“mˆ ĹPV^‚úĆŨQ=:;ŸßƒcJ\khŹĂEëWăđ‘ăŘ´a=:şşu>­ĆúZl{ć9TV”)álX‹W%œ-VçZ^V†Ý|zzútœ?˝ŔЎŒ,5rÎ9Ç% ĹĹB=E^g+#Mśž’rIěs_E EÔ¨ra”fG#J–íĆLćvŸuVś\+oByŻgWÎťË9­{Ń{-3â–sö’\*‚ ‚0ݏ´ę˘Ü4Ž|Z" sÓMÁúÜôŞH‹ţ^WşŇ™áśä–†A˜=0l°šŮɗEo, /nÎَÍ͋” T”ɨ’›o~!ŚîÁ‚FKć"n ó* J( ů˛°•ht䊧'V˝"ڛ§ˇĽJźŞ˛ł(OgTËJ”čň[(IĽPŠć'Ő'‹ém´×PoěŽ. $R¨O$ďôŔ&:ŻšÚ>›JăĐÁŁč@´$‚gˇďBŸšžđ˘ľˆ ÇUŻK9*ŐǧD¨ĆŚzTţ׏<Ž˜:żĘŠr<>žL`ă†u8rô8NęŔŞ•Ëô1–Ş—ćŞKŃ×; sn1ž˙‰'ˇcIË"ÜqűMH)qŤIí3PŹçVž¨4âÄ4’4Ţň„ZF#˛Px A{ôś6rëŮš‹óܲs˙Ŕëć|ůźËŹŃĂĐ-kD*Ë1§€9ól×{MŸ‡ßUËřqňĺފ[‚ ‚0ëšđć›Qťxń¤ëUގD&ű>›\űŚ7`Ă ožt˝;*Ÿp~ŕ€Tôŕb„;“é˝ĺíŘĽת•ËSâC§ÚúŃäÝ„š†ÜŮÂźƒ’ƒ_‰V*‘"z˘éSJŔ `řC˙¨—‡qÇÁ#X§Ž€~jîý%bĎěÄ zńlxć9ÔĽ”°eűqŃcObđď>Ź%šöźćD >U> ‹ŐţüJ˜:]2ę%Ćđ:†?nžl#ÚÚ:tě|F‰*zˆ`ľŹŚŽľu5އ˛ĆýżzGžŔÂŚ&ŒyŸŇXĄÄš…MhmëÔ=Cĺĺe8 zƒcĂX´¨ őőľŽť ‡PSU‰Ááa´śwbaKĹ 2mF/tœŸ<‚“+䌼°­\Ž-ݍĺ͝5ÁQ\qĚĎčŞTšĐÁbő"“€Ţ22”#ŠŮŁ˘-'/W.Y˝óÉŚš¤ňíŢĺdŸ÷Qôgs éÝ u袁Ѳ]AÎäł$Ąź ‚ Ěrš×ŻÓŸbˆĹb8›ŹžęJłFGĐ&ÚÎ U˘arDÜć:Ąźˇ–ŞďĽ:38č&…Ě÷~¤—‡”ô°NÍl°|Hs¤’'žBˇĎńŢY¤ÄĽĹnˆÚ҇ÝXoC‡âœłpFI%gÚℊ*´::şĐŠ>˛,¨CEešîéĄG{r†‡†ŃÓӋú-ýí6Ü|ýŐŽ') é]K/‚Ćz„UPwOŸîbˆâ3;žÇ‚†zÜpýU8xč.ťüb46Öá‘ÇśbĽę)*-¨^˝Ó”^ryśF”ŚüĄĚ-OáDI-s‰éGÍËMÚŢńŠ*×ăĘł_wŚíäÜ2ëŮLüŽÄĆÔ°űžç)úQśF"íÓůËJ"YÔ7Šď ˘čHŽ:‹<É7śą\h"Źâ9AAΐŠŮ6@ČOkaŽBíŹ$——„őÂy@Ä-aŢ2^•ˈ´Rľ4  ËMîz š‰ĎÓžŹ^~ÖŞí`VF#ƲK°¸e!‘ˆN,™N§ľ˜2¨zţRŘŢ։_Ü˙k<ţÔvÜő˘›°ń˘ päđ í%TUU‰-›7ŕä‰VdÔ64Đ(šu*q‹9ľş”ŘĹäńuŐUŘ|éF\˛é"‹ÇáůúĂYř|Eže.÷<šŻŒčdť"•ĎMmĺ$aˇŹŃ áÇěқOkÔ[iVYGŔrwlyŒË\‰lwœFŠ}ž –]ŒtÖÉ ŚkАZG'Şż—…P‰śß$žwGHänx Ź=â­ĺî;—ˆ^A„łËYň&ŮńđąŔżÇO ŕÂľ@eY)˝q¤[3ˆľĽŃ۞F<‘Áp,‰žt eƒ$Ź éŒę0őëNÍ´­:Uo­†TRuHňˇ?ˆP0„ęLł‚Qeh„ŕ „Ôö~%LŠŽĐh ˛ŞçĚç şZ"‘FżęüěčGowúşÚa  Ţߍŕđ°N3ńs.S6ŕ“ŰžBeeĺ„çĹÎT#”!Œó8 ?LtnđzˇéÎTľ]<׉Ë-K š‡üM…™‡ˆ[œ'볐Ό[=\ä‹ 1CycRę;\EÃF{ƒH§†qP‰Y?ýů¸˙ÁGÔď4n¸úrÜ~Ű X˛ŹíH)ciő+đÝü ľUU¸ëΛ•qÁ•W^‚p4„Ď|îŤxúŮçľX<žĐŸďýđgJ[‹gvěV‚“›6­ĂEŁŞ˛¸Ą‚ICo*GŘrâůršĽŹŃyˇœu‘Ë1œFöĺÍże8€ŔůŮŠ:@iCÍ҃ ćhŰŁ’Çç„/shы ¨ŤI9yˇx<+‹œ„GíĘ2#,Ú:)˝ßr†đÖDz­ď5łsAAÎ gQ`iŽIŁoĎNʍ˛8 ŰĘ>ʢd*łčS’ƒÝ~ §- g€A%^•”W*Ą*Ť˝ť2Y?ŇńdeĂ%Iř”°•ѝ…id31Uü~e^…á‹”˘łťMďłs°ýńa ÷ŁA­çO'P)QçęÇe‚4•”"Xť‘˛ DvŔşažń'0ěKe‘>řŕƒXž|9žxâ \qĹ:F{{;Ž?Že˖áčŃŁz´? ]­­­¸úꍹ˙~˝N]]^o͚5ÚţéďďףŇclɒ%fS ˝őę‚0ƒqK˜•ä{ďŒK$‚đËďFôöaôwŔ¨‘ňěźoďrď:țŢoĄă(˛“ Ez˘ĺĺčo=rŐ#Fď"&/ĆŃ#'ńÜó{đóűÄŃc'°nĺr\´n Žşz VŻYŽŽNüď˙}/žăf,\Ԅ믻Ye$ éŚ1ŁÄ°?ţƒ7ăž_ýßúŢOs#°œjë@ggˇŢöąÇˇ)ƒË‡ˇ\vĽ˝+zBŮÚK{,QÜń1˙”/ďÝ7’TÝI‘eş^ŢŢ=Ó[HŻ5ď(‹ćěuŮϟ7yq}ÎńőßÖń¨ĘšđIˇwŇ6a…îßß pGI´\ńÎčŒçĎPgS#ěÁ(yNˆ&g¨cpVzÄĂmB,Ëű%‚ B,7dĎľ F…M9Ë0íœlc˙3=(UbVD?!ż:zÚVB•iFŰbéTzŹ!ÚEJtZŒa÷Ž“8­ÂpJ ZJŕJ(Á*¤šgÉL}‰,ŇĄ $ŐHTýiÔďF(ĆIŐ]Z_RŽ‹TÚ’ĆFüěÄnMW(AŠśjÝíjGăňĽH-^ƒ‹ďş ;ďű%úŸŰ‹Žlo}ŐkP˘ěĂhIɤçEęЧžÂŇĽKľ500€reŁR¤2öăącÇôč{œĎ˙>ŒŐŤWŤŽŘƒĘ†Œ`Ϟ=ÚËŞôčjkkqk’IǙZV1ů}ËcƒçÂ~Ĺ@Î?"n 3݈áÎÁ”búFíËB°´ žňŠóîM7îlîE4:Oôŕޡ˝×}äčPĆCß :ÚťpęT‡†ąiýz\ĺz„•Uk—ĄeI3üÁ JËʰqĂXŃZ”ŠófoÚ~ř3üúá' G040ˆ ZŸÁë_{7îýĺ#ˆŃe<QFGűöƆ ×ŕégžS˝‡It÷ŁqQpŇ2űľPCWúŒöLňů­\:32˘eŰcôܗ“5âɕKŕž[ÉÍa’P`dž‰čó†5R—šěoÍĺţĐő@ň{đŮ1ÇcËvrdiłŹ+–ŃëJ:ů˝ôQ|ŽŃěX#9ż˛#/xzŮŮ>çőfz?ŽPĆuš,몁-ęz5œÖý9žČ+Ř$äFٜ[HÂcArĚťÁˆˆ52 ˛5şŞŸB|Şš¨:“Qě¨EI"€PŔB(čG RśFzRŁĘ."¤DĄ@¸%rYű÷byŁťCËp"ĹsŸĆ@˛Ą°¤žKVĄľweŞ“qŃŞ‹Đľo/67.ŐጇŰNáŽKŽFŹű.^đ'Ř´ ö Şëýč?ֈĘëQ˙˘[qÉm/ÂއA°ĽeJ0{ÁË_Žş;oĐŢU“ŮĽ]t‘ţŠS~w0#ڒœfŘĄş´mĽćÝyçú›—Y×ŘŔ´q)pIŽŻ™ˆ=EyĘSϘ( Ë‚!˘—pqK˜˛ŃŠŠ*Í˓/Wž”ĎWă/yžĐů™HÄ0Ëę/¸7ţçhýŁqa5Ş•ĐÔ´4‰KBA×xđé}ň;Ş„Š`Č ,eÝýĘĺz÷TľńÚ7ţ†” ÖŰ׏ŹY"Ęyůŕ ,hŔĘ śh/#Š[)՝¸hQ‚ŞŒ˙ţń P__Ż]Îý‰Ť SžŐIę3é,2杆Óg$Ěą8-Żo(4šG‘‹´ţéäŒ6ѕß(ĘůQŔcĎ]џKօœ+ZÎMŰť.ňNH{•(#w,5ŠÃsKą‚ôL`ś”Sá\â\ď­"Ű´Ż,X€ŠđĆ?ř3ý9ŽŔÔůĂźßšdŸořˇ˙6z^cc#á´É{ŚŹB— œkDÜf4ŢzŃ$őś<Ĺx—łr …Bşçˆ°ÇhhhH ]ĽĽĽşQČetľŚf’fҕš˘—›arů›=TÄ$ŮL*á‰Ű[yŁÖpoĎTą•<× ¨ň.ž|ˤë*‘ŠçĂ2ą ĽĺvŽG̔+ŹŽ’˛*,XԒێëđüZ–Ź(¸ß%ËVbüQzĆÂăńXŔäU ÍÜ Ś×ŰňZ˛źÜތJD1R_ W,Ś—ŻŘ2›ĺáČbՋڜ›ĎżËÇc›˛šű†IúYsmýżžŻŒ`ęÓá—Vn4KţMŒ8bţ\‡Űä—eŇň"ďžĎ{źßÂ⚐|Ţg‹7”ŠÄ˜„š‹y8‡<ďăŕ X^›Ŕ4ŔĽ›HŚ ŢçL<ľ„™‚ˆ[ÂŹĽŘź ů‚sOíÜšS C왣ŕ°bĹ <űěłz6)jp ŽÇ< ńc^ć ŕ|#`œ:u ÍÍÍÚ5›ŰQźŕ7óĐűИ!¤ •y˛F*Ď<ÝÝÝşL<^ooŻžOáŠĺŞŠŠŃżY޲˛˛œHÄkpÁčőŚ‹bÖŸ{î9-,ňúą şşşô<^k–™‰GyM[ZZôľ/)"7ÄTËëý&źNźžĚÁżŻ'ŸňsčĐ!˝.ËrňäIýÍQ†ĚýbNéőĆű… ŞJß‹/Ćé`ňyšaÚ(pď1sjťš˝ż˝źŘßĹ`ęďqÇćňË8Ń:Ţ2y—™2J(¤ œ[LçË(ćšČeš#5^˜—¨HŰQ„I°<‘ć÷ČÂŃŤĘC'œ#DÜfcźV\Sćt €B‚ĹŠ+L”IńÁ58Ú ]ś)°ĐƒƒÂrLÉFĹ" 5\Ÿâ nĎő(̰ąIqétÄ­b`Ł›ĺcňN–‘ŁÔ° ľľľş\œG‹Â ËM‘ŽÂËĘďóĺáAAŤŠŠI—‘ĺăßĂ4Yf“p”×’çCą‹çt.0^d¨Œ˜ÖÓÓŁŻ!ďzœą|)nőőőémXnŽÇkKÁ‹çČóă߄^‚źß((žö˝ŕ ó´`ňÜΐ‚Ć˜óMŻAŢüűNď>WfŻčĂůů^`^ŃĚx]y‡Y÷ŽKáÔ<^Œç ďIďţLNÓćoă•č„3űs^§œoĘlĘÁăąź^qĎÇ{\SFî—ÓćţθůčA˜~L'\~}ĺ.ÄźŔ$ť3Űrňcš—¤íńŕň†PŮň„3!—[Ë+çyL Uôě‚p6qK˜1XnžŁ|{ĹŘ0NiçćIŸ˘=VŽ\Š ŠĽ(hP„ 'wŚąĆy‘8Ÿ"Ĺ 6ú(‚p= ]ÇřÍmŒ€dBÚŚ6ůa™yŚN/'žËhx˛áĘe,/ĎÓx­˛MŻ Ż?Ż•çxMř(ËÉ2˛ÜM‡ËϕÇkÂż#ŻE7ݍAâ˙Ţ-šŽWźdß~Čm/˝ôRěÚľK{ÉŠ‡‹7,wÔüqž# S$ďbRœ¤îüý,ˇ>˛ó6ąôsČű—Bš‡(€vvvęűœž‰ÜŸO#qŢ+\ĆcPô5žŒÜ—yny/ňŢăô‰'´řÎűn˖-z>ŸwSwqšőˇĺ2Âű™Ăąs;>w<ËÔŃŃĄËÄýŒç'ËÄoóüą<\Ÿeçöœć2nkŽŃ˘E‹œ1Ô9łŹŚîĄŘĎý ‚0ÍHq„<ÁËňŠśitSŘ÷r#" ‚pšPŘňQœL׍•žˆąÓ‚p–qK˜äwÂi{Äf%iYĎňN›Ž‚)â Çc#Ó\ŚQjÄ#“GɈBüfŁŇ›œŢäT2ëaälB1ˆe0Ţ &7•™ÇožŁ7W§ÜŽó¸ §lŠÉ“5đšš\[&Ż;ŻĄń1ŁîšłĺýVţíĚߏw/źŽfT “č\ŽG ËËó1!‹—]vYî?bů\óžăú\‡"§yLއÜ÷GÁɔ•ÇŁ@ĹoŽ–Ĺýp>OqŒ÷śƒ)ƒń䢸Ďő(q[ŠjźN<&_ăĹĆň˛žás!■L3ÖHƒ˛P}6fzž`yGLtëvÖ]YŸŞš•ýÁ˛X„ÓŲhóŞÎ\őíSϓĺ UŽQŢZb€ 硄×n3 zŸĎÖÓ>ë´´­QąÇ4ÜLhšWĚ2#fyĂqŒw‚™>WůgXfŚäRŮ]ćˇIĎFŚ U"ç{d5–…ĺ2""?ćehĘhŽż Ľš o8â˝ĆÄÜ+ůĄgg.l9÷¸Ďr„+Ç~°Ć<°Ź}j<ˇˇ‚›YđC—–#›I#>Đ7ň÷ćˇú0œ™Â•ń´˘ ĘPf“żË¸ '3 ;3Œ•Ë*Ím(™çœßÜžĎ =¤×yôŃGő´3J¨úH‹âŸy#šńXÜ?á7ËȐYžËÉg‘eŕú\—b­űay.\—Ç:rô(荥ʢëOľœeçůPĚ3!¸\—ó ćá̘Źîš—!ŠŢÎËóm9‚–?Ÿˇ†“2şŹ œ C eˇS(Vϔ#{˝ źáˆó°NÎ+"n 3Ž|/.ď|oh–ĺMDt/#Śx=™Œ`•Ÿ¤Ů›ŒÜaF;˜Ü>ĆÍëÁĂ2o'Ó(5ĄEF˜1럫ňćò™œVůe2××x˜œŻ2Âä3eőŠ„Ţ‘6§k´g–5‰¨+öCąx{˝vôyžýhYą ›nşmG÷cׯŠžţŒ_—<€ŢUćw>{ ĄňĄ8U ܡ9N>&œśPâxŠe¸ŒŘ5eXG*qŻ|ĺZ$(jí߃ôđPnąxh šÂcĺ幙/äÉÓf`˙Ě@#=?šœ@şóŇŻÄ­0~šłw]‘D4‚ S#–Hâţ}ŞłŻT?S–ĺ2ڋtDಟ#—ÎŁúI8?ˆ¸%œwŠłź˝qްÄéĐň˝‚ŚŚw>ÄíAâ†Á”)żl3E(ňĆĺOTŚ™$l‘óu=˝˘Žů Œ<“yp‰ŘUS§x†c/$ëƒĘĘ*d”SYYŰoťˇżîUřĹŻÁ@g;şNŠRŠŹT:ƒ5kÖčĐDz/1$yăxŻ?ňčŁ7.TÂPŮěn{ŞsŠZż5—\KŐ?Ý?ý>’÷ŔŚă8Ł>92ŢxëNôŰ+4OvŒB#RގŹĹ7TÉüs›l˝ńś+4żP'şŢ㝫ü-Śöˇŕ‡Ď7=y9R˛`ÁäŤŰˇo_n„\“Wb2Házě|şíśŰ´8}˙ý÷ëýłă„ĄÂf0zAŇë’űf˜1;zčmÉyžÂŽŽˇň<'ć%Ć ôˆZŽĐE—g[çŰň#8:˜Ĺ_~ń9ÜźžeŃěŹSeíŹkjzŒRĎýQhJf/–ç_3Ë˝œm-Ë 9ôŠçg0žĆ};úp¨?(˘Ÿ)çůrźˇźöýŘý ÂŮGÄ-aF’/xYšŽ7'— MôĺŻ(s Š+ôźóé{ŢƒćYk7ˆ1žŕˆzîţö6˛:„0ŚŤ™Şú:\}ăuXľ¨ÖŻÇS[ŸÁžCűLŸj|–"ŹśśŘŕe• Ӆ ęFđŁ=†€Z'¨„˛BŢaŖÜČqŔô4Żźű2űŸp}zT6/A´š~Տ74ŔßzH§ ó“€BóϙA\Ě.ŚÓƒË™łÎ¤: &7'áhÁF0cÁœwĆ;˜&ŀɫ7Ś3Ľ@}•ët~`~Š\žšŇˆZ0˝Ą~řŔÁtJp°ß§­ţnŠ8˛ćĐLŤ?.ó~şŁŐj!3Ť÷e~ œ%'JńŰ7ú7Ăy) 3ǖ‡}Ą%l)ť4ԝ\ĆsËŠ|šýÍĎúG8߈¸%ĚXti1Ë#pŠßçÚ)vRő¸ĹtŻ›ĺ›y™a:qîw%Řq}Ďëçy N{Ćak2źb¸žöĚw?–/UeĚYŞ^ÉŞF,˝%¸ęáýđýwˆF˘čŽŁ˝ľýşţŠŻˇTĐ;v`ďŢ˝š\r€ >qVëÉÜßÉŰTʉLyébň…,ËŹăYž/xĺD*ÓžĂ$˘˜w9ň×óě‡+ŚúűěéÖšśşˇ>dű)iř ó >Ű´žzęŠ1ƒĚ07§9ˆEn3¨‹YÎĐă/}éKN˝âÎăžčńĹ}q]†sóßŃ”^^^Ż-[çšąF’8[DŽBÓs÷G‡&şŢy–Ď­mÝhgÝrđYć ʔ¨ú™˘VFMgG ZzړWŃĆČ´ ĚzĚsƒŃ%ŸQB—Ÿżý:Qç­ó)‘‹6?&ߖŢĆť]ŢžĹ@Î"n 3Š\ţďź\¨z1-[{ŹĐž ¨Ę6ŕ‹áŘîŻ!\ڌŞú Ę0”[Z˜;Đŕîm'ö~]ß놢ęűßŇPŘ{Ë]aźÂ\cV§ę– Ü~pd]՘TŇO?S`7#áJĺĚĘÄbęßf;Ěą;y̙‚‘„ńÂüdT˜`Śźƒ3(^9rdÔ<ŠcŢ||3sţ~X?ÁÓ¨S—Í#Ć؍FŠ÷|[šôŐa ń {‹”ŘegržZ9AˈYZČň #–0—0"”ÇÔ+HYŽhĹiŽŒ¨E,ŠZ>3ß#jyöŒ­‹Ä.΢3ŽœWƒ=ÖŃB{­¨ş5e¸ ű04đžúůëH1şj@ŇÉ:92˛ŽM˘çăÇx—‹}"œňŰ|ŮűÜ6Šă‘e9ƒ:š÷{8˜A4’AiÔŻďů€ßyźöfżŢý y˜Ę$ç*ĎߞictŃ`SČđš+G‰[ăĺĘ_>°UC<5ŕŠxR‘ Â9‡ő“eŒ"M^]6ćE3ë'݁číŠ]şŽ6żm×Ë-ëńb՗.  FŸí×ßFŘʉZŁ.H}'ĚMź^[^a #r–oʰĺɡĺŹow‰ň“{ŠŘ­Ľóđ‚ œ-âMŤĐqëŸ8 Ió€§Ë!̓—èĐD6Ş]­J \a+'pi!+ëźx¸EWŽŹ“oK‹Z0n§Ć¨Qłf?ŁÂsu…Çóʈ[Ł<ł|Łż˝ËMÂ(qŹŔąá,"â–0ăp*Äźź[ś3:"ÉŮA+'xѓ%@o­Ź#lqŹÎŸ`DŽŻ Ł;ޤN8äˇ7rf„5r;"×Čozpé{›áˆœXšÁ ymĺ>bDLL~h˘eöŢbű†íœĘœzĹß ě™űP˛˙ {NŔ7ż”T$‚ œ …ëm&OU/ÂđĘË0¸ńgđŸ“űfŹ×–5ż{=<Zđ*$piáĘvĂ˝ů/œ„ó9Ak”ŔxëxK Ga.0ގp=¸ň…-+σkT¨˘5FŕĘ [!gˇ„…׊"><#'ú|ŽĹ˘űV–ů‰ld´×Ö8–1c$u‚pžąňźśô4Ƹ,wdPżĺ ]nȢ5z˝‰Ž#¸xCVœ€Çí~dřjŰÉŒuŚ9› ĘÁ‹nÖĂÄ; ý˛y1ÎyÓŁŽ#‚P§,o]äýř\ËŻ_–ľŒ°ey?ÖháŢ{œšúBČłŒXEňFĆő [şžwëřÜ<=cęńŃ ÂÜÂă]5JŘr–YyőTA1Ë[wě cBGí[Î"n 3‚|QŤ÷–3_5öýĚ˝eů6˛jc~|9Q 9ď-=‚œPFcÉKűS8—ŒóŢĎuşňâňYŢÎyg9Ÿ1ŢZăxm‰QŻąćőŢ#růQlÎd݆'tĹÂ2*ÖYB‚ ŒK†ž×ëĘäтçe`rŰäÄ-+OÔňlďýĚWLŁÚhTN%ntޜŘĺ,ŠĂľĐ•¸Fv0Vŕ„šĹ蜡ŁEŽŃ[…ĹŽQ[ó˝ţÎ+"n 3šüş‘™p˜4ž{#béů>ŰőŇrE-߈¨5Qy1U„sÉ(Ó!g4ä‹S#"–şktô‰5âľ%í˜3ÁӐÔ9ü˛#Ó:B1››ś\Ěö$+ÖnŁůŢZBXAĆR¨!čőŘźůmržZ^-ř•Ä0Ď^…źˇĚ|˘˝Ż,‚0–źcž'Ĉh…ź0E Ż5ŽŔ•ŰßčcÍYLn~ć \žQ"Źď-Ož.݇Nô„šNžŠ;ĄĐ…őĚD–(ÄÂ9BÄ-aĆŕľMňě”ńëD×c+_䂛<~ô~ź=q„óĆčűy´ˇŐŃĘ#\ĺ‹]c÷5Ž! U.ngŒŔĺ́“[ÉT4/0gÂŮ]~ĺ"• ^Ć­´Çy QËű­gO lwŹšL‹ŒI2ďšÜí쑗€Gěňî[ęqa>P žO°*VÔĘ_WÎ2"n 3ŠB—éËë|ËýYÇšČH~-ď÷Hĺ*íMá|2^űcĚ7Ź‚ž]…ÖË߯Ř…Ý;?ŞBń \ž‘´ô|ŸëešaˆŁ*–‚• BqŒéŠČŤěG‰W+xy…­B/Œůä՛ßyqDŽü͐g|şäźżćÓ5ć=E Tů^^ă=#bŒ 硄WŕrfŘăŻcyBÝeś%ŢZÂĚf” 5WÁo1!öĂiŻ˜{œłœ°DWź2"—ˇŃY(yźxm ‚P ĹxoťP@Ě@ؚĎxëhďlŻČĺ]o˘]j°K˝.Ě%Š­/&†§°ž œmDÜfنŒ-âńâšhŰŰf”r 6‰0٘¨#ŹĐt!!l˛ýůxźˇěźď\eăůX9÷БeŢ5žŠE*AŚÂ¨ Űő5ZÄÂĢ–w_óŃk+ŸID./yuť_A˜g•ŰUžá<#â–0#)$pŻ×x"W~hŁÁśĽÎfăÝĂăýžĚ[KîńqUЌ#p™őźëŔz˜/téU=šZˇA˜c*í<ĘYŢé‚=[–ŠĎć!ůס@-˛Âi"F§0ĂqK˜ąä \fިŘEo+3™‚‚Užá=‘ç˘P,ËËÜŰ(,$lyś3Ť ‚ L•‚\VáߓšöJE4>S}QJ‡…0ŸCR˜ĺˆ¸%ĚhĆń*ë‘UŔs˘†Ä(főOdoˆ-R$cTopĺőâ"…FŻ@Ţ:Ţú%7KęAŚ@Á |2ń …Žüm m'L š~‚ łˇ„YAž˜5Ţ2/ă‰^‚0“‘´g™‚oĹźpʼn*#łA„b™j|yą˘ÖdűA„9†ˆ[ÂŹŁˆô ×„ŮŒÜĎÓHA—Đ"W! %,´oA„éŔšĚKę!AA "n łąáA8- %çŐP´ 7,§z(aŠ‚ x™ŠŃ2îş§.‚ ůˆ¸%‚ Ě_& 3,ÔH´§Šq*‚P EÔ!RĎ‚ ‚ˆ[‚ ‚ )*ćY‘‚ œgDĚA„1ˆ¸%‚ …8Ó¤„$ ‚P§AaÚqKAÎҀAA„s‚ˆ[‚ ‚ ‚ ‚ ÂŹEÄ­YJôÂg!‚0o9~bJŤ§^ˇ‚ ó•ăSŹ3żůF‚ Ě[އ0 qKAAAA˜ľˆ¸%‚ ‚ ‚ ‚ ĚZDÜAAAAf-"n ‚ ‚ ‚ ‚ łˇAalŰĆlŔ˛,‚ ‚ Â|CÄ-aÚ)ś(0Af*łEĚĘçtË-őą ‚ ‚0›qK8#ΤXh[i` ‚p>™­˘Ö™â=oЇAA„نˆ[”8Ű żüýK#K„sE1őŰŮŽgBgÎQę_AAaś â–0.Smĝpńîá\0^ýuŽ=šÎĹńŠ­CYŠoAA„Ů€ˆ[Â(ŚŇ°šŽFŘT˝ľ$|F„édŞÂÖtÔ}çłîšJ§\‚ L'ł-ô[ę?A„Ůƒˆ[BцĆD띊ąâ5Ś"v‰Đ%™P¨îâźt:­?fůtˆ<çbűé8†ßď׃\‚ œ ł9—ĄŘ™‚ łˇć1“§+fÎh‰ ZŊ]’'F„3…őH<ÇWööŕÇmY$ŇYXPâŽZćcݢ…gÚĚ7ËrUZÇgžoÖóîkd?Î6\ćóY#Ë1rp™;ϝܲœý…ęʐ߇+낸qq%BĄĐ¨ë"uŤ Sá\Ľˇ8SŚŞ=•őA„s‹ˆ[óÓڊ™ŸÉdô'›Íć>\î5řńů|šOž‡€1Šť b|‚P ůőŒů‹ĹđÝc ô ť˘“Gœ˛ň~šŻE0W„ňAËýÍşpĚžF„0g™GĚň™ímWd3™g=kzÂ%,Ă5ŃQ■BąœMO˙łÁDe;Saö âÖP°Q–“‡ňĺ­Ń^Wȅ Á*›Žr!ƒvÖ #ä?# ęGžĺ–*G6 7Ń<ô\'g—{,ţ°o2ŰgkËÎ%ĄwJŤWą=‰ę‹š&¸ňëÓbęWoy啗ăżţë?rËřžšüňkôôżř?¸č˘ q>řŻ˙úžôĽ/ëi6Čîż˙gŁrŒýęWâÝď~_î÷˙ýß°nݘ>őŠĎŕÇ?ţ)>‚żţë÷c:z]˜i˛3M^Öń֛ ä×oĚkěLNą3Żý›řčGş×çŽ;nĂŮ◿|ďyĎűąqă|ţóŸÁé u¤ ĚDܚŒ×[ĆožPľvâř …a;ˆńÇݢpTЉ8qx?v<ůí}^Oˇ?‚Řđ bƒƒzy´ŹL5"ĘĐÔź‹–.DzŐëpŃĽWĄYMůˈ`li%íŽÇÔ~c bLyĎ&o2…Q *hnjЍăŃ5ŐYąÜ{ďýٌ6PŒÁ1Ý455â­oýmPŐ××ăLáËýßîíĹxś$_ř}ą$vJâOoŹÄ†fI(-ĚźuŁ#cš˘źŻŹ|Ą rq99˛`9ŢT–;ĎQĽ2Jç2BV։A´GŚ}nźŁ ;Ô9śt[ĘŇB–öŘR˙pőŹ:}wLEWüânFFW4ű(îÜGŽélk>öŘăřŮĎ~Űn{f*ĂĂĂxřáGpă7äćÝwßý8[źęUŻĐ߯|ĺË1H˝.œo&ł3îîÁó–Łçx™đýH)Űn¸}üýůƒYźôŸĺ2˘’w°˘ł1IY8řłóʒAMË.şŠKVÖj!GěLGÜ"o|ăëń‚\7Śz<Ţöś?ÂśmOăŻţę}¸űîă\ u¤ ĚDܚgx zj:ކCąˆ›Ëeę١ ÷ßó <ü‹{ĐŐ~jÂuz{ô§íä1<óÄĂšůľ pÍ-wâúŰ^‚Őë/işĄ#ž]Śěʨ°l×ůˇáŒ2Fz˛ę|NayË"”Ţœëtť‰S<Űż˙<„ĺ˗éy÷Ţ{Ÿţfž0ޞ6ĐŘxűŰ˙Ó{­Ši¸rűTo–źŕ…ůˆnđŘNÂv]ƒŘÎh…Fčňšš¸,㥪˝šŒ¨ä„ZöHŇyzdiď-ŰńÚ˘÷‚´čÁÍ8ŰąaĺzxÁ`–ăEŕWő€3ÚŹO—Ă4ö(”ů|~ľiVϡmWŁ7F|ÎĚHŽîŻ Îűě„(~ěc˙ŤŻžR‡ŽĚ4řžHĽRş1iÄ-ć”|řáGslœO'ôűŰżýkLRŻ 3‰|;sďÎN<ů­…H'ýSÚëIłżB"×TŚ‹IĂĄëýŚp&ĺGǁ “˝>ˇM!­D”Cs’ őG2ӟT|5ëŤ#¸Źą ×5WăúĹŐ¸źŠjKШ:Äí¤ł^*îlÇíS‰¤ÚgBď;“θÇĘ ­żłZd3eąsÁĹć⚞gŸłžž^üűż|Âő(.˝ńżŤD°ŕ…/ź˙÷˙¨ë?ň˙ř/ş4Ą3Ö}œĎ=?Ňĺe¨ß+_ůZ\yĺu¸őÖ;ń˙đOęŘ=÷ŇK7éoŠYŚŃhŚ×Ż_§šŁCT^őŞ×éc>řŕŻsóŢůÎwëyʇIwwˇŻţ^ŸÇW\Ťëę/|ásuôżţëGőú&¤‡ěÚľďxǟá/¸Y‰l/Ä_üĹťôűb2¤^Î7“Ů™ťS1ea‹čşLŐŠŚ^3bŘŠ~ „˙߿۞zžţÚĺxćWbǡŽĆÎo_ƒçż{Ü{ý\sbX!Rą ž{°lŢۙ?ýéĎőşôx%ozÓ[p×]/u,–‡u9ˇ˙ŘÇţƒnÇÝwżB{mÖϡßţâI—ëŇ˝č˝˙w˝ë˝čëëĂDH)ó ńܚGäçӊLjŮÁɇÖňp`×|ęޅ};—“ßĐ"UeeƒęQ*›p[ŽËO(QżŞrócąAőrjWŸě~ö)|č˙ý.V_x1ŢţŢcőú n{,/7— d´ě\(P,íÓçdÎąŰř™rŮe[đŰß>ĄbđżŻ{Öř‰D"¸đÂőxôŃßNiLĆůüîŠc2Nž¤ýë‡tCçž{ž[p›żů›żÓĆCyyślšT'óüÄ'ţ[5¨zTƒč˙{Źo?5„ţŘřŘë//ÓWő+żuŒŽűÝmCx͖‰˙Ž‚0Ű(fHútléDŒV7L꬜§–™śł°•°¤T&-úűŐs,Ť„/u’ÎsE%‚q:™–úś3Î÷’Ę0.kŽÇ†ŚjŹŞ+GPm;BÁ 3RŹóqĂ$ŐąNô cW{/žkďÇŢ.ŐńPëfYˇüđiĎz8Đ}Ëďx†ůʜ獌č̓xöyĂ^‡}čĂřя~˘s˛lÚtń˜už÷˝h‹ž›7_‚cǎkÁjűögđ•ŻüŻŢŽëPtbކż°Ţ=zô˜žfä/ůŤřřÇ?‰ššjš{÷üŕ?Ôë}á Ÿˇ| ,ŔâĹÍú˜żůÍĂ:ÉťiT^uŐŘłg/ŚĘ{ßűWşˇfÍjÜtӍjżé<[ôöxӛŢ0f}6FßúÖ?Đbô€ŕ;‹eyúéířÚמŹĘŘ4^f…ěĚŢ•8(l™\Ş^Œ×T<ś2Y ‰ÁńĂćRCŘـÚnâNÂŽ#eĘfmGUŐüľ3YßŢyçíş3°㪍ŽÔÓß˙ţ=řđ‡˙ĽĽ%:/ؑ#GUö %¤íÇ'?ůqíű˙÷•ÜqnžůŚIçľkŸ}v‡ŽŰ-Z¨—=đŔŻľ7ۇ>ôÁqĎ_ęHA˜_ˆ¸5O1 'ÝňđŽ7ÜŽ_Ň˙ú埌šŸJ&đĹ˙~ú/hÁWľľ Q]ݤS$˛ąqM—]˜ÁňĹŞńśĐFeYĽQgCޝŘ7ŕÑS÷ă™Ý~lŰĹmË´0ÖаDő˛ˇĄŤëöî܎wžé.ÜńŞ7ă-ö„t,żkD¨ŠżxóÝ:~ćc˙űýË?Ň <[ŁÖlٲYV|a3-ä˛Ë6çÜÔ§‚i8­Xą\ďŐű~衇յ­Ő†H~8 4Ü>őŠ˙ÂŹŐĺ`/\ggç„çţ؁ř¸ĺŘ´8„K—„ńÁŽörŘz8!/xaN“ß#Źăü‡vÁěSbT*çědĘJh;Ţ\ńaă1Ô(Á*VRŽĄUëŠ[›yYXQŘRű°UC-ˆ,^¸˘ˇ­^ˆe5eZ°7â´—Ă0,%FUW•(Š……%XXōË ?‘ÄcG:đë#mP˘XPŐş!Ŕz ŕЋÚcAç(ô9šŔrÉđ­ÂW!ÝďLęTŠ5×]wk(`}ă_ľœ×ú3Ÿů=ýÎwţ™ÎG544¤=¤XĎŇKŕĺ/iN€zôŃÇpĂ /ŔŻ~ő€Ţ憎W ŠR\ýuhjjÂÚľkĐҲX'I~ń‹_ŚCýýýă†D˛Ž˝îşkńŐŻ~]5ř~ŁÄ¨tž0ríľ×ŕsŸű"ŚĘŢ˝N˝ţ{ż÷ťşŹř>ŹĹŽBЁĺ`ޚ|ä_ôŹÄ­xlĽeŐúY*OÄqňؤ”Č,)ÓyśčŮeŠĎíŤńúMËP t.p?ž°‹şşĘąkĘCAܲj^°źnÇ/´"ŽŽ´ĂđëőFä˛uŽ.ćă˛}Žç–ĎÍf.ćłúËżü ݸĄ§=°Ř¸2 לśvU×wëi3 =Ĺ*zĐ ŕšçž×âÖíˇßŞD°ĎéQ qëA˝.=Ĺ/&\ţĘWž†ăǏJžĚ2ŒŻ5˝ľ(nąńĹş˜á6Źc)”NCö…/źEŸçťßý~]?s?Ęؘ,„Š×ošĺćÜźbGQ”z]8ŸLdgžŠ”/n™zÓxsé5XŸ‘cËW¤¸eO!lŰk_Š ´ˇwäňp˝óďłœ‚…ť39ëyŽG(ž‘áá‰sI)ó ˇć!˙ö城ú˝ű™­řĐ;^Áž^NŘÜź‘ˆ3jâMWdđť/Maí2Ż2ľ:әp?ü8–ÂgžÂŻ÷ŁĄaŠęiŻW”=8´oţâwáƒ˙"Ö]źE \ýŇźg4ćŘgË{‹ű˝ýöŰ´ŃÁö@ŃUœ=îfä˜|ź9؋ĺ…ßůÎ׾{÷3Ď<Ť÷÷ä“[UÔ7UcëKę”cş`‚Ě_ďéÁş÷ůŢý˘*\ą,Œ§Ž$°ýŘؤÉW­ˆ@„ńp…vo]3؏L2_0¤CWWGńçW_„Őuĺc„+†!ötőÂRŞŠŠ2„ĂS÷p(Ľęşe¸ta ~°ëžlUuu8;¨ş1čzqąqgë`FW¤ĐeM!×éŔó]¸pŢöśˇę°A†¤D"a Oi?wÜq;>űŮĎëQ OjŐĄ|őőu:„‡üÓ?ýŤĂx,6ć^đ‚ëunŤbĘG݃%KZ´§Gv$“î8Q˝ţţ÷żG'ĐčĄGtÍ^ Ü/ëvzNL'RŻ 3™3¸źâ–WÔň’/pĺ{lLOnć{‚ÇŮöܚ­vŚ÷ş|ęSó÷˘0uŚxŸb<íˆÔ‘‚0ż„ňó”b^ÎO=ň+üőŰ^Ą…­ňň,_~ąś/ČⓝŔżź3‰ľËă⛖ϊŕ_˙2Š÷ÝÜdëc-_žQťƒ}řŔž[yŔ)œé!s~LůÜ΄믿%%%şą200˜űO4꼏?Ą]Ť ]Á˝0dć‡?üąîŮ˙Ď˙ü~ţóëa™éęm’nz1#ŇpŸě…#ě co]¸'J*˙ęÍe¨ˆŽ<ň˝ĂYüë/zńÄážšuhĚú\÷—–BćĚYupăŐŘ˝l=v/Y=ü´đł {Ő÷^ő˝Że%,^…#Í+q*BĆć÷q${‘IđVÓ/Y݄Oźd3Öԉˌ9˝­“Á÷÷ b˘ŞŤż'Ovb(–(¸ź$Ŕk7,Ĺ/\ +•@’‰ë•¸–ÍŚ„öçX:Áź›ÁĐI8nňo14ayěÝ÷ [ ¨­­ŃÓ&i2=§{ĚńœcRwBъůşXç~éK_ÖóŘ4 œŸ˙ü^ýýéOď~÷; ćöšz†‘o}ë;úűÖ[ ‹[ŚŽßžýYýÍdĚl,Xw÷ťßWuűNźď}ďV Č˙Ă{ßű.˝ě‘G-¸OSŻ›ŃsĐźâŻÉy¨‡ÔëÂLd:ě°ÜyIĺ˝.ŁÝc.ó]0Šü$ř,_т 9›śćl´3Y—WW;ůtůˇšôŇKô‡ůł¸/ tÄ\cy&vm1H)ó ńܚŁL’8ôŘúçżx ń˜ljZĄ†^Áţ Ň’ł× ş|ŁŻý[˙řŮ~ţÍÍkĐÚz==­řđ;߆˙÷×°n“ăÁžDócĎďl$üdcćea‚d2^?óĐaC#xŐ×׏éQcş‹3!&÷Icƒa:̃`\Ž˝0q'Chč đGô÷€†C˙–.]:ĄaZX\Ŕsą‘^*žäżţÄ`ÁőšnĐn’N ÂL‚ĎQşe-˛‰a”ÝÉÁîäŰŇůý˜ŻŠĄJ0 $cčV‚ÖĐŢg°pxŞtl ďšu îXˇXo0^Ý- #‘Œ"‹#ô;˜! 'Nvhq*‘LaiËř9˜.^PƒĆŇ(>ťí †ăjżŞž šăŒ“wFuď×][Ž÷–3š˘e]‰‹×”9VŢü淎jŹp>“&3ó§0ż 9­­mڛʈN„!ˆlŒ}ç;N¸ Íęęju}úá˙V­Z…x0—tşnťíV]{=š Áź7ł˜ď塿}¨ŞŞB__ż^Î÷C#YzGp_F¨ťâŠË îó-oů“ŒIž9ňßU ÇdreŚ3RŻ s[×{ăylé5ň–Ť÷V1查ߘ}ţłŃÎäüˇžőwń‘ü;Ţóž¨úî2rNo1zٚ°s†2üóŸ˙˘Ţďß˙ýߞś][ RG ÂüBÄ­yF1sl}čO^Ÿś,XŠ ƒˇż6ˇźĚ¸‰ŸÝŠż$ üĂ˙Kcy3đŠŻűUVčů¸ţîĎނ˙ň°°eé8#):Œ'hM‡ĐōŽĘƊq,̛đ/˙ňa=Ü;“łÄQ_Ţđ†ßÉ­ĂĆ žäůbƒz¤˜?üáiWrzäów÷7zŮO~ň3ŐxzJ÷ŔqŽBŁpĺsç†<*‰Én^[ÖE!ĚhÄł”š…LöŮö`̇Ďüđ>ć}}ŚFéůĊ–Á ĂMOĽ-'%Ą;b"E/7§–żŹiŐ`ęPżWÔZ¸iYíäÇPŠŞę d+Ja”­B5^ÇP(¨ĂŁŃńGü˘wYPÁŸ^śŸ|r?ާ—?tZx4ÚuN.K{*ĐsˉŘqęD ŅĺœNJĄćľŻ}ľÎoĺĺe/ť[7ź8âáśmŰőH[wÝuŢńŽ?Ňó l1Ô0ŽD;ŠFl„>úŃŐَĎé°EÖľüŕ‡088TTŮčvńĹő…Ql<ŘxëččÔɔY?˙Ţď˝E×ďßüćˇőrţ­>˙ůĎčLzP0|˛ĄĄ^ XoÖëbőęUřÜç>­“1łü€_4öGô‡&“7H˝>u¤Î<űœéőo´DłďBˌ÷–w==żˆęjŞ^[gkŕ"Ăl´3_óšWé2ąŽgXe8 _x3ţüĎ˙TçR$ż˙űoѰčÍĘçđLěÚb:ň̑:S˜-XEĚ÷Ś7Ó>ϡůřÝOŔý„Ô‡ DŞ’ÉÔÔĆ­rx{ X‘°RĚ%Tœl;ďôČĐňÎož\vŒvs樈ďză8¸{‡EdŽ-V&ď{[/љšŸ.ßý…˙ü?>íľpüřn tcůšőřč—îqGQ„ëí`オLîÚ°Üćc~ÎśQ2“yöx÷íŠáDOzLÍʨ‹TŻŐ ŐËý˘E!3lčçv4S áÁP~O7ŹżĘĘĘ´cFÎň2Q9Ydzăźŕ~d˛™ÜKĎšŒŔ•Ő#!ÂćHˆŞ—\ \ŠŽV,ŢúJŐ1kjËńž÷ż MzýŽî>RXVEó˘†ÜqňGKtęçŃuľů­Ď%AP °˝Ű;ë0´ńđŃV]ˇ-nŽ×bÇP Ÿxňţ ‚Ą0Úäľb.ËĐŁ(ú|Vîţ~} .yűƒš†Źů°Ěůó -3çĂˑTÇűŐ§—b"6żîYUąeąőŤ‡4ßţÎcZtΡ/ĹÜŮHyzH9śÎ”çűôQľW¨/*ęé‡7UÚýdÜOÖóą=ßće㝠Ä;ˆçÖő5Ÿ.ÓÁƒŰqpĎsřâţţŕÝÇ­ş|}ą ę íŇm8=lł &×ä'•ąńÝmCzČcŽ ĂšĚ3 îŘ36@†††fŹąa`ůřĄŃÁ^Űńzág"śĺŒ'čţrÂőožgę̰D[‡&‚a Ę6Á>vÝ]Ř˝{jkëŕWbԑíŽĹѧ*˛úş*ݛ=i%VőőĄ$V"~ĐńŢbxĄ]Řť‹u\0pŤC§Üu%źĺâĽřÄVŽčä6 „,-Îe™\ŢőÚĘşQ–ÎHŠ&—ԝł Š×'FęĚŮGĄŃ‹őäň6D§4Z˘eC˜›H95¤Îf+"nÍA y%äÓ×ׇ֘Ô°˙šířé7ż¨3ĚsĹ^ý[ŻľńÖWpéůuűdľń‹‡ýڛěĐĄgđcUÖî|9VŻŰ#ÜśĹlÔŤskhhłéŞy.Ŕůkś”é0{ 0Í^őل1>Řf’ĘÎtlO€ž­CřŕZü­ł˛óăznŠĎ•Kęđ†-/Ŕ'ţóŤZ{jës¸ôŇMÚآ8Eq‹‰ęÇ3ź‡  uýtřđ) ÇuƒkŐĘfŞ6 ql^Tďńsć/Ž(Á]+qρXęř–Ďuźf.B sœGĎ-7Á<ˇ ŕĚCŠ„óƒÔëc‘:óě3Őúb2ëËÎZÚŐť˙І(ŤŘŃ-]ɟž­+vĺě@ęČɑ:S˜ÍH ę<Â|ř;SH"Ł–}úŸŢ§€šš…z¤Â–ŔŢ7Óđů˙|ŕTC­ şl,#Ëúß˙ôĎh_ĘňGĐŃËő4HM˜K0iěl38ź°ě<‡™ŽízG9# :"WÖьT˝ă Pa+aKTďf‰ĎĆßßrVŹXŠĆĆj˝ÝťŁŤŤS‡ŽY݂ĺËᢠW:ŢUůÇS;O&RđůÍĐő6≔;ŐČľŠăęĹuXYA:—+Ă ?bŮ´ Ÿs~\Ůő䄚€Ô™3W'ЁěŹƒíe:ďÖdŁ%N´ĚńÚň!*“ę;Ť?pfÔ§Ź>Ś×ěÁC˜ßH)ĚvÄskžÁýŔŔZůÜ{ţú[ş{wlC B}˝“á=ŔaĎgN/Ti đ>%śýŃĄËŘ×ׁ˝;ŸĆև…-×ޔK‡ÜšÔ9ŇEUzфš_Ösá…mΥаć3 {LjuŰĄ5ă&d×J˛J0zÇľËQ[FĚW‰9şëouň÷íO?‡ ęý45Ռä×ʃ5ľ•šüYôđjR"Y[{JKŁG‚cśĄčuřH+–,™<á8yŮڅřČăöűď­ ˝¸\EKC)äšg*łŠ3g.>ż:Ÿ: ŢŁę˛táuŽ?° ‹ŽŰޞځ1ËLNŻbźš´—ßÂľoj•‡Ë;IgŃ{˛ ZA˜ŻH)ĚDܚxS|‘÷ö!Ý;ő­˙ůý][ťH‡#Ţt•…+.žyÂĐĺްńŔoýşŹmm‡đ­Ď˙—ˇn΍3–ňEĐ70Œęęęœq#îâÂl†.âsŠ'ŠçÂŢô™ě:N&Š=Ł$.ÇË K̨FQ*Ľ•aźę˘˝€IG7oـűďB{Gmßž׿ŕ*Փ˜@cc­Ž[YŸ<ŐŠsj-ZX§…&î/‘H!y%×ŐUĄşŞ‚i˛ Šbź~--ŽŢV„U ăŠUx´}–?ˆ€ĺWe´uedýz81'ߖ%â–0ë‘:sć,q>ăS†îgŻQ‚p–‘:S˜+HXâڐ‡@,CgœS#BĎÁÝ;ąçŮ­J (AČi,ýţŤ}§>˜H_ť§Żý“]Xý‚'PąîaýYŁŚ_űŽ]řú; #nNs˙o{O—žee™w=ł‡ö=Ÿ;'[­Ó5œÖçZĚ5„™ Ă+fł‹řxđœňĎ$Ď­‘đD;—“ĘÖšˇ˛Ů”ĽŇxëĽKrĂĚӐZ°h–-[ >t ­­mZŘ2B{gg/ŽoWóťpě¸3\XVí/)ƒĎď„[‡ß?ľWř –ÔÁÖa<)ÇcYÇͶݏ;4-ÂěEęLA„â‘:S˜Kˆ¸5ÇOź1ó)řôĽF˙Ůřńˇőwee˝ö,¸ę Ť–9#kMőóíŸvbÝMOŕ­ďڃÜۉc'HĽmý9ŞŚđ‹Nźĺ/wcݍOŕ;jÝÓ9Ćęĺ>\y‰3Œ=ËěœĂws#&’ޤ•끘ěšÂL†ŁŐĚUfňš9ů§|š1‡G„-Gܲ™Ÿ0ěNj׎„ąĐ;´´´ ›6] Ó{ë™íĎkń*ˇŽgŘ.3›ÂWuU9N‡X,ŠE˛ÁÁؤëV„ƒŘX_ććŢJëň99ˇźÂǃĚBf+Rg ‚ Ô™Â\BÄ­y{ęcń$˛Ń~ŕß{ţŽŹtFźë&zXSúd˛ţß÷áM˙ďyœlK`íÚľřŰżý î˝ď^ěŮť{÷íĹýżź_Íű[ŹXąBŻóFľîŸýí>˝íT÷â›ýn™qëĄ{䜌+pŮÁç\łŇHf/fô—šĘL;żQ#Íş‰#šˇLby%ýPJgpÇęFňFá∇_rĄšWřçŸ;€D<‘[^[[‰Ĺ͍hh¨Fóâzœ)ĂĂqß‹Ł1ćŸK!˙ŇŚ*]~öffłŔĺ [zÚń_˜•H)‚Pó•:,ć??´fJÇcŁf!-Wű˘ŁőN=„E-ËUŮé‚`Ą/žAŁ:go-yˇ„ŮFź@¨Ú\ƒçČÁfśGěa˘ő\=jťC&ŇsK}îX36™;똺ş:lźx5}äY;FŻŞ~”–9yšż… ëÜcŘ8S Šşş\ŔX šĎ‘Â8ęb 0:áňęšr”ř-$Ô˛Œ˙}œ|[t,ˊ°%ĚR¤ÎA(Š3…š†ˆ[s”B˝îŠT }ĂJ˝–ććíxňý]ZZŠż/^ďWŐÔúžó“6|ö+ްőŠ˙ţŽźâ „‚!UEÂo6ŽŘŕÓ )śœTŃŢôć7kĄë˙đíZťöŠźâŽĆ˘Š…‹×ůńŘśŒ.{'ž}ňQ,Tâ…4 \}Ă }ÎůÉEäfô:œŽŢŚD"o~óŰxŕ_Ł­­%%Q\~ůeřßy#ęëĎÜ{čLŕ9fMÝ0ƒđćŮbmaťßn’*”ý¸¨ącĆTuK$Ĺ5×\Š­O>ŻÎ/]ĎDCă§nš€lO2ťžBśí8ěD V¤h\ kő& ŹŞŕ6>Ÿ…ňň’žZşÔ뻕•Q<ۗ„/Ԟ[–ę€ŕyš%ç–0‘:SĄx¤Îć"ňWžG°'8oČĺC{Ÿ×ßѨ“ďĺҋŚ’˜HÚxĎ?ěŐŰžă‚K/˝>żO}üJÔ čŃĂÂáÂJ` +ą‹!;~%vůUłĺ˛-řËwýĽŢö˝ŢŤ÷5•c;e)űὝOQ<㜳 ĚFŚËŕ`ž?ů“?Ă˙ýßWqěŘq-tôööῸż˙űo×óŚÂÍ7ߌ?'NœÄt1]ĆM¨^.4Ńv„.3|ü–E•újźźźĐ[uqËb\rÉZýťľľsŇ! SŰEňG˙‹Ěžga÷w+K1ťŻ öŢíČţäKŔާ1n=k0ćVT—8 ĺÝDň™Ź=*ąź [Â…Y‡Ô™‚ Ĺ#uŚ0Ď­9Äd‰Ó)ôdŹŕ(߆%’PČÉĂľźĹMÜ^$ßűYŤÎŸľtŮRźâ•ŻĐšĽś§:îSßlä1d†Ł&âăKëelpq˝—žôĽřÖ7ż…}űöŠ}ľăľw/,úŘşŹ WtÔšŔĺŒçjÄ­ńźľŠőâşçžáХÚߥP .Äu×]ƒšš=ďŢ{ďוçwގŮƏ~ôíávË-7aśŃÚÚŞË˙Âނ%KZ0W ×átđéO˙žwëęjń7óŹ[wşťťńĎ˙üoŘśm;ţáţ ŸůĚ'q>)äayžąuŔ^fÔ'$ú{u­#Ş:tRŐ¨¨ńˆe%[VV†›nšZ-?ŞęŠ •Ţń8ŇŰš 0JˆÚö RÍÔ+{Ůzë5v$ß–†ľ'­öÚ ¨3u…-Ÿ›?ŹĐ›ät=^šÝg>ó?ˆÇřă?ţCÝá1ÓŘžý<őÔ6źöľŻV˝Í%8<˙ü.üć7á˙đmÎRg ł™ď˙9r4÷›ž/ŘźůR,ZTźm|6čďďÇžđ%źńŻCmm-Î&łŮmH)ĚEÄskÁÂś´žŮvÂy‘†BÎż¤Ůďää*ňóĂ{Ąě_ţň—9 #Ł‰ŮŽ‡ËJ…É‹Í(c&„†›źäî—č}ü辎)[—U—ݡZOőœ™¸|Ái–ÂÉë_˙ýšóÎ;tůżýíďę(…óE„+–ٞ˛s‰é¸w9bč/ů€žţó?˙Smp ˛ń†Ë/ߢŽ„bđ˙ýßWđ†7ünżý%ř˝ßűCüđ‡?ÖĎqgg§îI3źůÍoĹ?ýÓżb:˜™C5;ž¤:÷VÖëÁĺÔqˍ݁ĺ‹Ô˝W6fk  $oţÝťqÉ%ë zPéŁ ö!őôoĆÎ/¤0mWë%'Žo´VvbŻŤĆ˛¨3Ř†Ž˛m'IžŃíŕä›.ŘX㝥˘˘ÄL¤ĄĄA×! ­f/Rg łvüVWWióuŻ{ľî°‹FŁřÎwž§ĹqA˜n¤Îć"âš5OpÄ$őňôî5Đß~WôŞŞ4a‰ĹąíY§˛Úźys.\'ëz¤UEâKłWŔéń×óč=ćŽŇeťë^rÉ&w_}˜ŠŢZUiše÷œ‹Řܖ™/kˆNGŽ-6|źqă .P˝ŸĹž={qńĹ!œ(nÝx㠘kLNjřđá#ڛ‰4Ůű뼊Šţđ‡FÍű×ý(~őŤUoqŽžúJ<űě|üăŸÔFÉK^r—2śoÖŠdýúu¸č˘ 1ĚDŁC{nYXĚ?eŞ{$PąŠlb!¤­ľ˝}ýhiiA08~"ÓôţźŁçŠş2ĄęĘPŔ ß“>•ŽîVŒ_ßč:6Qő•§Ž×IńGFŽř}ŤýŇ{ËĘÚşÖĽ Ĺą8,wÚxüžiýÉúqɒ%ÚŰu÷î=Xťvjƒ‡œ X—ó#Ěn¤Îf;´1˝vćŇĽK´ŕőŔęÖŇŇRÂt!uŚ0qkĄ+yŢąáAýíó9 ¨’ߔFJlmw†¸_°`#jqhyŐ¸JŤ†“IĎßlq9^).ç'ă]MMΈc§¸Ż)4˘JJŹQe :žŽŔeů’sörn1§XUUUŽ7˘Ď=÷<ž~z;zzz•QR‚ /\Ë.ۢŻĹç>÷lÚt1ślٜ[˙äÉSřÖˇžƒ7˝éőšpG/Œ?ěąß˘˝˝]_ß+VčĐHăqđůĎQç=ăz‡Ö!@ü͏ąńLřxôčQ- ^qĹĺ˜ &Š|čĄGpŕŔýˇăßűÚkŻÎaěUdšřb{üń'ôňťîrźŰ8çÎçôËoőęŐú…śmŰÓřÝß}ó´œSžť|~ЁĺĄw9xđ>fOOĘËËąaĂEZ œI LGÎŁžž>ýÍ{ψŔň‘Q׼Lő˘ué^ľŻ}í›xĺ+_Žwżű9كÓÓ*1Óň;ĺF2t;ŠŮÝiËńŢ* ů'ÜG<žT÷f ˗5ŤkďÔť…Î2ŰqjôoĽ,mmŔOŽŚp]“7,ŠDŔ[owˇ)qküă2)źđ畚–ރ=%Ş]ĆčEŤĂ/‡šš8]ž[Ź+XgÜ|óMúyţÁ~¨{y' ýăýĹú‘ž˜4zYĎŢrËÍúş3Ź÷/=­^ô˘[Ô:Î@(ŚŽđv2ĐŰĄĄĄ^Ő%×ęßǏŸŔĂ?‚ŽŽNU–6nÜ ëbîˇPČŕÖ­OéăłźŹ‹™×Ôů˜ú";ĄCCĂúŘ×_mîýVˆ3}?0ěă׿~HÍ?ŠŻ/ËwŐUWŽŞ;Ů08zô˜ŢöľŻ}ŐyOě{6‘:svrÁ•Ş{ PÝäD^Ÿ¨ýtűśOŤ?Wzz˘ľŚÖm ›ŢťwŸŽˆ÷Ůç}ş|ůrm71슝÷Ý÷KźýíoÓő'ůň—żŞííßů7éߏ›˙űż?Ť…„5kVe;ć3Q ăŐq†ÓąGióń¸Ü†Đfźá†ëső^ąöęő×_§ß ƒj&}-**œ€bl×ÉĘ1:S˜‹ˆ¸%ŒÂə…)c ů"qrj9 +3:÷Ɇ_ŽéTJ‡)/Žüă_ւsu“ô\ˆ<߁q{ŇvíÚ­+qžě/nVâM‡68Ř Ł1qÁkő:ŢĆ ł§Ł°ŐŰۋď~÷űJˆš/xÁu:‡Í}÷ÝŻ^Ώ⦛F<—žxâIľüz˝Îž}űńŕƒżŃůÁřňć߃yřzń‹ďŇůĐüIœ:uJ&ăA—a ˇß~›n>ýô3:$óo|˝‡t AşëŽ;ő ‹Đp qsÓM7ęŢGg,Ÿ1¸ŚăœňĄ㽌4PxœććEú7zĚéŔőŘ+ÚÝÝŁ^¤÷éđR6 çĆPŇĎ˙îĂĂąœ š×şŻĎiyźńż;j9ťÖÖś9•Ól2Ěh‰Î´ŤůťÂ痄&~}.]ś--MŽ3é ÚӉQ?)7Ěb āţ4ާŇäí“HMœ•yśŕzęzNfŒ°ň[ś)l9!‰şC@ˆ#%ژ#"2ď§e˖ę{Ţ[Ź&ót=v옪3ŻÔ 16.~ţó_莄Űn{‘îf’Úűď˙^ţň—˘řl˙ŕ÷č†áwÜŚďő˙ř'ş..äIö裏á™gžŐbUmmî™ţÉO~Ś{•Ç{ř\ąĘuظŁ8ö˝ďý`TéĺLßÝX/]şŻ~ő+Ő3šRű{@‹űlDذźúęŤÔšź Wă#ućšĺşWëŽĆy‡Šf+ꔐt+ĐźřŃ'fŽŔEš …yBAˆ"7˝‚)đ٧­EێuÁ˛eKőű†Iź9Íş‚â’ąYYQěçoÚ@†ŠŘY“•ežŹŽ;]{”u1Ă5™#‘PůÍoÎĺč*Ö^ĽW1ëk–ăç?żWżS^ö˛ťőňÉl×bĘ1_:S˜iˆ¸5°…‰ą‰šyђ2 ôőč0A†&Ç,T–/ 55„qôDLżŒř’Kť^ZD‹YéŒăÁĹkď-Š[i-pńĺzęTŤ^a#{{ŠKŽŮîq,Zjň޸3†Üœ%‘‹/Nz(ą"_š˛°'--‹sâ$ô`/_ěěÁzꊧľÇ=¸Ż˝{÷âšk [zlÜ˝ĺ-oÖaxî'? ăÝWŻ^Ľ§Ůˆä1ŮłD…Â{I¸óBşýö[ľ—ŔxĐ@bo‡óe˝&žüĺvÝp2žü[ržéľâ˝Ŕâ 7źŤV­Ôóęę괁Ă^é:§|źÂ –ýŐŻ~EŽ\4P6mژ ‡ĺúƒƒƒZťňĘ+fŒ÷–ă!tf" WŠ4ŘŘŚ÷ {Áîż˙gz߯~ő뾸ÇkŔ‘mĚq?ň‘ł/z˘œ-f’ÇœÁöD8;é­‘¤Tj2–šÜĹ]‹ü“ü ­Ňтƒ_ľ˛nnŽ˘:ĂúÚ‚ţź:ą¤ÓARßöٞpDg4HŸ9×i€Š/&‰üŞUŤ´WÁdâ G |Nyä1]˜g›uç/ů+ biő.b=Ä}óĂŢ÷B=ě|/ąwž<ÖE„őÍźaăÁú›B“l™^ô Ľ8Çz%Ÿ3}?p]6ém`žŠ_ţň×rۘăp_óŠ3g-LݰőŠO} űŘǔ€}ţöo˙V‰Ő8—›nžüf Ěăń¸žćłĎ:őÖ[_čŘ×p<Ó?÷š/ęĆe˖ę0ë#GŽčiÚ}ź‡y˙r9ëzgqžˇœŠUL&ŤăNÇ%ôb9Íű€FtšŠ˝JŠĎ:a'.RŒí:Y9f Rg sˇć|Ž3é$ünvRRVŽĹ­L&­Ĺ­Ţ~•ţ˘÷yéĆj-n=Ľ*4Š[ÄIď$’Ď…'Ây™8Ą‰}<Đ ˙ŘŞż/ŮP5Ľ‘{űCçlŐü¤:çéťĹ)”°7‹đ\čÄÄň&4Śě%Űąc'şşşľ÷_äĆŕâ7öną!†Ż™iP‚׌ /öŕńĹĘFLžç˜W(" 2#˘tuui×ao>_Ć…Î8Ç(É †E‹闽=d^C‰.ëü[çç˛až×@8ÓsŸ^`ě5äˆCöXňĂF§˝Ž„˘ĺLM…˝_f´ĎӅב nö(ţÇü—ņ'ďËo~ó;Úŕ`˘Ďĺ˗ĺÜÉ9B RޟěńĽŤ8 ykI9ťXľÓʎ;t(Ú=÷܃ţđ‡řÁ~€O/*Ë6“Ä- [ô"´ťčQĺó„Ťóž­ŞŞTőB›–˘L!‰Pl˘ÝE[‹‚Ĺ-Îc:/SąłŠ)™¨Ž;{”0Ź‘Ţýô ŚG>ŸEcăMĹ^5–9WÓn)Öv¨łŠ3…šˆˆ[ó>Řv*xÄ­ŚEKôˆ‰Éd\˜xäDKŻnżäś…řţOO*c⇸űĽwç”q'iźă9ĺˇŒŔeŕďď}÷{zúš.œRÎ-–•°ěú\š—ŒZn§”çŸžŘwžčL¨_Š4&ę `ˆ ˝˜ó„•:+qz{yĄwC`؛ÄF =ź/\/ěúţ÷ Ýľů’e/{ŔŚcł‹nöéËËóć˝fgëœhýřÇ?Ő^#ů^"|ŽşęŠ\œ—™”+a:ŒÂźô Ą1űŽwüš>G ćď|çŸéżŃ˛eKqÍ5Wicíío‡ÎID/ţŽ¸â2?ˆđ9ŕź}čĂşçó5ŻyΔ™htŘđ†çŮZxˇ‘q\şÔ=Ü6˜,j?ÝÝý8vźMÝߍŞă Ŕ¨ŠK×ÂŞ|v߈â [ nŠQFӒQ1†ôÍ*ĄÇç/žc ŠÖŤíş3Á§…-Iîs„­éđÜbGëúŸţôçřŮĎ~Ąç™:÷U1šU΄ü:íÎ;o׍.>lŒĐŒ!Šů˘Őéօ##\ť‰ŘNÇű Xó\z1ŕů†Ô™ł‹˛L+ťv9v=ą)œ\wÝuŞţů)ŽžzęîaĺÓ\ś3ő(Ł#ŠŠ3MýĂ:…ů x-ć˝qŁ#dQđâ<†)N&؟.Ś ĹÔq…˜ŹŚ7/;+(řłŁrëÖmjŢĹ:üz:(Ćv=ĺ8H)ĚEЎ†…Y +eöˆXéŃĂČ/Zę„Ô%“ĂúűŔăVџ—ŢьEMQěßż_ő”ýhÔžG<ľŇžQG÷śç;ßŃŽÓÍ Łz_S9śSVzÄÜsÉ+Rq眧É•b{ćůaXËdűĽ@Ă/ Oa/sĽ0<Ć ]š)Äđ…Ŕź.&§ IĄÝśi,P 2/báöĚ5Ŕž)ßÚÚ:î6ôŕ6&i¤"ÔD.Äě9ăË̄řšÎs*s'đ^+”ű€ö(ąˇĐ|x ˜—g&š-›PŽ3…÷ę'>ńzhqö.ňšd˛nŽRó_˙őďŁrúź˙ýďŃÐóšĄaĚŢb&ĄfOœC=3'˙ŽtݟŚë\§“ܸˆZiňäŕ˘ÁŤ>űz†ŠÚĎ zvřü ^Aí+|ĂÝJ1ŸÄc0R\u[‚ÚS¨u(ŹN$Ďós=ŐčٛuÎy:<ˇh°Ňóˆ=źá ŻŐN˙öŢNně:óý€ĘŠsf6sœáœœGҌ4ĘÁVvdK˛÷=ŰťZYŢ]§ľßz-‡ľ˝ś%+ZÉĘY“¤ŃäH‡Cr˜c“sWuĺ*ŕsTŁŞŤşŤÉ÷ĎX(¤ş@÷~÷œsš‘Ăë|¸÷ׂďqű@V.îUçŢöw˝ë˘’my6ŘáĐ §Ó!°ŰaĎ]ö (Űťgg1­žžŽčö }?°íe›lˇc|¸—|ľVâĽÍ\^,öëöŘącâ9`a‹ađÎwžsÚsUVٖPëh˙ţ—„ˇ:äřŮgąË.ąýă/+i:Gpž@ÎĹű˛íă‰÷aďٚšęŁfٜ2ĚfăćS5„ž~á-ÄÂwPpţT94Ę5żúޝrꎳ•cš mŚd%"=ˇVlH\œ<Řślíf#G,‡8œĆož§ü‡ÇăŔ§˙ěZź˙c/ŕ˙á…1ÚľkWYű×nʆ\JöŠĆżs˛äĄĄĄ\Č ÷Rq{%ńşW^9,\šíŁUqc„{ăŸ|ň)ćh%=/{ď9WL¸ÁĂ—š„Ńąxč-öŚŕœ2VϙŒ>—‰{Q8yćíˇß&Üš:"*Ž3ĺÎážnŒ=ýô3âřěŽÎeçJ†ĺ}°çTČ+Ż=HěeÇŽđœ/‡+"ܸĺ¤Ë<ßŮšVŒ”Ă#œľľľ‘śt\ĘKyđÍöäřЇ~CLłý&ç"˛F*˙ÍżřĹĂb˛˜çşč–÷R.e–‘hKĄ Ż%v—uŹÖ5 Âc˘ş§ľ‚|€Ju=,Źó`űË şš.ĂÂ:çÖłŇ5XĎ>çˆÚłç:‘Ă– sÝΞ ž;8ĺ_ë}ĂaŮ,Ŕ†$ΆĺŐ΂ŰŘrĘ0››O}”í:{űó腜;•m*_#ʘůÖW ĎuśşëlĺX.H›)Y‰HqkQ*1 ľœ´ĎŠÁއľsŻáŽ‹˝¤LŤđĚÁźó-mxvß0ţőKgđŸ˙ŕżŕw~çwđNę/ĺĂeůɏ‚üÇ=ę˙Đ:ĆÜFÇH&uźrÔhźDŁFŮw^Ÿďzîs蹗dО,ڧ{qďú7žńM1¤<{ ńČ0ß˙ţ„XĂ빒QżDš‡‹Cĺf‚{‡¸gŒóHń5äcqoç3(îzŰŰŢ"†^fO;ţÎą™Œ>_#Q†‡V~đÁ‡rC+ó9łĺsáĆ$WX}ô—˘2Ŕ˝{÷ä<&㜠ązy Gjá^5֚Xn¤žđ‹4í•.näKú|5῍•¤s%ĂçXčţż0<˜ĚQaä}2/ ցç{"EGŒNƨ"=I € Z>qn3lÍ؆—Újľ˘îűރěČ \— 'cTËöCilƒ^Qkl?GÁI^] /ů×÷ähĚôDSMK7ň‹éS瞸’ĎĎ}gçÚiëXĐâ]öŢZ,q‹G9ĺљxTEn˜pB[ť(7x8÷{@đhV,>ń(‰Ľžy+áű’kěŔ{—; >_ޏm7JŮK€ [yl¸ÁǍ.öxůBßÜĐĺQŮ.łpÇkÎ{ÉÇ^ŠĎӕ@ÚĚŐ {m1Ży ‡0˝Ÿüä'IŘyY,[ ođ+{^~ăßóœ—ČŞkŮó?YĎ>{˝đ(€,Źł€ÄůEí÷ĹúőëÉćČź:;× Ű;Óh„Ĺ`ťĘ"ÎO<)ęlÜI8[fłqóŠr9Řó–ířˇżý]ąŒ;+œm!őU;łŐ]g+ÇrAÚLÉJD)cšbűnÍŤśOkr˜“ÓœŘ:ą˛PEŠö Ě Ťd%:d#Ë=łĽ<|rɐ‹|ň1^=z=jcžĎő‡î˝Ă˝ôŇš–”÷ ţ÷×ŕŢ;疳ƒĂYţËżŒĎ~ŮH¸ÎšŽŢńގc/ üba؅™Ďs~.cd>ţĄřŰ˙ys´9<Çýĺ¨đÚ:ţ0ę›Öŕ‹źœwÖhýŘš}Ť0h–ˆUęójÂá/\9řđ‡cZBϕßwö— ç\8sć,Ţ˙ţ÷B23\á°÷BŻDŹpŞšÂ9.řyaŰa¸Âb&›i–ě6Қ8„mÇӚáaMĐ–- …°H%H|Šă—ďš[ëś}ţž!„'HÜ ůŃĐX'öłŻˇ˙Žřg.CŠm žĂž elSä8˙őéÓĂ§× ‡ÓC“Cx€/xŽě:ńľ;r‰‹ŮK9ňĐ,>=őÔÓ˘ScąYéď‡ĹFÚĚŇ,Äf–bŚ:§5öƒ×Vtߡý>‰ÝX>űŮĎâă˙¸-ńţŕÄy|ôŁĹżřEdž ŃáN̕Ďţ^ńĺ÷˙—K"äÚě‚YŠuKÉÂX-uWi3KSĘfĘç{ţ¸Ý.‰=TXU͘S֜4ۤŰ>mIpóú`§őÇJĎ­J1/.^ÖŘP‡ &ŕ M ‘|Ű˝oÁžöYLL q맏Äpď]9ý§řř‡˙ľˇß܀Oţé+b˜áż˙ű˙SrűÖ?>ýç×áojĂ|ŕ22FŽ“Űî{kŢúôäÚkŠ Ľb”ř…Â#ǰë3çVY‰ îľăÜěŃŔ˝<ÂťÄs؏dvřeź’{ŐŹóťÚóxŁ*ڇ•ˆŘ3ź›xbĎ-RƒđăÓCBܲÓĐX‹Şę ‘ˇi)rv<†Ń´NŸ‘C„Y O'YKŘF}QrnIĆjx?\¤Í\XÉäˇm3ŇSpCôsŸűœ^M#†J‡ŐTw•6S˛ŇâÖ §Päbwf5Ń ŘÄ­ťßü+ڏ5„††<ˇ?SçŇŘ´~îĆŕoéŔ›^߆ţô~üP7Aoż‘›ŚĽÉ‡Ýťjń–סâíonƒÇ=?ѓgŇxţĽőŞdsâÖÝoú•źmÔÄ8BĄü—ĽŚ´óˆ]üĺŢŃĺćĘ\.œLňšç^îáŢĂyc¸rŔ.í’ňŕgvĽV:Ź"K’ÂcCśĘNJţ÷Oá“7uäť:Ó6ęjC\J<Ó;Ĺéâ'łET34Q1çeŻäŐf5ź.ŇfŽ>ʰĭ[§ň豗Ĺמöľr%Y|V[ÝUÚLÉJBŠ[ŤntqÂż/0ŽsBcC\ęÜź[ŽÝ‹‡^ÂŘŘjk[đů݆ń7^ŢČ"…xÜźçkĹt9řÜW'DŁ‘ËšÍf°u× yÉäuMC˝O纔]G9ç O+żß×žöHć÷@ł×‡‰Ź$řœ–ň¨nFÎ-ÛI׍a8DBy]âpĄ;ÇCg‡q˙ú™“ČN„'qî|/ź7ÖŻo5=¤0ďäVŠtÉdŠ*msx!šÉâفueúčœÂk‹“Ék"Ń%Qœ/$ssöKNżVĂűár!mćęƒĹ-ą†ął%Ť—ŐVw•6S˛’ŮŐVł%N瞬ľmÍHĺ­˙•üžřéQż|:†ç_Jšš–Đôâ$&&ĘČee~őˇ~?ď\Rá!´ˇ6Í-cŚ%ËNĆʕ­•ŸËBFğ܈…ƉF°żéÍd‰Ap0D—NŃ?ěďžU ęďE,šŔčhɄŃ;ŒŁżoąÉňF]´34<ŽžŢ!‘,žá‘šFF& eľ÷{řüRŠÓśTs´DŽHĄˆĆ9Ł%bAŁ%J$Wi3Wúßţ Ÿx˙ë1:ڋĘĘzt÷đ;ŒżţÓĹŽ}Ąüĺߢť7D"*ĘȞY˙ďmˆ_&éČ(śśŐ‹s´#E-ÉJ€_Ö|ß/W×qv_.=iÖp,J^RyĂł‰—),ńhŠN7ţüŮKxÝÚZ\Ĺű‹ŞŤC¨Ź Šňą2ٌ¸ó0M.§N‡Ă”Ýčş|Âk‹?KńUŕRŞ“´-—¸XŘҨKU`Ëąe”_ˆxÉ @Ú̕ŰNłžńoä–=ýôÓ"Żcϡ%‘H懴™’ĺŽôÜZeX"O{{;ÔpoŢş ŰŽĹßó!Qčî>!B˙~ńř$žđľąŤîľőy*Ă#MŠ2qٸŒozďG°~ë5ůçGçdĺ\‚Öâńŕƒă?řŽ&ǎÇg?űš’ßW üŇŽŽŽ^VŁżpYšĚ˩‘ CĔЕű.B°DÝáÂ@JÇ>q&o›âą2™ŒřnˇFÚ7â ¤Bą…÷.VTřŃşŚŽD}WŃőĎőMŕšÁ˜đ4eVSĄ–T °BuŰżĽ@?>˙ů/˘Ťë"Ž&ü7ü÷˙Ş ~1ůůĎĹĎ~ö “BťřĘ+‡đĹ/~ą˜á!Čóźl5!mćĘŕůçŸĎś ٰa$ÓáQţžüĺŻ`)ňĽ/ýűŞłGËi3%Ë)n­"ěbÎćÚiŰüĆü F;‘J%ĐÓsJˆH˙úĹ|÷Gb˙Ť1}‡~ű3T. —‰ËśnËüÚďýiĺçs˛c)p-íímXťś+Ă‡ŕ _ř–:œ “‡7çi)W>¸lV9—[RĎ)QËAКWMĄ‹>Ů{‹˝ œn|˙ěžyl ˇ_zşĄkÓŢĘĘ›ëáóű°€ĽŽĐMá3ŻÂáö[k”D‡¨Ł%Z!‰J.Lq)Ŕ=°ëׯŁkU!ž{>YxřáŸărÂ÷.—Łąąóĺjٖ††QöBoćՆ´™KšŚőëëë›qý–-[°XhV W†2Ĺl Ěí¸t‘6S˛\‘a‰+{baH˘ÎKui<™ËíÁýôçđ‰÷ż‘đ(U&΢Ľeţę˙ b<Źăˇ˝W’Ďe„Ä5#ů}˙YD"ŁUVă˙ć pŠŹ—ĘľĹ؅.)z͍;śC˛ôŕ—:Oœ‡„‡qN§Ó"OWşŇČĎW,xrš\˘\Ö K•™Ž‘X%FGäVŽÍ^(ÖšČŰšHŕ"9ČĽáSĎ\BKЍŰ[+á'ъC˝>ŻŃTâ§şşú‘H$ŃŘP#<°Ś•aÂW8™Á_쿄¤Ă%Â…×–éš%-s4HMˇ˘ť K3Ż _ŸŤi+Yܺ瞻qľákpűíˇa9ŇŇŇ,&‰´™—‡™ęšĽ ęš×•żýk^ó!ÖNĎqxűíˇ/jέČČÔźžBdšăq ;C_Ö+%+i3%Ë )n­ +3˝„[Ú×áOţĺřăßzĆÇ O„ććőř ‰LgĎ'ńǟlF0pyI4Śá/˙Ś?ĺfakll€-/ţÇ?}Íí%÷-<ˇ…V8ŘeúšçžÇG?ú[y˝ŚÇ˝áo|ăÄ÷—^: zŚ8AtuunźńlÜh¸É‡Ăa|éK_Á?ř>ÔÖN „˙đ˙o}ë›ŃŮšV„“<˙ü ŘťwinnƛßüĆiĺᰒ]ťŽĹŔŔ .\¸ Üpš çΝÇË/á'ěžĎĂ;ÎÜ>{öěűY|ď{? Šb=î¸ăvńýĐĄĂb˙HdĄPP,ç†ĂgřĽöŚ7ݟŰß:_ţ=ů|­í‹1::Š'Ÿ|ZŒjÄ/ĽÎÎNúŰrÉdO?ý,Ξ=+€řüożýVÔ×ף\ěżÁÇĺňÜrËÍy^ ĽĘý‹_üGËý]öîݍŰnťË~šł+śtÇ^\ ›iŘÆjB"Iˆe ŐŠŽ˝BĎo›˘é#ż8‹oŢż ×5T˘ŞŚR(TźŽX¨_<–ÄА1¸‹L…â–ءDٸ˘ŠQyJUě&ÓYüŮž‹ȨP]n!j‰05ßž¸çŔšW€§€Ëן{îęđčš5kÄ3eŐËą[l#ž}ö9?~BŘÎCfyžƒĂ‹ŮĐŮĘÂďśŻžzTüÎŚM›ĐŘŘ ężů›ż>íwf˛‘H?üáŃÓÓ#ěŰYž,ʱ缜ϓmżs^÷ş×Šw6Űžąą1!ŠŢwßëh›JH懴™’ĺ‚”;W!ĺˆ=[ŽŮ‹Oýý—ŕńú„ŔĹyޏBüóÇÂx߇ĎăŮc"<çrLĎďá=:/„-+ǖ%lý•iëŽĺËeëÖ-tî˝XĎĺ–EŁQ\şÔ- ‹_ű÷żD/Ü[Dٌ÷yčĄGňö)Ć8żĚ›ßü&Ü}÷%ˇăŠ 7˛¸Á)Úúúúńîw˙Š˜.]ş„^Fšœ?A4T¸üúĐŻ í˘JĎDŃííçűž÷ü*Ul6ŠíKĺĆáëőď|O4VĺWމ7źáőƏüÓÜ6?ůÉĎDŽűďƒŘ&ŕťßýž¨ř”7Âx{N†É׀ÓÓӛ÷3•űÎ;oÇM7Ý îßú­‰ĆœDÂŘCó&ś3ĂJäłrz0Š;ńîNáŃŽąYëv;sy˛8W!ŠŞ”´eěí‹&NeŚ­Ndđ‡Ďuá\‚ž¸<˘l˘œś\[ěexi!7Z˘5-4Ą|gçZŃřaÉđł966.QÖóÜÝÝ#śą‡;sn˜-[6ăxŻíí{>ůnm]ƒśśVąŒ?~懆†„e[oűťšźSĚéÓ§ĹçűŢ÷ąÝ™3gćd3ŮVŸVtۙl Ű^ćďx5Rď" KĺœË\áăƒqýîşëN9ň*u,<“[?›}/´çozÓ…ŘĹ Tm5ĹsIŚ1—ş×ĹăŔŃg1'Žšćş7÷‹Ž˝}űö‰:Ă~đÔŐŐaą¸@šN}Ÿ$í§›ĚĹ`OńíŁžÉĎ ×ă8‰÷[ŢňfQ‡a1Ą0'ßlvë‰'ž‚öÝwß%ž]ŸĎ;Ł]+fCË) ‹ú,$YżĂödßžý%g&xŕŔAńřŐ_}—ˆŕNNŽťY”cšÎËuaî<áşńĂ?"ġ7źá>ąŒĹżRöY"‘Ź,¤¸ľĘ˜ËKxĎ­÷ŕ/>˙=Čá€ç¨ŰŠG*źÔ“ÂúDţËť„§’0zü>9—Çü˙܅nú ţ­sç‰ßVTá/ţíťŘsŰkP.ĽÎuŽËˆ{ľ,x>𣣣]ôjqo‡­°W˛¸×içÎísN@̍=î]b/É)EgçZjâóůċ|||‚zŢo‚{:q/:{v• ‹X^݇öëżËýčGŠör;_ĂŘŤ‹{‹Á• öÖzýëď=h\bŻ´ÝťŻ)nse†ÁëŹ^śP($źĺŔżÁĺeď ._ŽŘ°‡1ĚVnî1daŒ˙Ž|šź‰…đcR•\bypBy+é<Ď;LËĺFLqá#^ŔżžŇ+rY•ÂEâÖś­ôź­§^ďâž8|ßĂé4zęšÓÁÎŃŃ~ďé ¸”˘2:˝źá”'rmŠŚŔĽŢdŠ%tŮĹť……°Íäç{ýöĆZłŚEL–@Sţn÷ŞäNnÜpźĺńeQěůdűg, ˆ‰0,š .?çlKxÝ†łÂM7Ý(l çdQÍăʁmőë^÷!ÂńąŽż~ŻříbĚd[ęęj…ççóâ2pŢ ŤĺžË\ijjžZ|<ŽŘƒ‚.ž×Ęąď…öœÇlχŽzňÉŇĄœşÖÓß!Ać›$ČÓ-ŸÍ l:::虻~NžÝ3ÁNšĂ$ü> üôŸŒÍěŽőżüpňĹŠe‹‚ČâŃ{ßűn!–sýĎ‹ëGÜ)çxH“™ě{8˝úę1ńěrÔ?ťěšÎĎh)ŠŮĐŮĘÂcě9Vř;3ý-f˛×]w-MťD9ů8UU•BŹbĘľ|=¸ł™ß'\VîüŮśmŤx—p–ß+|‰D˛ň‘a‰+”byˇĘɉđ_?pżŘîÓ_{@|gŽżůúƒřôýmœ;q„z™Qež™^BíxěŠ0:Œ›o á÷Uáž;+áőĚM/MĽt<ůL?úŮ(žß9fŘ[kxřFFzžýMŰńG÷ĹźPÄÂrÎtěŸó…_šÜ{Ä/vŽ °çż8ů¸ěňœÉdECÍťq>üęœÂ{<wY‰šr`a…’Ř÷ă†oaŁw&¸Ă•šfíÚľ˘ą˛aĂú˘Ű–:_ĆJÁž–––ź°ŽplŘ4׊J‡ŘákČű–‹yýýřĚgţmÚşpŘđ™kš%;úT  šË´/B貣 MâŃ_Ŕ ˝üĹ­mh ŽôŹŞľh"çěJē†ŚżŞEŽ []†śýÖŠ!|ăô¨HpŻ:ŚÇę¨Š0DÝ€v*aź#٘#ßĚš…÷{q‡‹ –G ]ÜĐŕe×\ł3oŸb!}s…0üœŽ–JĽó>.ŢWłŮÉböœßIÜ(ĺ2wvŽ…D’cĘTĺÄ Ć´,¸Ě)†8Ԛë1ü,˛ˇcŻËÍdˇ¸nĆ6¨0ÇŰ^>Ţb•…˝oŮFű.Ă\)ěDĺsdĄŽ™=ˇŁĘŻ;E†D"YůHqk•RR칊lpŽż!é+˙đ—řŮ7ż€ŃŃ^ †ŠŠ…„Ž&<÷BDLw7v]ŔőťCذ΋ŽvŞ*Té5*ŔѨ†ą‰ 5n’8{!C‡Ł8ppRä×bXÔâđёz™Ľ¨âěŔ›Ţű›řőß˙c’8[9g=ˇŔ=d,žœ:uZźĐ‡‡Grů°–ëh/örséƒ|żhxr‡­pŢvG/lp.ĺóĺ5ťż‚$‡ÍH$‹Ům`ˆZ"áźn„U›a„VN+öz| ×ţŕţßkđĄíđ¨ĺŰ'•ś UK>sĹŘë깞0ţíŘ zT˛•Š“tŢeŠš+ ŰL]$‘7΂kgj9ěšĹ°ÂĄÎÚÂ6ĺÚk !‹/^Ć^—KXćdţ*SČrÖÜâJœ‹ýţZ¨}—Iľ%Œ˝35›&[ľü˝˘dm]‹yŻsÇé7żům!sgcgçZqüýč'˜+…Ďđ\ŸéŮĘbŻ0ßăĺzöW’=—H$—)n­Běž\Z6CퟩŰŕožö`Ń}xŏ|ň/𚷾˙ňŸŔŠ#/SĘyşŠ×Ľ^L@/îŸÓ\ˆÇ#Ô3$ŚŹé—žůš=říOý/lÜžŤč>ĹĘŠÓž‹ĺŠU=ľÎœ9+âüŮłÉęm2Bh"ü͞'†“cÖ×׉}-lÎÓb%äœOOÚ|áJ€=?˙ý9a('5ĘE"‘yxâ\+‘ü=ť&'ǐJ%É¤‘ÂD¨CZ,ăurŘÓsŠ*ĚűĹž| >ÖV:ć˙ř§ŻáÓ_} ¤°UŠtdDœÓLçźń‚Ĺ-~ysœ?‡ŐX°pĹů8!/7FFFDΒ#GŽâ†Ž۰ç7ôxn4peăąÇžŔ•‚Ĺ8ö˜`qŽĹžGůE^.Ρňýď˙P$7fˇrŢ6OäěhQxžœž–>üđυ@U ?b7sކCn¸ňÄÉIš‘Ë•.{ÄqŇbž6ź ŽĂœ5Â# těŠÎ븹\řƒ3>7veçŠďÉ'Ÿ*ťÜ\yŠĹââYb 'ţęWżžsçżďWžňľ\eŻăˇžőźđ‹Ź.Œ(E3ď–bćłb1‰=ŚŘ{ĘĺćşËÝíØćĆßÁÍß=†ßzô,žsjç&e˙^,Łá™ž e˝xó'ńgp:NGO$Ž×9ç—ĂČąĽ‰–˜•ĚĘڈdńVr| şůĎČÁĹB—ą^Y°ÞYl 9?Ž*ÂóœGoŚ‘UKQěůdZ~–Ů3“ŸEś%vÇT°-ápśloěškŽ4ĹĘ>ó9—BťX ž^œl™?ŮžqrhśŸÜ-ÇNÚs~/ţô§ˆÎk€i7W3Ő3Đ07Üľý¨oü :žjř¨ě tîş~qNĹÎŐb>őLa›m.§‡`[ĆĎ ô7řŮç\Żü$–677‹‘q,O,n4ąö­o}ď|çۧ}ç^<ţ >_c>ŸöövąÎęi­ÜüÉI”ż˙ýˆĄ­9a47âŘłËÄđ'ˇrBđďXžo’Ő‡=—đ’âŃâxŕW™P3"|Q$swhP4˛ZŚđ8UňAó>ëBt„\¨ö8ŕwŞâĺIg1™Ę˘7šBW$‰K“iá>  Ź((nútZĄ‡ĆoXb›đJłŠfÚDái“K€3•Çđ䞅ڙŸ ľĽëׯÇţý`ąłs­č ŕçŽđž…Ď'ŢÁĽo|ă[xíkďž œ|ř™gžĂC=,zýŮӈmIa~Ť+Ią˛Ď_˙šžKĄ],Űžf,. ââa1›,´çÜAÁĎ;î¸-gkĽÝ”0\Ďlźć0Ԁšf˘C@x™ĺőŽhj›ÉN*ôü]sÎińGRćDéüŒą`ÄÂ3{şň@…Ł%ÎƝwŢ!ęW?ţ„xÖx€ îdiÄÄb6tś˛Üu×$„;ń裿‚Ű4öňˇň,ŁłóĘŘ@‰D˛şQĘXnĎndÍŤśOkr˜“Óœ8š“*ęE\.Š"—V﹕¨–_"ěÂ˝sŮżđťőÉ^:O<łşZá ŐÎMä* ˇëŽěçOEυłčéB,AlŇHćí†ŕPEgMÖŹ]/źŔv^ŤČé5_´LéČ0ôąnÜsűMš—]Šđą6ÖxxdšXř‘H$Wöţă$˛ěibđdg&›Y,ǐĺaĘ{ýmxÚĚS5ŒTVScrŽÂßĹHYúԄ’¤čš4ó{ÖHëžŐŚöŸŠq!TGW„xĽŠďŠ™$^–bn§Šäđfz-ăSąĘeć×2…,EŃ ĆŤUĚ}48éz>rwhp‰_^d/X‰DrĺYˆÍœ‰rę™OţňôŃ-<ҌHßňʕjN‘¨ŐKőä¸űľ×_özćrďű=ÄŁƒstŔűß˙^H$+R6SÖćŰíş‰>8/‡qoWܲć¤Ů&Ýöi˝hěó@‘a>¤çÖ §TNk9Çĺżîî[EOúPďĄ\/Ť…ľ//O;źp×wÂSYWôˇZ:։iąH…G‘8 ˇ–ČĹý^ŢT_‡-wߖ-Ľ”ŃYˆ1b×löŘbCÇ=V‰de˛;Ą›ű ŤŠ[ŢSô^ćœV"7 JŞFúçÄĘn_šńŠ8YXËć„(Q ݘ‰ßMeŠ,˜!††g–!nqBxE5=É NA7ójYšśĚ3-(yÎ_kQFK”H$Ťƒr꙯}ýM˘žém;:­žiqľŤ)eűšžÉ!ˇ[śÜ|Yë™Ë ŽBŕcöňä„ďZ"cÍ[fÁßYdşýöۄ'Ťě=}şżŽŞ¸‚5ó~Ésƒ/C62DÇ°ŚŠënڕ ‰ąĘ\xN…ó3UBZůő_˙ $‰¤\Ź‘EWľbšdÁbŃŘRŒ´hŚywäśL;lĺĘâ\ZĆ'ĚOÝrÓ2cٖć YŠl¨éşMž˛ÜÂlß-ĚđGÍô:3ą:o‰¤|Ę­gÎű~ľ)WŕZězćrÂď÷‹ü\‰D˛ÔâÖ*Ĺ^)Gزg‘‹˝—Ř“‰GţëééÁČŮSČ:ý€ËĹíƒę ŔéĄy§ŞjÜfş–9˛2É8´ä$ôTH'ŕČÄQWS‰ćuÍhnŢŻ×[VYš‰D")…ÝţŮmâb OýDV+EĎ R†hĽÁň¤˛D,ąš CRôÜîşnĽŒD‘˙ó„‰ărčĄj˛X8ÓěgZ˘tv[o„/B™îI!íŞD"™ Ĺę™Ö<łŘövą™Ť—D"‘HŽ>RÜZ%s/U٘­GÍZĆŁîuvŽ ]ăăă‡#"i4:€ÄdR$&ľ†#çd|^—‹Ä+ƒő¨¨‰| œŹŻX™g[VNĎ™Ź„H$;3…‰Ů¸IäIbáśCĎű˝‚ă)Şm+FË_Íᇹ|Xů^_ßiW%ɜ˜k=ÓbŠćÜ*g´‡‰D˛tâÖ2cĄ/ŃR …•ű2űňrÄŽÂ}JýÖ\ÖͧR!+ÉĘŚœgźÜměöŠ“˙ůő x˙ŠĂb¸ó™^ói”ŮóYŮ狭/gŮôőzŮű–=l[[[Šî#‘H–/‹e3gŰżÜzfẼˆŹgJ$ŤůŒ/?¤¸ľ ązţçűŔ•[Á(%tŮ×ÍÔ7[ůć[aXČq%ÉňÇJ´^.ĹlćL 0^žaĂz1YŰŰörz\N;6›÷kŠůRűJ$’ĽÍbŘĚš0_!ëjypÍő<Ľ”HV6sľ™’Ľƒˇ–S˝ë*˛Y NçÂÂefŞ|Ř×[”#v[7—˛ĚuÝ|ś“H$ËöŚRĚ|Uĺ؎rlfan˜Rn0W;gĚbýî\D.‰D˛|š6łfŤg–Ú~Š"m˘D˛:(×fJ–RÜZfđĆ9U8ťÓéĂbPĘ[kŚí ˇ]Ě.ǒG"Y}$“)aË ą)e3 ˝ˇ E-fŠ[? ąĽł _‰dů°X6sž”[Ď\ŠHť'‘Ź>ćb3%K )n- s˘D"řý‹Sé(ö;Ěl™ÄŽůţćĺŘ^"‘Ź,Řţą´ŰĹBĘľ™3 \öă\mo­Ĺf1źe%Éň`1mćB‘öE"‘,uĘą™’Ľ‰ ɲÁJüëršÉ¤‘N§q9ą'śŚšn_δ˜eH$+ś{l˙ŘÎfćk3‹÷JŰĄůÚӅŘÝŮÖI$’ĺǕ°™‰D˛R˜‹Í”,=¤¸ľŒ°\ōЇŁŁc¸Ň\îޕn@J$’ĺŰ=śv{XŠrmf){3“-şâÓbłPÁK"‘,}.‡Í”H$’•Ę\lŚdé!Ĺ­%Žő@Ů ü ˝j„Ă\MŇ(ťZ :‰D˛¨‰dŠS82Íĺ¨lH›)‘HV ŇfJ$Iů\ ›)šşHqk…`őŽYó…‰D"YĘŤ\\Ž ‡´™‰d% mŚD"‘”Ď•˛™’ŤƒˇV….âöe‰D˛Ü¸ÜöKÚL‰D˛’6S"‘HĘGÚŻ•‡ˇV …=j‰D˛\¸ i3%ÉrEÚL‰D"))h­l¤¸%‘H$‰D"‘H$‰D"YśHqkR؋&{Ő$ÉrŔžÓĹú~%6S"‘,G¤Í”H$’ňšZ6SrĺâÖ Âţ°Zó<‚Mąő‰D˛T°W.ŹÄÄĽ’/&ŇfJ$’ĺˆ´™‰DR>WËfJŽWÓfJŽRÜZćV6RІR1žčÇéÉAôĆ˜̌ ÉІD"Y¨TŠ:ÜhńW`c¨×T4ĄŢí‡Űí•‹…V>ŠŮLe2 ľˇŽÁAčăăp&“ź$‰dÉ 2JUĐЈtˤ‚+b33Š1˛×1§I]…ćR!-ŚD"Yʰ%Tu Eƒ4ĽSpR›yąmŚäꢔą\ą}ˇćUۧ59ĚÉiNnš\4UĽRé YtŹ ÷˜%Š16˜Œâ‘“xi´‰D˛ÜŮ[ӊű7ŁÁ€‡qÜËĆ̡âQh3™„zü(ĐŐ‰D"Yött@Űş/‹ÍLS5Lő ˘¸ ‘H$˝Yľęl’‹ě˘ŘLÉ̸ݎ›čcœŚ4M)š2ć”5'Í6éśOŤ˙Ä>‚yˇ–!ö^4ŽpÄb1źéš/’Z‰dEÁ]ďnż{C-đűý9—rŚÜĘG1›éîžźô’ôВH$+ ˛‹ĘŢ˝Hśś-ŞÍLP'Ă źŇCK"‘Ź(Ř*6 o2:o›))+!nА,+ě <­ Çc]řf×+RؒH$+śklßŘÎą˝cťg%0.'ŻK1›é>{Řż_ [‰dĺAvM'űĆvnąlfÔĀś$É „íۡ¨'4/›)YZHqkaŻpđÇą?܋Ÿö…D"‘ŹdŘÎą˝cťgŮ@fڊG1›éşt 8|‰D˛˘!;ç&{ˇP›w0 $‰d%3 ˇ°wsą™’Ľ‡ˇ– ö ϧÓi‘8ţ;—d#M"‘ŹŘŢąÝcűÇvpڊG1›É‰ă•/A"‘HVdďŘîÍ×frâř!Ĺ ‰D"Y °˝cťWŽÍ”,M¤¸ľ ą{ţbč´ E”H$Ťśwl÷Řţą,Ëf:O—Ąˆ‰dő@öŽíŢ|mć„Ó'C%ÉŞí݄Ë7g›)Y:HqkP؛ĆC1drTD‰D˛ę`ťÇöí`Š^ľb6Ó‹ËQ%ÉęƒěŰżšÚLÍᖣ"J$’UG„ÇNt¸f´™’Ľ‹’e?`ü°A"‘HV#l˙ęÝ~¸\ŽÜ°ÍĽ°lŚ{ ŤY1“ŹFähW€k Š``N63é B"‘HV#)Žc&#eŮLÉŇBŠ[KűpĚÖĕŽÓ‘AH$ÉjäTxˇ…ÖäŮEnŔz"ŘmŚ{puŘĚů XRö’,gf’Żfz&V‹đĽ“¸•é蘓͌ydƒN"‘ŹN˘ş éšUh3e‡ÉŇFŠ[ËëÁ˛Fo荅!‘H$Ť‘žx$g UU-ZŮ(´™úř8Vbud61Ť\ŃJzuI–5e66 ˇ*źďWjŁE™˜˜łÍLRănEͤí“HĘgľ;)¨łÚLÉŇDŠ[Ë ŁňĄa2›‚D"‘ŹFŘţą,§QbŮL%™ÄJbŚs×ç°˝lÖIVÖý]Şéa5Jě÷ť2ÓqVZ#†ěß\mŚŚŹŒ´ź ݤř%YMĚfűf{VŠídűWŽÍ”,-¤¸ľŒ˜ Q„%Q"‘ŹZ4Ńř2ćgyl6+Čf;g}–mf[?Ÿß”HŽĺ6˜ôRŰńКIčZq˝ôó°™Ëů‰/ççp0H$Ť…šŢíĹ<@K­[NŘŤ˛ţłźâ–D"‘H$˄rE+˝Ä>łí/‘,EĘm\(ŰŰ=śňZEÖŰ÷ˇŽ!ĂP–s´JyłĘ†Źd5Sn¨śe;głVŠĐ%Y^Hqk™!_ş‰DbPnˆÍJa&aŞPÔ˛Fb}ęeG"YŽ6DcŠ*s>Oʞ>‹‰`ścŹ4kĽÚ̢ޏ…Ë íŢ,ß%ÉôŽۊüeTş–Ł-•vaů!Ĺ-‰D"‘H–8ĽŠb˘Vn*˛n,˜ő¸Ér ¨ U°^,1VŠ­Ą&ś-"r­tkĽ1ŤHU ôĎ4_t‰dŁxh•˛…ĘÔ%ˇ—śTr%â–di#+IůČJʤa‹Gôą–Y"VžŔĽiyë ÷Ÿí7%’ĽDą’R°Îś„ĽŞy^\,r)–ŕeŠ\ź.7Ü;¤Ŕľ˜Q˜*â˝ZěÓžmącJ$ŤšŢYÓźa­M ö+ÜFÚRÉĺFŠ[’ĽĂ*˛ę!Y͔Ź{†d%bEQJزžkć:ÍćÁĽŮsÖrű1ěÇ-\.‘,EJ6¨`óĘ"Ts^ĄgÄZΓľ\ľ= <ÜűL—diQRؚAĚ*š ô™)‘Ź"ňóÚ: t%ˇ^<%.ąÍÔÁ¤Ŕ%š˘HqKrő™Ąň Ďs?‰dŢ(%Ÿ‹˘Uë9‘‰eI1ޘ°U(j‰ĺćzÍ\.ć‘ßČÓ1sˆŽD˛”ą7Óű*7ĎâÍłhĽš‚VNŔâOśĽć>ź?3 \˛Aśt™IŘ*ľ ÖŮŻiǖHVJáH˛ÖweJز,-‹]Özť}ĚóęšE“H)nIŽ%* z9ŰÉʆdľbVŚ1ËĐöRäZĚ$lešĄf.Ëdłâ{–-SÔâe9Ď-Ű~V¸bî7 ‘,}”‚yť SČây‡Ă‘š<Ń:§š=‹\š×L/.ťŔ%Yşä‹xhé6{g‰ZöeĹś/<žŹoJVÓ>mb—%tŮEŽé‡+.pIąKršâ–äęP¤˛ —Z?­ ʼndĺRl”š™6WŠmoí+ŽĺGĄřTLŘŇLńŠEŹ´)jĽYä˘Ož2沏éÉeSű< =$˃‘UŰwžw˜—ÓľhrąĐEŸ|Ď;iž…­l  ş O\nŘ=ľfľŠmgßß~źÂăK$+iaޅą6Űjď†ĺýjšěËJ_"šœHqKre)WÔĘŤ\ÝrúĄdĽC˛•=˙+졝•<šxž­˘"—ôâZ”Ó°˛B5SÄbQ+Kó)ž2!neŹÉšX܂ŽČÇ0Cgú‰dŠ‘×xâÉôÔ"—éĄĺ0Ĺ-˛xrÓär:ٝKÜű.ščS3÷-´‰2WĚŇŁ”×ÖlÂŰČ\Č6ŔQlŰą K"Y-zlŠZšA8Řnš!ŢÖźČхé.Šyé˝%šÜHqKrU™Ň­ ÝĘóˇĐő‚í ç!}ˇ$+Ľđ>WňGŽá;ßňú.)tIďƒeMĄ×V.Q<0•K‹>YŘJ“ ĹÂV2ŕ UQ+c6č A‹1Ř0o ă˜ÉrAR˜íĐjtŠŹoa*ϖ%rĽ"d š\đpʄŽ\ăĘl¤Š–¸ĄLĺđ’ös ŁO]a [Â>˛řOś1C“FSVxšjeyrÉĘŁ„çV)QKŘXŐů&ępRçÓ%vą \Ó:Pu]ćߒ\v¤¸%šr”ي [śůÂő%ö+ń3ɲ$çĄU¸Ŕú*VZ˜ëšQLÝËXŸŰE<¸dcYP譐'rq(" XڧV‚„­$-k{ýý˘7U"‘dăqtí+bŢĂŹdó9qcď-ÉŇ`šM,œLaËľČ&Ňß>"‹‘¸•ÉóäĘ÷ň˛ťt‡ŞD˛˘P łZ!‰0B­ŽŤ€ĂşNxý~řx|>8u¸H첎ÂgFÚQɕ@Š[’+CÂÖ4QËŞpء-éŮUPéuÉrFÁ´Ńjr+`ęU֌ĺ>ÓŤKT<ôœ'—)p­ -Ëk+k ;LRCŽ˝śf˜€äĘÁ—îî´śŽßÇÇDžŕX[[+ć/]ęĆΝ;088ˆ††ąR›DR>işĎÔâkěr^ü7čëëCKKKnťŢŢ^áaPSS#DŹX*5•|>—/š$óŒbĺݲyoI– %źŽě[<ą°›ǖJ<•ÁÜž˛Ž(‘ĚŁg@Ě&3:NŒ‹ýSď3!‚ézÉđD‰är!Ĺ-Ég&aË.jiÖ69ˇqä*2°…)N ę\p\‰d9S˜OSB–1kš‡#—Ŕ“Qš7:Oä*Cŕ’,9ôBOUŰrť &“ŚŹ™<žĂYŕŠK;xĹ9áŽ>ŒÉÉFGG1ŁŚşgϞEuuľ¨ěżúęŤ8}ú4š››G°~ý:lܸ’š311ŽŽ‹¨ŤŤEGG‡XvîÜ9!tąŔĹטI‘˜uöě9ÜsĎÝBčHĐw‘ƒËĘÇĹ ćé{.ę—e7Ľ'×ŐcÖ\Xúôœ[,‚˛¸ĺLN"䎳m,˙†ÉBqť¸R1zĆźpşÜ›Ëî YJ̲쨴§’ĹFŠ[’ˏÝuźp™]ŘŇlšxQ–{ÝDVsŚOŰÚ/H‘K˛<)âž[lσ#˛ş8Á T¨n¤˝eěy FŹQ1ťŔ%˝ˇ–4…aˆbŚňmY ăÓfynź'ĽýťâT„B¸ăŽ;022"„•`0ˆúúzÄŠaÍ^CěaÇ^[ۡo'ĄË!ź‹ŘŤK2?ęęęPYY™óÚbÖŻ_?m;žĆâú3qöřâÄň…áˆş92ŹđÜb›HĎ J“L/‘,>ÉD Y§>@f8ÁćDxń3/ź(ŽÇ6ĄŠDoŹ}^FFÇČ11ĆÖ͛ŕqť!™?.uc|bťvlĎ-ăźvüŒe˛¸5m*}‚ŐA`uŞZ"—řOZUÉĺAŠ[’+Fač`^(˘Ů@ƒľ˛BČŇ2,leŧHüɓfŠ[ƒKĎőqlć_”H– Ó_řÂ3ËČęi$öT qK|ňh5bÄi[šřTÍgCwĂŰ ć B!mËáĎj…o›HÍśĚ)ŠÉq%’B¸q•2GĺÉÍÂ×3Ȇj–h,:Ň6.#ň’Ë4Žš“”˙Ć3źdqI$’AeEHXç.t!Î 2A=‰ůŐU•ˆĆbB,ćukŰۄ0‹Çhż1´ś´ŔëőŇ6Q<úř“¨ ă~źtđü>ö˝ô˛¨ł´ś4“P5Š /Šî š¸sŻĽšŁŁœß0K[~öđ/°eÓFń7?{ţÚ[ׯÚ3çĎÓďx°yĂHć ˜gÎ]ŔľŰˇĺ–eM;jö„ˇŤ=ŒXzżJŽRܒ\^ +ß­[Âđ™.älł)s¸fzióiCđbwW˛˛ÂÓËL8ŻM7çš%ë/’ĺL.ľ–- Q…)pń°ö$QŠĆh5\šS.8ÜN8¨â&„^šçYÓYăgL„×Ř~ŁĐ{Kzs-J5ŔŚ…%šDÎ-ÓCAŒ˜ČÓ*ˇxô3ŮplgÎŐSL™šéŹYÖĚń)ž%O´m[*Q†).ěy¸ňć­ĐD+ş´—[nÜKĎŃn8šƒMˇF›4Ţ?ěľsâÔܸgˇč¤ťëÖ[riÜn—Ź4ÚśŞ˛BSź†Cě9l˜aO 4‚˙†ě‘ĹžWsÝń“§°iĂzŔź‚BäâmóďŰp›áś›o¤2IÎ=^76Ž_'i}§˜ňŽ#˙ÝÍ6šđÖ2ÓbŤŚlĽ´›’+ˇ$W„R^[Sßu3‘Œ#őřdÓid#Qüż×˝AŻÚńHýJ˛:)uďO&bř§ƒÁ Ju9é™R Fű’Ţ[Ë űßš°"i-łĺV%.Qd‘k•Uŕ+Šgžž^†ü͇ĄĄaLĆâX-¤mŁ‹fmžšŮhśňzŠĎ‚|[Ň^.-f I´'•gEtňčŇŁuąáźuŽZ“;ˇm™ú☒ŽżnćĽÎ:Ő8‹dšys?3´¸vÇśźăAŒćsa‡G^9ö\{Mî>‘ĚŸbU ‘FF×ňžšźgPŃóBĽŔ%šœHqKr•°…#ňWÍś2ԋJ▖L!O˘6X‰g.źŐíÄ:_6śŻÇđđ0Á pc–, Q*aý# /WđÇĆĆċ‡óƄĂa‘ Yä0¨Ş˝aŃh~ż֗ĆÉ~­ýäËl~Ž(c…ZX˝—ü÷ajŞŞĹ3ę I‘&M6U7Ć­áđDŮ<[>ŘGG´×)5[ĺQł…'ćíŤĚsËz6z†čpĄžśZ\ńp„žĘiŰÇÉź†ŇŞf•ŮćŒé­•5˝ „@lcŁëá(ŘGZÍĽƒ˝]dĺôś™Ć‚ŕŇkG"Y|Ě',ç-ŠÚžAĹöĚĺŐgźÜ†Éb!Ĺ-ɕ#gělß­ź1YłR™5<ˇ2Š42‰"‘~vđ4ü'îÚ¤bCŰ:œ9sFŒBľcÇHż`ĆÇÇńň—Ĺ_{Żß‹žAÔây$/Ξ˘˘BL.\Ŕć͛ŃÓ݃d*)śçQ¨x˙ ^7ßr‹XĆ´ˇˇŁ§§ƒƒâ…„ťů5Üs&™,0ňľäĄîů:ň< Z6l•‚ăÇŽŁžĄkZ[‘Ľgž´WTÄDĎWVĽQóYSUłç Č v/+ˊ\By _ܲźO,ď­Ušs‹s˝$Šs„Ĺ­Ńń0FÇ&Đ70Œ`ŔD2)śQUˆ[Օ!´­i‚duQÔkK×§‡ľŒ*+=–&zążMŹ´.‰ŢĄĘjH$s…óLőööBRÎťćđiÓ<'óžIHű)š2HqKrUĐ특„Ԍdňć°ÍYjœh$p…HTš*œÔéôÄ>{öědq`Ż*Ç#<łX aŃđúŽëĨ7ÍÍÂK‹Ĺ”ŠPEnXôښZ1ę˙Yřâĺ,ź°§–˝ÎÇgÁ’÷†‚ĚžŚ|­JA+‰Xvv^ł37ŸMŚé—˘JźjÖ)„-]Írâ-ŃP=e2ľÖŠ@ǔĐe…') §ëŤ ~F~&Ł1D&Ł4ďĹĐȘ°OńxBŹŻ"A+™$V)ÂXzű‡Ä>•Ň>­ěb°Ž)Ż- éŰł|)’¨‹p)P]LJúŚ5Hć w´ŸďşIq o-›--¸d•Sr%‘â–䲓Ÿ7ĆśÄ2€šmX{–H [,peâ1źńţ7ćöŸžńˇŠ¤}Ĺ|QĘ]ŻĚa_ĽČ:Ľ`śŘńJP/ń=7ŘŽn_Ślgxđ8Tz!e3$l09Ă03Öëşá6s°ŕĹ"X~œh‘ÉÉź˛4¸ee)ńQ#“ç'ĆGmç™+ĹÔ˛‚RÚOťä5Őó>Ś-ϛŐKî>óşż[îÝu%K"Š8=7ŕg'ę"Ą˜ţ–Íȇ Âsʖ™{K™*ŸŹ|,mJ5ž-‘ VƒÝÜV[Ľž[ěąĹ“Ĺ֍ÓśiŹŻ…dőb„-+'rYŰl/=–&zAČÓ´äňf´€MT¤l)YúpęŽ[őnťýá:8wÖXős‹D"!RUđ:‡Ă+M.üˇ@ŘĘ­3ÂŚBĽ=•\F¤¸%š2˜ĎţÝj‰j$ \mŢÚÖmŽLk,孟öŠäś)ś~F袍ůgK6FĽ‰Ÿ)#ŠŞž{ćťë–.C—şÍކŢŘmŞMÄęb’izwHćN2ÁᚫÇX9ęrόmřzFćeZfčI‹ \zYuIÉʆďƒŃą1‘ŔˇÁ@ o=6Ü?0€Ö5WĎĂ/N‹r°ˇţČó\÷ćy+_‹\,hń2Žžŕôœ‡˜ˇeQĚ9šŚŚF^W‚bÂň:ĺt(˛Urâ–äňQ˘"Ą[J@ŽGÍĘc&ü቞¸€_Đz›|3/”‚Ďšě3×ýň]ۧľX7…<}ÚöĘ´éůűçz[l‡.,¤X§˜Ÿć†šCčSǰ{ě)öß*,CÁ×eô.œ~Šç /})ř™Q3isäQă™b1KáçJA.ą§Ýk+ťđ%š*̡amyžhŤ´!ÇÖ,Á9ç$ó`ő=óVŽ:ÝöÝţi~™ŃË@z ,1 ź¸ VN{‡NNNâ‰'ŸÄďżżäßqpp=ö8ęęëpë-ˇ1!•JÁçó‰t N§K<>âl-—,]žqź$ŒŽ"Oŕţű^—çŐÝӃßýýOŕťßř* `WçoÉi(ÄČć€S€‹Ĺbšy^΢{iń˝^__/Ä,ëžçűôJÚ'kÄJ+ˇVžŔel‰äJ!Ĺ-Éڈ˜ať4-+ByŇiš›Y.m<ç#6•{Ź…są^;ӽ틩QÖrÝśž?YŽ<0Äc;ĹŚÚčSbň—)JáOëśÂYÇÖ§‡aÂVĚi"fՇrgŠĚź~ÚŐ(W1˛m›÷[zńăÓő⇛ĺÜ+b@†Ź1ę(?KÖs•ťöy,Žđ&šü6Ô C§}‡ń—ĺJźD˛ša;¨pŽHÓÖŠěŐZ jÉf×ň¤XG@ą$ÖS\ůŰ~íë_yAzčaÜsĎÝ%Gŕć}YpřéO&ÚńůźBhˆD&s‚ƒ?ŕG$Áë^÷Z!:H–&ĄPHxk]ˇëZ<řČϧy5ŒŒĄŽśƒCCXŰюŤ—‰'¨,řä{ËςU1o,+Œńj1ŰóX¸\v H.Rܒ\yt{H"l đŠF¸ˆÝžSΘ|㩔ڤ`EšŢRs6Á38Ŕ\.sžRiÂú4ćí"–íSˇ}7ˇËi!9ď+kž0œç•)Ń śyĽŕˇ”"żÂu˜:ţ´ ĽçŤ>ÓEPfćŁ.-p÷ĹšfB§†œńÜčy˘ąýY‰ĺĽ‡Ö˛§°QnˇŠşů÷ĺF˜D˛šaoönߍŠq˜ślŰM{ž l¤lŒ-3 C‹đ‘=ţ8î}ÝëJţmůŢŮłg76mÚ$ŽSI"×đȈ÷jhhŔD8,–gé>󒽵 ’ĽÇÎíŰđěó/ŕŕĄC¸ëöۧĺ§JgŇxďťß%B—/^ކRÉ^‚ě9Čb‡1ň˝(ąź˘ůas†˜¤čşÍĂkęoŔŮŐ‘şÝ>Ś<šĚöŒEŰwűŽSšzdĄheű[ńr3J‘u x–+.čĘŘĽźŞDţI”ťß ‘Ľ‰…aÝL.nýŃrz€Ź[,f Q´­€D")ąV&Ľl¤ü{K‘œ˝Äˆ‚Ľ˝3Żţ€!S˜/¤˛˛R|^rY îš3_ĹtOÉbĎ˘ŹƒJ.7Rܒ\r/óżB#Ź[Cć§šÝěFpş1WJĚϸžČ†NZVďvbm˝•~Ôt ăšC¨^ľ*ßP$ŽímUH’ IfEqę˝:’Ş#‘$. Dž^“NÄHźęE"‘$̍;ŢóaŒô¸uővÑ #Ô°éH7jÖQĎQjýgŽ ýş:jZ h hą\îj;ŽĺÍÉDڷ݆hd˝ç`­TĚëjœž]ź˛ LšĄTŮÂóŻ`8_ŽM9ąĘüTŚš:ŮśłŽ§ýwŠ„$*ÓÖCĎ˙œiÓÂ"ͲÍ|™żĐeż8ÓË:Ű1ĘŽč(x–Ś?kƇ™T^şo-{ sYBä’H$ůH‘cĹPؐ. ň?ĺ{N2OtˇVŁ`Ş”×.6‡ľÜ.jÉoÉĺFŠ[’ŤHWONřÂ,•ĎâŽ53‰Z3/.˘uxÔř_65Šcr2 ŰxiŠĆ‘ÍŚP_éGr4 e ˘7iRCȤđÜôpĽQYĄ = Ą! ]8… 'łMÇIě Ăđ‹ßé>ň4"#đű]¨\ł<§KAVÓ›A6ž[ŠÉ!4ŹšááKPŞđÜRمĚÄh˙¨.OŢ9MŠ)péZ91Ë›ĚůüPDÝŚź˜"ˆŽQftSŕ˛ýźRLL+şňţ–ů/ĆŠ2ĚÎBŤRÇ)Űók–}­íXťV&”_ÁdłY!nY"×jˇŹQy’’Ľ„´Â’ŤCž[ďôešFú<„­BŻŹRë§ňM'AĘQ4a!CâMý֝˜TܨM ŕžŰ=hŢV¤4$ÂNÁ3çFhi‡2<€ŽáI8čŔ“i~ȔËY(HMŰn!ď|lB rçW ,™çŹ ]ŹŔ‰%ü95̰˘›ßLTä)=…!‰öĺĹźśŹßĎŠn…Ó čł_‡‰ËĺŠs…űV$—™[ošgϞĹbóĎ˙ňŻřŘÇ>É „l ‹[lgxÄBKÜZ­a‰–°Ĺ œŘ^Š[’Ľ„ˇ$Kƒbb3‡°´Rߕ2—M}7 0AÂT€SlŃ×Î5öź>duiۍŽĐyôŠŐh \ۂpőšGýp´BěAŁLęˆd8Ź ŻpP{diZĹpńńSńie,ő˝(zńí­‘s‚Sž§–%xéBČ2ŇBšIĺہEŽ&c[Cä˛ý>ýSą~xZX"P(´MŢVŘ6UŠŸ˙ŹÚ“RzqšŻâyč[eOÉűżˆčVÔÎX;Ű˝0M̒ŹzX xĂëďËUĘ7oބ‹/Ą­­ž‚~ŕ}8zě6oڜÓ>SŠ´}f1=ť%’đJ$‹I_?víş6î˛}ű6\wÝ.ń=“ÉäîC+™1ň}=ŸűSZÇŐG$Áĺ`rňňWrőa;‘H$đ‰O|çΝƒÄ€;ÇţáţAŠ[’%…ˇ$W ]/‚[ÇźâJ‰yťpby5)s8{^%H˜ňP}9I —~hî˝Ńkšü8iĂöŤP*ÚąŠÉ‹÷úƒł.‰>ĹEÍĐař>em#>ŢüŤĆcO<ˆšś¤Ł#¨ljG&„žŁ˛žcƒ—ŕöůŠ!ęŔ…Wž([ŕšY찄,ŰźMD‚–˜—č]HX6=ĹňęRL‘Ëôćҋ$OŕŇs‚Xž¸–˙—ÇT&úbçŚç~>ĚG éĹôâËěǛ‹§Řœ~°‰‹ö•yD[hbn/ł!(=VnˇMMMbžC ™ŞŞ*ńyË-7‹Ok}!k׎ŸíH.7ë:;óžŰsÄń}\ ö"X˛i&Y ’ń(~ö­F|<ŽŚÎfúoů#|‹ó–ĘyhyUTTW†8.¸˝200 …­FFF„ˇweűzH$Ki9%Wœ˛+‘sşň˝ąć°ŻR|‘‡˝ŹTC¤âďúĂ67œT/y%ś }) ­í×aDa´~3Z•ăظ։ó3˘čnłŽí*Ś—€SIĄeËľĐ3 TTŻG<…'@b–ˇŠx_ţęzDĎšşJˇŹłÓ ĂŮô<.+ϖb÷ʞ OŠá˝eŞČ“Ŕeĺăšú s>„&Z+a;ˆýwíß NT™~ţĽĎyú˘Üa”bŢP ¤˜Ęeó\ÓÍĺĹňnYV źˇJ g3xnGŮD[MČŢR‰D"Y:LRî‰'žAG]˝z>G7žîý‹Š6…ęL.— ńxŒ>Ýâ˝Ía¸ĂT?l]łF„Œ{ź$ ěŢ˝’Ľ‚–(™_Y‘,%¤¸%š‚č%ß3yí̟ټœ, ĽÄöޘtxU…*(œw‹„ˆxŠ×‰ę‹ĎĂ3BßËIÔľyŕutA eĄ8 1‹ÓTšUzjSżsä‘ďÉáͤňŞ-Q|Ţź-Ąüź:Łu›"$œ˘l"’)$Ůȋs×mŁ%Z×EÇÔźŠ˛č6Ëř [~ŽBa+§ĐŘDŤœŕŚ[…Ë0?<˜Í˝¨dÔ^Šő  ŘąĘőŢ*śOń°Ă0ëƒRä‡,4éĂľęXŞŃrFÄ[JČň^^R^9‚—äjÉ¤IČ:‡k÷\‡§öżˆD,ŽßŒ%PU]mD+hšČQ444„`0(ćÓé4FÇĆPYYIő?‡x#×ÖÔ@˛t`“c”(Égľ)YzHqK˛4™ŁTĘX—z¨Ďz' /n˜\*ç¨QčSÁđp~RŹ*ýȄ'0‘đ ă ůćTˇ‚Ąţ ź,pŃ;0ž&‹Ÿ°4JS6Ś™/›Ž™’ŇfšěŢZúÔ2ţŚ(ŚŘ5U Ĺ.pĺ–ë(t=Rěž[śŠ0š˝’;8Šœp‰‹3ýLJîĚ]?šM´*ĽIÍ+ô(ęľ5á,‡ŹcHJŔБá^ œCe…ƒĂăǖ-혏 ŹÁË?ů%ö^ śéűŠĽŚ"uŃ W 5Ř6ľáěäz„HE'Ѩöă×Křaü4ŠÝ¸6܍‡=7B­¨EDĎŕýÉâ[#›0čZ W]#6z/á†Ń§ ;q)ĄŠ!^}ANO.§žş=pn˝CäM˛„ .ďđŔ Ν:-“AJĎ"Š)ˆŇgLŁyúěqŰ‡ í7I=ČqęYˆĽČR#S!› îUŚ*}wh8łI(ÔHIúkŕö‡°ĆĺE%'D= dÂE‡و0văéËy^š9žtęuđ77ŁrmÇ´ň&şÎ 3: ťĎYQű]ŤaúâÂ,{†oo| GŽŕŽĘ.ŇĹžƒůî:¤Öߊš{ކ{ÜgąŠ÷먈:ą&ëBň°Š'Ú°Żőd‚ľđŒĂ]ZnݲQ4ň¸1˜ŸŔŃţ* Y*żNOB˜Ä­!ŞLf˛ÖRˆŇg4“˘ĘL­žT‡ ˝Š8˘É8´t\ˆôÎ؄°[ŽlnZ§ĐńÂ5í¨ŤjÂ^_ˆ„: L“G1*EŞbřٞ}rę’R2T.›ŞěáWŃv×íhذ!WŢT7˘˙ńopŸ?'žy˙[ß ďî›0ú??…Ë: 5ŐňiŒ˙Ă˙‚>6’{_y^ű&ď;F˙éAťp.ďĹĽÖ7Â÷úˇÂˇëń=öĚcHüřŰĐF†DAŐśNřß÷!x7nëă/ż€č÷že _ ľĄ ŢwžŽŚ5>ňBŰwçĘ{ćĚźůÍo2FœĆŹjÜeĺóŸűţő_?ƒˇžímšňöôváżýɇ‘Č$Eš„hŮ×(§×ÄíˇžFŠ[’˛éččy9'VWWZ[[…GŐSO=…믿^Ü,@őôô`͚5B˜bąë[ßúÖ4ÁĂInn°@.ëXúHqK"YHqK˛¤ĐËhžĎnXlŤÓŹĐcŤTä/¸xZH,j@U¸čËâxŞ[Ý:ZFącďv„ƒ~ô{đŁýľ¨T&Š˝Ą žĚÂí FÍg‘r ťßň8Iđ:˙ňóĐłITP_lb-›v ëčA´oZ_u3Îż Ök韥 pîŤ@U2썐ž„ÓBtě"˘áQë˘ĺëF֌n LJđCä„,k[#Ąź9okÔXŠŠjé֑Dbr”p;˛ËIĽ&`*,NĎ/şU|kkť¸6ľş$z‰Ďrö](3 WĺŠj3‰msifę—őL%ˑžž B hďhŔ‘ĂвŚ^Ÿ‹V*4zŁŁxŤëĐę “Ýs"1Ą ´&çúoŔc/BŐ;Ÿ„Źü>’Š‹dŰřTć+Đ'uÄ!|3ń!$ZUL&ißKüăŻ;ŕŹ|銓$›Mbđ’ChćńÁ,Ú|NœO7ăllzüŐĐĎ Á_•Âuí1ŃĐădĘ hšHRRаA)şĽƒÔŹ!Ł:Nż=?œôĽNFq*śB$ŞjhF’ţމCŔŁë+<ŔtŐIâ\Œ~˙n1â/Ë~œ€’ĹCUKCwšŻŹćňA‰Ç UV@NBžc*tOůźp&˘ô÷p‹żƒ+Jۑ@çNĐ'‰’,:˛ˇ]|¤ŸŢI<ńäxÝ˝÷ćĘ{üř+HŇrťW0˝ĄMŻ#‘@2EÇ×ҐHĘ套^Ęű~đŕAźńoD?žxâ ńĚXźüňË(ÇnźńFá 6ěĆy¸$K)nG†%J–Rܒ,ićŢg<łWVţ÷üő…Ë]TW8UIJš!Xeu¸¸Řք@pŽśJ )ăëA÷)2îí{8Ü%~‡…-އĂ,pŃŇP]#@ „şśuPŠńäńšŃž•Ä1jĚ(ÔŁ_Ő˛ŠŘŞš×RŠn—ŽÉáóÂ-Ţ[фúľ[1|ö9Şź§Pٸ“á}ůŁás’*ö=§Ya‰Öů›ÉÍő)-3(–Übxm•’MrÍ?CSěaˆ%(p˜íőh‰\ĘÔ)Ěř zʖ^zŐŹĚśXž—–yma RWÇSB˛˛áçÚEF-Nby,–FcS5˘Ń(š[:XÖ!Ák žôÜs¸v×uřç#­ČźüöÎBž4&ĆŞq}ëÎ÷CzÍvdÇGpęĐÓř˜sźÁ*ř›ˇ›áT#T{ŕ:÷":ÚâH  b6ŠşH´ˆŽu•ěďu"Ť“-M&ŃďŻ@Şű"ôXi÷ő"‘2&Ƃ{lUC¨É’Ęí áƒj弆~˛Ť!z\*'ęIˆšDâÇՁX<‚îŃnř<~ŇŻBČşd„#Ȓx⢂4 2m§ÓÔÁyśp$‚Š0’öps2A5‰_-nÚH´Š ßbż śišŃM@ö]‡šJç•W#1ČYŕ?œ|îIaˆX¤÷Ţu/RÎBÉjB˘ €˛]çaˇ \ˇčë…Ňß+ĪċO!sô°Ůĺ@ÂĐ=÷!súp‰Ţ9ńIÄ_x™ł'Íc“ô´‹ö'QI{yżľLüü'ČŢúšźňŚ3iq. ]‹úŽ ­Ű‚Ús‘ř w–*ö˸ސrxŕŽ’ §ëFÂT6!Î5ëk¤k%{Ě▟ޗ^¤ŐHԇnŚ÷ gé5 Bsœ>˝ś “xç Qpw_B*€¸ńę&xGF ¸ô|Vˆ[Éd*ŻźN菪ƝJ1ÄŹÜ{'ç"ŤČ†–dÁdô”¨?؅­Y)¸íš››„×ßŻźr7nŔ‹űöaĂúőbš°ôlwww‹‘jĽČ%‘H$ DŠ[’%ÁB˝Lň›öeSżPJÔ*š)œIĄĘP—ţDŠzŘź~¸ŠÁé:ţ°OéGeĂľ¸Çpźň4SĹ;™ÖPĺUÍdňS<óľ†N=ĘŞƒCý¨D•x]ĎŔA Nq/ýěkÔČ F‰‹Kj,8Ўˇˇ–]xĺańÝt˝šňlҧD]ĎwŢĘm`z[ٕ Ťó;ϋK×s2 7 G,˝¸ŻWlßm’Îě×zސ–`e¸ŚMFqЇç™ŮĎ˝¨ŚĽŰ>m×k&f˝+çxۖťô˘ó ”> ś$+Ÿ×ƒ‰JGž![˘ Ĺç÷Ą•Î{•‰%°őŚ[‘Ę aӻ߉ářz&şQIŰlXS…gžóXˇy'ślčÄKGŸƒďšh 4 Ó=ˆ- kńӋŔxM#úĂş†*ô{÷ÂĎ‘Í*x[ýC¸ůŘW‘p$áuAŠÔÓ]přŤLÄ0™Ęř&Ѥö'Y1í˛fĆGłœ!F e‘‹ůΗĽ BóP9¸čň /:Ž8 Zz*Ĺ€îô@ËPc•öNÓyj/ôlj\úHüň’¸$qL';ÎŚ‰N ŸŁZ~ŒÄ­j:Fł7€*úΞaNSěrQ4ž]źS%3H‚ŢécF¨RS <ŰŽEôÁćśQwě‚ţâ3PÂăČ ĺíďż÷­Čö÷ ů•ĎŠďiĹĐÝ%l‚Ň҆Š_ű¸AŒýÓ_‰őZ÷dNź*B*ůŠ?ň{PéœF>ţ~8ČĐeN‡vӝôú°•7g|u!ţ‰psX¨ŇIHĘŇśě‰%$;ŠFS˝ČzHźrűů PŽ {ĹeÓđƆáŽôÂZ WďŤtRI TŃu˘c{hŢkԀçß`o-ÍéB‚ŇdUĽČĂćMDÇTŽ-űőUU'\î !F:TşwTčD2Âçş/"$ĚépC"YY¤0gĚ VżřĹĎąnÝzq_ň}<>>.FGÜźi“XĆ ýč\ť‘Č$‰]Ł"˛F&’—H$’!Ĺ-ÉŇg†śůTXĄ]@Á|ńułý›E-—Rš"‚Z"ÇÄ.8špi¸ŠzŢÎĂM’KťŃÖűÂI ^jq%łœł‹$ڔßS&•Ł!rŤŒ?3ŠTŢw-kŠké´)ŃÚ^,ŁvŽ4ÉE_(S'c‰[yám)Ź,%lęě•"ęb [ö4ČČýiÔtÁ°¨ôdűؔ5›–[ŤO?TNSňĹ+ŘśŸ&‚•şJ}Îϸpž:QÉĐCóźJExZŰ.R1$ŤœX, '‰;-MľÇąŚľ őőŐF’q)bCĂ 4â˝;ŞŃœ˝„Cg8I"ţĆśF„ÇűIHPńŽˇÜżýëżF4ÁĽ‹]0GWŃňÜ>|ěˆýÚWpÝk^‘Š8şĎ@ťt JÇd”´Ę8ź­YŒźĂyozŤŰŕ T@g;7ÜO5’éyg˛ÂŢ:PŒ„ ŰĕŸ°ŁĆVUj@XŻnśgŠ8ÔÉQhě)DB‹žŽ‰˛jfÇv×ჇλšÄŻ &Ő.Ć5HtžA–Dˇ4‰dýô9Hb—ĎăĂş*Hä ĐĂ@éDş\śÔžgĄj†×–çÎ× ŠĚšÓ˘äšÇ çÚuH‘¸Ĺ'–é:7]”OĽrö@›ƒ*„>˜!Ţxś^őOţÖř5*ęš§Är>?gf§ ä4Ţ)ą8tzMÇůd‹ĺ“tG˘Ÿ—’¤kćD–…Aö˛ă“P}Ȓ¨•ĽăŚ<~*S„Œş’“âr*>zUĽDăÝÁűg˛pĆ2$f^¤ýŞž(ŽEĆ"Á‹DŞýÍü^dÜt\Ż–iđŃľ.•/Ŕĺň’P'F”sĐßČŠx{A5Ä-şxžE0‰d!dő씋řá{ąłłSäß}÷]bŢZĆlذA|r/‰D"‘,˛ YŇ(sp™.jM­WJě[*$‘ÉhČU˜Ă Á§ŔGůćžWхJdCĐŕĆŘh7N¤Ţ˙ ô5Ž˘iPożńYKią˘tä0hűžˇŢTlŹmŠŠ2Ó=Űi˘‘nťŚşéľĽ\;ł`SŇÖÔĘűŚ`ú˛2%R™"›ÝC ÂYĂ(oÁőŇP rĄř5Éť„zÁ|(Ű6󡴗Ö\öˇî’éë$’š2Đ?‚š *ŤBdۜô}ńDÖˇ AĎ\vtzU=Î$Ɛ‹#Íŕoş/źˆHڇw˙ę{päŘqLNFEXI&Xż~#nž~şúúPĄ'QÇ[1śn—Čá¨i@&#9‰…‰KDžóŔŠá`OŢu>LŽ Â=1@‚Ýďńh~uEˆ*BB2=ˇXˆÓ0˛•Ę6€.öůrѲu$MfƒcĎ#ęP’1oÜ$ú“ĽR;łÔ™šŁ&yÔ3!ڏ„7–‡ĘŮBBŤ˘Ăî(ń”4 5$rEł)œ!ńŚ’Žj§ľ3Œ%$Łđ„/G1:Zśë,Ů/ZW] çšv‘GŒĎ%uţHôé ŐĄDšěˇž ÇČДŕÝŘ Ľˇ'÷đÇíGôŤŸĺk߸qđFő4č=ՐK4iÚnÎ7]Ú…Ă5“˘?D–Ăét}ętaŃQW˝HťHsX˘Ş!CBŸƒ.şƒ;pöČâAWţC Q͍ÉúLÜu7\‘q(}cđ_:/V{úŕ:ƒŒˇ‘ ĐÜ$pCszE(Ş2“K­~¨9Áx–ŐdBnɢ’aĎ-ë^+÷MnnĆőĆőë7@"‘H$W)nI–6%[ńúŹť(… ŠlSz]DFpm<ŠŁŇ­’°e,W¨2Lă/amjĘź )RÁűVyTôD5¤řť˘Ŕ ŇËĽ˛‚ŮXą„,L ,ö\RvÁEÄ­E]ą‰\:rYŮó„­éßs˘›]ŕ2˙ӑnh?ŸŠ‹g,4ËJçÜʢ”ćő’yľňźłô"J ^örä‰\%žO?ƒ"”بܪqąíf¸$’š˘zÜřŢţ čhŞĆĆĆjyü,ÎwÇđŽÖvL˛ đ„pKGÎLVⸯńŞ.ě|ůiLźrˆŔĂOŁâĚi8Tööň ë хq ď˝DUb˙ĎÇĄ>öޞ}Z\!óąŘ—›œƒ¨ŽŽ@/ÝkZăÄ+HkkA偑 ™;ŕŒ€—ŠŔÓß/î+ÍW5Y"ϑ0ŕš1fĽ–gĹŁYr˜"fG…5 R–Ĺ–HJ’5¤Úš‘ó8×qčĐ+Čd˛Řž} $ËE‘ő°b#„Ęk#Y:HqK˛Ä).ŽRĘ3ËžN™eŸÂď]CنHc 8œËĚçiŇ ŻpŁŇ‡c“śmĚ}ćwؖYĽĘ ?3OąĐi.ât”OT„°•ďů5UKв ]vńÍZ`”ŐX`ˆZJ^䈚fJţRŚ_×ü ĹbW_ÉE7%űÄmŐ~}PZȞ݃Ž˘!E…-ŰúźsËŰšpăYžŰÎĐţˇ/\^ęűÔAeĺA˛0NŁ_ áOévŠĹSŤjÁ/şŇx' ;Ż'1ZŐ†Żž ă–F:CxŞŻÁČ/žÂCOŰۄt°ápDäçâ0ĆăűžÁw’{ŃŮ IJxéčŒë_^;›;Úp‰f—*Öáń1ŔK‚× ^=a/śŹÍb°;Šž ŔúÝ×a]C#‰ü;Ÿ“Č'Ěpě\46‡ÎiFZwŠéĐĽ [ç&ƒËˇZVGĺôř0B˘T–.ΚŜX7F‡U蜵lJ#C‚•Śg‘˘ĺn§‡D67Ü$”đ(šZ&)„{ź [,ˆ•²‰ěŞÄ á3ŻDęÄŤš#hÎ!öU#ŸÖK“I<4xA$NoYłŃd řźŘę  >…›„Z]“3\~gG'œox~ô1üd2=z ×_=źtÍűúúđěłĎá ox˝!81zZtÔ6Ăâd<b8ţëďEâýďAĺƒOPšÓô[N’p%G Ň=Ăçă8‡ŕ?+iOş>^]Kj†z€’éţp×7AŤ "ŮۋýńźĂ#pÜíe'’•!Œśl@ÖçGíĹsđŒBŁ7Ś– żyĆôČ*VTöâÓĄ˜ň&{Z*UU„đćPśR˛Př>´wF–…šáéÓ§pöěY‘ŢGĎńΝ׈QÇÇ'PSS-’Ç bp`Ż{Ýk!‘H$’ĹCŠ[’%Mą†˙lŰç}–ôÚҧí3…žż…Ů (Ě %Ä(yirŒš -ݚó–H˘ˆ.9! ˜.haú6Šmy.Ż@ +\VxüiJěň’ąĄ-ľ|A¨˘ľšoŠ˘Ă._)fŁłˆÖ•s{؊S(V™×^/üءÓ1Ł×€iš¸Pä:ĺ]E+ľĺTt‹Vˆ ćžÚ–ŔňEA‰dţ°Ď“NÂÉx։ÎMâŹZř?‰^ |ž ?9ŽŸmރó?ú*öŢ˙V¤ťťąŻ'‚ˇčƒ8|ć‰=›Zě[ˇc/=‡Ł/)¨hXƒÚÚ:œG8F˙đ8ę_=Š7žë]x đ]ŘľÁ… cIx[€Mc^œ9“EĂ8 %Ék?tgAyYÂĐĄęŠ)lpDœ!oX!‰üíŹ5Ú+'™ç˝4_E"ո˃lĘMĆ2c =FţDaž˛tt-•….o.ˇ_$_W“H‘°ă ąÄĽ8˝1ᚤĐ1 w1M$\Ÿ Ǎˇ +D%™Dě'ߙ˛z,茏ŠňK¤Ĺ(¸0M¤łÎ%’¨çS‘ŔEűg=n8hťěĐ TŁő-řÖPD<Št˝$$qBꎎÔTU"yţ Ô´ŃHG]Tˇč]A˛üô7uTTbŕ}ďĹƇŢ3ˆúŠ ÄbpL ÓĽK‹ż7'¤WHřs§âĐ"i1zb´†Ž#Ą05­˝ “롣29‰@bújä‹ůú§č7ń8ܜ@Ÿ„Ęá­ŰPô0\‘QǒĐN(%ťŤřşŤ"U‹X,LŞô÷q¨NCÜR9—*˝$ &­žsĹźíx”Ď=ť<ŇušĂž‘Lžłs-u*ÄĹóÍÉ㍪Ť„——ź_%‰dńâ–dÉŁĚy}^ÇX6E"7‚ M*ü^(XLóŕҧ6™šĚîa•'ŕ؄˘â˜őĂş­,śƒXŢ[…×ŃŠXXîb"—˜+ôښáâŰĆi4Ĺ$ĹîXfž›"†śĎ󶲝[ŃD}ú”űů"–ýzţ˛Â[IŸ63? E,ĽP¸C1a×ţH掖Éb„„ˆ?ť˜€Ż˛ ŐčÇř˜†ŸLÖŕĚŮnxÉĐÎÂéCűń†×ߋĆ:5۰sS'vÝu;úzđ˛ŰŘÄ(uˆŽŽŔéÁE‚Ä_}ępćôYT¸âr8ŕ­kFť_ż”†łB#A­íÁƒÂ8{l+Ţ˝ţřün¸˝~4›qéâŞóŢÜO˙ĽITq)ÂW nĹ…`˙­´n„ƒg͇ˆs‡eQQAPsŔCe‹’ˆÂŰ:5#ý˝N‚ˆČë$Â3ÂÓ̑ŒÂ5ڇ”Ó G"GäŁő>úMˇęBĘD~!ŚŠˇĐÉtm&qK‡{ýfŃxMÜgXҞKćsMenm‡âőAďíA÷ऍăĆp$ŰíFee%ŞI\B÷9q˛gOÁ˝ă:d_~jtăđařiŸL<†8 a܈>vě6oŢ,ÂľŸ}“ýsŁÝş÷܌R‰Ú9 ť#Tîß{7‚_ýš_9‹D„­á3˜ŒĂáň™:D¨žB§aHYHřĺ@6XĄßý*7oÁڟţÎŻbŒ˙‘I‘ü=]]#„UW:‰ /ăńĐľ¤żĎ™óˆ46ÂW[gd Ę@Rü}ŠávxQl‚‹ţ^-ôÝIÂŹ‹ţNúťąç–Jo'•H‚đÜ*ŢM5+[ˇn!+)ňýíŘąS,ŰšsGŢ6ĄP‰D"Y|¤¸%YâĘÓQJÍ+Ľ×[ &eŚcÎAK˜śi‘}‹ Yyb–5oßÁœ4=_Ň 7ÉrŚ„Ź|ď-Sž˛ \VF0űdĺ°)ôŹ*v)tű5´‹Z…×VÁ ×ŇĚÎe%>śž›ÚŠÁ2<4lלóĎżd…—0_äŇó÷Ë;'Ěą:;CýwšˆUzÓźmPĆöɜáíRi‘\}÷PÚŞ[p} RŒÎşîuo†~Ë;ŃĐЈá/ýńÜyHΊ­ ŕ5wíÁšŒŽ“ĂƒŘśë>u‘Ń:wŔ]Yƒd‚ŐŐ8ŃŃ7<†p<ŽÍג`1qUŁˆĹ€1Î ě"Ń&ƒ 'ńź'‰ę†6‘ŮŚą.‹1÷Z46řňŠË÷>?óěĺ!†+,ě ë0Ÿ aCWMßKó13! ŸN,@ÂJ”‘SJlKŸŞ‘ŒœsPń„îř$ŘDCľPŐHŽu“€“Ď_š„]$[w‘–B:Ďł@Ś”ň0˛]ň › +Ťëyś2ř;Ÿ„{M&žřϨîy@„[rc8FËCÂúoşßˇt¤I, ţúÇ>{˜#)>”ĐŨˆ‰áa!nńtęÔ)ô÷÷#SĺÇZłäŁß Ü˙v ľHi Ű;ęuÁyžՏ=ƒQ_5]“QÄQ8$BeFĄ3)‘ Ÿ; u/+<š< ç2i„ţŕË˙'OžŔńŒxŠŢ ˛!dÝ>CD$ńŽCDé„VJ÷Š31Ab¤ŽÝ{Z[úš#ôGŒL+Š‹­ ˇRäóbAËA"—ĎĄâ–ĽŃŠ–Č-&‘”†,ĘѨ(|îŢ˝[ĚKŻŹ„üSJ$Ë)nI–4żóW˙gţ•ƒâŐLË,yĽpĽČžÓÄ3eş†“yŰ>śeJáňÂςí Ŕ.ĈESܲ„c™b6sŢřÔ ŘśUr˘’q\%˙¤`ó°Rň×ĺyn™ërĺ6$>ăTEËÉWÖźjŽW­ĺšímšvlMFK|,ĺɕ÷ŹíŠ}/8FŢ'lÇƔfżî@žŔ˝¸ĽĎđ]/ąń|ŞÔźĎßxII\.8˘I¸H´z­_ÁłÇ1Ůş Ţ&?H,ůÖżţ&ΞE۝B(Ĥâďâ^´FÇĐŇ؄ţÁ1¸ęÖ iű­đ­Y‡ńăűPuóýCSŔ? @uëv˘&X…DeĆŞŇhËƅ‡Ôşí đ!‰ÁĄs8~1†{ślÂ}oل=[ëąďgŃĺ â–­šâňłďá03Ó&đ FFĽŹ!`pX Žœ8îbĄEaKiqˆÓ&UNF.áAĹŰh*U{x_s™˘9‘‰ĚéťŰ/<‚”Ęd&zÄą3´˝î• Đâab"PI¨ńĐtMĎaĽlÚ…'•Älm=đćw‰Dë,`9Í$ďŽúF!yďş›ÂI<ňÝ ŠąQxną°UWW‡şnĽk]kŘYúŰššQőçř“?Ǚ3gńĹ=ýֆ „÷‡;ŠŚHöňř86m܊ťî¸ƒD˛;„—Xq¨ÓŔăĆ؛îAí? ŽxžÔ"ă˝"Ať–ŠŇń˛âÚŠ‚=_ý öÖĽ1Ž$ŕ#m ÍŁ&ŇuUŞHzütŹ,ÔhDä óMNq “$bšéړ‚ę‰ÓöAÄ\FšŠa ŇbžlFYÓtcÄM]vHŽáš5?8ßÖńăÇÄłŘٚۜmƒdů#ľ-‰dy Ĺ-ɒ†GäR nŮ>Š­*ąÜ&˘(Ó÷Q ÖÍ(xĄ¸Ŕ•§\Ö˛Ü>Ę4=ɨכn=懺¨X˘–Ą:qŔ˛ ňÖXÂOźß”Ŕ5%é… šRDZ˛]„|qkj^QŹ5zž¸%ź-Œ¤ŔF‘Mز \šRŮD2q<[ŰĹÂ)<ÎtL 넵̶˝]Ë!rj—źďŠ^D”*"„ źLűFňj]UíWoę¸( ÜvY‘D֚lÔIfsn%Ť¸>6OĎI$wěáoϜíC×ӏ?„÷żý&źé5oCsGΜ=¸7€|çGxĂÎÍčôšŃX[‰ťý!DÜUp+$Bđş5ÔytřęśbëÍMBČđEb˜ěí/9‚@…ŽćĆz„IœďŽbĎŽ­8}"…ýGđšűoĂÁ—bs( w&?MŘ(MžB,Z Jœ‡%y<cÖM‘×đˆ‰šńi$˜8pů'Ń-k_˝|œ^ńŹf\~R°â†aŕäďôÁœB琌“ăpAó†ĐłH{ĐčXÚo;]—őžé‚‘ŤŠ…Šzăů&-™€wďÍF' \žÎš0äT:…xM*7m%ąĚq¤8 őƍńÉO~-­­P6nÎýőŘŔ;ŤjšáNüŕŔ1‘ۇ§ÉÉI#´Ţ—,Šq>m<¨úđĆťîf|‡ëœ1ě †Š†ě;,<˛ôt z–ě4 ‚./]“&ďy#’7\ –ąP1ţ­ţ„^|çŸ|ă•"ő¨L]B8Ľ O7…­@4ŠpC›ń—ăŸL%Äť]÷’’5fß8č•Ő é3{K‹%šD–"ëŒáŹ;@"Yš­64×7+‡ßrË­H$âBŹfťuđŕAńl‹ç>•DUu5ĆÇưwď^HV6‚šH$rů×ĘĄšîžo&&&¤`/‘Ě)nIV4sś!rPŁ€Gœ*2ŚB˙Š‹fT͔R°˝}Ćň*˛DÝśň6.ü4É+“mYŢfś˛{ĹÎŢl*ľ°ř‹]+ťvVxţšmôüĹ3‰Qyű˘ř|a™tN$Ía9ĽśĄŃ˛Tqľpzý˘—ŒG§o6JoŁ ˛Ş 3DR.ŠÇ‹ęD ýI'žTw ^§Pë˘7ž‚oŰľřčÍH˘ )g+ŽaMűZTč$ü|'P_K3âîÔÖjDndœčlŽÂÍNŔérÂŻő#;QH˙¤Ő‰ăTĄO"á߄Ÿ>řs4\w+*Hü9öä1ÔT×ŕŇ  C˝čééĹYŇvď˝!Żź*)MNn>ů Œň9Á]Ÿ˛zNâ0*6ޏţ ”P Ct?ŒCŠ"0FŔçEÖëĘÉůy$Fź˛eYnô'I`œ ëA▞.žËLŘaŤĂěĄĐItÔő4 1ú[Šđ˛˜6K˘‰d6„5™keŃ|isˆ,ěđ裏枻0‰\ÍMMpĐ:~Ć9'— Y\ÜsĎ=âł§§GüíOŸ>-:"ŹÁCÖŻ_/Ö_¸pĂĂ訨Ŕíˇß.śÝˇúĨ›ŰśmĎÝ3ÝÝÝâ˛öíęęď“*ŽňHÁô°řąeËVą˙ŔŔ€(Kmm-††† ‘Ź4¤¸%Yň$Si¸ŠáÄ˝aÜjp’á>qţ˘čćđ‹îţ!źöfŁ÷ë_żőCÜ|ív\číÇ;^{Šž;ř**‚~´75b,ÁˇžÎżržgíučƒ‹ĂYŞ*á÷¸‘rP…œr…zr‰ůœŁă–×ދʚZźđŕ虂hí\°ź¨7WÁ|ŽÜśĎ)‘kŞŃ7=ě° <ŃÜvĘżjŞPšc+g9͍ŹČ|îĂňžŇ‹xpŢ[yž[yë­RY?iĚ{]Ćđď}ƒ#ƒˆL„Eĺd*ƒşŞĐ´‹“ŚŢ ‡N‰†Ő–ÎVá!sÍ _ô‚íšÚn JÁÖ]ťqâŕKč9˛ßÜNÇČxDŸ˘u5fOŰdT,Kg˛h[ăĚü/ÝF%˘Ś"D‹ÄŠAɕ?ßűcpt\œg]M•ř>‹ÓýS4Vyž É÷ö™‹=b›öćFýĽÂŽ$erd;c••"7Ńé„Ď nk¨DzTĹ =ˆ}§â8Ý^O2?lhÁšÉ0&ItŃţ!&éţΐÍuůüp7ś ˝eÎ6ˇŕÝ;śăÜĐ(&zϣƝAd¤ŽĘ „ŁqÔmمdďi\sÓ͈˘k8ŠŠ›Ń€ZÖřĐÓ} Í$šmŰśĄŠŞźňśŠ~†ŤSšžK\şnŹă§X1œyŇ:+˛Dř˘j:ř°ÇW [Ł$pšbăHşÜôü9ŕv¸ÄHˆYšç°ÄŒ’BN,ŃH’x塏Šř =ă$ňÔŃ3[M6ŞŠ„g‘śŠĄc)Ëtüŕű?Ŕ÷ż˙}ÄăqÔ×׋gŮĘĹË|>ź$>˛7çĚúĺCŕWŢöV¸ü8HT˛5Ÿ˙üçń‘|çϟ !ś}ź?ż›››…×÷öłĆáÜčám÷ěك UA+ąB°Š=ô.mŰX’Sq8ÝşşHœďôPƒ˝łIŚ\>ŒĚÉŁL ‘,¨!łŚQĆҍ5ˆwAË8ŕŤk‚kl™Ä$œTO:5ćâUđ’pڐ}„“EúיϏóx‘hŻ”HÔŻŃß&™IŔË^et¤h[ý­ü.żHzŸáÁŘ{śŹî‰¤4şéş=§;É|ěYœ8wîœśřůäg÷Ž;ď„dš31’;ř^`;ýG˙íDŘ깣Çńöˇż?ü°°g˙é?ý'|ó›ßÄoüĆoŕÁË>öяáË˙ţe|ücĂυ^xsEŠ´’Ľ†ˇ$KśşűEŻlK}˜x"‰_žřkkĐ;8œˇběúK†D2%žóËáŃ^Âúś58vćölۄbd¨A1™D 7Ȩ$!dd< ?‰]I'UšFn•B^hÓ-ˆUĄJŁĹĺŠ2ĺ‰T(.\Ů/Ľ`{ˇÄ9Ú's¨AÍŹŹ<\0e$ŢHłç×2CĄçţĺ…Öé…':SÎ-ŰúœTŚŘ2yŮDŽ|1Kł‰_°…&Ú.ón‡1ě;żäG#pj=ۋʀ7'nŮ=´†I€z⼣¸ď–]$<ĹĐPc‰[SŰV` ˝ŔŐľâ¨4†îśÎ1B““îKc*œŠď#Ňxšl–Tą`QËçő K ox•Á˘Ô8ĺc6×ŐĐýż?46!DłÝëŐĆ=ÄÂÖÚ5MFéĚρř{gĽ§‚dv6†ü"_’?ÇÖÖFl!qäěŽm8™ÎŕšŒ†0#ŃĘ30'‰ľŽžÜXíċtßőPÁ÷čzzv˝ý­řy¨ăü, Šş ?ůá÷ĐŢšCŃ2ÔŁœ$ńľ–˝‡HȨojF‰,n˛…z{ĐYéÄáK—°mý\ťs‰2 ԛ}M yĺľÎ8VŠE&úâ6ĹŹ°nŘ;žé*&ha’p#„E0ăœ$œř8Ń8‰J–zł9<=W>*ť—Ĺ-°H˘BqzÄŻ ë yŠĂŞ Ő$šÉćřha#}VŃÄoľˆA.ě€ŕŃé˝ôĐC Ą‰ß ,lľˇˇçBOŘc‹Ĺ-nx´¨˝=čBÍäŽ|űßQßP_C3jw߂~z'őőő ŃꗿüĽčőĂހ§žz ťv횡îźăNüďżţßĆő#‘ˆ{÷yťçž{>ęři#ąą°Ŕ<Ę`% DţX›RýxšŢ‡-M­ôˇKc‚Äö‰IÎMp×7@ţIÄϟ€žNŇ5ĐÄžNę x‘x/ÂN‚uPƒ•Ô;5ˆl|A2‘iřËŚĹuV¨IĺÜ]tÎZ*!r˛ąĽwŠÎ€âöLĽż——ŢÇiş†|^Á —ŽA‚ ˝ŸšŁbę2Ąźdřš+ôl™ÎÜěě5ðx͓D°]?xđeœ:uZ|o ›ŢšŽ; RdÇĹÓO?-–łGŰs˜ŹecÔ!të-ˇâ….<ůēšcŢzë­BŘzć™gÄwîиîşëDG˝ęČ﯍­Ă‰'Iź2ö?|ř>ôáă‰'žŔżüËż@"YiHqK˛äaQĄŐlôX=Íő5řOď}'&IHšBłwűZW+ź\öňú˝źKTň›H+ú.ęĄŢĐÚLâCěďŚý‚żXJŽĺUsŠ{jM_ś˙áĂŞ@¤űĄe !ħ:PAœ‡…—GTüY¸wĐ:IąĘáůšŘś8„ČcŒ.ČYœ”žß7ě ŚŃżÍ7ĐăWă0D/ŽU´eĹIÂśŘƒƒĂOž<)ň`ńsÎá#,xqď;ç<łÂ”ŞčůżŠĘcˆf ‡ŚŠq3&öI=ń š8,D1K űßůěۡOxźĺ-ož[/^ÄącǰfÍ!˜q>.qtŒlŃPfvusÂlD˘íŒhgéynĚÓiř˝n˛/!›¨ŁĆ‡Ä÷ŔqÍn8@*…Ťc†î¸ ÁżüCŹGSaěĐU¤ß UU#Ą÷Њ mëIúŕ T@#{ĺˆL/9%CďďtÂpć‘(ŁąŇî2ş!vňßk4܇qŮŰ­žşÎľŠî=#…’™xţ…Ĺs1N/=cÉlŮŽ[üŒq(°DRČłĎ>‹Oţá'…-çű„GĂ=~ü¸¸ˇ˛6/Un§œ=w{÷ěÁ–­[„Ç,wJ(fžI;źě}ď{nšĺń˝Š:˜>˙šĎăśŰnEoOţű˙odžÜŹgΜĄ÷p>őŠ?9,yŰűěżáďz'-ű”ř]†ĹŻ_|ÉrGŠ[’eAĄŰk Ex=ůá‚w]Đ8L‹a‘˝ťÄ1hj6÷+VcŠ Ä'{ŐXŰĎ łq““čܡ5x ˇłĎĎ´Y^ŽAfÚ}–Ď‚ý”‚Uł}/¤ŘöłÍĎFáľ°§vĺšúcÔ1ß: Ał@زf꨹^W…’!ˆÓ~¸`6›J`äüÉb[‹{“Ă‹ř䦆–˜'Ü>żČŻ!šZ4ßŃćĎű˝ĐLeŕő••(7î<Ôh_ß֒[&ĘKfĂA‚H×Ů3ČŞ.htďԌLŔ5Ávz–´Ć8ö(ĎAÓ}çő!MŢç{‡ŕ¸„ˇm؊“n2qyqÂႢj"Ůx<ÄXß!žžňĘAlŢ´5č(œăŇŕ0*¨!ŰűĐž“xý}ŻĂM;:…wísĎoŁŽ ăçŽ ą%?dœ˝pX°Jąř#D.#ü0EĎÜUŇĂ–žŠa8 ĺÝŞ^´*š| oŤ!L‡%:ę˜œEşşĘ(„˜Ľ‘¸Ĺ˘”đ>ŐUh$ú•˛Š|M9Gýőč˝ŢNjŔEqáâ~x|AxźÔ1E"f:s$’RđóÓDr%`Që>őGšvLŠń<Ę&OüěÜś[ˇnĽŽiŰrgČż˙űż‹wŒý˜‚nQě÷ěBŮß˙ÝߗÜN"YÎHqK˛˘Xę=ś9ÁF7:Ş-ŃJą‹\˜ZWLôҋ)`—ů\óYgH5zţ6śó.vŒšź‚ =ąr×ř2źÇ<˝Ă9˝ng)]ą8ł•M&L–Ě%CWc3ęčţŞ ÕHĂ™Ŕ†Ô1ŹŤa_Űjî…BBʑł—0xŽ žÉvH8jmFSŔ‹ďßr+ ?YŇ>\ 5$NĢ1hÂX$*Ä¨×î݈š*?6n݆—ěG{ vĄ*×ů`§‡t„D´ŘKk‚žGiŠhYôĆ'1žN‚ƒÜTŹN*Ičao-–”˝<8Aßž§QŐҎ4Ý3j  ě’J@ďéfńÍ;&‘4óÂŁpř|Č$XlT‘JÄé:šŕô6nTO†1‹ŔM×<=> -C÷ý-á4+ž\wˆPE#çVqëŤ 9ÍĘŽ%źđ*ŞÚPÁ˘–AGízx\H$‹ÉD<‰ÇNt!ľ„ó[6†ü¸sSۢ'řâ™3ÝÂţ-UÖ×UbďÚfŹ<؃˜˝yӐH$ĺ!Ĺ-ɒfõ׉üDÝ=="xmmqäjÂ=ëąX\¸űú.˝h–:)qÓíŠFŽX#™…ţt =-7†˝.4}nJ’[ŠńV!rQ%h]%mçM'Ó3đ‡BxľĽ ŚF9œldÂŰghPŒ:ĘŚ‘M§Ä€uuu8vňöÜrŞ9Ńw<.Ä­}:šŕÚčCĽ{aʞ?y>ްO # 7.ž9ƒkZó“0'¨1už:†HOÇŮř‚Ľ+!-9œ$lšáuNykAäČâŃu‘ČžGácëě2%rÍaĚqOř$ !Mb ˙ÓTĂ]4Ŕ^\b™n„Ëqx# Jš"˛"%<É4řUĂűŤ?ůÉOđŔˆ@·ľeËÜ|óÍbču^ÖÚÚ*ćßüć7‹m9đ}÷݇Ǝh$ą§ÓšvżřÎýňDűárš0K``(*‹ÁR}T„W9rD„(rRyÍŘk̂ßSě)Ć—V4ç+wTF."°m™ž1ÜQëÁł$ő†›rß-ĎŃů2‰áúżú*úHŕšÖhś—>ĂŻčx÷ő[sËzîKńŢâ|!ŰIšHqK˛,čéî#ŃLNF…¸uňř1ŒPqóęí'á‚qűý~;zŃvnYO˝Ć Đ:čľçDÂׯĂb‰„'„¸%‘H$Ë=ÖԄ0xîZ7tŕÜ`żůřćóh&ft(ŒÉ^ŒŞ•x‰Ä‡ ŮÎĚÁ— oކ‡Ŕ;zşńÔÚ  ů ’Đĺ胃„ţ–5čęęG¨şÁPΞ˝G} Ö7ť1>™Dme}đÂ]Âí;7˘*@ÂB= iA*ű0věÂŰ;óʛ Ńc˝ľ2)#tBJ.‘Š=v؏'•I"M—CX”"ĄËĄ8iSExhš8d‘C…Ĺ( $Ґ Ś‘˜“rdčřNL*Ył¸u#Q%5KW5ąLx5™oX^[iá;¤Â'<žŚˇÚN“d†=cŠ~7ŢxŁ˘ýR÷%‘žE.Aq˜Ä˝ˇ˝ímřŕűß}táC/ŇűeĎýýŸ!™žZě#ß}š‘HžłłSźŮŒĂ99='çѲjjjpčĐ!ą˝n—‘´žT¸ž‚ŞzΊő%xŃ=ŢM-*ź•5¨Ř˛ ŃÁAL‰2MÄIř T#CďdÎGœJ$QYՄÔŕBô7ƒ§ŮTšîKváń´gŇYŃŃŔçŔ‚–Â9śxžËÉßĹŒ¤D)YŹ$1S!ĄĎĺŕ{ŔÓMz˜KŒ˘ŤĐß˝gŕ0â‰0m݉d18?<ž aËďvâs¸_zî;qQ,ó’püŽë6âĚŕ8^@Gm…xÎYsQG‘ž!̇:?|˝ńŔ6ŕ‘G#đ͗ýúć,líioÄćŚ ‘0öŃ;ŽĹ{żđ3ž5źiç:ŒD850Š Ő¸02őuUtDň¸ézŒa8ÇݛŰńłĂg1™,Ďc‰-ÝĎŸÉ‰[lóžyćiźć5ŻĹňF‘ :–Ž×œD˛Ôâ–dY0F˝ŃŻ=†ˇżí­â;|› ch˜OĂCˆRŁíŚ[ή6:xpО] 5ÚNœ8Ž`E墉[ĹČRƒ)žH!™ˆ‹ďÜ3żá†7Ř8ń1_ƒR˝gö8Ž„9 †/.„ć,`ZpH('ĎÜ´iÓ´ăr(N DGG~‚ęąŃÄŠ˛Ä#Ú˙>###"G5rŮbôöą§ÄáÇEx7:Y”-÷¸œş§§—>cŘšsgÉăĎvÍ$’óîŁÎ‹KŁÜľŠ ­Ő!|űĽx˙Ű„֞ŹŔĄKƒb›űŃZB23ˇç¸Đ3NQvîKöŘŇDÎ-iÓ$’r‘â–dYpűmˇŠ†€5݆ ëĹTHsĂmâsŰÖÍBŕѢ¸˝ŚĽ ã㸜{őĆŁI1ěyO÷El¤ĆK X…4ő"_ěî#ç9i]mCśoل• 7˘xŘ{/5bo˝őœ>yŃx’/Nř=NĨÁljŚ˝ň *H|Ô3qj'ŃŢކŽöVŒOˆÂJs´@#ÇĚ%ôöö`÷îݢŃČp™|ŕ×pçwŕţčSÂcaaˆď•‰ ţ{ç‹[GI E5Ăăc8ßE ąŽúűôĄ‰z_~ůd2i\Ă ¨Ş\ŘhJ\îáá!ôľľľc``P4v­$Ҝ‡‡gf‹b×°ŽŽŻžÚ/Îç….’+róĐwŸĎ/B™vďžIšÜĐZ‰?šŠŘŁ^Űv ú57NÇHPüđOD}ËVč^mمĘú&tz˙ô!Ü4ĂĎöތŸśwŇňVÔ+nźiBrRÁĐÄEŒŽG Ĺ†ĄúI V˘ÚŠâŽ q<{Î_  }:=˙$źœ:߃‡/ÄĄ]:‰X¨Ęîzě îĂŻÝşŽJŒ#?¤F4,9] 7˛´ é)¨./ź$jeHÄGÇEŇxżż‚ú6HĢg?E;¤ł´ę"•‡xÜ@Pč NŹžßÓ´šD3ÎéĹZ*ý„›v`(+<łĚrˆäód[¨ ěGТƒ`dŠ0żüĺ/sÂ3?ÇěĽÄĎřŤŻž*ćů“…y˙ożýv<˙üóŘşńN8]ŒN„1ŚúđŔ™4ĐŤŽľĄ:]łW.őa€Ţ-‚ČÇä}řÚđo<öŘcŘźyłĐ8WŰ~OyUą]86Ăů‹'”çV9šžŸa’-@Óé”Č•&‘,ę"tv˝fK;žŚçúŸ? ž§2žš˙8źô,˝ńšuĽŽţöäzölćKá­ĎÂöB˜Ďł´§Ł{ۛ„ü•=[đ˝—O ;t´wŐ~žđnXی:›ńÔénœěASeż<хkęĐV]hŠ:!ɤçăĚţwbaĽŒˆi \‰¤<¤¸%YćţˇfMËÔţÔËĚÓ夯1q¨‡ž+Ů#$lœ;ׅ ß…šÚfęUĘbt°—zúW´¸eÁymXˆilj&ąë„H0\W[•KjÜšÎđ˘‹M:0IŠpö:phŻ”pmíÚ1o [7Ţx>řÁä„-†y\‘JPăˆsӰDŽťîşK”ç駟FK+U8ŸĽĆĺćM§`ĎĽ hhiÇbF…xƢ ­œąç$őüýŇĽKš\”ě‘Ęâ9 h###š2ńďGGŠ„ľ×ŕÚó xđťqź'-<˘TŋäاOŠN"Ů牋Yľý—ŕě'Q.€†lI˛_ńd\¸PrT`SC†ě*G˜˝ł¨ Ž$ý<^#ŹÔĺBUt/V"ĂBĽƒ–ťTąçϕ(ŠŃĐăM7HI$&¨ăę”ْß9|]äč_’Ĺ„C7ÔUŕĚpó!J÷ýýţ“čO…÷ŃłÁŢ\‹Í˝[;râüÉ#´.„Ým¨%Aj$–,{Ÿ]bbžsनŘ~~öŠWrۜ+ŘËŘţo~>ű(€ĽxÝ–ŠşŰXß^î蜉¤<¤¸%YpĎóőjˇśŽÉ…Z”ń2Â,Źí,ňś×u3GËâőđŢ{ßësóš™?D$Ŕľš… Ome÷Ŕ°Đôš×ź&÷_7Üxó´í,Ď,fóÖüý‹a \,ýß˙űOEˇÝ¸qŁř,läÜvűíâ“óß\ýőOŒĄľ­[6ŰßpÍ9o‡…ÂBÝŰĚ0Z‹ëŻß[ÖžÜ@˝űîťrßYĚ˛ŕ†˛D2ĆĆ#8pđ4ţ š[ę…'iUŔƒ3§.`ÝĆv\8ߏd: Ÿgo¤FÍŻÖşđŰ <9ęŔCău8Ę -™‚ęvb §Ą5;ŃóÖßGŃ_˘ăT {˙Ó@ö|$hd}~ÔVčŘŃ2@ÂMY†Âŕ‰ćOáŽMkđľoţ8°żžqí("ŠŠP~•„Ĺ žŚIÇw$¨ycŁp“ ĆúFÜ9•@-Ň$V9˘ŁpĆĂĐ h?ÜA7*Ř Üŕq‰ă¨ŮŒđôa[Ě! zć=t0'›f2×)s¤E–Ňَ;ĚŃy5‡8Ž‘€ÖE śzšÖÚ LŰą0ĎĄƒ,Dłw%{˜Z,έĹâűĽ‹—¨#$&ÖąŕS8Đm" Öaz×ńs΂TżąXŹbo,chxĂ>ńţ,xąxŐĐĐ źśxZGVřŁőŽ|Ç;ŢŞŞę"w_"ćçĆ#ĂHrˆŸ+ČÉĹŕ¤ë_¨ÄĐŕŇ!säIńO ÷oŠiÄɊͨď~ăNý=<4…!Ąň¨îE:3ažküe•™˜Č™"űŹBH‚ˆp˜ŞĂ-B]öȢ÷§üŁřX”"Á2K\Tś‰‰ H¤&ĐÖr=źî &ăƒ8uîQĚ>ţąDR>zFŸţÄ{ńđ‘ł"ÜnŠÂ!ŻżvŞă”Ÿ{Î÷ˇ+ƒŘ÷‡ďÇă'ťć˘xĽŘP_…;śNĽázÜJH ˘›Ł%ęŠ K”HĘEŠ[’eÁŕŕ˜¸BŰŃގŁGŽ`ptŐATV×ůŽb1‘‹‹‡!ŸŔöí[qöôi„ÇFĐžůhŠ8‚Ô5Iy5uŽÝš—KĐ*ĎDCIćIşbĚ$^ňß¨ŞşVLÖßfš°#‘Ł˛ÂÝ×mĆwODŃwŞjxŒlŕ:ŒMDńČc‡°i['‰#ý읈X*ƒ;Ö˘ZăÝuY Dp)™¤^ř ˛É,†×ěBÍи[ÖĂátŔ51€;î¸ú†HŔPąeçN_ýÍ$)Ş&ćÇŁ#8|iąőג áÂůÁQ$Ç/ŕlƒ-ö›yŁÄčˆôl&ăĐ|AzHšüČŇ2öŞrůŤŕwş'őET‹°Eí×âöbÓĂ)葠Éçr“@ىőx?>3ş“.„śŒČÉĽëƨˆ\V‡#š!YÝČáҕŃ0BűąWVfz‚ö›nş żřĹ/r*řĘ+ŻĐľŻD×Ĺ.ZÝĐŘ l ‹U×\sÄX¤âđĹď|ç;BřJ$ ‰Ĺ.^Îë-qK\:> ^ÖwłŘKƒsqą'‹]vëMozüńHńƒţŚJ÷I$ĚëĚ#ş}uH¤ŁbdºРDűórqX`M,Šń5ŕ íŽAI ‹áŃúŤśŃýľŸţFNdčoĺ!“ş×ÇÉőëŐ`ŇáĹX‡LŃß/•„;›†›G:¤ż™ŽG ˙έ– 14:ˆP°kZöÂĺô#•ŽăŘé'čD˛ŘÔW†đÁŰvaľÁvŚŁĄżŃPÉŐŔˇ4™sK"))nI–Nţ›HÉh Ď†zN;‰őˆp9őüvŹí€–!ńŠz9†Ç˘ĹúÎvxő4Şnœ;†?TAó.TŐ.ÂhJŽ"†§—,9 ÷=1›áĆ[fe V2όd6¸šNeáМp“ÝŠ&SźŘF˘ÖŤÇ/bmk=ú/öáú˝[I8đ"iŽ ȝ ç{{ ÷ôÁľŚÉŞJč^/ÔÎőČîN—^yţYźńÎĐN‰ťu3ĐB"F–E~3ܐnĎh ¸?ô=„Oýo÷ĄąĽ}Őă1a܈<Ł<"^ˆÄŠ´#‹ Zi—źŢŇ mrTxš}!TV5 ńɧzĺÜKôcktő§Đş+ß6IŮę ˆŠýY/Š„Žjž <$”( ‡ÇИ$1hŒŽ˜H@Ĝ¨!aŤŽ&ŻŞ ъŽ€Ă‰z'8HËrrzÝmŘ)ÂŁKÓČŚ8B áW‡Ó Á ˜v†/ŸG‚ \z‘%ÎéǢ‡˛`e…rbgWdኽšXˆâOöÚbŠËÁ‚ Sœ“ϲŸœ—ĂyîŕąŕpFŢĆČSčȅyłˆĆś“Ěwuu‰ő\†”ˇŒÁŹh@ńź&Κ˙ׅu‹­XÜ ůéďž@ ZŁÔŃäÖSpqx'—‡Žľƒ&îęá0Rżžw|M.qˇ‚A…DɌ&ޤÓ㆒Á7‘€ #ćĐ·ŒĎ•ë”($ÇXdíM×Âë ĐąI¤Î,~TW0˜˘ż ťn–Y"‘H–7†°%=ˇ$’ň‘â–dER_ß0mYuÍ剿ˇœË%ćpE_5…œRbŽ%(EŁ1 #FŸ‹›€RßçCC}‚ÁŔŒĺ`‘…˝†††O,nˆ˙nyőT.ěĄ—HĘ'™ŐámŞ€‡EĄX u#dş‡ 4V!H‚ĘŤçz 5ˇ"“ cäÔYœ9z7‘¸Ó´/)@“a¸HŃé3ĺ‚iv܄ë.|JÓZC8ćD<šAĎ ‰ŤŘڞA*íŁĺ6TœěVŕvŇsěKc˜ł/C˘N’솊žĄ4ě–ŰĽđEx‚D§fO]Š(.ĹĂ"y8ă&!JŃ Ç0Ήĺŕ˛HŔjv‘Ć#'ŇJö*bŹŻR•Şś43”9"# OOžtŇő!éE\§ ZćW ‘†sN5ťÜJ9‘ňW#˜>‹I{÷îĹĎţsą‹Y,Pą8•1˝|­e,~ą§{WqxޗóN—đ8eoŽ'NaŒÁIây;ޗ˘ŕýů;Ű܎öąÍ… „ Ć^\ü›,šąŔ5ąlL\ý­Ů .Ť+b4HŻľę4ýHDóŐÁ™&5: ”4|zAšX‚tŞœŰL1Fš4E'ŇľĐěN㠕шđˆăQ-ł‰Š—A:4 b‰Š‘1dăQh Ľß\$fyéoK˝âď­ł—žâ×)hF ÝŁ—úÎ#kJ$É2‡_Mşx+IqK"))nI– ÜG¨gť-/ďČLp8#{WYŰgŠ5ćtćçóČd˛Ó–ÍqFGÇDƒeq.j`QwMMľu,Ľbđšőôöâž;î˜6l°ÎáVŘZŠdúş!N)fCNŹľ­Lӏ|ťŽ˝F$[.UnLüĂ?ţCÉúZuU5ţîď˙~ÚÍɕÄʡ%GK”HĘGŠ[’e7ůůŁTĄw q땗 ‹Ăë ń$ŸDuĂřœ:Î]ęCMEC#¨ŹQߋÚ*?yúeěÝą‘*ÂşhźébˆyԐ¸űÎŰ1_4:ŢČČ(>ő—#MˆźŇąőB'Š2á! r‰¨F¸†ĆŁ| ݁ŹůŠĺY"8Ä\ĆŁy‰}é ˙íĎ~wÝuŁč­/ďŽLR— gëç7˛˘ÔKĎçŔ!3ŞCűů|^!(ůźn‘ŤĚÍ ţ““Ô42D.ŻĎ#ČRăÓM˘^,žß5„•4rÂÉŠˆIú3ü>\t8ôŞÎT ÝJ 'ö^O÷Ď(ęjŤ…8ÚÜ҄ńđ¤řŰMD˘˜œĂĆ͛pŽŤՕhnjWCzşťĹ8b•Uâw˘“QŃ߸q˝żKrŐI6Tă›/řPőüI„ŽŮŒ{6WŔŕĆ#ÇŽ:7Ԋuxügą~s<.­k‘˘gńpÖ'r'éač>túşm^‡l4Œ>F“ŘÔV‹ő­8xÂdۺՒ/?‹ż{Ů WëZ¸ź.źmm>Qń"FHÜŞ‘`W…XňšëHČâźZô|ۃ‡ýd+Ú:ę菢çł7ăŔPZEJŒ˘˜Í‰ô!§ ŐŞ $¸Ő‘­R a‹=°2fž/M3›ÜAŔó$ʀG`äŃůtCŹ^E"$ĎŔĐÍY­1ÖqŮjI!s*öčD˝{zĂ÷3ŸůŒř´Ä-Xh2~Z͍h}ç폐Ck”]aCé˝ÄâŰÎłgĎâˇűˇĹroä|Z~Č¡’Ës'–ČB˙˙.Ű_šśnÝZâŽ0$˘8‰BŮŹ*$C<ŇE¨& QTĂĂMă<`I¤ˆQ U~SϊćW€śs‰ëiä1SI$sd"ô÷Čŕ¸9˝XŐ5U„r'K66 ŢăZJ= ¤OŃąIz᧋—”Ž9Ŕ×AS8˙WŠ3…כâjŞÚéP!H$3ńËÇ~‰oë[3nóŠ?ú#´ľľĺŐ5bt:č™ä ;Öx4AGÁč؅#fK$sB1FKÔt™ŰW"))nI–_˙Ć7qôč1ÜsĎ]â{u]=ÖWřŃ=0Žd"މąÄu*˝ŞhÄTVWcŒz„+Š÷óŽ´ŻŮގ˝ů~œ=~˜Äę}N% řH ˆĆÁBŕJdrCĂ1œzőaQŐv8|Č$#$˘yH¨I˘mËý´Œ IETĘytŞl*)< 4×ĐL—c‘g4Ńŕ†˜NűšZfCÓľź Wšn…Ű—ÚG×Ë÷Ѝ†¤CxĚə9148„ˆ˝'œąl݆OL`÷ž˝¸pî,ý˝†ŇßÄSOˇ>!BňÁŇé LFŠ‘GKÉ%Už/ƒƒRŢÚ6\ł­kQźÔÄŠý݊$éáĆ#ź•ŐUě?tëڛ qgj ůŠ1úóGŸ¤śTąÖNô “1Í!ě؉ł¸ń†Ýčşx#ýčÜź6”L##‘\1.h^üěŔlŻŠÁ†I ĄCƒ"×uňe$_ˇ ÉŽ^a~N9‡ÚŰw ĎÉCÇq6žîŽ6¨‘d~z~œˆöŔÓš 1ˇ‚úŚzԒ^SQé@[]€Ä(Ejî@ëîÇ˙ÇCȒ( 5`8Ջh‰†J??äŔľkł":p˜ÄŽśZÍ5&lĺĺ˛řHX ŇL }6‘Ŕužžą3‘ş‹D7=ŻěÝUMëŤH ™WÜ)2Ô/Ö°Dt!aą‰âKVˆ0Š9{ƒilŚč8nEČ-bŰ$Ż× ›Ą VnZVE¸Š$ů6F^@śWÜ!ÁÂçÝbń‰Ă 9?–eĎ9ŹPxąŇv–W SVŢBžçő=öŢőŽw !ŒĹ1>&çěâuě™ĹÇăýy=Ű^^΢˙Śßď'´‰ž Eî #43šŽŠ¤úœ‡Œ;h8,‘Ď…ť\2Ů´đ”ŇéÄ ­D†Ă/ýdŁ ŃŽş&čď”5CUtä°$輿C2Í#QňJĂűVôßđšŇ䨏˘Ÿt“pĽ^ućߏ.—G\ŰŹđ ŁklŠ’|L‡Nę9U ‰¤$ć-žŒL5Mk*Ľř*)Ës+ŤHqK"))nI–żńëĚűžśŁC|nŤŽŸé­› SĺÖmKßŃŢNšQ Ôť]]m$Ű­˝éfjdŽDQ]U‰EÁs‚UTߌ&@&oˆ/î 52¨<Š›ÖA+AÂZ,šžI™dJŒţ¨‘Č yáöşŒĺ)j¤$Š1‘$Œ*˙)Ş$銳ěęş]”škČŢbć°â††Űí2’>ŤFÐ˕ő•˘ŃŘŢށ‰ŃAÄ&ĂŘś}Ν=-ÄH.Ăéłç…A2•!Š<Ďá™N§kńĘHeXŻö Ą­?žż˝ţ{čٟF:Ťcç5;ąvÝzáů7>>Űn­[ş–A(T!Ú^[ˇm‡çdĎ~3i?Ÿ×ƒ;w ąłeÍ1 ‹nHŽ>}q?Ξ@wűëđńj]ŞCpŤşf#.9ŽšĆ:œHÔ@ŤŤCr0…“űᱏĂך×U¤ű?ëÓŕhkGöě(HĺčKęđ#€t4†#pęIřÇ8äчѠú5Ż…'‡NbžÚD‚š÷fÜXŰ c(’Eߨ‚h́şN §z44śM•×!D*ďŻj„˛׀SĹxÖHđîá<["|ŃňւđŘbĂoƒ$Űj"dŁć&„.ö0 "ĄźáŠÄ#%Ś„­‘P=Ľž\ěGä9˝ śłFNô)Ó=28˜ŐIŔ"‹P"d0˘|Ȃ{W‰F0‰^źŢťŹ6ocy]qC›Đó6vxîě9ŒŒŽäźĂ8\ążż?÷;>n@“€Éëřxœŕžšš狊[çââb„ŔЧȝłCC1<‰E'&I˙¸ń>rĂÁvŢô8f/Î)d.Ą0#ěSt(đuɢ'ŤWItSH(ЅŚ Ż.Í!‚@K”SžcâOÇůśxÔLöVé}Š:ŕĚşH?s-¸óC˛z÷SsK3čb ;ýô~7DhęŠ.é'‘kxlçşűÄś~Ÿí{ľ$Z˝zć<ŞCA„‚ąM†î÷á1Q˙a1,<•â–¤lŒŕyÎ~(›ëIšČ§E˛¤ůĆ çIĚ)sŮěěnŻB1_/_ĐŚľ›Dţ.‘07m†Š<+Y‘ˇÄĺý˙Ů;9Žúţgf{/ˇ×űN˝Z’{ŻŘ¸bÓM1„–„@B’€@zď`LąąqˇeY˛Őťt§ë˝lďť3˙ßďÍîéNő$K˛„ç+ŻoËěĚۡłďÍďó~EŻäeą*° Čf ZYéqž§ÓYä3ˇrşŚIz%1Iž{N°s!É:7Axi)˛řěüĎĚá‰fE7:M&QÖ˝žŒäHxRxĚëX€d2!ŒIžx̒Aç°YOf…—Íć…É#+/-?‹MRŸ‰ŒŢDSĄe,čĄ~wĐs|3” UEŰŤEČ!ŃŔ!°Ć!Dĺ\ŐGÉÉQ΅cČĐš$ĎX/.¨u`Ä%ĂcąBžLaRv ůڋžĂcť&iYƒˇş˘ěۍöö:lˇUŁ+Ž BsąÇĚ.Hf'ö8%R%e ŞOŽ@ůÓ˙ŔŻ&ňŐ`Wŀ3 €D– 4č–Öd¤ŇöôĐw(hpk°Ę*ýÎUč—š?ű’D+U?,{ň(­źt—˝ł˛4Ć&i|͖ɛ5=ד&$rFečqF÷ĎŇ˝AKŢąúśj)DΤW+”t¸•$¸c‚Ž2´={rąĎC­mŸŕmŞÔh9<“C+öüäń˝ą6iĽ"ě%ĚĆ0/ńyJů ůqTq;Ę^\ ś†ń>ůýŰśmĘăő`*<5ŚÍž` Î8ď§ Đx? şî¸ăŽăœR)ݖ$ pá) źśd䵂ȡUŻ*ŠpNÝ3ż‘ýYUÔ^Ľ€qa€ÉÂëKďëœř^ZÔa FăŠfŇ+PŠ„[ Sî-   ‡.â^ĘüŐr˜¤H-PTÄ8­ŇąU[4żf “°Ůƒsó06d˜.ň+d„—řŃźţ,ŤXXc-higCuHOöÍă]çĚkŹCŽŢĎ ŹźŘÉׁľńg <8:ŽĆö3–ş Í]šTĘ cL3dhŽ2ŕ–ĄsZCŃ´XYء]%ŢP5ź•z9sžD°ĐrśpvýTÖŸőČç=^̜˜ž.ŘÍ&ľ;G€‹Ťre!łDËb5‰ÜRěą%[Íd€Đ¤Uԓ+tQäđĚň9NćIeQ(­úO'ƒ?_¤•óɔ!—BŤŸ6¤2ş'eáÉQ„T„*Čœ‰äł™$fiÝĐâ D…Ť4Z„›˘ţÉçOC_đ.*ˆI…“*&".x+2xô@‹ą\Fl'ҙ§ýGô1ƒ(ö)'tgĹ9˛`1pb1bU%äńÇȲǏ9eď‘r8‡3r>ŻkŽšFxeqŘty?žXNVĎۖĂy ^ąbŢôŚ7gŃCĎE&BŮ# ˛€[Âťďőiz[ý{%÷ćTT1ҒŠŘƒŠ}ěh'̲8”‘CFă⚢đ°Î[ 4IGÂ=Œ>g^÷bf_‰_;ܢĎU,Đ8Ź0 d0hÇ5ąˇ–¤ç¨L%GäˆNN<~ˆ_ťžK×0,S鯂#˝6ÍŚŮ&{r—ŐNđËĐšŤíűNß_ÖъsEbńĽ4ć2dhn2ŕ–Ąs^|Qœ O uĺĹíŢ/ŕ–ƒŔP“Ď;ýФÎŤ¨pŇjˇŞ‰°ˆŠdŃĚٍQ矼Ţ( 3ů\^ŘP"™hŠB!Ü>Î/—÷vťţ4›őPKĚf‹°Řtď.ŠĘĄ˜ćžtŽž[|ąŚĂ Şlp˛¤Rń-aťD‰xt‹ y2N-œOŸÝLX†ú‡ŰÁÇĚ ă/žˆÓ}20łyTÜp“aŽ&ôÎý˘žtĎ- ŻŚĆrěN`Ľ}ŹT †Ş`K%‘I§ĹŞ-{ 0HM$Ó°‰ d!˜¨]żÇHkčźQ~*†D˙\) G`D@~I ŠÖ˘łB‰a,Ĺkáŕ†ŕ\ڊľ žJ0ű9Ax„Ŕ,č´owÖÄĆŹ‹}žGť›8ˆú†6ěv4!륰řz_ŞL"˙8…]¸¤CCç¨.ťŠĽÍ¨č—ĐLű˜YŁý'ŕ–“=ą çž؅$ý1{hiĽp¸˘4Rě1ŚrÎ,úÝ ¸EiŒm‘JTÉI÷VŇkReDRhöäŕJô˜ĆŻ4AąT.M&/ÂËE/.JR<2ńyyüĺńœƒ(żČUepĹŻs.,kË9śLńŸçqĽżż_Üç÷đëűö폖ąŘää¤3|1Dă÷pŽÉB)'ďý×=ŔţčŇA'óç~…L wź¸'éšżtĎ­TřDĎq5ĘIëš2cQ ú%•ýÝô,1yę3÷#ďŸ!˘XÄ)ĺ-ÓôpGIĄ>'`(ćGöf㼌Š \GmŠî=F >Ś/é‰ě•rĹKzŽçÖ\&|¢'† ͒ŘÇž^"œËćčwšE]]FFFE…Î֖á…nčü×âöfœ‹vƒ>łá\Őé­oČĐK—1*:ç%Œ"#÷‰Ęv,bA˜Hć`ĎŤbôwXäČ`ˆŚ °šXك gnUlSé'%V˝yźhžFˆAsWŠ‹zkf;ŸE`ĺ­°RűSě⢟V‰`/†7–Ą?/)~hMŐôĂ(˘ŘY„ÉëD46‰\ŔNŔd‚Žd† pqhôŔŔ8–ŻŞ†…ŔAźč§ż1r4¤ŃŘŚZˆ§âŘžůE´×Ö#2ĹÁ",éIż vŽŞ OŠ"ţqŮ}nÔű ظ—'ŞüÔÔ!P–—iÁBĂŢ!+깍_fÎą'<Ş€$t/J…a?ĺçe›¤öŞHÄčNN.ΚEďĽÇJ˜Î& Š‘řŇGŇNÉ{ŤO'öçq›Œ‰Á°\&™ŢÇB2WŒ„îé%ĺÓ°KĽRŒeq5ÄLZ´“A­ěĹUGäĹň˰‹seÍ4 ĘaŠĺÄđ<.óöĺäÖ ˛ÖŻ_/Ş$ňţhąGCłÎÎN‘{ţüůčëëaŒź?†kŹrháĚöň1Xě5ľiĎ.}ťé׾’Ç–ŇÉŢŇźZTݛ•únpp?Ľ“B•_@’ťąüF‡&Ŝ§–źâ¤éţÖ÷ •V?ôă•B…ë–$ňQŠöŃX<ł˝V›E/´"ib[MŐçyÓ¤źđ4ăď PĚŔĄ“‘V*Np4qD^źä*Đ,NŸŔż˝s!„ĄÓ#ĺœ]¤TEέ"ň0dČĐÜdŔ-Cçź2p–\yóŹç˘éň@Ÿ=ň ™—ghąĺDitQfž ™,ÝW˛ <ôóĎâŞ{? “‹ŒCsS™q,tŃç"Đľ}čE,žřVH´"˜Ýˇ.?’ľŇD&ëá"d# ť2÷•‘c]pąaĂ`‹ -Î SÎűÂ*Ż™Ť3ĂdN^t,‚Œb’Ďç„'‡ądčťáż=Ý˝âx ć/ś‹Ëĺ9śFG&QIŕ‹“Ž2Đâ. íÇďs!—/"žHܚ{_DŁŐ‡[œť˘Ą † ˝’6Áë$ĐRˆcba“9úɛhœaĎĘEK›Źô˘śĘ‡Í[zĐž¸{3&ŔÉäÁ‘_fř,[.ĄÓľ{k/€29Kq+ŰÇbfł ‰,bË1iŻŽ8&EŁaf‚B˝Ł&´Ö1żFĹžA`_żkŻźZ„ýHĽDížĆ:ý ™uŒ‘Łd=ášE‚đŽĘŤʞnš–áIN…04†eĹß é]ôH˘=’ŚMo,•$ľä8 Li 8<"é~B,6čí˛—ĆˇU‹—ĎjŻ˝š×-jÇÓĹ$a[ôĘąš š,ĆE(zŚäš+!;5!Ůzây . BťsĚWœ6˜É°NŹŞőşD“Żżň2‚falŢź™€¤ ~żGě#đŠĎT˝xĄ‹looC.Ěš%5¤Ć†‘ĽďŢ3Ł˝×]w-ć͛‡ ›?ŮyS÷$ˆŇł—%ňLžyižző­ˇÎęßËÖ šŔŢŕPo)T_ĄžąÓ÷b}ÇyŠlŢŔ† O .@SS“|9_Č Ż5­‡*“|4îx=qżŞJĎťÉĹX˖-ƒ!CgCĺpĢvîzn2tŽÉ€[†Îi˝űŠyÂŤé\{E&Ǐx>÷í‚#Pę@$M†œŠ‹Ţó tÔ-ĆŘ×˙‰‹°ćĆWcŐk1´ţ׸úŻE<śڇž ßč~xçľ­@ô×_‚Ňۛςáą4šÔ”Ďüa5^Ş8Ń9—ľ.‡­”ŏůyŸ){ 0X;ՕI6ÜT•Ěb_ę úŕ&cmÇÎ}ˆĹ⨨¨,•ŠwŠmŹÁ8y{OO7âɔđLŕ°Mő‰uý‰É(Í\}ěԀ_ύÓ…jĺôsü×=ˇ^{dD-^ŹW@ä •2rŮ ĎĺtL÷QYźm„Á5…+%1<Ą;"šě™5Ź8ώîá!>ŐtX¤ŹĄc‹Ë ږލɉ~rkSőʁ|*ů‚ş7TEH÷b¸ňš Ŕąĺ|ŮË×-ô+\-<œŹ ˜L*<–ŇZš ҅%úe¸pÄQEîÁ˛§Žžź]‚×´ )óçá[¨˙ct@ö…°ÖÉXsyÁœlô[âqA´×fĂÂ[o†g`Iéăęçݓpă3žëȖK:°Ÿ—ƒŽç+q˙+Żco(†`š´‚h¤Ęž?’\j§\ë¤Ň_Ýg‰YœLžó|e§“­ÓsO¸â™ÇížÝ^oţ—/ᜁą„çîÔ=oyŰ ˇéŇ+ŔIn?ěô%Ďl//tüţ$ۄxŠéJF0P C†Ž§;î¸SÜ :׼âŘ^…† :RÜ2tNËKp„Ý…#‘¨đ6jjjÔ_ŕ*X 8t­ŔÉh!‹Đ˝łá&>rĚÔd, _QŽŸg2c‹YCDľ!"űąŹÚą)<őČo‘Hç„ńxÁäÚC1DŤÍ°-žÖę Âą!ü*2‰[Ś2`†c§íl\†yMTí)Uę*çp)Ťœ&-rLYÄߗ"=ᰂt*'Œ†şəš˜űgcĹdâ˛ń2Ü.ݍ6Äa4ƒƒƒ˘*"[\B›Vţ~ląÁ#’KswgXWö>c Ć!B^ŻgşŇ!żĆœł†si”Őp?Ömډƒ{°ú‚•pş=HF&°s÷^˜ŹvŹY˝?ôźęî7ăŔî­Üƒ¸ţʋŃ;‘Âä`’>Ż ăSQhš.şâ:´5ž„˛?ţޡĄ¸&$X´`zú12:Žôƒ0dčxâßšÝáB¨ŞU„¸ÍĹ3ł 'VNFÍG}Ö*Iblŕßf؊ö:hhnšs{ϖ¤cľ×ëƒl[xŢ´—׼—^vŢ´×ăöbْŐÇmŻĂî€!C† N˝šĽôTňEaă2dhn2ŕ–ĄóB FúúűŃŘŘ .p‡zńܖ=hŹŠŔä؇Ĺ\~  Ó_7Îś*şd'łHňTXáąĘ(Đę}_"O+É~lÝš íÖE˜F8Ŕ>˙řm‚6utßžb˘˛^2ć4w„ Z‹ä%˜y bĄ śXĺŐđ2č*Wۚ™ă弈!UQ€@S‘ŞC^z,‹¤˙ÉTšŽ‘'€Un‚G^2 +‚!źđÂFř}ndÇðZ-ž@[k#vďé$¸Ľ—ŘžŤ¸r+“ÉÂăq´ó‹ęceńgM&’hnn€ŤŹúĆ&ʆu5dÚË&Ô×Ő FߓĹîĆ6׋/ť mͽƐ$0guş1ąťV‹;3fN§żŸ§KM-md@ŠÇŕpş֊Üd† Hĺ\PěiČżýbý\YÖŰV“Ä3F{OŁ^9íU /VC'/Ś˝°qă1…›ćÔ5kÖyľ ˝ŹŇËs” z2dh.2ŕ–ĄóB|ąşvÍjLLLˆdş’ن‹.X.Ón…ĹáE$<‰ĘP˛™ đ2Ŕ-7]Oç&ÔU8 :Mpd Řľçt,¨D&eC>ťšÉż?‡×‹'öíE](€•M~ěJ ;2ŽX:ƒ-{şqšŐ ­ !O`Ëć5áĽ\^éaA°ˆ3‰JT%éŢSł‡€˘€Mzł—tQW˛98W 'çŁ&SYÝ[ :Ť |^ńş*œ¤uxdH„ŚÓc"'N>_^năă˘Ěv†áŰ)&ţäĎĂa3ş˙îťď:b[ŤÓƒE ůśŕГm-GÝďľ×\=}˙–ŻÁ™Öľ7ÜxÔçUŁbĄˆ˝_7n|ATĎăœ3ńX\äezâɧ°bů2lÝś+W,Go_Ň 9× ‡ńr8oQŐCÖxŒhkmĹO<‰śś6a$˛÷csK3ÂSS"Išđ`˛;DUї˘ÎÎ.ŒOŒ `ě§‚˛ř˜U••Řźy /Y, üđđˆ(Áí[˛x1{ěqÔÔֈqƒĂŰx„óúqűęJšsNˇ¸ŞZOO-Â4Š$ďœŸ=N9źü|$A:“ŕĺʕعkŞŤŞ1NcŐŕją\…m}ü>×3ěxbró;:„GÓŽ]ťĹ÷cľYEńŽyóp˛bÞżÇ`0(ćŘT:…šę+‚čéî9†bÔ×\ů7Aă3÷ëË Ž¸Gč{vš]âć„óiš3űúŃD :GĘIň :žžńŻăŻ>ń‰cž.*öő‹Äń† ˝œâ„ňęID,2ôJ—ˇ ŞŤÓ[Źęęęé×ĺPzy„ŰŰ<¨*(°xŹPŹ ôŒB=đ†ó*ć_p%ěvöwn‡]–Î§ń–k.ÄP,I'†Š€áƒC°“YEŰyćyŕSLP E2@spœg:<ÜĽJW9)‘z†§V9OTů9MĽ#ĂOM"kłČ™–ÎŚ|áźPNť™LŰvě%¨eGGÇ|j80؇ÁĄ>ŒŒŒž$ăŘ* {jM†”qŇ`٘ä :%18ލ¨Ŕ…!˙ÖřŚRIüéŃÇÄk;věżÁąń11ô÷÷ č"XĹ@‰a ßAwwBôžŽŽƒ'Ȱ,J Éfľ˝d¸UKpŠáĂ+ľŤKxě456ˆtn{š28/CťĄÁ!XçwL‡Şĺň9ěۡżť÷ě°Š`\*™:cp+OđlrrJÜxŹr:œ˘Oš3aĽ>ćţfđW,pcŔž ŁëŕA,\°@|7ěĽĚ!Ő;wîPá!/P0|Ş­Š…— C°nPü=ščp(9ƒ(+/5œ‹zzzE.3ˇ3—Í@ CCØ"Çc0ˇ“?ËË-î_†kěm{ ł“` ]L3Ătž2đcăśśV2t"ĺJ9ËހĺqŁ|ÝSöd/ßçq†Ż?yŹEkk‹ŹÇżoýóĎăÂľkźî¤1ʉ7CîciĎŢ˝běä(…ŢŢ>ěůźžyÍkč•#˝Ö,W ΐ!Cs“ˇ :Mr9˜‹ü“R…k’ÓŽ`aĽÝăi cB1Ÿ„‚Vv#AX1Kö ĂC)\,;ŕReě% U˛ÁbVP[aEŃ>÷Őň™PŞĄĄ Îq˜-Vd˘ăŞ&$ÉhrÚlČӅ{9p8Rl@ą'ŔA2˛řBŠ \6&g†ëÍY\\M+ťQsţ,Ž–Ć“p…ŤLŚ@JO>ů4P|ŃX)źŘŕă MŤŐLFWF|ţr…2NJ/ÉÚtő˜“÷ Fö†8*CAC†Î'­Xą\ü]śtŠ0ŢŘ{ń–›ožŢŹrŽ#~ ¸ććŚéó}ń˘Eâ=˗-ăÇE^8k˙źMq6›ý„má÷KIĚy˙3C†YěÉtŰ­ˇŠűüű/‡Šń{rÜYW'Ţwŕ@':ću ŚŚZ|ŢćĆn˜Î383gÓKщÚŰX2\ˋ3ĂęŞil˝ä’‹§ßĎâąő˘‹.Űň_Ý+J@‰ű~>Á:ţËű)ďA“…ž“‹/ş¨Ô/šČYČŻéů™ŸńDíĺďućw[^đŕď—s–Ÿ+[–ĎěÂÂÜúWżżté’YáŠüžĂ=‘ :‘řZ‡syzý>D#qqnΙyGŮ32M`š˘ńy e¸§ßb‚@+i>‡††ĐŘĐ(ŠŃˆJŠtNňőż6>1ĄCxچ˙ňC+>Ď˝ŻxOj†ÝŽ'Ö=÷œř­ó5˜%ŘťňD0ÍПŸ8‹o4OăÜ ľ./Œ2tŽČ¸0t^ˆW°8TŚž.¸yĹlrbńdÍM ÓŰđł÷eĚ=$ŃÜŁTáa¤ĺ‹˜çu"žMÂáś`4? ĹmCw˘ˆÉTŽś•°{°v2fd—‰Š4”˘Œ-JiZń7¤1•Táŕź]~ęNŃ(ă°!6–Ú[°}ÝF\äÓ°ÓçG"™EGGąÖUW]… 6ˆ˛đ ˇř/_œńĹÜƍOÉ(ä‹D6Œ,f“ÁąŮĚv‹(׮хĂ+ A˝a¤S)ᅍDO¤D8˘Č Ćýc*/ˆbQORĎĄ§"ö<™˜˜ Šebl" ›Ešś2Š$ěN7ľ5+Â]šr" ODS°x+r[ŃŐ7 ŸŰE‹âL녍¨MČR›ŘŘă ďX<ŤŽź† H3Ë3Ľ˛ĂLńpřűfžçXżŁöövĚE<ö ‰ c6&/źpíŰđo_˙k:ęqš] Ę*‡Í•ˇ9ŔăDí-÷ŃŃB÷Ę}9ł=eŤŁő}šŸ7hgž‡U~ŰŃö1×öÎlwšíĺżghJ{Y‡Żgł†ţ|4<<ŹßĄÓ}ttô¨Ű0cĎOž†X¸pöíŰ'ź`9,Öl.‘š•ćÜĄeŘ&XĆŢ^|ŸC”WŻ^-ŢĂç._gůhQŃ$Žit VI\Ąűœ‹”9$’ˇçt¸}ĺJŻýkä4dhŽ2FKCç…8…/*†Äă`Їí[ŸĆĐČ ŮŹvz@-­ÜŻ\}!\+ζԜŠ\4+VM9™<|";äY–śa÷TÚîńp5’΢„QąjŸ‚€ÇŠÚj3Üv{REž-ŮJ?QMBö$JĘĎ\AyěąÇ„UW_UÂŻÇLpćâ0ŠiěŢ˝[lĂĆŇoű[aD=řŕƒĽ<,Oˆ×řěđ}νŞ08JŮ l) ß$Xh5ŢDÇ*ŔĘP%“)şpĚęžYě)Ŕ'éxb*§ĂfsyÝk€C%E’áS÷žH•BpŽĽáĄAx+jO' pľ.›{¨Ÿ8oOˆ.67Xj]ź’ k5^$čgÎýQÍ„‚œ 1MŢh†ţź•Jg‰ĹáuťČhŇ=Ťřˇ=:1EçŻ_üĆĘĎq~*[ÉsćLy(q;–¸ă“a?Ź,—ŰQTUŃ֑ńIT˜dqţ%ööy)cÄKio>_Đ˝6Čŕĺ6pűŁą-3v›čîw.¨Áyű$AŸÇM Š’§™JŸU˙nř9}vž˙ěĺ÷=‘÷č‰ÚËFôT8ŠĘŠŔôţ"Ѹh+;đÍé8§K§Ť˝† ŹŘ;"#č1*p:Uŕ\¸đč‹X ¤fŞœFCςYŻ-^źxÖcöĚbyÜG拭=CaԆÎ}i"0ąh$”7dč$dŔ-Cç…8Ń1{ŚÔԔ/´ľˇAĽŐ|•Œ i[ľr…4ŞZÄËĄÔh ćl˛EF!™ƒŮĘŤwwŇEń\€Ď%•’Čđ>żĆŮ$‰dďPiÚ*h˘Â{|A5!3’…ÉEx'QD>V€Š8w¸tˆ˘‡&•Q‘ =АýĆaĺ0¤˛wŔáîĹ/%÷–ćT۝ě‰ĹކvlxŇ.dŔ™Íź ‡ŕda'%OŠ•KrȒA—ŁŢÄŢlÔĆlވSő~f­ ćw…يUłň9Z‰ő 2¤_xŽ\ąlúľož/‡VŻYsÔ獄ň†N$†DŁ„z"CôŰ3!FŕeŒů0GbÂ˒Ĺ^źC0†\>ú 4֝ýœ/ŁăSzuÜąIx\iáŘӁĎő…íÍ8Ř3@đ(.ÂôX<~řźnńwɂśłî͍'ĐÓ?„ ß+@÷)a\8ĂO}Č}Z_S)ŞÇş Öń6“‘(46íÜŰ)€ޞďŒ pĂ0Ěá°ŃXŞc‡a;CˇË)žÇŚúSKzÍ@(ÉŠv1ôä6%čXÜŽć†ZŒŒMˆśr› ŽĐ÷°réüičyś5×öś6Ö (hČĐ\Ľ˘pĚ×"‘ˆĚěšĹŢTEŔU bPACgRzľDZ4Á™_\0dčĎEÜ2t^čî×Ü9ű IFcs3Î%eŔLŒŞȢ˘ŸlŐ˝ˇ9p"u ş¨‰BxdVDŇu‰§Ż$ ;˝'GŠđxb˙ĹńŇ 4MâŁKÂ#j|rrökG$ ?úk'}LMżÉŠ ůbžnüčójEQžQx1˜č5'(“SQ2˘ @qX {4p"yÎ7ĂűPč>˛bA…ŮręĂÖÉť&łel2tž‹ßˇ^K@'üœ…`ŠÍbFĺœGŸWu˜˝Čd^ždś~ŸƒĂă"UŽĆ§Ý.ÚÎŔ‘–Ś:atŠ"Ägc0äŚAƒ= Î6ܲѹkŤCâ¸Ü.żĎ#žc8ŀˆ˝ă˘ŢĘ0”a€ěÝJ 2-dÄvôđřÇŻ5ÔUĐџă…ÁFţ.ěđsn—ă%…+ńwŚý˛wŹđN h N‰q—á÷3§Ś˛“áŞ*ƒ"źęĺŇ\Űk6—ś†NNzŽĐŁ_ď$’I”WŐD.._J ç ¸ečLJ+˙“^žE{C†ÎGW† 12YdT­HĹr°ť JĺŮK‰ŔŒĂ‰AM:G÷íPSYXE˜œ&‘¨KSó(ćyň’üőœTˇÔ8ĄlŮő%xn„N[RHލŚWjÎaô9Eˆ"ÝĎds´lČćU‘7jl|Šž×$Ř%áPî%ËzBčtVŻŕ¨jĹY ™OVl šY ˝’ôşŐÖTsQ\ůŻ•ÖąT[őŇŞ1žnqč$ßNF źXvx41dœ)ö^ ř˝Â 壘˝›ŞÍ>ŢĚź•ţé{ĺ0֗S'Ó^C†Ž'ú3ĽIłĂžř:Ą Ž+C!qÝÁů9 R׆Ο |C†NVÜ2t΋]Áď|Íëpýu×ŕŠ+.ÇŤV"<5%’h[lvÔT…ĢÚËV¸NŇ/„˛YjDŚ_E‚1Ĺ4­ž[$äR9v_Zj,-GŔĘ$‰PÄB&'sŞřËĎÉf ůDöĄôâPBŔ,r,Íí–C ψć:Ď2 3ÉÂۊ™˘˜JPJšˇ4ŮLźŤ ň椳źÚn…™=GĚ‚_i¨" S•ŔŠŞžHž=!ʕĐNE™LvŁŁcŢqĘ'>JŃRÉ<Á*¸œ+'l& ‡ÓĽ?ďńŠü_ÉxEúkˇ˜ĹwœŁm˛ů‚¨@f>C `wí؁4C5ŐU˘ocąĚV'ÚZ›`ȐĄ?o,<3dČБzç;߅%K–N/虭t‘=´pćńxD"yVšD}˝ž`;ˆ6dčtKd.ĄŤLU3Â šŤ ¸ečœ_|üëç˙˖.ÁHКMOo/ʊ„Ξ,ýăƒ"Šö%—^ˇóě_t0lqť]đ57BÍÇMĺKçaˇĘpŘbą'Ä,Ľ™ÔŘ‚'ŻG“•YC>S„â‘„§’ĆEú؃KQQ I1;Ěđ+Ś“&Oň&|sK’Ë%ä9Z>Ÿ€ĘJ+ďœŘ$\ů%ń™4š\šĂ”\ţ:Kp0™Hˆ|5eXÇ ę9™ş$z‚k§ÓyÜךjăčX 5Ř˝k7$[?Lj—šř8${A˛-7LeP_„ÍjĆÄTj.‹¨pă@÷(ZÎ`Čl,ĄJ‘0ľłĄž`×Nh—ˇ Wü;:ŁŕېĄsD<×H’a :śřZă†n€!Cçśô„ňĆĚmČĐÜeŔ-Cçź8_Ă#[jŠj`KK Á#3ń4ŤÂĹܤź<.⠔‚ÁţӗE5žÓÚWŻúýž:śřbŢa?łŤú‡ý„Fƒ,ÚaŢlœB”Áć\[ZQ|ě•55Oڜ\ž ‘8†\SH§ł˘’"G„"– ňBĄXę[ vťý¤^m üÇÍQS][‹şĆ&zű]wé őéy•Œ ąĄA´arbądm-"ĚŇBűd3“Iʕg6ôń‚ŐŤK•#!ň ľĎkGąP€!CÇŸ“|>'łäů*—Ë5íIaȐ!C†  îkűšˆÓÉkĽ´ň† š› ¸ečœ'â=ÜĆçÓóĆT۝¨ŽŹŔË-ŽUUŠç9ÝÓ#œ2č9ĐaHTW[ƒß=ôG$“)1!žž6Hlư'Žs<1jËč|| >ľÓš86>‰Űn˝fÓéőčK$“xţßŔíő‰đOÎĄ4Kpː!C† 2dčĎDĺ|[Ü2dhî2ŕ–ĄóB‹/šjkjÄcΚ¥5ě…ĂŢP őu˘çLJ%â¸ô’‹NgĐüŞfdsČ(bᒥ°˜d„#1œ q2ňœŚ Âç†bś!Hë›Ü‰mŘKŤŞŞf‹ şBQ‰ńł=iäő7ŢH)/˜L&.%^ŸÁŔœŰŃP_:j‹&™ĐP]˘&áŠË.G^°r9Üţ ˛É8,ԟ‰XKdąG’Çí„-ŕA¨˛R´ké˛ĺˆ„§Ęć1:<„tACsCNV ˘|v=rô­Mľ´oŕŠË/E^•ĐŇ֎B!Ë/ťŠÉ, “Mxpiźm'.äö‡ŕvÚiť—–4Ť#e2Ůă–ń^{á…‹’0)úú‡pÉĹk‘¤óéŠŤŽ‚Űĺ!]éöx'XÖÔXOýć˘sӊƒÝݸŕ‚Uh$hgĽĎŔE΄îşç$ ˘NEâ˘-ˇ† 2dȐ!C†ţ\d@-C†NVÜ2t^čĆf{ZqĹ,‹ĂĺóßĐ÷ 8 CâĆb¨u4+$¨şíŞŞkÄíĽh^GÇ1_[¸hQ)—ű‘Ąy‹Î?â9L/Uí/!ůó˛+qşÄŢděýw"š\NńˇĽĺČďsš•ĺőĚNN?Ż˝­ô~Τę,ŹÁ :ߝOFByC† 2dȐ!C† ˝ReŔ-C†Î’ ŮşúG‘O'PUS ”Ş˙qrt•;“A>—‡ĂéÄÄä$ZjŃ=8­˜^a‘h .§Š"ŁPPa2›: `ëxę>Ř-ŽĂY\Ĺ0‰đĆ9ŐNĆS͐!C† 2dȐĄ3%Ł€‘!Cç‡NVmC† ]41ŚSIxdő÷Đý4†‡‘Îdq&ĹÉÍóůâ‰8†GGőJŠÔ—äđĂńą1ńxj*ŒąąqŃM;óŐÔ¸ú˘D#ĐäĆGúäâěšZę÷Ă}ţă)‹\nĹbƒƒHŃwÄâźVeMŒ'’C"ÇäTä˜ű+WĽ›ůţ—*Nś‹F HĆEÁ„l.‡ąń 2dȐ!C† 2tśdT.7tŽÉđÜ2dč,Édą‹$ĺŹĆĆĆŇßœ ůü44ĚN8ţr' onn• ľÎ´bąř Ęł‡›ÝéFWç8.\€'ž|Á`š|éx —­Âđ`? Ů4$‹Ф˘:Dww29r!…œdC}U{lv'"S㘿hë_ZČ)k``™lét uUJb|j ˇžęz2dȐ!C† :˝:UÖ˙d€-Cçš ¸ečœ×`_śîîD{k#2Š4ŇšÜN+˛dŕU M¨ŽŹž?šzóŃřm1›xš=‚ôĂjg.÷#[>Áęˆ6#çŇáÍp:/9'ÓĚ#Ÿj;Ž&M'Ó6im8š8_V:ă?nBůŹ|Q †GĆ„ôy\Her@EAżW@.łĽN— ‰x”ƒK‘JeQYB6Ą"/Ň㪪ŤQÁŰg2hjXA_ŕ驚čt:ŕöZQČgQQY _HFhj† 2dȐ!C†NŻřr“Sˆ:RÜ/ŕ2t.ÉřĽ:çełŰ!iE„ĂQ(’ĹdƒŮlE$•â8”Žá–ůešxâ™<†§ČÄČçó˘ęá锢˜ńşě¨ő9Ž;‰đń9”._ȟ^ĐVšŘv,ó 7çP9ť, §˝fł‡]|ß'3Ąňś\]óxŞŹ<ôzEččŰĚLŘĎyÉTXĹţě1§ăŠŠgJó:ŽLüĎĐÍH(očx*‹˜œšBE0ˆń‰ TU*Ž =ÇŠrŔ Ąśśö˜űă°]ŽĘj\Ô:ÝâĘł-ÍÍÓ矟źeRŽ\ (/ŚpîFĂČ2dČЙ$ŞÂUW]…M›6‰g´łpÍĺ´Kp˜eŰ4¸\g>]ČɈÇÚÖÖV,X°ĂŠ< :WdŔ-C缂Ą*ÜüޏxžŁăÔŤđNU ąX ?ůĆ˙ 259 ˇř[Ăl'ýyićƒéGÚĄ§f=6›Í¸ůľoÄňĺËp,•/ţGÇ'đšGw!?fRpsŤ­5•°˜üę‰ç1tđ<6ŢřÚťŃ7؋}˝;ĄJ*&†bHĹrh^TM;“OaŹ Á]]ƒŠž>Řr|ŕmo ŁŁIÁG3"¸ldŒ #:ş f›Ex, zň|N˛Ĺ9ľ4ÎEĹ0*ý‘QČ楘%ńź$Ŕ<÷Ť(@Fť‘éf‚Ýî‚ÓہĘP…pš™™Žęzî2tΉ˝ úӟáÚkŽAWW‚AŤĘWUWášçÖăox=ÖŃ_•ŁŇ*8Đy`şĘ+kpéßś­Űpß}o‡!C§[5ŐŐزu+VŽX!ĆÔ?>üű6ÔÔÔŔ•ÍćhÁÇ*Ş%'’IDŁQ<؍o¸ž>0dȐĄÓ)‡řZüCúXDćĹ"^*çU ë×~/őŇPťäDĚýĹSárĺkmžćĺŰź  ŇQ2tŽČ€[† ˝D1„‰Ĺ˘xęÁß!™œ[{”a?­”`VE…[„˛eŇ9zżDˆGÇ`l4Ĺűt4V^§Yşć",Yźř¸íP99üÄ$~˛ośB˓S÷,@Ľ/‹m;úđżż|…ţ=¸óšK° ­Łc]4YG1íŽ]}ˆ‡Ř9bƒ'Şb^k#&ÓYźŘӏńސ+CȌFpçM× ąĄa–‡Çá"#p{PéŠA.GŸĚN€‹Ú—#@&+š¨Ę(ӅB:‘"˜E ËŚÂlĽmčő$+nżůtZďKQĚÄââţłHA‘üž+*žL~8F 8î6e,ţ˟…?+_Ŕ=iŚ&>×ńúăLhv;ůƒ¨:ą‚tîwvuÂëő"Î ‘H oFţ]ÔŐՉ߃zöÎdI†`tŠsˇgoŽů˘@Bm]- :Ęfł°Y…×ÔT x …059…p$"śiooóE†ÎM‹ĹceÁ!CgB<˛”=Cyž,ƒ­˛÷ÖY[/iƒÓˇĘ×Â|ÝË}Áýbä#3t.ɀ[†Î íŘš‹ŒŹ¸ĺćWÁjľŠçxba/!qQ{•ÁÄŮ‹Á”ôÁF‚K‘ÄtbĄ1ßĚ+†3fn›ÉdAŒ^ă\aŠlBAŐÄýíĄ@T+­ę€‹'!ţœ'vÖßߘ@09† ‹‚ű˙ř‚á‰jŤ‚",śˇł UM-â;d/–ÉÉIj[ nŸ{wŁš˝ƒŔ\FźˇŽŚgRĎ­{*QŽjÉދ;ˇm…ÍŔŐWœhYĎĐ+Y|ß|ËÍHÓyËŕ* ‹pçD<ŞŞJŘmSbLĺB-͋" ÍŻ1€— ~ÇźyÂÓŤşşZxË2t&”¤s” z”ŠeK—bů˛e0dȐĄ—E%˜S†:e°uÄuůÖŠBŽ“`WÇ}Q;áöÇWn•AßšAaČĐLpËĐyĄo~óŰ jhhŔšŐ`rl/lßGb‹-"h†ĹŔ—ËŞ Ťw~ˇžP5ş`íĽWÂă´áLI„đ0ČĄIŻŢmBČc…Óa’Ëa˘¨Ŕi'M#䢎|qY‚‰&„Š* šŒHśÁ°Q­:‚xQB$žÁd"ąÄIIJSC*’ äÇb؟1ÁâĐ`QސĽýŐŤáHdąŽťƒ#żÜźúň‹aÓě¨$ŕłćŞV蛀•ÍdŠúÓB[6…ÖvŕÁá8ěűÜgeĂ5AP‹¤–&hĹɲLxěOă]Ÿx;~ű˝ß`rt÷ž˙őp¸mŘľy–^¸ůlűvtaéęĽX÷äf„Ç&pű›n†ÉfŐçbvk“J8I1e˝ĆŽ%Ő*óđú|€bF<F2™‚‰ÎŤx,Jߣ tîMĹň9‘ËŃŢ֌ţáQř<‚AœiqqŮd…#›ÁčČš[ZKgaČĐńÄ9ęüt^ó UĚzÇWÖM7ŢHŘĽoS G^3†  Ő–ëÍđ 0dČĐË)žě,{*̈́Z§ˇNaÓSôÚҎýč%Ś › ¸¤ť2dčlˀ[†Î Ý{ď›p˙ýŕ‚U+Ĺăóő5•đšŹbEĹďóÂćöĂjV0:ÔOƙUľŐ˜šŠŔĺöŔf9ó§z•Y†ßŠÁíP`sZ ěQLe‘N鬄&‹ŠL&K°I†×B1Ť\ž'‡ś™,Ăf3qĘ+Xív´lpŞE8ÖÎó†%5ŠŞć†Ć ţcű€Żžf-‚.;6?ˇSRŠçѲz9ägžÄmK[đü–­°ŔˆÇѰé[ PŸv™đ%\huâ'ÝĄŠsjEž@ŸŠ…¤qréLf‚!?voڍKŽ\C_› ™s…Ř[śr1ő™}]đšűî^&í ÚŞŤB>U„Ăkßsžú#“Hvœ´8_B[këq'áyó:p*Z¸gMËWŹ<ęóFByC§Ce°5SŘ2dȐ!CŻXI˜[ŹcFRœ3pK;™—OI3Ă :—dŔ-Cç…V_°JÜĘjjj:涍 őÓ÷[šqÖÔćdÇ"ăŽj hކ4ą fâoöE Œ§`éFŕŒI&PC€ÎĘĘ歂=›Âęš$ş÷ö!––PŠĹ1†€Z!Ť ťi&9a“s¨¨ô˘ă§ŃŐyć?vŽ˘gî@+V-D‹œÂŕ`“˛‚ŰşEî/wnć6zöEčqV§…Žyhoʟó$Ća„Ně+1ŘĘÓEů\wÝ{'duґ’ŢÂüy'˘ŸJÂA@°ś.§ŐNoł˘†Vď5äčŠÂCJ‘‘|Ţć°"{Šł1 2tvŞ<ŞŽU¨â\•ŃŢ3ŤSmŻ1Ö2dčôiśwŇ1Ǘ“vN"â$78ópŤ,cŹ5tŽÉ€[† &iEh"Pô$ŹJŔËÄ%+—.Aęţ_@!ˆŐŕPPăU‘'rľuČ܅ŕęŐPľ*8mŁČdsŘA`+_ÔĐᓐ.œÄ|Iŕ*‰ arÁ]DĐdÇĽá÷żzŤoZĺÍŐxv_?ýđ 0îFŹj) kŽGöáŸAklƒ4˛U-~dŹíÔÖmˆôNÁbvÁU[ƒ÷Ýq ݟă!1ŕŇŕSe [™X{~ü 6 ™ą/U…ˆŁoňî=pĘiójفľž^\˝Â…ŚË—ÓkEŃŤ<s¨ŁôŇrćršcćh;WľióŹZšÂ¸€0ô’ĹPŕ÷ż˙=~őË_Єܧő ÷%HV\zÉĽ¸ďď9Ëç:ˇw §żýŐý¸îş+đŕÏáŞ+/Ćƍ۱rĺěŢ˝mčíDeuâą8řÁ÷ŕsŸ˙üó?} űاńo_ř'üÇ˙÷źöN<ůÄÓxŐÍ×áÇ?ú%^˙†×ŕ7żţ^÷Ć×ĄŞŽe:Épš˝ë7<Ž'ŸyyŽň Îů(A7Œôň .‡›˛d.…sČâVţ.řž¨+éc^jD˘ąŻ ŞÉŠDƢ’Ź*ś+ç~áçňĹ,R)šT´ÂtÁ žqŐËĽ‹Wăć›^'Ćż™íýýăĎâ—?Aí-ŠB&v‡.ęCťÂEr˜ˆ%!ŠE˜ľ<Ňš,l6'Š´8S(ę99Œ[ă_RŐéöBŇŚO/>œ¨Âaá"sů”>űl`ŕqŻźp5Ţúš›a=Ź˝Ďs˙>űr^řŕ—ňjňń¨O܎Ţô†w˘2TC† ::áuŘ)\Śč-€sýęϸ>5t.ɀ[†Î =÷ÜóŘłw^˙şťEÎĄl6#źyÜ.§x=•NĂa?~ŹZ*EŰ8N!žmŽJ„JdV‘Ý!sŠ)şf÷w,Ft|CS9Źô¤ąčR*–řPŒ XÍX;E÷ž<Ű˝JëR¸ŰÝűĄŚS°Đ5űhđSçjƒŇžŹŽŁëŕ>}Ű;Ń7•Â@tó/Ăö}}0“Ąpɚ…řčűîÂďހî‘–,ĐőŰa“ÝˆŰšáČZ7)™Ý°W)ČYe¸ÉŘŮľ{kç6dŘŹ )=áżb'c•úä…˙ýţOz"M+‘WÍXąĄĂš€42žŔFŽ2NFÔ0ţ´e×<öîšw źMÂBR‹œn_ŐËPž¤8v__?Z[uƒôhĆřd^ˇSŔĹB>§Ws$ŁÍĺt KÎđ#‹`dd ń$őßÂyظuV.]@Żç…aŮÓ;‚ŽyÍ"}°˘9:vžöŃNǞŤŘűÁ~Œ˙ýú7pĺ—ă˙(tě­[6Ăíń‰¤ö/RDQ“´˙5Ť–ÐĄăiűöíxÇ}o/•/×Ę8Ľtá\ ˇ˜F*úkGJ”ΘŢ^š~öŕZ t”ď‹7iłŢÍ˙řŕĺÍ÷Ţ; ¸´bŰ_\‡Ž}{ĐÔÂŘđ vîCo|nFűa•‹›¤ßh1č)šúú ÂhŘľm ćľÖa˝ů˛ůxqă\yéjlŮ´ 7^öďۏ$ý–×?ó,î{ëkąiĂŤrŘśu3†ş1:؇t?ˆbű–-Äć7`blŰ7=‡+-Žéöěދýâ'ôţWĺžä"*w4ř›aĽńÓIyą4"ËRЊ•4ŁVŽrŹŇY¤ńďP•.IyńZ‘śUiŹÍć“H%FQÔrĽ^-‡ĐĎozŠ ‘7^wçt{ˇď9€űţúŸ Ńó(yĆڝng|h¨Ž†‰ÝîýKeaĄ~Éç2PLô^Ť…ŽĄĐÂÍ4F‚ŕ‡ĄÓ€/>‹ţíę`Íd2ÓÓyřińťb_S4.z]v8…wŻ>˜G˘qs ˜ß܄ŢÁaŹß´zDĹ˝wÝr¨îĹţă(h‡úW?ĽAă‚-vÜyűëéyn2dčôiNç 0žÓžËó–2ôdŔ-Cç…~őëűE•ş}tĄÍ^,ťvîÂŕčB^]hťˆNÁăőÓęś3A!ŽdçôUŔc“ąç@/ęëkˆĺ°vÍ8SJŸÉŠĽäň4q4;iMšŚ Ö` lnî~'2–°?S…­šŠ‹`ö !Ó ˘6âEv Š)o;°;ęé˝ýI),Ş„üœ,$$‹˛HŔţôó/ŕÎW]Ľ•v,݋ůWŢG}%â#Řžy'œ6?ž}äq(š|!¤Âi<řÜÜľ˘•@ ĄĹ-říşípz­Čdelˆ„qísn•ÍeYćœ[fQÝĎęłaá䡹sâýˆyëé53/Țž756ĚjEm9Łhq/|÷?pÍ?~˛E/7ŹOÝŰäD'…|u dÔöŠâűö쁿˛áąkŕ4kŘťżmÍuÔÖě.ݍ 800ˆÚJŇÉ \~ Ů4†Ç#°h)üéńÝđŘM¨o=š|^Ü֖ÖfŒOHČ`‹•Ng0<ÖE繌֦:2osěě2ŕ–ĄăŠAĂśmŰ$‘@TÖˇ 宄c˛‹\‰ „V„&[ Z˜!ĺâzň"DX-ę^HŤEłulHŤP¤ńWJ& ăQ¨%`aŸB€°9ĽmyQA‚%ƒJŕܚäżVČ\}Ő$#9܍"ýf^Üô"îzÍkDâ^Đ ˇF†ÇPßPáŃTU ÇD2üŠp^Ż‘Xœ9\pşÜŘľk?-^( .$i(ěiJŸkÁ…HŇo3•L"‘ĚÂOmÓë\ dĎž.ŹX˝ üá4654ž@cc=úzĐÜÚD`l?ÖĐë[wîüöěíĒ% …×ŘĽW\ƒlAžnog×ŢRIřCČOÓ¤ŇâčÍ™lŠśwĐ<Ą”P"}üU÷PeŘπˆa{'‰włççg$°u[ńçˋIGđ?OßA2Ézˆ#Bžu؋Ë/IMˇwמ4ŽŃwĚm¤‰“Cż šœ€ôEťľVŽú lŘ׍LB…Íl^v9‚PŠ™Ćuö›˘ă‰:46[lvä…G•Î3%1^DęŞB°Ň{ÇÂhoŹĂŠ…íčěmkŞ­B$žÇ]˛`ľ>mťyűnźćŚŤ§ŰŰEpŤX[(4ý`üXç]ސŢd† 2dȐĄWž ¸ečźĐ;î{|čaŹ\Ą𕕕0YíČ%ŁPhľżąŠ‘ŠI ¸šxí*Zu€•`‡Q´´4Ń5ŻDđˋ3Š|Q÷ÖJ‰ŞśKČ„É>ů,U-¸°iň­ÎŒĽŘmóÔP¨ŔňÂ:ři5ť'Śahű¤ŮŕnłD+ÔlđsO‰˘!T)!6–‹›_ÄőW\ˆ*żQżvZ9ďŠbýş=¸híbTˇ… „ŁřůÇW9g¤ę\{á ÔÖąy8Oľ ö†…ˆŽĹ0™b?9ľ‚m 6jň´Şoeƒ‰,łĂЎŢqű7|OŻ[‰Ai9ŇľČ;jéó)d$˛×Yöb–áÇpMÝŻq凧0öœš íGac÷PËÉĘfł‘ŃÚpLŻ-V}cłřđ.FjkkŰtx˙e㸜1ƒĘŠŕôsŹ÷žó-ÓűĎ/Y<ýxŮĘ5Ľ>9ůĽ˛ŚĆF<öčC˜˜˜œ~/žn+X t´5#f†Îe‹zšQţ yŤëQʘ_qEł‹ ,0KÁâCŽ—53Jđ)KlĹLo̊||Ek2C/͍ŕŒ#›G^."í%Čę‚]őŐ:ëě†Vá…›„fg(f†2Đ•€—ejé@ Ě’d‚]™đ˜€[ů|^„K: ¸E Łťˇ˖.Cgç>‚˝­ŘOp™+äčěšűčőĆĆ& ôőc ­QŃ~BmŚ›ËiÇîí;pŐ#C`¸ŠŠý}"7ăÓ4>ż˙}oĂwžő=źńwá…u&O˘Ąś–@JÚŰZńŰß?ˆ7żéőřĹŻŔ;ß~/űŻ'đŞŻÁ˙ř'¸ł…Cí=äą% pĹ0KŔ+ź0B—ÎDaą8a#0(Ꜵ˛÷żJߍ˘8}rŠě|*§żÔßo|ÔĎ’ŞˆmЇę!y› 6Ís´Q, “’ĘŰčţvšd™Őż Íĺé°@ľŮh‘†‚"“ă°;-đ˜$8­fDŁEŘěNXé}ę× Á¤\ś•áíCa8*‰‰z(¤˘‡r?pťŮ+ŕq'´ĄąqôŔítÂçvc=AŹh"%Ú˛—€^á.[ĐZ7Ť˝ öŔeçQž”ŇBJ pi:Ę3ĆBC† Ú¸aŁđ† Đ|:ŻcŢŹJą<đ8¸g÷´ĎkóŒRš8ČîÝťą`Áą /Œđó<çŸoŠ8 zŠ2ŕ–ĄóB‹-ˇ˛ęiĹ˝žaö6ją‹č˘ŘIĆSšŹýٔI֐§‹k ÍEEW´5xČţX…ŐN˜ć™ŃÇżż0ьŠů Ť‘R˛hÄ$ŹíTÓýý[ ČĘĽT´řœ¤ďG™3‘U+¨łŁŻsýĘońž×^ę:2,vLtö ­Ľ“2&GşqĺšEřńž'°-H­Ç‰ŠF?~Ö?ŒŠÎ~Äi%ÝÓÚw\ÁD8 §×'<>ć"ŁT„˝Ą<N Cńű_mĂÍ7Ŕť?ś S#›0žƒ÷]Š„[x.Řĺ4ŞkFĐxKŚ! ‘ŸVcŃk?›Ű9 ř„yŠ•á9źeŽ:ZňPc|;üőc˝ďxŰÍE ăÄ߆†#öwř~Ďĺ¤Đ†Î%éŢ.EŠ& OŐěam2“^5郇 Ë6Źä-phĹl†œž"ŔU„5; Sf‘}Ëč.h´ĎB9‡GxĽeUxiNşŃb„J€Z5[qúőx TŘRqÚ¤œSI‡,˜yŕ@7nżíŐxčÁ?âúëŻÇ#zW_u%Ö=ťkV_€-›7ců˛eŘśmÚŰ۰oď^‚?^qqď´X SSS¨ŕB‚Qź0228(ţ&Ł1—Ś6ŘŠ]— Cƒ#•ëĐCĺbÉűöv˘ŽŽZ<ßFűď¤1´]@śƒiĘĄö*fěŽZ28L0ŃMĄžSʲđŹbĎ(6VĘyśŘ 1™y;˛I,ÂpżŰŠŻ˛9ú›¨8ËŘÉëa*>Jó›Oô‹0z˜çĐa˘ď,Ż% ő˜J MăŻ*s÷Ť˘yœ“K•ĺYýŤ2ě4JĺAš^7 ř”&¸ĹaĎrڂX1GsA\Ěi•ć—tv iŐnEĹ[čTťäR-§Eˆb)?X<•D‚ŕ˘>Né 8Y:o&#q=L•š ˝9‘I—€ŕ‘çƒBç—ĹűUD˙Ň÷[ňŘâńĐ$úWĄŸ† 2tzuř5Öéíkjnša‡‡čr°÷3Íšźŕ¤1Ôçóall ‰dýýýtŘˆšę ‰ůčĹ_cŻÝn`‹=ľy3dč•$núłŻp3Řzšä¤nZ['ŁȒÍ`S rM5ÔӅ¸[F,*ăǓ7#ś˛#„ˆ–Ŕ@Ýľh+ރŁÎ„MFw†W[ 'ýBšP˘<Ç9” ‡áţ!x-Qřœ*GßřĹŻŃňáߎ\ W؆x$ŠŐKŰąçŔ$şă)Dç/Dś˘ÁŠ*H›ţ„Őő-ˆgr(J&Äň2d…–q46Ő×ëiv;$Ůɰ3[Ĺ}÷šŔ~˙ZěřUÖHĎŕ’‹ăhź˜ďĽ^ŠW˛Ł*˘{%<ú‹Ux÷âśŘą¸"¤_B°G„̰Ďś :ué^BŞŮ. ’FŔŞ Xšn 3ІČ@Šo&'=çĐ#GŔEÖLœš‰ GT„›$dúmgz+ˆĐFUÉÁ>ŐMďőŔ95ŇŹäínÚ'Á3ocJŤÉ9‡öTbFßa-ĽąŁWäÉkF_Č××cttľľ5čFŁŁ#Ł¨ŞŽůí<ĚÂá0ćw´ Xʄ<°ˇ7yaÚľW/ě@qlH\řđ'çüńH ĄŠ ŒĚŠ­ŞFooŻ~zÝz´´´b|jRě; Ҋz~żńd’Ž]-r{Ő6/˜nŻI2ŇĂ Mԏ }^Ń۲$ŕ–ž_KÖo´MQҰ‹l˘Tź˝Lý.’Ăӱ̊ţ~U$…—á˛yu°Żż‰>#˝żP„ĂD4šo]žWZÉsKÓ˝Š4pIG9ŘťJä1äÉŞ˜‡DÇĚQß%2yšĂdą°â$đWp˜‘ÉfÄWĺ"čĆ))0!mápAţœ"¤˛äŐZä°Ó˛ˇŻ° šm:Œ*ŻOh:yďĺŕIŃÖŇg<Ü‹űÔn÷•ŕ–…úŰ*Îę}\†‡† 2tfuú“Wą—aŐ5ŐtÝ\sA4ĘóOţ˘_Œ­ěÉZUY%ć"÷xŰŃąQ´ŘӕS¸8p^¸Vü5dč•&ĂJ4t^čĄ?>Œ={ö➡żUŹ\$qÄ)Zą8”46ƕ˛ů"_w%­ŒĎm"gŻ 6>ôUx|ńÄ[(úkż ›•ߏÉĎoƒ;; Ë+n¤Źddj ]EtЏńń'u×j2â„1ĹşbbndłÄ!Oýhnjšĺę=Sý}}Čh7+ú‚Á€X ă°x"!rűđgËŃEßßšc§čóŠęZ öő Ż.NXĎF]ŠVÖ˛ÜnÚś– aŢĐlzéCîţ}{Šťzî$zěr911Ƃ'—ÓËĐ+YšđÄQ9¤~ Eö"rx`" "3Yç`ņźĹ‰źdĄ4Áť&b:§%ĚĆ(bŚH°ÇÉ‚dUb×ß)‡48{ďAHVœ˝Ý°ÄDXŁc˛W€-çř4‚dQeďhÍf!†Éx^ŸcŁc¨Śq‚`TUe%&'& Nhń †ĘĘń$”‰qÜI‹śv´X/Ú:*܃^şůŸĹ˙źĺjD÷<Ÿ×‡p,*ö340ŒÚşZ8x×^söîë„ŐŞ Šą ŰwěŔʕ˱iÓ6ŹZąŒţnÁŤWaĂ ›pç ¸Ĺ]"*qQ‹˘ĆĄˇJŢ[’r¨ęŸČŠĹůŞ8Ź‡ΡĹUĄç4P* pD%˝"˘™ú¸PĚéď/Uą˜Č$"PTڎö/ŤĘYšŚ ĎŚ#űXO]ĽW5E=HěÝĆíâň„jƒÓ@•'€\ĎA¤ľ˘¨‚›‰ăů=yÝK›QúąDč´¤éŮžtŠj)Ç˝V~%ď.ąîąŚƒśRiEIÂ1+ăjz.2ń~”<…=šź“hȐĄł§Ó ¸XH­m­G3zúŚČ iÄź†>TTrŢ0Ů$A­ź*ÂŮpńĐ>˘YM<× vöt8؍ÚúZD öšœ.Äe:*Mx׍‹ŕˇD‘Žě Gđëß}O†ü~ĂNďGő˘vt44ĐjQ­9á7Mr˘ŠÄ1ĄĐáŇŤ)ĽđEXŹ\˅œŇœľŻ_Fß°›2bĺßîŠĂĹ-Ůç"#¸bž†ďvuú0še7Ş/Z% 8c?ç˛9† pż2Ź:VvíVD(^­ž Ô–-[°`á"s)ěéěÇÂůíČgRXuÁ*č3îÚň"îzýBŒ[­dXÇń§ÍćĂek—c¸Űśî@c]%V^x)B~^޸2h&'xG}C“¨ ŮĘ ÍU:XŃ.Đ-OçűČß ž?ϞÝôŰM‹PDŐća‹\0!ă­@öC@îégá{úIq-݊"ˆš\\aśÓî@ŔjÁ ˇ E— YůšJČ`]‰Ihq4ąqHP´pŻž›Ď‚”KľĽ{vďĂŽءďZçľ`dt„Ć$ĚýÖpşOEhNđÓxsC&•;•B<[œŤÖô¨îXĚ$ ̘‘˘Upk"ŒâóĎŁĹÂáwSˇBô;ŔŞUËńÇGž[ůl^TD]śt1śoçj‹KńäÓĎ`͚UŘ´e;Žşě2<đĐł,ŞÄŘ/˝+z؜\‚ó%H᠘öHe`UĽÓJĎéŻéĹeŽLČČJÖD~Bb(>•&Ĺóž9LĄ¤Čš%ëŢT0(ţlR…WÓěqB‡dE>.é™ěERz™ šĆ€>Cý‰ŇbKšBşŸYQ€{“8,“=ś •ާˇ—ԗ˝ˇ$–ŽoSžÇôăę°K+mŁŞĽ,ôĺʇ%ŻłĂ Nź(ŕš/ĽÚŇÝźD>šß2—!C†ÎžNż×KŸ 0dč•*Ă"2t^č=ď~'žxň),YźH<ŽŠŽ†ŐîD>€;P)Şz9vᤐÁR]Y!ńŃâĄGŸ™Ő^MŔ}€~Ą"—{ݞˇg9‘sk #xČšĎčó+ԇâ9ž•l%šäÄĔG&¤ŠŠzč˙ţĹ_úŽ \wVqŠoś D1˘^ ”(^‚ÂŤů‡yŢj%@&‰AWŇó^1Ëçô}Ľ%¤ĽŇ1Ę޷ԟ2ƒ4ŽHČ`“ŕWr”ĘĐTŐC(ÜŻ]č9ˇf˝Ă*=ESJ á%ŠôyË řg‹A˜ZŞ/É÷ĘĄž"ą2÷Ż˘ˆËŇ9dh2d蕠Ł]—žíqȀú† ą ¸ečźPKKł¸•U]S#nÇ—‹?Sbw_Wu*‹= tĄo‘8” ŽEĎOLÚł.‡˝]~x/–4űą)֍Ć+n@UpýŰńŘ3ăˆlËéÉ×éB?/rüŞâąI>‰)’.ňƒM˜˜GUcÂ#Ű0żĽ [ëEN•LŃ ‹Ż‘ă›ŔłéxÝhÁ–zlŠ Đ֎ax˝n´47áSżů-ÚˇĂZQ…Ż?śÔŐĚąГü˛‰WäwSٍ$ƒym[%ž˝˝̈́Ťkł´l˛i¸żW5Çp`ʁΨ ‘´w6‹%Î(Ň ‹LąĄ$ŘÖ)„%˛ ťÍá5g& çűeńšŇš7óœšmméů˛ĎŕŇ%‹pşŹ8ňźöű|ÂŘ5dčÄŇ=jœ5HMŢx#–ýě÷ČNDPIç46)9*<.Ů/ˆá N6ŻćĐ+’~‚C y ˛‹"VˇŠ!˜2Q¨Ýq˜Ć' |eö(Č;<č÷oŠD`œŔÔÂÂűƖŠŕϊĐHé8".žh ~ôă㒋/ĆŽ]{ ˇbĎŢýX°hžđ´ä…Ž"–B>Á­D"‰Q;C9sR ˛ĂŠ\:wub“ƒ0ůmpy´‘‚…]őČ>š`Vŕ×÷˙–Vť‘Ą6Œań˘…Řž}'îźý6|ö_˙ˇ’f‹YT'Lě^łzĺěžšątxe’-î›JÉâŮÓi::fÉ"€˝I/E01‘pž=S%ĽÂt&— {Ë)%X•/Už¤/Fx<‰…„"‡›ô\\›)'B÷řĆ}ÎŞĂO…’9T sT$=‡-Šý<ɧ!*3iłˆCÍi°R?(f‡ťpŃţ“ExŽ1X`K䶗ő0BţŒ%ˆŠ{uÓ3[ÉSM+=ÔŚŁ%č_@ď‘<ž˙qßJzŸ+%¸ɀ[† zšuň]<Ć űádŻçޞ9Że˜ů%52dč|”ˇ :Mr›%ˆo°×–ďÓääłĘȑĄńÄn Ď۸Y‰ÂíÇe‹`m—0&c.<Ö׌ůÚ6˜eˆźVI2ʜ?…ŽÓÍ"_ĘĄqţ''"ƒ)ěŰškV,Áß˝÷6XéýýĂ#p+°w÷ ˜Úł5Aö ŒâńëńÚĆťđćW߄Ż?ô'<°c7Z›ëDňçęP-Ö=u‰Ú˘/< Ü{ć*wáp…ú ˜Ď˘ďFÜ~Yö<ĄAqźŞÍÍdĹ5ósřáöŇËęU,¨Öđ§N2úŘ{$ţsř+ (D´HĽ0¨0dČĐŠJŇó\9ÝůŕëáýŻoÂup6zŰKp'AĐÂÁˆB÷*„㍸vf^„$ĚüŰöUbüo˙ő/:xŠŽˆ°ßW2 ÉlEŃ_-GPŤCQą H;/9aíěFÚㆺb¤lŚţ¨€`G“ÓĺŔÂEóđâ‹Űđţ÷ż_ţâWpý ×bÁ­öÖ6ôôôĄŽĄăăăp:íl„ ˘…íúŒ)ú.“łˆ\„%˝•HO¤ąŠĆčZçĺ1ŃľUË/὜ԼĽŠ űöěòĺKđË_ţ˙řG`#°ľ}űv\uÍxꊧqľáń'žÄ5×Ţ0ť˝'ŞýM0™-:3Q›L6=ůšI)yé€K÷lŐż ~NIćőň˛<ťRŤČ_UĘÓĹ^Nzxuž‚Ř*ˆ„îţN„‡ dyDĹFÎűĹVJ)„qöŠ ďťě&•áSQ÷ĐŐd‚c9.R¤öË"¤›=ˇXf+AK‚ƒŢV*•ř•JŠ˝ąJ^Č({Úrřٍž¨ĄœVŤl‘I%Ż-IÓŚ=žĘ!ˆ3eł8Ŕ֋|diܡ\)Ň,úˇ¸čV‹† 2tŚŐ;Çh<%î×ůœtsá%‰ĆźĄŽMˆO&PŮP…B:sĹ<äŠ:¤bߣv…›ň"<Űj;ąpZ_˛˙؞Ń) F’"4Ýf6ᚎz2t.ˀ[†Î ýěgż Őú}řŔűß#ކD#aDbIxÜÎéŒĺ¤ś/×*…IŹźÓ˙Ěşw›™˘n,ŒŘƒh_聾˜@ĚďFhš =Ý;P]edžg"(.šů§w ҰčšWa`7ŠC}pYŘ  4×ĎD›UWذ{ØHd~ďkążwy‹ ÷M">ľÉsFĂh^B¨ŽŽŽ6tő÷ă VĄÍeĹϞ^ŻĽ’xÇm݆”ôbt$ ˙eópyK;ä9&DĎd‹đZ ÂŁ€ NcńşŤŕmۇóŰđ?öKlžك—`¸u!Íçd¨Á‚?íĐĐXěĂjůy\ľä~4űF1ň‹l~˜ĐU6‚9×Ę)đ->?FÇƨύŽšÍÄÄ8Ś6=|‡Ť‚9]Ó`1C}˘ĘfŒ ÁKç\2™‚JŚ7„Űé8kçÝ@–6=I4éĐßD2ĆFă‚ĂĐÜÄ eÂă‚eÝVř6nAĚ€99Š,AhEąŠ0>mڅFO ŽŃEł$ź†TXsĽVTö ŕ#›€m]đDZÄCvx|ůD8"Q(ąúXŇ)˝ęk* %+ĂĚ@Á ’ËŰĄŘ $cG´síę 042,’˜75ŐaËć-řˏżýýƒxÝ=wc÷Žhh¨ĂŘč8‚ž˛éňŮ4G˜Ć;ő°<ş ďŃoŐNđÄéŁÇ=ŘПCWĄ>%ŐŢN•’‰$"áćÍkĂ^‚g×^w5ţĺŸ>/şŕ‚+ąnÝó¸éŚđď_üo|äĂŔg?űÜňęۑžÁ_Źp˜Ą‰=‰8żČ_ňLÓä¨*'†"CE¸ Ę;•“pIŚóUM_ÓÉŞ¨űRčěلBbAęĺ4fِˆL`˙P7Í)8"&Z(hĄĹłđÂ+r’ű×÷5=$T¤q×ô¤ő˛IŻx(*ĚĘsőC•‹ƒXĹx^ą‹ňdtĺ2)áyĆŐeĹ\j7ĐDńE'ŔçĐÖRűE}M÷8+;ńWźŚ'җKůť¤R–™âžeŔĽ08¤›€[2A.q3éß2xː!C†Î°ŠGwś*?9ˇ1)O Bi^Ť @ŐrqÔŽŽĹŔhXäĺ żú5ľîÁŞ–ź`ăą8ź^/ŇŠĚ Ňé4ćuĚÇéĐh,+ÚkĹX˙Řž~2tŽË€[†Î íÚłW€ŁŠŠ°€[ť{h…>Nk ó,Ä>‚Aœ{Ëi‘OĎŹúZéż^\8ŸiYNxë›ČPiuCF:Ż˘gďĚ[´…Š6¸­2*źNŘÔ~<üp/ľ™VAÜ5¸${›ý—ŁčޤjýŽÔ/ˇ!;> Š‘ÉňÉľ˝{ß$üÁdšŕî4A™Ř!ʸ[*ęQ[„RáÂíž řÚśgýÎ)TVĐ^[M6f Ź{ éőş ć%„wě@Öë.lŸSDe,ŽrĄv6źL󎞝îFĹĽƒhýpWîÇ؁űÝ+#•ĄĄˆV„<,|UŻa˛łK?ôv_Cž o Öé`'+ÎĎŚóÇG6ŰŃsą#– ƒM‘DBůę /ú‡'QSUA Ž\v ôu€ł˘‘ ü4śí ĎD}72<‚ĘęjŒŕ˘ËŻFUʼnŤŢœŠÂ‘(2™q‘Ôy![>ňÚ/5ŕ–Ą9Š ‡ĹŒčÍW ňK_żM[tąč¸îhĂĄ‡šîľ%)h<¨.'Ty'ßν0ÓEś’cŃ/ˆeŐyŒ+*\ô›Ďs„ŔއĆ/ WjUĄÄc"$ÚJ0„q,qb> T#măĂp$ăHqâůŁüŽŤŞCřáwKkAÝAa<4Ô×açöřĚß üęň+108„ĘšjQ2˝˘ô;̏˛G‘óü& 'şěăáÎ1„nEDzë°{`Éńďăn{Ć?šW:;ąlń"l|q Ţýžw#bĎpÍxřńÇńáżü :;ŠßÚŘ8¤ÎhhY<Łg…_œH¨^ÎA¨ÓőP;­”ëJ:”8^HšáÁTzfzŢŇŹ'Ś:ń̖Ÿ!ÂESň§ĆóŘ?¸‹ÚŻB"›B_d’@”Il#KG´űuÇ*U9ŔKş—{ E2|YŔ@˙¤(@'— Ež+‚Sf“UÝŕĐ@&Ea‰e ĘšŻ4~N-UM,ľŸssq”ÖUZ,ő Dî.:g8i<Č™KPšŽ˘XŽŞ¨{‚ąG›Ź°Ç˜ś 2tv4łŚëń͌š…(Ś3YlŘön{Ő=xôţ_#LâM‹Ž#¨ĺ‚ÍފJÜě™5É9-éšŮĺŚEs.âB ԁ@@÷ÄĽqˇœ:ĺtč˘ć*<˛ˇU.;/_EzC†ć*n:/ôţ÷ž Ď?żóçwˆÇ őő4¨ÇŃŃތh"e´˛#Ă&žLa~G EN&œ‡|Żsç]} îůŤ˜~Ěí˙ýoĹţű{łŒŠ/˙ű?cűó߁ĹU 2ÓV2łi$О(ăô {ŢůVdťŃťiÝIUKlnócĺĹËŕ ľ`ÇŢ^Ř]ő°´,ÁAŠ ÁV0agWőM„V`ýýżA•;‡Ę9źgíJ,ŸˇĂąJL$ŁXAFí˜Ő‹TÍ2X„fž[‚~3G…{M¨"„†WÚÝ-MXüŚÄřúç1ľy#ŇŇ>Ř8ZȘńäĄXóP'4¤ŸFŰPuýŤxí"ú ´ŻœŮkţܕfœ´<7]8ř śXŐŐU¨–M¸omm%6E5ü>\N;üRQę¨?lÂŁX¸Ŕ+d(T‰€ß‹ęP>ĎKtM?ŽÜôx}~ň~Q9ńň+Ż@2…!Cs“>Yű'p/H+ź Ĩ P Á9ÉšÉN Ę…Äľˇ"ťf5ĚĹRnât­LMŔ˝ţiěűíCčÉ8ŞŹ‡3G ق~ OŮŠĐx\Ű"~ŻbŚ1NřčŘ-ĐbQ˜Ó´­7@@¤ŔĺôpÔ zęŠÇŸÁͷތu4nŹXľœ¨­ŻÁţ=űqßŰފgŸ}FT<œšœ‚ŐN0ŤĽŠ]VXl<ţ(´ň܏J[’Ćź \äpăw=ƒˆ oÁ˛Ś<߀š~1ýޛą‡öˇ`ń|űťßC–,YDű^‡kŻš_řň—…gו—]†?<ř0^˙şťńŔýá/>şxv×jzŽDv.UJpKĎ5%—Şʇó5áĐŽ÷”5łđVŇR ýL{#C$uďŢu?bą„Ď&ď‹ŕ'5­;îGŞ JwŔk˛ ćj‚lőŔaq” Í%%Ö˝:‚+ŞŞ Y˜2S"˝H‚Oű‘8źĎd#0Făo!ŮLm,ć‘)äiţőŔ’őóź'Î#FPʁ8ŠšqÉŽCRŞ Šß×f¸8čŘK/ŽX„Âp+Ÿ¤y0'*jJĹě‘gnÉ-Z›Ń‰Ó0VOC† :ň;ʰšő1Çi9хé‰ê׿ă“tęĆ=ďnĄÖ._L‡BŞŞ>Ŕšh—.[ťƒĆű‘ 2NOi Eźn~˝đŕj2ŕ–Ąó@Ü2t^¨šVâď¸ăśéÇĄ¸ąÎö,ăó_řÂżá]ďz'jkk .űéĘ=Gp&OˆJ{Ys4[9͆¤ťű-UXŤn˝Sń$"dë=÷Â&ńž*š¨–/Z9÷œ[œĚŢäÁäÄžyd3ţůˇ`9Á–‡zÂX°r)­đ¸O§ŕĚO@ĘÂYŤbţ%Ť¨ŤGĆÂ˙>ý8Ž Ř1U“ĂČč(ĚîvZ­ń`0<g6ĽqNÍ0›é3Çł´Ę”•Í49iâLôÂľŹćŽ[Qiž Z2B"‡ôř]tjĐđ†jäeéřF†v ąy}.ťžŸF5‰}žŠřýÇ IdůłΗC^gޟ7Żcú9ŻťőČ}řόÇVYÍ-­G}ŢH(ohŽ’hœŞ|ńfÜţ*äúrÄW :hŕ†ŹA!…Ó>‚‚`r*I×ő´Z…†°ZĄe~G§E?š"‘6mَĎáŸńéż˙'\|áZlŮźÔB$cq  Ąšš ?úᏰxńbÚ>Ű 3Ag3}6M@1šŃâ7Ă[ً|*ŠŤ]ŹiéF6ž;öy°Ú>2™ ęˇď؉; Y=˝˝¸ôҋńäSĎŕx/ŞB´zý§GqŰm7á˙ů_ńƒ|˙ď‹˙;Ť˝üdčd–JŢHěÄayZl)č!Ú˘˙ín†ĘŢGěá”#cĄK˛ ‘Ŕ<—Ý)SŮJ…‡'ř$ üĽ5ňĚR9ž”ăb$ôXÉ%HwÁ_{=œV1#=QšŚH3ÚKÍDǕŞĺâ"7—Y”h$ÄĹ9˝Ô´ŚJű(rYg“•Ž&CĽ9M÷ź*–ÁKđă°çŁČŃ{2›ň˛ů'•Ś–riňHă˙ËĽjŔr‘`V6NÇ͈âv.rŽIŞ(Ţ"•Â9ßĆ"ő1磹Jęšş 2dčLČmłˆŰéĎ-Ľ‰Jýz•9 ŞŠŮ…Âg_ďIŮĚň™KoŁąŐ[†ÎpːĄÓ žO bćŃĐOĆ'8f¸ĺ*ÍyƒƒC˜œšpŤX4#䏤•v3’˝ťpĽi'xá§0Ԉ]S ‘Y<ĄqrČ,Á(űÁOk2ŕœd&-mŽ‚§ŚMJ‰ŽZע}~;DFáqY1:6Œ'ťSxë=7ĂçrbĎÁ^lvay} ~œf7şű19:†•M.Ll~ň=—ĚŠ°#cĽĎÍœĆ,´ężé…ÇžÂđXóŰýČç˛Xą´{3 ¤“ăXŃp5lú FĆS¸–%3š / †7EööPg”•7dČĐIJD>YAŠśƒ!–ĹAp!3ě\*-`ĹéB@n623ÁŁBĎ~b“Â;ŐľHÚ=Č:\Čp9˝ź SE5¤É1‚V°Ś†ĄĐëZ&ƒ,k{žŔç4x „R*‹' ŕĄę˘gž^‡•+–Áfˇbăó›đÉżţžň•ŻâB†\ŰśŠŐë@…űöuâ–[nĆ(}ż?€LoˇČaĹČTiƒŸ{´ IS=>¸t=j )š+ąş*ŠĐÔŚúú0oţ<<ňؓ˘bj[[3Ö=ťW]s%žř•ŻadlˇŢz3~ńŤđ‹Ÿý ęŁýtĚ{ßüúYíU9Ń~! ÂAzB~˜a“5XMN‚Y&qăœPœŤ/KPŚŔR<ÎYl"Iş\ĘeľŮQČe`Îf‘5)"l˝Ű¸0˘"s5]‰öL0‰Ţ›çÜXޤ{Çq"w†Lôd€ŁJ=Z9•üěyDŚą”ţËů„H<Ďůśt% O/νĽ"ŁťĄqeKţDŽJ¨ÔĆ|>Ĺeő˝ŇvV:€UĽńžčÓc;hqC¸Ř–ČO—f”ŚĎCExŞŃůĎŠÜ2’mEýeŕuXŇ-QIŒć;C-NŞ/č8f‘Č_"čĆNј 2t.ęärp•Me‡áŁĹÓŁ,˝Č,sĎĎkČĐŸą ¸ečźĐ׿ń-ě?Љ|řƒ¨ŤŤ%’ŔŔđ|^**yۤR)8Ř5œ|ĄPΆôŇî’yűć7ţO<Çâ–Rr`ö.ŕ›x^͢ud úě HŠqX|Q…Ź˙š?áâ[ނßmœœŢ/'ˆL mA…É4‡2x ٜ ˛ÉhŐčŽObăţJźŘY@qÇĂřÉđ7ÉđJâžwžZd•rOlځä`QÉs]+śÚ†PAFéŢńD˛E´’1ńÚëޏږĐ5áD“27““żłc=Ĺ\Bs!Kĺş_Gý‘B&†˜‰6â*0W×9aś‘ڏĐ4o ť ůrě΀đĐČ ÔĂ{4˜M'?tń÷066ŽŞŞĘŁžÎ Qă1˛ž?†{ZíqLţ<\)LšeTQůlڞdřńçćđKQäóž ńą¸Şđx€Ç)Š 2tbéagśœŠślžĘ¤PSQ‰\68'§ß˜Ťm>Lž ›ÖCí=€|6EÎŞYäZzÖ-ëDÜý6rî ݟÎO‚!š} š)‚4ƒEšś$úmé9”*ňÉ"ÁúŃá=JxÍ=wâąGGSsývCxňŠuxď{߅ř-V­ZŽ$mÓŰӏĆĆFą]°"5Ożb˛łŽVłwaăPöćŃčŐî÷ >8 ŠjŠőŹ=[Ń=<ˆ%ËVâ ţ1Z˜¸ř˘‹đô“ĎŕozjjŞńŕƒăî×܆o|ýŰčîîĆÝwގŻţĎ7đ•˙ú2҅CíU$MNé÷‹G TÓ}+˛\!QbŔ¤ˆŐw…`–¨’HăŸnŒč‰ĺ1]iPůŤ$ťÖR+ťżŽĆöŘă}„ŘS‹ĂsĽ ƒ*ŠźßR**îŃxzR_ pŠ@ Kplڏ°é0ë.{"ôQxČ*úwÂ㊤ꡔ šŠî¤Ô$,î*Žvą “ĎĽĎk!°%sUEYŻ”hâǰŃçĹ˜ŞŞĽďYŇJi˛h§mĺ|Žä5Ćc¨>ž‹ÄöÂ3ë°3—öe1ّ§ăĽŇI¸^:§lČR_ˆţ„Tށ`x† :—u2žö őóŘşyZÚÚ`§ą7ŸĎ‹$ňnˇ[\tű|~‚[2dȀ[†ÎOpĆ=kĎžXšrţăiľ™Œ-ŽvÎ÷čâź˝c>śí܃…óŰĎ Üâ nÇ‹!‹żż˙~=t‚ Z‘NŰ|řĂýżeßYl€ÄĆ{Ńqý-°ç4ąęîvËĽĚ'@:ÁŤoťÃbÂjmnƔ9ŞŚVâJÇĎ% ƒž-ŁÍŁc^FstŔ´yłp5VCkó#Mધk/îšýő¨{a†‡В E+ŕlĄ[`%:v!b5ÁWS…›Ż˝c‰Ž Wô—ŞQ[ ^*B՘Hˇa*cA,LĐE.–rŤTˆOZ ó™aN ȉ\&ËÄKPĚ2˘ü°bX4V t‘ŃŁr.,ÁK?ż€e'#N(?55EŔĐsÔź[ë×?/Ŕ(‡GÖWűńÜúͰx‚šÍ°{Č%#"żŰřĔČý–M'PT%џAjOtjV‡ N‡ şzpű­7ăLhóŚ142.`i&›Ă殊j\}ůĹ0dčÄҸě/—ĆK0‘ BŘAĐ[÷xq: řĐoĐĺŔlľ wÝMP’—Á´}żi˜;žôr¸ţáŁh ̲LŔł <č÷ĘůBňáq‚ęlŮ$ý&Ü"˝ę^D śhˆ|O4ţŠńÄ1Żóëëkąvĺ|źá oǝwފuëÖÓo-€Öy-xäOOáÝď| vďÜ-ŕOK[3zżŐ‹J‚×||>”L I ç0–t#T•ĆPçźşa?qœkĄš đőŇxö‡'ŸĂżÝ~‡X,ynÝs¸ćúŤđ–ˇ˝“““¸óśWăg?ýŢöÖ7ăňË/Áˇžý}|ěcĆ˙ď7ąţůçąbőe‡,é`&—Ď"•ĐÂÄětŒ żnWH€r&äźf4ÜéaŒ˘ÚUQź/•Oc2Ü%ňX%N-ŸƒČ5¨Ă+ľKîDvűŻ‘ŃŘCP‘AB3ƒ'†–ç­ź-WŇRôE‘ˇŤäwx1ţĚě_Ĺ ĺŠĂdŮ$ć^”ŕňf+Íbů‚fŠ™Ž'ÚÔL”Řš"ć5}‰ •™“ÍÓü˰N$¨§ăĆ Xi˛•Ŕ–TʇĽ{oq.2žYhP I@ 8ŇMW”¤ůG:Ňu ZésĒ㈥&`Śń:Hç˛×[KđNŸC 2dčĎI|˝ťjőáĚ`‹Çu—ˋՊL& C† ’ˇ z˙űލ­ŰśŁľľE<^źhv÷bŃâEbU¸PPĹŞłĎăF”ŒĽ˗˘Ś*„ł!‘kÄăÁ˛ŰޤO:3 ˆÚ%ŤŘţu‹Ws_Â0ĘdŃś\wŕ‹űŽľWŠD‘Šb:n8çWU(„÷Ýűb•g.‘Œ+V,=Ć+‹čvόýëŢXťcÚKíXíŕíŞŞjáq_/źNg&(>,{§q;ä“Ě/ ʧý°ŇĹŔŃÔBçVžá)őł?P…   ›a•UÄSTV×ÁDpĚ尋c×ÔÔb„ $çĹ řiՌ ăÁĄađŐÖÔŕL‰˝ů‚Ą*ŃV†q^—٢aĐšŤ˜%ÄÖśŔÖ^‡–<‚„›š‡ŐîƒËF¸#T@ť48O. ŮéÂȚľH$# ˜^䯟ăëŸ řÇr pĆ>NúäqűˆńäEb G<:…\-2L 'C— "OŽF#č<>Vԋ/Yg˝}}¸ăöWăŁ˙$Á˙›Ńšż ˝˝˝¸üĘËđŤ_üí"ŹoďŢýxŐM7 ŸNĂĚ^@‹”¸7UîF_ň'đ×)đ[ ߟĂřÔdč3öÓďéšç7 Ë‹/^MĐě üç—˙@—ż}ŕ¸űî;đUYë7ŕď'^wďťńöűނ÷żű>üîwšˇxüćyȤXP]цHlŒŔ|Cƒ[!ŰZ}bĚr wŘMÍ $ŇŤ3ţ7-“Yƒ‰ţ#œťË•Ą ¤ˆíDa‡“(4 ‰œ‡E5Ź{xq8+çÜ"ŔŚȒZК_ä1’sqŽ,UxĽÍ=--ţXč<ŃÔűů/â׿řnżĺUřä'˙ßůöWńŤ_?2ťÁĺĎ=40äŤ.…äĺ1ăâđřn‚7 Îƍ ˘Šn9G ľq-|Î ý5´@`=lˇ"ÖNôĂŚ@ M­˜ZҌ‰~ŹĽEžy,ěÄ 5EłnŘ ĹÓQ:Śsz>:œ!ލ)oYůů^˜&!ř/xô˝*Ł1‚^SbÎ*Šj–Ş€ ŤŘ÷ś‰ĐyÄaˆáĽĹ!ŤŠVňŁ1ž+**2—TáJ†EŃ7˘"§ČľĽŇĹ'A;ęE÷قĹb‚-­!ÁÁ›ž ´č¸đn›Ő|ăĎÁáŒtßë ŇU Ő_‹X:"ćáQę_ G(hkmstž2dČĐů"ż˝ö'­— xoȐˇ : š ZvlyŁcSř\°ťýpÚ­"I灃¸îúkđč#‹Ęa-­­b•Üď÷aŠŒŤX$‚šFöJb|ƒúćvź°á9řüŠxÁ+đô3ĎĄ˛2DŤň˜M˛×ŹŻŻÇΝť¨ŻŐ!Ą!C†NAšđ°y{˙v4ŽDúň&çĆŻiĚŢđ źţ=Č;ÝPź,fä3)GPČ/^X<ÂŽő­äÓ $łŇ(*2Ű\09](*f„ŒŚă"S>Ł‹˙x\Üççůu†%gZ6ťnK´I´!ĹP,"ϓD+ÜEx!Ä龥~¤öš-VäȈěí>ˆáĄA‘$Y:MłŻf××V‰DĐ{÷ěÁî={ŠM 2œ¨ U`ßžý"ů~$E„›•ŒÖ­ÚŰíVźqú:ŒŒNˆPŃę /FƧčsŚ!›m"/ ›żö8SČř9ĐuPVěݑĎápŘ1BýQ Űh÷î݈Ćâ8Uąq˜H$NjűS9†!Cçś$"œéAXę˙uĎb•[…žv80Y­hź”r9ŁđؙN@ÎŚ`Y˙¤=[D•<“JGłŔB°!Iš‹!rBp-Ÿƒť ˘Ćí^:4 AKÄD8˘V(А7ˇŮ G+¨âńŃ<¸Ř{ôłŸűříh\?ˆwžómřţw(ÚyÓM×ă?ř ‚Á ÖŹY…ű÷Z¨ ‚ź ř!0§hy‚mĐĚh;âcQěytö?śSă„cŔ —]ŒßŇ1RYîťď^|ó›ßóĆ'?ń!|éK_ĽĹŠ1üח˙_ýŸoâO>Amřž!˙˝ďýtV{šŘ„™čr"4FóĚ žčÄčÄÁŮgÁ>NŻŃnSW/DćîŐĐ\f˝pA-ÉjÂLß]ŽDȞł"ŮťZ!‰r1 3_!pÇ!–ůbN@´"}ŻüźMÍÁ*ë7§…¨5|;˝ßgZ_ŐjGŃ΄J݆Š &i›R~öů Ísž6ęC>~ŽÎ;‰Ď˝|Z䢑Lš+ "tѐ!C† 2ôʓášečźP  ŚR•źÎŽn,]śýîwtqěÓ*c Í­mőtîĹxBEK­˝ýŁVV"—ŠŁŞśŹ\†3ŠŽ…Ç÷vşćĆŁ'oikǙPu}3n§›ĐŇEGź~ÁŞG<ˇ`ţ|źTůC5¸ăö[ŽťÍüRčßUW]%ţŽş`uéń3ÚҁÓ!.FŔ“É›ŽRmń…7Ą:čÉ]‰Šá^‘ƒh*–Bs} Ňš˘¨ţČ@Ž=,8ŃôŠU+ńô“OA1[ąxA;‡ÇaŇ2ˆd¸@=jůRôÂĆ %HŘŇÜý&‰$˛".şp :ątä d‰ýîH%†ð¨R]^¸­€<:†ŘHżŕMrŚLŕ‚o9:÷M˘ß“g°Úđ‚ lÔŠŮ4‚ôˇć:ńhÁ†ôśŹX\Č P%jäŠzURŚ&ˆŽ|Ě`ŠŰnš{woĹż~ţ?đ…Ď˙ƒČĂôýü˙ô‹ÁÁaüěçżÂ‡>đ^:˙łřĺýżÇŞe‹ńŔ—Mŕ—ŻÂŇymČííD– •#PSŕfÉ jˇd˘ˆÂ˘nżř|ýÇ?Ă7žń|ŕďÁĎ~ö+|âŻţßţćcďžxëŰߋď}ç˙đă~ůŃOaŰöÝřńOţ_Ü3Ť˝†ž3Ůŕ0+"wŸ…ŽÁE1č‡Jă92ş7bxŠ;Ln$kÚásW xUŕž3PŕLSÔWV“N¸8•™Äá~ÔK&łŒÁÜf†UX˝ęBáýţÉđ\փýé ¸x` T 8ŸK‹ÄófEy­˜e*˛*ÂŇš’˘Ć•iű‚ݍn&‚]Žńân?47­x6Ĺ OO“ŚJšěób!Ć&Ó'śÎ^ĺ~RMĐaRŘ3Žú•úVĽmM˛žSŤwx32ŮWŃý3—÷А!C†ÎKކ^i2ŕ–ĄóBďß{°˙Ô×ë9Ž–Řę'ăfĺęľőPŽŽŽ.‘okébZ&k'¨%c Ž!&V÷SŠ„(w~ś559!Vş]Ÿžł¤X^&“B+Î´ŞŻĘ\,bUZOz{f‹F‘ĘdEEEyFN°Łĺř:ŮJ„§$ŽŚ•LÂaˇÓ÷•Ć/{jÉ>H'ߊßçƒßďEœýŤŤk°~ýspŤŃ}° UÁź–Ftww“ąO`ŔaC2“Ÿ=ôöíÝo°áń(FŚ’´/÷ƒ[üýpŽŻx<ŽŠP2Üł† ÍU̙śîˇbUw%ěwx°ě*/ţř@Ó2 Čtţťăô{‰Ńiâd~PÜ>¨6+ňľ4wďEĐYƒÝŽ4˜˝Éăĺ㋍H¤Ů‹!-rjq¸š*ĘĊD&$ĽźƒzZůŽv ><<‚źďcxÇŰ߂+ޏď|Çűńć7ލnźoş÷]hnjÂľ×^Ď}áKˆĆ˘xqëv,­qăoŻż€@Š‹€Q’@ Ý")¤7íGVĘvHY EűĆ'ńűîć;ćáҋ×âťßů!^s÷řŇ?×žámř§ů7üă?ü NŢôćwŕżţó řůOż…÷}ŕ¸÷­Ŕg?űOłÚËŕ‡?bN#°Ľ)]ôqTĄ|ó ŒزšěôŕIDÜbźÇ•9ĄEŇŤ)r蝉‹f˜MŠőWŤ´زfrp1Ôę†c‘ŽĺíčzhöŚPŮ?‚œ}ÖIJ^Ě9&Z2›GńŐ/@mó@JËb\S9HDŹr>?¤TžćĎ",‰8ĚÔW\´EnářuŢ'ľ‹Ăe~ŸšĽq[‹ěą˝V¤<}.‚‰&7}ĤŠ^ü#)8EęŹHzŹ0'i9:žÝP1 Ÿ9•VśÇ}˘Úĺli" ‘ŰĘš2#;w™š˛ű=›ěŃó‹2dČĐYG$éZVŒ;4<şœ.ě4×Đ‹Ĺ,^ˇŰőPižncńb=_{sT żĆQźđZ.ؤç9œN} ä(oĎ×ç\)‘ßăršĹâGĽđ˘ƒÉċ 9ą˙r'SéXĺČ.Ş”ÍdĹąxїsx{ކóľňLű Nٞ˛Ňď6t^Ȁ[†Î ńżrĺ!#^­mnjœľÍ’%3mŚďqywƒ“—Cá‰q$’)TTV!<5 §Ý†DŚŻÇ‰d4  šŽ„A´˜Ŕܙ‡&SiŒ őC3;aˇ(Č$ăzČN>łĹ.ŒŤ`°U•8óŇ  ‚ÍáÂřj/tœ6žpX°`ţ1Á]{ťžßĚUzüęŰn?b›yófˇíÚëŽ=l‹8ÓZ˝fíŹÇím­âŻ‘PŢĐÜD@€ ˙Ăé‚ůZÔi đ“ Ű……\/žűňĺhźTăSČPQe™‚L°*™€ƒ`UM*Žxř„i!aGь‹´!ü,W<íăń˘“`q9üŕ ĺb&­”`o!‹ŠÍMW 4….ź Şá>˘ĽĎo؄wžűíxőÍ×ŕío{‹ń—˙ţůż€ç_ŘD *ŽzŐ¸hÍJÜsÇ-Ř´u—ƒććňž}œVh´’`I…a šˇWp Ógľŕö âăYą˛ýW`őĘĽxϻ߂ô“ř+:ĆÇţň/đů˙˘€Ţő‰ف Ţ}ďů0ţęcĆO~ôu|ęӟĹ7żő#|ćŸţńPϖâ…CĂ<­TĄa W$ƒ…óYľ$Á*™Ć" #詀Ei’RÁR YäűěŚŇűŁÝpő Ă,ăż˙#=pS?(Ž}5QüöŮ͐L˜Gcˆ™˛bߥ`+ŮüüPĎ@ÚMÓm!ˆIßAĹ,A΁(;Źś,2ÜŰúaŒ¤ăôđ’„+ľ‰˝š žŞďX‘żT–HŕĚé@bI5|4÷ĺ{úaÎ[`UÜđpœäŤĎ,-6¸ŞĘD+„áÍćP<*T!/´´ű(go‰Ńiĺ b’Iäţ•éřyę#Y6 0C† ńź&ŕ’"‹pö4Íu<Öó˘-C&™Ë2Üâmů5ý=ůiČĹyĄ”ŸłXôäń žĘp‹AżŚĂ/YźĆÇ,W2çÇ(łŇMЊŁ8ÁeÖ›˜h>,ˇ…ßĂŰó~ËĎą ąÖńžËÇĺ皝† ë2ŕ–ĄóBĺ „çŁ[ŰE8 Ç#r`UpN2\|d8ńJ K1ŮŸ#ŻşdČxŕ\%œLm¨šą8VQŐűŘfˇáěHů˝<—˜0t\Ĺtf=ëΊGš!Cç´hľ˜.Â_ UcŮžî˙Ż^ô†eäŹ(˛S$óďٓՏ'÷fďŇ|šńx"aŘmÔĐĘš|H—źtö(^ÔYč˘:™Óó˛×A"7fŤ]ŮîćŁEˇŞĹ†Źl%:˘ˆĺR×ţŁśôŽ;oĆHßAźůÍďÄĘ+ńéż˙$~ůËßŕ˙žűCşhWąć‚ĺřŸű6ž¸ ˙öĽ˙Ĺß|ô¨ł`)Ćvđą˝Pč"_Ť­r’Ě\90ˆooڏm&?nšq!öwö KŸąĽĽżýă“řř_ž7ž rţÝpăľŘś};~üÓ_ăoz 2š,>ó/˙­Ćá ˙€^ÜuXĎb:Qßçľ÷x|„şiěaoą÷zž€ýľŘb;`)‚hI3n•xϲŘŃż t’š@ýgĂd>‰ä3BzbŃČő%Á§° 3"ďYu+;¸;bSˆĆÇČ`ňăpşĺÇQőÔ.=Vó=6Rf¨ő.KyČń4ňމڀŕtîî)‚Odü˜d˜% ľ“ŸeôLbɚԨ͎šr,@¸łŽĄŠľ›ŒŚéĆŁ(R[MI2œ*.AÜ%c0҇ů• ˘šž39vD˙ją¸ţ6žScÔżáhőŤç`§9EĎáfȐ!Cg^ €‚Á҂ş¤Ă!†A|}Ď÷gŚÁ`ŕhňz˝âoů˝<ć `URrÍ_7—A˜Í:űş]ěgĆqš Ü!§á#XŽRŐ÷™°ËĄóMÜ2t^čsŸ˙7 â#ţ ::ć‰Pż‰pŒV¤HĚ"\"G†Ż48‘ ˝łłSźˇŽśŠTR ÖąxM 8Ý:^"qáƒĄáüí'>ˆüř×8ŘՅí˝G„Q5útnä4uEYŔ&΁•Tăî+căćx~ÓVÜ|ÝĺXĐކo~÷§¸ů†Ť‘JŚpՕŁĽąJxšm޲„BxÇ;î%֍żűűĎ#™HáŢ{߈̌8•Ă˝ů/Až"Ý"“{E8fsĂĽdˆX1ëAOďsâ“ćV <Č¸U• ôˇ”ž’×Ö4ŘŇĚŰĚ4ją{˙s؛AˆŔ`b$‹L1+úĐ̋%v/ů4Ü4„śšŞąŰ5‚]c{‘HOÁoś˜œm°\›šŞ!ĺčËdŕ$hiK#ÝK°)čDĄšRT§,f Pë*Q;FL劓E|ZBŇI3ôӂ‰ŮDPÍĉ Ą‘aeĽĹ ŽtkÚ҃hEs–t“Ž:Œ-34›„šÁËA‘“iÄr)L,᪇ÜAp­ÍnÇç.çăsą@ßmt˛S¸qľ4^EýkC41„ČÁGKhȐ!CgVĂŃ$~˛ů.o­Áš&=…é0¨t2ššýŹëőٍ śŽŚ3˝XnČĐš,ăě7t^Čét×ŢňęF˙ZÚÚđôcÂ¨B˜`W ­ôö÷ö˘ŽŠkV­ÄŽŰ![ěŘąuü• pÓÂFĎPř´Ă-§•FVÝĺ—WŹqzĹŤúź’ĂĆĂńÄPˆŻˇăôŻ\s¨ˇƒáĐńŔRšě­Ąv”/Npą‹řÁƒÝŽí‚c׎ݢzd2ŐäR8¤ŐlV„ˇE×Á,^؁^:÷źd0ť˝>QŽ>Âi{ö$á÷x\aÜ×՞™„Ć=ݝČBć䊖d|sÂűŽöf24qR÷âÄ AZ!Śß´Ş)F¤szN:żłĹÔˆätĹ>N&î PĂxÄMgÄěBŢLۧ!€Öp`{^„ć­Nđeů|g;›Zv¸‘Pěťýô›Ő`)ä`ĄßŒEŁąĘlŃsUEO=óŽšî*üÝßýž~Ţůî!›/ŕš+/Á‡ŢóÜôšűpŰÍ×áK_ř ŢöŽŕÂ5Kńƒü ”};`âŞ~*"’á™ĘBrY0a)âŔdĘŔźô™ëkBHg şLM‰}ýćwá?ő1\~Ó=řćAäŮ[ž´ď˙ŕÇń÷žƒ×›‘NgđŮ/|‰ QoçťföŹđbJ¤G‘HN Âß ˇ~˘6¤ŇQěďZGcFšŹ ™K#HsVcý2[žĽwčĄůĘă Ż^¨(•S”I"ŠťŰ@…ĎO n ń| Ú{IŮi?`wÁLýYe࢖Ľđľ,‚Ż÷EÜUˇĎO œ™Bž8;UÚŻ`l2u‘Ľ/A`Ég8ƒ|Ď8ŃPM#ç+ ŇMçˆ-ůľ–ň@\Ą/d˘cjčďVŕĄچ -­vä’Itä´ÓśŮ8=–ĐLç˜ső*x¤ †`ƒ“Y8bФä'RZŊ }/ƒČ0$;mÉłĎ[čšŰâÉa$S“¨´ÂăŠ!•ięßÝű…EÎÐ!C†Î†~şy?~ťŁĎtâ5+ځłČŐŮ6X^ÔYţa—Ú'źň>…KsöžňÁĄs]Ü2t^ˆĘ3ĐŞŞŞ—-_†ń‰I\rĺUşCˇ‚?+–--%u”pë­ˇ Ă-EŰ"ž ŤŹ8ÝbŘ"sŘ˝}"‘č´çQŮ^!'œ8ň“‰R6bn'qBHZ˝Y¸p!\••Ç Ďäçů%вcŰv‘ăK+ÇĆHĽ°N”ŒTşă$ăÉBĐFádĹÓ ÜgîWÍ8ÇK>—ĆbľĄmńřýžcŽ2ؚ CqO'Ň”D-4M-˝Žç†â<8"Á4uJšyœúţLJĹŮV1iÔ4—IEž;Œb+ľŮEŔŠŚy!ł°§ŽvZČ(¨tŒ<ŠN&“ř—ƒcHçó^2Ą9ä-÷܎˙řżďăţöĂÂř˙}ĺëpŘ|ň#ďÁ—żúm|űk_Ŕ˙}ó¸ě˘5ř_ţšČÍőĽ/ţłđîíí›Ýł4ö…#ŇGQ[ľ 6G…îĂFZw˙˜šdŤ˜ Ś"zű6Ąľ~"ÉItmü6}Ěk˝ nOÜv7üސ˜;´R~)‹ŮŽĆÚUb8ÝĄËękí,4bMĂ"T—`dj ˝][ą¸˘^“ K–˜đӞíÔßĹŮlUPŹ%Oó@&ŕ@†§4ŚEr<ľ‚OÉĄ&ŸĂÖŞ J68imî0cŤĹƒHgو!ś)¤ąć›ż{ÎS ŮdéAŹLpɍ—a"=Mß+áĂ]ôŢ0Í1N;,áŠKŤ°`Í"ŒŮSˆ|őTˇ@k›Ő\•žÇptć¤ITW,„ÝVĄ{ j Œl…™!8™$Ţš† :󺢾[úFqÂFźiMÇ˗>ĺdŕ–ľmčĎ\Ü2t^ˆÝoŰJ‰łY|ńZ uťCôP;›őô­™bƒf‚Œ¤ťďźƒŕȸ~L“aö‘1Ăp‡˝˜ĽUs~l‘KŤňĽ4Â)×â˛"̀%•G†ś YL"ao”Œł/~÷‡¸ăŽŰ űł°ÇÖĐĐ0Ţöš7`ÉňĽŘł{7::şźđ"Z4!O XQ[8‚+hŐEËĐ´r‰4‹ŽĘ¨\>äp#31Œt*ƒ}/n#WÖvâuż|žUŤŽÚÇąţŰ÷ďÂ{ô),6Tym°ňČŇž ŠőU‰Ń(ňdĐH™5űń‘wĐę“ć@d8†ľk𓟻đƒ?ÖŔŸÄíԗž6mšÄß\‹Ţ4­îż÷ťp‘‘|2•9Ą| ŕ?Ś›ř˘E EŰůâDiiŸąŽžQœS˗-™N˛ÉÇ,Ň÷ĂÉCŮCŽCĚô}_yĺĺÓýr&/pÖ\x‘NNKIHÄ{Ű[N¨­Ą?W阝 ęńqž$x¨œŻ‰a—d҆Ó9涇É…á–5Lć‹<ň0 "a¸Yb/NET^”FŘčy z¤‹„IúiNŠ´żœŽ­΅TĚš$°Ô“ bźӜścznUÓbĆŁüŢűŃoׇŸţč[Âóö/?öI<đ‡'pëÍ7"ŸWńŚ7źůř§1JPý'˙ńiŘÓaXriZÜPšt!Š4%ýV|q3hsj‚~,\І8˝wóÎ=ČerřŢ~…{ßxŢqďkj?‰‡}Ý]‘ÉđŢ÷˝Ÿů§‰Ë˙ĺó_˙/žđšżĂŚ­{fľ7‘Œ •Ë Žę‚N17äŮKÍąMŞ1Ą9Q¤ţ6QĘĹšëšh,É#!e‚úĄˇw,ŽqĚoYż+(ÂËă Ű$N‡ŸŘ垐 ŔęŠ6,í¸XŁ ““4^Ť°ˆrQŸŮ,TŹ\„żźę<účĎfŸ œü>ŸŐeŽftąňźđĄšXŃ>”"˜™Ge2‹çŕE]:ŽK|őč̢`vŔ´`"ُͣäý9D'ł4÷Ńř˜˘÷ÖZ<Đmń*lز)sšWÉ)łŽy\çP-Pâ“űáŤô@-  îńŮý› #™Šŕ[FŐ.ú7W,ˆëęĐ<ę[őŽĎN2dČЙ֪Ć*|ĺö‹Äź76:F×ŘAa𵠗 žő ŰgJéŔ•9É=ç띜Ô?Sč(v—!Cçš ¸e蜐t_޲GĐÉŔŒł%68ҙětůqśM\˜Œ+ąL)†!źĘN“ƒđ\âmčžŰ$łí…Ľ^ |D˛vEłçtˆ2EĆd…ŐYFŠtú„ĺÍšRé ŞŒ7źý-xü‘'0:4„;_÷Züěg?ŔE—\(Â:˙âĂŔÎĎ~őW^‹|¨Ű6n&@âCî…=XsíĹP“18.ƒ-:GdËZćarß^l߲™tú„9ąřó3)xF'0™aŽŰPHäPˆgČŕԐé"Ă­Â sІknöa9óÁ4ú&Ňh¨w žzz=Ƨ‹jqÝŻť1ţÇ_ĂĎťľÚ‘”MřiWw`ńÂvtöá˛ënÄ]o|ţřĐŁřőáż˙âŞ+q×=ŻĹřŘ>óŮ/b2Ĺż}éđŻ˙úř×ĎY]?ýŸíö7ă{ßů*ću´!5ÓĺŒŔ•ËîđYŒóô9Ü1ü ç#WčĆTdi‚jNW5}†‹Ĺ|Qmő XČ/_öfľ[Třk§=rËK â7Ώ3íđUĎĂJMŐ ˜ ą:‰ §`JMĄÖ[ŤËł×Wkž[˙†˘łúם‘ĐąŇ|e"ŕA˛ÁgJ†Ż=ˆŽ}SČ猍g‘!P Ś`‰‹ď=’Ď`l}ľÁ†X\A<‘ŔŽ:¤Ŕ¨ĆćMCÂKŹ/F‹%A'ŚćUĄ?ćŔ¸#‰ŁZ\CPB^ZÜHˆ,Ŕ’fOcš‘=ĐĆŇIh.-5Ť˝ěĹf'cQ?75Ńß2AYö64[ýŠˆ÷ëyÎ 2dčL‹âń8­ Z€  ŻŻO_ä,Mi••§ čsĽX —¤Óz­7E EĺʎzeĆüIç3dčĺ’qŚ:§tŹÁůSŸţŒ˜<>üábń˘…´şÝƒ"'§ŐńPŔ‹Hx i‚B~Ż›Œ'ELŔátĄ@r FgÔź×%Aç㸂ĽŹ\͉Ť\Ńäŕ$Čĺ1›ŕ&€°™ĄńÍT2rćŮM¨´)Čźϔ™$ڰz‡ i˝DÔܚBŰĺŇ146ÖŔnW°mÓ ¸ăľˇá@×ᵕ™ŠR̰9í˜*Z›ĘĐ ż‚ŞúzLŃń‰AÁ–%Cƒ&łÂÔ($§v2 e›› [ynÍ m˛é<ę¸"Y~#‘ YUô‡ŰfĆMŻŽÂŰnI":ćD&™Ĺ ĎÚ°ąSC•-†úGMřŘg\čßTDtʁ0­ţkvÄGɊŒäŠ=…—œx˙• j:ŽD'Ů"gľ(ź¸ňçĘƒČ U`ĽHŕK…‰Á:=ś ŤV€—Ł˜%řÝłœŤ ĆŢ&SQZőe‚Ďůľ$Ž€Ę Ň32ËOLŃAŰؗvX9/V6wÔ&öő˘śŚŠŔÖwP__Mţ×ř/˙Ls˙űË_@€ŔցŽNüř§żFĆťŢň&ŘŹfhÍópĎĂ AŞ{oź•wśŠüy/nŢ…ƢîƒÝ¨Ş âŠË/BĐďÇd8‚˙üĘWqŮ%kQŞŔ?ţý_áýů$žűƒŸĄĽĽďyĎ[đ˙ţĎ´ žűŁŸăŽťßŠ/}éßą|őĹÓíeˆ§˜ŹÂ›ł pđeŁ>,ŠöU†ęQ(ĐHEŃÚ¸\+2żÁÚUˆ ny%ýž*Ťć#ž‰Q{U‘¨žU/‹î¨n/•޸îʀH´ž~p7ŹĹ<óN‚[ô]ýÔĎnŹŰđ}GłĂ•lŽX żžƒaLt„PMߗ‹Ľ•dÜAŞ‹22ů,;ƒÉ*;†'Óř́.ťŁ—ŠŘ8¨¸„˝G1§ĽýÖT¸ŒŇ\G .ô˝?řť'­E\śÂŇčC[ŐÖxŠhń(‰Ńąi#C$ŐéÍcg˜ Â2Š4g5ů°SVĄ§řüŞ”5 ď­˘¤Ňk¸\hjh#ŘoŒ}† :;boŚęęj,4?°ˇëxi0NF<OŇľrśP<ć6\P$č´Áʜžlţ<ꈜL&ĹÜĹhÓŐ :ÇeŔ-C瀤>ŐŘ؀ńqN_-sř_>›ÁžŢQ„ÜVĚ[¸7žˆE‹hu<—G66‰Œâ‚Ă, ¸u6Ä@Đfƒ&†UY$á&cĄÎaß"çË‚*â“€[Ű"EÜSgÂ#ŒJó‘1`çiACu<–ij٠dÇĆqš%‹ kmHTž †?[Is~ŇĐ+RzXb˘ 0ŔăŒITöcďŤÁ|ą€ź*—źeóťč˘š~Ď Üe•@/B Nşo˘÷qh{~I…4älAYĂöź,ŞÚqXśĆPœŕm„BŒŽI ‹!Äš§čžĘa‹ĽßĂŐLcŇŻ~ú4ÔWâ×÷˙ű›sśřÔGqáÚUôśţöo˙Y$„¸]¸÷Ţ׉ąg׎]B’Ž9eőŕu7ߌ­ű˙ˇ]žűłßbœ€N˙Ŕ0.Ą…. qí5WáG?˙5žZˇzüÜpý•xÍ=ˇá÷=‚ß?ü8ţţ_ž€ŚĆ:ÜxÓľřÜg?;Ł_ýú÷đŤßüa6Ü2™éł™„—­$ÍpéŇô›ÂsAÍŃ/f“ šl‰t‘HÔďNŌÚ`3bŃ^ě?ř$ć5_ŠĆÚ%1řâFˆź…Ŕţ-Xľb-röü8ŢßÄ6ô‡GŃ7هW/¸&/ŤÔ–ÝÝ;1żžۡ?‰‹–Ž˜ŐżięŤńŹĘÁ"^ Ou"F†YŠŽ Ľb‘ƒQ„ ×Ětn(Hťč{sš#˜ÔדĐŇţĚf ôůč{ˇĐřnwá/x`ŚóĂMsaM$ƒÁÂŇţZXr\"yQią%*ĂIçK4ŸĂúB# (Ĺ8Ń˝˛˛5łŤ%rĺJ™á!ĂX‰ÎU-+Š}đ9](yr9•°˜9!CgGeozNÁÓëńŞžŠÂŠăƒ- ™LfP嶟–´ě}ĆpŽ č8Ǥ!Cç‹ ¸eč,ŞTŰ|Ž^73čw˝ó>ÜyDŽșÄZąr•p—]}ĄîMÄĆDcC˝˜Tňd()ĽÜG…BńŹ™őVž Ě Z]fĚ÷HřIO ővZův˜éâ]Eg<:§ U6Vno4Ó꾄MLd`žÇŠv—ŒŃŒ*Â{.ŽP0‘REřâ\•HgđĂďýD@Ł×ÓsVęˆť{Ö˝ˆ:2Ăťąb >š´Ě&z÷+b}t{&ŁH’ÁčĄŐô7ű˛ytŘLsÎC)‘ő•"{Őň˘!dÁ=Ť$,YĆ×ţ‡ŽÓĽâ“÷`ÓEŤŹ0¤LěĂĞ4ޤPáľc4VŔ÷“‘;wŃÓť„ů­¨n>?sœĚEŘր^Ż<‰šsČ3„%ĚJ$á}ŸtćPyźTľ Bź˛4(&;„¤Řƒ‰Ŕ‚MRK̆˝ˆš4Ĺ YK#Çšë“€2"<ŻNÁ9ęŮ*W~ĺ¤ß4fňżcˇ—_z!ŠŮ)üîwŕC˙[1śßţęńŢwż]äŔűîˇˆgž{^œĹ÷žńxý^QźâOO<´L@SC–.]„kŽž˜€L/˘ń„p7Űľkm{‡řŻşńJüř÷‹>ř桞ëŻť\x>ţË?ţ-žzvbŠ$>úWG–-D]m5>őˇAggđN›)3†‚î7ú|JyŽÓô*œÄ_!@ŁP,h܋ ŔMQ•żVECŔS›ĹE‹VúŹyŒŽďŢ[:~'IŞČ÷ˇŻwFĆ÷"é…ßßDmy’Ž™™nÇűžŔĂžGVÍáʋŽÁÎń šŘ‘<†iý.úŢdd- 4‚oEN2ĎqőœhžzAĄoŃÂciц^ÜiÁÂAĎsŘ˝Íj‚l:‡ÓBPI†;ěúŹzFčî @ýW!Ó>F ŃĆý=9TVŘŕsJHĽó954ą‡ Íę‡<ˇ…Ř MÎî_ł>öšâC˛^”DŁż2oÜNJŹž˝† úłQ&_œÓv ¸ŘăÚ$×u†^Ů2ŕ–ĄłŽŁT­=Ą8§PUUŐŹÇÇĘże1›gmwś´ĐcA5ÁŹ‘Lť˘Ň4ŃTŘb#kW$-śÍäŃć6cg$‹€Ý† j$l˜ĚcQ@ÁÃy\[mF“]FŒKRhA¨Î˘ÁlŸ{;rĹ|)çˆŢËů|ATAsYi…VśŮ;l$•˘ú ŚRÔůóđ8lÂhĹńdçúhő>C扝ŒÖůdʰËstFî—I&ŁçőËM¸d^•> 5íQüűúąç ÷]—@ْůNřÍS‘‘ý§NSń"Ě.4Źpá?LŔÚz5l-> ţěWˆŠiZĽwŔQkƒ´ÂXAzŠ2.}^É*U%Ľßś&ŔVQĎqARž„Öń–^(Ą|ShŰ,Ač)ˇUT6´h:ô*H˛đčâ=p#d;Ƥ˝§(ŢŁŠĽĘ¨Œšd2tÉng:Ąç“"FQ G?#ŮCçńǞÁ>ň×Čĺ hinŔ—ţßçxÁż~éżÁ9ëí´¨ńŽwžMĹ%pôäSĎMç'iki$ФáŢ{_Ż~í[Œđvť{ô’ÚqĹĺ—ÂIc`<™ĆÓĎ>‡];÷bÉâÔ5Ôŕăy>óĎ˙c“Sxßű>Ž_ţü۰X­řŸŻý;~ňł?Ěj/÷I>ŸĄĎm}PMüˇľčy1jĄ(@Z6›"ÜeG†úś ű0•)ŔŚĆŕąť`ľŘŞěŔŘÔAąâvVˆĎ‘Ď'qóÚůřŃĂ0>śŁŁťÄ¸Ě‘x6Šâ´/i?üMö  gh==™9JžYô—=á@âĹ šż¸ŞŁŘĄ˘{ŢIĽű4ýÝO7­Ä¸ pYlŠXHâ0@Á*šŘFNpJžŕWŽCYi{ú,&.R`˘Ĺ>MŠ„ť‹˜˘är&Ýë*ŻÁËE ЏĽ"kžč°KT>ç8D’óo˛!-™ű7OűU ŇcUą9ˇ 2tÖÄaƒqZöŮ­˜JfŕwXOč=u¨ŞştĚ*čÓŰöžÎń(-J[1Lđimpö{ľăSšâ~,GsƒĹtîĺ<6dčh2ŕ–Ą—MłVI*9’}°ĺUzNŞî9NBđ—[K}2ü´xžnź€%^w…hľ[QŃMĘBŸ+WšĚşâyx-fzŹâŰ]Šëoź _úĎŻá›_˙Šhď|ǛńŰß=ŒśîŔŕŘ$ţţţ Ÿ˙ě§E^÷şŰf%”/WGd(§M4ţÄŁĎÇĐô8›ó–€"Pupx›(@b1[ rĽ‘˧ą¤í2HÔąŃřŞmč،ŞĘ›Žwŕ Vˆă$˙šľÄ÷¨gٓtb'ĆL†^ýCű ĺ˛âžt¸GSٰ"%qő€éńáĐÜÁx§riű"0•”‘šJ‹űš¨ ˛lt“ŁeńKĽ$Ç\YÖD†‘đäâ"”Ľâ*’î}Í˙ăVč}#ÓůŁÄłłšËŸ*_ĚëЕŤv ˜UýŤ¤K§ă°Ů+ ¸eȐĄł&žžšM7vLáÍ´řrEzcď(V7VbC÷" źvŐ<ĚE<źnœ@$•c÷źJě湙ňîŽó/nŠĆÖţq\Ř\}Üí#é,śŃąX/öáž‹ pgČĐš.nzŮu¸˝}4Čő‰żú¤0jŢ÷ŢwaůňečęęD6•„Ĺ„EѐNĽE%@`|ąoąÚÄ ='InŹ?K(„fď#őf<>•ĹÖ´„şNwŇĹ˙ť=f<™Ń°3Ť[B‰|V¸ řˇ7;°9!‹rö7pp’Šŕ’šůvŒś+ČîĎÁnš;”P¸Ś; %9ý_žŒI­ü§ŠqÄT\vZÜ6 C0K¤•Œ>΋ă&ƒőîFzăÄŹÔśp Ń\(N [‘ćěqg˘ vV vé$şpFx]GϏ:°żĘ‡ŘŽ”ą"Ú§4Şd44šđ­çذ§çšäÍěxćQú3Âđv![҈˝f/őS†ŽŁ2Ԛý”Ą?CŹÔÁ‡î•Ĺĺ’Ç ˝­ňP§éšđbO Î%՗+˘VÓßË@Šđ˝xQ‡âąÇOzŽ-•@şÄ)˘4Ě SÔߏTú+ł7ŻcäÜZża"ń„$˙ř鿥ŒO>ł—Ź]‰Ÿţü~Ź˝ô2‘‹ęmoyŚÂîŹ[˙<*ŞŞDe'~­šĽ =}ƒ|4ÎŮŕt8ątéRüpËfD"1W††qűŤoÂoţđ(ć/˜˙úĘW°gďxjj*đ˙žđwxŐmoĆM7˝ ßýÎw°rŮBźîőwáp3Q)V͖I|vY3 -UŚ1?݃z“ŮFŸ? ö›ł˜č5úüétO/ZĐ ¨ĺvúi^KŔióĂíŽĆT´á‚_I ŽŚ`ˇx‘ĚOyČ/ZŇOrŮŇ*=př˛>‡ËU3Jg†TŚbbmö ?]1Ę"nľ(rBZ9ĎVQ`L*ĺSĹü-Łä:'žcŃôœ§zm‚ňË:ĐRő˛‹A’t¨Ć,{Ü*2Dĺół rşqĆ/ÎCڍź ’‰‘’÷Ą!C† ­iŞD4Ă­K[ÄßÁ-!|hwš ˆUšO"M‹˘W]ˇ™•9gyaqôF[…żŘ҉f˙‰ŘíĘö:qżŇm§Ç§7—˜!CgJÜ2ôň¨t{řs‡{š”ľrĺ <ůÔÓbž•H$ů˛ű÷ŔČĐVŻ^…ν;10™Â’ů­Řľa#D>™łˇmvČŕ‰<’tąţF›żHŤ¸ŠŔ̏čÓÜ×R‹ĆĆ&Ř\.Q2˜+DýV¤^źÚú"„˙@†‚Šd–`×<ţţƒtĄ×°˙6‚K'yą.•s˝Č˘2XUe‹'ňj9؜TÓDľŇg‡”ÍŔgľ $E°-äiŰj,”ŒŽŒáB‡cO<(Œ°ëęý0ĎјNŚdXˆA)9'Ƌ.k%¸Í4 eąáĄŹŁĎ5ż ańšœƒž8(ckwKożq"cэ›`ŁœĽoYqÚ ]źʂj\r ăę\ýÇ^yšţvŽç iŽW¸tO™ĂKÔtď*M­c&~Ě÷‹E=XQQĚ%ŘÍř.šçźREbŞH0Ÿ)„'ňÁšŔ\ép…öĹ^<źQ1m'Ŕ@‹CČ9ÔA>NHľńŚkŽŔ}o{#†ÇƐJŚńšý"WYLNNb5-vŹXľ ==}Čd2xňÉgŃŰۏ ÇŞ+CđűźČPťkŤCŘH )‘HŕĹ_ůť:;;as8Đ@sD]M%<4VoݲMäjdϰOýíGÁdfѢ…řÄGރz^ˇ?ńŠĎĄŚŽ–Ž{ÁěĆőžšËhŃEa.¨Ľó ݡŇń‡ Ö×"“žD,ÚEFŽ>ž™L6Ĺ8Ů~AË؊Đ\"ČUO°kéL˜XĄCîcˇîZA*Z=>ŘL4ÎŚct‹Cš¸Dzjƒ6ý›?źŸ5Úż†ţ -™U‘WKŚŰ§>ꥤe&<žxLÉkÓŢaeO0I+M7ô:Wkd?.•=ÁJűçﯘU+{˜éŔTŇÇ"zN2îÎÝŚĚČX,ÖZćÂź(‚Ŕű೔ç5qžň\AűËfc%ĎĺšéX=cȐ!CsŐ3]CXQWu‡qikő ˇwӂňĽ­5Ř3F4“ĂÉ(FŰsĺńŃXúxSçâÂ/Łą޸ş;'O¸={níҡŰ20NvƒÓđÜ2t^Ȁ[†ÎźŽ˛fž†öś¤'+Ĺ3Fí{ßüFÜyçípb-_ž\ü]TÇ›.ž^e^źxÎśž*b-[EţůoţN‚Fké"{Á‚xć™g„'Ůć/ #BC.;‰ŽÎ­´ă@>˝V˙äV[šž/dZYÉcÓăY‘ŕ7PIěćš-Ďp7´U×ÂĆůODVI,^™Ÿ?lŃ,*œf¸,2Ć#Q„ěv2Œd2Š˘}nŤ"ź¤TZÍŻŠŠB6“ůVd2l5aŕÎ-떍x|!ZÝ'PŐAl1ç"›$ŁCɑńQŔetź7^7ľ LUţ•Áfüí˘{q@˛ z×:WŹÂ Š:Ä^[y žŐ6†Ď˜šqpóŻ ă†:œ”Ř€ĚĆřł–,• –TŽAOĎúmKđúłÛGŸyvÖs“ Ż}Ë[Ĺ}3Ua$-m‡6ýJ’ޡ Â;g‰đÖiDy Ľäń‡NŠŇ­Ł’$ŃĘ褼ъŐ⹆†FlŢ˝Wá|‰ECßtß}¸úň‹ńôćÝúg P媨Á[ŢvŸŘń˘ůóđ܋;Ĺű&ŁđŐ6âu÷žI—ľŻÁS›vˆöě 0fuŕÖ7žA—Ť×`×pőuŒîé€ćŢ÷źaßÔ|ŹŢöÁţžQŃîĹ+עo,‰%Ľ…†§7îBNvĄ@ČĘL픨˝#ńć/šH÷\š–'•<ŁóąÇ–…@–šĎĐ8;ĺĽ˙3IzRtłÉ‚|.%źšŽ T„켤ô…éoĂlq"ŸM ÚáÓćF<“ÄX:"ŽWţśH ŇĄTE°{öîeÝĹXN0éć[^ƒęŠli˙=oz“B‡ÍŰ:-çŠ)Ď"wĘ!Kţ_ŞVv›šáŒ]éáĺůţŁ ž/žsř_u] 6íÜ ‚ /¸DŠ˙_,Ć:ŠÜsĺ1OďiQásëî=čě(írvn5wlCňXžĆčhȐĄŮŁáŒű4nźç’%˘ ĆĺŕüT'†ëËë+ÄßE5q›Ťxˆş{E›…äŠë'“뚎zý}ĺu'ܞ=ˇ.oӝ.iŠž.ÔeČĐš.n:Ł:şĄ4óU”.pĽ™n'3.X˛HÓ`kÖť•$é¨ĎŸ )y`€.¤+Ó´Ö bbj‹ęâ(Lý śMŔëƒY+"–0EË+L¸˙,]iÂó 0;ĚÇddb*úe|é?sřţ˙Ú°mƒ“gޟGBGСYâ:h"ÜQĽ•7Aś˘™˝§|pŮl(äóČ)váa`Qô¤ŔąÚžĹćƒŰçF.“A:aC6WĐ=9´š÷Љ –K)"OűM‡eäFűQč—Qаvžޅ~(óźPNĄë‰UТ:˜‚ňľMp„jኈ`éݫቄ!7ľăŻW5a}çŹÜŐŐ=“–V6źţŒĽé^eCO¨ š¤ű'Üš-鯕Jůqž~ăż{ôą#ś5{|8]:ĺ ˆcŒŰŁą8FŸ[C|V‚ÍŔ†ű„WŽ"ŠZĐŘâőé^C´ÍŕŘ8ÝĆtŽᏠoŔ+ŕVžyäiZX wq v‘ “9œ1›şząšłWŕ }ß2ě´oYx$ixôŠő⾲#ŹÍé†úqR4ś>öězÚ'{,I"1ž~_Ö=“fÎ_t“…ˇ“~ÉŇ_óôó şÇ[ZƊ;ţüšôÔ!P$™Q>ň9†V6ôGs˘ĽUxɆ™,ť(˘ŕ-ÓsđČH˜nϗ€›ž'“Łëô°­œŻ‹îŘm‡Ş\˘Ě§ ‡^ŞĽ°ÂrŮ­t_„jGÎů'93Ký“Sč_÷NVOŹßxĚךËę ˜oȐĄ— ™‹A,ŤY™~búţiŻ[ŞĽňœŕ°˜ší™Ú °eč|’ˇ î­UÎŁ!aĆEż6ËĂD/ /‹lIxĄL“É$ŚŚÂ¨ŻŻ{YŔŐ\´(_Ä3Ôś™4zż‡`K““2l. á„>ŞÎcgĚ sŽŒ˜‚ …&Áڐ„რęh{%Ł˘ŽŮ+ý2oy•6‹ ŰAPËćŢŽœăɐڒ`ˆŹ˝ląw0ŻË '­‚GâQ‘°×ał čőŠU ţ~N‡Xuçj`—ƒ@WŃń(’ą¤H3‰VW‘;~[œŻšĹš Ł5ĺߎŚQęW›‘$]ĎŚ{‡•ó ęK÷a-ýFJ~MÚŒŁ•afŢfĄŠr|Ţa߀VĘĽ–Ş ´ŚďÍřŤiŔŹÖ`:ĚŻěɤ/řh`‹g$ 3ÍŤé–é›čŸgĆ1ŽčOIR:ź˝RŮšNšŮLWY<ĆpźŠáTÁ֙Ö\ÇzC† z9Ĺ0+‘ÍŸp;ÎÁ%cš!CÜ2ôňI’f\ř– nšta-Ëz"ڒţúo>%żůÍoÄę VaßŢ˝"$CţäpŞ[b^óIĆŞf=CP¨ ¨Eńń,ě*­ńgeX9˘„ć%›ƒÖĺ3œt ö˜ŕ!pľ°VÂăO19ĄÁlŃDΒ‘Ą$Ź´Ÿ7Ý-٘ÓPsІNmŽ+Av †ÁkčE5/běEŮtٌV-„jo^‡6j”VL‰p=ŻÇ‡|6‹"ŃŤD2+€W>“ƒĹₕśľ;ň(P?Çb)Ě5{eŚ(cĉęy DţDí%YČ9¤¤<<؈×]ŕĆţ ě™1 ŽĄĐĆ3Ż6As"[HaŸ×Žđ“¸iÍ0žŮ܄-›`JČ{hU,ЀSUρ=0šCěëFŔçᘏńX)~îP5 ™ -ZpÜýp5´T* Íá9‰~řa¸ÝƒzYćd2!ržÁétŠ÷pĹOž‹şż)NpÝŢŢ6kßťwďÁŽ;pĺ•W```€ú=.@š“ŔŁŮŹŻŘľ´´ŕÉ'Ÿ$ŘŰ ~: .Ď ¨UŽTĆśü,Ż-ƒ[ý9H:|áŕ(ŻĎ4Úý^Mhř4´bL ŔôÄ<śu]u3ú_÷y~…ýc&Ċ~x3#âź4)Ч…U ůy~Î&ĆÝěôߙÇŐk—Rڏ8×-¤Ói˜čÎĎĽtŽ”ö6‹I囦Íř{pĄ ľJ÷ľŇ}ńK+A^Q‡OÓ MbÖßĂŰ3ei3ˇ,ő­ŘF:ľôçĽçp$䚆qĺŰ ÇŇéŕMýQÉŤJé›Ńœé­gܙőä!oŞ™Ÿź<˙Îěň2đŇJ€púIĚ<ç$ĘéX:Ä4k+áP¨âš¨Yßů Çňkôú3‘ń=:Ă:rÉăô‹šó1RůÂQ§~~ŤžűlV}ü†!CŻlpËĐYÓL›lú’šta)n˛nœKŠŹ—öVkŽšż˙ÃXźH7â(¨úGĂp*úúú_v¸ŐMn%™SťčďP—„˝ť ´˘ŻáŔˆCŁzŇŰÉ Ő#ŁET˜ŠhöJ訒a‹™ą ’&1[Áy*† €}őěŐEF)A§eďœŰtĹ[ EGrľ¨ŇJżÓQń‚1>d2Y‘0™óť¸-VQMËbt|ŞÉřD„&J n§pE6ÓŞƒDęđ˙ĎŢ{6r]gŰď ˛÷śÜŽŢ{—%ٖ%[Ž’‹\ă–ęÄéůä˗fÇɗÄ-vÜ{•,ےŹŢ{[IťŤí}—ËމŽůď{Ŕî’\<4 b0˜3çž÷œs ™…%^ŢY‰Ç^ęÄř’ l~Ž ĄÖz´ö5":܄čž&ÔčÝǁ 菄ąůĹ#˜hđcřâ6´ÖáíK’xúP+ză1ʌŤßEu:Ö´ŁŁňŘÍVKk+Ç"đŠóŽŹŹŔx(‚ŢžŁŸDKS&'&01:2ăvřťĺ5ôF'€ę=@ŔŇĽK•uX‰eľˆ¨FŸşžşaρ6nÜ ×eÔ#ž(Ty\ށR[ž|9ZZZ0<<˘„­q%ězuąě˝{÷býúő:叞žAš ďNź‡ŹH‡0`d6ę­ó€P&XZÄtQ副Ő4ÂßݍvSŮÍ`#qx&‡qś9ˆmę`~]+OUÂ.đz%ŞÖŤß°ĎëĂŤŞżľ1u_\§ćoUżă kVcëΝčRâ-…Ú#==xmç.\rŢšQśC ś´O˝đ"nyˍxĺľmhnlÄ uźźu+jkŞuM­žž~TŞűăągŸÓÇiEM‰ZViň)YÉśŇ\°Ĺ˘d**ظ’éČ-ţÁ‘ٛ­Ĺ-ŘăÇNí#×ŐÔ[2űM]ßttW*ўœb×Ěߔ™ŇˆrÁT|Y*‚+{ťöGn[w(]N›mŚţ5R˙:ŞŸĽľŠÜ6ŢÁĂą˝Ô~2EÓďpÎJ§°ŸëUćšLŤ8÷đˇŰPD˝™{´BťÖâ‰4˝ůĘÄČý',$"n ‘Î}€~¤Ň¨ôdX–G5ćM˙ÔĎó­7˝7Ţđ&%XóN>ĺýzŇŠ(ĆŐce‡z=ÝçÁÍ˙8ŽGL$ëÔy˝šŠŐŹ}…i¤—™Qh°/tDD;âpŠűÄcdÖŞ›úŘ˝Ą&nŁĹT‹UX<ĚwWžßŻ9_Fˇ@Ň64Ë˙pťĺ>桄ĆáÜ;gĽjléˆŐ8÷˛`˘Cܢ1ôű‹űçÚR°Ä-u.ßčĹPÂÄp4ę¸aŐčúiÄÄÇ֛80h`Yľ1ӏJ_ŐŞŃQç3˝H('|8b€§_ŠŚ‘¸ą¨ŠG>,Ťů–î‘7Ő1ÔÔŤ†k}JĚň+¤ąŞZ‹ “jěڋő-­8¨´‘0&ŒŢÖľžŠ ŽNbęOŠJ†§đ#ˆÄ’Řł˛=Ťšąż˛ ‰ŞzT+o2ŽśÇş€‡Ă1 úęŕKL"P×¨Ş žd/Z'ŸÁî‰$vĆá?¤&_ćIKѢÎĆo„ÔőE9Ăßş×{lI˝eNýxx^Ťî–[˝­ÔĽ[.űs§ŕeE*YTML š˘ĄĆZlR÷ŕśmč^šɉ4/ŻQBöÖŽ]‡˝Ý=˜ěŔŤŰśëőž|ţ̆{öŚ˙~0UœĹÜs0–´ľ˘­ĹąÉţ%šŽóą#ŒŇҒvh ٗ)lśde˝ŸĘ łŢłh;Sžľ eGtĽvČ(Őő]8|ô(ÖŹ\žţ <::‚Ó›kug€łkŢš•ŽŕJć~OME™ĽşL¤ŽËqŽfś¸bŻ9…%˘9ś:Ó-Źśšlă)¸üŇKő5­ŠŽĆç˙ë?­N$Ă`ŐČ0&ŃúŰĚxŸQLޜ*"ŸL][{ýŠ8ą\({ŽŽýŐI@1ľŞJ Ź~?ŞUçÇś]ť1 M[ă÷?ôééUiżüí˝9ˇ|㾯ÁĂGpî§Łť§÷=úxF*lś¨Ĺ 0UˇPěb)2S:–|Ż‚0żĚtÉ=(,"n NFz˘Ö´ą•„ÇkEx}>$••¨ŕc˙ů‘ GD‘P=ţI堚‰¤Ž#eęl”TO˝ÓŤ1§ý1§8{gěáĚŁ‘O[‡Î5+Aéĺ[jjó+gK \c&…,jš?Ůl9Ô~OR]§?MZ-ڊý&XŽÉîW˙Üů´Š°â=żFĹý¸‡ăX˜şśę˛łŹşÁbGAP0ń)ń-Ž˝jVş‡Yӂ1um÷Şc ކ&GNěWŰŮVßĹţA$SĂŢ'y ľÍđ}獨üŮ÷ň÷ Š–Ďxh‡UŔî1t l ]‰eüžĽŠuěQg]Şy;Ÿ‘@°zŐ~ë ~ “ÄŞ|đď=ˆHň0†}I}ţ?˙çôpöůž•ÎďIöˆRÁČx™ú۰ ÄSŻŇŠť‚}ę~ń+!2 'ŐR‡×ďÓ÷ÁĺqÜcŽÍ‰Q¤é)ŃŇăŒčJ}ÉauOôőŕŚU&žĐۀк“Ń–ˆęÂx}"Ţ*œą~=~óô‹h¨<öÁfKwoŸžHfd”ý’ęq%0§˘śŚ ą[–#apޞ”#$ÉȘ2+o1UŇHŐŞcBÖŁĺSö*Ŕ{ČŢ}j[:ҰRúěčŻL2ĺ:çž-qËLĽIŚŽĹĚ\+ăo‡Č•Ţš‹đĺ/Ńřd(őˇ6•]FZľľn#Ó˜ČxvŘŞ›™1 b*ľqęŸŽ&‹ÔNÇ''ą´˝ !ő Ľ¨ĎN,Š\nâ?÷ŞďÛČßÓRWS‹•Ë–bŒ%uáŹÝfŢ#‡ŕďɎ6(ƒ’Ć)ú B9ŽĹńěţ^T'uL9Ă'w4ĄšzöĎí##đ+[şťŤšjŃQk˜kß+ł Éa;ĺžN4"n ƒm誖a׹Ó/7‚Ӛ U~Žäl ňŸdrŞýÄ|@NcƒÖTČq¤˙Šf~tY0Őż­áô>Äů™ŇĆ&SÍĽ>E/ʇŔ.ô'éšt‚}:JËTÂV"˛~uĎxxďř­ÔD¤ ĚŽmdŤ\℔ éßB–ă™ú†­¨?Nz@ëź|i֟źń~źîÔfüB9ŨÁË;ŸĹőŐŻŕĚsNĂśžvź˙´×đŤ]gé4€ö:¤#7 kpQpÓi…¤ąž^ d3×§›ů¤Śý‘ƒ)[îLK´Łž˛WOIc’ó3űsÖoÜ´ő5všyÇN„Â!-ě0ĺpÇX8ý|ą—ˇëj%çA*J+őˇWm‹fŢg \éTKdXZëéhąôQ;„3ë\3ŽVjƎMŻb\ PMxň™gő –¨“ŠÜ2~Kś–h]a돤ژ3bË~oŚţśt/3Í5sÔÖü Ľ €ĺ&l‘ÜţKý=%gxŽ˙ě7węH­ťzU#űńÚŠ‰Č| ąŠĹOވVĂĺšf̓ ”<ő\Ś0‹'IŘ"KęŞđ“wâ’ŐK´ĐEq‹ŁŇłl4jůěö€0UUUy;ÖmŚ ZyD.ż„ůDÄ-aţH…h9okVjNJĐ2̄nŹÓ[fyƒ‘(SGéEŘSŤ[Éh Ők‘dŞ\2aEpĽRTĚŠ\MéDéÂt2űvd…Ý#Ś‹Ĺ[uéx_x>ř‚AFęeW ¨ď!ƒľë<žtô–š)‰Ů™Áöž„KžŰ´Ú2@şŽšÇŽÜJ [ž”3ęSUJ´­ŤĂKřľ‘ŔQ…3: \´b+'n‡yř!ěkŐËs$PĂŕź3ÎĐÁ¸rxuژ –utč"đĺüÖŐÔ ˇżT˝îÜťO/wœgçŻßí×h§žŮ—Ő7’Šä2ŚDsš¤•)jŮď)nMĆ-1Ĺîôv c*ĹŃ)ţ8ŇMä~Öč5ě‚ń†c˙˛j†ĺgJؚ>?[°3ëŠ´AőĎs›^věßpš*Óv[á2łĂ˘'m˙ÓłŽáÁ ‡ ^öh*Ňo&ěď‘5ÝFÇǧ}Ž#Ŕœ÷gŞ>áô_ ¤V*¤ž‘SţŚUÓÔúžŒ‚î7A(fř+Ž­đcx2ŠáPÇĘîţQÔ¨ŽĐM‡űqůšĽz(bç|!|6ŇĆóu&q+}eÜsŽĎÄV ˆˆ[ !Ľ{Ľ#I8\;ӓĆH§úÍcęřfľb*­Î4ĘŹOi‹O[Îţh*űӜzM-l˜f†澕âĂç¸Oź)+}Ů×4P(Zě ÇűŒô¨ô+Ą¤ ú˝¸°łC=×UÇRs-ŽF|]ÔľMUA-’ńţŕČیڲŭْqŻAD-áÄ!▰pŘ/ť7\CS7ÖíQ­ŕłr×tي#'Ć|ZÔJĆíz[Iݰ˛kŻ$“Sw)8ׂ03SθÇc; †ž'ŇŃ:>+•×°ëlé×Ôh‰ögép‘)G#cžP2Ř pgĂÍ)jąaî礞w_jP‚ÎŚjœŃ\‰—|QôĆ $WöŁ˝g/†&q°ŚăžFÔWúĐ=d9ĘcŞ\™ȁid6=ý8.rHQSďu¤“%!ĽuLEgév­túŸ;j+ľ5‡°”š•Vn˛äŠ´Ŕ•śŃIéÚXŠuuúbśj–^Ît=/;†ÄHíÇ:fëč\.fÖŤáňŮÔ{—F˝{çSďM—żÓo{tšPZO݀˛•Ź/éˇěW’uĄH×u|‡Sm[ŹßP(ÎXւ㡱*čř{*ľńx„­l1ŮȲ§Vš˝XTaţqK8AXÎźi‡Żę(ƒ$<ڏX*~ć#ŚÓŻ’~ż­ĺśŹ€­¤ĂÓ7óŽ(&ĽFFϗţÓ.?%pYQ\|u‘gM.}˙éBŮś“/ÍľŇÂH…šşY6O–ŔĺK‰Z~6Ţ}~˝LďxßÚ3Ą҄Ç[’UCˆTůą1ąĆQž„1™đŁX˜Š=˛“÷2SÎ9/a˜éČ_ű6ńŚcm‡@a \Źse?w0“(cflĂî8qęBŐ<Ś]\Ž(°l1 éLüi癡śĺ83}S˙S4sž‰‘őŠ,…Îą9ÇżÖěĚën8݆iŚ"ߦń•ZŘR÷ˆ_¨÷Ś…­tj/Ęú˛lQY(.œéÚvJ˘[#ŰđHĂZćÔ=fÓ'ëcÇóXîCažqKX2\ďt-“”ŔeX’ľăᵆ(g1_Żí$=ş¨aŇ. oI•5§wc›Î”A(-ŇÉ0YOť%ěąZńiQX—OŽ×ŻöHŠG:˘CŘJGm!sóBqc7âěơzRÓ^úRWP5ÜŤý>´FĂH(ťW,ŞíIPĘ@WoŇ.΁&ŒŒhœyľœ†Ű߆CéÉsÂJÂD"eë­âë)ŰoG;śř’ŞceLÝ4veŤ¤áI/‘LMŠ­ c @7r¤ÜME‹¸‰AÓĎ;é؊Že¤Îeúe™•ú$Ł‘`fŻad.‹éĎ]ëˇăÝÜö—‘nhŚ×L˙m—ˇE…$€\Äćóˇ4őóąí›}ć-ćz´KaŮA-üVdcPu–ńńÚŃ[Y–s4E@cĹNşČÄ´Č-kň¤….Aćžě›áš%÷Ÿ°@ˆ¸%Ě/Ѝƒœďíyt@“)×?ՋJŃËŁ„-Fgą!ćńŚcЍ-Ż™*-œ-jezé„ŇazĂ5#r Ž, \đX°ÇrŕuϙדŮk–QHŢš+#˙{ᄓ-:ŘQ\éxJФhĽęʆ2ĺŠBVľjŔoŒD0ŽŚINŃ(Âą˜.USB-› Ŕ˘Ĺ.sZt؉Ž‚M ôpťƒlM˜[2 ‡–ż`L‚ČWŢ ŒbŹP÷BU €ę`PO•j ęčFŸ%z1Ľ;u/et `zƒLŹdńb¤üFçŤ'őüó2 @ž‘ŠteԖnĚ+űčKŐŰbƒ‚.;–‡ë0ŤB}UócjŇâëŚ"rtׂiN „„bÄufß éÝTŞ!óLAd¤–-pUQÜRݜg×ŢňŚ"=ŠíŘ6Ň# ą˘$~‡Ż3ŚGmÁţ=xEÜ„ů‚ľ^íűĚîtËHKœulH4Ľ0oˆ¸%,Ď!l‰CQÔ8ëȤçY¤Sa§(Ś˘Tt1ů”°•`ÂÔçžTJVD}Qó)lĹRÂV"ՙ` \ć´ÎA(>˛­—sp¤„*6˛ěÁ‚Šč-[䢸 ¸•ŞQgȐE€ŒH7k)˛âŔţœuˇŕˇh˝^üÁ $#čéëOŰ;‹ĚœäœPŒá˘frbCĂŁ3/x˘ĚÂ\ý> ÷7Ógg É0źú㽖ŤîVzuąÂ<#â–0˙ŘbŃ[ů.#UƒËăązçR °ĚŠ˝ÓÓ3"ܜŕôA(—žáöšát˘U†če8Vqś\ˇ-%ŮE“-ßÔľ íT,jtDžÁ(,ťžŽ`a_ ZŒčŠSÜJMşUŞ–ĄłÎR6bE…‰Ť…rŘ2[ČŕßśXe× ł.Š˜šŠżýK׋ImÓŐ(“Yq“ľ0•’hşÂ‘„+**1áç?‡Đä$bшŽăšL&,ŰgŰ@ә`wœÚ~'Ą|Iťˆ†ă5K¨Juč4nÚÖ@•UU¨mhŃ÷˜ľ›žˆaLšÝ„.A˜DÜœüŕĽĘ6ƒé˘ó°…2#őĄ™^Ę4͝&Ššâ˜ĹČ ĎúLgŔ!ZšErŮďÜËN}"”šD{Ñ:•L‰XŠ­bŇÁt_lČSéˆńTJ"ŁŽF]şŘšt%Dú>HýmŘ5ˇR 0[ܲEŹ@ŞÖ–’čsDm9 Ęťî BQcXЉjţř]WV˘Îlԍq [ńxĚu[Űż¤5hQşě…iÄ ¤Ĺ.1B9’éf:kdM•¸Đƒth[™ŞM¨Ţű|~KએŇ÷ďľě´Äě”DA˜oDÜGô–ëü”ŔEě(.+S‘\)Lť1oN [vŠŽ“iťŰ*”†1ĂĚljZ¤–őŠá’ÎXř…bÄ)bŇ&˛AŸdă܎tMEoŮ[öŠńT .ťW2•Ѝ'ťžaÖH‰"r ŌábuÄU*ËăHOôŚD._*Š‘éť~ťÖ–#Ęˎڲ.cąK8Á™)ŁSŁÉf”§¸Ż>ço! *G’vś/™œŠ\Őśp*E{ş°%6Q(_Œ,?3#⠙Q[éÁlt§ž@@ [ŢÔŕŮQ[ööľđažqKX8ŒĚôD’Áe}f‰VSłlĄkŞQçśmѲ„rdÚď8; ËČ\rš¨ĺ\6ל„˘#ťî–kŽ”đOÓT56ŕő<őˇłŢ–śřšjÄ%lQˑvăš%9ĄqKLGnY3­ZKІ”ĺŹŻĺwüm§#ڎ1ƒ]ąëÄaŰÁ\öĐ*ea}˙´iÇg:ޏWŞć śĚd:RË)j9…-ąƒÂbÂ0œYٓĺęIßOFJäĘ(&ożbJäĘšA˜cDÜN()ŠdšČ…)QË!t9ç;ˇ%1ăBYáędź›>ßEÔĘ\R(5l;i8:<Š4D–¨ćŃąT-śôH™ Zę5‘jÔŰäÓŁ#:^5. 9ąŚB1’™A“)öŰľ˛œŻ>;ĘŔŽćJÝÎŃÓŃZpÚűYźLk$k;™šŸ-)ty1%Žą1žąĺ¨ł•KŘ‘K(gÜ: ˝eLŕĘŽćšśź‘żć–ˆ\Â\#▰°Ć4*-pٟ‘Ë^Ú1ňłי‚P&Ě$r!§¨ĺž6ä^)aœŃ)ŮW:j VNÂNC䲜¨•JE´‹ČťĽ"JCN(fÜb:-ŃńˇáHQ´ëĎyě-;˛ËąL5Î ”.>e:EŒŢJf\ühűg§FŃ2Ľ;+b+՚=~˘ŘEĄ 1ŚůŒSŠ„n\ś˙‘SěrÔęrŮa>qKXxœ–=ËńqF$WŽŐ ,¨%~ˆPJüĚ/Ŕa0fłŽP”8SoœŃ[#':.=_ ZžTšĄÝŘ7]"ślӘ̊P“)” n\â–aL‹ä˛…_]‹)őwś°•˝M×H1ᄓś….b¤]‘Ő)pQĚLŚ„-gjŁ[´–))‰Â"&ťNVęMŚČĺˆŇ˛íiś°ĺ&Š9ˇ/óˆ[Â‰Ă­Ç  ]9Öu[LƊ|Â/Ž}]Ąt°ÓmąË¸tcóůššl!Ë.ŸK̒FœPĘd QŠ…H WYóíĺœÂ—˝ IG,^ÜęmŮó8.Ó°l!ĹĚ´ eo'K̒Vaą“-ň;Ĺ.7Ń*-tÁČ-lͰA˜+DÜN,NĂ6ƒĐ•^Ěm]AXdüë—ű¤¤q‹ŢJd\vCŇŃxł…0Ýł +5g&aKtB)0-•ĆEŕr‡KT—ý™›°5Óţ„3zËuÔl¤~iĽËc-§çe‡Ăö‰M!Žőë0=’+; Ť aː¨-aaqK(fşŇ‹A„źˆóPś8-KBOę˝]WËţ[ĎNEpŮdGÇŚŠ‚PLŻ“9ßH‰ş]Ů˸ĚsŽ#73 \éůvŃxĂ!d9„Žô<¸‹Y"p 匛čdd RŽ™˘–ósś„ˆ[BqâfĹą„éˆłPöd§á8#¸ěĎ ëMćŠv]{žg„Wö¤!'”Ž¤”[DWžůŮëg&œxŚŮÄWĆr‘‹č„mcŞhźmGÓöԉŘCa1P€Ŕ•Ql>ľŽá&zÍ l‰Mć ˇ„ŇĄPC(NˆPȃ_p0“ŔĽq‰âJ/ëhđeDnĺˆÔr[VN43YEc&Ëĺó\Ń_ČńšP"p™9"šŇóľeŰ:Ű~"ó˝ ,B˛‡iȸ˛ŻŻ"l 'ˇ„ňCŒŚ eˆ›ŔE\ُě÷.ëŚ×skřeo‚P|äű]ćkHĺތś%7ÜżoçH‰ůĘa.óaQ§Ă+ű}† ÍľÜÖ„ůFÄ-AA(˛.=/őšQ‹ .é59œS×‘Ç Ľ…k͘–3fą=Ą¸płaÓR‘˙wýłl§s}AXŒłšRo _Vć ˇAĄ„Č%JšEre# !ŁQA( i**zĺ[^(nÜRm˛#´ŒÖÍ^_‹™jć\rO ‡ˆ[‚ ‚P‚Ě$rŮäťÜ4Ą„˜Mƒi6őş„Ň#§=Ě#tM[FěŸ LgۘĎvŠ]ˇAĄ„É—^¨?w™gΰ-A(efó+–ß|y‘7Ý:ĎwKřaövRěŞp˘qKAʀ™Dތe!‹i|•79Ë( =[„űF(6DÜA„2ÂÍŮ4%ÝFXÄHL°‘ß‚ Bů"■‚ ”9łb„RD„ AAXꈏ%‚ ‹AA„r@Ä-AAAAĄdqKAAAA(YDÜAAAAJˇAAAA„’EÄ­ĺ;WŢ A„ĹĘĄC‡gľ|ÝG? A„ĹĘč,mć9ľAX´P‚ˆ¸%‚ ‚ ‚ ‚ ”,"n ‚ ‚ ‚ ‚ %‹ˆ[‚ ‚ ‚ ‚ BÉ"■‚ ‚ ‚ ‚P˛ˆ¸%‚ ‚ ‚ ‚ ”,"n ‚ ‚ ‚ ‚ %‹ˆ[‚ ‚ ‚ ‚ BÉ"■‚ ĚŚiâD`AAa1!■‚ #'JŔĘGžcáKAA(GDÜA„YPŒ‚VĄ8]„.AAĄ\qKA  QŤŘ„Ż|–}Ź"r ‚ ‚ ĽŽˆ[‚ ‚0šDŤbâĘ>>7!‹ËˆŔ%B1áf[ĹN ‚ ůqKAr0[QŤŘ#ˇrEkI— 'ŠBíćąÚWąk‚ ‹ˇ„)–Ćš8'‚ ,$nś/{^>űX Ł%ćŠÜĘ'r‰­ažYHűXČžÄî ‚ ”>"n šR(,#€ ‚°PĚ$l9˙N$zšíö撙l ×ëŐSś¨%b–  ÍLö°P{9—śKŰA(}DÜZĔňˆ_ŮŁSŇŰۋ{ýľhkkĂBK˜řů xa‘¸‰‹×TŕçTĂď‡MŽ7a+b|l ą]ې8°‰É ~ˆ˘BŮCou ź+V!°n#Şkj2D­lK/A惚Žt=–u ąmĹhO¤O9Ÿˆż*Â\"âÖ"džkĚ739s];† ؋/ž"ççwÝu‡n,^sÍőű‡şľľľřň—żŠßüć.ěۡŸůĚ_c!Ř~4†ßź:‰ĂCqŒ„’éů÷żÂsű"XÖčͧWa}ť‚ ¸“/ősę;z‘ťď€˙áßÂ3:˘ŚĹţ@Ô7`üĘ7 ňú›Đœj‰Ŕ%ÂB0›:…łő?gcŤ dĂ^nĄl`>?ÓăńŕŮgŸ8!>ĺ|"ţŞ óˆ[‹ŒbŹ3[N¤c˛~ý:-d9ńűÝźďz×;ôë;ßův,tţíŢᜁ#tFBQźÖĹ^]Ó— B~˛…­d2‰ĂۡÁű•˙@p˙n”žáaůcD_} ‡>ú‡XśaŁn8IŠ˘  MĄő ńľPf3˜Ć‰°‰Ů~&ÓÉÉBű”ó‰řŤ‚ Ě"n-"fÓ;VěBWŽ‚Éó]ůŸ˙ů˙˘łsŐ´ůêјÍÉ'Ÿ„ż˙űĎ`Ą`X!_—šOőŒ‰ł ÓÉg9uŘĎŢ#ĄŹ Jďî0żüďčţÓżĹҕ+őźbiŘ ‚P~ ‹ĹÇ§Ő/¤ ˘oO{řš|v+—ĎX,ƒläň3Ú§œOÄ_ažqk‘p<Ł~ăh‰ůœ“býësŸűwüô§?Çťß}3>ýéOi‡íë_˙&îşëˇčééE]]-.ťěRüŃýžúťNŻóĘ+Żâ‹_ü ślي`0€ÓN;żűťŸŔ† ëóî‹5  Ĺs~îQ§ĎúŹg@¸,בš‚ŰÎŘŻ###HÜöcVď<(e|J¤‹üę}˙GP__Ÿś“"h ‚0—Ě$lQÔ:Ř=€‡ˇŽa[w GG‰¸E-oŐ@c°ŹÁ‹ĺ ~ŹmŤ@WS•Áô@´YNŃËmŸöäü<— Ĺˆü™´…&ۧ´ßӇěďŔŻ~ők}o}ëMřýß˙dúœfň+ßőŽ÷`Ϟ˝řď˙ţüřÇ?ĹŚMŻh!íßţí_đë_ߊç ăꍯÄßüÍ_ę¨2{ߡŢú^Ryď˝÷éýÝtӛńń4mć†řŤ‚ Ě'"n- ő‹Â‹óÁ_*đaj;5ůRkŠĄÁöo| ˙űżßD[[Ťr>ޢ;îř5úúú”Sń˙đꫛń;żó }.W_}%ĆÇÇńÄOéů?˙ůŃÔԔsŰ?{aŁŽšŮź÷‚đ›ýţÓăú=—ýŋ¸ĺź‚03´‘cÝÝđ?ţćÔLz}HÖ5ŔŹŞE˛ŞZ=•0˝ÖŁŮH¨@< OhĆÄ<ŁĂę@â˜+|߇‘×˝555y#‚ sAśď …đđK‡đƒgcĹčŁY~ZB˝0~+šđ`b82°yPůŞFLOeޚ*L,Q.ĚĘ:ËëXÓĚFż˝œÄIôOĆĐ;Ç`(Žąhăń$&“&ÂJ4I¨}Şвňč°ůp>ĺ”Sô+‘ůŒ>xÇ;nÉxţůçâË_ţBAënßžCż^}őUřÓ?ýcD"<ţř“Úq ˖-Ĺç?˙ŻşĄyöŮgéy7Üp“v*^~ů\uՕ9ˇýÔîpÎĎÎZŔ9Ť‚řť_ eĚ~_DœApÝđrž†ĂaDŸyţ8›\Çi[”x•hiG˘uŠśY18ďâé$eŸ=cCđöˇżç¸….O,ŽÄsO"Ź,ŐŐŐŽŃ[É%Âą’/#€)ˆ›wĹwžŠ!–̲1ŚőezŒÔ {C-oâHȃƒĘőyjŔЂWŇ×K<ô MDÔr“jFXŮWęfIľ1Ս‹„zŻĹ3À›-Cp]Áč­Fœ(2Qʞyӛި…Ş\´´´ŕ[ßú_ís]f<ůäSzŮř•ˇÜň.%„}Xwź~ŕÁΝťpűí?ÊËńŸ˙ů|˙ű?ÄćÍ[2öÝĐЀoűëƒ:’‹]żřĹířÄ'>–łĂDüUAćˇĘœ\áŕvŮÝwߍ/}éK:ÝŚ”ŠŤŤW=Eż‹ëŻż•••Ž×\4Ň6nÜ â6k׎-xÝkŻ˝F÷l1ÄűÁŇŰ:÷ÜspŃEčĎ)Îqş˙ţńÝď~҉Ĺň7bƒ>ĺÄE§žëw[­Ďőž-“řŔĹľřö“cŁŃ;ä[„üŘą=ťŻÎ–ϏÄŇUˆ/Yɖ“ŰŽF”fÓo˝jy_ ŘvK5ʒőÍzŠu_÷xďRË ‘Ý{ôš‰ˆ%Â|’Ýa066†ť^Mś`GĺŤĺL#­?ikJč2œďŐKŇc`Bg#(ËchËÚˇc/gNŮÔ,ÎM áSMcXšňdœ(śn}-ăý™gžžwůSO=%-$ŃŻ¤¸599ŠßĎĆŻ´;Z;:Úő+Ó2)l‘ĽK—¤ÖÉ|֜ţyiŸřĘ+/×âÖčč˜î,oKČ›řŤ‚ Ě'"n-"œBSl–üšĎ}nÚĂŞV˝SŸÇŞU8ëŹ3áóY?íšn°ýă?ţ×BŸ…đ†7\§CĹďťďÝ3öôÓĎjąë—żü~řĂďęůŸůĚߣşşJGw1̛Ÿíß`ĆmłŘć#;ŚzĂîÝŸżžvńÂţ6ŒN[çâ5Ą0h'=G­ĆÖla”@ű2Ä;×)QkŞ0n2ÇH÷AŒövc| ‘ńQ=ωÇëC°Ś5Íí¨k_ŠúŽĺzž2rˆŻX¸zďۡޞéh‡Ů‘ěí)‹g€ Ľ}łáŃIléΚ€Ľ_–€e8#ˇôŸNĄË&%\yËÁzohmK˝2HÖ°/##pkMbÝ6ˆŤŽş'Ś ÎĆĎ̗R~÷Ý÷ł_YÎâ˙ńx˘ uÄ_a>qŤŒÉÎ^{îů­N+˜6ôŰßŢ­‹dÖÖÖ.čč_ÎmfôcCńjŰśíxÇ;ŢŚ €ŇšxűŰoօ<ťťŞďă^˝Ü§?ýÇxó›oĐ!ű /„›Ď­ÁKĘ!°ë O&ńš{†ńĆSŤt­‚lę*=xÇ9Őa:ŮößÉHtö‘[ĄÖŸŠdskzVtrGˇżŠťˆEQí  ^‰^•Uľzڊ"3M<’L běŔnôíy ^ľ\óĘ5h_wŞ˝(–Ĺם‚dS+|;śÎ:Š+Ąěföy–jayŚĚ0ęEYô¸aa埿0ĄŒf`Łś\Š- ĹFž4o!ßßA"_g˝şá@VD—‘e‡ ç ZˇĘŒč˛„2+ŒB™‘źě-ˇ%#řŤęƒ¸îękË*‚őxüĘBxâ‰'1::ŞEúíoďŃóęëëtŞd.Ä_a>qk‘íXđˇoßžięÍ뗢˘ž¸$ᑠě82íř÷îݫύĚG#íŻ˙ú3ÓMŹgŔ°oŚC2ŐóOţäĎőPÎŮ<őÔÓřŐŻ~Ł€K/˝ťvíÖóÍľdIGÚ`čřđěłĎcbb…ôXŃčÖĐT†=;îş<—•Ɛ LQČ`éô–BˇYQ‰řigëW’TÂÓá­/ĄwçTy}XYYƒ–†*ř=…s)ĄŤ?<‰žýJčÚťmkNĆŇSÎÖé‹Éć6ÄÎŞ…ď՗`„ łSç4Ó2ÇnC)Ţs4.BŰyß}wéú^sÁ{Ţó~ěŘąŸýě?ăuŻť őW˙Ÿî(`}™ëŻCŢušüĄ}4ď2űŘGÔô;y—aÁĺkŽyŁţűĄ‡îŐ+óÁöŁ1üćŐIŠg¤ěÜ˙ZĎí‹`™˛é7ž^…őí~BąĂNŔƒ}´S9lŸŁŚ"°ĚtV*˘Kw3xRŻnśÉ%˘‹Řĺ Š‰Í %löŕ­×]ž. _._Y)ošĺ}Xśl™ŽáEŢőŽwäiRüUAćˇ)lŹ0jËŮ óü¸üonAǙŤQ tż¸ýËOˆNE*dŸÓ\ÆT6Qľ>Č˙ęŻţ_úŇWtäŔΝӗăçŹ[ŔpNěÝbŒC63ňSŸúQ÷Ě3ĎjŒ^­­-xä‘ÇP7¨†ÍÖî茍Uşמ\ Ą|`„L:§ öč§ ‰=j)'6(dŰPęÇ´ş…(ŞKŘJ‰áƒ}ŘóĚCđDÂŘP߂Ć`叡éS"XGU­ž†Ővö+kë‘ýčşŕ*Ô4ľj-vĆšđżú"09ŽŮ2ŃZ÷ß˙@úoţF~řQ] y>řä'?ŽM›^Ć%—\4ă˛ŘXŤĆ†v›÷QWWgZ|ËU3fĄĄ°őo÷ç´íťFTCń5e˙˙đęzö#äGlć‰CGÁŞë?2ɎČâ–™Şąĺ1Rĺ˛ě”B¤ Śáˆč˛BłěňđFö†˛ßzŚţ^ǧƒűđÎ×_ŽEńrŤ;xź~ĺLźá Ż×ţëo~s'ęuÔěG?ú‘׾ô›)” šŹ¸‘őˇ‘őˇÇńjOŢÔäKMôŽŘŇ ˙OC8&lĂAŁBCBŁÂĄ|—/_VđşÎżůĘihhH‰*€Í›_M/łńm—âŒ÷_‹Râĺoߋmż|"ýţÔSOĂżř466Ś ’ŚŠŽ:–r.šüĘĄ(îS=ůŮ˝ű¤žŇŁ{÷ŻSŽÂiˤńSĐŃĐŁřEŁ(FčxpÔ§ůH;tč°nŒĐÁĄŁ“íŕĚÖf泗œúűűŃý§‚–ÁĀŠÎ9ŽD&¤ í؃}Ď?Šĺ•uXZUš2A<ĚÓ#8ĹŞs/EóĘÔJä÷mzF$<ă6ú›š°äó˙Ą{řm›9—v“Q[ŒŢşîşkpď˝÷káéżţë?0dGn—]vľŽźýęWż¤ëŇĘBDnýű}#JÄ,ě?yiŸžś‚;b3çÎfÎD>›Ębň_ťs'ž:Tĺž.ŹŃ ㆩ Ăłć||Żć{ŹĎXÂú›#ĘŞeěż ŤźţĚ^G–8ő™Šśyu˘mÁŐW^Ş*ë8ňŮ<pc Žçčˆď~÷Ířô§?…cAüŐŇ@lćt›)śŕŘ üŞ—a512…?ŞxjJ¤Ś¤c2ŻÎŢ §Ş:Ma•Č­E@Žú1ödSßš‰ÂęA u]K\ĎËůžTëÇ ěąçÄş,Ź]Ŕᓥ.KůÁČÄÄDŃ:6<>Nt: “Żđmi`Ě\s‹Ă̟|zZŘbúŕ‘—žÂIőí¨ő[óhĄš>ţ x››0ůř˜xôăá`Yuę•ŘńÂHŞßEk×˝ďÄ)§ĂťéśXgŢȲG_~§4.C…7óq[{ÓMÖvŐö&}ÇC­ż§Ô/Ák›ž?X†ĽŤô1đX<ťvΰś1oŠvJ"‡˛ç@bžĂĐ?řŕĂ:}ĽPx|üÇŚ Ć3Âbɒ%řěg˙MGšäăśŰ~‰ţçĎjg÷ÜsĎĆÁƒ‡pÇżÖŠ‹ß˙ţˇuÄšäoţćoąbĹ %ÜŐâ•W^Ĺďţîč‘ĎX“ńöŰďŔ?ýÓżjíŇK/Ö×řcěÚľ _úŇç|&ý셉táe7Ţ{AKż˙´e¸,Šbű§›ybÉe_ü^sŚ-=JMk‚}8ˇžŤ—6ęČ|^FQ°Îrü~''G0 a0ęĹH܋‰$}ZKăbsˇÖ—Dƒš–7TŕŹ3/DsssĆîDŔ:1ˆżZ|ˆÍJˇůzÎŘNHĚŹ  3˙¨âŹĺkgp*Uč,Q°S@J  otŻş:$—XŠ<‘ńQzá lŹë@ĐăĎ][Ĝa›ô°Q \۟•W7ę‘y,FOŻR;öîݧS SÉW\Ś_ŸţE PťĚĆŢβeKľ°EN9ĺd=@G.z”¨70`íăškŽÖŻLY¸řbŤŘ<ĹąšćÚk_§_™ryŃEŚ˝ˇˇĂĂ#úý§?ý¸ęŞëÔ˛×kń‹ěۡ?ç6ƒžĚďç]çVăf%\5Tyđ‹kńí'ÇŚŐŤąS;b3‹Š[ŐÁüéCüĺ7ů&đ–3ŞqÁççśœľ٨e´d{{ťšÚôhÔ:â+—°%– ˆÍʉÜZ„dö´IR0J”֞ǛŤhŠ8+BšŔ^črzPó\tĎ} †ŽçŹšĽSHՋęߡőĄjŞjgŒŒ2SŰôŚRdźMÍ3×őĘCż uƒ8°ÍŤÖęc2Ő61 1i.pŽ’řÎwž;ă3vD°žŐ;ßůöŒůN[žp #ÎNC\¨Î ç~q5욏6_ţňOŤ ˛bĹňœëł&Í#;Ś˘ˇîÝŸżžvńÂţ6œ^…5k;b3‹žK]ĺĚýë§6ŒâÔSʍĆB˘ŹfbŚmHԖ°X›)” šľČq–O$M]Ÿ ”Ś„ăř%jK(GXS¤ÔjĎ)Qb#XčôÁSrůňÔ2I íx •M9—…# 1–Ldźˇ6b âÔSQ}ŮĽđutäߎ˴´Ş ƒ;ś¤kęcËąě\¤Dşa§$FlٓÍ}÷Yâ—3u€ľ°Č‹/ž¤G.´Yłfľ~=r¤ŻžşY˙ÍČŤîîŁ9÷ψć榌cĄłűÔSÖŕ͌üš‰ĘJË)ćˆI-“<öŘă9—gÁx´Ä'Ÿ|*}ě<–ĆFŤ€=ó‘υŰÎç|ß|nM†0<™ÄçîĆłű"řÉóӖç˛,Ćź˜›YühqŤzćţősÖÔëBŃÇ*lĺŽ$zKŚ›)”šľHq„”śĽSýJ F›ĺ-QJÖ *Wxnö¨yĽAŽŃ92bC˝ţsřđ~´!¨–ň\Ď*{›|ßńš†Ą€ă?ŠŢů63¨”HÄuŮš†iv1|ă_Ĺgœžţěá‡ÁŸţé_j!ŤŻŻ­­­úó—_~ńƒŽŽNôôôč­ZRLE<ýôÓt‘ößű˝?ЧžŒmŰśŁžž.î— Ď˙řGuAů˙ř˙ÂŁ>Ś…$´_ľj%Žżţ 3†Ľ‘âE1FŸńXóEnýŕ?Â#p?‡”6 ďo|˝>–|äCřüç˙Ÿ>Ç /<_§Lňœ[[[Ňi“nýV4ú°%4ĄEëGĎş7D¸ěbeLlfńĂ{˘ą:křË(K¸˘˝>ßôŚ Ł)ibGé3Ҟ¸í|*b‰Ř%,Äf ĺ„Dn-bĚŹ¨'ŤćViMŹšeJô–PŚŘŁż”+ĺr~Ś(ěZ[‡ !pěĹźăŠh+Ăn yŽmXëFu “‡Xo˜Çc\ ě”D Tˆœ°G)dăԎ޲‹Źł1ɑĎţĺ_ţQ×Ěąáü˙÷ĎâuŻťJż§Hőgöi,_ž<ďqźím7á˙ţßżÇęŐ]xńĹMÚÉ˝ńĆ7á˙÷+”X[[‹Ď~öŸĐŮšJW J,űż9—˙×ý'q622ŞĹ¸/ů zrË-ďÂ˙ů?ŤŽyüIěŮł×]w žűÝoęZ`ů¸áô*ŇÎć"מ<ˇ#@–b3K+r+ ť ÜŕoŮc$QíRšç˙Â3đí/Ć×>D˝ÂmßߏÇî;„]ŰzÔý7˘…Ż™"6$QÄf ĺ‡Dn-b˛Ĺ ť |."căŘs˙ăŘąG˙=ŸjŞŃź~5Ö\s)‚uľ9—ă1ťŐÜ„r€zšĂsdÚI)`"G_*ĺ,!023PÂÉÜfRŰĺŹH.őžĺ“żos&”02ţđămŮ?<d"Žô1Ÿ˝uđÜÎiŽůßů°žÜŕhe=ö`Ć<Š˙Úמœ1ďÇ?ţ~Ć{ƒţěg˙9cŁ˘œüô§?D6\&{97˛É†bÜĎţăŒyĎ?˙TúoŠWÎ÷ßűޡ‹7˝ézš-ëŰýřĂŤëqßk!ŠO+ __éÁ˛FŽSÂÖiËJă^š/Äf–•řaDÍ\çân›ĆĆĆđŇSaLŒYŸ+ł‹ÉqÝ{ŁŘüXUÁ!´,5ąlmVR‹şú}˝Ü"Ŕ\÷*–°ˆ›)”"n-běŃmřgKd ÄWžűÄ8ýžŠ¨VíĎęI5d'ŁŰmxíÎq´ty°âěŹ8šőőÓÓEĚ+b3…rDÄ­EN!‘[G_z}ćs8ç˛Kpë;oÁĘĽ–¸ľďđ!|˙g?Á <ŠšŕÜ+/wÝţCŸů7\űď˙íg6mdR-Ą<™+‡ƒŠXŸúԟbďŢ}ú=#gX§ˆĹݟxâI|á ˙™w´ślŽšĆŠ<ůÎwžĄ#nćžkiŒhă’DĂbÇŠĆRrl>Öz‘™ç},ĎúÜ(xű<–äŘĐŚÖňŤăRbąŹĽ¤aWJPÄşĺź= ™ˆÍ,ě:YŐţF㹗é‰aI{"Câ|Ă`Oěô”môj—Ą %ÇëÜŽöąm{GŃyÍ6^¸ŕ\ßüćwpë­ďAss3Šů>ŻcĹ¨_xáEźűÝ7“úĺ/˙Žžú*lܸÇClšqlüĎ˙üŻţíś´4ăo˙öotqîÁÁAüëżţ›ŽCô˙ř/řęWż„ ĎľœŽ¤6/Y)ƒô_$Žc‹ŒYżďüŃ×áknÂđíżA˙Wž‰\řĂSá¸feF,ł%)]Bš 6ł¸ÉŽŕ˘¸UPNgŽľěá0NML‰[\ŸŃ^ąHvėa‰Z˜š`LٸŘ@{<Žö{T \Ë\Żß‰Žâbt G‹Ýşő5]ťŃ/q•0…Ô „Ů 6S(GDÜZÄLŤšĺ2ZâČŢýŮwýŔGpŮe—f<\)*\qĹĺ¸ń՛´¸‰Ć™Ěkď–qĆUoĘy ŢTąäŢü–<Ű+>˙÷‡ÁÝPßľ*c}ˇŃç Ž°uéĽëżCĄ°W~öł_ŕýďŸ8 L[[›vřŘ;TŽĚĹđĹˆxŕ!ý÷˙ńj‡ƒPý“?ů”ęMłœ §M†#Áýđ‡?ւ&GŞ[şt Ţüć´°IGĺ–[nMoűĘ&°Ŕ÷_ý՟ăx)…ĄšuŁŞŇx[–Œfź×ŰSﳡ_˝˘Cżw&î ľ0+,Ž3A2†‰@Ęą™ĽEކęüŁÁIN‹.aWu­‰7÷2•ŽHLĂzŁ…Ž”ŕó$\™(ĘIŠXÝÝÝxĎ{nŃhŘ0 üG?ú yä1\ý s…ŘLĄqk3--‘‘[‰ĚČ-o•U×cp|TŤíŮŁMpŢŔ˜ŐíFq+še;ź…ŐËš}îŰ>–ěăKžŔŃé`q¤,ä\lٲU;,CCĂŞÇ­ §žz Î?˙<zţőŻgu&Î;ďÜôňGŽtă§?ý9Ţ˙ţ÷ŚÓóÁ^:¤#­^˙úku1W{ěTǧŸ~F÷NŇą#‡Ćă?žž~uŹœqĆéúÚqť Ůçś?ń‰Ľ×çşO=ő´î ŞŠŠÖךÚ\i‡ŃËł—”Nöš5k2ŽË7žń-Ý{ĘĺöíۧŻßs˛éî>ŞŁˇˇľľ5ęĄ|-抹ř-sHtÂß„ßCȝźë]ďĐçG‡ƒ×âóŸ˙Ź>ŸţţüÎď|Bő˛ýď|çŰńçţé´ÓÁżçŞB)Dé+” DAk6LŒ`,rcĂÖ*{1܍!őŢ&ŽÄŞăyM†ôű%Ęjë16rTż„&ŕŻ, —?Vç&‘[Bé#6ł4°Óé+t4än†đÉÝ3î&nńş7ľúpd‰ĺDhËy܇ŽŢššÇżzqň—eaé͛ˇč†źSŘ"ô‹9jëo{Żőţý›jP*Lcäói•ęü˝ęŞ+2J5Ř~Ăľľľ8ýôÓtg,żťÔ…gŸ}Nű1uuľjWbĺĘ9óĺ—_Ńű׿ůË/żLGŇgÓ*mż×öĹlßĘŮ)üóŸßŚüÄV˝-ű¸č3ň¸ôÉO~\/÷üó/h?“óč#3]Óšo§żK_ŽŸ]|ńEeĺ<ˆÍʡ9Ó Ęg~^ťv|އëśŰďŔĽçž‡–––ŒĎůúĺżŇS܊dEzwt­G!ÜţË_â˛órm˙} <–ěăKœŔ‚ňÜ/‡¤Î&ţÚkŰ´§`ÂBŠtîťď-đlذ'´Q/ăˇřž=…[,ŕH!lĺʕúĆ´tťúŽžÎ‡Gö2‘HT/Ăb|ĐĐ!şíś_*1¨o~óĘŮôjĄë7żš řŔ­(”ƒŞsźüŕűľƒöŰßŢŁ…ż7žńőÚ1cQÉűďoű[ Ú^(Â/y‡˙ŢôŚ7ęÚżů͝úÚšŐ˛Úż˙~ýë;qᅖŁC§ęĄ‡ÖN1›l†‡‡ń‹_ÜŽ˝Sq啗+‡1˘ž›űŐľyR‡@ŰĐąşňĘ+ô2;wîÂĂ?Şk­-YŇĄčˇÝvťĹčP2U•BW<^<˝C 'ăăş×ŠŽÇäd(BnĂsć5&üMÜzë‡2>§yôhNÍ]ŹĐ1ď>ź q%R9ŠnnÇÚ+­ÔëƒĎ?†Áý;3>Şű°VÝWţ3ď3śUSŤ÷šÖPߧЌ ß?öů˙/cű[îú‰~ßÜš+ΚT˙˝ëŃť11Гą-ŸÜ:¤Śź hÄfΚFI´Ą¸ľŹ1żč0bp,Ś|ĂŠ‘θ^ے Ž(-3{J-ĂżcˆpÁÖjߤŘŕo~ Ës¸A’ż3 ËS#–ďŢ˝ëÖ­ĂűŢ÷ý{ŁżÉ´FÖ"ĺľ?pŕ ö‹.ťětvŽŇŰż÷Ţű´ĺô‹(DQТĐ@čÎ;ďÂG?ú‘iŁJÖU˘xô†7\§ŁçůţÎ;ďVţâű´–틹c—žE9–™ ,ýÁuRŃO>ů”ÖXÓ´ššIG qßçxŸQđbАÎÎNíÓ'~đÁ‡ŇţŽ0?ˆÍŠ ˇ1zčää”Z”t-ŃÄ꡿ˇ˙äÇ8_‰Oď~ëMş÷‡PŘů‰ ~Š>#‡ÇâđWd÷zÇo½OźóŽś"n˙ÉOÔöĎwÝţí?ţ1ÖŢr‹>–lq‹Çě<‡…ş8äí3Ď<Ť ůÚľk\—ĄxĹŢ/[ü˘`Ĺ'ö(QÜboÖ /ź¤#‡ŮÄmíŘąCŐ/n‹˝ t2l§ďĆ߄Żý[ÚÁčęęĚš  ö°¸t„řĘĺČŮgŸĽ…:@…†îó;cř°˝ţO<Ľóîm‘ŽçúŔ˘P(ĘQ$Zˇn­Ţ6§}č9{ß(Bńš˛P$ĺ×ůŰpBçöĂţ€ől¸ţîÝ{2–ă9Ź_żN˙Í^F^ĎhqëŐW7ëRö.Ú=’ň8ň\0SĂ čĐň˜č4°Ç“ׇ˝`÷ߡŢöÍ7żW;źüž8˛˝ßĎţ_§m‹˝ŞóE) ĹÎc *P•ĺđ{ŁSՐkëĎúÜç1´řÔ î/Ö˲ßglűŢ?ú‰ ˘šۡÂďÜžáŃK7ŚŢó˜l‚ęXł,‰@EI\A˜ ą™ĽýŽśŚjř=cŞsÔ==‘ßćśî:—MtĆĆs[{ <Ţ$âţĚŇŁ%ZQ]öŻÁlÆkŞős^/Vd׏âÉUđڞo/GxŽžúĘ´oG_äßřśŽz§FżčŹłÎĐ>áov||\‹YŒłĄĐEŸ†°3vŰśíş3Ö­ô;ő**Tť`u—~–0Ҍ>’훚ůbäîťďŃófSĐű’K.Ö÷#aG%ŁĹŘŮh‡Ü6ωŃf„ţ6ŚľŮß/;Xż÷˝Śýl!ą™B9"âÖ"fZÍ­äôš[¤óď¨ęúË?ţ”ęů).šě2=˙‰ÇĂ O> 3% ěďž^a×á 8ÎľýŽË.GçŰßézl 5Z"Ůąc§ŽŢą÷Ă^ŽnxS:ŐÎ tAu´{ÝěsžŇĄ`´şěŁŔe?¸gÂr>–f„×SHc/WOOˇÜ–Ą łvmfş(ϋ‚ąŻĎúg“Ÿî‰Źaş !ŠNP"‘,tsÚiĄhȨ3†ÚóAIĄ+—¸EÇ%;˘‹pů°G%bÚ#6n#; Ďy^„b–"Áď´ŁŁ#ăÉďÓçË_C¤Pč¸2-÷xŕů0ęŒ!Ţ˙ůŸ_ĐŁŘPtŐÂńO~ŽŽnCGŐ'gEYţ>ŮĘPq^{Ű)ľĄă=6'öž‹€ĎÖą˛v•ŠŽ‹ËWÔ7˘"Çšň8VŮNW!ďÇ^~ #ŞéVáń"ŕőLŰžýž˛Ţ˛7Éx >uŹŮÇóe5ĄD›Yź¸5˘9×ŽĘӇ‘dŽjľÎśî(ŽŽF3„>›ƒŐ=˜É´_V´–#%‘7ŒbĺI\xá3ÚÖ…›xĺÄMü˘ŸäôíŘ ČëŮß߯Ĺ-Š\œMoĂh&qÔZ¤/kc§4R¨pƒB٧žůÍoë)F‘9;xÝ|1úoŮQg…`‹V„iněđĚNQă}hÓÓÓŤýŘŻ|ĺŤÓś5::&■b3…rDÄ­ENFÍ-ˇČ-§üńŸĄůœó°ëˇwáĽ˙ř$ćĄ1E˛ç\O^%bÔŽ^ƒ“˙čÓč¸ü $Řç&n-`Z"{ąě”5öRĐšĘç1¤š=dě٢Q§g´—F;1Ԛu(r1Ä<ťîŘąP¨ĂĆč,*ĺÉNKWW§^—Ąí Mö÷Čz\é…ĆŒcŠ˘Ó™9VXGëöŰŠk”Ń d„#ęXËëXwj>愹p:Č'?ů1=čŻăüÁkĐvlšOúSÚAîęęÔŁ2-ᓟü]ăŒ=¸źVL1¸â Ktć}Ŕy˙đ˙„kŻ}nšĺ]8^JĆéđ¨űĘČŹŐÂ;-2܏Š–šÚÔÇŢYŮ$•ĺŘfŽ÷ĄžTśś#BńY˝o(ŔNđ^ć1‘¨:FĂ𸀠”b3‹Ÿl‘‹_͕qŒŒĺ^gß\ënŐ5&”¸5}ygJ˘§v+.‰¨ďâJrl' ~ŸMMşÄCWWç´Ď<¤s lÜ"ӝó¸Í‹/žP‹Ůđ7KŔĘĹŻ[o}ŻNyäą2Rç‰'žÔi€vzZ.ň]ߙž™…>S™ ißwNdDswÄf 刈[‹ˇČ­ě‚íSh˝ôj=-4ů~˛ <ĹŹB‹Ź %ŹĹĐjŚŰ9‹}RPzä‘GőőŢúÖˇź}†ďRÓ#ľĽœö€0ě×ŐŃm†Ľs_ěYaŻ‹‚ž˙ýďK§+QHšoü~Ÿî‰sbçâ:]ěíaôU{{ť.FĘ:` ;wˇŘ#ÇbüÎQUřž˝nË3ý“˝žÎ‘‡öîÝyˇśśč‡˛]c€°Ŕü\ČBç=2"2{sżřĹ˙Ô"棏>ŽŁůXüŸŠ˘ď}ďťÓi—äŻ˙ú/đƒüH×J`] .÷îwżK;ł6ęů _ř˛v<؃;N‡[ěŚsş@é?ŞĹ-?€@c;b˝˜ ŮŰt{÷ŻĐWx|hđV7ĐŹÄśTdV¤ď¨ëągާ(Ľ‹ŘĚ҃çŃ^kbOq‹^K_8€ą‰ˆŚüFxt,÷ăč>ˇ˘ňžú t^0Š:%ŻĚˆp*Öô$ţžěQgQyúCœĎ)gäŁě)LŘž}*Öľý?úOŒžqŠNz™„¨\ЇĽ_ĹT4Nôo9838€O._Œ×Ÿu˛;péŤÚĐ?e}]Žž— Ś´1*žŰr^î—Ů Ü/ý]––pž•Ń\+W6¸ŐbClŚPŽˆ¸ľˆ™>Z˘‰Ydމ8Zb6€_;LícM'>€™jČč ~śiÓ+Úů°k€ŽÖ˘ŔĹĐđ|!ŰvJ mő†FŸ#čœsÎYŞg3Ž‹ĹStąëd/c'|č466čkĆeşş:ľ0ƢčůÎk.Xž|šÚçŤ:ş‘S÷8ZŁ]oFÖýb¨3C—Y””‘UŒ°rƒâŁÍŘóÉ󰋘ry7q‹ß E?:B\‡űçȖłŠAçmÓŚ—őľ=ďźs´SÉ(źšJKœ‹>öZ~řĂÔÓLűdm3Nš`íąo|㍘Kćň\ç6Š\FĄîC¨ßxŚţťry'bƒ}(œěmşżoT!ĄîU?i6Î*–uNăŃC9usßĐŰľkˇŁßńގMłiź×8č…üă-űĂţXۊ\źím7ĺő‹¸ź:Đś=öŘÚŠwŠč6öˆš,źË¨ťćÍńŔFë÷ż˙CÝqaןYLˆÍ,ě.68W4đԑÜËŇĎŰŐÁҎ˜>oŽŤG~^[‡WŸ #ËNMTŰ­Úó&đşkŽLw>kJ˘ ;CŮńČşMž"Ĺ)–O`§YvDϋľŹÎ?˙\íŰюQ ˛S÷čą˜:#óťş:uG&ý˘+VŕÚkۏéYfƒŒ›˘í9Óą;~ł}1ú”,ęÎÁ{l˙ŠĎnƒ‚}YúQّyŮđűćőyěąÇ­Ń2S~#úYG–Řţ.0:óĚÓő(ŔôÉŘĄëN„)Äf 刈[‹˜é‘[FŽ´Äâ%YDâĹ:&ě‘`C‰Ą´ńż¸M?ÔůyW×tĄ…Љl`1|<ˇXôá‡Ń˝^t"8 {>8B  i,j÷RŇŠq.Ă>.ĂŃsˆ˝D‡=ƒŒ’bA{6Ls×\„ö2LžŮsĎ=ŻS5YفEOíšft~XŸŸłˆLšŒłŞ6’™ĆřôÓϨéY=$1ŽÎ‘(0š×#$ň7Ăď…ËŇq+öžímoŐÂ$ë Pœźîşkq×]wc.ŕwhé,gxŽĹ8,ť+Ş1äqI틫ŢlŚ&ZPąt%&ˇoA2.p›ČÜfęýŽ}­í|řý>čÝ5ň+ôąČP?̉Ix=Óď]Ă3÷6Ÿź'iŤŢóž[Ňß/hœg~ź°X°RÁ(J֖Ą fs˘GEcă™:{Ćłë˛aFA|.ĄmfZířbDlfń1SÁj k9ňáćěřŤĚml;…Ł÷ë‰6/}}–8öa şy'ŸǕW]•žNś•KĐ*Ą‹ÇpÓMoÖŠ~ô GGŸU‚A…î c˝0gÔ?áůÓWbgĹrÖ'ĺČÍöšĐĆRřąý"vT˛Ă/—Uô“x­iÇ)–1ę†ĺ:şş:ÓűtúbŹ­D‹ţŞ ŘSÔç¨Úü>)Ä=Ä(1ţöŮA;Ąžg¸čżÚűśý]v*°s”ÇɑÂ9JwÉř ŒŘLĄ1 ˜o8ŢŰ{ŻöäMMžÔD‰”Ý) ŞGáiDŽýŔ惋 ön°bŚ˘Œn‚-fqÄűŢwŤzˆ>—^néG?…šł/@)1ţâÓ8ňż˙•~îšçޞëďëfť°š›SSL=v łŚđô‘|pZsaqC‡ƒáúĺ EÂcéQcJ-ď6ŽŘ¨Ďv\Ž×ffŰMĘÝůɏĄbhŔ}ýŽ6´m ăÚť㯽šw>f={ź{ţî3ÓŢ "i&Qă ˘Î?űz!5'†Ę.+ ÷ĹÇ`up 76aÝWţW÷˘gŰË㱙Œôä(UŇ)46Ú(f3 ڎҜ+^zi“Ţöl#°ć3r‹‚ë˛AČžv đ÷ÉčŢšŠÜÄfćcŽmfĄ8mŠŰkww7ţúÇG1–˜nçX)ƒÓęĆ>óćĺ)i´ILK{üÁ¨Ő­ő­Ă8ýœVĺĂóËeÊ=Šk&Xź›żu I‚p<ˆÍĚM.›)#/;Jd§ş>Ź&†kRU§ŚDjJ:&Óńšü™}!ÓúE$rk‘ă,>UĆ-wÍ­â$:<ęZTłŕ…ŁÇ0jŠŠ+"l Ůđa\νjöů• †ęÇ1rô EŽBlý(ü5u¨\ľáƒŸŮa4R˙™ŞQi0*2‘Ôď—TÔăXńŠc¨Xe`UÇ=rž`ŽýĎOÍ-FM1ši!–všâ{éma‹˝őěeß˝{ˇŽŔZ˛d‰ĂěÔm:Üßüćwpë­ďɨwČ™Ţň–] /góo|K§řŘůůĎoÓőY8‡ 6ß˙ŞQ?Ą?c GCľa‡#`™ÍhFH1!׎„wFŠ1ĺŮ)ną k^}ő•ZܲqÚč\óxď÷>ĄlŠ|f°QĎČ/ÖŐaä„}}˛Ď×yÜ:•ŤŤKG÷ć:n^ó'Ÿ|Z§‰SäXśl™^ŢŢ>Մ)IL—rFŒŘ‘%…,3_ˆÍ,^ě(Žěh.Ś3ľW…06–KÄ7pdԓńÚKúNüMń÷Íy+Wž1mcçňŮť˝„Ĺ„ŘLĄÜ˝EŒ3’‹ÓĐCw# […ĺK`ŠŠńĄ‡ďžvĽ7 ŚŃuÝECí˕’;7–č>Q<ęۜŠ„U˝{ľ§Ÿ {úr,ď„ďűÄđĚ_~ Űžň_9×)hňxQsĆŮ0R=Œýę˜xlš—Ÿż†SQ˜’MQ‹)*ľ˜~lóŤ_ýGĹő׿ď|çŰőďQŹŹ3ł°^!GüzÝëŽĆÍ7żC÷ňŢvŰ/ÓÇÁfь˛âń˛Đ-ëŮ䃢Îƍu]°ţţţô|Ž*ĹTëc‰ŒĄXČgǍ7ހ}čý:J™Q`nĎ>ţéOŽ…,^ß7žń ú8r7—çͨ7żůF}ŽěŠvŚŠŠ‘ŁŁcxßűŢŁ ý2:uvœÇPČ2ó…ŘĚ҂żĎŐ-šš#VÁř‰d˝Ł1-îf UŹŰIќö†yöç"l B~Äf ĺ„Dn-b˛Ĺ Č‘ƒ8ôšżBýU7ŔSwbk•ĚDbtŁýŃîCóKIÜb )N‚†B3ޏ Îr‚çTjC3[ !÷cŚF”PÂÁŘá}¨]Ö _C#ŞO:[^-`Ë^D6oÁ¤Ş|Aőś°Ńݨ>ů4řę­Ôą#űTÇäń掖11;ÖřťâŠËńë_ߊß;kŸ0RŠŃ?xkş6Öë_-ž÷˝^b茪šoŘ`fT‘]ŤŠőţžůÍoë^ŹOĂâÇőőő¸îşkҍaÖűbÚ%ÓU™ŇéŸGŒŹbmFońZFhąčűąÔᨲŒ˘˛ÓŻžúĘi ~7Łľx>öžXƒ‡Ł‡QČĘŢ?ßżűÝ7ëW{d)Š‘ě„Ą8ĹÂű–űľ×ç÷öo|[G™Qh(t™ůBlfi`Gpąƒď´•Ő¸oŻ9Ý™ÖĂ0ąˇ/Œő+§Fœ­hUNÂm‘ Ěb3…rBÄ­EŠýPĎƒ"G ÷_F)#=qBšÁč6FĂg—2Œ€™ÍȔń'}ŠńUĄďĺ§QŃŘU ‚+;‘ ‡ŮłkÚ˛ĄžTśś#Ň×§ˇŮ8ţTkÖé}’Řä8ú6=ƒF%l巉ók/­çmÖ¨hQƒ˘~Č.úÎ4¸|# Ît~Ż#@˜6Nzzzľ ô•ŻL˝‰ŃIšÄ-Âzc—]vŠŽEĆík㔵„î¸ăWřîwżŻG‚dş_ŽâüźŽ,:íąčěŻ]›?ž{đ|yŹ)—P@łá@$Îm2"…ŁfDž,3ŸˆÍ,f**ĎűoŐ˛f4řŽ`(^3m](a ځýýáŒßaĆ2.ť˝Ÿiž ,VÄf 傈[‹ą™"ÖŻ_ŸQwäDÂô•;vä]ŚTëo ÂLŘľjJÝńŕyĚwݝůÂ0ěąTr|ŽţŤA?ó V\úxýTŽßĂëCx'mה˝˝űWč×joZŽŁž–˝ç eŤ+VŻŐ=ó€:–`ę˜óÓü7ňř}ۑ@Ĺ@ösώbv^‹ěe(ŇšĽŰŃLů`”‡Źç‰,žMąŃW…ńÍ>Že˖â#ůŽŐĹȡ{ď˝O§&Îň`ŒÎúя~˘Ó8X˨ŤŤS_Ś:q{ÎfĎ+d™ůFlfń‘ŤîĹĎŽ†0†úł„W.Ł. {,ŠëŔŮŰqžćűŰíA˜ŽŘLĄš[‹l>×D§˝Ż,ôkOtĆwîÜŠ'ţíül.Ś|Űçąđ˜ňłŰ9 BšŔ‡u)<Ŕc/m‡Ă3ăŹo埈âđÓ"™ˆëľ*ÖŹEőYg+ą+˜^nIe3Ú*ŃŹ+`Ťš˙ă6kÔśÓ–ÚçÁ§@p"fŐښῙįů‚ŃNÎ}dd$c> Cł ;ą1.gĂh˘ŮŔ”'§ŁÎçDś¨DŃŎP˛ßł3Ľľľ%uŹ­ú8Y‹Ëž¸ÝÁÁĄ‚Rř›ďęęÄîÝ{ôÄH.7xžŃhL?ďl˛Ż ÄósŚ´łü;Ţń6-r1.7Ĺ4糑i'Lˇt‹€aĘŕŘظĘ!Ćcv¤x­œÇ844¤‹ŰŰşĚB 6ł¸ą}5žăŮŤ‚î]üýŞ˙&œ)¸"l ÂÜ 6S(uDÜZÄä‰8­Xą"C\˘“ýŇK/)řžř7ç͕°UČöWŽ\9ăqŰ̼è6mzY˙ÍăřöˇżŤ‹$ îp´,gb^;^ĂRé b͟o}ë;úďbűžfÍáĐKiô+š”BÄÝPę‘YŔTëŻU*Ě(ö?~ш^×ßށęK.żc‰^ŚÂ[j_|AŰt›|mÜćĽđľ[ŃľÜ÷i¨}×đ َ‹° @S_şt îźón]‹âĚ}÷= …'{¤?vf477éяéÖË=řŕØ ÜkOíÚľ[§ÚÝsĎ}éčżß‡‡~ÔÇńŰßŢŤGr<őÔSô租~š…¸nOOŒŽęă~ä‘G >n‹˘Ňđđˆ=Ň ^r˙ýęă`áyŚ3:áůÓśň\˜â÷ŇK/ëăgM°lxÜ‹çĂíQźâş<7QŽąąA?C_~ů-˘ąp=GŏëŢ}÷=úZđ;šëŽßęh4F•Íf™…BlfńĂßËÉkÚŃŕwŠů“2Gă1O†(;Sô–s^vaůR`ßžýzdXFT kÚžŞŰűB `Úóżře} ĽćżŮĐćp€Œů$Ű×-Äf ĽŒ¤%.2œĄŕ|͕&@AĺŰ94,{€Ž˙f/;k~ĚÜÖLŰgc‡N<{ÝXˆ‚ňtÂŹ:2í-φճĎ>‡ßůc>Y¨ý ŒŇŕ5Ë5ü|13Űď{!ŕ11z„÷g8.Ú!œélĐŃ(‡a˜í†‘§ŔRS°ƒcĂŘóđŻąâüŤPŃĐ OE%*Ď<eż˘{÷"Ąk:ÍÖfđś4#ĐŐoccznx¨Ÿ{ÁhRď{V[<>îó-ošQ WO¨FČÝZDf+ŽęÇßśÍő׿A‹^,jNń媍ŽÔϢBšřâ‹TŁ,¤ž{´ýá¨jޜđ7zÉ%ŤýÜŻDŹ ńÄč%ť÷šizďz×;ôąň8řœaGËlR;;WécŹ)–Ër?,T˙řăOŕ'?ŮĽ… Ö稒Îëń裏ŤyżVçՂŃ[ßz“kz¤}܏<ň˜푅¸WŻ^Ë.ťÄu˙ŒŽćö)&>őÔÓÚć]zé%ÓoŹăEŃđöŰďĐ>ŸŃ,Čďü˛ĚB"6óÄâô=łSíWţţNjڋ'{Ś˘Ft1yÓú'šœ]ŠőbŒŇrKšž-wŢyşÔóĺşëŽUßIłţ-–˘˙ڄĹzŸ—b3…REÄ­2eŚž6nËp]:ľŮ†Œěĺ)@͕Áăś Ů>â–űůÍěĚŻĂĂőYX(F$ŘQ ĽF1ß|˜sbă‘÷ #RxϸÝKó Ż!NLŻâqo  bB÷üŤó1fđÜhÂHtL \w˘uăhYŞÚ†W‹R•jJ†ÂHôEb`‰á<÷ ńş6ÔĂŰÜoG‡ÉŚz&Ídý;6ŁoŰËhđŐ >0Ka‹ç4ύ@ŠXn°ątÍ5Wë)ŹMuË-ďʘ÷{ż÷ÉiË1Ž“Ű>ŢôŚ7fĚcD“ÍÉ'Ÿ¤'ňĄ}š`]Ť\çáĆ9眭'^ă~ô#˰áđŠOýAĆźuëÖęɉsv:qôĂ\°Wöqżő­oAĄ°Ö§\űˇata—‹B–YhÄf/h/ŮXçz㈙ӛ'ΞXˇ¨-'’~xlđ>ŠçŁK9Ň+)U˙͎źŽą™BŠ!âÖ"Ŕ­€'ƒ›abc‚Ëf§nĐČč}ăźě厕BˇĎůtؙ’‘M ŕĎ0t39@Ç C´ŮpąwŚqźřâKş^ImmîmgO#8ýĘn 2-†ŒŢc•דQšz·/ŁśmŰŚ#1ŘŘĺ>x-™–ĂßÚ5kÔ÷siz;\ç‰'žÄkŻmÓî“N: őőuyżoçąń>b4ˇy˘ÂĄy^ܡ„cĎvJKRýśŒYfó7ęôV ďľ—1t`—šÎDÊ.â芏€§ł~53QSŞV‘ÁýUa¸üći'GďCďÖ‘œœ@{E+*=łďYOú}%™˛#ǃŘĚâŔ韒 ë:ąćĹW°mŹÍš˛ť&<Ɣo趝ĹS…éϰƒ—Eř)ÔÓ/)äüIÚ)vłÓúk_űşö—čËŮ~$#.Éďü·tşśÓŁŻEč÷Ń÷ĺ6Ö­[§kćŞAHŠÇɑbéó1;„<úÎLy\ťv­îč gű™ˇŢúíŰĐżĽďŮŐŐŠßçň˝íă¤OwĂ ×ë÷ŒŘeôíîÝťľ0ĂčŇK/˝XG şaŸgƒęXâ>œ¨šj:ńú>÷ÜóڟdÄpSS#.źđ}Llß|ď{?ÄÍ7żSűó6ôŁyĚş(ćßąŘLĄTšsb+ßLČŽWĹůLűă!{âg˗/×TNü›óܖ=–É>ŚBśĎc´Ĺ9ç´~ý-”,䂣VQč sđá@ Kçčz,ŹĆŃľ.źđüTŻý‡ľHDž|ň)- Qźz÷ťoVő5:ő„ŁiŮPXbÍ>Čßóž›őƒ™ľXÜȡ>hylď~÷ťô¨]ŹƒÂ˘Ćš(t:Xt$>ôĄ÷ëh:†˛; ĎčĚ>řÁ÷ăüóĎÓNkŮ::LŁĄAGŕúëߨEŞ;îřuŢmîÚľK=xƒ:҃ÇÍâÓL#bh=Ósn¸áMşžŰă?™^çá‡ŃâĹ9ŽWЇ^x1ç>&&&đӟţ\‹cLĄâ6)vŮé7ByáČŁ_Fý–B§*_VV/GuÔŔáçŎű~Ţí/#6™Y_†B–G Ť:BKMü;[؊Şu¸îŽ{CĎ>ʎš˛j9Ş”€v,Ç xç­@ÁĆi_r TěźťrC^Ăń,MuxVxbŽ—ůöSNPdúőŻďÔžÍ{Ţs‹öŃč‡q*dÁmЇąĄ_—H$őô#éĂF‡Ň—djłô‰đ8nźńí{ĺó› \Œĺ÷ĚzXôůčăq:xđŕŒŰp’Ď÷vƒ>6 Ą?Ɂ8)H?3_-1 aŁŁcxßűŢŁýCvFsôŘ\KŹÝČó¤?ůŢ÷ޢE8ÓŘؘé˜FţÚkŻ!űşđ;•çŻ Ě šľHĄhpĂ 7âç?˙YFÚE#;ÜÔ JÎ^”šŠÚ˛aMĄŰçą:َ–-[Ž>ˇ¤{TęAÁ)•ŐŤťôńŸvÚŠ:­ĂŽ âń°ÖŠí$đœŘ ôŚ7]Ÿî}b$ ł÷fŐŞ•zž×^űştůy睫 ťÁeríçĘ+ŻH0f{ÄXÝîÝr2›uEe÷>1jiŰśíşçŻĐđuŚŮé/tx)vŕŔ˝MţÍjö÷ČZ4ěőbkxšÁëhGŹö0ŃéqŽüÂó˛…:ţö7oŢŞ{ íČ4ž/{sĘĆcŁ€JçĎv´oźńMřú׿ĽĹÉŽŽNĺżë‰ŕąG8q˝ćŠ&É5EßÖM8şĺjPÓځʺ&k•hŹ€×g˜ˆÇˆ„AhdýÝŤż}†ę„đעĄf%|ž™GëËÝó‰€GÂú…‚ĄMž‹eÁƙU@óěÓ×aýöWđÚXGĆr XzŐěőě<ëŹ3pöŮgé÷ôw8ĐĹ­‹.şpĆë`×ýc§Š˝ +ě\ľýU;ňĘň'Ťsn‹~:#’;Ł)ŽqŕvT梍Ť3íŇ磰tÓMoÖűáÄxú^…2“ďí„ÇĆŇ~đV44XŠű´Sô[ó=˙x=ŽžúĘô2ŻýľřĆ7ž­‹îŻXą|ÚňŒ^cG´]‘ÍĎ=÷‚öďy(0˛™>6ˇÉ7†††sŽ +Âěqk‘šČÁŐW_‰?üĂ?ÂמöUý Ó@1 T 0ňXydN?ýt|ęSŹ{n˛TóířđaJQŠŁŇtvvę"ştrÁpňx<ĄŁ˜FiĂ!ŕÂl 2 $ŇŮ`d…ÇB†Ÿˇ÷“=:Łă^yesF*ŔlÖąa¸óŘŹs(üˇ“=Ô0ˇa‹™tpč |ĺ+_ś{Ńr‰[n)›źfěúúúőďœâ˜í´ń|ůyś G§%—¸e xK3~gÜC×é¨tuuB(=œ ,çß6´f[;FˇíŐÂŇąâ3Ńb‹Ú"T8q´Sú„‚ĘLébź6Œ˘ Eq‹KŒäšMM>7˙žQ>œb™í?9…(ŸĎ›łcݍŮřޖßW•śˆ}=ňÁÎN§ŻGŞŞŞRwŹť‰[„ŃhĚ hŨ~ţŽíóbç*S<uĆÎb~ô?ƒĂ‚p|ˆ¸UƸ5Мóé@üŃýĄę}šH Żč¨"‘đ‚Gvj^|ń…Ž5S ɐBŒ$bý'úŹ55Ő9EšbçX}ďŮŕVj"_ů ŚRřb1{ú›ÍÍMřńšţœßŰ,ŒëęęÔQtÎlAގnbk%ą¨ă%—\¤‡@ˇ#gŠYŕr:3Œ8`Ásöڜ¨"ŁŹ_Ŕarň͉ů˙_˙ú7ącÇNI–} ěĄaUv{äX óXÉŢĹKîçȑîŒ^ĄĂ‡ŁľľĹőÚË:óA[[ŤNt:(źĆŒćZš˛ŚŕíěŘą#=ź˝ÍŢ˝{Óó)(2dÝyž|ŸďŘŘŰćŒ|cčđđˆşF­Ę~ό]uć™8Ňľű÷îĆŞęzçnčiŠWAoŠÖźIFąâ BŤ×á,uNl4‰¨%ÂBí‹f \„ÂĹő—ŹĹÁ{cÇd+VqÚşŐÚ—#ŒÔďďĐăôË ËAřýžt'(G/dí&§_D‘ŠľN sšÄČü]ťvkQČ)śŘ°Ł‰Y{Ö.U’M?“ď턾6ˇĹč}–ź°Ů´ée-ćJÁěëëÓ××ţÝ1Ú?ޏúzŹÇň,FÂŮĺEQ‹eÖ˘ĽŔřŤ_ýZ—ąŕśłG§ářqŤĚÉĺDd×8 ¨Á‰”BäVvCĚ­ rŽeŽöśĐńŕĂ4ű!řꫛuŚkŻ˝F§ŚńĹĄ”í2—ç¨)f(^ŃicHřƒ>¤C•Yěœb Q˛öÓąö8ší‡Ńl=ö¸v؃Äc{őŐ-b.7ŰuÜ`ş%:#Î0đBá@ 7żçžűp晧Ťž2S×)`} öÔ + QʘňÉsáh@śłČHżÓN;EHÉč ĽtŒJž+őÓ>6Ö?;眳´ăÂő)ţŃÁĘ7[šdÉÔ˝í=űŇç°k|żĄ°9¨R”†0Ä谁čކ”ĂŽěCĂŰߣSlm¤°ź '7_•.oééÇ/6OŕšŐw:Ś­“ď})A_…>ÄC=˘#yXâ5śÖŻ_Ÿ^†őŹX΂ž^WW§!đĄ‡Ê+”˙i bŮžŞ›ďJq…5Tš>kH#ôÇčŇeqvúĘčČÉLžˇŚ,2ýĹÝ/ťěR-&nÚôŠ.„ŸoôpúPéüóĎŐ) L)dQxťt‡Ó׼hƔEf0’ž!#ɲ—Œ”ăůq[ü~eÉĹď†Iq{/9Ę%™ľĹ€ŔA’čkÚ5ĎAČDÄ­EˆłŃFrýÍ‰˝ň9,šÄŹšvrŘ ÄQőؓöśˇÝ”ń ˝óÚđs: őőuş¨dWW§ţœŻĚł˙Ĺ/nÓ2‰g1v:lě!Œ9źđLů˙ůpŰ{˛(ŕP|aŻĹfĎWěXÖɆ…=÷íۏüŕGéáŁg0ŽnČů çő]šr%ŢţöˇÎ*uóŒ3N×QU÷ÝwżŢFWW—ţžčŮpÄJöĘŃI¤CšqăFíDćľÇ>6ŽŇ¨t~˜öȢúR˜ť´É•ĘmŚÓBŽť÷íFěśŕđřQô(Ą¨ÖWƒ _P§#Ls '"‹#n&`V×o{.şöZý›-ÔĆ ‚ ĚnśÖmŢ%_€ĘŠ—” snúůZŽ6‰çôć7ß ýŠ_˙ú7úYCŃř˛Ćh ^óôÓϨéY-Ź0ňŠĹäm˛}U7ߕ۽÷Ţűľŕ3Wé{ó;TďťďíŇĽČĹň)63ůŢNx})ѧźëŽťľXĆÎ*úrů çłó‡×É {ŐŞUÚWˇƒŮž.Ż1Żí~ôS}<ô§ŮYš Ƨžz×]—).ŇĽi<ÎWžˇëŮň|íˆ5AÜ1 ˜o8ŢŰ{ŻöäMMžÔÄ| ĘŃ Jí.lœZaöƒŢ.$N՞Ń+4śÇ˛|ó YćDRh­•ž(ÂÂÁ4^ľeŻ'ŮÂâąÚL§Ísű›ŻěĽ}äÎ;ţíđíܚŞžčQv0žzo|+ŽşńU9SÔŤŘNA(ćËf+ůüË| ł™/L‡‚Éמöu%][˜E*ŠJ7Üp=ćFĺ1Ťŕ¸Bń’ËfŠ˝9v”(O5ž9ĆŹƒDŐ6žšŠ)é˜LÇŤýPpţ ¸ Ť$‘[‹„Bzɜ7kvýƒbc6Ž!A eŚQ9˘ĐëßţvlŮxöžô"’;^C˛ˇF4ŹSh‹ GŮż`%ĐÚ߆S°úô3tosvafśAXfŠ”Ív„ÂŕˆÎ›7oM ĆTx4ž07P4fš(k}1ƒC„šGÄ­EDކÉ5ż”Ać ˇÚ[öH­çœs66nÜ  ˝ÚiľSŠ ŚsĐ †`§`¸‰Xb/AXHrů ł]_˜Ł˙éOĄëSq Š\uE…ůă™gžĂöíŰu Ś& ‚0÷ˆ¸ľČČŐS–í {QůBqzA8 ˆĂţ›b ˝KŠÍ\s<ő ËŠ8ł ĽEž(Ž|ë…ĂŽ?řƒß…P×]w ćÖă$Âü!âÖ"¤ž˛RvÄáaŽq \¤8NTzw!iے~(B1áV#ß2‚ ‚ˆ[‹˜B‰RAA撙ę朊Ľfa!5 YFa!$‚  "n š\ŽDą‰^âđ‚°PR§°☍€%6VAA(EDÜ*1Š%˝EáDłľ÷fŞS˜kÄŮbEŕ„ĹËBŘLA„rAěaé!âV Âű,WA„rDz…/ź63_ÂRHďžéźĺY"ĺÍBŰLA„Rfś6S(DÜ*!ŚFľň ‘HÂç“a|AX|ĐţŃ’B"‘ćĘfćšœŸ— Ňp„ĹÁ‰˛™‚ ĽH2Y˜ÍŠ„’‚7˜ÇăA4… Âb„öv°Đ›šś™ÜfŠ(+Κ ,N´ÍA(%"‘ÂmŚP\ˆ¸U"LőŚđz˝ƒ Âb„övĐiłY›i‹DΊŘ(…ca~)›)‚P b3…âDÄ­Ân˜řý~Äă1Äb1‚ ,&h÷h˙hgkN„Ít“Nä$ÂâŚŘmŚ B11›)"n•v¨¸ĺx088A„ĹííŸÓćBlŚ ‹ą™‚ …3›)"n9ö ĺě‰çfőŞĹ1:*a゠,hďh÷h˙l‡ĂŮŤćöˇŘLA+b3A §›)7"n•v-Nę&Ĺää$AĘÚ9Ú;Ú=ŰâdˆÍa1"6SĄpŽŐf ŅBŃĂ‹CĎ;UcŞÉ>ŸO߀ ŸŒÇ¨ŤŤ… BšÁž4Űá Ý›Š7MlŚ ‹ą™‚ …3[›)/"n• źálčŒđFE(4‰ĆĆ&~‚ ”:Ńh CCƒ:DÜv8ěŢ4§œ ą™‚ ,Äf ‚ Î\ŮLĄxqŤDpöŞńŐyĂŮ=lÝĄˇˇ~żľľľƒRO„’ś-™L"‰ča˜c1ŤîAeeUÚŮp:ůzÓÄf ‚Pîœh›ŐöĹf ‚PĚĽÍŠˇJ7ÇĂYüÓ!O$J…Vkđ6ő˛öDěWA„‰{!cÎ3RÎFe†ŁáŹPˆĂ!6S„rBlŚ Bá̡ÍŠˇJŒěşÄž!훒Š4oX§“Áyâl‚PŒŘ §ěz/Î)ťö˝\!Ű›)B9!6SĄpćÓf ҈[%ˆ}Łe˙´oÔl'Ă~o#· ŀÓips:r󜭳!6S„r@lŚ Bá,”ÍŠˇJˇŢľě›Ňéxˆł!B1âćXd×{qűűXö#6S„RGlŚ Bá,”ÍN<"n•8n˝kم@ٛ&7Ş ĹNöČ4óálˆÍĄ\›)‚P8 a3…‹ˆ[e‚Ýťf˙m“퀂 3nÎĹ|8b3A(Äf ‚ ÎBŮLáÄ âV‘"îœ'‚Pj̡ý›)B9!6SĄpÄ~•"n•!Ů=j‚ ĽÂ‰p4Äf ‚PވÍA(´ĘˇAAAA„’EÄ­2$ťMzŐA(œ5]ě÷ ŘLAJą™‚ …s˘lڰpˆ¸UF8oVűoŽ`ăöš Bąŕt.ěÂÄšŠĎ%b3A(EÄf ‚ Ή˛™ÂÂ#âV™`ߜ|ÇăH$zâ{ű5{YA„IöĚ^Ż7ýĘÉç󥝏šv<Äf ‚PjˆÍA(œi3…ƒˆ[%NśłFq¤wOž|Żl?Š}‡‡12Q=kâh‚Pźx<ęk‚č\րÓ7tŕâ3–ci[5€v>lŽ×ůpł™ŢÄ‚ĄCđ†{ŕ‰ӌp‚ -Ę&=A$ HT´#RšQďÂŘĚĐX˝‡F1xt cĂaÄ ´A(jh ý^Ô6T ŠŁmËëPYë›s›)œXŒćŽ÷ößÇŤ=yS“/5ÔäWSC4{œc;ě1‹D"8Ü3ŽÝý*~v?AJ+Ď_…wżń4,kŻA0Ô˝läXl›é‰Łrd3üb3A(}bŐŤŞ?IßüŘĚÉŃölîA÷Ţa‚ ”:Kş°úÔvTŐůçÄf ů üŞ>@bjŠŞ)žšŠ)é˜LÇŤÝ{âüYkDÜ*Aœ˝ht8&''ńŕłđĹ>'Z‚ ”Œčúý÷œ‡ŤĎ_‰ŞŞŞtH9)Ôůpł™5у¨xN"´A(/”] 7Ÿ‡ńŔŠ9ľ™˝ĆąőéĂĄ%BYAťxň…ËĐś˛ć˜mŚP !nIZb‰á,ŕɉÇíîÂw~š ‚ ĺű˙ţţłâ­WŻŐŽ‹r*¤F‚›ÍŹ íBpče‚ ”ĘćUô? Ł1‚1̍Í<´c;_ę† BšA›ˇĺŠCˆ†—`ůzĚÚf ŅBɐíp„B!<đĚśA({hçhďh÷lHňE¸ŮĚęČAśA({hçhďŽ×föěaK„˛‡vŽön66S(>DÜ*œ˙ŽĹbşpü—~ôA´w´{´´ƒů7›ÉÂń•ƒb3AXĐŢŃîŤÍdářמ9 A„Ĺíí^!6S(NDÜ*Aěž?šg‹ÔŘaŃ@{GťGűG;X(śÍŹŰ*5śAX<({GťwŹ6sßÖ>iÔ ‚°h ˝ŁÝ›­ÍŠŠšUd÷Śq(ćŁý!Q„EíŢťŽ;+—tŃOÚĹěşn6Óo†ͨˆŇ„™Y,uTh÷ü5');8;›™HÎ٨ˆb“AXćÂŽÓî­:Ё@<§ÍЎJ Ţ`t:žŮ,őAXœĐţ-mŤ†ßďOۜ ŰfÖFËËfkcQژÂb"_;$ß=Tn ˜*e˙Ćźłł™Ýă(”ăŻÄ( ‚0rŰç™lQĄś} {•ľž‚lŚP\ˆ¸Uä8‡cś':Żl? A„Ĺíߍ—wfŘE:,N§&ŰfzĂ=(uň‚Faې†¤°˜0 kČdˇwœ÷Z9]´q˙ělćŕŃüâÖ̂VaśFwAfƒaj4ŚŰîBmű@÷(:VWťÚL‰Ţ*nDÜ*ěË˝aßáš A(5h˙l[˜+T<Űfz˘Ľk3s5"Ýfçݤ),Fěű!W[Ā–瘗Cč*ĺ íßlmćŘpŘu[šE-ˇ"őš–ƒ$Âą‘aŻsDqYć-ŰÎLˇyÖ˛Óˇ1>™Ńf ʼnˆ[%†ĺ|$12 Âb„öv°TŰfz’Ľg3ÝG4Ëz3çgšś1›ĎĄ”ČŐřČŻŚ–áýă\… Ľ\BW)‹\´łľ™ąpbÚ|—Ľł–q~’mŹ Řˇˆ^‚ ¸KÄʰNŰnfŽ3]ěr.;ÝśÓţj3…âBÄ­b*E2J˘ ‹Ú?ŰßȟŞ7e3K-t)űźr53ćgĽš-#ĺLţ:ZSËd TNuˑ˛âş˛EŽ’¸ĚŮŰĚ\ö$5ÇšiÇÜ ƒ4}Ä ‚0{ň ßisl‹TvDŽÓL›š„ŽL‘Ë9ČF!6S(>DÜA„"˘a+ŰéĘň\śc¸/A(er‰Nœ;%TŽžúląĘ˜šĎ¨.GÚbÉ \ÇH.aËUÔĘ´ŇËdŘ"łŔý‚ L‘Óć:U,Úw;"×4§ ]Ó;-L丄ŇDÄ­Cţ‚ …ŚŘ”š„­|˘Ö´y˜žLööĄ<Éüg¤ŚŢ8e,K´˛‹gŹ™z™Š(kś6s&aË)jš ZSóDĐářČU Ţ)˜§SŠfš]Ů"×L—بŇCÄ-AA(B܄­lQË)hŮĄ3ÖÍźœóĄœ1Źđ+ëoýŻÝ`™˛řހSčÂ4‘Ëŕ-p•3 [٢VAËi›œŰrߏ BnʉôťŒů6ÎČ[[čҝ‘k&K(MDÜA„"Ŕ-Â*[ŘĘŽ‰ăľÜçeES@œ6aqŕlčdˆYö[Ě2ÓóŹĹŔ[Ę)p-ž‡ÝɊÖrŠZ9]d/ MQÁ #+ Qż`*ײŮ.B—CäŇ:WşV—á*p Ľ‰ˆ[‚ ‚PDäśÜ,ŤŔžzu,—t,Ÿš­éš ”Sľ´8Ďăš<ö<CôJ7’ě›dńFpÍFŘĘ´LDz֟fú’N/4/I„Üdw$¤#ł ‡­O X†›ĐeoaJŕ˛SEŕ*DÜA„Lîš4š…-ŠZÉdR‹ZńD"ő~ş¸5-UQR‚„2%#ZË!hٟe‹[´8ůź^}/x<5ÁŽ4Ě(.ĂUĐ*ďč­é‘ŸŮÂVŇLŚfs^2CÔҟĽDą)[“k2ąE‚ äcz ˘Őa¤çiťŻţ÷ž”LeŰq^†śHYůi—ţ,GŠ˘PZˆ¸%‚ E‚S€Ę%lQĐ2ľ •DBý‹'PS\ýÍyi+™™$)ŠBš“3ŃńšĄe‰Zř”š÷%á÷yá5é{tŞ"….7K7ˆ]ô2jlYö(™ś´I\"i}ľ,áË)˛Ű]iC—š}A„NÁÉQŢĄ•ťŹYi‘ËÚ+CŰuÚ%Ăź)ІZeˆ[‚ ‚PD¸5ňœÂEŤ„š˘ą8âJÔ GăjŠ"‰kĄËŽćĘĹé@."— ” NQËúcŞ4šÝČĄ UôĄ"@Đď…ßOˇŘ/P![ŕʎĚĘ(V\śdĽ#f§":„­Šˆ-ő_ҡ‡{069Ś?łĹ.[č2R×Ç8"Y"‘a^Š”t)ŤÂW)ř~Îőv*˘v*bËPSmU-š;ŹŮʞ'Më@žśGGÜŚ,yF ތôDĄqKAN nNÝ´¨-L‰Uś°Ĺi|2‚x -§_`};Ś\ždŃůf⪪*!,<ĆÇÇľÓżč1Ň˙č­Řř†v=Žčä Ş+­›& D.kD.K‰1SŒ˝ěˆ­ĹRX>;Ń)l%SŻ/ly=ó+ŒŽç܎×ëEMM JTœ-ńxˆĹb"p ŽOč)ěůáő˜h¨Ib`ԛw9Ťłnjškęjđş‹nÂy§]nżNMLŚ.Ú,;Eq1Eá–;"n ‚ BŕÖNsŠ\VÄVR×עP4‰"ęoBçEďÇDąc¨Fi ˛ ÂÂCAŔł ]˛ńűýđůŸ[čkŞFĹšďD÷ó?ƒ'2¤fžTę"?ľjpYˇŚ›¨UŢŠ‰ŮQ[p¤ş [>wxú-ZUTT ‰ä Ř¸¤Čĺ& fŻ“t#xúvó5PM‰T„ă€ĎŢŻůđ{MT’Z,şöœq<ôr5˘q`"ěŃ)ŮDŁQýęŮy.đŚj(R`˙ՃßĂÄä(ŽźŕĘZÓ.ťe§%N‹ŢJˇAĄH˜^k˜62b"a"ŚŠÉP mg_Q–PPÔĎńiuuľZä*WŹ{Ȋ°…=yühXs)_šMGmń3FxŒÔý˜*0?ŐţšŞ˝ľXpO×ĎŇÂÖţ#ťp˙SżÔ ĆŞŞ*TVVbppP \ló:O‹śRóVtŽACM{öě×Â몾ĐwhˇŽJĺTÖ˘ŁĽƒý}q˙íV×Ö#ŕ5PŠöŤżăDL5_}0c!ՂUßłš&"1Ń ŐЎA„Ů1SäMdGs§wEp ×3VÇP[5îžŢV‰HĚPs†.™ŕÜćą…sNś- ‡ĂÚÎ8—Ąýá+;vî}â6t.߀Îeë,ËđZ)‰)[d‹Ż†b9#■‚ !™I¤jnYóX<ŠÓ+ęÚ˛ÁÁƒ‡pŇI ŠÂqK§r:|ÇvÜǡ~1a_Ÿěëäl —ŇyF"ь÷ŮçĹϝâ–-Fp™R˝öď?€+–ť6Âx“““Ş!d5‚xN55ŐéÔ8M "јj€S˜ęŐ÷NEO.śPž¨­ŠYSľśÔësŻ<œţŒ M6*yy}ůŰIčˆÓxć˝ŁŚĽKÚQŰԊśśe¨˜¨m]ŠĂmm¨Ź`||ŠF´6WaÇ+Ď桂Á€fëP­Ä­x<†Xh I# žŤjՐ+Ë‡řh3"■̆=ÎFĘ.kŽáź atśGąź%† ?‰ ËŁhŠK Š6ž^ÝD˙¨/ámÓÇ$¤ßâ´ßق¸-˛ŃśĐ΃Áie´5Ü?śŇٟ}ů!ŹZşŒĆŐuí„DĂČ˝%”&R|AAN0ŮůŮŁÚ'v P2‘ÔЉNFGÇđƒüĄPßýî÷QťvíĆWžň?ÚäzO>ůślŮŞD˛Q-ěÜš GŽџ%ɂśÇ}súÎwž§ˇ[ěÜ~űş†S$Źó´ŽßÓąţł?ű ôööáoţćouăœâČK/mҟ=űěsŘťwŸžVüŒëe/ĹĐď~÷{Ř´éeüâˇéz\S?DžßĎ~ö ő›ú!nťív×TĆbăžűîĎyœü>ůÝuwwëčľááuŢ '=ÚhÂ*€Ž§d2#‚’d§Ď,†tˇě¨-SˆˇŠÇ›Šë´çĐśô2źxOPÔ˘¸•/â#¤ÄŚdx#źç"8rpżŚź0qÔÔ7#›Ä@?ŕőçcŞ‘Ëčá‘aŒéď1šŔ˛cQő‡”pćaKć€ęŠ$ş:˘Xť,‚ő7S—)A‹Â–ßg˘ľ>‘Ž*ƒItvİ˘-†ś†–*ŹŁ)Ž“W…ąD˝fŤ[´ŐŐŐé)ŰvĐžŘ~…~˜]Ż‹Â–Ľ<–îäŁ}J§R'Sb˝™ĚH‰\ ś|1 ‘[‚ ‚P$ŘQ"ÖßŮĺU¤rƘ–˜Đ#"fzbÝÝGpÖYgŕźóÎĹŤŻžZĐţžxâIÝĐß´i{ě -j­\š\ŻżcÇNŹ]ť••Uxúé§që­ďĂi§ŠrَˇW |_ŐçzřđÎ@A‘ ˙řGőőůú׿ŠĹ‘|<đ :;Wá™gžŐx.ˇeË}m††F°téźűÝ7٘Ąăß×חŽyâĆĄC‡2ź&ŤV­B13::šłvK,ׯÄŻ~őküĺ_ţš^–˘¤•f׾ă=–ôeŢ{śŔ5U˙iqÔeIGk9˘śŇ鈰RĽů÷DhljTƒ“‚SöźŒmŤy;ˇoĹ>ŻQ% ű<Š:f^ŸNň¨Ćk"×{O&â9Ÿ“j_Ąô{GEŁ­TÇ69ćŃŠP^ŻĄö‡ łÇNE>C§ŽŠ(AËÔŠ†/íŞ@]u]íV„ÍlRÝÇŹľĹŰ=c§”–Ŕy&A]œ÷#×x“{3ŁŽĹç’mgÝl?wFf/ĂĎěUí‘Ç'G­0’Ęn{-›ĹôÄtTnjÜĹ1ny#■‚ Ś#jfz¤„éˆ"IĽ(š™E’×­[§#ˇśmŰŽ„ŽŁ:żĄĄ!çţčüQ X˝ş ۡďŔšçžŁ~Œaɒ%8xđ ÚÚÚ´łŮŐŐĽŁ—f˘˛˛í(%jkktýŽłĎ>K‹[ÍÍÍhllL.hࢋ.Ôén§œr˛úü°úŹAúľ“Íĺ7lŘ …ŸľkýčééEąÓŢŢŚžďsľřĐÚÚęZ(˜ßy˙6oŢŹ[Ĺ.l ťšŇq˝^K¨ăwzÓMoŃŃzľľľž%ŘL‰YźçX\ޞ‡ŹÔIJoM˘ŒZ[śŇ\p/팰pß´ľŢäÄ8Ž—¤ÚO2Çž˘Šů˘k ÂąĄE+Ő!’ˆÇđÂv[÷ú´ ¤ŚŽ&ő ĎžFAÚ˛˝üL›UÓ˛ŇÖ!e;íÁgÇB˛Gu.$Ú{ŚŃŃXÎíYŁßZ[R9熣öVúQţy"■‚ !Śă5-j™HĽKY)AN(Pź˙ýďÓS˜aZP>¸üţáďçüüĘ+ŻŔlijjÂgœž~_čĐá'’÷źçÝéżď÷>9íó|ŕV”ŹErňÉ'Ľ}xťîT6ü -_ž\ AĽŔŃŁ=9=°ŚŚFO Sú8 ʼnĎç3ÝĈ­éŸgş…W\q9J‰wžóí9?ŁĐĘR \F˜Š˜Q$ß!ëWŢkŢŹ{Đ4ÓQ\ĺ0`B!Řś'ýȈârF—ÚHľëÚű1IĂSX|؂nÚöŘaPY…Ům>űu6ä[wÚígN-c"3řÉ^ÖČq\9÷k˜o…7jNmÓQ?юֲ:.œÇnU“— ­ŇFÄ-AA(2œˇŒĆ#Śęp%!6öđéӋŽ[Ł!2şŠœĄŔ•O|MŚ#$÷šÝ š>Şčb¸Čô”Dçő™˝-JfĄlXcÇ tŹ=]ŰNč˘ 5yë1 ţDH‰ô^uĂVz=¨ *űç÷j;7M :č…ĎkٰP$ŠEŸh,iĽ_ĂşŐýęó ĎPËYy†ÉTt+ńqž:{äDÓŽĹ‘=:=ŃČPĂl[šNT/1]GÔJaäścœâę\Ô4™â†u.fŞ&V†ÜŚG8tĚ3Źż­”q`řČ>ôěيŠňƔMO÷T˜‹Îž—3"n-ZÄŠáD"NÉnŕš˝wŚ$šoA˜tŢŤŞŞ ¸“™œ}ßĺ(ÇƑ™ł2˘Iáţ˛>a~1 –Ž>WžëăH¤ŇţkýŹŞńĄ^Š\“QŁ‘ꔐEAh0œĐBײ:?ę+}¨QË ÇWBOM…ŸG˘1Š–ŁĹABJŕVďGÔTĄʚ /Ť|Jó*áĚL„¨D3ľĹ/Ÿšá1(ŞQ첔.ű=’ Œőuc ÷(ꗯV( ~WS$%ƍGLK 7LĆŐg)á‰"\(i ŹЍUKŰXî‚ŰÖSŞśWÂÖŞ´m˛Ä-Žżóąß o˙N˜ńhJĐĘ´_ößV”YJ>Óç'>jŠ"âVŮ3K‡CüA撜ţ9Űš„ŻŠ˘ňŚ!,i”ĆٜŠHŐŐ"Ź+Śjŕźúě6ěŘşŸďÔ÷×=ݏ7ŁvšÇăC XŠG˛cCƒŁŮĹbQ]—Š#ÚY#Ć,áC­Çĺš­ ?¨z˙˝:jL5;aÝ$X)€ŒFđŒ*ŔëU .ŐŞliŔŘŔ0"“aKaJÄ0ŹH˜Ú^LŰ ÚŻjH™th­mEba˝}áG4…?čÇën¸ÍmMyĹ'gT¤ó^ËXĆQk1“ž.éĽ ,†‘J[››_áˆ"*ty¸ě6ŰqncęďĚŕĐĚ´žŠíRŘiŞô✎J%řx08™P“!56őkƒą*ýVDU@‰SŒŒŇŃRjŠ(ąČđ*sjŕđpŻľ\s_ ;ü×çOęöJ“J‰@fSďŚjŞŐś+*”°đNEgY…ŢM˝?F]ŃNOôbđĹť0Ńť=łç˘žm%âŢ L&˝˜ˆ!%h…ŐzI˘JYâöX 1nw,¤˛/=)A+¨Ž™×`Cs'ľU`˙PĎ Šm™Z‹é貔8oéěÍ´­JőSˆ(_žˆ¸U–˜Çô‘őąÜč‚ Ě†9CCpÚÇfžćTd:jŢśÍößv#œidÁŠ ýGúcÍ$Žčwć™gh1‰˘„]§ƒ…łíżY@œE™š<—ťďžűuáp§łýꫛőŤł8üń—áƊţ&ž}xžůݎéđ¤Nӈ+‘*%pžT Œşź>TTŐ ˛˛&5*–jÄ8ô:Ťú;‚‰đâŞaĂqŞ'ZpˇĹŸĎ“˘>oi+i'9Ďa||RżZ"–%ęŘçĂNżzNǙBŽśŽDSű2PŠŽ§E‰QqľN•R‚ę}P N}ă1ŠĹ+˘¸¤N•6¸>ŕŐ)‡GŁÇ,AfWWT=MJČň!eçŐw ěąYÉsóë먣°<–¨hGm%ŐyL& L¨ĎúڙJSÇÉTÂhŁę8Ć&"đىŚÁý¨ŻŤ@W¸żšďgčöŻ@ÓęÓQÝŃ zŽxU§†™:ŚdJ1ŰąS)qŠď|ę8jüÖˇqÁňj} ŞŐuoTBײZŸNË<2ĂŚž†ÔţjƒţŒbdŽˆS8: —Č[ąi%‹ˆ[e…YĐl°AX(ňŮíşäŐ˛Ě\”S‚UËe¤L™éš$ 㥗^ĂĐАv˜ŸzęŹ\šBHĆe ^ŚŞŞZGŇT*!Ťşľ Už€ęĺD˙ö=z™–ľKudX„‘Ëf$Őţ㪥Ëh-ŠZ^őYX h#ŐÔśŞ*jÔ:aŐ œ€Ď_ƒ_~GÁÚőkň^ƒĚ4ŕÂîI]ăeŃ!v—´DaŽ0ô󨼭ŃpT=“8Š+ë@Š{]™™Ă‡aŐÚľ¨ŞŠÇř@ˇşˇ8z´mmÍşó&ޞoQF&124fŮ  eCbJˆ‰GĂĆD(˘E& QŤ×ŹA44iŮ% Œ…Ń lXT‰îďiŻFĆ&ŃŢވH(ŹmXkű2„•ŕî÷{S˘˜:4%ô¨#%˛řtôjBŮÁ $”šŒŁ­ž5 ęy{5ŐVĎ×&-6őö ĄĄśB™Ď€ÚŸzUB[_ߪŤk02< ÖkÂ#ýŘş}ˇ÷îŽ GtĘo˝Ú€‰zőI}Ћ*e‡C1K}gĘŕ¸œ’Š.ÖŘŞđ1BÖJTouÚĄß;eź,;o¨kÄD$ÉHR§ňçD‚ ¨^žK;עľŠ Íőľ:Íëő`Dí—Ď….†pŠCŹRÇ|R“.˘ŽJżßŠdŤŻňŤk žGę˜VÖę{‰a[ Iőú“|BYχ˝J×ʡĘ3‚–ŤS"7ź ǃKK/ĎPËB—ŤČľř„§iž–•˝€ÂŤ†łĎ>ű÷ďGOO/jkkôčpö¨xާťššI9ęmŘ˝{ÖŞFBSS#–,YŞˇżqălŢźY_ˆ(+î3ar|4U¤6™ŠÄąR+,q ŠĎ”ƒ›°zÝŮťěɰşu5ÉôˆHSűąvŚ3Áńcłz‡­íÖz˙MĘŮÎU`ű×B˘˝ńŠQ—Œô. ÇAXi+˜áĘŃsl˝&sŚź8N uFÎ[§~ííÓF>œ‰¨˘ąîÉ÷AŐřQâ ščv’ęÉ7źi1U˙ÇÔO@OŒQ Şa捎R /Ő  †PÇŠąń°˜ú;2B[]“Đ*`T7ŠFĄz÷'TC4Ş~ IÄTĂ3âI ŚYFP„&Ăč~eŻ.ě÷ůô5fŁTg<2-’‘ #ŽÄ-Ž€TŰô댥Ö_Ň܅ńđ¨j¤-H€qŤeç\O4Lď0MGBÂńaُ˛›‚ĘĘ$1Š„ŠşúĽ!ÇuT4Uö% u=<ęůQ[[‹ČÄ*k[” R9#;•Ą¨ Ćľ-0ź=Bę°¤ŘŃS][*ĽŠ (Á+Ş;v–ŹčŇŰŻ68źËÖu‚QK ^Ö­ň(ą<“‘ŠĄĆĆF”-K`i} ’A†Ç#Ę6yĐĐҌąžÔÖ(&‚éSLm%ęëk0ޞŐJŕ ĄžÉ5ˆŞc1Uچ™É„>ž˜߂JÔJ(á(ŚDzÚžĘÚ’ązŒ)ƒĎ(ŠdŞč;ÓY؝śąJýÝ Ó Ő5TćßgL :Lóc@ŸĽ >{iĽ„މ¨}K0 VjŞŤÖBĄWSoh;"ZŞVbޘŽ&:*ŒŰdÄÔŇĆ Ő!ačôő‰Ć" -–ĘŚˇĄ%ыń˛ĎJr¨TjÚů§ÔĄśŽ?zŹ;†Bč<ŠŃ]/ÂwĘI8ýÜ3P×Ќ ę€‰Z8dßÁa%äŠ Ł;Fź‘8Şď斆*Ô*Á'‰ÄRŸM¨ßKƒĹú`L=Kâ8lĆ3FCœöÓUvˆ¸Uňƒ¨ĺ)Ďť%ńâA8 §xŕpÉĚ,őĘ!vŮś*ˇČ•Sů*kŚz§˘ťL‡Čᤳs•~]śléŒŰ]ľjUĆ{ ^äďx;ŠĐä$^|ä.őzXőr'1<ĂŢÝčGS˝ÍĘiŽoŞRB݀rî—âŕţ<ťe–śˇŞđjěܡëşşTÎ|ĎP?ToĎQěŢ{H÷řś)qjYK+ĆUŚV‰TŁlبFӈzÝwđn(ş~=ü:CšCJœŠRâČŔxT­Űˆ k×ŕÝz2Ž›××ömxôGßĹžń14¨ĆVżZÇî˝™PŽy:Ú[0Řw•ĘI?}É2%ޘ8ŤĹɍUŘŤR˝ů•hîUşFHßŕ8öî|•ľhoiÄj%Ö ŤFPm$„#Ą(–ŤĐśąQlÚą-jŰŻ[š\7ś†”xŮŚ}#cŘŐ7„‹–wŕAuç_t)ţëżżŸżp7/Ž#aľż¤jĐ ۘŕB1‘E‡kšęTc0ŚSjüJ¸˘xDÁ‹é3^őy 6¨NUA,­Y‚đř„ŽôŠë1>:ŽPŐŞ!ĘďËkzQŐ֒ŠZTďĂăhjmFmc Ő@ń4×QUËTƒT5ŽTيQŐŞĄčÓM^+jĚ`ąâ‘a-žľ´Ô żż_5–ލĆk5ރJÜUSpX¤#E–ÓńgŚť˜Xî8ŻA*g3s~:w33ŠTŽŠ=ÉD #ŞÓ€bE<EŒBĘÎT<+[sôČ!8hŞű[Ůk%Ś +•„w„"şܕ-6Ě&ĂJó3Ş4 Óę&”=˘€>24ˆ‘ÔţŽíEƒsا„F•ŇCaýđĄnéVb;8şťűtŞâdHíĂÖâÓöCZ„Ó‘ŤŠÁáőŹhF$:‰ŁŞs‰ŃFţĘ*L ő"šô*űÖŃYccăZ tĂôřP]QŤ#ŠÇÔśą x|ž…ĺ< ŞN”NńćgÝ_†>Żśj&še˙ŤKвű}(˜EM„˜2¨DŹx"őŞS­4BeRuÄmZ…ľ–ˇVŞmůuý+uŃŐšG‘Tâaľ/ĄŽ1€–šúG“¨F“ĘFs˝Žś*ŹnŻŇ×:Uţ$jÔ9)IąÁ~ř"Ű`2zŠ™•Şłmý™h_ێ†ö8"q/~ôč!l>Vë‡ńä“Oaëć-čRĎôÎÎ.,koGŤz3Š¸ÝŤ„ŞdL }j[ƒŔŘ ŠĹ­ţĄ ՁQŁS#ę3ŚCއÔďg4Œ¨ú›ż§ ö*-o¤ćS~Öâ‹Ä-/DÜ*'ň‰ZY‚–9m~ž ‚ ̆´Çzëü,%|ŮËŮ+3Š\‚&‡ŔUJěßťţ;DŐEgÁ÷Č3XŽŮ֚Ü?:Ś“Í64ŽE˝:Cϒ x¸"ǕçžO}=ŒA|F‰WŹZŽł_|=—\ˆFŐ řMs“Nő¨ŤŤÇ_œv V˝´›Ž=Îxĺě¸đBœôř“_ś Şœú‘áAüÒĽđІĚĐIëńp 7nߊ}JŹhkB°żĎ?˙ Ž˝öňiÇţřƒ÷âuý°iŐ:\ňěSH67ă•ÓNĂĎz&uĂâw ěXz&îÜ{§ˇ5ŕŇ^ƒ—^ƒ+ˇž€ĎןŒdȃ÷zŁí]އ;ŒMkWáۓ]XžŹ7{&qęŽmxćęËqŇKOá‘ĺ+đŚîƒ8ÚžTâ^ţĈĄI~Śz˛O způŘžşáœˇe3žR´_Ţö3|ěăĂgžUčץkÄ̈́î!÷ůTĂ@יňč[ŒččT׼: ŁčÜЉáž!Ř~Ő°iX҄–Žzěß~^Հë:i5şądőRL(3Śn“Şqšdĺ2ŐŔŤŇżßĘĆzÜӍFŐëßlÔëȇ ę…ŻŠŽÔČ&ľ÷}Ű÷a…ZgzÇ’Xˇf úôŁF5”:–ľ`¸oËźËuńăH,‚Ń1%6Ö4ÁkxuوŠ2•JčZÖşZż/ˆ:öŁČ•űjQźĚy(y0RžÁđȨž˛™H˝Ćă“úuD ń#ŁŽĺÂŃiëDÂÎ5a pá¨Ĺ M 'd}îÜăĐŕrvLz{Jě§ß™G(’™Ou~8łŢ‡”hf3>:Œ™×{Hß_Źm5ë(7 W“ŞsˆeĂŹQ‚WJäbŢ SuÔsÂÔń„%Ô3ŐĐŻ´ f˜+ńŠ÷č„^‡b"ŁcY@ž‚ƒŠĂjšá~ëţfí-FÇ1şË¨ďŔŔ “ĆŐő÷+;\ŻžąÉQxż€joG&ă)šaŐęeËŰŐöŞQŐR Î1tgˆ÷Šnź|H]3ŐŃ3ĄžŸ-›7cókŰŃÚąkWŽÂň%í¨W8• ‚hX_#˜ĐÎ(žÁľnŘŻëk…Ő3b’QbJ|cú¤×cę(^'b™ĘˇJ3ǟš,Óçf8S˝’šw#Ś@„Čhđ™YłÍôňśĐ•š 3U6˝°áÜîânX::KšhTőTŤŢaŻáƒwxfĎ Ú”ĂzúĹ lÄŃňüfx•Ăźě âĹ}ŻáäęjŹxe3<ŤVŕ rmÑ^=tg*ßľížG€ŞJœ­áÖK/ÂůʁŻÚž Ő ÎÔÇřđ8Ń(˘íKزŔÇ7lÄ˙{é9$Ć'Ńţ™8TU‡­ŻîÁ5>?:{ žłNĂ@°J÷ôť{$Ś{w9 7˘Ä›Ö“pĆŽ-Řվͪ‘ąl\‰PlS‚Í‘˜j¨.ők_~ÉpţfŕŕĄÝWT˘žŇ@Źş çM `üŠ qő–'áQ"[tő Ý­n0˝Ž žŽuđŠžţ?šč\Ü~¤IO ˝ę'”sż/œŔJĐşđ•—tA]ŠILĺd„Ŕl`tkŘ}A˝A]GKIDę4Yű$ŽŐŕ V´bthŻ<ń˘Nďi^ÖŒŁ‡UcĎĹŽ­ťątŐŢŃŁ„­^Üy'ł‡öÔŁdíSV†Ž 鈋ŢŢa,íZŚZ 5O„0Đӏŕx%üËZuÚKMU+ť–ăČÁĂčܸ ťÔ÷322†ćm¨ŤŻĆk/nCkk z÷ `Í]Q˘fPČđë˜G \vŢLúÔůřuÚîL˜ŽČ$ÁÓaĝݦvJ°  ýۙóýŠß˙@ćŤÎŚ…0˝fZéűЈnĆ´räÄ@JüaŒ"k™–Ŕĺĺ}JĹJMěËEÍÔá›ZŘb}3;ĘK.’´|.Ÿ×Ł;8Z-E1őXÑŢ0z ˝]Ö@ÔĹ÷=j?ÝŰP7˛ÓQ +á-ŘT‡Ú %HFc0ŐsšśĽ—œď7Dâáýxőđ¤ÚwLˆhÄăJl;‚žî#hlh@çĘXľ¤-MMhjl҅ö몃¨ :Ňot2œ:㓌‚cÝ/CŸcX=ŤłŁÝU )Ő凈[%KĄÂ–›¨••s†žÓOFbŰfěńyTĂbMՕč[˛ÝJ\ˇŸQŹÇ’œíץGŹŞŞ¨V=ä•ęşVčď&Ťç›Ł˛°<_Yp¸N58‚%‚ŐĐąŞ#ĂŁhëěŔŃśź !%ťqő˝újށ ?üŃZ–´!Šaý™'é´Čť`ɲvřý~D•pŮyöěݲuőhŹiBށ\ř~-&°ŽaľčY÷IFŽ]Ü0].ŕ÷ëß&ërôEŽ8Ťk„é,yŻśťąX<ŤćŸő7…+żzöxŠ‘ “–ŕĹČŹ˜Z&”jç%“–čÄH/–*Lšf* ĎL <ÚĎR÷—źLÖläd€É‘Śi­Ăíp?^oR§AęrŽŠď^.çŐÇDâŕKę8Âč!äńᏠíhn¨bŠx]KŃTěÄŠnňŕâó‚şNcR \[†t9qrBGŚ %ńŇŕöîŞB{[;V,_öŽečTĎSŻ'¨ž JŒSWTuęDŐr‡TÇJ¸ŚÁşfu‰'2=FSڷ厈[eDNaËMÔĘNSt‰ćĘţS!–€ĺœ3őĆłŚšv?ZśČeŘán—PVTC3Ě›”e¨îfن‰h>ř*ƒ8„DëiđN¨žfëcA=Jß3{öĄcĹRÔŤŢ؀ň°)X˜f wnڄˇŞÝÚ`%ÎQ ÍЅçĄzÓËđŒÁPΡɲ(Ş{;02„Íő0;Zpśj°Ć'#VÇŃŽ&YÁ…°ĎđŁ]‰h•CChQ˝ËnDŮ WÇÓآ(55^q);ö`u•rŤÂ\qđ :n zlígœs÷‡ÂX[_Ť ˇ.ݨ~ÜńꜨ âRu.7ŹlÇ+íÍX9t}G\}rúŢqp?Ţ­Ć ŻƒŁˆ)A묉 ­XřŘQLL„đÝCřťZŸnÉŮ?źc ÖA‰čŃMŽ’˜ŞmĹ[ŃŁÓ˝úú0ýor܇¨7„Śĺ]Řż÷֞ž÷Âę ëpôP:–´˘żŻ_‰~ÄAľż^m+ŠďeŚ5†ÂqT(Ť˝k vż¸K;—ă•ç^E’i%ăcŞQAËiëfcĚo ą­كˆyŐľčl‡Wă˜üź^ôőEă’&„Ô5ŕhŽuJÄP?%Î%Ź‚ÍĐřu }Ş{2¨~Ăę~Ęţ 8ŕG ăčŽqŽă°ĄęńuݞĄá146ˇ Ą–ŠŽ  ¤4´ ň‘ˆţ˛śĹ”fí$ڈąĄô$Ń?4˘çV­Z‰ŃáaÄÔŚN5°#¨¨ŹÔ÷˜.â=‰p4ކú=ŞÝ˜úš‘ TTPY]Cű÷`<ÁŇĽK°o/ÓeW*a~ńX%ęŤăˆĘÚ:ľ˝¤š?ĄöŠÄ,ő§ EX<‚††Z.F}ůt”™OGeŽ)qw<ĚNŤŤ‚ő#–ŚţO`ôđ^TOXéˆJÜR Î8šM@RQYŁÎG‰Řş0|XMqe׃ZČVˇ3.9cŠŁ~řřAěě ŠÎ#Ż%¤%ú¸ŹëćET‰]‡Do?8´ˇ–z#X=˛Ąa ŽĹŕUĎü¤zFkŃÎ,\ÜZĚѸ儈[ĽL>a+[Ě&j9-3€œéĺ˛3AWm. Ž„C¤\Ż´Đ•-rŮY‹ÎżEŕ*œ݈ěWâК5ŤÓNڄrôĆÇÇŃŢޞ~6đłÁÁ!44Ôk§ő™gžE˝jPžrĘÉz™íŰw`íÚ5:mČšNĄâ N†˘ŘZÄ’Č jş”Ó:qUŻżUŻÄŁľ~“ę˜”˙ŹÄ–îCŁxňđ(śďëÇú•+đśłĎCĹÖ-زööö(Qh/65ăŐŕźçń‡PSŔĎ7 `„#M˝ôźjŠ€ęńĺ‘M:ňjëŚm:e0遞^ęę˘űŔQŒŒôĄŠąY‰QJëU Ş*´.Y…#şőo´śe Fz†0txăJÄD}Ťćőč=4„ʆ8Žlťcƒ¨đUčýďܡC7ęšZš”÷ęÁÄŕ„jč$Wa5ęűłĚƒţĆUť†ÇSÎnBGÔ ŒiE^°éćZŠ\t؎NN¨ß͈NQ2وUâż?ÜNކ6ë¨%ÔFÂŹ)7Ň"ˇ›0Ť”pU÷ND ]‹qFqĹ'F­t-őýw÷ ˘šš †ŽŹRóŁ“RČRvatl\ Ą“cş(ś_Íב\e;G"J4žĐic?şť{ôy9҃ŚćfŐWâj8„ąČ$âCĂPˇƒÚ"hŹ čTČX<„Ńá1 *á+욞),t”•z~„#JMD´PO݈)×cŁ#Ş!ŠýŚŻfCˇńz9ÂĄőˇ•öz=ú•i‚źWxk1J‹őątĖÇ‘—ăkP‰ˇÚ¸,ëKňe$Œ3ôŔ.ęÎC€‘ť+5‘˘WDŮÝhŒđžôęg„şa€C/#˜cH=WÇœťŽËZkŐ3ʰ˘ŹŹĽě9*Ô:ę^H(!8ÉÔtu?ŐÖVár%p”@üÍűśaWO(5ĽĄ_ě+t<ązŞ{Ž?Ć@_v'˘ŘŒˆzV0˘śŮ :’–‡&ŐnԳ̔°Ýņˆ[%NáÂ֔¨5MÜʈŕrnQŇA(—tD#‰…´(e84ŇS:j S˝Œ–@wKpexx;věR˘Ő†”Řsřđa=ä8t;wîŇClwwwŁŚŚF‹]ĄPW^yšĂřŮČČ0xŕA455bT‰lhRc„ÂÁƒ‡°lŮRôööj„Ëp>ŸşnĹľĘĘJ˝í×˝îjTUUĺ=^ŠM^œ< 5Y…l{ƆiŤ„G5LkëęQUW Î ř•'ßŘPƒŽÖ8öíÁ]ťw ­ľA÷čr;CC#¸ăɧ0rń…hޭЎ:LÄüŰuՕŒœˆčFE2őŰâ(€Lm[łá$„T/sBőŽ+żX×â9tč(–/k…ďźsáM¸ " ęzU#¸ŠN aÁÁŹěŹŔúyśŠF€ßo˘ŽJ54L6ÂŁZXǡď{ŚÚŚ?h¨ů#:…d">†ĎţćWĘŠWü¨U¨F}o­*Şœw3%3íēzŚűÔ¤$ôšVM#Ţ#ŐhţÜOîPâSĹÔs~P̢¸PÖ ňQÜbڌĎęAŽĹu3#ŹDS}ß~ď$NݸϽ܉ΕýŘ}  í!%ÔŁŚJ]ëř0Z—Űu÷>4ˇxqö™ŕˆaQTúYo) Żş.á‘ILƢčŞŮ q!ŐđďöëßVЌĄŠV5bF–bugzĐ\s@}VĂcíˆO&REcőé†ŒŠŤ§ťî˜ĂŁEáÄ@1‡ âě_#íţÄبŽD6„Ëņ1ĔSĂŞá5Řß§ű~Ś.xôwi×â7L€wÖÚˇF`ó+qK§i%ěbŇ őŰ;¨ÓdŁŃ~ °0ś?€%í>r˝Ă:B$˘ěcB‰b´+I>ČßԘŽ,Œ+űD1•[ě>|U•j{Q Ťíńs]Ň;ul^ŁI‰!]ŸopxDŽH˝­E|ĂIýčߤ~˙Śyuä•תšĎńüĄ`UǨUŻUŕQ`>ŸG‹Zꡠ€Ľě§Ď°îÇŠ`âç^ĂĐ÷Ĺ0vöPhنĆű”Š…“Ą&TÇSH‰D‘¤ĺŁQ0Ł(<Š: Ć&Ő395a\}Îv9RĄŃ˝ Ť1ŒýGG10Cƒz†žuĘľ}uMşóˆƒş JÁŽB•O×­ Š{=Ąî‰€ęč˘ĎxΚFľÇ“ńľťˇ`ߐ•vQ˃AkDJĎT;5x=#ęe8Ć똀Wő´ô<ˆřڰbU—šĂ҄]dˆ¸UŞdߊÎTÄÔӄ-íĐ'ŃXWƒU+TOu}•eđ2ňƒÜƍł B!.4E:ýCŞ1ť˙`?†FÇucŮ5j+Uß!;EQ#&)'6ŹĂž=>%Xőë26—/_ŽD­ŁJ°RNçŔ ŁĐĐЀöö r‚úďíۡc˙ţş.%^5aßž}Xż~˝ĆBŞ”" çÇS) ĹVŽ\ĄD°QÔŐŐjAŻŒ›IŘ"L}Ť ĆTNyL9Ŕ ÄWNq<6ŠŠĘ:ĺĚ*§Ú]ž˝ś\ęŐsËT‚Kżę­ĽÓ:Š„ŁęŠ Zę”2C÷Á=X֎έšŰ÷`íŞVô NčĺĚTú„ÖZŐ+úáÁ~ĺŤĆA ŠŽý‡z•s˙‚+qňĆŐXžbů´c_ąf#bƒjC“:ľ˜Ä’ÖJ Ş†8ţdcaŻŢŁDĆ=Z`eMBْ1´,kÄŐלŁD1Ő ˆĆ•ŮŞőW^;„Ýť01TĄ{Ä'U#›QTáđ¸ş^^l0Ř ‰˘Eý]Œăśń }NźO*X@=–DœăşgɅÁT,ż<ŸNävŮŇ"uŇ*:Ě?#ŕŐ |Ă3ŞŁlš[TCŤ1ş!%HÖO“hCŁ!j@MÐŁ(pÄľ ÎZN’nrb˜Şů3}ţč؄UăÇńšU”~*şÉŽtŠDÜŁX.Ń-ŒŹĚ&žT“ýÎĐŠ`Œ*‹ę)ćX.¤'7˘Źńe—Zo$;†˙‡tý8FqĹlA+‘ťđź°xŕoœ˘hŽľŘ“FdU*Pb-;s*ƒ~EçW–/hEŕR쥧äȈŹ?ĹHFFë2uJ¨ZűL訏˜ŻÂqŚßC/Ďh)ŠÇ“ŒŘŠ'´8›J§Ję:xÉÉQŹ ďĆčí|“Ţ ŢpÖ2] Ź‚Ą–3ŐłËTĎŽD$œž­ÉPϜ`u%źJ„‹LŒ#66ŽS–×âĂo8_ťëUěíŸĐ~ch2„ĘŞŞŠHqĂĐLzžŔŔpcă*8ŞXB )>]\zr2ŒńąIôöŒc÷ĄA]B#T=ŐJĐŕĄ0íŹ^9ÇJT3ŐźŽś ŽˆZŇŕGD9Îýƒ“hiŹŐĹné¸ÇS5Lx-îÝŽšV –Q•XąršŘÂÁ¨íÖt.s=ö€ŻŁ“-ŞqžŐuÍł†Hr3*+źĹWb,~2FĂtŢ{”hŐŁLƒ\łń,œ´&˘ŽőŮ>ú‚Ú†ýŁXťv˝Áö+Á¨W^҈­Űb÷NK‰PŘRßaCm3^ÇŁc¨TBS•rꯪo@łzžWŤcZâ÷`Ÿuž¨lTÝ.̚˙Ÿ˝˙˛$˲ĂŔă_ë˙㇖Š+ł*łd—誎Şîžžžî €0°5pÁĽm\.¸Ć]ŇÖviśk aÜ1‚Üš„Ćě 0ާ§u‰.-RëĚČĐ_kĺÎ{îó*¤(ŐU~Ť"㇋çĎýű{ďŢsď=Wž‰şÉ D˝Ŕ'ÉŔ uä=ĄAÔuş˘82m+,Ďqď9‰ž/‚\wBžŤ6J×FH, řX‘sĹđ œDjÔBŁZ•+bهäťĚĄU-˘̢şŃA­ěÓԘ\yDş0Ş“ őœz ŇȡÇ Ż•wp‹•şŐ&1y”´ĺ{äwIBü#||óŽňEQ>šVóň™?}Ňű™EÔ9bˇQí´ńńˆŁ@Řv0ĚO> 1é†>$ŁA]#ѐ=č; ”'‘ Şü°¨#[íŽM`$Xˇç¨€ŒšlˆC¤Övt]dô4ő­N×׳ÝsşfÖ(KŒÖ”IT˛-°z! 7W+Čɐ:ńŕMgQۨ 2G8=Ä{äôX $"óvŔD9v{Ú6+ó˛čƒ/,ëôZEœ@UŽáwžv˙ăwĎ`ąP×ýM™LŕÎçFpů‚Ś .ďGSę•„Ź­şM‰•Ľ-Kk‰n}dYün`‹č<˙ţ­_ý"ž}ňxâ‰'ž|„@;ÓDţůüFeóí¸\âíż=ŮSbQł´´ę S),vžcŽM§S;śď$R'ൗ|ůË/Ţő˜Aâ÷3]Ź…Bi…MŹ—zšŞŠ €âk‰2ŰÔÇBŽ‚uQ’o,”g‡ZŘöcd$bU@ˇłSă8:ĺĂęF“#a1*k˜IăĽÓU̎%БwŤR7QRCٌ´WĐŹ!^nV[$8R5# KV™éĂ#™}__š…7zV ä0^ H?›Lƒ|‡ WkEVJ{ń7ŸÂ÷ţKőZç×לqК•ç.`Z,ŽŐĽ :v ąx?÷\V@ž$~~2)ŔÎ5źůjĂđ„Éřčś˜•ţ‘Uęـ…v0†¤ě9/ŢvňmÝ촐 ÇŐ`0r!Žĺa‰JßBrůT花Óó; f)Ó>|T$ °b “AGŔ&ÖWě6›‚聾Re×nœGvxQöŽE„Ź5°ÄP)ćsâÉ€39"}îhixŸź‹Ť7ą´q]Żĺsr¨I;“G‘™ 1Ľ÷狙÷Ři55…‡DÄFă@ Ť¨÷žŃ~$şgú‹gÜxÂw€óŁÇ{ĺÉgY¸&0•É7­ÎΔ_‚SÜî×ʇśŚäł łŰ V™H,FˆXęj™Ł=štX–Łę–‚Xś‰ŽŇăzśdŒ:sÜ0𠘰6°´œÇFš "Ż>)ž\C™4üєĚë2ˇB[šŽ0UŮń)žŚDv qź/–€Ýq´đą‰$~çëâůŢi܇ Ďeę-~ż)Πjě‡ĺR\°ˆŁ<œ#ă6Š1<ŮOâ[Ÿ ēľ-zK~yhÎś<ńēOp^şpy G.ë§%b+1qGô–'Ÿ鈜˝‘k ^i  ÓA×!HÁAŽęľ6rë ˘j˜_*˘,@V€ŠŹź$wކ-ä›™Hcz<ŠéYÄÓeDzÍÖqcĂʉ&+: ˜RotĐl4•#„@`œŠ˘5ęeŁ\Űô\75%ixdŮĄ”‚_ƒű^Ľ:†ŸžZ0Ś…LşƒąŃ+¨ˇ,ŹW"X- 1ŹeĘżů~[ú^DCî§X¸ }spöĚO1œar8 gω"xZźßu4ťIőşxöه`Ĺ'°˛:„ââyDüaü¸[Çá(c{8H!2`Ú´a|Y”úXržľ›¸_aÄÉ´•DŢîiÚ&+(2ýŞŢŹ X—P“ƍ/ŔröAô,lŘuĺ ÄcZžY++ážcwĺű› 𺀧ă8xě ŹÜ\D Dj|L Ä[+ßuĺű,–ąą~]žÓEtşŹ„A,œŃęˆÝvŽô§]—ëIĤŻ1’bbuXuŔ”Ťˆ…ťÍßľŃ$ÜODŽkÔŤ¸ő3räÄÄXGC¨U˨5vF2ŒŒh´HP ő†źĂŃhDÉŢýáüů}Z˜œ9 `¨Œ]ŮŢŚM.ßu ҔYŚü>ހАŘę*7š°ČD.˘JĽ˘†ůńŔŐk×06>Ž÷…2ÇԍEhmś=Ŕ˓OB,Db1 Ľ7Ó똞ĘŠD\8Ńx\ÖŒŒ—Ćí\čo|L? i*;SÝŰĘ_éŰLV€ËĺQ&# ŕ›nĄ›™ŻÇľ]pŤŮ6܅˝ŢVůŇËsluşLᷕ‹ŸmŰ´Ďߜ—ĂĹ+°ýMś6:>üĆ32ţd~JČZ”Ńˆ`yuťm˜3-ł3LúÍęŒ\SXń”)đÔtaśü dÍdÂřć“GđŻz +Ľ†>­YŤ!ŽčĄZ”i™šJĐżqŹ oŢßoâ[ŸQلłöˆÚÚ$×éÉÁÓOńhj<ńēOĽp~zďqŰppšŐƒöŠŢrźŮěs!51\WVJä4I#…D (´=Uz{˛ż#€G빚†˜ë߉x4ŹUŚž|xNÓ/§Ç#HĽÂ˘Ěŕ֕+bKűĹ&âQQŽkbˇ†üÁH këU,olhJ=ŕĄ˜I#ˇRÍŁTŠ)ÇX1ĂÄŘčŔž;~ ‘pˇnÝÂčĚAœ9÷#,ĺhDGQnřp9+ŔĎ˜:4‰ƒf‹ĎIăňŽÇpděŢxa$0ş‰Ÿ\XÁO~|O>3…ÔÄ4’™–—×1<<…fk¨ä(q\ěWúű2Ó4Ĺhż&†Č51ô{3ǐaę ŸÝě1 W ¸|ĺmÜ/ĚçÁ('ĺj#‰ĎÉ;˝Žr™´ęu­ZbůxV抄Ր Ů/ Vűę°:a§…€xęCF9’ĹQ[ËŁÖĘkZᑑ§qđÁcX¸t mf e…,\şň'ŠâuČłM(¸ŽÄĐl4ŞH čHÈ}ô č 'Ľ˝8‚bůMÉ1íwŻX…/"ŕGȐ|3RÇJ&MşŠ'Ÿ¨0s ÓeĘhƒ*–…Ĺ@gŠq:›AŻŃFаŽÉéY¤3it0=ń˛^1ŹCň=Ś’15äiט" ŕLžd–ކzJ@VFˆŽ^u]‹cPX\ƒQŸSS3jÔç6r8ůĐŹĚ?TŠyxâÉ'!D^ClqpN‹D˘ĆtŚ~C ŠďÎť}ÔX­—yX‹((PÔQ˛xÇ=_9%™†Ř/Ô@ŽŹžI7ě9Ŕâń•–ŁUM1Śšˆ­ Ďdýh ##­”Œh…DŰí™żźˆŹż†ókXŽś1w`˜’yÜ€.(kFSš´,HœFmńjhËoŇ„"Œ˛•5$*ëMÇFĽÖPn:]w"2ˇ“ƒŤiçG#žrjöÖUlÔŔ–9Őéˆ K;ŁŐÝJČ,(b÷Lô™FđŁűKÎ|ЌĄTLŢľ:äM|ípjŐM˛úÄĐ(ŽšÓT­¨€˘ĂC=ž|ňžŚäźZóăâßňē-1T16á˜IĽŞČ(SˇBbżr¨Şś`ćjƒÖ˛˜F[Ɓr`ĄhŮZůWšłZš“üë(ŻĎqQ—WžÂB ZÝĘYČ6:pŰč™ă4J‹íń|ˇd­­U0ÓXĆŇâ2VĹůÔ ĆńkĎEžPÇÄԔÜTPAŚV­-óvWX-ś"‹Šô§‹üZmÇR^ШT>y‘˜_ů›-ŔJ5D˘éK@ě0沞üđüřĚ<6d>’Ź^ÉŰĘĘžŽež-¤äü …U<ůě‹n}će´ĺÜj™Ď˛GBđēݢœ*bźńĘ÷1ýŞ[ĽčŢÎű¨R<>˘ÇOS˙”ŕ{ć{ę9Q 3JřéÉNŃů‰Ę–2 őŁNąYgëů{×çIč Ž‰rp"€+á ‘  $`‚a%%šS\’ Ľ”€@+ ,Ż—0œ á聞đÄQ%ĆÂhĺ †Yľ/ŒńюcLW˘PoäŰxôH–K9žr-ÄÂAőSAĎmŹ+ӝ"áB˛ýÔŠƒűîDŃm/âňĹK˛„Q.ŽbrjXŤ ţňˇ~•ćsxď˝×`‹‚´DiÇ1ő2Ž_ëÉ}v‹ŕ~źŠőb ó8qâ$=>‹6NŁ”_BąHB÷ŽIE݆Ĺ?ŽhbH=ô“L‘öşő bCy¤łłbDˆ!ŔQŻSGMúňAŚ,JšBbˇÄŘąämĺF‰0rĆψʞŞmń˜7Z MKˆ™ă'W–<ßŘČ0ęËňÝů’b¤ÄĹk_o<ä~‡5’Ť!ŔY2‘Őg Ś‘×jWĂĂsřB‚Œ+źCĎ˝ô#‰!.s&ÓU*ŒŚI2Ő3Hđ†OŤ}ľ”_Ć2Q`‘űM66¤ŸZA,T°Î›{?yéuŰX_YÂú€}ŹĘjwZXş•0˔1Ô Šľ›;ü[ˇn\ÓĎů/ű:ďF~+ęj} ˇíďˏž÷ýMcúđáĂ8wîܞÇzâÉÇ&•ş!?›•˙\éÔëw:]SyKäs4Pk'`ŤUm]ťo“žgHŕ[]ˇŞĄc)8Ő%‘|ťŤm7’‹s§Fh9öE0Šˆ‘n—żűú—)]‡ÝĚc˝ÜDžŔ×›Đjş5ĽÚr2#n-FmYś8gĘŘXˋCŤŽ‘—LĽŹ @Ցőqbb͈_l×@M졑™Ç¸â| x×ҊĂ3C<rŻ^9ĽÚÔ(ämeô°ă˜Šˆ|Œ(V‚yż!˜÷fţý%¸őY–)‰[\[ćßţ6ÇKáńdOá›ńŇ÷˙˙˙ţ÷P.?Rop8ő‡;WŤäm*˝wo}P;fŰś“HŚńkéŻâwţ濯¤ÍžÜ.ŽËĆПłŹmœ[ŰćGăy˘Be‘\LÓ˝Żs766”˙Ś˙™„ň+++Z%16Ü ýýť%—ËÝF@/‹ °1DĺÔA,& gŒipäE9öÂHE-˛˜’&^eQ”ÇÇÂČfc˜0‚K”Ř …\ą‰šC´rřcŒT0”Ŕ,ĆÇDŠŻ;ÇąVbœHď\h+Ů{łmkĘZYž•V\đC‰É-ŸV˘b$Á­jy°‘qăĘUœ{űUŒM„1:ž‘ś (—/ˆ×ş†ů¤˛GńÜÓßÄ(‚jĽ"J{“3byeA€ź#É"9t śhańô,–—Vńć[xřň†ä16>…zľ‹ĄĄĂ¸ríM´ZLąŤ RXC(œ@+ÂtźĆœD$#^q[”űôĐ(•uSúü>‡ %ň”č“{§ÇŸ Ľâ˜ˆŚ™Ń(kwL5¸ُÄIҖw¤ňä> EN`Ô:˘íۇĐn6ľ˝fťŚŠ#‹ŹčȒôŇ×Djąô0FffQŮČë÷1<3Š÷/–‘™ž@#_”ďF@ĎdRŤt´"˝ErâJ•Žô‹é>̅ˇe:nţž ˇl‹hSâJËĺ6ŘţL4ÚŮŠŹ¸ŠˆŹć’Żi.¸ž g;°ĺlŚ#nł<ĺβşş˘×ÂÂ|đAů{ŃhTIš×ÖÖqčĐ!Üźy““rĚ"Nœ8Ž_ý ”J%ŒëńŤ^xáyźöÚ8räVĚçó,eŃngŚMŒĘ5֐H$ô7‰›Ÿ~úŠ{ŽtŒ„}Č Ey3‘TÖĆÚR ůűÄá7ƒ j2­ÁÁŘhǎ%5ípd4#űâÚ6DĄžŃJ‹źWH{!igx¤§ŔĘÍ”dlźuÚF˝ĹRä>” rO%W–ÎyV×/rWÇ7Ł|zLőĐčŸÖŔž8ţ8 ĺ^űţďi$ k5Čă\EÁ!ň|ĽĹŠĄT\‡ÝЉW;Šxf¤ĘŠúĆ%QčeÚŠÔœÁűbpŤ!˜’íhĄŐ¨ ŮŠăĐÁ86ňcbda8Fľ„baUçîVišJÉxFŽł…Ëu†bäŇýΈśŒ9€QŢ=ău—gĄ†“WÚŚü‚!eňdD”Vě ‡ŃĺqüŻŰӊŠL/l×ČÖĂČĤVZd ÍŠf˝*@]Ĺňá¸ňĽ4j˝fG¨vłĄIbhHşx*ŽÉä¸űXÚ}=@2Ž´xűůu8ň^05ŇAţ†!ĂçœŃsůŮŘG+BD )ț{÷ťx€–'Ÿé:ś`ŕüĆâJ /  .´d-c”jŘoŔ*ĺÍrL…EŚđi•Cۀ^pŁś:n ¤† ś‰3‘Pć|#˛^ƚ,ÜŔZaIŁśZţ0žţŘJ•6b0ŐZ=ĺŘň…d°Űâ´2|_Ť9TnÝÂÂŇvœz c#Q%ŠoۢS͖5Ü…`bŚZ.#t-„×*5-j26>Ş|{ˑÖ{MM[lˆŁ%‹Pu‘ŕA-Ëu“z˛żÄˇ>'˛3%Q?™żw۞x˛MřnЋykyI 4ŚçKE5NIpICdźüÍ<řž$Yn]śWÄ[ŢŐ< !ńş¨ĆšˇÔĆ˝„-}O‚b×ăâłLőŽşôľÉęH˛đŇKÓîďŽ cl1%ƒr͎>†5ł˘ Ó6ëőÚćqédRIl …‚ŰÝÜ‹E4şŐhlnóĹpK?Y έRăÉ`1Uƒú•z÷g@j˘'wLÓďż˙žVś+‹˜™™Q`ëĺ—_Öc˜~FĺpC”MU$ZćqgΜĹÁƒЇzčNŸ>ƒ!xÎ{oŃŃŁüšví:}ôœ={NÇ çFzņuBź„žăršŤ¤śÉ " WDšČdH Ňţ$ÓöČöRą%ŢŕeTŞMoŹâĹ/Dz8-sOîů<ŚFmQpňwCK…÷Ź 2CŹÄđr­š(ÝŇNO<ÍŐFW+Sé<§tD+(’Ź>_(ëS`őŔAŇkÖ09s#S‡pĺęQŕĹK|cMúčÇáC`­œFIžńĐđ¤<ż4*Ž€ƒŁ2—ľQ-Ĺ1;łŒäčŢyý~ţKIt7„ƒa\˝^ĂŻýR?}ů2Ş˝¤ăe\šź†ë×n˘^6s°‚@LÐg G_ąÔ5šŐ#b$֐­UŇűó (ÖíľQ—óâń$4AÂ1ŔŸ˛ť˙ġ>Ó˛Ő ł m}4-ž|nĹ1‹$8L‰…Ţ YDůŕÓSN×ŮrÝč9>ËD.9n•*]¤wE3} Ŕ”ďL×%06Š1”`’‘OŒÜrłhłÜ0đŞ×댖 „ôAő:݃RÜ?Ç<enŮT€i8mŢ;=džŰˇłěëć6%T†r؛déđö”~ꡉÝÂfjâ€ăź8PĆĆĆ111jľŞ`óňň †‡łš2xîÜyüň/˙˛Fn1Bkii ÓÓS l1*ëąÇŐąOpƒźNśqęÔ)g2 =z-kŒÔ2`p@ŻńĐCęř"ŘÍČŻ{’šŻŹU¤żĆÓ ůŃhöĽă$”‰<$ÝÓ;ˆĽRäDńЉ *ę°kčśl\¸źŒúŻŢÂWžCv̇zĽ‡ĎbęŔˆôů–WZ8wľ‹…\G@-˜Ş %”§0u<#,ťÎĘSś;ׅ”ƒjđťF{!!}<ńđ“˜8x•ň-\ťt^Ó$xä*‹‹âĘVQćł'P*-ăƕˇpôřăҗęm?Ž‚€8),ŹVÄHé*`5,ĎvyţěČWsZňڎä9qói4–R§GZŽO0¨ŐŹ+iwą”ÇŇę-%VĐýDlł‚˜šŠţ{[ďŃÜ˝Ož ™ÉŮŇŽŁŠh—ŻŮĹ,@züxЧ’Č ŁTH Đ_P*'ŠŚô[ŢĽD,Ž8I|€Eťm˘Z Z+ÁŠÄŃ눗_P͉ŮYŮVC.W@łŃÁÚzAž_M "ń´€W!X˛&1…5(ëAOֆ LÍiőÓTä!y,üůçiBŸźÜ Ë:ă´&Ŕ{ŤÓÝąŸs‰qRAǝĺFi8eęůy2ĂŁň]:¨ ŘŮqS¨,ŸĎŐĚz۸~“3ݟŽĺwuî;vü!tëE™S‚ŠZ"™ź A×wI+‚2užxňqŠĽdčÉxLÖŚŚŃt4ŞJM‰¸FŻ &$`Ž­k_ŻwťĂ˜K×?:8ü–ߐ§ť|Y†oKćB>w-pĐâ’ésŁ•y=“Îč‚[śÓOö1AWˇçÝízĄúš8Ć֑Ťľ5’ęńŁS(VZ›CË  ZŹËüÝPţJö!ULœK5;ŒZŰQÎ/mŤÇuą;şŐ=ôGĆű°8Ш<ÓîŕőŁňœ:2†š&Dʼnܖ6¸ţPGŢč6;şV…-qn4ОśÖd˝‰şY}OoÜOâ[Ÿuٞ gëÇqvĄîđēŰD§{Q ‡łY,-/ŠGž-eˢÓЈ‹Îv´( •Ât4ˆx´?ôX[X?qŃkš r˙ŹMJpgWAkç’S.–ôg@O7˙J§SŞˇŃTŁ;TV1śýşP32€D’ś›fÉh’^§ă’n:m QţQímž\aŹĚÖżrߛśžąa€ł]*p›oťzMOTSźTŹúĺ7Z´‡7ď%.°ľ9oYŰćłÝź[ž ”d2Ąż™žKaÄU_yäaýM ŠBĐŤ/'O>4°˝ƒân˛ýÍîGjľ.–Ę(ŐldŇ1 Ĺ4Ľ",JЌfWŒr̊Ií@Ń`@Ćq …|­zëë%?ÂčđAD")ó6Ę-6dź‰Réüâi ŤkŠyGćŞ F’Ɔ“j0Źĺkhľ{JŠRÝFŠRÇzžŹĆ6…żYľm0oue ł""žĺLڇ§żř ČKż2™QÄýIœšôĘó7ŠăŕĄH%SXź~3s‡‘ćDłž<,€ ßýaɰ…' áň|]žMNÁžéÓ‡ pHŁ_ ZŇ˝§Ć{"•#( FR<Gž¸Ž`óyŚ€\‡yśLd 4ż’sö˛8säZś€S7 †!ÄČ5ë]­l7vhŠ‘ 6V×ёůš+€čô0Ě š+kť5`ăɤFÇ+1řI|,FÚ˘€­LŸIPF§ĹňźšV4•Đď8ĘÔHŮ4ĺ‘óBHźő\”|vů &űü鸎v((‹Źia/-ń“c0eLƢíŰŔ­”€Ő$šNĘwŰŚ‘Úk+€N$¨lŕú­E¤3i4Şuîi0óý @ĘękPƒŒ…5u•?‰XXsÍŽŘÊFNáúĽuŒNŽk:lfdA§­…ĘŽŻŹŕʕkb|{ ´'ŸPçćxHÄBÜ$4≕B+„Ô廙 Gd ëŞî=Ü҄C÷= 21@ÇoRuËQŕĘq×öv~fÇŮTŁ|°7i7Œ&ě>-HČŮVÝŰÖT?éKńJk X-TĐęKÇŚtnN¤eŒv“ˆĹ•žëČxď a74›Îčŕ]FÉZfŠŧ•séŒŕZĆš\\ËXAą!ĎFo%Šg‡čý‰4â™.H“ žĄN0YŸÄ)Ô Ý!‡¤Ÿ’ś‡mí3ńŔ­Ď‹l_Œ­_jăĂĽ‰yňů–€x8ş˛rEDYdÔ $xă‰ÄԍzUQ,wđKÉOTĘ/œœÄ#Óń6\.˙Ő{9ĚŻ×LÉámbř§uťňčw1F˝ó(&%Á—Ëĺuť­ŢŚž8A=Ď/ AtbĄěčV4ŞLű4VaÓKĚňăb`†˛c;ŽÓżîf*œťC?ËŮ\_Ať˜ÓĹő^…mĐĹgéÉޢó”*b™ ˇ#˘ž|Ž¤Ý˛Q,ľŃOl<ÜŃęw"[ SůĘ B:<ŠéšbK‹K¨VzjL09Ę莪L*AlŹŻâÉci$ła%7ďő,„ŠW|Jř>5‘Gô–…J+‚˛€0>1ƲiŘ>3{Ĺă!$LIŒŕÖ҆[îŢŸŸؖ(îB gp9×/v B˘\OzH~Žá՟üjĹX”{š>đ(đitë(lTpá\/>ďˆœŠ{ éˇRŒ#<‚k7ΠŃF­<cÇK?rň˘8uę¤ĚĂřŁ?ü\š|Q<Úâ1ŸÁ—żö‹ˆ‡|řÝřkňŤ‘qż#Fzťă¨ĐÔrk‰ÁĄ˜ZŕÜc߁ŕ“ă{œÓiœ”ŔtČëďŸP1 Gžnm] š]A  axzLAŚZľ! eX+ĽVJ /ščŐkrÜŞ™3ĺ:ŠDJćöˆF$tĹĄ/}XÖAP ĎŻĆ ?“„#ďOž?‚Œâa‹rˆą0@$€áTŘŤ–ř3Ž—u.ÝžOu‰hT#§|NSŔĺ ÉşLp˛\iţ4yßhź7äHÄ]ŐŇ5ľĄďAŇÓńÚh´‘`ËѨë.şbL+H;9™#6ˆNd†5âŤ.çˇjLNN PÖŘ?O<ů¨Ĺ¤ţŽ,Č:ÂyŠkVłAGrW߸:2ě;€Ź&jŃđ!Lňš4~qB(˘ nŮnDEW„~Vƒ˝xŮŽ~Őç˜Ýá}ľL!'91+hĺQ(QnۘĎbZœ­Ś€pś€Îäł h%s0ůŔ`2rŤŰSŔMSÜÝk6ÄqÄh,Ëu*Çq› ą%×Ô,żé•?`˘ľéŕ“ľ5Ő!^`[Ŕ° 8°ĂŃŚF?“rĄ%6 #Đ-4cĆńĐ­ý$¸őY•˝*ĆěŘź…rykś'ƒEŠHLź!A¤Óü "IŢ]X”kĘ%xß.ˆgU ¨ĆÓxňŕŘś˛Ýf}íf –‹FŠt9V¸`ńw FłYßä ¨'V 7Täö꧍~ńç0|ňqĂíe›A˘}˛ú<ŽgŒŕšŮˆĽ—ž‹ŐWţ˝FeóI0ʍý4œ"njâś0?9Äh a+ɓ˛Š{ěęűź[;őžâçA˜JÁŔŸhČŻQ”LAŒFE ˆźŐjçÎľĐnŠ1´ę(—JĽE›#–q<Ѳćż˙783ÂôTRŔ.Ü(áO_š†§OeńĹ'˜žŕúr …ZO eSŞœŔI@ç[S˜őqęYŘşpmiOPő漳xď˝w14:‰áń ŹŻŻauő*Vdދ¤Ćp杗Ĺđh‹b/ŕ]˝…Ë7_Çťoż,}8¨óŮäP ăÓE1ʨ–mźđh“s!\ťjăŔl?} řúĎ}ßů“ç^|Ń@A—Oż,Ú¸€pL˙´4hbiy+‹qîěi şŚ4źu˙N-݇'‡aE‚8ŮŽ‹ąP5suœ'Ą$‚Fů9*[-3?2ĘMćߘlžÄÂőEt5#kŁl&ŚfĹ*iÔÖÚ †ĆÇPČ吝p+¤žöJą‚jЌ˜Ašv§.@–8[XYL‘~#× ÁĎ#sdNÄ#°™Ţ ˘YZGKÎ'!> ÎÜDŽĎ5'd´źÉ÷g!Ž1Ýn1Ęşą{§1F˛śçŔd´tłŢĆňb@,“ţżş´(ű: †–Á(ăŞëŠ‚[¤%ČŕmɹՊ_ ŕh$˘€ZWA+óĹ_ż~ 5qÖÍßźáV‘ëj$"ű8!Ű{E<ůřĹĄžŰŕú~|Ň(X‚H2oň9yw{úNwťˇ;RůŽ2ęŠ)ǘlD[uXMËľˇĽÚŚňaŻg€2›Î ŸĚąĄ€Î‘Ô› @Šz‹-ŇřÍ%ĎÁŚs§ÝGwĹ[(”+ˆŚR8q`T3'"™”8Œč|ˆëřĺřkŮpy˝L>űÚUę’íwbô|Ś–Ó)§EHĆ­-@ľ.“ÝĹáÉ4{feD¸_ômöš'÷ÁôF8†T<ĽY&´J%řC5ĺż%ޕgíÉţÜúČížĺ­tÄЊžx˛KřV´ŤT  ŕ4uĂo%  .Œü›äŃZ…Ězƒ‚˘xúĐ ¤VOtŞŽ \ŠČ/.H$š.îJ5$Ä4H*ŻŤś 0r˙0ÚigHśŁçő‰îťť"+”7‹^{7-ĽĽŠ;b°ŠŃ“Łň`YîĘmixóÜmšdď\4“˛đoŚTr›m:ĺ#Í.[—†Ş9Öq9Čz(ŠĄśă!÷˝FŽ7÷–mó–uűsňHĺ?BlČoĆr<(óŒÓD*J \ü­Ő.bÁ:ŤŤŕU ×FžÔ@§ŃF Çúęšx‡m4Śâ č"@ŐŻ %ńkQvăč h¤ÚBŘ  áŘҐ6‹]…BĘcE#—)ĘÁ€(Ő˜(u źwšâ$ăœA3ăC:? ’–%Qœ—n\ĆŇőKh;b(×6¤rÍXF@ˇqř1’ZB#hŚFŠTÁŤ?úٗ~řö7‡ńßü÷ë` R"ŔdŤ‹SÇý¸5ßBŠF*9¤¤źW/]ĂË?}GŁ–zžóî81dÁ ţô˙Tž•á^azľíÜżW+$T$`iô€ Br˜˜ţĽšššŁ‡5JfŁ\’śkňšŠŇ•2†˛ŁjÜE=Ěçéç˝t´˜ #ęü2‡sđÉúA +9”ď*„&š ĺ{a4—Ý(Ë{ÄĆ͋HÎÂԑă( ŘAż:VčˆńińŸšő‰ SžhpNç,`ÓëÚfuĽŤEYś€°ţůŐjg`;ý4bJË­{Óş Hƒăf]&ßÖś^`VŃwŁQŻzŤł'Ÿˆ0⊩Ů}1ŃJ;Ľ˝—Â1|[LÁUÖĺÍ2:Źe@Źžƒ–üZ‘Ĺ2!>łÍśTŲÝýĆTÜłeh7xyŸßEŤ°‚ÚĆ"ň•j2ç§BDoöÄůQk!IČľ1ŰCÇ1E”¨gł´IG œřś“\{E׎ĹeNš~1:˜Î‚u,ţń÷™´ĹPȍNł q>ővi3(녅‚p…"qq„$‘g[­”•çŻQ) ÝčŔ“ý#¸őgŕ6gŰDĺěHQ؀u—żq‡cvŢ}ěݎ٫­{šö‡íßîś>ęţÝéyěľýgń]ĐŁ"ZIĚÝ^UP‹‹ ż `ˆ€Küš~7Ÿţ>9ՎV Iűíާ~¤Ó }†Řž=0%ˆŰéďGxŠáě3˜ë– ÉŚ1ŘěŔ5 ą žôCŁéĺňť¤™JŽÉżű‡YĘ$Śe–;=łčîz‡™Va"ÓXUŇTtCÁ4ĆöĂ2äÔÎ^ßĹ~;Ž5ZšăFqí&•wîpş'Ÿ-‰ ř3”ĄŃ ĂaEĽvÉnP@óś*ĂľVH=łLŤČxoˆ÷7mcyuIźŰuLM áŔ̸V.}`6ƒ?[ŻâGŚtyđP Ż =űä!ÔK9Q˘ťX[­Ëů%™ďş bE"A5Ž[-ˇŇ+IČT!ż×¸€eŁCЁ}?őřIĺŚńäÓ#fďâg+Ž‚g+{pžxňiŽŽ‘ÔY{°6i–{ŰĚž?Ő2ĐâńÎă}ýÔçžëčksŃ0_ţIgD%ż˘ pKÖĘx˜kcBőć`4.ssTŁÄÚ 6‰ëHĆtŤ?ŽĹ Œŕfbh„š:Š-לęuČŁh˛5x –Ś!śĹQÁBtdw{MMI´ž…i ’Í5&Đ hz:>F€ł€…Ăľ,•ľ#)íő4ň̓ý#¸ľ_ÄšÇíÎ}óQžżçŢoűwŰwˇc>H˙îőšßëšńwáěţ˝›ěĘÝÉE¤ÝÎIˆáPŠ×QĚĺv  Œjbؐ ’+eż Šß]Ěx ‚ ­źFé˙ÝOGěÁ›(-víwÉß ĆńĂÝe*ƒEƒŚB›Ýn˘ąş€Ü•řV_Ľ˙%ů§ş´ ĄËôľP_ş‰ʤu×h —žčĂMފbŤ˛ŠKß]ě ‰™ű÷ÉĆqŕĹc˜}ę°yŚť:ü˝_Dž'JúéąýąÂqÈIF]ŢOĂOJÚ-—ԉ…m$"äŢň Ŕá¨ň’ů%ĘËřŽ(~ÎȎذO@ 0rĺ"ą(†‡âČŘú X\ŻÉřś”„úŇ­’€K6žô…1S]ĎĎTëcĐ*°QikE€0ÎQ‘†€ow܈'ď0é獃S˛ńjŞM†ńÜsáÝsçP ) !"óĘG§1-ˆ’ŐŐȒ÷ßzS€˘5Ź.ĎcyšĽ´VWݤđĽ'j8r0Œ?ţ~gÎÖđŻ˙ź €]DżË3I˜:Š7.,ŕɑ1üŰOL㥋—Hî Ůáüľď|N§ĽŢyŢG:–ÂŹl?łp÷+ĄdŠń j$Ő§qÂÔéť?Bzl6ÓY˜&XŤ#!FKF@(+ŕCŻŐQ~٘xňcŠ8|LŖ˙xĺZŠTLŁéŻÍŤőGô]¸vUž÷8RŃ$bâm—‡‡H:ŠěÔ8šŐ–<˙žĚŸCj°(_Ł€iuů|ŕŔ0ÂéŃQ󌓢X­ Űn ›`KŒŽ~FŹ$MCÚł­”[,U´•şŔŠËł(A3ż†Í*šź˝ElŤ]ŁsşđkŽEVEl6š˘´5R‹iËY‹LńaľŞ87Öó¨VkZľ4JM톞áö#ǭâ4ęřł=2˝}'¸ő9—>ç7´=š/‘Ő)@/ůŁbŔŐP˝Xť-jŠŢśńĆbE+şiLOƒ’/†ŃɉúaĽÝ\q7ˇ÷•ÎÝ琍Ł$Fc_čGuő%°-m¨[—ţœy Őką#Š@Ľ$†oË˝šƒÂűŻËqçqŻq@ŽŰFOús݊/ Ĺ˜~fÓ_˜‹Ú‹wĺׂ'TnŢźŠ ÇŇŃŁGäsoźńž|ň őş2Í÷üů‹8räižŠČd2šŽĂń}ŕŔŽ\šŞŐŠD~Ü"X †ŇaXôTežš,`‘ŐC*ÓE§!ăź\r e¨ ‡_ş€(˘Ç“aŒŽ$d(614’Ĺ×_<‰×Ţš‚ŤKU4ŇR_‚ěôZ“ÇĤËź"ű˘ĐćÜś[Ž\ZÄšw_ %ĽĺĘ˝žôÂł8¸šĂÚʆ(čXá–V‚šJ‡Pn•°xý *Ĺ&BŠ…Νť‰˙íßLâ˝wŰ8v(ˆßűĂ<Öl,ŹĘ=Ž#őăÔD…Ć’c,őF0‘L`btË+9ř ˛řđHŞŽ†š<şVJŁLď&Ł“Yâ(äJ(ĺeÎŻÔĐĂÂ'ˆ%ď=5>‚ČTCň,ŻѓďgzzCs“bź´ppnœë!yvÁb卢ąt d‹%Z/ˇ¸$Ŕ¤–â°H %qĐ *UHĽäO“i‰S"žŒ  F&-ŔXȇÄi°!€% źˇĎݒďz żýo˙6ć&űůŐPs:=M5e”×ő+7q|îIxňÉK (€ŻНV]ޑ‘ÚLëgz#IČ3’ď›)…¤< iĘjŚ™ě°tiËů†fËP(_ŚźmÍ÷ߍfá¸fŞ1 ö čtˆńÇŻ‹Q<:šBšŇÔkYž š#=(rŠ\1k˝ŐU™UŻ7w#ŒË\)Ž2gGR!ŹÉ8ŃjwbŘó= ĐË(ď!™Sil—‹%ĚîyĆľ';ÄRŕ&‘ˆŠă˜Â÷ˇI@GĆ ßužŰN[)BËkJ!Ł“ä=ŁBŁŽŠ?ąbŹă:dÝč-“AáÓˆ&Đ> ěZ&B*Dg4Ą,[‹Îęvf?čx ‹Ó"‹QšĆ´čżţŇ-$:9qÖ É\,Ŕ˜8XX„$[œż9Ž!3Îű81&Űç7cÁŮę“r}šÎ$-ü$ş=× :›¨ÇđůhDZËTEgWÄâ>yfŠNĐ]Ż×đ%:ô+ ?…•e49f˝˘DűJv,Ś+J9~iFuŹę(ŐőÝŠV[8:‘ÄÜtHîÍŔH€šĎ‡§Ôƒ‚Q ŹČ& Y"•Ť 0Ő1ŐQŁ‘ Vg{čôŔžĎÎeńĚóÁO XŔ녥n\<‡•ľ†´ŃUŁvuĂÁjŽ…h0‚ů1 âŔ7~.Žr)ˆŸźÖ’6â(U‚8|"ďýř&ž{ö9\żrQçʏ/băŞh'Ň,IßĎś 8sY čŇŽ,ˆő†zĚkB5[5%kďˆ#`5ߒůîţ'šš<ˇŐĽ˘Îy%ű 65ŒgD†ĚpM`eÂvW ł s^MĆäůŠAĆ(.ż|Ž 8ľä8~Ś—ĽČúÍp8„Â~JMÄźJÄèJ;cÓ# fc!„y#Ÿ-l G#HFä{÷9ű#…Ɖâ-éC˝ĺhÇ`×ǣ§ŽƈšŽ‰觤{ň‰‹Vsc$Ć'˜_ Ë$h őJA€Ž”ŚR×Üâ@ŕśŃw&RPFn0b…@) úX<.vĽrŮtTŤŽŞÁëČ[ŃkŁ_qˇ'í°xĎŸB:—wÂѨĚAŹ’ę“w'&×- 0 †‘%.săŇâ b™QŇęĘţœ Ś#ăSŻČ8mő.Ai™ÇşŇGÝľż­–‚4Đ-Ťö‘¤Tzňů~„şßT'qύDäťÝŠ|ZÜ$¨‡Ĺĺ$%fů bŒ˘ĂŠíZ¤iž„|NČzFAŸŇŁ&ă§É´@Żúc“€bFHů|†o—}𹠈rwqz–uŇňŠă™\źŚ"ŞOďŠ@•ęŇ273’Š|Y›ÚÍ6śe$şú2¨vşf|˛-ŽălFs2ň7ęÓč1ňHö# ŮWjěŤ!2uŒŢddąč<ě3Ť7ËĽ °dý­×nŃJ:m@™ŻýçwCđŤ/¸­ŁGâ“’R=€‹Ëa„D)ß(ľ‘JĐŤőPoôP”}KšŽŚ ‘Ť# Ŕ‡_y<ɈîG\Œ`´Œ˜úť¸ś´Ž|ŒʆP˝űчłHĽIź+^^1Jo­´°Qlˏ§ˇâQzŠű¤ź=iˀ+JŇ3U Jf[[[`ę"zż(Ţ™cęh†dî@%B ­ÝD ’ŔÉ㸾˜GaĽŒq'„‡ćÂxë´V$‹§žppmqL ň%Éžˆ;…Cł‡°‘[Ç˙đG`&ŕĚdďéŕÜ|Iďý '§Q°ĹpOáěü†&mŹçćMU+w~3Ô~ÜŞ ÷,ŤEüôÍwTňcîŔŒôe\Œú8R!1üŹVdŸz`\ÚąQŔ,,ŕYY>‡ýŽ?Ë×W6ĆäŒéT 1vÂň,Ú&ßšz7=ya a˝ZBŤA içZjxŠ:(ć7d<ŃČ퉳L€ÚÎ ü2†Ú žŽ.-ŞąMđłĎÇ(nc WUŔ{Ÿsé ,Ć{Ď1NŻžÍČéćfŞńš3§đŽËqUĄtŐ÷qţ (`ŁżŮ2Ą˝Ţ8&Ć >ä8Ţóëč6Ť` ͙ —ĹiPǝý$čWÇ Ŕ¨ĺÜrlŘňd§°ČQłŽőŽI§sL%W:ŹÂ[qůůîŘ$ŠD=W&帏›LŁç<ŞÜTL ”ßý(*Îd?Ť†'ŕ2”ôŔż‚PŒ ’ńSŞ5ÜmjDŻÝqIŕůĂńÇ9šŐiÁS.1źfęuÝâS>q E4 ‹źľ0ÂNq$h|ĐęěˆČzkÖ)ŽaĺěR]<¨Ńeék*“šź’śÚęLösÝGJ"ލ“u°Ł)•é”fşrHŽ'" 4{ĺ"ö—xŕÖ>ÇóXz2Pœ{ßƒŸvEMŁŽ¤ˇč5eş‘Tw‹ÓŘm[<ˇQ1¢ČçňŞœn&t-Ü4ÎÇ'ĆEA_ƒË\°ăœ~°wŸ“ĚO-ŔÍr í–§‹ĽĺšÜgąxTźÚb¨ˆAĂTFéx ËËĐTm‹@ÂýÍ5ĄT#Šń Ď#ÆcŇĎíFŔŻ-żŰ$ńůthœČ˝ĆĹ5n…ý›H‰—܏ńVú2ŚGŇJÜľMú 5~ßśb“ĂŚ„|ŽÜŇj•1F0"K)çĺť`QžI¤˜R(ßg¤ŇƈcňŻ…,ýžž{­ €ÂńáZbhÍšAox Ťb öR)ŹÉ÷ٖgC¨yUŘ<šáx¨u?xĽP%lgľß(Ó#:O“&“Ń[ä* ‡C&ű çhdWDć̔ĚŐńP@šCšŽmi”2Ď%PÜhľQőˇ ŁrŁ­zkM@ĽbĽŽÇPv+JnŰ]+Á”E:Sd?Á*Ś ŤŞ­)ޞć"¤‘”]—ŤO6ďs9"١90}Řbô•-m*—\¨^­éÜ@Ţ<z˝^פË߸ p)1‰”vÂĘŃŰe˜ô3 ĄU+)̀'űKýŸ€SGš1ýZR>@Ξ;T[Ґhż)%Üf¨‚ŚŞŁlkßAĄń‘•ŠJU qČǘ&´ăJÔŰŐçxcŃO\Ą'w]@änłˆj­ĽóQYéN7ŹošTFS dÍńŽrrô°´’ÇĚhmŚ+vBŸÉ„qx:|ľ- qÇ a$J¨Ů(ŃŲü–š,őŤG™J=ŁĘőŚŽIMeVÍŰÖÔ FtLŰkڛžˆ#ńtV#SŽ.ś‘˛CJ4=6‘pm\Œ ŸĚ)âE†1$&ĆGŕ;UĹÁ‰[Č݊âđH ŤĽҙuŹŹÂĘŇźŚ^ü“öđĚca,tbřÉ[ť(Š‚ŸI&qčéIV x@ŔçäQú đ˙üsÄÆëęÔŠ'Q|őĎ1;:‰+K7î›b*M!03* QQů0*“"—~†üˆ °ä—FÉ%ÄHF ÄÂ&š†Ď°Ĺ¨šhJçRŇű\’`†ą*ŕe,âCFQžďL2ěZŒ6°€*ăýŤ‹řB…vĺüŒd󨍥˘¨KČ Čü`q5™ä'ÔHslÎ^¸ĚäŒib8Ę9<(9(ĆRąŢŇRőž|ş„|:ŸJq˜˛(€{㳣űx˛?„ÓmT@­‰ń!qÄĆtC[#iM¤UŻnh8"Z0AÖ=YËŞ˛ż^Ť+č‘ős4Ł•é´h´LĖF-śMECÎĺŒc›\ű…›٨ ŘĽŃMua:˝•AœÂ§¸Ÿë)~ż:­˜ŽH`* Ł8x]™Ÿë5ѕŰ<Ф&ň|V@dşpXŽkÖ &Á2VÁĺšĂ2mm¸*ĽŠFXG4ý×Dź1r- #, YXŸ€d /vk?‰níń–fO>˜œ:|ňQ•öŢ-ęŠÄ|ây$ŽD፣u휂T{ńgńYŃɟÁč×~U b—ż‹ćúŇŻŻ#˛O}™§ž‡ďőŁôÖO4bŹŃjퟀϚř'ž|`éWmîJ‰ý´ǃ’ĂîŚőœżpéŁŮŃ zŠm˜Ť˘l7ęuL¤EÁmUŽ ˜Ĺ鈠s"žĹ͛kxčÔa‡@6›ĆŸ<‚ˇÎÜB˝R…-íĹ3!äK]„ýäţ°4Ž&Š˙P2‚3b °°Zך(!Ý+—[Žu4âç‘ăĂ҇Ž(őƒ‹eX˘Ř_¸’ÇĹ–Üa‚~ńçÉďć6°ą^ÁŁŸÔʀĄ`$^ó0V–Űxöč8ţđë(\ń0ă Ľ~ôŁ ŐĆRůaźňŢqôČ4&3id†:xüOŔXźŘ7‚¨ŕ”śf w4’Š!Ě؉JGŽ Z˝$`÷+L„Ű°Đ€€IŁ~M­ :=%önYAy.>Ô8ň[&uŰq,­G#†<\ E}Ah.šžrsĹŁú|#Ż–Öqčŕ„ńȡ$CҞ^ů| š|I@ž^}÷nć*šBČnŠseŁicm6‰›×–Ń ÇńؑQ,^ş„d<.ŕäŢý,.źő>bs0<5)mˇ4 @çL:lˆ”{–Rxr_â˝/ž|*EćÓd"†3Şďś”X˝‰RšŚ)ü|oť6z˛ćř!ŕĹőUSe-g3UWâ éÚÎVTSţú܆ňš|[tuę=Cóa™ęŒtÜ2ERi@ä¸d:ş3ş,đÔjjUfťQĂcG§đâĂ1$kZD@ššXË ˇÔÁ!I<óŢ Ćő 8×Ď!GŽjźč.!eůózš6ÉJŞ-ĂOćŢÓšÎd ĽuÇ O>oâ[űDźEړAbxYîňn|Ö¸˘˜“/žČŘ"3ˆŒN˘}ëʝ—5wA÷'3b Aˇ”G0;ŠćĆňA8Zq˛/vč„ŇÈ:Ž‚€[ţÝÄšn9fĂéăEO>ZĄY­~z+rąT4­]Äsę1.ՐM'Äëk ĐTŐcaSĄ˘Žœ;!Un{ýČGŸ!˜­ŐJŚŹš/ŒŽĽŢ§DÔâ“FĽŇĂTş‹fϏd8ŠN‹)oršźŞُ‹RŢŤ, Úh&‰dÔ§ioőVO”l?†Ň~DâPG"ďŠ"ŔIuGG"XÍ5ŕ Gä;X@1çĂŐ+UźńŢĆÇzˆ†lřĽŰ—Ď­!=ZÇH‚ĺÉ7L˜´ď˙¸™ŮyärHĽ3˜ĺ|qá˛z°‡Ňc¸vënˆ7Qş‰ńĆ0|Ca4ĺ˜$ɲ›=LOÁÜ؄€xEź{á °şc:9ŠĽ|îžuů—.­ŕ'WP¸6ńÓEăjÝ0m„žńNťkř}†¤ŚW?‘0ü(ŐFǤ”Č÷`^ľĽ•ż”S…äIJ˝Ü˛u~ŒˆĄÂ(†<˙ůë‹pUPŽ”0ľ0˙ÚOq֟Ԋb–^ńá,–Ž„‘ :¨Ż_BőĆĆĺy-Ţş…ßăs?wSăCxy!‡üůyů.bX­ˇĹ[ßÁőZ Op˜ŰXEë~ž|8ą”ƒ'&ăŔ/ă˛z‡PDĆ燽 ž(đœĘ ôĄPČŁűRKM%^ s‡ÁęÔpkai“ŰýÂ4Ž|ž0¨đBY=fń‡˘˜žB)ˇ"Ű#ŘČĺ5J%›Í`uuÍ[ß=š'a%A|!𩢠Oć|Čw‘üQtś˛JxŤŮžÍ)ۧàăĹÇČÔŁjĂ2ď'¨2 ňPݔ\W5žX霣…čČőkÄcnKŁŁm…őšą4›äö$h×ƌŚěbOĆ4UŠDPůľHßÁ¨/v.őZ ŐrEA§FŁŽŃTŁÉ1´Œk)@W.Ç0B,!Ď# ëL\î_9Øn`Zb]Łł˘‘D>HOoĎoRŮ-Ś\šŇŚ$ÖD#‰˝c‹S+”ŃČ-žg*qÓ}"¸ĺ‰'űXœ(KNŤŸ¸„Ć?óőC:Ó-Q|ç´VP˝zvłîznöö[˙ÖĘ-Ź˙ů(ágăć•M"Í=OŁ—HŒÉÜKßA'żŽŇ™7gkĎT ouőäŁ—Ž›:Ű7â>Â>ŇÜ.TâŰâ}]ďôđŢůED#~L%ü2 Î Šçˇkȟ-S˘œüL/<eOœœ@¤ ?.YúpR*”qćfזüřţĘRń ĘmGŔŁŽ€[ś’ÇOdc¨Đľ–Ťb$–ůü^őŽ*ԇfH§ĂbĚ6P­7ŢĎąĂ!f˘xďý˘śľź\Ä˙íᅪü†<č)×ÓßűŻÖ5%Ż_Žę?ůťăX_V–sČ۸z˝…ů51dÂŤ˜ÖHśJyG 2‡Ëóď‹wşĄçžýGxýŮu˝´ş‡Rji‘ŽýÂ×ę5H¤{éÖ5›î×1ą|ć*ŽżqQ án™`DÁ ŚnŽŞbŕC+F,jČ śŠ^¤xÔýŒ~ ieŘZC€%1ÔBb4 Ĺ|ňŒŽŠáˆšw7rÉ$´ÝéŃ8ürc1`H@ƒĆ°KüĄŰD’-ň}3YŒY-íüĹ ň˛ż´ś€°źůŽ'OaÍą-ťuërÍČPv8‰Łx[m\9űڕşM›€'ŸœĐpgÁ¨ż§ďî•1›Í ˆÝC*eŞŸF‚Ź€Vƒ?"ŕŚ}ó֒Œ•a”KUš›EÇńékÍ*Ť†Źžl¨ ’ řT’š -ďY@Š&ÓdĹžvsAAľcǎÉ8ŠŁ^.!=>+`śźĎ~fe˝Ž 005ŐÔyŠü@ąx Eť˜Ł)„;9œšp§TŔç%5™aŒOÍĄ[/ čPpËOî&–EnŞ(†22˙…F•ëľ^Ť é3ŐůîŮ2,+Šuy5-o—°RěP$€ž#k˘ŤČ;AM7 `h3,ˆs&›0 9śj9Ś‚iOŤČv•HžBŒ‘Hžřs[ÖX‚^ž9ÎoŔ՛KąÓ \ě Ř,},8LrŒ  TŽu㨊ř”ŽfѨV4˘š`v(G,‘DŘŚ>pMú(kˆ!Ä)€ĹĘČŃD\#њ˛UŠEuLń˜ˆ86œHP?3}ąŻwwäŘjľ§Wé4,šś'űKźąčÉÇ#‹‹‹ú.łR"ÇJ$6žTQţâń8ţé?ýgřöˇC~˙süĽżô› œ0e`bbgΜʼnÇUA¤G™!˙C2Ž>N°Œ}l3]Œd´˘°>y2‹ŻźřŢy˙ŚPŹ\ÂÂ2•dCZŰĺEťÁˆŽroÄ8ľIąňžƒxbÇć’(TĘŚJޝ‘ `ĄÖĂŐůŠőžFó,Ž xÝé)S"AŠ:ŃHąrŁ‹Ë7Ęb¨%ýäß˙ĹŤ|˙‡Čĺ;Č×:H$Ä -†ůŘń9ŹÝX‰¨ç'GńÝKĘýÇ`ąá;W:˜8äGeŢŻ\b“!\ăűćʲró}ă‘ Ź–{¨TH˜ŰÁđř´ýuš8[FŽŔ05Ő7S.ř/˝üéx?@FW ŞŽ€]9wőć-4Ę)1`ĘřâÓ§đŕÓĘ]hR`ĽbhĚ/mŕôľ[(‡˜BąŮBZց° ľz‹Ë2^l#)ďS9W@66ÁšŚš\ťTÂěě4Ňbě´šžJĄ!óéĺK70žI#%FĎp"‚ľĺ%×r8ńŔFSŔŮ÷ĎŔ'ß]2žĹĘŮwP(WpšXBBňaGŔ’ů5ŒČwŃˆqŽaąV‚]çu[đ䓝kŞ!vä{ÉÔl—věçüB€+špKžÇ•ĺŒLĚ  •ÄúňŠžßŽŚäŞ”JGP.W5ŞĽRŠé$’–sm|LÇłiĹB2ţ@傩´Hi6jšö;=;'ă5)YTŻWďř1)sfQTĄhł““šć;Oɸšc5Ż ÇVEć—GOĐČӎĚ×WqđĐ4<ńäžÄuÔhĽBz‘čłŰš’Ď˙l— }Ď&,=ëďgčVyľ]úgGšą ŽĄţ˛ŕhőá f-PW ă¨§ŕ–mčv ~šëşâók_ ‹ ÔTůmíƒM‡‚ŒOŚ@2˛ŠŠƒ–3ĄŽĐŻmóao ÝF0‹ŃŔ\óy}­zŞ7Ĺ ĺM8aFsňţ˘§+$í'äyYZ܁bŹJN^Ž–OÖý‘„FĽŇ)ĺúń°Šb*“‘6‚†ŤÓ“}%¸ľ_Äł§= wÜâšĐÝűŚŰóĄ)|ű‰ƒIDqy­ˆ˙ÇwĎbMź§ŕâÂ÷§đ+Ě)Šôďţä".Ž–ďF/Öňúşz„˜Úł´˛j¸îSq‰Ç†Âa8rĎŕŠ)Ó|‡kńńT ÜP!$‹űő[7ľ2‹}{§TYůČBĺ<ńd€ ˝té2ŚŚŚ°.c€Š€T V}ĺ+_FF”˝—_~E@Ů._ž‚ˇŢzGŽƍ7”ĂbmmĽRQ żÉÉ i§%?“řŘIJ4ÎĎt ůÜlv°0żŞĘ0˔÷z–’ąóGK‹‹Rk”cŮ&Šo:G6ÔĂęb‡ĺ>F‡mźňz ÓŁ1ńđvŃ,J{×r˜㑃~üô‚ƒC8:+o™_~únŤůŚ4˛ŁŹŽdűđr$1. n}ƒ9ˇnÖqéZ]çé *ůę˘ě>rĺ|Y瓃qňŒů4ľďĄ“ LGpuЌ_ȏ[ËaŘäů’sëb¨‡l?Š4~tĽŠdv…ü’L=LČ"™~gß}ŰDŠZcÝŔ- p~Q.”Hîד>ˇjU5t*ë´Ť( pˇpK€FI Ÿĺ×T™¤€˙ĹRMż‚ü7ÖŐŘxđŕJ­2Ţ|ëŠxŢ( ¨ ™Ş‡‘ůľŁ•Ź>CP|őĘ5\˝|C@Ĺ{ě$vçŢ:'Ď!ƒČőyL:(b—.ߔ›oĂKa4™Â<Ż˙ř‡˜˜žÄěáąxń,–.—÷ŢÁɇObiŁ §YGÄg"Íěnž|˛bÉűU"hK@ĄÝžU [ś7Ú™ť–Q(•´:šň´˛0ŻďV*™PÇšŕşvEÉč-‡¤×ň>Éސ şTÎź„ˇMĽ:–ëP˛°ąQź‰ëËkiŁŮ=Ĺ’WŞ‚sgˢ/„ĺܲţ­śĚąäćQĐ- )(qîâuMKœżq͎ăÎKmŹŹxQ[žÜ›0â°#ďp­!ëPľŽ gđšŹyäŠ*äÖ4rŠ'mwJ}WÎĄŒy˛]őŇŢłÜăÜě[S ¸Œ[.ߖ˝ĺźŇě3N¨7(źĹě}ů4وĘ/k‰nEad‘MEuŇČ-ăR‘qăV(—q˔I­j(c“Î5ŽĽ\;Bâ !`MÎF[UŠé€cj0ő~G­&ů5e]#ŔÍs|Aˇŕ“rků”tŢ0ż‹ySٜ+5č¨\+`őĈœRĆSť÷—xŕÖ>o`{2HœťĹqľěšÁĹęřxŁŮ!D)•Eg"AŽ*Ęç}˘[ýÔĆžLĽŁřŇg03–Őřwžîŕ?ű7ďŕnź}/•6ČHrfáîŇŻčŐ'Ćä˘Ţ˝ŽzŹ,ÓyYœ#bx;ˇó‘Óoy„ňž|ŹB@7-ŢËi1žršRŠ”ZiôóÓzÍĎĎă _xBAŻlÖT["(Fp‹çń|‚ałłłŢ˙q {e"§Œb­Qš˝–‚[6ӏ,ămnwS J5xhľĂ€ŒšáL\ŒÍ[ČWzZE˝n~Ĺćf˘ ŐÖŰgëxlރ‡ćü˜&űˆ\¤ŮCxŘÁ꒍…’Í3’Kޞ”W*™ĄX[Ŕ4żđü×fZ\&„ěHšĺ:Â2oT+mœ˙Ń”’YßĎŻŠńěĂĄą0~çŰCřŻţ_N=0‡Zq §f“¸p4jŕ]9ş%÷萨ÝPO n‹ĆM˝ŽĹůř›űďhvgĎÜe^źćľ‚WǑĂGpőę ¤Cbđˇ4ÂŤÂĄ/ýœűŁˆűŸŻ‹ěP:)@D§Ď`îřŒO¸•*ő BBźä3ci›Aą2‰Wßź„IƒĺťłěşśĚm̎Śä'Žƒ‡ĺ}\qrXœmœ>w/<ý(b Ź]ż†FWŒŸDżđÍoá̙ó˛5žU˛äĂÇÜáCčY‚ŽŻâŃ'ĹŮËŕ“ď‡<`/ţÜĎ+ŃđMq¨<óĚxçshË3=ýöyŁ ŃęÖ°ą2/ďšn}ŇÂT§jĽ4p—ÍźĚSmĺÜ2.!ŽÝL“˛ŹĘćßĺ’9?—ßúţśÓp őôzͤfWHŰžÚ:¸xîýÍżâߟ š]XÇ9ůŮݏ|Ţ{ˇ<šwéČ|‡ČnN×zíŢÎďŮČň[>ĺßâÚÉľ’ŃV=Űv-(ŕÔçzľaÎĄVŰs 婕0AŔf @Ě]÷,“Áƒä߲üŞ÷ÓńŰju Ÿb@ëv5%QUĄPXć[ž %ŒŒŠN­”ęČPŞŐFQ之'âŘIjĘdÇVÔ ˝.ŁŮČ%ZW]ź'k1Scń„ţŽÖ[Ú9V€lTkZ‰‘ýôë8ęp!š>ŁÄĘV÷CžěńŔ­}"ÉĽ'ĺ>Đ­˘âŚĽŘŽÇ‡ ĺ­˘˛@Ľe1Y)TĹĂŢÖETËňŢĽůí)OńPcɈ.N9Y¸ÂAż ŐÇL´‚Šĺâžçv˙ďuŸ‡HŁŻîńý§R@#ŸGŰ÷H>Üiˇë´{Ę#s§ľťqxyâɇ‚WüĄ|ůË/Ţś˙‘G֟O‹0š'ňĄRkŞBšŤtqášăôb7şę™e$¤%Jo׍|äkuzZY)5”ĆĽó×đŰżt?|cO=9ƒąT í^GŽEĹť-ŠňtĘÁFɇĚÜÎżš˜\kN搹°OIĆ "h+GÉě— uϨ,ŰöŕńÚnŰ=˜A˝ÔBIŒ”dÚxśŠ„Ź Eýřk/dń_üŢ ţö×Ǐ„^ˇfľpÉą ˘E1Ä,I$[XŕŚÝi!K(J:3ОľŽüĆ Ţç,žńë8óÎ# Ó†Ś\NOÄąĂqúý÷M$@‹Ń,l÷’sG55ëžżé÷čP 'Máüé‹(„‚đ h Zʎ X*ý Đđáđ 釅1™÷˛CY$“QÔYů0WÁKß O>8‡|ĄŒkóË8ťtCŒ—ćŤ865ާy@î#͢Ń“ď;0‚L܏ş!#Ă” 9 &Q]ÇO.œF Ăą“áЉ#X–}k7nâ•}D““łhŠŃtht+ŤWá“ďœ†×˜ôů‰ç^Ŕů˧ŐÉAĂ̓Op-Ź7[{mƒöíuÜG˛özëˇ'Ą|Đw’ TŻ×ŰŹp¨1Ş;ęŕQW1‹l֌2ÎUuâĘż‚cö&ŕe0!Ÿfcř}n’ŁłĽłş˜sľ%FkUËm­†uBű ęoGœ.t„Đ1ĆÔ^Fn‘ťŽű Dľ´Š‰óŒźb‘öÂňw<‘Ôvm7MSěe=ŐÔEF€Rhƒ0š­˝°˘ÇMŒ+ˇVšXB­\–gŇAMŔ.Fx0ďI?œ^ŰDaú}đdˆnyâÉ>ç>Đ-.pŰ+ősř˙üü2‚˛ŕNŕOĎ/š)‰†˘!Œ‹1ĜýĺRővwǕś{ŹHtůÂŃ1|űńƒHÉyzvxú^šşŚÄ™šţŕݛ›×Ý!ŽÇɡ‹=™i€ížńŚúŹ{_Ժ۪9ÝËyş€öú^ŰŢÎó|.€çxš˛Ë;“?Ž*.e›G[^嚏V˜Fđi—A}̗šxăĚ"fƓJb:›W Čf"ôtŃŹ´4=ˆ ůŹ|ţëňţŃ4ŃjÓF:CřŤĎciy ÍË×0!ß#ąň9ÜZYĂƍyüň—ŸA&9¤)8–?Őr?={I<üÓ …ˆfˆX(kĹGGMŁQ+#Ö(ŕ֕kĚ!GŤQAťRŔúú „Äs˘ĂxçÍÓ80wńdJ#jkâ$‰„ăxúŠ/Ł´ža@LODSœĂMéí*˙­V3 4ŞKŤîF™ÝT~Žěđ2ٌڞ˘* ¤Řžö@“$ú ĂÚ“žŘëj4Ť4öƒĘ¨K3˝YŻ °UBťŃtA8]YW˝EÎ?Łzxcr?‰níń[OÉ]) î‚}qWŠŃĆë××qc­Œ‹Ť%|‹qřŰOÂ×NLŁŢuđzߏ_Í­očöŁŤ2hœĚ`r8 +ĆsG{řÉĺüK´ę˛ČÍę8łRțŐ_Ô}đÝVlĎČ1÷VIl÷qŰ˙ž ‡—^Ÿ VŤ‡âB‹ńyTV˛¨‡śÇÝJöÖçmTŽqś…÷÷o)ŐۍÚíôśĎf›łŁÍíý|ݝŔÔîý[űvöowŰŰŞ77}xa$Ť‘KëÓö<ůP!e{ť˘!;ŠáĄ¸~Ž‘çĘ ă™šQĺŇŠŐm”kM­<ČéB9C,3aĽ“Qźđě#¨Ź_Ŕt6„Őľœ`1–áp’słڞaL&ü89x÷Fă!źsš‚r•ŐĄ4$ِ+Ćş€l‘ ÜŔŒĘ¸ź˘uń,9zdŕ=|ćËx§d#"ŔŢű—⍖kŽĽF)ˇŽő\ż˙ĘMÄ8 NePXśÄF4”‡ÍTŠ›7ľxíĘy„bidÇzXY$yžnqäóHË=WXéÉ á•W^Â7~ĺ7ńĂ?˙>ÖWçĺšřóW^fMtx–LZt(†Vn š3o#$ŕԁƒ‡p?R0ϗĚ":Â*pA,ĚÄbYkëxűőwpňáăú”văą0^y㬀Lu|ëkϢŤŐ-3ŸJ GRyDpDćťl&ŽUťŞůElĚßŔšË×qpfç.-◾ö$~ňöű˜=ú N:€×^zM<ú-š—ˆVÚJÉ3s´úⵍk¸zkW/]E6›Blx!k?ţ Ţ}ď"ŞN_|úqźüÓw1”Š XŹâŕě1ČŤ…X&弼üLÄRN;ré0âb÷NŔŃ֔!Ă äӔ§ŽňąhŁŠYYN#UÄPľţšć3Ýś!żöš ’śĺ3\y<—Űűܙ™tZĆSUۣӌŰh<ŤCË1¤ŮŠ Ą°ĺ,Čaśuô}ôY†GŹÝniEFÇéškŸĽQĽŹŕÖf%ŁjŹ~9sĽn{kŢžŚÚŃqÓ×Ď2]Žu4Ë]}I~ˇľá€÷Ĺq#Žä<Ő}Í܆>/m_ĹS.ŽÍ#úYîgŰŮtrťj¤ŮŻT[&€­Ď=7Ú9LŢD—^+ Zůuü¸žÄň~M/´ă“1ąb“fČí˛žr|ľeÝŹ…g̘čşĎ$‘H¨“šQ`zŹÚč7ŃÜaČ9ś°ş.N­ÚŇN‡||´)dîč?O‚eä[dż<Ů?â[űDźĽÔ“A˛'㖳íˇíÜÇUßűCÉȢ÷ÂŃqYČbb˜DđŐăSř3ˇH|<šN`6›Ô ›e­şE@ŹPoŁ!‹]ČębĽ\Wyň”T›=ą$.f卺)‹0\`4Śéa"™ź–9vśî– 瑑8†ăáŰ žzÇĆÍbK9pœh–z˘”;@]†?ß=üČBąœCů(âÄ{´Ł›áŐ;Şľk›5ŕ)ßËśΜ=ÚŮyŻwďěߍŸĐöŽö‡żO>˜đ}&a+>KňôÓĎŕ?űĎţSüđ?ÄpŘƐ€`á_ůŽFj=\—ů!B%†x–ă™ăď‹OG*ÔŕCxŕŃi”íž}~Q™_"&-ŻŐqô¸(Çá>QpEѝ<:†…öš€6–Ě9]ħ" ŕ…ś%ď!ÇZížĚKśŚ$fâAœxäI|ĺŤ_Ř÷_üÚ7qăĘ.œ=ƒçŸ{Qs’éŠâ-óF$6Œéˆ˜SfŽý“—ü(UŒ§źŢŠá§ =ź.ť[˘o}ŔĚ2>ß ćŚą•^âŚ`NONŤĄżśp šĺL €61~JúÔ3X&}ŁĎ{Bƒ„†Ç_ţOţ#LMOá~$&^őJ. xäcɆG˛¸~ůŠô'( ߜ‚TńˆUy>ˇVó¸uő:Í.œÁôĚ´Î1ŒÔő‡cđˇ,ĚLމžĽźeSfUSiŒ `meIŤŘ 0ůOţčOpîĆ<¨áŠS1żphś1wô$<ő0j ×dŢ­Ű źţÝďáoţďţ.n݃Ś×=ŁźkŃ@?x3ň[âĹ'іuĽÚ(á§§ŒS'N"œL"ÓOVXń,)ß;S[‹˛N7vĽ!f‡†”> jA ŸĺčÚŽ%áëľąşQŔäěříŽFďŃpí‰Á/¨ľ°4hĄUßjłE„Űä‡Ńtą‘/jŒËŠS§pĺÚ Ä)Yűƒ`éŚDwťLłj+xF:„|ą„X*‹ą‘ ňyÝ”ádZu˜–č.ľb#26{­şŚI3Rź€q1ŕk%9GÖyf  ×÷9 ÁoŮX^^Eá<€k˙Šž1qv¤4B™ó;š KĽ ˘ń¤Vš‚ňžô°!óq{ŠvŞ•˛ňŰüQÜdl”K ۚÜVđádx4XČFĹĄ/ômEQ}ú$= Oö™Pýň×~I> ůć€mHČňw˙ýżƒĎ“´2O– ¸xeĂS=źőú;˜–šN ëçÎcőÉGŤ4ĹČOŠAĂ4Gć&pîě ž_ –z˝!Žz÷1úŰbüřtŢaTa8äùãČĎ_C4šÁâÚJĺ˘3müôÍ×páÖy´JŹ…x|ú9|ĺĹđOţ—ßĂé÷ßDf4…oýâ/âÚĽłvĘHĽbĹ$bd’Q÷N_ÄŮÓWŃmäNČlëÔątmW—/ł~łY‡'ŸŹ°bŁ ‚~[Ł-vƒ[żѰňçuhĘmŹ`xxÉLíZkš‚˛ŒňˆĹLE•ŒšŠĆY×ýáŹKÚŽˇŁ›Ŕ—šˆŘťvuŐ]ĂmŐA&§gP-WYkFÎ (_\×ń čÜAĚj#ä7†=# :ŒŒŁ!kw\Ţ×h2ÇĆőë‹:O`ćĐ*EÎQqâI[M,Ż—\›; ýđ‹QßÂÂrC™Rą ň´Üňd˙ŠFů1ňĐé)ŕÓŞŐE§„‚^–!›rž=Rˍ#ƒÎVÍZđőut ›áW›żŹMŔkWčGki|ĄĺYreœXNŕr4âĐ­§ ŔQGÉđéTfŞ Ç0ŒĚ"X%Óž‚šAF_úz:÷ˇä­$.ú31śË*‰<>%ë yÂxŻĎEF{×ËřF‡%ÇfWĆ==´”gE,$×'€Í;$@“ –í¨ţg Aç^ťé[űL—¸ú—ďÜÄŻˆG3WkáÎ,č"M°éńŠ4ŚĹ#:&`ÓBĄŽ×Žëĺľ "žmęňFMQfą <Ý;ĚŔǨ,x§&xp"…WŻ÷´jJťgBĽűŽˆ‡6(^X*HBm[Á€Ď§ m4Q~z’˜bĐp+21ÔúŘąŁŞP[{ĺđí~žŰ0Š;Ý †ÝßI?lŢ,ĂŰelƒÇůLÉýĚRČě?´(ŢhË2 W˙řííJ]ü$ĺržx2Pś§ÖŢďţťűł’­t”ŰS‰V G0wpńdX.ËęaőćUb$ĚşxvSGŕŇĺ%Ť|ńQ|燯 \Š"91Ł€+OöD eîĐ XŞiuŤ€:eń°_ş°¤‘]'“–™ď˜ž‰âČJš–ĎĐÔĚRiŤů94ФÄoœyW0ťÖĆj˝€÷ćoaz| ‡fÉuJ¸tN%ë+˜MbiuŸb8•×5Ęg7ߥ'ż0ŞV-ŁôiÄíbř|l]{óʓS‘wÄąü¨ÖëhÖ*ÍQĚ­ 0ŮB,DYÚ"¸Eَ%ż•_GÖvŽsŐZCŔÎ0´¸"ŁşĚŃŽ˜¨m1†s9Akš"š"ďˇń‡ÄÖâËĂp*Žp:ĄklSŽĎ5“\A4œkY?˜bßňyš@+¨‘ćĺRŃô(şŐ‚č1lä+š&ĽDÝbˆ3ĘŹ" [˝VŠe8‚"×ĘVôĎ@dsaÝĆŁ$?Ż]ß@\ŔŁĽr×sUőšŇ;JĽrVô޸÷ת†›˘/Ę!°WŞÝV4ő]…)M$ńĚ\ +•Ž Xv§s-@ÖöŤémqŃ%9źłíŢů;š !–0äĎŹĘÂЉÉ),..č‚ĎSľZхżP(jxv”"8O6=PÜćW°‰•dި‹BM%}ËŕőĄ&Ď'œÎˆ×:ŚĄÖÍR>ˇÔrŸăŠÄ™]%Ű m‚Yl+_ČkX6<*Őä0`ęZR<ĐĹbÁwş-‘Hbccý6^$O>[R.—Ÿ+affF˙ Ü¸qC˝¤‘HT ľ<ćććÍ!—ËéţáaFGđa^„#Gk.\ĉÇ÷l÷㔗_~GŃw¸­é †gdd?üá199!÷uSűšL&´O—ĽRYĆB ŁŁŁH§Ój° e~ŚäâçΝÓńJ°…ă“c‘dź>ŚtΈŢ:śSŠ$>) ĘüáX]ÉŁh ]-a|b Ůáqtuźü'˙‰ě?˙5´Ů÷hĄĄY¤˘5 :đ ŃiŰČ͟GRć,ůzŕ“wĚîů4ŐĚĄEž"ń´7ü6Ξ=ÉĂÇqkš­€ĂÉČąŒT ń'˙oż÷f'J›´4‚8ˆ\~v“Ć_ŠXçOŸĆüň-ŁAÔęX‘ĆÎaíz ™ÓÂśĚÓҧZłę9ů~B€§.ká^1s•JESWŰۀŻfkcÇ19Y—(˛DnŁşľŁ˛—“Äéé¸ŰKiŇŹ%tÝŽH#Œ*Š”‹{żÄKޚ~mţŢ&EEŘś¤´wSžě;q”—mŁľ+‚OŔŸÚ˝÷3ŞŞQ@{崂Lf››†ámYľfuŰĘcĽą[Le Řą÷0“úÎj‚üŃH2rËHĎD7˛Ë1:!#ƒŒ”¤ÓÚ Şă—@•#ۊDzŹœčŁžŞäî†g•kÇŇĘŇ-YëĘŞcf˛#H ‰Ž1˘kűÁމLăe›ĚtŕqŒźRpKÚ M urVOîk1ŃemóW:F:–ľ5ŠŐqÉFÖH…°œ0;W€'űGxŸXżÄwdN —űđ_cŁaćéÁřôÔ - ÄDo`‹0%K ˆĹ5—˛!Œ[]ÜZĎ!ĆůK ~-Ň9§őd>ţîŋˆ OŠb8=./o'ŸBúäĂhĺŤpVťX(_Áĺsďcfňž}üQĚ/ŽĐUĹâę <˙äQbၐ#Ľ:ęůĂv‘™Ťó$cE×cˆĆÄój@yňéÎWŒúű4€š uů! ç᠞|Z…úaťź‚ňĽ"ŕßâš%áş˝™,`Š)Přn÷Ü óYŘ$†'X¤Žáń"§\(dŠ‘CÎçf2ř´Hƒßdtc˘/„ÔA´†ůÜŇČX’❊„䄤îÉ5ĄPká˝óWpőĆŞöó°8ޞxbT­˜ňjńz$Ó§Âv¨ßú:]Ő­y|]ÖVC j„WWŁÝČ­KĽäšŹçsX)ĺ*ŠHŔŻň,Á5‡QaŸĆčmO>>ńŔ­ý"ŢJíÉ1ŔÔ°żgc¸óľMK¸¸œWc¨* Ő͍ŇÎT‘=ŇűîŘâ‚mÉ"ya˝‰łËY8#ZÉk3 Ďý÷őůŽš;hĐůťŃąĹ,^,{'źrŘ]SZšăG:“ÄÉ/€¨ĽJÁČȰ]ëřÓßKŒÓž‰ĚRŠg@­€˙ś[ě§šJ0Üb´‰F‰Ńpʎ•hkjz§^ƒSĚkD™’|şŐčů.—Ť˘˜”ľ?Œ(3רOŸlcjĺúú†!Ý´m­Xăh~­BŁĽ FöeŤ†p”Ŕ^tx ÍüşŤPő77ĺómE÷íŽ šŐŽłŁmݙ9O>œ\šrEFůełYýn‰Ŕ1ńŕƒ'ÄJĽŇÄ´Z ßFůĽDIä÷ňÄOŕÝwßU‰ŃN<‡Q?úяuÁ˛!ffŚő|\Ă}\Âw„ý˸~ęFGG´?ěłVU’{ĎpQ@źąM’ýBĄ }ĺťOpQ]ůüĎ֋Ë~˙ĺżüŰ BňžŘˇX,.`â<¸Yő’`Ý')qžóy”××04:¨Zńń¤Ä;~ć7‘™{ÁTUń‚G"A1l8ą´Q°=.†DŰv,ŮK%09ŇÂjž˘Œ–y'ďĄm¸bR#“J>LG„ˆcfâć&Śáˇ›xé˝[˜žÁÔÜ!,,]ÄH Ĺę¨É ťx,)Žn^ťŽriUSC‰ĘgTÂŁËŤËXC*ěŻ!čabv>ǡ<ŮK> ˛=*ÖOIťŮ@Nt9ę„Lűś\ŔŞ+NänĎÔ6 ŠÎŠ)áňťŤŠfťęŒ=SšÓ$!¨0•ICPPKł,ĺ§ăëHý´ÝhËÜEˆĹ_˜2ŕ•O4>:×ZÍ Š}]PÓqFpk­Ś}™GŞt§ŁEš‚ŚJŞ[°I+‘ (ĆČ1Žä×ŇžJ;=ś¸>ö9žç—ľ‡Őy×Vk¨Šƒ†}Ś#7!Ž•X<*}ęŢ[­'ŸńŔ­}"ŢBéÉ^âÜ1_O~> şšˇo›Ĺ—ž¤ƒ… t˝ŐDłíÓ2ĘQ–&ÉäŽ1Pw¸ZŢ–Ś‰ŠÂčdގŹEäs\€ƒÇŔCÇŁĎ‡¨ EcçQcőÇvא^ÂĽ#ł|›Ţ`Ű˝x1żËůEĽÚvÁ4€ŞŹřŒŤ'ŠNÁDÖ]ď˜ů1ý2^5˙f;4”ű ˇS´<2úeĎťşOŸUĎôÉgu5ŞÁD\9›€ŻéWĹÉRîŰM­´KJj‰c*ÜŘÎć˝öÓ"ˇúŘď‹oŰý›çÉűď—t÷äĂËŃŁGĄˇ˛Ťź<öŘŁ;ˆiů™)ˆ}éĎęĹużkFńűVŔÓ1ßß7žń şŸ‘DŰŰăďÇorš}\ňÔSOîšď‘GĆýŸŃĎRŽËüA™žĎj†ˇ0‹F<9„ő[ב`s(;ŒKšUÄI6]]Ű@:+@Ś%€#?eŽ˝uć]LĘq T€-K ˆç;81=Šë—ŻĄÍ"ˆ‘ÓSpËĎ2󽎀a-ĺMzřŘچă841éąźţö"Śč'†ĚČt‡ĽmŸÂŰ/˝‡šĚ‡Óf1’‰ann vQćň2ڕŠĚuiݧeěÁ†ÇĹřrZ¨wëX*ćîźÖyňąç Fţ>´MźŤň9f Ź p~!ÁtHÎ'¨Ý@ů ↠út}o×Jb¤ß˝­°[ńŃ,}Łzô‰ó–Ź‘ Ş•ťç—ůüA„eÚdôb­Z0>j*=“œ[ô€ŇŽÔFO>?Bđ‡ď9é”ăĘu„2 šżs.î ŕaU V#íüŁŻŕ˘.Č˙ąe†‰OŰaD#š:0ÜYŒ¨˘–Ćš˜Ÿétîëe§Xq”×dŞźË Ľ=KڞO˛v,N¸§ ŐšÔŰÓž÷Ç3ßaUŠ•Ă‹ş„OŠG¨}öuIţ×iýS#É ´i´—!žgń^„c+ )¸ĽcĐuŘöşä肮)œcTgĄ^kůIÔKƖÓlÓý%¸ľOÄSé<$[‹ć'÷†|ÜW˘ŇŔôÍý'$÷ČRĹô\mńIYÉÂ×q c"Ť› L_%XÔén)ăţ^‰xO=ů$N=rI\VmÚ˛ 6ʡŰ;Ÿí!Ńö6ĺ|{”ÓöĚKĐ‚łEčéKC ăV}ěu}…Ćq+člßžyÍmzۡ÷ßşďގk˛Ű†slgŰôĹů“ńÍ(Źí)‹ŰyŮśƒX[÷žmťoŤŠĎ‡­#é 6yŚ(ťo߀ôŹíŰ´€ÁŽcúŕŐ ömóäł'Œˆň9ËXšuCŹ Śćfąąś.ń̄@ُ|=qÔe,Çd(];‡âÍE,œ{ńcŔCŠSĚÍĹ œvI ö0Z˝:zôčËü™ÂÔبVcázĽŽÎŇZß9ű~ëמ‚p<ƒĺ[óýˆ%8ťą€ąh 3ŁX으ŤxMŒŠÄř9Î6"Š4â#Y¤ă…˜™ĹĺĺkX]]'‚ęFNKÉ{ňÉŠŽŕüBÝŰŔ­L:–˛ŃHH#Kbu0ő…čqşXĎ14<˘dÔţtm“óc—B-qćp aúůZŁ­ÄóŒᾢ25­ŽĺŐé55{Łq ßôÉť˜FšÚ‘wŹ'mçP0`)ŕEÝ ×jČľsŸœFW@­ĄĄ–Vs–ߌ&YÍ×0;‘Ňţä֖¨ ŕŔÁC°ä]w|!%ˇW €NC‰°ý¨Ůíš,z°Ĺ˘(ćÖPŹvq@ŢÓäřA,]9D€ĂŃDľZݡ>ŻbŔ7“˘ţPýŠďqCćH­Čwšmh& Ľ˛‚Gť…€ ™L]ĺs×mŐ˛4ÍĎ8ŤHľZ]ŐżAŸ›ĐS÷žňo… Đ+ď˙ć8ě¨T@]Faéą]uÜvä˙ˆ€ź[uCá\Ň{C+"çśŰ ŠŮę 3ŔílŇڛ˘Gčë‚Ô•ĽoJ&ßEżjšę† ’ő´=Ňn„ZLIěl>ęɝŽ€j0í÷ş t4{ĂŻŕ1šôŸç=Ýoâ[űDźČ-OÉ_֝ÂgJLXs۲ú@ĘÝŁÄúšůý¨z…ČółÜҖĂÖoŤ{1ŒéOŒúśHŞ7A$ËcŢRőĹryË-áźšÇ͑Ü1’k{´ĚöÔFӹۡo^Ó˛vTkܙˆMNŰŢuÍm œk`„Őöknż×}ńőˇš-mgí÷ć&O>„0š‚¤řŒTcşS™˛ČtÄŮŮŮO5׆é{AA—~ߙŚČąÂtĎOZšľ*n^Ň1ÉßąháDGy>™OçW‹ůŁZlÄ'FçNż#ȂƒĽĽœ8ř œŰĆčp ŁCJ Ŕ0T•v2˛=ˆ\+ŤëxőâM-Ÿŕjd$éń,FFłĘ$ńÓw.ăęősČ H‘ů¸%ÂZu sCŠţŞ˝€\يŇBŮšsšĹ&‚•~ĺW~^ Ÿôgł­ϟŃő`(5¤†”'ŸŹđ™sr hľnÉßOEgI›€N!‡ôЈü¤P–ĎšBIŁăbôŰ1Bş.F6ٰř;(żcqS­-ŚtĘŻ)S4‚›ĚşjlCÚ ŕŘŃCűEwËq˜›ŁÖĂż^–w‘\~– ZěĄ#€h˝Śë{ –vđ…âFAŢőŠ™0ŠWJňSq‘ŔÁŮI1°Ű(U›ˆ%R␪ZB§ŮĐ4păĘs)Ś;üv[ŔľUdĆčUÇÉǟŔKCŁü ŰhxňůF´Zˇ?l*rkúÝP (‹ŁŮmm:\´ ZcŻgř°˜vČńŐS‚wľ”ËŻď1 ä™ŇG ×ľ×"çcK@ŕŽf0Ş+‰‰PШ×s4JŤÓ5i‰vOá69a;Ü'Ó}ŰTF$HG™?‰%€[W. ™Žę¤AF’‚Ę˝§ĎŸki%GŽŮ•rEžƒĽ@™mW7ď™ ?f_p WG3A3W?÷ű-ŔŽj…Iƃq=Ňqc“@ßđ}¨öűLŃ&OöxŕÖ>ÜňdlVKÜëőĐ<ţÝů8ßĆ>Yzˇ{ďĘ!ĎĄĄŮŁîƒ.˝Ý€˜t|ey˙ůßűϕš íŻ˙ĆoŕŻüĺżl˘Şşmc;Ö…U,ľśQćďŢž{›rlŮ&mq÷ö~dŐÝÚŘk;ĂΊ0°¤úîca ž?T`,lż×÷ŢŮ÷Ԇ'žÜŤpÜqěˆÎĺň jóďąąQ~čs‹}Ĺô˝šŁďľĘ˘đ˙,Ŕ-ÓĂ߃œŕ@Ućłë—ßŕ!‹éCGѰ(Š!™'ښғń;sđď/(Ç?tpůBWOŻ˘TŞi™úx4Œá‘ Ś'Fqxf_xäˆFź.,ĺąźźŽˇŢť†Őľœ˜üڍ:Ú­ŞńŘ7d.)ÇŃ śhhbéćUĚ&GńĽ'ƛoź‡b]Ž%?څ†VĄyđ8ÚÍ.ˆn@2Ëg+řĹ6˜éŔpy×ţÜÚ'âa[ž ž|‡´đÇ´ ü ßI.öľZU˝˝Űť3HŘ~÷vKK˙Őżö;Jţ̐ëééiőîú”Ř3 ?śeď8Y=uƒ@ÂíoŰݏčÚąÍgR'w€A.Áť9t×ńvTzě_o|ڜ͐‡ú°›]żiu[ľJ7]ńśh8WŃrvësš›lߎcé_ó}ć˘=ůôß-Ę3M#“Rr|FR–Je<8„Oł ę;Ç8ç“OZ ¸]ÇúĘu×W‘@-_E2™0A ŁZSŒ{1äťMt†ÜWĚŁTŞUDYľęxíŐÓ27NâąG!ŽŤY‘Ë•ąź^Ŕ›ď^c*ŽjăŠřV––e^čŠQD٧‹' Ć;g×А#”Ž!lÇ0™>† ë:–ŠyÜČ-"×ĘăÁ'ŽĄş^Ĺľ›K˜žœÁO?…+—Žby~ż÷Oţ5~ëŻü*|Á˜8# ˜;ô˜rÂÄ>Ĺ@ççWœÍŞ˝ť§yžs•JIŁJZ9ĘĹÉ(“<ŹbQcžůu5ČkUľĄEO°ĺtŠ5Ćč•cŤUk3՞Ƹăr\ö: Üźľ¤Őâ AŐRAš.eM]ŰČ#-cöp!—Ó"4tŐBÉIu]™Ât)ŢOĽVQŁ?żáWCV%Řţ w t°śj¸8R\LŒwP*伭ŚŢ'ű°(€-ůçJgĎjť ‹ËÚ gŔóŰŚŔE/  ~FĚřH éôÜjćQ)pxúچ'ĺş-ÔęEt-9n,†çŽ=ŠŽĚťŤ+ë8rä0˛‰ž˙ÚWpu!vţjŒ>q_űÍoarrž||28…ęÎűkľĆŽ5cł˘ŽËŮwŒXnUˇAB°Ťď˜ęřŰů57ŤśŮ†ő§ĎŮł= šŔR>ˇĄ×Ůőí(ńľ{ím×iťçśŰv˙@ók[ĹĹíÝe$"#žúaú÷jk´´Š$Ú/Ür§çĺÉçG6ßgg+Ö}łŞwYćÉţÜÚ'2ŘxŢëXÜĄOÉžťĚU¤ÍÚǏĽÍřyí˝Ý%-ÇÝe;¸ľű}槜íŘçŚâmí3›ŐSŞŐřěĘŞĎm›[ŒÇŐv˜­vďĚş[9ힽĹšga*ŃřÄF†‡UůWž.śXkÉ#˘Ü--ŃÚö/nKăÔ÷ ÓĂHO<ÚTŞ­Űšş[Čę‡níÂď4Ňk€ĐŻ\łýřţwŢŻlsŰńŔÁÁی‚1° ǂçXűč„Ő24,ď'ߥ‹/ę{z? Ż]ť.@ŔĘ岞ß}a4=­?+đœW<ˆńĎ˙ŠrmFm źĺ;Ä1\(ŽKÖgŒíN g3”SÓkgÓŁnťi$†Ë̑Œ˜ąěćí3†ŠľYœ‚7-ĘáĂŞvJ^ěFő°úÓ­ Tx9Iy`ÁÇ,Ÿ—ÂýŠżŸľś=ůü ¨äŃb*ŁˆŠÓÁRp+ŔâH>]etz&â‰`UŠa+ ĆTÝKǨÖ0œ kdÉäKu‚ľ"!™|Ś˘ĄrwYäŇ*žňZPŠŒFt”đ˝ăÎíb5  ĺ×*G“ĎËŁŇ ŕĘÍuťťÁĘi‡ü¸äsŰ †ĂfM`dă&Mˆ[ĐĆÚân5kč"䲓cËšźqŽŤ#ÝŻ œżď,WýÓS2÷“xŕÖ>/Äٓrˇ÷‚vG×s7BöŰŰŢăł ĺěž´‰2Ú #Ú řš§~nz"˛@2Ź™ŢRő(ЍąÍ›{ťĐbxu4u‰5ĹÓÔhŢv\(ĆŃŁG17;Ł )A–(çů͎(ą1ˇśúťc9Ű3ţÜ­{pn ˇ"v vŁşƒžŹĘ.ťmŤôîíâůňíü.•ŹŢýŮÝö&čľK,ßíۡřĘn?ÖŘšÖ]ŰđäĂIĽRÁĽK—ő]OĽR8}úŒžË•JułĐ# ůÎNLŒcaaQهÖÖÖńŔG5ÍöęŐŤXYY‘ă8sćŹňVqLPÁÂňň2˛ŮŹ’śüZ]]ĹŹŒhž|:…ó ŁCś<üť^o¨‘Đç&ăwLž2nç|H€“(ZpCćU ÁÓAŠ“?câÉ'×Y\ُ>^°ƒüJ{ ËĘo—~‰ú;IŻç‘xXšÝąs˙îĽü^ƒ§ˇAťÄŮšÓŮÝŚłuHűľ‰mÇo:ŽvîŢ!ä4ęŮÖűíě:ž‘)•Š'Ÿ!ąŹ˝ß+kűűź‡ó™ŽusËŃjƒţžĄÇ%xEއ˜ĚÝ]=ׇˆĚĂVžݸŐ6äđuŃUƒMň~9nDŽ_çűD$¨ŚŽř•‹@Spé¤LĆ€gśF2´Âc(Q§E0ŇT}Ö§By}ž`DŁŔ4"‘¤őĘ4’KŽ-@%€VXôŒNËptAy™j)k‘´ňÇđőŃP~J Űj5[J0ߏvÔÂOîCeú°E'ˆVlěşUrxz=ů܊níńŔ-O‰ƒťD/ŠűćăX>ž÷ąO(T2MżŠNdŰwçdŒĐ˛íkëBßl._(äńť˙ďßÝLüŤőwđˇţÖßRC.áďâŕĘ+›ŠŁě÷#vJßŘ=>•/dW}.çVۍ€Ř~,ĺöă}ŁÝľÍű%OŘnţ~ۃŰńťŕáÎűéGzmǍĸ˝&‚Ţüô‘ČŐŤ×X¨ 0ľŞďK&“Ŕę˜*ŞçĎ_@jHA ţžr媒˜?řŕ °Î੧žÂâ⒀IŹŻŻËžŚŚŚ\ŇóśaďżZŰ/‹†­á…žÇ~đCýÎ ¤yňi–ŰçqŽďÓ§OëœÉńyŕŔ;;˘ßůüü<6660::ŞďA+V[ZZv#ű*"Eô˜çž{ożýŽ‚Z.\Äžđ„nO§S Ź;vLß!Oö—C6Mu0›tpy)ˆůœŰtďग़ĘMq,ÉëY¨Ëœ•p/’ËÍFČą°^őáé‡ëˆČ畵ň-ńˇuäřƒpĐAĽN#ßBLţîö,”&úd$ecŁâC*ě`Ľ z€ěűŇcuĽó7B2Ú(p”$Ůäčq ˙ŁĐ´|•óňš"Kâ ľ•k˝u>"Ţ-ÍşŃDvSÎOőô:1Ů_kYŰ59/$}ĎçZĄ*ŽŻ–Eâđȑ.\ a!€WJe ŤŽgťř‘Žźż>4ştJůQ=in´ GŢŐ¸źˇÍ†ď\ĄŇź}îö[ŕˆW}‰r^ŤŰ6@ ĺYůZ`'‹8‘?ŁŮ)Ÿ:„'(!_ÇC$Śí˘´ŃD"€ËB”NaQůH4ßéĚÚßf› i”Ľi~iŰŔˆ‘QšÂŘí)-9ó´Čƒť=Ŕ(]ŇW„Ţ N› X&%W€6ňĎĹ"š–Îކ O€Ž.eŮ>î:][Ó~Ô/0ńZA‘…OXŒ‚@|úăŔŒ;Ţ;S-OżÜwâ[űDźąíÉ š§”ÄĎśĽŃ^!Mâáˆx˘ÄăÓlkŚÎ]APä˜xűŁ‘ˆ‰P G€€d]7ÍĽ/““Sř{˙§˙=ôŕfYâ~*XK1_8şƒläúí n)'ڀČ-ßn0É]Ř-‹ÓöNđĚDš p‰;Îí_ŸeÝ~,áB> ”˝xÖ,ŸíÖŽć}Ś/ƒ"Ă/U裒ƒŕÚľkřßř5žš››ÓJ|üţN:Ľď)Á\?|Jżys_˙úĎ pTŕ‚ßÉoţć_Ô°>¸I`Œ€í/˙ň/+¸[­Ö´H§ÓřĹ_üÖ&ćɧW8”iŹlÜ"¨Ímüáťđúëoę÷Ďęo‡ŸüɟâÉ'ż ď,‚ßŮěAźńƛíG0•ç1ďŁś|ŽŽŽ(řIđ”‘__úŇs œ2şď“˝ćŤíۡҡć$§çŠÄ‡Ä"6FŇ6nŹÜţ|bĹâŔqšŞeW‚xđdŚťZ-ó˙÷Ł811›ŔÜdϏöPcż!çŽ|h 80’Ąë(UoËqY’[ Ř$ AŻŸäş>YÁŚ~đ~>XÇŰm1Ót˛C$Ԗ÷ŁëC…“€[3˛]\ĄQ…źĂ~\j˛m•~5ÄjĘŤôţĹ0OvńŔŹ 3ł¤­¨-mJ{–€]ăŇĆĺeż6Ɠś˛Î 8vŃ Ů×Â,9@ ˜–źĂi× Čš/ůqô@ůŐ ¸Aهŕy ;­†Śi›j†ăÉWČTÄŚË+—ŒĆaăhXâ|'ĂA˛Äăý[i„Qš,€$`•OƛͶĺę"@Ő1نhچ”>Ŕ~Sˇ•śëâ°°Ç ÝHWČ>_X+֒7ŃÖâŽ:ˆCâ$é9–:BŐÉ옔Ǿńa)ÇůY´O:Łĺ^¨ľ˛BŠ/Pňy‚ÂL4šÍT|d4°iäźfĽě†JşE'h4Y$žňđd˙ˆˇ’ďń"ˇ<$ŸG2oF715ńđH s#Iœž•“ľ8$ wOš #F ÄdĄęа.Âo˛Ü8K6ď*É͒Ć4ňč)˘ĄHţĄ~ŠN 5†ŐG~ˍPę'$X.Î4Řŕ2d˘[ÇöšŠÇÁö¤*aQĐśo@÷–Úhv@˙í× Č=%×Ď#şřî‘)vĽ˜8ΎŔî~߁íiÖś{ę_ÎÚŔÝÖźů飂ŒĄô÷SɌlUdD—9îčćśíŠ\L;ěËłĎ~qóóäääŽk˛}rÎ}ů,|ďÖySŸĺžoßO“Âůď›ßü–——´,çśßţíßŇjŽý”>Îy42ţâ_üśÎŤ˜˛ŘĚúm)÷•<ŚşôbTß'ÉÓĆČÝë×o(Ë÷˜işáxŤŤkÄN*š7Óh=ţ¸W‘ŃíZXÍL$É6鿝™Ş5¨Zɋc*făֆKËA5dK.­ 5›vp}UÁ˘r̊lłĺw÷;XX÷ăȨœ›÷+ĽBA–n§ÄjjĐ5Ż)ďäc‡[hÖXlUÚI05>B疃lR@ŠT+ˇ-$ĺᆙT#Ă.ÍĹůĺŕÖŞčąMˆLŽ‹‰%•nąčCŠáÇŘDO#É6*4˛-tÚ>Ę-6‘őÖşý.ôsöä˝ Eť¨É;_óІ€[ĂW*Ź˘kë{ÓëžĂ{JöŢĘQţؐßR@KŤsĘ@ë)o–¨;ĽJ+ĺ:†łĂˆČťš†ŃîĐqŰUĚ€L~­„¨m3ƒĆ ÚS`ËҨČőޖźŰvé ŸFjąwÁPXÉŢéHŁ˙2(k 5˝T`Xă¨X)ą'ç*ŻbŔżÉ\Áů¸+ŕ—ÍBLtŞ¸ÜŽÍF]ď) *ŕĽéĘíŐu ęĺ|ÔâŃ,AŸ9ß÷x–›šh÷ÄŃp+?R‡W/˛‡*ďńŔ­}"ŚÜ,öN;ޑđ˝kűÝÎťÓţrü }{őďĂôńNmŢ­Ýűí˙ÝöÝŠôůßĂ>M7ťşőëbwI„üH$ŕ+G‡ńÔL р…??ˇŒJ˝ą÷ –Ľ˘šá$ţ­Gǐ—ošŃÁ›×ˇD$[ţď˙á?DRŒ>uŒzůć7żŠŃVťŠĚ•c7wź!NŢ#š.ŠżŚçmŰîÜV…D1uşˇm§ :ţ^"(Ě< śk˘€˜pďÍcmó˘ ŞŞÉj6ˇĽzZ–Ë˝óXGyž‚˘pmhÚ`ľDŚ,ZžÂż…Ę퍯ü‹Kˇ093b!‡J­…t&+J¸702:˘U˜|đăĆľkxŕř 8â­n|–óŤőŚx‹Ĺ‹-ĘmDŔ ŚM: šő:BÓŃÍ­"(çe3đ ŃŹTĐe;>”QĹ׎%ao,Šw—6n^G0UřéYüÚoüŚ–ß.|żĄôßţƒ˙ůĽ”Ľ/Yiť,ŠúFŠ(熔›o(™FEő‰á6ćW׾ü9­›ľRÓâIç8ZČçĹűœ@MÚaşIK Ą ĐĄG|ŘgČÚ âŃŚëD@ٰMŚx…IĹX˗M'ÄŔąđëżţ[řĺ_ú w¸¸ŃwŰĺȑ#›Ÿ™Žx?˛ť-Ftő… Ř'%Œ˘eÚ$ç꼼%ĺŽë÷Š’äŽ!ŕFÎ8ÜúxĽ!ŕЙ+‘­ ŰŚzžšőşŻ,†P¨ů6÷/–ü;őý¨~žzëööš˙Ň6us7nż”Q-|÷ľřmçj?ěعÕY5ţ/K_ˇÇꥳă]ŒĽ{¸p3,s€ěźآž g~}ŠžÜ‡°]Íń‡ňƒţĂŰUő=^ňş6ěQ ĚbJŽŠf-bô¨WU+5y˜Ž ˜ŐBĄ( QÔAŽT€ÝĽ~ŰCŔ ’VK?SĽ3žO“JČ(0“č(šŰVXyŹz­Ü „#Jęîôüjśd{aYCŁ1Sĺ0Đ1‘_œs9ˆĺĽeu(k[Űď!¨EK˜ĆЈ-‡Ńh.˙nHhré%F˘aŃOĹéŇé*ßÖfŽ‚KbœŞ>=.Ĺý'¸ľOĐuoţqˇƒ˙íÜĺx÷ˇr P¨iôœ{ěÇöŃŽGC:•Ő[ťśéłLî7ŔśÝŠL1îůŢśˇ% ŁXľf[GB†‰9ęΚˇ˝îá>Ÿ˙ýěťkäWÎŢÇĄ†}źŞ]Mދ…Bé°óůšxœzwöÚ¨‡Ş'^×.­×Ťw°ZiTBi¤˜;€Ńą%g'Á6=GĚýﵛî–4Z yeŒË-Î)†IĂő0ů݄Ė( ëAŮ@őŻĎwNӊÜcśo§ŘŇÇšMˇVރÝŕ–[UŚŰýăÝjeĂڝRˆ{Ž–ŘeQĎ@7ÝŮƒ„™çşOö™\ž|o˝ń*žű‘œBôÂť˜:rŐNˆfĐ'ĆF†qţĆ2‘?Rᅧ+s‡qx}׳ŁpPzjm嘀ÍŽ–3ż”/ŠrÜĆáFÇ/ŸFëÉ'ş~•‡N qúM4Śgđş(ŐQťƒgݜCçÖüĎ<+BُŠ÷Ăx<ż č5#cýŮ/>w[ß÷ż˙o‘˙ üÄ?­äđo'˛(E}ř?ćZŇכ8>;‹祃řżźr1€˙Żń0^›‡Ż\/ÂřĆkřë?˙sřÚę ţđĄ#8.cě?xéeTĺ~RâůţoS!T'ć°ÚŔŇČž_š‰h0‚˙¨Üƛ—Żá?~ńYœlT°rč(ţŹ\Ŕ_PíżĎŕßPđ°ďżř/˙ĎxôŃÇ17;ˇçó'¸8¨zٞ¸˝Ű5eÝ9ˇqîŮëřO›Čş!ßyÂŘg‚X&­˛Ł #ŁxoťÁ8O>œÜoEc.+ďß0ď“óe "ž°¸ćĂňŞőö=8 =ńäCH|ý>uş´:ĆŢđSŸ¤=ă3Umť]BC6j˛]+dŒü]6VÖs(’v-4ť>¤#MM• ,ÉzFSt+:nä´ŽţÍJ‰ލËúe]ĐJáü-×.Š6‰Ž‰*PE°‹ŮŽčƙ…CGgp`$ŠŠŠŹžH§r”źXčëŽ6BŠ‚‚d™ &Ľą?­°ŁMúŮgÉNݛÜ]}=Řqůu 2úËń9é3<ů|‹níů¤R(" %"HÇ#Ř^i†W/‹G>_iě™vĎ" C(,ű™kâoďy(ÉGŇ1éOXŸAÉíCS¨d<ŹF}ĽŢşď>…B~BL&ĺwŻŽę˘qDţ^\Ż`~˝„Oćq;؃fi lß×˙ĚhĄ;žÄw…î$ہ’ţKŕĘŕKZŘŹÜŢŘ= ď‡ ăK×ňřáŐ<â5jŤ°÷}ry ňľ6ţç7ĹP#™çhdŇöʇĘ'%J…ÁáhD#ˇ:rƒŽr|´e šœÄ /~Eů´€a4ťZ}ąD2Š^%ž›EŁ-ďŇJľ„ď}˙ť˘Lh5cťíwnšü^}Ţ*k[”ňíiű “ľë1ęľwÝ?ۆ{o;śť‘XšN2€§ËÂŕČ­ÇZJ˜`řüĄŰÚßú^<ďÚ~“N§%ŢÜŹ gÉĎ^@÷GŻ`čŔŹüâŻh…§ŮW_B$‡}đ¨¤ĂHýŕ_ŕäs-Vv@jö0ÖDy×ëzë 3 '–DíÉ𐯉Řűo#pî"O~Ą+7Đ9ń’Ľ˘KŤ8ţÍoâfÍŻ×ôíŹg'`7kH˙ÇxţžŒîš ůÖŻ`-7˜ŤcaqAVa"7ˆŒoߍ?EňđüLJâ?mtđďNdqěÂUüGOáż~ĺ äŽĂ×–ŽĄ9=WEAgtŃ‹ řyýőw4‚ě/=ý,Ž‹ăfźÇ8Mj•:ľ:ʌ#ŢońPĎNâď&’ř Kđ—ŤXzč8^0ěß=ƒż‹ŕߛ…żI$„fŤ‰ĽĽĹ;‚[Œjbôç˘P(¨óŤe’~zzJ‰ăÉĂfö‡‘°‘€PŸgé};Ó^?Ây÷ȑ­Ęccc›ŸűŃhŰŁĘ<ůh„ č~L1ßĹ\ŕ‰'‹l/ĘCÂö„ĚůSţx"°Ľĺ}t ˜C[ĚvD`ˆđ ŰYŤ´°˛’CĄRF6Eṗ†Uç57“Ć×Ň#F'Œ‹ƒ˜ę ŽŃůä3ůekâ f…đ őÜhT#ąb‰8ňëh)ż'#%kÔ0-ך9y@$\;rn›-[ŽęŢ=iŃŇĚPR2Ys"†; FGĺýł zPć™@(§ú,Ť83‚[5WrŐú}&ތ€SĺŮř¨{އ áÉg_łŐv ŃdZď‰ ¸’5ËłíóՐ ,÷o˘"ÄX­wD‘đŁ#^ŚZćĘţqłâÜb䖼o­]ďŞR.PšcűŕhŤzÜvëwŁ-;={׹pÜjgŤ=ëŽ$ů;ż¨pť‚ÄŇť˘‰4wťŐ—zâËđd 9‘ˆâ2őŽź|mŇĎ=ƒĆľHÝş'ęE¤Ć'”,öąFéGŕÎ"Äľäô9ŘĎ}YXzŒăżú+°âIT˙Őďc|jŮ˙éÁJĹáńY ƒˆžđE`f žc#ĂÜ~ˆŇ7~Q­6|ßű1"?÷UĚ'†0qě0œUQÎ@BDÎO ě{8ŃŒ8ą„ł3C°ł ‹Çüo<ó 0ő˙I‡đW„űňChe§kĎ sßůcXÉ\dÖťÜÜüDŤ§Ĺ-ÖÇFoŢĕo|á+×dţěŻ!Ŕ?*Wđ×Ö×đ7žôʎ†ĄËWńŔÔ´–~ď cir ‡_} >Ů|{DVîWív ŐjU,Î[ŒxbĽDY$…g;äUăąkkŤ:o"@÷iˇ<ůŮȠЏž7üéiúĐíűîńE} Ô*n,tpŻşěnG×tż’m3âĹoŞŤQdô‹ }{Ą'ž|Ü÷ťxŕÖ>‘ n1B)›Ši”S6U¤žXmb­XÝq\ťÝō•"Ö˘KáČdW—ó¸ľVÖč(‚]Œę"0F^¤r]ˇ%˘šćÇ0ŇBĽĄŃUr eeâeŠZŢA^ŽďGj9î}q˘dtVUśłO}a˜į̂(ë2Á˝yÉx¨y ăĺő†’ ڇ“XŘ(ëľy-śQƒ' `|(!÷XCŁŐQ°l4×(-NŽ‘ ŠZÇ˙)Äë3"Œ@–‰`‹"+hŔçś^Şé5>ŹEX™żŒZ)§ŠYTŤ”4ôwˇkú Ý žŁ S1(<ž‹…ĺ*‹č6Ĺť?‹˛,Vą¨áŹáůaůŽÖßÜ@c­…ą‰ ]06źľówHžťŽ,ŽCcň|lgfjĘbđ÷0Iéáźn$‚- Ą/bcb:¸Y†^a”HPĎːRfL !m}qŒĹŇ{ęžný•Mß Ł¤zÝbŠ„nd†3r+öąę rAČ~Ş •l*ćŒĘ˘BA~ôđTż[rYŽ0<3oý{]`‚[&şIüYLIŚPŒvP* ä&˙´™ŽČČšnœ$Çtż˛e_‹| ŁGŃNť•c6os‹jžwČëśmšJ„łŠLôŸ‚s[䛳í_ËmĎşíŇDg_;;Ň0­ÍďqPŞĹ ­[ÇoŰ&ʈŻUgV§ąůÚôݰŮĂ<ůDAS™ă˘ŃȎíc0¨t˛šÝvé§Ă~’źH”rĽ†BąŹoŤ3’WŞ" ňN2ä+Ż úˇţB ţĂ˙/&Ÿű"VXzü×~Ą›ó2—8îTáœ<üč4–=űŽČX–q_{đ!Ôz##aŒxZƲšŃ8âëUt×6p˘ş+ü}óXhËß/ĘäČą¸ć˘§ă#“V~nŤĄFŻŽ­–éäÓĘl}0€ëvOtłžSĎ rN!O]@œŽ#)´Äý´lÔÄŔgą„ˆ8Âr…˘YĎlCDMčCgxâÉ^B'o(,ď_T5qřŽÓ1kšľÁj­~ŔEaڝĎ§Żź×mFOřÎű]Ţ-[9Ź4UQ>Sď XTÂQ4Bu”e–ěŚEWwëHǒ˛ů5`Y0Đ;Ч Şw2= {–‚ÁQr`ÉÎVł˘z-Aą.‹Č=`˛ľ˙PçrťŐ6T5źQîý5“q'ýŚÜj’lž§UvĺÉęŕY‹•˜Ţ —3—[ú7çŢŁŹóČxżő’šśňxŃĄě†Tz”ŽűOŠŘ4š gb˜Ě&ą!ŕRĄj&ČąĄ8Rąđćgj*9<ŚŠŽ ™“˛˙ŠăSxůĚź†ŕŽËq7źZ2Á&b!ŘbW†a>ŽąąQüä'/šiYŽ\šŠ“¨œ;w^Ť}ň;ćžůů[š’V’wňÔŠSř8ĽRŽ 0ƒ%ýóË’ąT?őŹß˙}q„D៘ÄĆ˙üuĚFDĄ'Üš9\gÉ,kQţ™5ýŽ€TGçfQ•1šÖn"lUýť˙.˛™”‚CůRE×އD2#†q ßţuœ~ďG"ű˙Ă/<…Ě(œC‡qľĹŹ<Vyj6ç=z(€Ť,n$˛Xż1wF’˜ďMŕ`˝19‰|łĄ(nt-üáâ-<‘LcĄ\DR֒ Śp8X—ńs.5´ŇĎĽ•eü‰žóć›řONGK€ąźĚĹ2g^ň8“:ž~WÁĺőţ÷2^OŒâd]”ůfăÂE43IÎlűîŃČ}@ëN˝Âľ% şG$čSc7¸E€‰yďńd m†hŐ5R+& WŤ^Á­ć ҙŒr÷„ `T7ç6’XˇZ,$ŃĐuŢ/?vOuŒX,˘mƒŃ'˝Ş˘{pm›œ™Sޟ’č‚Ô™bA Éě(††GĹhnŠžŘj‹¨‡‚8R=ńäă@ ą1|Á¨Ió–w”NÚdfH#ÜMF,glo50…sĂX̕]˛Ăö]ôC—ŘFW”ą>ŃRŠTDJ”ÄvŤ)cŒŃ3ŠGŤwł !q›H›Őjióť)—‹ZiĹďżĎŠAűfî?žˆŠÇ‰ż[MŸ.H†$ˇ}Bm„ÂfQ ¸){ô–Ú˝{O ˝›„B[ýW€‡‹kěuwĽőąš6Áj-ň™ýX!Ř鞦čÔ6ÖĹŔmč3g4=PŻýř%éX•őŻ|ĺ+8,Ć,#ăȽÐďĹĹ”Ę%ĘúQŚ3ÎVŠăf8şƒş€bN~7˛ÉşâJ•†pRö]ld.ˇ™ł+°ÎTbÄpËxýśżjúS)€‰(Ůź¤ËçĽń‰ťŢOîł7‰żĚž~T‡˝ ô ˆ‘Ź/˘3 /ćsÇzž|8!Gżˆ‹/ăŤ_ý ~ôŁiT†‡łZ­ˆ\DŻżţžřĹ/âŸýł_ýŐ_ÁúúţěĎž'Ÿü‚žçożýžzęI|ÜŇŚĄNŕňÜĚM`mlđ'ŽŸúx˙=,ő›( 6!NP^–7^}˜~ţůU :§[ÄôdŻżüŽË<:ˆäŕ÷ţńďăŻ˙Íż.Ę| YK°ZŔŇŐy„R“¸&żO=ň0†2 <ôđź#FÄŢZBPłhf}AŁ6;=Ś‘Ă~g°b|fĄ‡Ť+ëřł…ˇdíG.a\œ>ĹŃg1_ÚŔ?x˙ ŞÍ–FƒpŒĎb…Ç*<ű–uÜöwßÁwß{OÇ̏C?ţÇď~G÷ý‡Ĺuńűpˇ5ĘÖ˛šNĺJ”Oo߸&Fˆ_‹żőÇŞŠ?xöYtaŒ/˛Ę“Ÿľ0 ƒQNЀQť…oh d"ś!ÇTĎ Ç #:7şƒ‘‹ň/b˛NÓxڃ‘‘.bAkԇÓé*‹ üňis6ƌžěQe%Ób–Ö?Â~q~ŠŁČŞÖ4e‘NˇŽđ=|öžx˛§¨N.TŚţY˝–<Œî'¨C]“š‘hÍzMِölÇ͒0?.¸ă÷šzšŤčč$5Lľ'6@Kƅ(r‰ˆ…b3* XTúP—u˘Ť:s€@ÉŮ}&‹†ľ¤ŽůeG€Ń`bŰhĺ`ŚKśj&ÍWîĽËôG_ţnÓdCp Éý4DďsÜ´bŰPGSˇĂt`ň݆˝FÍMѤÍÇ%‹:8Á?VAŹ‹r­–ň‰E“)q ĹD‹(˜Í욌ŘL]ŒÉ:Hť1ÔKč8NŠÓh,á׾˛Xať}Íؓý ¸ľOdÇš}áŢë3vŚőkŔ"1|4d€^LĎ;>;˘(šŢ•‚‰Ô‚łÉĽĐŻÚÖ˙|sľ¨ŕ…dďÓâő&¸Ľ„‚Dń˘ęŚ^+4ĽŻ/Ś„,4=Zl`˝› Č÷d‰MSŐžŒeâĎ&äâŔ´I‚N\Ş˘\ŰŹN7 Ďlý\m˝T×JFmQ‘rśỹ—I–ýfĘ&#ĹÎmČ9źśňm˛šďb;.Ŕ ›Š\ł’—ű ȂXՔ#Ž 1ćžťioüVN1ŐŻ6ˇÁĺGK xhÉBp ŽR×,\°JŁ–\ ÝĐä8ĺ°ôýęsÜjĚËÂĺ ßț¨˘Ž‰’rÄä–ĺ lMDCi’%ú€ŸY€|n¤”iwçł0Üç&jˆ1ŹDVíş)wŰReś–­E­•ë ]jj áv>*Íá÷ÍoOŽ›éWđÍŢLěh4X':‰lvHŤŮŮYýݏČb ŐŐëWÍ7IÝďŔOĺž7:F­-`j÷KГ﹝@ ‘i› ˆÎím´i´‘¨€’‘řރDbőwíšu;0­­"šť‚@kgt–Ď a§tâđäCJ2™Ŕ;+_úĽoáôé3xţů/áúőJ¨Mn$r)]ştĎ<ó4Μ9ƒoű×qţüyLOĎČçßĐčĎŐŐU<üđ)Â>nŃt]yoSqzŻřŢ÷€’Ě™—˘Łxˇ˝ŠůüĎđőoýb˘čżńÖ”eęPްşŒůä~´zý`j,Š8(ňĹ 8'öłOŒäľ2ÖJ=Ô+E„;˘ČtpéĘMy>×Qšů+_~J€Żžxň$nŢÄĹsçeŒÉŰ>9§ďđŸNCˆsbdđ‹IPŠ%FršÖǂ…kĚËürzí c'3kA”ę˘äˇÍěŔwýŐKpŁ\vÇ­!ž%ţťoü}@БéŇ1i_ŒŸŠŹƒł7&S~čGâúH"ß_xJźâ–?|ťŽz§§ őßëMü&ŃQž–Îaŕ‰'D´Ŕ‹Ÿ%1Ž[͝Q\‹Z­Şší(F,—ßPť,†¸áÚX]QŔ* Xĺ—őťŁşJW+Ś9Jľ@ý“çÖŤ>ȰĂ7hˆŞ;­ÍőkńÖM„}]~ŠIˆaź–/Šq 0vdî¨ÖđēMä]ëČZ[*›Ď†+ĘQ'T­ŢP‡kDŢ_ňáî•éÁő„ ĚÂPÂ÷žífu؛ŃV\ě’ř˝ĺ Il–p€T!œÉBŇubčľËŚH’c˘,ť2†.1[… 1ëƒcES× D1=X~*LîŮŽţfŠ>ßj5uM'XÜlľĚb›ÔŁŐ邟>ťM=GŸ‚h=^.ęóˆÄÓ†ŁX†“ó°`šŠX*ŁY)śŮŻhŠ—ŘÉď@&ŠfĐ8Ëy– ŮŞŰ6ë;c<ůü‹níů i‰ç0ázžcˆŃ5§y˙CG™ň§!çâ BŃ'ô3×Ć&PÔď‹Q …ŐTŔ ő˛1Ɗ@y­ŕšNfšf@lr/ĚJˆ ë%ĺ›M*dť€šŠÚFŢŠ€KMäJľ&94ĄdT#ǰ ä8.¸ĐŔ2öťÄŽýţ›ŞRťŚČm@X_z:áo?ßppŹ3Q[Î}ťf_čalĘ:núaGŻ—Œ'”‹Ś"J[H‘NĐV "ĐŻbmń4q‘éÉsËś“†ƒĘšŹđű ƒËmy˙–'L¤Ž˝çšš‹dVĄŤ~A€ŢíĺłűŃN˝]Ő ő\—üÜ\݇śżŠůz}Ž™>A­mž¸Wí”Ä‹\m‹÷ČTćsś™v}Úď‡g\žĽ‰.2j Ľx‘OŸ9­iž|=zT#ˇxžXnťß>ŕ6h׽ޠ4ÁÝÇË7ŽHŤ(cǡmŰVŃÇ nm śÚÜŢO—í AĺP7ťź­ uڃŔ-߀ď[óĹ6 tŞpDۍď‘CěLMžě!äŻyńĹô3-ĘČČżÖö4Ăţţ/}éK;Ú8vě(>)áx˘§y(BŠXÁ•óÄňőë¸řĆť˜9pHçNžgaQvżřčQš[h—×Qn˛ŕ†GF1wp‹Kźň“WeĚFń՟{F˙:ΝťŽf~O<”Ĺw_ZŔAŽSzŸí äřTRŕDá7ž$×Ď//Ęţ|C#\Ő°ą^‘5Ł3°ď  Űxâ°ňĎe}â°Ąâ_ÖbëÂb@hTh­' ¸…Qň{ŐŘď(ˆoůŹg^礳.ČÜm‰ڏtĘARć˜WĎUĚşC`KžĹC‡Ł¸śŘĆožĂh*€?zŠ‚j“™ƒ'ŽGpáf ×oÎłťĽď¸qśEœRö:Żś?Č5=ů BLS¸‹Qçeă@Úś–teˇřS›M6ŐjƒÇbťłľ˝Ď ßjŢP1Íq;źFn­íď˘ăö×O>naDc˝6¸Bt›Y­ćϧfGgŤâF€~VzۍďľXÚ2N|ż­NŕT˜1a<ÇFŰŚ“J/čzꎴ+¨ îŠ^Ҕ?:g;ŹîÚËD]q=ăOĄÖwȘ˘ Ęt띏í# LUӉšN˜këŕ(_.ďÝN(ĺ€Cűƒ•ĺÜŽ€ŕAi—ś_ŸrĹi7Dwmk@A:B]œ^˝ž_érx?$š÷ĆôţÜÚ'ňa9ˇnŞ6˙śĹŘčŕęR~űÁŽň ť; Űڐ kXŔ)F^c„U˙:ŒŒ"`5‘M*Y;1†­2…űYyńŇÂFĺœCYŹäŞ.heŽEäţ‰c“ځ-’Ů3Ź–çqâă¤O"zśß鲴­I§dŞ#eJ~÷•x.đF3 MO¤Á2š‰ĄÖt#Ô°’ąŻäk‘~͍ĽőÜńlKe“RůŔ­AßGG&ôjĽ¤Ţ­&"‹ŔplCŐ(BíRÝ,R™4Š#5"CA7ôßkl9ßo5ŃiÄđĘ“ˆ9ác.ç’ËÝä )ómK‰śӏúéżŘEnmÝËöëőAŞ~äVŰć1ÖÖqMQUßčĂšŇˆ$~çSÚöďVű~MCźGڟŢgžGĂ5cÔŃPqW fŕY,†ÇĂŮ!=ćđáĂÍŐÖ`íLęßË@ƒŽ÷âXˇEK"kf9çH;‡p{gj‡FÇą×ö j‰ťŸŔŕČ-MŸlZ:Ć6Ĺq6+÷Ř[Ą‰›Ńh›Üć6!g˘ęěÍă(Ýô4Jż„N(‰ŰĹź[ń[%x˛ż„ä° ńĆ2răĺż‚ĂÇOâŇĽ‹(ćÖ16s?÷őŸÇ#'áÍ×ĎâÁ™IL0z–%ɏDńű˙ę{đGłxćš'pQ@ą7sX]`IŔëRš†Ő7ßFrxçŻ_“šŽ€†Ěűţŕž~úAÔ[XYZFěŘM{Œ@ýĺoţţ͟żŽQŇ*LÇUA$/><ŒgÓ źqą†‹šfŇŔ‰16*n•|Č× ůúƒS>Y[řƒ}nHœľ..ů0ż^G˝Ý3óAnňŤř!ěÇjĄGˆ#—ˇń䉎-őˆ[˜ ὍM<0B,äĂzž‰#3axB#yĚÁƒqA@¸ŻËwĂčŔ+WŽ(GŰɓ§ 9G˛Ý—^zEŽŸSđŸÓŁxż‹‹K˜ššÔ7Ν,l˛°°€ćôúŹĆČ(zč=ů|KťÓĹĎR>Ź.ć‰'? Q?;#­NůĄŠÍNo“‚“€ ë‹#ŔUOćZYg‚äŸ˛kÉš€‚a5Ś+ÂčźL—ě1HĄÓÖH+uü:Ľ¤a{ĆaÝÓję]WýëšÎdŰÄţ_Ű{ďٲü<읥ręœóËa^œœv–ł3Ť]î.ƒIJÜ%Ą`Č$dBś,Ŕ˙ ˀaÓ`@€%K2$‚bÉM3;ť3ĂÉ9źœú˝ÎšťrŽşAżßšUŐŐŐŐýúĹyá|3őŞę†sĎ­ž÷ÜsžóýžŸŰa¸Š4Îâa&ŽËŹdšw˛šeÇ—Ÿ bĚv6Ś×dŇŞ@“Ląۅp™šćd‡(2íW2mĄŕtY1qŞĐ˜Ç€e!’AŘN†G>?K&‡xč É­‡7ű݊›8sF,Ď31Ä$/ߎć@ěSrH%~w”^ś •8‘Y.‡IöĽč Ÿ*äp>>N&WÄĺ™5ěęoÇHO‹ żfV’ˆŇš°=7\iVde ˆř˝č%i™Č-n ůřź},™r˜á‹ń ŽÎG‘#ŠÉŚ€×%ŽÍÇ⏈3Ë ôÓw^Ć!ěĆ ŻQvęÉY"G{Z…Š=‡2ŔçÂY"“™˘ ú¸łvevM4ú\?\Vâi\˜Z­dŕąoMk;JavN3ŮLĆÉč§ŇlFţ6^"­<".Şi-+L],^vë5rĂMƒĄv_j`‡ĎŽ!Pň@Áý5ŁžEs啊ŞńŚÔý[ˇˆřÚvçéü ěƒŔňlŤŇ÷ViÖKsӃ]51;7ƒX4*žp8‚]ťĘ˛ç6u”ííV4Ük[Ř̈´YžC‡˜ÚPŠâ(7ŤƒűŞwY4´7/S*+ěşe˘ƒbhĆ- Ľ¸1óÜF˘Í ‰‡ œ )śşŠ8ľăă—14śĄH OłĂ"1O!CíüÚZ­zÖb+řŤWŽ‚ÝM„ź‚O?;Gí …K݁Ż5ÎMŤ(dR…|čh "“*a˙žatwľâÜšI˛iě>ĄNŻ-źů6éďn‡žO@íéĂűm|x‘Úý\%ĽšĄşOÉa-Ut+a,˘b~Š„Vš;yK:Ć虥Ž=‡dTÂsEgŔňço$aWI|âłOîóy•~ˆkSE\™ád&ĺ i¤ňä6R9qŃ*Ţw¸îŒu*•Ä'!¸víVVVÄrVô˛ăđđ°HHŔ䇽?÷Üłxă7…!ßťű÷ďŸůő駟Š{yff†ÄÇĐŮŮEטXÇíâG}Œ}űö âŒ'y˜ă㏎ŽˇööËÄŘüü<şťťđÄO@BâA†˛…ňú&JÚ 2—xŔQ #d’‰­VŠeÇÜݙ`­LJ2ÉĹ=_řy¨j4Á­;Ě… ăÁńťbŒVŚ}Óů‚xö(ŐŕžŘ'*ĎŻĹŹVó ćˆł21iüĂ EŘ! ž4Ëa•\&oĎď.Őٖ{¤ՃĂ9š„Gd85ÄذLűł×KˇJČsćSö‚ĺŒ‰JAřp‰0c>;wiôœőiśß/”xŹiV2Ž:Q;\&{ kş ‰‡ ’ÜzH`ß ›;×kDü||aé\I4V "¨>lśxqjÓKqŃx§‰đZXM "ÍČů7řôŇŹh4…ą˝é¤ťeB‹ëĘe+çĘÄßىEř<.Ńyác2ĄfÝŚŽ‡] šăÔÚ 6päťšD34Q#ĺdÖŁ—Í)ą¸"‰p˝š‡ 4ƒ“ ÝžAx ™śYĄuÖVvĺś!DDy‚E죏ŤłÖ eĂöB6])ł^ŃWIŘÎŢP•ĘóJŠ]+ĄŞ”cgÓž“ł2śĂÔr˙ l‰JS¤]vÁëőˆż­‡:n‘˛X3_J3忏̈́Z5ěo“ Ž˘öÚ´Ź‰˘ŤZFcůBľŠÚnsŮtĎyZ‘Đ›”nĂ××ÖűeUO˘™˙/ńŰř˘× šĽMő¨Şsž§ ńp;偖LĎ-ŕŠgžĹë?˙9yâk°5/ľŠEj˙SęmŻ\CŽČ—‚Ÿ:šŢ.´ źAş:üôjÁď~,’‡>4Œš(Iú\řřÓs8vüÎ}ţ9çqřč1Ź­Ä0:v˛9ŮŞ rć&Ą):víCÉ_BČČ ˇFçá1bz›ÝÔ3„é5ˇFĹ€!VĹň‚ŸĹö ˘ë‹Ăž9”™ű‰ƒŁťi’ĎÄĘň"MTyPČĺáöúÄ˝Ëg•Ô6Ă6MáßĹ×5ßËzĽŤŹ*xî§IřŠŢŠĹţ\Y¸¨,ÝíGOgDLzń [ÄŕÓ}ŞŘNČ%O@–řšˇ5"½pÚ`ćÖnëćŢíˇŠT2)ÂŚů;?_9ń“ œ$ČEődcn.Ő,œ‘Ú ?ŁžžŰ-Ú7őéĘ–fĐ5O‡÷ű|â> Éżź…Ä˝…ţśš ő˛¸n9‰ ľŮ>Î\Lí:ŤœĘDääˆpÚ4i*ÔRœí܂'ŕuŒß‰äápCŤrÝŠÂc—QŚxˆŹß"y›Î+‚ ŇÝş¸6yĹ׍ŰdŸGŰ1ĽÄ=ɇ.Ň~|?麣 +ÓŕcľŐŃÇĘ[˘Pý!ŒßMť$žQnş^ŁŠŒ8žHâlß]§ůbADŃ0éeTTcδżC„…éœüôű(4ŚR*LsvbČ Ĺ÷8Í3‹z°ˆmëç!üƒů;űa–D?ÝíMސ„ďĂIn=$¸ŐŮfö…Á`%z¨G“ŰËəôáW=rÔXĺęRA;á‡—Őƒgł“4pHbcü9Oő`őV#řœ %KřR5+˛Š ’xVŽeęRż×ďˆëUüF0ˇÄÄVÝŃEëy{°ÖXÍ0Č4ŐvUüŮEľŞI9ǰ ?)Őůj‰PĚ"ÇŽW˛ů‰iżuRĘy_×ôlÔAm0t>)vÝžőôI}ĘF5UeMcčO]ˆŕúş{UË݊ şu8eë>7<­>yę„ ř˝~<˙üóŞÉ󑍸lđY%¸jĽT<Κ…%VC›™Á+öĆíŤä™0âoX^ ĺl,c§†ň  \^”\ FPUţîJUĽU˙Ë ŢÚPvĺÝFý_‹făh Ż•“4ďWwŘ™ÄÆ"Ť_şŒ1‚hW/N|Č~ń>zť şňĺřŒ´űGzi˘$ôěžH.Ňäs;<Ĺ$ŠjŤ+LŽ_ŠŚŢRÔFˇŠݎŔvh ĆÁÇ0}áńúˆ„ †ů‚ŚçJ"Šţ~"ĘüšP0%iäüćëŻačšv(ŤR1 'Ň´îS17ćây"ŞěJ–\z~4DÓ@<§a* u[œ+i ^ęč'h ~tȋřĽö÷ëítăňźI$‹Gwu˘KOă“+)ŹŚy`BĎjobٲ˜Ínőş°ťUGŔçE4k`>UB›W>•——ó˘S˙›O´"FXKЅN"¨úZśďâqv̝‚ŐXUT‰'&†Ž?V[ΤQ=8Cgه›C|bރŞŢޙu&ą¸ĚĹĹE"ł2"Ńđâô÷çɈ(U…Řčč($î l癣ť˝â3_ËĽ˛ťFnxčY×ÖFDdžúŒů4Üm1Šj0Š}a"?y`ŕA/mτű ¨ŻfĐ@ŮM“ˆ žMĄŕ02äę~˜š_ĽzĐÓŔ•ń)töB-çĄëŘE×{Ŗ8k˘U@¨­–˘‰„=ĽL`áÖ6˜C(MćiÂs —ŽsšHL”4´—łŕGňZŞL×YXx—†ˆœĺŽĽQČA§~‘'ŕ‡Jő™Ÿž‚颺•˛ÔƾѺ°“5NuŃšĐ×Ó-2×q;…úsœ;ä׹KŠžg[gľ‹E´Óďă÷qFq KkhyM!äщqĂŇ\T=•Úť¨yƒIǐäÖ˝ś{ĐiŇÄÇŞ"şž¸­Ę鞤ç!÷ŠüĄ<ěĂh8„pÉÚ8Náţ^,]ŔŮÉ5A.qJ„ěąšĘrwł6Š* ĺuÇ7Řţ_VĹĎXc‘ľ˘Tă˛9˘†ë­e "Ňƒ^$šőŕv)†$îTMóoUď#Öé(˛…rœ˙ĐöéÔY‹ÎJQ6R‚au—YFYx?ŻQtÓ,—Ÿ›˛Í!{›`;á°;!ÂؖKóRçuw;ş:z˜‰!˝H3śm~ę`űE§œS~çĘłłUR‘ąŽgRš’8UeŐ&,^n7¸ˆU$ŕUeb •bˇwʰTTJÓmYŢ(ŹAĎměW‰ší‡sý¨cúF4#Ď\ŹćłĘ~Gń‡Íç#qK¸Ÿ ťyJăÔÔ$ú[`ýĚ@9/ t‘ŐnAŃ*"ńę9,Đí=vě ­A ]N ›ƒFdŃM~Ld̜?…`(č\{4‹Üݢ!čîŔřt/&ă8|¨ ]‡žÄħ`ďž>$“Yœ<ЍPĐCƒ "ahPÉîîN/BQó#şt6a?~ŹiÝçăE\‹*ČfxۢăEuÉŃ|ČBJÁXŸ‰ž đ—Q[Líl.:O oÎćđŇą "4zůŕrĎ<=„_ţć(̂‰ľŮijÓ4ô8뛍Çó83—ĹßzŽß~„Ő˘ŠH_¸ęĂ/Žĺńýg˝4Pśń˙˙˛˜ţůš0š`Ó ˇ„ţv ÷îuŔ^…üşP…˘ÇńˇŠ™’6În™ř2ÍÂŚI‰;'Ą OĉŹln”Üú$!/kĄÁźîőŔŚkœ=Ű8‘ ýÇ*;ń| ű—0‰fՒćń‰,‰ •Í*ąËńx­aę˙1T.¨oC}"ÚÖI.cĐ1ÂDŽv ˘ÉësŸx`^6ÁśŰăĎ%VĐ(*őˆxBÁ•JŽ Â,žĘAŚvƒH§éěyä0Î}ň>b~azÍ <\^ŻPoĹRÄpiń‡ˆtňbm‘ęOuőŃzV1ťĂtŢôLLii…[)!ÔŢ#2`ŻŽÄŠ=É"ŕ P}udŇiáS§édhŔÎáԖhW˛‚đëîl§ 8ţäF!WB‚ˆÝΖ6ä,9Ôť—Píéžu+śŔđĂԗô ’†űh[X¢:VŘXććăԖÔů˛nî;ÖM˜+ëGXßßŮVä`W•Z?ÝnvŹjšJÝ,Ť‚Úvöúâ$BŮ#!ń@śx dţƒçÁç \!:ö÷Rǐ–/›˘ÄH̡Ĺh¨Œpw‡˜áŕ?[ʋř|go(]ť‚˘‡¨ęŽ”ĄňŞ­NU}´XJ-ZŻŽVëPŞŰTWÔ+ŤwŞ ´ś(ŤZĽqń Ľ$͍LůE\—"Ą{Ŕűĺ—ŔĘŞ2p˝úđLu.†žEß 08ä”fƒf1úĎţG¤V’b6ëˇ~ë7ńťżűť˘ĚĄ eá1WŸ-Ń9Ȗ**ŘMĂ7ŠŤřaO-všA‰¨TBCoDšei<óFƒĂŘ´mĽö›ëČłqÖ㠚JI—Ĺמmo2˝ßŇ‰Ű›žžćŕ–Ç…oŇŽ]ťDhX2™D ¤h0ř§úç"DěĉX]]Šޞ€KKK´ß4Nž<`0ˆ;1L—Ę4Ő9Íy¨ž—’^ÉŚ1§, ËăĆę#č§őÝ4 U¨-[X#Ö°‘č€X€›ŽŹ˜ČR‡ż§+‚BŃD[wżţ­§ńţgçqîŇUţ„`ţô?ţĎ=ąVé0ŢüĹ)ěŢ݁îŃaxÎĄłĂ§‡đoţjĄÂ\˜ËŚu§Ińš8D8¨­xőó<˛†J¤’ޗޏhP üŐ§6f’&Z| 2y_\Ëáİ ™œ…7ĆÓŇFÝ\=7‡°Ç…éů2ޟPđőVň_.ˆŽůl˘ oH'rŚ$îťČŞ"HóÚ´€…6ż†Š”ŐľűYk S[>ĎöĎ};ä ›Ő6Ązżł÷ŇWW×ĐŐŐ)|łx҄ ĺůZ¸×ÉSŽ#ˇĹ|"ë+|žɟŰŰŰĹ}ÂFúwœí°ŞnNĽ’ľ6ßQ(XŚ{•\v%Űp:—áHÜĎá°Ă™É ń9Ş:ŠmŃ˙Š{ŚFă1ńœe˘jmEuŒ´•ĘŔÚ2+a]žřôSTU ZerŚ–=ŘvBŸŸ;šđqyĐiŃޘżr…ˆŚŒxމ€ű2Ž ľłîö!]Ĺ'9B/&+Şf'™ ‡sůk‰4‡†DhX,ž†^š ť4>‹’a‰ŁąţžoÓ$“&B!sáýŤçĂżĂŐËĹůŠ„7ŞSO^Ž8ÇĺIN͙čI‡čx—‰ěďéj…Ä=b›ĆlĄÎƒ´býJ&ęúgM˛”WŔ×tÉ2!!!ą’ÜzH É­•Ě$â/J=šÖ=]xń˙MdÓřčż˙‰ü°J‚{K^79ćL ęߔ|´;uŕ؏+œsLčs#VŠgšľÎ÷(pS9üđŹçŚ\•đEŁ’DŔ͒e`˝>xU EöTkB7‰ě-,yŚ÷rEÉS YtŠNGÓ°í |XăţŞ[łŻp8Â™XTčÂcŠČŸ­Žu^~ůrĽ×[78ŰĤmüęńęśx¨3á(ŰÔ݃řî?˙gčtőűŰ/żc˙ˇž‘ÜŞÔŮÚ⡰w¸\„v°š&6gElÚxe;rÎpły[§îÍUgÖ ë…ě\d U7mŤBš}Ţ.0ůŔ^6ő搰3gΊŮ~^~öěŮĘŕŢĄběÄaߏ:üâ‹/Ā˙ľ×^ű3ĄÁž8œ­ŽI;V`ŹeR8M3Ş#K4ŔĽëf[iş|>5éşEzež‘VŮľn|âiŰWŚm5ôRë“÷…ÁÖSÁ°_dDœYH`|r kŸ˙ŚÂ/ď—hËÎ|ň "úƒ^Œ śâݟ˙ žpT+ƒĺĽ5XT#÷!ł’B˜î…°žĹUoJ¸ŁiÝM”ˇúźXLŚPö˛ˆG‡y„­âóÓ%1fm&‡ NŽĄřńĺ2JD°ŘÔfíÝÁ=…ĄĄ~SËč¤ăŃ÷ľ‹ôťS•Ę•„˘äš˝^źš‰,=­.œš4ąša?"eú":ŽĆ üŃť%ŒőŃ1‹…fwçF0Ń977_ń-ąńÞYLpr8_şÇ~[~żţ^áá#RťÓ=Í>[áp÷¸Md?-“¸UpűĚ/Fgg'$îœśżbĄ`m\ž°´ş)ƒ´Ő0ÉÂáţ s‹ąźYˇÂ4ˇđsfé*ĘŘŞa"KŒŤńUAź™uŻşhxčî>ţź“T‰ú2Ĺ-ŽÍÉ&Ż]E>—#‚ŤŒé\ź˛O“žJĂäUýů”ę2%—ˇŘ†ů űłúCł%î-8ÄíćzťëWBBbgäÖC[úÚ<0hěrć?——^•YzžůĚqç0DÁ(b1…MƒOÚ+¤ű,ůe“ĘT™N4Đ >> Ý`Ă~ÖěŽË‚ýœí¤do6š*™Y2O™›ELD1‘ĽÔőÓxÇéƐ¸Ş‚˜gMÝ4hăşZÎI‰-Ř´˛,fZ×ĂúŞűY‡ŠżHlןŸx–—É8ŢyśłJČĄzFvEz]™•˝p9ŹyS*'Č>˙ö‡˙ĺ¤# ńĹńÍo~S ř¸óɓiJJ弛܂аIŰŹtb5VŁK­f›)jěşĺ9d5SEŮöڞ7¨ĽŞÇŁkČ"’Đjčl uVexSG\Ý|LĄçşš|ŽšrKâ–Áƒ¨3gÎ ¤ńńŤčďď+Yx†Ÿ‰ÇâĎüˇ:věyä° ž<‡Ŕ`_˘ąggGÍTüN€u¤h0×ç˘6…Ž?]k—éţŮŻSűS. D„W[+Ś1äÝBÔ>ôÚ"‹’đ3•đco„Č-" íĹźX"…×~ţ1ĘtmľGZ1<Ö*IhíeD|:Î^Žr´^řÖ!¤âKDŠ™XžZA6ÄřŒŽgžÜ…˝>…˛îŚű|­iÝçâ%\]ŠĄŻĂ—fĄ3L„~YCŘoáX݉§=n$ł >›˘ö°s=-<)Ą˘Saő•…Ő$ĐݞĂÉN_XŲŠăÜ?’ůÜ4°îjqĄ3äÂB˘ˆ.ąťÓ…ĺ”…3“e$s6B>ÎĚ*TE"ٞ>â§żSc{B5‰‰5:FKßÖż?˙͙ŔĚd˛‚ŕňz}b9üwC˘mĺöŤJ ą{e5z JHÜ îŐöŸĂţŘŕ};óYěÄUľ@$>żŞ`żŁťîűKžDBBâa‚$ˇXÖÝ{˜JÜYT‰& 4—&˛7zT%TČ{=;!KÜ]4ČbcžŇL UCG!…§múAë#ÂÉQn-fsřpyĎöô˘Ăë hؘq)ŸG†Č›N/Ń äjŽ€}4čՉˆ§N`ž3FŇËŻťđb_Db‚%Q,ÂCƒĄ NĎÇâˆŇ ęîHDeŤTnœžGivt_KD,Ż‚O+šłĽ-*V]ą2ŒŻ¨ŐLN_Eńpthš8Íeţ$?…¤QŽŃ6ŐëŻJÚpö”•Lˆ(ŁŚČbœ/Çqj9Z WtΨ—bńŰr*‡DšLő´Łs/X*> ú~˘,#oŽgXŠĆnڕ:¨ľˇýy7z„5¸yą 汗N˘;Ü%Č)ţ]p0St\‘.§ł lQvő$jšT¨>Eae[˝œ‡§´ ťœkŘ´jóž[ÜIR*Şˇ”}3ĺ7SŐo›…Ä݈çž=‡Q,dquüčZč§vcĎžƒH.Ěát<†ľËÔŢtŇ˝~&“…ß~Ú:1sţŇń5|~¤zöÁë beqFt˛5Ż_dˇ˝4šŒňO&Š=QąďĐ. Ršą…üŕ￀á>>|o§ÎL9ÔJdPŸŸšF†˜S—őt"´7"Œë›A„(k.‘m)_@ŚŕB"ŁaWż ÄEáĈ ů>ş\‚—Š‘â"Ŕž:Äńá,&ŻÎŕü’šÇ……d‰ˆ,.'€–ž˝čńyaӄ@ ×ِĽ[DœQćf_<öXřtźŒŸMLXxőĂ"ޚ(ŕŕX+ŞMuűŐçu őHe•„„„㍾=űŽ>_züΟ9…ůľ4Lę#ÔďwÁ™ŕY‰ËIâ™:?ËĽŁ\çťQ-Ř9šľ!ťLŞŞ %–ŮĚPžËi2+ŘŹŽ¨…žn.ß!ˇŹ­Ë†ňBíĐ蚰ˆ¨ćš\>Ű,ăÓŤă(r*oędˇvtÂ]Ăş6˝ÜŽ­EńÔŁO ˝Çĺk×0źB„vä*|~Ý==Âݡë( ´Ÿ1ő Š%'%ř‰§Ņ/Ďá›ßxý=~źöŁWá őŕËĎ/âčă'°#–ČŔďwă‘cű1“r#šNÂÎĽšÖýé]~äŚZđÖĽe1+”1×PVýH4LĹŘDބÇK×}ŃmŔÓÇ˝pŃ ÄĚŮBíŐdľÝ{4ˆXH”ŕji‡7ԁ•Ľ8\ńtęľ5<1¨ŕ5 :L"ůŚć4D<mţž1"˙–Üřł/rŘCdš Řéö+–M¸šôđř>L€LQć(euŻžW÷pfI ‰u(" ěރ‡đÉŰŻÁŕ˙㿍™ŮLN­ Ó[€§˝%öG¤nńÄrZvÇ żř?ůůťş,üů+â/}ß= #Ùłăxd˙0.LŽ żĹż›úÖávš|1ń(v™ęáxÂT7żÔŠ\VT•*Ę3]ÓEˆÝ|ÁK3[aèÎlúŹ(Mýľh?ů×?FzŮ1iýßü üŕűßżW™~ÎPdÖeąqˆBEœs#6¤kރZé Ô/Uu,o%ďÚVS&ŻGˇ…&ŹŽóąžOŁßÜČ6ěUšŽęŚsjv>"xQľĎ-ťÁh_Š(şä0űĄ„‹zŢ]ý˝0f q=ńu63=[ńs‚¸ŸćEˆ\(×ú*].côčŁX͙¸4{žÉqźüÍo#bńoĐŹs ýGŃ8„ŠÓ_"Í`vf żőýo#ľ<W^ůž–AüŮżˇß‡ČžCˆŸš€•‹WńäӇń+ßyŸžÄOß>Mí掌u?>¨â\HĂŢ托ʱůŽMÄwáˇçĐďDŽýWç-¤2*‚~ —犢Íéô—hbAGg ˇăvÓpßD˜KČű­ńŹÝŠ-$$$î p_|rü ž|ęyĚĎ/ă‹/NÓłr k‰bZÁ$'OńÁíő#˘ óç/ĂĂýj]CŠ&^^zö$Ţ}ďŒŇs$ż6‡IšTéěé‚UH#‘*Ąu°édă—瑍ĹphĎ ŇŠ$Ś''Đćłč™:ƒb6‰K“Kh=ś‹K+¸ É­‡ś4m~€ŕ„% ˘ÇćŹ[&4ŐI˙Ě0ˆ4*‰ "’ɤŮűşŹ2‡ęYÎNúh›:ôʜ ľvŔ•ŐĄń`ˆSŚ"ˆ E1‰üRĄZ‘P›o@łůCń,a†ŽĐ:óOĺš\:Íţ(đЍƒîRĄ—4¸KÎńtÎşgqŹ?DČéŹŃ˛ŕÇŹŞ„,*ČCĽ‡°*|n"­ź)ŔKŰsJqß WžęTś…ŇČă˘3'NĆE3Q*%T1UDšt.Ue“) “UăÖgçŰÚÚđ{ż÷{ˆ¸#‚¸čićů0:P|Ľ.ŁŁ8ۂÜÚ"ÓĄZIOžaŰ`8úěśî [o-с˝é˜›=Žę()Ą_ü|ƒó}ľîͨ­Č­Z ö:hęzHěőÎSâᡑéĹ|†ÚŹ‚“ÔÍ>\^ô !n “J‰ľÇíƒAŰüŢűűHDSˆĆóČgS(Qać2xëőךĄĄ{1‚–Î. śˇ#I DÄ<ˇ7ŻüĹĎ]Ąľ5‚ľĽN}úS˜%ťîFßČnx‰<›=wŠf˘]x÷WĄ‡‡D¸˘Śš›Öýç řr>‡Ń7 Űic:|ŽŽČ‰„2Ý(Qť|qś„ŤÁ˛ßWĽ@flœ$Ό' BAn%áˆżgW>xžś.̚ݘšteKE,%‚ áň–ŠבŁv–( Ťœ\CCŽ@í°ęmfŠhŠvp+étqý~‹Ž.‹÷öÎnlž˙3é”đÔ]Ž™|#rٌ˜¸ŕA+Wý`m]>—…ĎŚÚš”¸×ŒčůÉ9–=b ‰{śhgĎ~ň˝šŤ÷ĺ“mKřW˙ĎÖö{ďóó•RĎ?~_L¤ö ŽâŕŽAĚN_Ņńiџüŕý-jCÇ=őÉť5ű ‰ŻňQţ@ $ŘbŸLLÔÓ ŚIłů4“â˘ˆË†ÂęŠr‰Čڞđšr鎍Ěä+´ ĄűdĚ ?}wmbBxĚĆŰhśÚŹŕ!ŻQ*ć”Ő´đ‚č"âÍăs†LřÔĂRl1ŕÔŹćs劮ˆđDÝç”[ÍÖćřaĐ ’3|1Ü4°ăLeĘ1'ŤĄ¨—­6ýÝn1Cƒ Ź,g_[C›Ç‡Ľ5&Ťź(Pű}~ÎŔě’}t{–ˆ4ťtˆeMtď¸5ˆGÁš’:‰ŕšŮ)Ş0­&$RÝí6~ńʏW†Ç„b6˘­˝ P˜fěâű ­c˘ęOţÝżÄ3_˙&ZZé7‹Ž Ľ­CÜ˙NĘË.Ÿ? /M¨0ÉĹeЌŽŽ,ÎÓě~Ą€ţĄœůü#źř­_#‚Ě…{ ˛’¸o`Űwl\ÇŃÓW/Š×N!ĺ÷$šő@*ˇ,\ďĄĆ$ +ş,˘‚T?“`nÇԛŐ6ԍW‰TVhPX(PśÓ€ˆú༪˙“PL4Փ!Nh$Ä:ĄÖą•ap ëLhŠCÄ(ľ•őrá×o,×ůČ!Ş5dúŁ—ÁćůpÖąÍMgTTňĚjRŽRĺq胁ȉm;5mŤł†‡† —uAţtttV Ů×C7(”u‚kx[>ޞů<7-Łż§’ˆB+•7.WČ­ZŃ7⚼Š—ŐpÜ*š…&uDăyV*Ţ,˜Óđľ ß:‚˛î߲.ž9źźH$ˆÇăßůotćĚY´śś Ef,ŤeG<}ú4öíŰ‡ŠŠizß+:ľWތăŔýbýG}Œ“'OĹÎvžn7ŤÄaBŘ2 dryŃq9ŹŇş|é"‘ZyŞOa"€:Ú;­‰Ň†_źů:7‰´Ą˝ŤOźüŤˆšuVâX;˙1:ÍÚćŻá˛ŸÚ3wFf•Ú?ŸPĄjÔv@$–ĐÍÚzä1{ö1œ{óœůŕ žű÷ţŽĄ–St"b˜9őž?źŻiÝýÄĎ\ZÉC#rŠ`hnŐq~"ăť\ŇĽţԁD‰ˆ°  şZÜČći PŔD´ůĺ‚Ajďx›Ý:ŢžšCG€~ĎB FŢ o¤zq ókeüż?ˢ3˘!¤vŰÖ1˝\ęŘĄ‹iSdŔŰŘż?€O&łD*×elňěĎHă—pňÉgą´0‡š™ d‰ŔçűŘG¤ÖňâFwďǁGŽáóŢŠşśöN,‰˜J%„*ëŰżöˇˆźĹż+ˆ.ž.XĹ51~QźłŇk~fí=¸5pŐ°Ĺ|ÎéťUýn+ĎQîrň#Mg9Ó8{ľ*ëýSMAĎ_~拈Jż‹ňč]Š"$îWHrë!”Š>Hp<ˇšű­/łĘDlšĘp !Łş4ńP+IÂţWŠéSK+Ť4Vœ4š RkÜS㪠÷´Ůr˝˛_…řrţˇE˜ UmrŹ›Ë+ ě– Ô*›m!<¨Ö‡¨ÚżPŐcTË­/˛ŽŒňýŐÄÄ˝9”Mç‡.“’w: yę\˜• qŸ)ۖ°i˝ů§ŰZuĽŮO}4–˝Y„ĺ`aKËV•ćuTšěć3V9tśœßŹŇÚPé(Ťŕk†;ą_~yJü}˜¨bŐwx'&&„Ç+ggçđío ăăW‰KˆlŸ““SÔˆNďŐŤW…wŢÜÜ,m;‹h4†žž^ĄPdň,1v{÷îÁôô žóoÓú>Ü(z†qäŃÇqţě)ŹĆcŽęRՑ!nnřBx‰aߏ-ŤŤ+đś‘)¤á ”ążŁ+Y O.AW6k! ŁîZJYüŹ0ƒŤ%z]ÎdˎTUŽĂŤé}˙3Oá;OěB.[ę˙ŒČš(>vcvᓉe,^ëFYmŢMzçjói ľDe||ME˜%VqŻHš­ŕ0K§Żd1Ř­áĘt™ś'2/SĆđn=‡‡‚n㉣Ô6´;ńÎe"ò*–aŒád$ŠÁ5"‰œ#2ÍĺŚ÷˛ ł‰2ţčƒb鲸ŽĚĺqrPG4MŃby{ŠžţA”ŠE"ş¨L ˘ÚˆŹç6[—/œ!ąG vví;ŒîŢ´´ľc~v>‚(ý=Ęĺ’đMěěîĹ؞B˝ŐŢхŠkW0<śG‡“`đu[[eÝip{+šňMËÝT‰šÂDš^}×7Ú\Š ¨sP†3HŚß™;< 昝7řSŐTm[܃Mü˛šy\ą:Ž™§bWuqöŽĘVš,ăsľ:zatőW8;×yn5bsVÄ:FRxq­ť~éÉüKă° š eÔűvĺB_‡Ä­áęŐk¸|ů2†††pöě9Ań߁ŐE2̃ű"„Ş`˛ęŃGOâ˝÷Ţ~h|3ŃĹ'hŘťwŻŘ§J\uwwcddX”ÍŁ"`7CnąˇÇîcGE‘H'apŚ?— A"ĎüôZ]]ŸŘwŻ@׎?Â1"ĂžxďC <ˇQÂđô_ĂÝÁę“?Šá6 Ő˝¸â ĂE篚y¤i0ŔŠR›î›Őĺ8ž¸ś€dščqۍř,_ű#tüƒßĂžŢV,fúaľv5­;_ú}a"’2%‘ůPd­ŐT´ű5ôś>Ż´˝Ňpj†Č–•Z]HŃydsEŒ=ҊůĹY<6¨áőĎ,üÉŤeôŇú•ŹŽ˝}TŢR I7ÚF÷Ŕüڂ§đ5Ď{° Dć—t|L8śß…‘wžUńď>Î#›/áÔD‰Ýńo^Íă=n˘k›ß˙Ŕ#Ç7|äÄăž9ńDísOߝđ€řÜŃUÉ ×ÖsŰş÷ŕ‘Ú÷CÇE#FvíĹÝ@†ŽĽśś$1¤’ ĂŃâq¨$“[ě՘Ëe„˙W÷x˘*‰Đ¤ľccŁČ­-"–)R݅<ľ{š=ŘK•śëë@9Ÿţőbô,ęë!ËŔpCĄ63M“-­Dúë°]ôܚ›‡„ÄW€ŰBVÜ,šUŻ‹¨~–ěÉ= –řŕ€o´fćäJ](Á(ŰČ&ó@1 Đ ËVŠ0˜WˆÜŇątł•ځŸE$‰ćĹí„Ć!“‡0j;ŘÚ1›ż%ĐĎÓÖކ_ű;ż‚ţÖ>ń[WCúŞD0[níŻ&ţ7͌@kű4„dň14–Gbô(Űűđ|ŕUÄŁiäiűż Ż­ăülžfĺM<ˇ?Œg÷šqy†ŰD^ýćŰ;Űś7´!÷š üvđS[6?; ˝3ĄĹJĺb!/H­Ťio#í÷#8z#ŸI)•Ă…łi… 2ôÜKŚ˘´Đ§c9Šaf. w¸‰R†ŽŸÁ‘]>üɛôŮFF #_* g¨Ësk¸üÚ_`mě âǞŔřŔob,˙ý&ç¨-3ŕÓLŹĺAvœČ6VZžÜçÂî^ í­ŰßWk+K‚ŒçvŒŐqŽŘÚցيŤ‚T\Z˜E(ÜR[ŸŒÇ„ Š÷á̇l*ß,sâW &FGv5÷J;xä¤xç󔐐¸ÁDýěÔŇٍjř8ľŃ îłq"T*Őt˙t*VűźMˆ÷L:QYbCňţwˇőŠťUrŤÉtžĽÜ‹a‰lGšľ)܌îDÝëBǞdł(ÎB¨…4˘ء†}QĄDׂÇĺ†E¤‡ćŘ4Cc—K´­ş‰QŞÉ2ő™JÝŰVŃvľᄩąkr%‹aM]ś ƒe7ŠÇú÷uˇxžÁ‚Ą^_Bj‹Bç}'ž[öúÉÖ{`ĺóyLž„UɖČjŞŃŃÇ›I<„[u¤R ‡´śísÂ7BD•6nŻŘ•˛­Ű+qݸ˝ŞTĂë6­”łÉú Dn1ůÄä†ú)ľ(ĂĆZ ÓŃ̎|ś áŠâ…˛­É9ŠÎď%[§‡ĺb Ks 0é";ůňß@ëŕN}đŽ0*Ý}éŘ2Ö˘+bŮšUlÇžÍtŠ)ůşn#šĎŕœiŔLFąË"]śđĚ@+˛­CČb˜3b˜œÇŇâFŽ?†‘§Ÿ†ţÍďaáÝ÷ĄÚ.j–˛đôˆosí*R‰<Ín§¤eş§šÚ4cĎíqŃLˇŠĽŒ?x^CűeŸLYXŃl śkx|ąľŹ‚šŹ š2-ë×Т:§ 8t”HŁńIş)tËn||Ąˆ,uÉVJX[ş ˛Ü†}:‚~~ĺ„Ÿ8ýq‘~‹§auC›yQx}% &–942čĹp 0ľ°{Č*ŐëŃýœNž,Œ†čę’P4ąAź‹fú§'ĆE–DíăĐÔp¤…îw+Kó‚ôúýČfR´źwܗJe˛Űn#•Š÷ ě.Ű1źćň2‰Ż2,ńÁB3Ĺ ƒ3žč—“ .h9\ >ş˘ ˛ŤX(ŇŔÉQBXYš†RěĄ}YĄĐ|8t3 ŽFšĚÉÓxsłüÇWQ!ź˜ÓLĽiމ<š×ľćyeUB/•­śź>ź>/Nž8€âäĎŔŔ 4CƟً •PĹúƒ;%ë›Ĺę*ĽÎ”ż~…R;ŸőE2Pݘ°ć#ś‰ T€fe ˛nłç–ŇŹějBu‹°DUŮt>Őu–W éEhf•Źţ ԛýKHÜďpɞX‹"ŇՅ4Ý;Á„§č~Ę`yqZ˜á›6„g .2ŻZ0ě˛ŕČKl’OWÎ1ú”ärŠş\ԎĽč™f"öŔ.xĚŤšŁĄL÷á×č}‚Ąo”⸺fbĆAkg7+ 0-Ť“çńÁŸpňo<‡˝‡‚˜žÄĄ‰YxóK0Gw!MDľš™ć7đÎ+?Áń#ǚÖ}.ZěŸÇˆT6„JęăIOŽp‚ %joS VMœZ(‰eÝDPQ—ë§_ńŢlcç˛*Ţű`ů2M@ °’2ŕŇ t4,›Ş#4Ľc…CŔPȅ÷fŇČN\ÁŐ÷MjĂ{Ú j"KżXŃť’y ýK„m7ÂU×ëóůKŻĎˇaţ›ŹoŔáäé$$$$$$îvÂÝ4qq;ł%nWQÍÝůüĎ[b+ĽÄýˆjhÚę-0˛ˇV_D¨X…, ˜œ2ł˘ŕSG.Ăd—ż-ˆěŞ–Á‡l)dW™ţÔ›P2!ĂJţŹĐŕŇ4 UV¤Žä0áö„Q*¤¸†pšƒ0ËyT ţnŃŕŇ(ç¨,SÔ^>_ŹĚđˆ:•KYÚŚ,–é.ŽŁŃryB´.٘ĄÁ­Őĺ&ňĺr†Fk*L"š,łäԑֳ¤ËŚci´ËßElrë#ö1˜ššF‡żóóóȤ35oą ŸxęÉĘvEqŽ.]0ËˢŸž!>ÎÁńs~ťKVL°§ĐĆżŤBż“.ü‡* Um[†ŘžŽŰD˜mmâűD†Â%'oËŞ?QF]]ÄrŠäëmSuÚŢŘTGViYÖĆă2ů'Îłá¸\÷ő˛ť!ńp!ŘֆţŃÝ(ó(ć˛8˙î/Đ3vG{éÚua|–HŸˆĹéŕ˘Kł÷!x‚:RąhDÖÇĚ(Ţ*Ň}îwa%S ‘JíA?LZśX,áš@?-¨đćšŮÄĎHÜ"bą˜řý—––qŕŔţÚň••$ Œ‰°łf˜žžĆđđ0î&˜ĐęߡŤ‹sˆ_^%˘ŠéĹYÄVWĄw#Ô3ŒÜľĄ[Úş{ą˙™ă0jy–°˙‹÷-”1Š ×5@׹F&Ę ]=ŕ‘;*úĚ2ډpďčî]áˆ'—ŕiŁ›Ú­ăłĎgńý_ďĹäΞĽK0’ĹJ°Łżô(:Ч¨ĺ˜¤y3°ď”ŰëG™ŽëMLŽć‘)+čzš_.—ŕs9™M_z4ˆ<'ťÇB8łŕ­“ůކÎî%ľVě<ˆ1Ϣ “î m6‘[œ„ˆ¸‚XŠî­Hć.•đíƒ^|8n`6UŽ(śœŠŞ€őNaż§ćܸ:ŻŕV@§ÓPo#mhŔý” RBBBBBâ~óApŽFލˇLpí„ÜŞ'Żă]‰­úmŞ6K%cF×5In}… ‰śCLŐňňՓ%’ʤ‘żT]Ľ—.v˛+$‚]WŽžđZôúŰYYç°=şîÝ:X[ODˆÇßáT ű˛Ź{\ńw)ŇuŸł‡˘ÔJĘ*‚pľČ:BJdë őWĽ0ąŢíöŔĹ~PŚNÇň‹m7 RŞ^RľÚ+›OŞţô›ľpMš]—Ű…–` ‘ Ń + LÇcql És É'ąŽBl5#+—9‘¨Žqţ˘Šňyóöö–$čŚmůUőůjRvXGqNJ“ěŠD‚ąZ7PG‰G<ÇOú ~÷wŻźňŞČä911t:-ÇD")ţ>|-˛‚˝âZ[[ˆt͋Ůx<ŁGÜľ~.•‚UČ`˙ńÝÄc{aÚIÄ×2D(Šđ‡ZP\8ľP‚Ë@!ł€Ť•ĐľwŽ,OĂÎ'‘ěéCËń Ó6™Lůógą°ş†Ç^z ŤĹÜř¸PNî{r7ŇŤ%D]*2éúť=÷é~5QĚçđř^~W} ż¸ha¸/‡D°ôHJž`óĘłęŇŹüô|-V“Ë&F;=řÚ7zŰyvύůŹ ąœ…EłFzßűŽŽ–€Nç\ăńv,ĺÚŃŇUĆًi|r-H@ÁŽvÝńˇ ¸p%Ű =sƒ{ý¸Bxăb钁 [A*Oĺ Ave‹’™ fW-üqÍŞ.‰ ‰ťĂ0fčCőŁŤfƒťáł˝ĹşŚŘŠÜjFZmˇžŚŇ‚#“¨gĺĚl6}>i9‰Ż 2,ńÁ{¨­ÇůŽßŠőd›îBĽ˘ěvĂď÷Áĺr‰AM*™D.ŸŻí˙r]Ö4;ŕţô°§ŒŽY(;7¤ßeóœ*°)ĄŇĐt:™›ą[NČáJnĹbƒŞĂ4p&šBar(ŸŮDݖ˛˛CHŢ)…'Ťślw|i>|Wތ#cqqłłs"›gkk+z{{ńWőCAhq"Vsqť044ˆwß}--wW>çńč‰vt öáÚŐ(Ěä2ŇÉ<=ÇŕňڈO!ęCkŻ™ľ%¤ć§ĐĹ*˛X;„Ŕă(ńŐŃY€śćÁŕĐ( ##č숥ď[ťq>ť‚™+ ŘťxťN‡AY÷đ0:;‹řÎ×4Dł*zť,LNfńčž‘C)Ě­é˜_ĚÁw`Ž.bŢ,oQ{[„UŰJN„ⲕɼDś„3š}wăďčÁĎf"HÎ/bh÷ âăDÂĹóř˙~ćĹŻ?ĄÁEíqŃČ TČ"—ą‘÷{10@gÁƒ\,‰…„…Ǩřá%üj ŤřóϒîtážĺC@!ŇkÁÂtÔĆšĽ擆PŞíd½NSń駟 /ŔžžnşFFk¤Wľ}äSÂ[o˝ŽŽ.:t°ś+Q‹Ĺ"‘¤Eşśzę|˙°áł„„„„„„ÄĂ šh=ä–Őđ~Ł*ŽŚëo$,ąĄĽ4ź7n/Č­óç/}úôÓOţ$ž2Hĺփ[řmu×;K9XĎÇ^VnŻđÚʧRb Îúl~ýťú0˛2͈đC“gJĹPž:@Z7 ŻÉ+ʖT˜IDŒZńőŞßŠ34ňWžY=˘ŤšʆZVDěeŁq¸a]=ëüŐkÂ/ĽJn•ŐušřÁۘú‘P\[@ŠĹ$nܖŐiĐĹÖbÎů4ŹáŔŐP=l9ĐSšsŠMśW6ťˇcĂŇä¸vÖ[–˝ńŸşĺŰÔ˝qyőűŚşŔšśvPG‰›Çŕŕ€ Ş8V×Âw÷îÝ…Bđz=BÝôƒüśXÎËĐÖÖ&îłßř_§{ňî>'ÚŰh •ŕö$qčČ(úÚťqćÓ/ńĹeŮŐXEí¨#ž4‹]#h™ŸĹB1…)Z^/ 3 °Ě"† ÜšDćOÇSˆfŠřîŽehOőâňlK_ÄcOĐ÷rďŸî@aţ ܊'÷•˛°0_@w›Ÿ×ŔË{NáGIüáżHáĽgœx>ߴĂVŞGŞH"Áaŕܞ™tŸ~>Y„őz’Č7šX ÜS  ÇÇĎEÎŘ˙ôqaŻ‚#{ě Ó@+'6ěOÓé¤ý2HŇ40tH6Ë }Ű­bťD6!H1ţđĹvźoÄA<Cޘq—îŚ^Ńô ŻdŐ8§Ş‚ˁćö#ÜŢ#T Ś0‡__kńďh¸6#~seQW/kj(ŻëP~V6“€Źžk(_Ť„Ş†şŠlŤR¸qšFë?/Ş7ŘĂŹA]Ĺ~a"ŹŇT7{n‰:6!Ťč¸Zc&g_ă6Hݸ=űvŠŞsžŇËůÖáńxÄ;“ UëŮîXąUţţţMűŢM´G ˘óXY+ĄC#RjŽ„'YRđcćZœ¸väs‹hď(ÝŔ|:ƒś#'`V0ГĄŽRť ŁÓ_ŔřĹIdłY´IŁć,´¸â82dŕă1"†ŽÄa\ź‚GžŕŞĄă˝Ë1üŤĽ"Nta5f`aąˆżř‰€Ú€Jmn~\š´°÷dóşóŐŕđpRíd0ľˆíR-ž§ qO_Žjhí "?çFŠŽa.ŽNLOψëƒ}ÜLŽ–ËÂa—đĘce “XŹ >xđ€řĚŰśˇˇ b‹IŽsçÎăĉăwÜâߞŐd[˝üKđšńr&äřZçÄ"I‡&Ó$JHHÜŘIťşSíV­Űm+-%$n4Š>÷ÜsŇGžyăNS=_TĎ#ˇsłäV˝ŠŤńsŁĚŒO ¸´´ü']]]˙_ ,–ř@Á˛×ď˙Ş'’cúŽ3ő*˜ÔdŇng@˘ęU“íd׳*Y ER=ËYÁďœŐ°P.Đžĺ`X•€Š‰cł‰24z'ŠHŰaQL%Zž/eĹ *O¤šlŮą”-äĹz&ćœĚ† Ƙŕ(ĽŠĹÇâĎ&•]*—ÄůĺŠYäˆ(3Ź2ˆš‹ţ3Œ˛Ř߲U"˛¨Ž|>4¨dő“nŹr˛Źőkżţ߃Łô˛+~^LřtFGßqIßF|đń $.řź ź! ==k˜ňYXXŁďDŒ<÷¤o&ܰ;F‘ĎŚqpO jWbE†öpôŔĹ$tOŒM#D‹şv …ź>ş?'NИí,byŃĆ@Ť+Ô˙čŻ3ˆn<2äAzŸ?)Ńú"-n„‚Řď¨Jm"ÜËFă9|ňEmĂe|´Iĺ™(!˛žĂíŠUŤ$ĎąĘœŽN’J=9+׎€íľqrqşßx –u|qľŒážöhˆHŹ žXöÁS\A˰Cý †WSȨíčtŁŕJὋyœ=ł„˘ŠVš "^ŔŻ4‰ŕÇ`˜NíhŘł}’ęgžyZ´ĹŹÄâwö]cĽUǎC2™ŔáÇijƒˇőűý"!“§ŹębuŤ™řâý;Z g ô7%őď4ř<˜Źăcs8.u\>V—íßż_„îvvvĐŤ÷¸ßÜ?˛‡Ú{/–Š­3lďĚ@Ŕ'üvy˛˛”ĎPŸŮ†?ŚçeŢH7†şZčٓ§‰›Eéů˔ĐÓFÄżęF–&4"I‰Ś)(Ëb˛Â2ٛ2‹‚˜ĚU1ś{7&Żaqe˛,ąS0gťJlmޏŐçc§äV32Ť!Hh]ź€uß­*šUúÁž˙ßx㍿)Ő[_ dXâƒAŞÔŒ×Q‰ŃŤTuŞ•a/&ŒřŐh#Žş´ŠŃ7?´¨9°œ`źÎP„ÖF*¤N“¨9ä8üšRg*ďléiíä”ŚŞ›fB4RĐ"Â$™˜dQe[§FaÇdXWŤDÜÜÝŞŔë[Љd3 ­ć‘UĺýÔj8 ]ޝ/nĂ} ęL8M 8żKłPÁ겙٪nżŐ,ŰÍ̒mWÖíŞß͔U_fľ HrëaC0Ä3Ŕž\ĆP„ҏąˆPańŐU´ˇşąş˜Bi¤cý†Ě0RńxÓXŞ~dđ˙4ŠžîŽŽąműa ĆÍăĚţv3ex ?ůŇ@Ç<‘|3ÓhSó0‰k š`ąÚČ_ŠíĹjÉ ogúÖ∌ ěéŇp´ßƒh^AŚd1§ĐD€‰Ç‚׾=ąÔčąćőzĹ;+ŻL UÁ~[őhksօáMűWńU¨ěĆuç ŒîînAŕ1ńF‰´sÂ-7y&JHHHÜŕž}WG׎\ĆĐţcč§çD:‡‡Č-KńŇ3Œ&š“+đú|śś5Ž˘ćĹÂě$úÇö੧wÁOÍőՉy´şé9ćí„[+ЄQ%"ľÖ’)řč!×ÝߏčŇ<­-‘=/ PÝ,LÉPs‰ƒU[ĚŃG~čÖŤśŞ°YšŐLĹľŁĆväVł1ívËŞÔĐ$4ńíˇßŽŸ={ö˙:tčđ?ƒÄ]‡4”`oMV2Ç TŐY4 ŰtwĄl;ţ0üÎJ&‡”q4Ik4ŤÝşđ\f%łá=ő:*ŠM'rŤ|}u;b\¨,v$§śí-Ăzi'ÖW<šě&uŹ’;…]ż_3ÜÄßfť˛n[ýn˘Ź eŢäž÷=5ˆÓ§sČJh!"ËŻ-âűż/#•ćŮcЄޭ‹ÁĽűptˇ ?ţĹ"ţӄŠ?ř;-ěďçGąäĆŻžŔĎßËŁԋtş Í<:@gˇ˙bŞ€€ĺÂÔL3y,,HeŁ|˜[Ěcj*%fŠk!Ȋ3?çö¸›*{˜ŕŽDZÄsU´ôŐŽşËí(hŮlžČ4O0-“‡‹ˆšOGœˆ•Dތ?ý ŽŽßŘÄą:[9Ô(”K˜œ[&BËĆpŽ^:żőO_3ńţĺ,žÜeŕ›C9|™Iâä#:ÚčxË +ɒ ŮćÖ ¨şĺRs‰ţŽÜö÷w<łÜ›–łQźEŹ€bľżó÷­śż×!bqffíím"4żŤŤS„Ź2éĹߙ„co:é&!!q?‚•ÂóKkB6ś„Ѝ‰D*…P„UX^‘%ŘG$O$Ż,­p%”i˛Ľ˝ťś_Ĺ*Mޏě"VyG\[BK{ ÂDtÍĎ͢Hݞpółs(di’@Őąź´Ęli ‹č 9Ş”Ř)˜˙aÍCu˘ h>rŮé2[ KŹBÁfŚ­‘ÜbS•ÂńăDzşşşŸ:…Ň\ţ.ĂşWçꯉŽËäˇJíݤ™sĽ–Tńĺç%ÎN5lč%E„ř•Çłh‹—ŕľuěœd°qű‰-Ë^?G•‘şŁt}ßţ˝<–]1ÂßÁńjŰŮuޤĘooٕ{ŞŃPˇ÷z–÷‡Ä Ořž¸Ňƒ÷Ţ˙˙üÚO3ϖ+Ö\6B>š<“^$3Dö 13ŻáëĎş‰¤.Âç×°gďßúeö´16ä&¢^6ű‘ŚüŤď.Đ=”‚U´ŕľLüäŐ8V3EAHő÷‡đâs!dr~š˝öă/ş@vCSnľŒD=˙Â×ń­ď|ŻiÝ˙ŢßůŻđůéOpéĘ%Ąöâ[•ß…•^îUĂ"´ÚËj0ĂD6ŸŞ[:EĚÇ řăOJřt2€_;Ŕcc:âY™ź…hŇÄů9 z"ěagăÂlŽ–ĺđŀ§f ¤KŽWr̊B–Ť¨E‡hřÝżůˇąg÷žm˙ĺĺeáŁĹá{Ź##Ă–ąr‹ąoŸó›4ŞĚ$$$$îđłfić˝6v—–Q‹|¨ÂŽËĆ4+6ŢŘŠü`eQřî `ÁĚcrzNl;SŮvĂ֕$QśmËŽŠÄސL&ţó?ŕš:‡ÚÎoŤ‘OşŁa‰Ő)Ř<]żk։­jX˘YY^uF.Đ,č&“ɰĎç˙$îîYrKâĆĄ –-‘ą~çŰNtbˆ‰+šDFxk™yŽg<=˜ĘD •i§ółK…W÷ÂgűvFúÜJŐ91˘ŞrˆĹg"Ą˘Z Š4+ ĂĘ )şriŃŔnŤŔ~Ζ¨jL}gäŸóMa­÷ŕě-ÔoÍČ- ‰ŻʰáNívw&CΞ=‡ááášÁ<‡iąAřÚZTěż+FŰŻ˙Í˙đżâ÷ŠŞćřËg›oËmÁ‘ęçĘ?mtOŽÔ-[\vnŘoţzEeY ßţľI'S§łĺËôúýb7Oau[ýŁ#cřџý\¨™Ž‹„íŞU¤˝ąSUŰspݙtډ2‰•Xš\VT/ ŠP=W\˘Q_œ ‘ˇa-gKôű"Ű&gOźÉ- ‰ŞČ6Ž8™Çé9Ĺ㟪Ů;ż›ŚŃŕˇloI”Y5|íʆmí-´2’Ö’Ř)ňů܏˜÷Cląş‚ů *?Ôčť4'´śSt5ĹőČ­í$[ź: Ušźł‘˜‰Dţgę Ľ¤‚ëîA’[Ä8ÉŞ¤­Ż˛…OĚú­YځW2C9[~ńÚ &3ôŕӃ^DĚ0îI#˛xyT¨nzř–-yK|×Üg–l˜…őAÝŤ ‚ËČŃşôŐ‘#ˆđ-&hŘ0üŇĽKÁ{ď˝/ŒĂŮOihhHl?88ˆ;&Xtż‰#öpâ×ýŠ­ţŚüwgvĆčč$$$$$âÁ0ÚÚ[ÍćŕuéÂKç>>Mfsˆ|&D<‘‚„ÄWVlUˆ­<֍äë_ŰŠˇŽ7ŔÚvđuŁa‰[ЎŞëę?WŮŁa;fďL:á˙ăôéÓ:ôßI“ů;i(˙AÜňÖu#™€áʁ"LF×Ä5 ˛ ZÂlKdýc"ÉT díLť\3ż]¨—K‹Ź‰Yú­ËNŃř˝~çôć2Ąrˆ%ƒaďĚsŤl9Ţ4;™yrHśÍíŤ] M”÷”Ä=ViƈĐfĄĎ?˙>ú(űbűÜšóxňÉ'qĹŞ¤Ď?˙B(o؇ˆŻi&šŢxăMôôô҉‰›żüËâ{ßű.îfgç@ý*řŃŰŰ[Sq}Ţ~ű"ŕŽŔ0 á›T%žEVUZ677/ÂĎW°‚íă?çÁçŔŞŁRŠ,~VĽńŒ÷ččHm?~˙ýÄ秞zňśdřă2ß|ó-Ą†ęďďC__ߌP‘ęwV̝;wŽČÇ݈ÇăŘľk ăăW…/˙FŹÄłęĆôô4‘–ِx¸ ÚţşűčŮV„™NAo‹ `ĐóÁ,!ŠŔăÖ%š%q×Áćńçϟ˙ĂŁGţ”žć°ŽŘކ$VŐ[[…$Öă†U[Œ[7˘ŢŞ_^/3Ť'¸ŞËM:ńžđ ďü‡˙đGżÝÓÓ-3)ŢAŘRšő@axiXNƒ#cŔ.Ń@•ˆň\j …R†H UȗKuˇ"“3ô;ěá€ěquíÚ5AŇÍÎΊAţŰVłJrKBBBâ!+‡i˛ŁœM ž)Áe•áÓ<"óx*™ƒćňŠgŒ„ÄÝ“ZKKËň;żóƒ?~ë­ˇŘ<ž["Š 6z°W?Ű×ym…ë];UnՏ-Ő[ÍRőÝbԟ@5›˘]y7é( ô˙KúüŻßzëÝç>đ¨ß<ěvëC4€l­+硆đ!Š˜U=ŽŠ‚¤ňnŰfŏɪ}çźč>Ď˝ŸáHb§p”C>—›ŻSĂ{/n?Ԙ†€í‡˛Pč™ő„BĽP)Cľ›Ťl—pE?ífˇSśu Ń x¨ËŐSéŰŔÖ-xÝ;óˆŃ]:>?ýÎ^¸áŠŠ˝źôÝďuÁV…$n"!?éŐÉ ^u߅ÁőŽitľMlf-ÔŘf‚:~÷$j÷]ĺ]uT™Źtäl ěíĆď*-WƒîY‹ˆhşÉ[ťň9?{%qx!cttř`‹U@U<˙üsľĎL,ŐoÇŕmůĹŠŽ—_~éśe•kV+ŤřďsüřqAŞąÂŠMËyŰăǏů6-ČË—Ż Ÿ/B‡IŁ|ž(ęËudĽVOOŻ đŰÚÚYÇJ(>Ť Ş~Q|,.÷‘G‹ăp矷ĺeÉŮüü‘`^ąŒÉ›őSDE Ď>ű,[DčחÉ9>&[‘HHÔ9 ň+Áx@(´¸>LÚ öÓ>ޞnßž˝¸té˛ yݍև%3n ž]?tzFhn/Tz¨.šŇuç>Ó*m¤Uź"ăHŢťúýŢý}o´Ít{u‘eÍ Ăwú”bRĚRéĽ •¨đó4UĄ çögG™ˆ%$$n "ň€î1qę*ň…Ě'&…Z[ďĚÄÔý~–{}n7ЈIÓ+žeš 5ńšžßЊ&ţzmćC ‹úńRɘÉĺ2ÔÝşřŮ /<÷."ŤęŻebëPÄz^h+bŤ™jkG˜ůS)[|Wš|ŽŠ ŸľĘKmřÎ/&Ű\•÷Ć}•mę !!!!!!!!!!!!!!!!qóhć­^˙ŞSŹĆކ6#˛ężď”Ô˛ˇŠĂuq3Ůż×,u°ľŠŤž˜ŞžT•ŘŞĎŞ¨Ö˝€urK­;†$´$$$$$$$$$$$$$$$$îę §ú,‡ŐďVĂňúŒˆYˇ Cźeb‹qł†ňßwz@Ťnű꫞ŔŞ~6+žPˇź ItIHHHHHHHHHHHHHHHÜ:ꚍás˝ ŘHjŐžĄľ“PÄfߡĹ͒Cۅ(Vߡ UÜ.lą^ľU˙Ž\çŘ7Ž­ČĽzőVăűNÂw˘Ôş%b‹qŤÄ˛ÍçfäVă÷fDĐ<qŤc5ű.!!!!!!!!!!!!!!!!q}lG.5’SV“Ď;!łš‘[Řćó áFĂQŚx=ď­­B•&űńç*بÜjüźÝ2 ‰ć°ŻłŹQšľŃľSB뜊ľęq; ĄŞ¸š-köyťpDeuh{ˡ O܎źjFdÝvľV=nUšUQqmľďVeÔż7~n„$¸$$$$$$$$$$$$$$$$ś†˝ĂuöMź_olńýŚq'ˆ íü°”[|ßę×[.!!!!!!!!!!!!!!!!ąŽ(ˇężßěűveŢÜI2HšÎ睐^Ű}Ć–KHHHHHHHHHHHHHHHHl OŹ˙lď`ÝvŸoî4)t#*Ž~Ţn™„„„„„„„„„„„„„„„„ÄÍa§ó[}žkj­zÜ ‚HšďĘ ěw˝ăHHHHHHHHHHHHHHHHHl ű×ďT‘u׈-ĆÝ"„v˘źÚ ™% , ‰;ëЏvň}ŤeˇînÄ/K’X_vj8ŁŰŢvÜMr‹ĄÜuwöXw[qˇÉ­*îś–$Ç$$$$$$$$$$$$$$$FÜn’éF}şî8ž*rŤŠ!$A%!!!!!!!!!!!!!!!q÷p#DŐ]'ľŞřŞÉ­*$q%!!!!!!!!!!!!!!!q˙á+#ľŞ¸WČ­zH˘KBBBBBBBBBBBBBBBâŢĹWNhŐă^$ˇ!É. ‰Ż÷™ŐˆűÜ’h ÷)$š%!!!!!!!!!!!!!!!!qßB’[÷-$š%!!!!!!!!!!!!!!!!qßâ? 1: json_path = sys.argv[1] if len(sys.argv) > 2: linguas_path = sys.argv[2] if len(sys.argv) > 3: output_path = sys.argv[3] if not Path(linguas_path).exists(): print(f"Error: LINGUAS file not found at {linguas_path}") sys.exit(1) if not Path(json_path).exists(): print(f"Error: JSON file not found at {json_path}") sys.exit(1) add_translations_to_json(json_path, linguas_path, output_path, minify) if __name__ == "__main__": main() kolunmi-bazaar-7b9c8e1/scripts/install-deps/000077500000000000000000000000001514314607700211505ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/scripts/install-deps/fedora-rawhide.sh000077500000000000000000000006401514314607700243700ustar00rootroot00000000000000#!/usr/bin/env bash DEPS=( meson ninja cmake blueprint-compiler desktop-file-utils gtk4-devel libadwaita-devel libdex-devel flatpak-devel libxmlb-devel appstream-devel glycin-devel glycin-gtk4-devel libyaml-devel libsoup3-devel json-glib-devel md4c-devel webkitgtk6.0-devel libsecret-devel # lsp clangd ) dnf install ${DEPS[@]} kolunmi-bazaar-7b9c8e1/src/000077500000000000000000000000001514314607700156515ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/bazaar.gresource.xml000066400000000000000000000421051514314607700216320ustar00rootroot00000000000000 gtk/style.css progress-bar-designs/pride/pride-flags.yaml main-config-schema.xml blocklist-schema.xml curated-config-schema.xml pride-flag-config-schema.xml release-notes.xml countries.json bz-addons-dialog.ui bz-donations-dialog.ui bz-age-rating-dialog.ui bz-app-size-dialog.ui bz-app-tile.ui bz-all-apps-page.ui bz-apps-page.ui bz-appstream-description-render.ui bz-curated-view.ui bz-category-tile.ui bz-context-tile.ui bz-curated-app-tile.ui bz-decorated-screenshot.ui bz-developer-badge.ui bz-entry-inspector.ui bz-entry-selection-row.ui bz-favorite-button.ui bz-favorites-page.ui bz-favorites-tile.ui bz-featured-carousel.ui bz-featured-tile.ui bz-flathub-category-section.ui bz-flathub-page.ui bz-full-view.ui bz-hardware-support-dialog.ui bz-inspector.ui bz-library-page.ui bz-installed-tile.ui bz-license-dialog.ui bz-login-page.ui bz-markdown-render.ui bz-preferences-dialog.ui bz-progress-bar.ui bz-releases-dialog.ui bz-releases-list.ui bz-rich-app-tile.ui bz-row-view.ui bz-safety-dialog.ui bz-screenshot-page.ui bz-screenshots-carousel.ui bz-search-widget.ui bz-section-view.ui bz-stats-dialog.ui bz-transaction-tile.ui bz-transaction-list-dialog.ui bz-updates-card.ui bz-user-data-page.ui bz-user-data-tile.ui bz-window.ui gtk/shortcuts-dialog.ui icons/scalable/actions/app-installed-symbolic.svg icons/scalable/actions/bookmark-filled-symbolic.svg icons/scalable/actions/bookmark-outline-symbolic.svg icons/scalable/actions/check-plain-symbolic.svg icons/scalable/actions/circle-filled-symbolic.svg icons/scalable/actions/code-symbolic.svg icons/scalable/actions/community-symbolic.svg icons/scalable/actions/connected-squares-x-symbolic.svg icons/scalable/actions/copy-symbolic.svg icons/scalable/actions/cross-large-circle-filled-symbolic.svg icons/scalable/actions/delay-symbolic.svg icons/scalable/actions/device-support-adaptive-symbolic.svg icons/scalable/actions/device-support-desktop-symbolic.svg icons/scalable/actions/device-support-touch-symbolic.svg icons/scalable/actions/device-supported-symbolic.svg icons/scalable/actions/download-plus-symbolic.svg icons/scalable/actions/drive-harddisk-symbolic.svg icons/scalable/actions/earth-symbolic.svg icons/scalable/actions/edit-clear-all-symbolic.svg icons/scalable/actions/execute-to-symbolic.svg icons/scalable/actions/external-link-symbolic.svg icons/scalable/actions/eye-outline-filled-symbolic.svg icons/scalable/actions/flathub-symbolic.svg icons/scalable/actions/flatpak-symbolic.svg icons/scalable/actions/folder-download-symbolic.svg icons/scalable/actions/globe-symbolic.svg icons/scalable/actions/go-previous-symbolic.svg icons/scalable/actions/graph2-symbolic.svg icons/scalable/actions/hand-openyay-symbolic.svg icons/scalable/actions/heart-filled-symbolic.svg icons/scalable/actions/heart-outline-thick-symbolic.svg icons/scalable/actions/horizontal-arrows-disabled-symbolic.svg icons/scalable/actions/left-large-symbolic.svg icons/scalable/actions/library-symbolic.svg icons/scalable/actions/license-symbolic.svg icons/scalable/actions/media-playback-pause-symbolic.svg icons/scalable/actions/media-playback-start-symbolic.svg icons/scalable/actions/media-playback-stop-symbolic.svg icons/scalable/actions/newspaper-symbolic.svg icons/scalable/actions/parent-symbolic.svg icons/scalable/actions/people-symbolic.svg icons/scalable/actions/person-symbolic.svg icons/scalable/actions/pip-out-symbolic.svg icons/scalable/actions/power-profile-performance-symbolic.svg icons/scalable/actions/puzzle-piece-symbolic.svg icons/scalable/actions/proprietary-code-symbolic.svg icons/scalable/actions/regex-symbolic.svg icons/scalable/actions/right-large-symbolic.svg icons/scalable/actions/sad-computer-symbolic.svg icons/scalable/actions/share-alt-symbolic.svg icons/scalable/actions/share-symbolic.svg icons/scalable/actions/server-pick-symbolic.svg icons/scalable/actions/sidebar-show-symbolic.svg icons/scalable/actions/sliders-horizontal-symbolic.svg icons/scalable/actions/smartphone2-symbolic.svg icons/scalable/actions/software-update-available-symbolic.svg icons/scalable/actions/square-filled-symbolic.svg icons/scalable/actions/thumbs-up-outline-symbolic.svg icons/scalable/actions/timer-sand-symbolic.svg icons/scalable/actions/translations-symbolic.svg icons/scalable/actions/user-trash-symbolic.svg icons/scalable/actions/verified-checkmark-symbolic.svg icons/scalable/actions/view-more-horizontal-symbolic.svg icons/scalable/actions/view-more-symbolic.svg icons/scalable/actions/zoom-minus-symbolic.svg icons/scalable/actions/zoom-plus-symbolic.svg icons/scalable/actions/permissions-legacy-windowing-system-symbolic.svg icons/scalable/actions/permissions-microphone-symbolic.svg icons/scalable/actions/permissions-sandboxed-symbolic.svg icons/scalable/actions/permissions-screen-contents-symbolic.svg icons/scalable/actions/permissions-system-devices-symbolic.svg icons/scalable/actions/permissions-warning-symbolic.svg icons/scalable/actions/app-safety-ok-symbolic.svg icons/scalable/actions/app-safety-unknown-symbolic.svg icons/scalable/actions/app-safety-unsafe-symbolic.svg icons/scalable/actions/auditable-code-symbolic.svg icons/scalable/actions/ratings/advertising-symbolic.svg icons/scalable/actions/ratings/advertising-none-symbolic.svg icons/scalable/actions/ratings/alcohol-use-symbolic.svg icons/scalable/actions/ratings/alcohol-use-none-symbolic.svg icons/scalable/actions/ratings/audio-chat-symbolic.svg icons/scalable/actions/ratings/audio-chat-none-symbolic.svg icons/scalable/actions/ratings/contacts-symbolic.svg icons/scalable/actions/ratings/drug-use-symbolic.svg icons/scalable/actions/ratings/drug-use-none-symbolic.svg icons/scalable/actions/ratings/gambling-symbolic.svg icons/scalable/actions/ratings/gambling-none-symbolic.svg icons/scalable/actions/ratings/human-remains-symbolic.svg icons/scalable/actions/ratings/messaging-symbolic.svg icons/scalable/actions/ratings/messaging-none-symbolic.svg icons/scalable/actions/ratings/money-symbolic.svg icons/scalable/actions/ratings/money-none-symbolic.svg icons/scalable/actions/ratings/nudity-symbolic.svg icons/scalable/actions/ratings/nudity-none-symbolic.svg icons/scalable/actions/ratings/smoking-symbolic.svg icons/scalable/actions/ratings/smoking-none-symbolic.svg icons/scalable/actions/ratings/social-info-symbolic.svg icons/scalable/actions/ratings/strong-language-symbolic.svg icons/scalable/actions/ratings/strong-language-none-symbolic.svg icons/scalable/actions/ratings/violence-symbolic.svg icons/scalable/actions/ratings/violence-none-symbolic.svg icons/scalable/actions/on-the-go-symbolic.svg icons/scalable/actions/we-love-games-symbolic.svg icons/io.github.kolumni.Bazaar.Create.svg icons/io.github.kolumni.Bazaar.Develop.svg icons/io.github.kolumni.Bazaar.Learn.svg icons/io.github.kolumni.Bazaar.Play.svg icons/io.github.kolumni.Bazaar.Network.svg icons/io.github.kolumni.Bazaar.Work.svg icons/io.github.kolumni.Bazaar.Audiovideo.svg icons/io.github.kolumni.Bazaar.Science.svg icons/io.github.kolumni.Bazaar.System.svg icons/io.github.kolumni.Bazaar.Utilities.svg icons/io.github.kolumni.Bazaar.Mobile.svg icons/io.github.kolumni.Bazaar.Trending.svg icons/io.github.kolumni.Bazaar.Popular.svg icons/io.github.kolumni.Bazaar.New.svg icons/io.github.kolumni.Bazaar.Updated.svg icons/io.github.kolumni.Bazaar.Adwaita.svg icons/io.github.kolumni.Bazaar.Kde.svg icons/io.github.kolunmi.Bazaar.github.svg icons/io.github.kolunmi.Bazaar.gitlab.svg icons/io.github.kolunmi.Bazaar.gnome.svg icons/io.github.kolunmi.Bazaar.kde.svg icons/io.github.kolunmi.Bazaar.google.svg kolunmi-bazaar-7b9c8e1/src/blocklist-schema.xml000066400000000000000000000007141514314607700216210ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/bz-addons-dialog.blp000066400000000000000000000013761514314607700214750ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAddonsDialog: Adw.Dialog { content-width: 550; content-height: 500; child: Adw.ToolbarView { [top] Adw.HeaderBar { title-widget: Label { styles [ "heading", ] label: _("Manage Add-ons"); }; } content: ScrolledWindow { propagate-natural-height: true; vexpand: true; hscrollbar-policy: never; child: Adw.Clamp { maximum-size: 500; tightening-threshold: 500; child: Box { orientation: vertical; margin-top: 24; margin-bottom: 24; margin-start: 12; margin-end: 12; Adw.PreferencesGroup addons_group { } }; }; }; }; } kolunmi-bazaar-7b9c8e1/src/bz-addons-dialog.c000066400000000000000000000256371514314607700211500ustar00rootroot00000000000000/* bz-addons-dialog.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-addons-dialog.h" #include "bz-entry.h" #include "bz-env.h" #include "bz-flatpak-entry.h" #include "bz-result.h" #include "bz-util.h" struct _BzAddonsDialog { AdwDialog parent_instance; BzResult *entry; GListModel *model; DexFuture *task; /* Template widgets */ AdwPreferencesGroup *addons_group; }; G_DEFINE_FINAL_TYPE (BzAddonsDialog, bz_addons_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_ENTRY, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_TRANSACT, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void transact_cb (BzAddonsDialog *self, GtkButton *button) { BzEntry *entry = NULL; entry = g_object_get_data (G_OBJECT (button), "entry"); if (entry == NULL) return; g_signal_emit (self, signals[SIGNAL_TRANSACT], 0, entry); } static void update_button_for_entry (GtkButton *button, BzEntry *entry) { gboolean installed = FALSE; gboolean holding = FALSE; const char *icon_name; const char *tooltip_text; g_object_get (entry, "installed", &installed, "holding", &holding, NULL); if (installed) { icon_name = "user-trash-symbolic"; tooltip_text = _ ("Remove"); } else { icon_name = "folder-download-symbolic"; tooltip_text = _ ("Install"); } gtk_button_set_icon_name (button, icon_name); gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip_text); gtk_widget_set_sensitive (GTK_WIDGET (button), !holding); } static void entry_notify_cb (BzEntry *entry, GParamSpec *pspec, AdwActionRow *action_row) { g_autofree char *title = NULL; g_autofree char *description = NULL; GtkButton *action_button = NULL; action_button = g_object_get_data (G_OBJECT (action_row), "button"); if (action_button == NULL) return; g_object_get (entry, "title", &title, "description", &description, NULL); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (action_row), title); adw_action_row_set_subtitle (action_row, description); update_button_for_entry (action_button, entry); } static AdwActionRow * make_action_row (BzAddonsDialog *self, BzEntry *entry) { AdwActionRow *action_row = NULL; const char *flatpak_version = NULL; const char *title = NULL; const char *description = NULL; g_autofree char *title_text = NULL; GtkButton *action_button = NULL; action_row = ADW_ACTION_ROW (adw_action_row_new ()); adw_preferences_row_set_use_markup (ADW_PREFERENCES_ROW (action_row), FALSE); flatpak_version = bz_flatpak_entry_get_flatpak_version (BZ_FLATPAK_ENTRY (entry)); title = bz_entry_get_title (entry); description = bz_entry_get_description (entry); title_text = g_strdup_printf ("%s %s", title, flatpak_version); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (action_row), title_text); adw_preferences_row_set_use_markup (ADW_PREFERENCES_ROW (action_row), TRUE); adw_action_row_set_subtitle (action_row, description); action_button = GTK_BUTTON (gtk_button_new ()); gtk_widget_set_valign (GTK_WIDGET (action_button), GTK_ALIGN_CENTER); gtk_widget_add_css_class (GTK_WIDGET (action_button), "flat"); g_object_set_data_full (G_OBJECT (action_button), "entry", g_object_ref (entry), g_object_unref); g_signal_connect_swapped (action_button, "clicked", G_CALLBACK (transact_cb), self); update_button_for_entry (action_button, entry); g_object_set_data (G_OBJECT (action_row), "button", action_button); adw_action_row_add_suffix (action_row, GTK_WIDGET (action_button)); adw_action_row_set_activatable_widget (action_row, GTK_WIDGET (action_button)); g_signal_connect_object (entry, "notify::installed", G_CALLBACK (entry_notify_cb), action_row, G_CONNECT_DEFAULT); g_signal_connect_object (entry, "notify::holding", G_CALLBACK (entry_notify_cb), action_row, G_CONNECT_DEFAULT); return action_row; } static gint cmp_future (DexFuture *a, DexFuture *b) { const GValue *a_val = NULL; const GValue *b_val = NULL; BzEntry *a_entry = NULL; BzEntry *b_entry = NULL; a_val = dex_future_get_value (a, NULL); b_val = dex_future_get_value (b, NULL); if (a_val == NULL || b_val == NULL) return 0; a_entry = g_value_get_object (a_val); b_entry = g_value_get_object (b_val); return strcasecmp (bz_entry_get_title (a_entry), bz_entry_get_title (b_entry)); } static DexFuture * populate_addons_fiber (GWeakRef *wr) { g_autoptr (BzAddonsDialog) self = NULL; guint n_results = 0; g_autoptr (GPtrArray) futures = NULL; bz_weak_get_or_return_reject (self, wr); n_results = g_list_model_get_n_items (self->model); futures = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < n_results; i++) { g_autoptr (BzResult) result = NULL; g_autoptr (DexFuture) future = NULL; result = g_list_model_get_item (self->model, i); future = bz_result_dup_future (result); if (future != NULL) g_ptr_array_add (futures, g_steal_pointer (&future)); } dex_await ( dex_future_allv ( (DexFuture *const *) futures->pdata, futures->len), NULL); g_ptr_array_sort_values (futures, (GCompareFunc) cmp_future); for (guint i = 0; i < futures->len; i++) { DexFuture *future = NULL; const GValue *value = NULL; BzEntry *entry = NULL; const char *id = NULL; AdwActionRow *action_row = NULL; future = g_ptr_array_index (futures, i); value = dex_future_get_value (future, NULL); if (value == NULL) continue; entry = g_value_get_object (value); id = bz_entry_get_id (entry); if (strstr (id, ".Debug") != NULL || strstr (id, ".Locale") != NULL) continue; action_row = make_action_row (self, entry); if (action_row != NULL) adw_preferences_group_add (self->addons_group, GTK_WIDGET (action_row)); } return dex_future_new_true (); } static void populate_addons (BzAddonsDialog *self) { if (self->model == NULL || self->addons_group == NULL) return; dex_clear (&self->task); self->task = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) populate_addons_fiber, bz_track_weak (self), bz_weak_release); } static void bz_addons_dialog_dispose (GObject *object) { BzAddonsDialog *self = BZ_ADDONS_DIALOG (object); g_clear_object (&self->entry); g_clear_object (&self->model); dex_clear (&self->task); G_OBJECT_CLASS (bz_addons_dialog_parent_class)->dispose (object); } static void bz_addons_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAddonsDialog *self = BZ_ADDONS_DIALOG (object); switch (prop_id) { case PROP_ENTRY: g_value_set_object (value, self->entry); break; case PROP_MODEL: g_value_set_object (value, self->model); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_addons_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAddonsDialog *self = BZ_ADDONS_DIALOG (object); switch (prop_id) { case PROP_ENTRY: g_clear_object (&self->entry); self->entry = g_value_dup_object (value); break; case PROP_MODEL: g_clear_object (&self->model); self->model = g_value_dup_object (value); populate_addons (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_addons_dialog_constructed (GObject *object) { BzAddonsDialog *self = BZ_ADDONS_DIALOG (object); G_OBJECT_CLASS (bz_addons_dialog_parent_class)->constructed (object); if (self->model && self->addons_group) populate_addons (self); } static void bz_addons_dialog_class_init (BzAddonsDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_addons_dialog_dispose; object_class->constructed = bz_addons_dialog_constructed; object_class->get_property = bz_addons_dialog_get_property; object_class->set_property = bz_addons_dialog_set_property; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_READWRITE); props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_TRANSACT] = g_signal_new ( "transact", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_TRANSACT], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-addons-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzAddonsDialog, addons_group); } static void bz_addons_dialog_init (BzAddonsDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_addons_dialog_new (BzEntry *entry, GListModel *model) { BzAddonsDialog *addons_dialog = NULL; addons_dialog = g_object_new ( BZ_TYPE_ADDONS_DIALOG, "entry", entry, "model", model, NULL); return ADW_DIALOG (addons_dialog); } kolunmi-bazaar-7b9c8e1/src/bz-addons-dialog.h000066400000000000000000000021021514314607700211330ustar00rootroot00000000000000/* bz-addons-dialog.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry.h" G_BEGIN_DECLS #define BZ_TYPE_ADDONS_DIALOG (bz_addons_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzAddonsDialog, bz_addons_dialog, BZ, ADDONS_DIALOG, AdwDialog) AdwDialog * bz_addons_dialog_new (BzEntry *entry, GListModel *model); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-age-rating-attribute.txt000066400000000000000000000005271514314607700230460ustar00rootroot00000000000000prefix=bz name=age_rating_attribute parent-prefix=g parent-name=object author=AUTOGEN include="bz-context-row.h" property=importance BzImportance BZ_TYPE_IMPORTANCE enum property=id char G_TYPE_STRING string property=title char G_TYPE_STRING string property=description char G_TYPE_STRING string property=icon_name char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-age-rating-dialog.blp000066400000000000000000000015241514314607700222360ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAgeRatingDialog: Adw.Dialog { content-height: 550; content-width: 640; title: _("Age Rating"); Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { hscrollbar-policy: never; Adw.Clamp { maximum-size: 600; tightening-threshold: 400; Box { orientation: vertical; spacing: 24; margin-start: 24; margin-end: 24; margin-top: 24; margin-bottom: 24; $BzLozenge lozenge { title: _("Age Rating"); label: "?"; importance: neutral; } ListBox list { selection-mode: none; styles [ "boxed-list", ] } } } }; } } kolunmi-bazaar-7b9c8e1/src/bz-age-rating-dialog.c000066400000000000000000001066101514314607700217050ustar00rootroot00000000000000/* bz-age-rating-dialog.c * * Copyright 2021 Endless OS Foundation LLC * Copyright 2025 Alexander Vanhee * * Author: Philip Withnall (GNOME Software) * Adapted for Bazaar by Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include #include "bz-age-rating-attribute.h" #include "bz-age-rating-dialog.h" #include "bz-context-row.h" #include "bz-lozenge.h" struct _BzAgeRatingDialog { AdwDialog parent_instance; BzEntry *entry; BzLozenge *lozenge; GtkListBox *list; }; G_DEFINE_FINAL_TYPE (BzAgeRatingDialog, bz_age_rating_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL }; typedef enum { BZ_AGE_RATING_GROUP_TYPE_DRUGS, BZ_AGE_RATING_GROUP_TYPE_LANGUAGE, BZ_AGE_RATING_GROUP_TYPE_MONEY, BZ_AGE_RATING_GROUP_TYPE_SEX, BZ_AGE_RATING_GROUP_TYPE_SOCIAL, BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, } BzAgeRatingGroupType; #define BZ_AGE_RATING_GROUP_TYPE_COUNT (BZ_AGE_RATING_GROUP_TYPE_VIOLENCE + 1) typedef struct { GList *attributes; } BzAgeRatingGroup; typedef void (*AttributeCallback) (const gchar *attribute, AsContentRatingValue value, gpointer user_data); static const struct { const gchar *id; BzAgeRatingGroupType group_type; const gchar *title; const gchar *unknown_description; const gchar *icon_name; const gchar *icon_name_negative; } attribute_details[] = { { "violence-cartoon", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Cartoon Violence"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding cartoon violence"), "violence-symbolic", "violence-none-symbolic" }, { "violence-fantasy", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Fantasy Violence"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding fantasy violence"), "violence-symbolic", "violence-none-symbolic" }, { "violence-realistic", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Realistic Violence"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding realistic violence"), "violence-symbolic", "violence-none-symbolic" }, { "violence-bloodshed", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Violence Depicting Bloodshed"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding bloodshed"), "violence-symbolic", "violence-none-symbolic" }, { "violence-sexual", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Sexual Violence"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding sexual violence"), "violence-symbolic", "violence-none-symbolic" }, { "drugs-alcohol", BZ_AGE_RATING_GROUP_TYPE_DRUGS, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Alcohol"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to alcohol"), "alcohol-use-symbolic", "alcohol-use-none-symbolic" }, { "drugs-narcotics", BZ_AGE_RATING_GROUP_TYPE_DRUGS, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Narcotics"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to illicit drugs"), "drug-use-symbolic", "drug-use-none-symbolic" }, { "drugs-tobacco", BZ_AGE_RATING_GROUP_TYPE_DRUGS, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Tobacco"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to tobacco products"), "smoking-symbolic", "smoking-none-symbolic" }, { "sex-nudity", BZ_AGE_RATING_GROUP_TYPE_SEX, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Nudity"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding nudity of any sort"), "nudity-symbolic", "nudity-none-symbolic" }, { "sex-themes", BZ_AGE_RATING_GROUP_TYPE_SEX, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Sexual Themes"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to or depictions of sexual nature"), "nudity-symbolic", "nudity-none-symbolic" }, { "language-profanity", BZ_AGE_RATING_GROUP_TYPE_LANGUAGE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Profanity"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding profanity of any kind"), "strong-language-symbolic", "strong-language-none-symbolic" }, { "language-humor", BZ_AGE_RATING_GROUP_TYPE_LANGUAGE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Inappropriate Humor"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding inappropriate humor"), "strong-language-symbolic", "strong-language-none-symbolic" }, { "language-discrimination", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Discrimination"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding discriminatory language of any kind"), "strong-language-symbolic", "strong-language-none-symbolic" }, { "money-advertising", BZ_AGE_RATING_GROUP_TYPE_MONEY, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Advertising"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding advertising of any kind"), "advertising-symbolic", "advertising-none-symbolic" }, { "money-gambling", BZ_AGE_RATING_GROUP_TYPE_MONEY, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Gambling"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding gambling of any kind"), "gambling-symbolic", "gambling-none-symbolic" }, { "money-purchasing", BZ_AGE_RATING_GROUP_TYPE_MONEY, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Purchasing"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding the ability to spend money"), "money-symbolic", "money-none-symbolic" }, { "social-chat", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Chat Between Users"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding ways to chat with other users"), "messaging-symbolic", "messaging-none-symbolic" }, { "social-audio", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Audio Chat Between Users"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding ways to talk with other users"), "audio-chat-symbolic", "audio-chat-none-symbolic" }, { "social-contacts", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Contact Details"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding sharing of social network usernames or email addresses"), "contacts-symbolic", NULL }, { "social-info", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Identifying Information"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding sharing of user information with third parties"), "social-info-symbolic", NULL }, { "social-location", BZ_AGE_RATING_GROUP_TYPE_SOCIAL, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Location Sharing"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding sharing of physical location with other users"), "location-services-active-symbolic", "location-services-disabled-symbolic" }, { "sex-prostitution", BZ_AGE_RATING_GROUP_TYPE_SEX, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Prostitution"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to prostitution"), "nudity-symbolic", "nudity-none-symbolic" }, { "sex-adultery", BZ_AGE_RATING_GROUP_TYPE_SEX, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Adultery"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to adultery"), "nudity-symbolic", "nudity-none-symbolic" }, { "sex-appearance", BZ_AGE_RATING_GROUP_TYPE_SEX, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Sexualized Characters"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding sexualized characters"), "nudity-symbolic", "nudity-none-symbolic" }, { "violence-worship", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Desecration"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to desecration"), "violence-symbolic", "violence-none-symbolic" }, { "violence-desecration", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Human Remains"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding visible dead human remains"), "human-remains-symbolic", NULL }, { "violence-slavery", BZ_AGE_RATING_GROUP_TYPE_VIOLENCE, /* TRANSLATORS: content rating title, see https://hughsie.github.io/oars/ */ N_ ("Slavery"), /* TRANSLATORS: content rating description, see https://hughsie.github.io/oars/ */ N_ ("No information regarding references to slavery"), "violence-symbolic", "violence-none-symbolic" }, }; static const gchar *content_rating_attribute_get_icon_name (const gchar *attribute, gboolean negative_version); static const gchar *content_rating_attribute_get_title (const gchar *attribute); static const gchar *content_rating_attribute_get_unknown_description (const gchar *attribute); static BzAgeRatingGroupType content_rating_attribute_get_group_type (const gchar *attribute); static const gchar *content_rating_group_get_description (BzAgeRatingGroupType group_type); static const gchar *content_rating_group_get_icon_name (BzAgeRatingGroupType group_type, gboolean negative_version); static const gchar *content_rating_group_get_title (BzAgeRatingGroupType group_type); static BzImportance content_rating_value_get_importance (AsContentRatingValue value); static gint attributes_compare (BzAgeRatingAttribute *attr1, BzAgeRatingAttribute *attr2); static void collect_attribute (const gchar *attribute, AsContentRatingValue value, gpointer user_data); static void process_attributes (AsContentRating *content_rating, gboolean show_worst_only, AttributeCallback callback, gpointer user_data); static gchar *format_age_short (AsContentRatingSystem system, guint age); static void update_lozenge (BzAgeRatingDialog *self, AsContentRating *content_rating); static void update_list (BzAgeRatingDialog *self); static void bz_age_rating_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAgeRatingDialog *self = NULL; self = BZ_AGE_RATING_DIALOG (object); switch (prop_id) { case PROP_ENTRY: self->entry = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_age_rating_dialog_constructed (GObject *object) { BzAgeRatingDialog *self = NULL; self = BZ_AGE_RATING_DIALOG (object); G_OBJECT_CLASS (bz_age_rating_dialog_parent_class)->constructed (object); if (self->entry != NULL) update_list (self); } static void bz_age_rating_dialog_dispose (GObject *object) { BzAgeRatingDialog *self = NULL; self = BZ_AGE_RATING_DIALOG (object); g_clear_object (&self->entry); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_AGE_RATING_DIALOG); G_OBJECT_CLASS (bz_age_rating_dialog_parent_class)->dispose (object); } static void bz_age_rating_dialog_class_init (BzAgeRatingDialogClass *klass) { GObjectClass *object_class = NULL; GtkWidgetClass *widget_class = NULL; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_age_rating_dialog_set_property; object_class->constructed = bz_age_rating_dialog_constructed; object_class->dispose = bz_age_rating_dialog_dispose; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LOZENGE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-age-rating-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzAgeRatingDialog, lozenge); gtk_widget_class_bind_template_child (widget_class, BzAgeRatingDialog, list); } static void bz_age_rating_dialog_init (BzAgeRatingDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzAgeRatingDialog * bz_age_rating_dialog_new (BzEntry *entry) { return g_object_new (BZ_TYPE_AGE_RATING_DIALOG, "entry", entry, NULL); } static const gchar * content_rating_attribute_get_icon_name (const gchar *attribute, gboolean negative_version) { for (gsize i = 0; i < G_N_ELEMENTS (attribute_details); i++) { if (g_str_equal (attribute, attribute_details[i].id)) { if (negative_version && attribute_details[i].icon_name_negative != NULL) return attribute_details[i].icon_name_negative; return attribute_details[i].icon_name; } } g_assert_not_reached (); } static const gchar * content_rating_attribute_get_title (const gchar *attribute) { for (gsize i = 0; i < G_N_ELEMENTS (attribute_details); i++) { if (g_str_equal (attribute, attribute_details[i].id)) return _ (attribute_details[i].title); } g_assert_not_reached (); } static const gchar * content_rating_attribute_get_unknown_description (const gchar *attribute) { for (gsize i = 0; i < G_N_ELEMENTS (attribute_details); i++) { if (g_str_equal (attribute, attribute_details[i].id)) return _ (attribute_details[i].unknown_description); } g_assert_not_reached (); } static BzAgeRatingGroupType content_rating_attribute_get_group_type (const gchar *attribute) { for (gsize i = 0; i < G_N_ELEMENTS (attribute_details); i++) { if (g_str_equal (attribute, attribute_details[i].id)) return attribute_details[i].group_type; } g_assert_not_reached (); } static const gchar * content_rating_group_get_description (BzAgeRatingGroupType group_type) { switch (group_type) { case BZ_AGE_RATING_GROUP_TYPE_DRUGS: return _ ("Does not include references to drugs"); case BZ_AGE_RATING_GROUP_TYPE_LANGUAGE: return _ ("Does not include swearing, profanity, and other kinds of strong language"); case BZ_AGE_RATING_GROUP_TYPE_MONEY: return _ ("Does not include ads or monetary transactions"); case BZ_AGE_RATING_GROUP_TYPE_SEX: return _ ("Does not include sex or nudity"); case BZ_AGE_RATING_GROUP_TYPE_SOCIAL: return _ ("Does not include uncontrolled chat functionality"); case BZ_AGE_RATING_GROUP_TYPE_VIOLENCE: return _ ("Does not include violence"); default: g_assert_not_reached (); } } static const gchar * content_rating_group_get_icon_name (BzAgeRatingGroupType group_type, gboolean negative_version) { switch (group_type) { case BZ_AGE_RATING_GROUP_TYPE_DRUGS: return negative_version ? "smoking-none-symbolic" : "smoking-symbolic"; case BZ_AGE_RATING_GROUP_TYPE_LANGUAGE: return negative_version ? "strong-language-none-symbolic" : "strong-language-symbolic"; case BZ_AGE_RATING_GROUP_TYPE_MONEY: return negative_version ? "money-none-symbolic" : "money-symbolic"; case BZ_AGE_RATING_GROUP_TYPE_SEX: return negative_version ? "nudity-none-symbolic" : "nudity-symbolic"; case BZ_AGE_RATING_GROUP_TYPE_SOCIAL: return negative_version ? "messaging-none-symbolic" : "messaging-symbolic"; case BZ_AGE_RATING_GROUP_TYPE_VIOLENCE: return negative_version ? "violence-none-symbolic" : "violence-symbolic"; default: g_assert_not_reached (); } } static const gchar * content_rating_group_get_title (BzAgeRatingGroupType group_type) { switch (group_type) { case BZ_AGE_RATING_GROUP_TYPE_DRUGS: return _ ("Drugs"); case BZ_AGE_RATING_GROUP_TYPE_LANGUAGE: return _ ("Strong Language"); case BZ_AGE_RATING_GROUP_TYPE_MONEY: return _ ("Money"); case BZ_AGE_RATING_GROUP_TYPE_SEX: return _ ("Nudity"); case BZ_AGE_RATING_GROUP_TYPE_SOCIAL: return _ ("Social"); case BZ_AGE_RATING_GROUP_TYPE_VIOLENCE: return _ ("Violence"); default: g_assert_not_reached (); } } static BzImportance content_rating_value_get_importance (AsContentRatingValue value) { switch (value) { case AS_CONTENT_RATING_VALUE_NONE: return BZ_IMPORTANCE_UNIMPORTANT; case AS_CONTENT_RATING_VALUE_UNKNOWN: return BZ_IMPORTANCE_NEUTRAL; case AS_CONTENT_RATING_VALUE_MILD: return BZ_IMPORTANCE_INFORMATION; case AS_CONTENT_RATING_VALUE_MODERATE: return BZ_IMPORTANCE_WARNING; case AS_CONTENT_RATING_VALUE_INTENSE: return BZ_IMPORTANCE_IMPORTANT; case AS_CONTENT_RATING_VALUE_LAST: default: return BZ_IMPORTANCE_NEUTRAL; } } static gint attributes_compare (BzAgeRatingAttribute *attr1, BzAgeRatingAttribute *attr2) { BzImportance importance1 = 0; BzImportance importance2 = 0; const gchar *id1 = NULL; const gchar *id2 = NULL; importance1 = bz_age_rating_attribute_get_importance (attr1); importance2 = bz_age_rating_attribute_get_importance (attr2); if (importance1 != importance2) { if (importance1 == BZ_IMPORTANCE_NEUTRAL && importance2 == BZ_IMPORTANCE_UNIMPORTANT) return -1; if (importance1 == BZ_IMPORTANCE_UNIMPORTANT && importance2 == BZ_IMPORTANCE_NEUTRAL) return 1; return importance2 - importance1; } else { id1 = bz_age_rating_attribute_get_id (attr1); id2 = bz_age_rating_attribute_get_id (attr2); return g_strcmp0 (id1, id2); } } static void collect_attribute (const gchar *attribute, AsContentRatingValue value, gpointer user_data) { BzAgeRatingGroup *groups = NULL; BzAgeRatingGroupType group_type = 0; BzImportance rating = 0; const gchar *icon_name = NULL; const gchar *title = NULL; const gchar *description = NULL; BzAgeRatingAttribute *attr = NULL; groups = user_data; group_type = content_rating_attribute_get_group_type (attribute); rating = content_rating_value_get_importance (value); icon_name = content_rating_attribute_get_icon_name (attribute, value == AS_CONTENT_RATING_VALUE_NONE); title = content_rating_attribute_get_title (attribute); if (value == AS_CONTENT_RATING_VALUE_UNKNOWN) description = content_rating_attribute_get_unknown_description (attribute); else description = as_content_rating_attribute_get_description (attribute, value); attr = g_object_new (BZ_TYPE_AGE_RATING_ATTRIBUTE, "id", attribute, "icon-name", icon_name, "importance", rating, "title", title, "description", description, NULL); groups[group_type].attributes = g_list_insert_sorted (groups[group_type].attributes, attr, (GCompareFunc) attributes_compare); } static void process_attributes (AsContentRating *content_rating, gboolean show_worst_only, AttributeCallback callback, gpointer user_data) { g_autofree const gchar **rating_ids = NULL; AsContentRatingValue value_bad = AS_CONTENT_RATING_VALUE_NONE; guint age_bad = 0; guint rating_age = 0; AsContentRatingValue rating_value = 0; const gchar *const violence_group[] = { "violence-bloodshed", "violence-realistic", "violence-fantasy", "violence-cartoon", NULL }; const gchar *const social_group[] = { "social-audio", "social-chat", "social-contacts", "social-info", NULL }; const gchar *const coalesce_groups[] = { "sex-themes", "sex-homosexuality", NULL }; rating_ids = as_content_rating_get_all_rating_ids (); for (gsize i = 0; rating_ids[i] != NULL; i++) { rating_value = as_content_rating_get_value (content_rating, rating_ids[i]); rating_age = as_content_rating_attribute_to_csm_age (rating_ids[i], rating_value); if (rating_age > age_bad) age_bad = rating_age; if (rating_value > value_bad) value_bad = rating_value; } if (show_worst_only && (value_bad == AS_CONTENT_RATING_VALUE_NONE || age_bad == 0)) { callback (NULL, AS_CONTENT_RATING_VALUE_UNKNOWN, user_data); return; } for (gsize i = 0; rating_ids[i] != NULL; i++) { if (g_strv_contains (violence_group, rating_ids[i]) || g_strv_contains (social_group, rating_ids[i])) continue; rating_value = as_content_rating_get_value (content_rating, rating_ids[i]); rating_age = as_content_rating_attribute_to_csm_age (rating_ids[i], rating_value); if (show_worst_only && rating_age < age_bad) continue; if (g_strv_contains (coalesce_groups + 1, rating_ids[i]) && as_content_rating_attribute_to_csm_age (coalesce_groups[0], as_content_rating_get_value (content_rating, coalesce_groups[0])) >= rating_age) continue; callback (rating_ids[i], rating_value, user_data); } for (gsize i = 0; violence_group[i] != NULL; i++) { rating_value = as_content_rating_get_value (content_rating, violence_group[i]); rating_age = as_content_rating_attribute_to_csm_age (violence_group[i], rating_value); if (show_worst_only && rating_age < age_bad) continue; callback (violence_group[i], rating_value, user_data); } for (gsize i = 0; social_group[i] != NULL; i++) { rating_value = as_content_rating_get_value (content_rating, social_group[i]); rating_age = as_content_rating_attribute_to_csm_age (social_group[i], rating_value); if (show_worst_only && rating_age < age_bad) continue; callback (social_group[i], rating_value, user_data); } } static gchar * format_age_short (AsContentRatingSystem system, guint age) { if (age < 3) age = 3; /* Translators: Age rating format, e.g. "12+" for ages 12 and up */ return g_strdup_printf (_ ("%d+"), age); } static void update_lozenge (BzAgeRatingDialog *self, AsContentRating *content_rating) { const gchar *locale = NULL; AsContentRatingSystem system = 0; guint age = G_MAXUINT; g_autofree gchar *age_text = NULL; g_autofree gchar *title_text = NULL; BzImportance importance = BZ_IMPORTANCE_NEUTRAL; gboolean is_unknown = FALSE; locale = setlocale (LC_MESSAGES, NULL); system = as_content_rating_system_from_locale (locale); if (content_rating != NULL) age = as_content_rating_get_minimum_age (content_rating); if (age != G_MAXUINT) age_text = format_age_short (system, age); if (content_rating != NULL && age_text == NULL && age == 0) age_text = g_strdup (C_ ("Age rating", "All")); if (age_text == NULL || (content_rating != NULL && g_strcmp0 (as_content_rating_get_kind (content_rating), "oars-1.0") != 0 && g_strcmp0 (as_content_rating_get_kind (content_rating), "oars-1.1") != 0)) { g_clear_pointer (&age_text, g_free); age_text = g_strdup ("?"); importance = BZ_IMPORTANCE_NEUTRAL; } else { if (age >= 18) importance = BZ_IMPORTANCE_IMPORTANT; else if (age >= 15) importance = BZ_IMPORTANCE_WARNING; else if (age >= 12) importance = BZ_IMPORTANCE_INFORMATION; else importance = BZ_IMPORTANCE_NEUTRAL; } if (self->entry == NULL) { title_text = g_strdup (_ ("Age Rating")); } else { is_unknown = (content_rating == NULL || (g_strcmp0 (as_content_rating_get_kind (content_rating), "oars-1.0") != 0 && g_strcmp0 (as_content_rating_get_kind (content_rating), "oars-1.1") != 0) || age == G_MAXUINT); if (is_unknown) { title_text = g_strdup_printf (_ ("%s has an unknown age rating"), bz_entry_get_title (self->entry)); } else { if (age <= 3) title_text = g_strdup_printf (_ ("%s is suitable for everyone"), bz_entry_get_title (self->entry)); else if (age <= 5) title_text = g_strdup_printf (_ ("%s is suitable for young children"), bz_entry_get_title (self->entry)); else if (age <= 12) title_text = g_strdup_printf (_ ("%s is suitable for children"), bz_entry_get_title (self->entry)); else if (age <= 18) title_text = g_strdup_printf (_ ("%s is suitable for teenagers"), bz_entry_get_title (self->entry)); else if (age < G_MAXUINT) title_text = g_strdup_printf (_ ("%s is suitable for adults"), bz_entry_get_title (self->entry)); else title_text = g_strdup_printf (_ ("%s is suitable for %s"), bz_entry_get_title (self->entry), age_text); } } bz_lozenge_set_label (self->lozenge, age_text); bz_lozenge_set_title (self->lozenge, title_text); bz_lozenge_set_importance (self->lozenge, importance); } static void update_list (BzAgeRatingDialog *self) { AsContentRating *content_rating = NULL; BzAgeRatingGroup groups[BZ_AGE_RATING_GROUP_TYPE_COUNT] = { 0 }; guint attr_count = 0; BzAgeRatingAttribute *attr = NULL; AdwActionRow *row = NULL; BzImportance max_importance = 0; BzImportance attr_importance = 0; BzImportance row_importances[BZ_AGE_RATING_GROUP_TYPE_COUNT] = { 0 }; GtkWidget *rows[BZ_AGE_RATING_GROUP_TYPE_COUNT] = { NULL }; const gchar *group_icon = NULL; const gchar *group_title = NULL; const gchar *group_description = NULL; const gchar *attr_description = NULL; g_autofree gchar *description = NULL; g_autoptr (GList) l = NULL; g_autofree gchar *tmp = NULL; content_rating = bz_entry_get_content_rating (self->entry); update_lozenge (self, content_rating); process_attributes (content_rating, FALSE, collect_attribute, groups); for (gsize i = 0; i < BZ_AGE_RATING_GROUP_TYPE_COUNT; i++) { if (groups[i].attributes == NULL) continue; attr_count = g_list_length (groups[i].attributes); row = NULL; if (attr_count == 1) { attr = (BzAgeRatingAttribute *) groups[i].attributes->data; row = bz_context_row_new (bz_age_rating_attribute_get_icon_name (attr), bz_age_rating_attribute_get_importance (attr), bz_age_rating_attribute_get_title (attr), bz_age_rating_attribute_get_description (attr)); row_importances[i] = bz_age_rating_attribute_get_importance (attr); } else { max_importance = BZ_IMPORTANCE_UNIMPORTANT; for (l = groups[i].attributes; l != NULL; l = l->next) { attr = (BzAgeRatingAttribute *) l->data; attr_importance = bz_age_rating_attribute_get_importance (attr); if (attr_importance > max_importance) max_importance = attr_importance; } if (max_importance == BZ_IMPORTANCE_UNIMPORTANT) { group_icon = content_rating_group_get_icon_name (i, TRUE); group_title = content_rating_group_get_title (i); group_description = content_rating_group_get_description (i); row = bz_context_row_new (group_icon, BZ_IMPORTANCE_UNIMPORTANT, group_title, group_description); } else { group_icon = content_rating_group_get_icon_name (i, FALSE); group_title = content_rating_group_get_title (i); g_clear_pointer (&description, g_free); for (l = groups[i].attributes; l != NULL; l = l->next) { attr = (BzAgeRatingAttribute *) l->data; attr_importance = bz_age_rating_attribute_get_importance (attr); if (attr_importance == BZ_IMPORTANCE_UNIMPORTANT) continue; attr_description = bz_age_rating_attribute_get_description (attr); if (description == NULL) { description = g_strdup (attr_description); } else { tmp = g_strdup_printf (_ ("%s • %s"), description, attr_description); g_clear_pointer (&description, g_free); description = g_steal_pointer (&tmp); } } row = bz_context_row_new (group_icon, max_importance, group_title, description); } row_importances[i] = max_importance; } rows[i] = GTK_WIDGET (row); g_list_free_full (g_steal_pointer (&groups[i].attributes), g_object_unref); } for (gint level = BZ_IMPORTANCE_IMPORTANT; level >= BZ_IMPORTANCE_UNIMPORTANT; level--) { for (gsize i = 0; i < BZ_AGE_RATING_GROUP_TYPE_COUNT; i++) { if (rows[i] == NULL || row_importances[i] != level) continue; gtk_list_box_append (self->list, rows[i]); } } } kolunmi-bazaar-7b9c8e1/src/bz-age-rating-dialog.h000066400000000000000000000023571514314607700217150ustar00rootroot00000000000000/* bz-age-rating-dialog.h * * Copyright 2021 Endless OS Foundation LLC * Copyright 2025 Alexander Vanhee * * Author: Philip Withnall (GNOME Software) * Adapted for Bazaar by Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include #include G_BEGIN_DECLS #define BZ_TYPE_AGE_RATING_DIALOG (bz_age_rating_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzAgeRatingDialog, bz_age_rating_dialog, BZ, AGE_RATING_DIALOG, AdwDialog) BzAgeRatingDialog *bz_age_rating_dialog_new (BzEntry *entry); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-all-apps-page.blp000066400000000000000000000056351514314607700214150ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAllAppsPage: Adw.NavigationPage { Adw.ToolbarView { [top] Adw.HeaderBar { [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: menu { section { item { label: _("_Donate to Bazaar ❤️"); action: "app.donate"; } } section { item { label: _("_Preferences"); action: "app.preferences"; } item { label: _("_Login with Flathub"); action: "app.flathub-login"; hidden-when: "action-disabled"; } item { label: _("_Manage Leftover User Data"); action: "window.user-data"; } item { label: _("_Synchronize Remotes"); action: "app.sync-remotes"; } item { label: _("_Keyboard Shortcuts"); action: "app.shortcuts"; } item { label: _("_About Bazaar"); action: "app.about"; } } section { item { label: _("_Quit Bazaar"); action: "app.quit"; } } }; } } content: Adw.BreakpointBin { width-request: 360; height-request: 450; child: ScrolledWindow { hexpand: true; vexpand: true; hscrollbar-policy: never; child: Adw.ClampScrollable clamp_scrollable { maximum-size: 1500; tightening-threshold: 1400; child: GridView grid_view { styles [ "search-grid", ] min-columns: 4; max-columns: 4; margin-start: 30; margin-end: 30; enable-rubberband: false; single-click-activate: true; factory: BuilderListItemFactory { template ListItem { child: $BzAppTile { group: bind template.item as <$BzEntryGroup>; clicked => $tile_clicked_cb(template); }; } }; }; }; }; Adw.Breakpoint { condition ("max-width: 1300px") setters { grid_view.min-columns: 3; grid_view.max-columns: 3; } } Adw.Breakpoint { condition ("max-width: 900px") setters { grid_view.min-columns: 2; grid_view.max-columns: 2; } } Adw.Breakpoint { condition ("max-width: 700px") setters { grid_view.margin-start: 3; grid_view.margin-end: 3; grid_view.min-columns: 1; grid_view.max-columns: 1; } } }; } } kolunmi-bazaar-7b9c8e1/src/bz-all-apps-page.c000066400000000000000000000126111514314607700210520ustar00rootroot00000000000000/* bz-all-apps-page.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-all-apps-page.h" #include "bz-app-tile.h" #include "bz-entry-group.h" struct _BzAllAppsPage { AdwNavigationPage parent_instance; char *title; GListModel *applications; GtkGridView *grid_view; }; G_DEFINE_FINAL_TYPE (BzAllAppsPage, bz_all_apps_page, ADW_TYPE_NAVIGATION_PAGE) enum { PROP_0, PROP_PAGE_TITLE, PROP_APPLICATIONS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SELECT, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void tile_clicked_cb (GtkListItem *list_item, BzAppTile *tile); static void bz_all_apps_page_dispose (GObject *object) { BzAllAppsPage *self = BZ_ALL_APPS_PAGE (object); g_clear_pointer (&self->title, g_free); g_clear_object (&self->applications); G_OBJECT_CLASS (bz_all_apps_page_parent_class)->dispose (object); } static void bz_all_apps_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAllAppsPage *self = BZ_ALL_APPS_PAGE (object); switch (prop_id) { case PROP_PAGE_TITLE: g_value_set_string (value, self->title); break; case PROP_APPLICATIONS: g_value_set_object (value, self->applications); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_all_apps_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAllAppsPage *self = BZ_ALL_APPS_PAGE (object); switch (prop_id) { case PROP_PAGE_TITLE: g_clear_pointer (&self->title, g_free); self->title = g_value_dup_string (value); break; case PROP_APPLICATIONS: g_clear_object (&self->applications); self->applications = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_all_apps_page_class_init (BzAllAppsPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_all_apps_page_dispose; object_class->get_property = bz_all_apps_page_get_property; object_class->set_property = bz_all_apps_page_set_property; props[PROP_PAGE_TITLE] = g_param_spec_string ( "page-title", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_APPLICATIONS] = g_param_spec_object ( "applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SELECT] = g_signal_new ( "select", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_type_ensure (BZ_TYPE_APP_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-all-apps-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzAllAppsPage, grid_view); gtk_widget_class_bind_template_callback (widget_class, tile_clicked_cb); } static void bz_all_apps_page_init (BzAllAppsPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwNavigationPage * bz_all_apps_page_new (const char *title, GListModel *applications) { BzAllAppsPage *apps_page = NULL; GtkSelectionModel *selection_model = NULL; apps_page = g_object_new ( BZ_TYPE_ALL_APPS_PAGE, "page-title", title, "applications", applications, NULL); adw_navigation_page_set_title (ADW_NAVIGATION_PAGE (apps_page), title); selection_model = GTK_SELECTION_MODEL (gtk_no_selection_new (applications)); gtk_grid_view_set_model (apps_page->grid_view, selection_model); g_object_unref (selection_model); return ADW_NAVIGATION_PAGE (apps_page); } static void tile_clicked_cb (GtkListItem *list_item, BzAppTile *tile) { BzAllAppsPage *self = NULL; BzEntryGroup *group = NULL; g_assert (GTK_IS_LIST_ITEM (list_item)); g_assert (BZ_IS_APP_TILE (tile)); self = BZ_ALL_APPS_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_ALL_APPS_PAGE)); group = gtk_list_item_get_item (list_item); if (group == NULL) return; g_signal_emit (self, signals[SIGNAL_SELECT], 0, group); } kolunmi-bazaar-7b9c8e1/src/bz-all-apps-page.h000066400000000000000000000021051514314607700210540ustar00rootroot00000000000000/* bz-all-apps-page.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_ALL_APPS_PAGE (bz_all_apps_page_get_type ()) G_DECLARE_FINAL_TYPE (BzAllAppsPage, bz_all_apps_page, BZ, ALL_APPS_PAGE, AdwNavigationPage) AdwNavigationPage * bz_all_apps_page_new (const char *title, GListModel *applications); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-animation.c000066400000000000000000000376721514314607700204240ustar00rootroot00000000000000/* bz-animation.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ /* This animation implementation was originally from my other project, libpastry: https://github.com/kolunmi/libpastry */ /** * BzAnimation: * * Manages animations for a widget. Individual value animations are tracked in a * hash map with string keys, allowing them to be easily restarted or replaced. */ #define G_LOG_DOMAIN "BZ::ANIMATION" #define DELTA 0.001 #define EPSILON 0.00001 #include "config.h" #include "bz-animation.h" enum { PROP_0, PROP_WIDGET, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; struct _BzAnimation { GObject parent_instance; GtkWidget *widget; GWeakRef wr; guint tag; GHashTable *data; }; G_DEFINE_FINAL_TYPE (BzAnimation, bz_animation, G_TYPE_OBJECT) typedef struct { double from; double to; double damping_ratio; double mass; double stiffness; gboolean clamp; BzAnimationCallback cb; gpointer user_data; GDestroyNotify destroy_data; double est_duration; GTimer *timer; double velocity; } SpringData; static gboolean tick_cb (GtkWidget *widget, GdkFrameClock *frame_clock, GWeakRef *wr); /* Copied with modifications from libadwaita */ static double oscillate (SpringData *data, double time, double *velocity); /* Copied with modifications from libadwaita */ static double get_first_zero (SpringData *data); /* Copied with modifications from libadwaita */ static double calculate_duration (SpringData *data); static void destroy_spring_data (gpointer ptr); static void destroy_wr (gpointer ptr); static gboolean should_animate (GtkWidget *widget); static void dispose (GObject *object) { BzAnimation *self = BZ_ANIMATION (object); g_autoptr (GtkWidget) widget = NULL; widget = g_weak_ref_get (&self->wr); if (widget != NULL) { gtk_widget_remove_tick_callback (widget, self->tag); self->tag = 0; } g_clear_object (&widget); g_weak_ref_clear (&self->wr); g_clear_object (&self->widget); g_clear_pointer (&self->data, g_hash_table_unref); G_OBJECT_CLASS (bz_animation_parent_class)->dispose (object); } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAnimation *self = BZ_ANIMATION (object); switch (prop_id) { case PROP_WIDGET: g_value_take_object (value, bz_animation_dup_widget (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAnimation *self = BZ_ANIMATION (object); switch (prop_id) { case PROP_WIDGET: g_clear_object (&self->widget); self->widget = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void constructed (GObject *object) { BzAnimation *self = BZ_ANIMATION (object); if (GTK_IS_WIDGET (self->widget)) { GWeakRef *wr = NULL; wr = g_new0 (typeof (*wr), 1); g_weak_ref_init (wr, self); self->tag = gtk_widget_add_tick_callback ( self->widget, (GtkTickCallback) tick_cb, wr, destroy_wr); } g_weak_ref_init (&self->wr, self->widget); g_clear_object (&self->widget); } static void bz_animation_class_init (BzAnimationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = constructed; object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; /** * BzAnimation:widget: * * The widget on which this animation is attached. */ props[PROP_WIDGET] = g_param_spec_object ( "widget", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_animation_init (BzAnimation *self) { g_weak_ref_init (&self->wr, NULL); self->data = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, destroy_spring_data); } /** * bz_animation_new: * @widget: The widget onto which to attach the tick callback * * Creates a new `BzAnimation` object. * * Returns: The newly created `BzAnimation` object. */ BzAnimation * bz_animation_new (GtkWidget *widget) { g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); return g_object_new ( BZ_TYPE_ANIMATION, "widget", widget, NULL); } /** * bz_animation_dup_widget: * @self: a `BzAnimation` * * Gets the widget on which @self is attached. * * Returns: (nullable) (transfer full): the widget for @self */ GtkWidget * bz_animation_dup_widget (BzAnimation *self) { g_return_val_if_fail (BZ_IS_ANIMATION (self), NULL); return g_weak_ref_get (&self->wr); } /** * bz_animation_add_spring: * @self: a `BzAnimation` * @key: a string ID to replace * @from: the start value * @to: the end value * @damping_ratio: the damping ratio * @mass: the mass * @stiffness: the stiffness * @cb: a tick callback * @user_data: the user data pointer to be passed to @cb * @destroy_data: the destruction function for @user_data * * Adds a one shot spring animation to @self. If @key is already running in * @self, then the old animation is replaced, maintaining the current velocity. */ void bz_animation_add_spring (BzAnimation *self, const char *key, double from, double to, double damping_ratio, double mass, double stiffness, BzAnimationCallback cb, gpointer user_data, GDestroyNotify destroy_data) { g_autoptr (GtkWidget) widget = NULL; g_return_if_fail (BZ_IS_ANIMATION (self)); g_return_if_fail (key != NULL); g_return_if_fail (cb != NULL); widget = g_weak_ref_get (&self->wr); if (widget != NULL) { if (should_animate (widget)) { SpringData *data = NULL; /* reuse old data if possible */ data = g_hash_table_lookup (self->data, key); if (data != NULL) { if (data->user_data != NULL && data->destroy_data != NULL) /* we are going to overwrite this */ data->destroy_data (data->user_data); g_clear_pointer (&data->timer, g_timer_destroy); /* old velocity is retained */ } else { data = g_new0 (typeof (*data), 1); g_hash_table_replace (self->data, g_strdup (key), data); } data->from = from; data->to = to; data->damping_ratio = damping_ratio; data->mass = mass; data->stiffness = stiffness; data->cb = cb; data->user_data = user_data; data->destroy_data = destroy_data; /* We'll fill this in on the first iteration */ data->timer = NULL; data->est_duration = calculate_duration (data); cb (widget, key, from, user_data); } else /* If we shouldn't animate, just invoke the callback at the final value */ { cb (widget, key, to, user_data); if (user_data != NULL && destroy_data != NULL) destroy_data (user_data); } } else if (user_data != NULL && destroy_data != NULL) destroy_data (user_data); } static gboolean tick_cb (GtkWidget *widget, GdkFrameClock *frame_clock, GWeakRef *wr) { g_autoptr (BzAnimation) self = NULL; gboolean cancel = FALSE; GHashTableIter iter = { 0 }; self = g_weak_ref_get (wr); if (self == NULL) return G_SOURCE_REMOVE; cancel = !should_animate (widget); g_hash_table_iter_init (&iter, self->data); for (;;) { char *key = NULL; SpringData *data = NULL; double value = 0.0; gboolean finished = FALSE; if (!g_hash_table_iter_next ( &iter, (gpointer *) &key, (gpointer *) &data)) break; if (cancel) finished = TRUE; else { double elapsed = 0.0; if (data->timer == NULL) { data->timer = g_timer_new (); value = data->from; } else { elapsed = g_timer_elapsed (data->timer, NULL); value = oscillate (data, elapsed, &data->velocity); } finished = elapsed > data->est_duration || (data->damping_ratio >= 1.0 && (G_APPROX_VALUE (value, data->to, EPSILON) || (data->from > data->to && value < data->to) || (data->from < data->to && value > data->to))); } if (finished) value = data->to; data->cb (widget, key, value, data->user_data); if (finished) g_hash_table_iter_remove (&iter); } return G_SOURCE_CONTINUE; } /* COPIED FROM LIBADWAITA */ /* Based on RBBSpringAnimation from RBBAnimation, MIT license. * https://github.com/robb/RBBAnimation/blob/master/RBBAnimation/RBBSpringAnimation.m * * @offset: Starting value of the spring simulation. Use -1 for regular animations, * as the formulas are tailored to rest at 0 and the resulting evolution between * -1 and 0 will be lerped to the desired range afterwards. Otherwise use 0 for in-place * animations which already start at equilibrium */ static double oscillate (SpringData *data, double time, double *velocity) { double t = time * 100.0; // ? double b = data->damping_ratio; double m = data->mass; double k = data->stiffness; double v0 = 0.0; double beta = 0.0; double omega0 = 0.0; double x0 = 0.0; double envelope = 0.0; beta = b / (2 * m); omega0 = sqrt (k / m); x0 = data->from - data->to; envelope = exp (-beta * t); /* * Solutions of the form C1*e^(lambda1*x) + C2*e^(lambda2*x) * for the differential equation m*ẍ+b*ẋ+kx = 0 */ /* Critically damped */ /* DBL_EPSILON is too small for this specific comparison, so we use * FLT_EPSILON even though it's doubles */ if (G_APPROX_VALUE (beta, omega0, FLT_EPSILON)) { if (velocity != NULL) *velocity = envelope * (-beta * t * v0 - beta * beta * t * x0 + v0); return data->to + envelope * (x0 + (beta * x0 + v0) * t); } /* Underdamped */ if (beta < omega0) { double omega1 = 0.0; omega1 = sqrt ((omega0 * omega0) - (beta * beta)); if (velocity != NULL) *velocity = envelope * (v0 * cos (omega1 * t) - (x0 * omega1 + (beta * beta * x0 + beta * v0) / (omega1)) * sin (omega1 * t)); return data->to + envelope * (x0 * cos (omega1 * t) + ((beta * x0 + v0) / omega1) * sin (omega1 * t)); } /* Overdamped */ if (beta > omega0) { double omega2 = 0.0; omega2 = sqrt ((beta * beta) - (omega0 * omega0)); if (velocity != NULL) *velocity = envelope * (v0 * coshl (omega2 * t) + (omega2 * x0 - (beta * beta * x0 + beta * v0) / omega2) * sinhl (omega2 * t)); return data->to + envelope * (x0 * coshl (omega2 * t) + ((beta * x0 + v0) / omega2) * sinhl (omega2 * t)); } g_assert_not_reached (); } static double get_first_zero (SpringData *data) { /* The first frame is not that important and we avoid finding the trivial 0 * for in-place animations. */ double i = 0.0; double y = 0.0; i = 0.001; y = oscillate (data, i, NULL); while ((data->to - data->from > DBL_EPSILON && data->to - y > EPSILON) || (data->from - data->to > DBL_EPSILON && y - data->to > EPSILON)) { if (i > 2.0) return 0.0; i += 0.001; y = oscillate (data, i, NULL); } return i; } static double calculate_duration (SpringData *data) { double beta = 0.0; double omega0 = 0.0; double x0 = 0.0; double y0 = 0.0; double x1 = 0.0; double y1 = 0.0; double m = 0.0; double i = 0.0; beta = data->damping_ratio / (2 * data->mass); if (G_APPROX_VALUE (beta, 0, DBL_EPSILON) || beta < 0) return G_MAXDOUBLE; if (data->clamp) { if (G_APPROX_VALUE (data->to, data->from, DBL_EPSILON)) return 0; return get_first_zero (data); } omega0 = sqrt (data->stiffness / data->mass); /* * As first ansatz for the overdamped solution, * and general estimation for the oscillating ones * we take the value of the envelope when it's < epsilon */ x0 = -log (EPSILON) / beta; /* DBL_EPSILON is too small for this specific comparison, so we use * FLT_EPSILON even though it's doubles */ if (G_APPROX_VALUE (beta, omega0, FLT_EPSILON) || beta < omega0) return x0; /* * Since the overdamped solution decays way slower than the envelope * we need to use the value of the oscillation itself. * Newton's root finding method is a good candidate in this particular case: * https://en.wikipedia.org/wiki/Newton%27s_method */ y0 = oscillate (data, x0, NULL); m = (oscillate (data, (x0 + DELTA), NULL) - y0) / DELTA; x1 = (data->to - y0 + m * x0) / m; y1 = oscillate (data, x1, NULL); while (ABS (data->to - y1) > EPSILON) { if (i > 1.0) return 0.0; x0 = x1; y0 = y1; m = (oscillate (data, x0 + DELTA, NULL) - y0) / DELTA; x1 = (data->to - y0 + m * x0) / m; y1 = oscillate (data, x1, NULL); i += 0.001; } return x1; } /* ///COPIED FROM LIBADWAITA */ static void destroy_spring_data (gpointer ptr) { SpringData *data = ptr; if (data->destroy_data != NULL && data->user_data != NULL) data->destroy_data (data->user_data); g_clear_pointer (&data->timer, g_timer_destroy); g_free (ptr); } static void destroy_wr (gpointer ptr) { GWeakRef *wr = ptr; g_weak_ref_clear (wr); g_free (ptr); } static gboolean should_animate (GtkWidget *widget) { GtkSettings *settings = NULL; gboolean enable_animations = FALSE; if (!gtk_widget_get_mapped (widget)) return FALSE; settings = gtk_widget_get_settings (widget); g_object_get ( settings, "gtk-enable-animations", &enable_animations, NULL); return enable_animations; } kolunmi-bazaar-7b9c8e1/src/bz-animation.h000066400000000000000000000034311514314607700204130ustar00rootroot00000000000000/* bz-animation.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_ANIMATION (bz_animation_get_type ()) G_DECLARE_FINAL_TYPE (BzAnimation, bz_animation, BZ, ANIMATION, GObject) typedef void (*BzAnimationCallback) (GtkWidget *widget, const char *key, double value, gpointer user_data); BzAnimation * bz_animation_new (GtkWidget *widget); GtkWidget * bz_animation_dup_widget (BzAnimation *self); void bz_animation_add_spring (BzAnimation *self, const char *key, double from, double to, double damping_ratio, double mass, double stiffness, BzAnimationCallback cb, gpointer user_data, GDestroyNotify destroy_data); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-app-permissions.c000066400000000000000000001231551514314607700215660ustar00rootroot00000000000000/* bz-app-permissions.c * * Copyright 2026 Alexander Vanhee * Copyright (C) 2022 Red Hat * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include #include #include "bz-app-permissions.h" #define DOES_NOT_CONTAIN ((guint) ~0) G_DEFINE_FLAGS_TYPE ( BzAppPermissionsFlags, bz_app_permissions_flags, G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_NONE, "none"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_NETWORK, "network"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS, "system-bus"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS, "session-bus"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_DEVICES, "devices"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_HOME_FULL, "home-full"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_HOME_READ, "home-read"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL, "filesystem-full"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ, "filesystem-read"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL, "downloads-full"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ, "downloads-read"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_SETTINGS, "settings"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_X11, "x11"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX, "escape-sandbox"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER, "filesystem-other"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_BUS_POLICY_OTHER, "bus-policy-other"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES, "audio-devices"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_INPUT_DEVICES, "input-devices"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_SYSTEM_DEVICES, "system-devices"), G_DEFINE_ENUM_VALUE (BZ_APP_PERMISSIONS_FLAGS_SCREEN, "screen")) G_DEFINE_ENUM_TYPE ( BzFilesystemPathType, bz_filesystem_path_type, G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_SYSTEM_ROOT, "system-root"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_HOME_SUBDIR, "home-subdir"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_HOST_OS, "host-os"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_HOST_ETC, "host-etc"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_DESKTOP, "xdg-desktop"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_DOCUMENTS, "xdg-documents"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_MUSIC, "xdg-music"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_PICTURES, "xdg-pictures"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_PUBLIC_SHARE, "xdg-public-share"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_VIDEOS, "xdg-videos"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_TEMPLATES, "xdg-templates"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_CACHE, "xdg-cache"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_CONFIG, "xdg-config"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_DATA, "xdg-data"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_XDG_RUN, "xdg-run"), G_DEFINE_ENUM_VALUE (BZ_FILESYSTEM_PATH_CUSTOM, "custom")) G_DEFINE_ENUM_TYPE ( BzBusPolicyPermission, bz_bus_policy_permission, G_DEFINE_ENUM_VALUE (BZ_BUS_POLICY_PERMISSION_UNKNOWN, "unknown"), G_DEFINE_ENUM_VALUE (BZ_BUS_POLICY_PERMISSION_NONE, "none"), G_DEFINE_ENUM_VALUE (BZ_BUS_POLICY_PERMISSION_SEE, "see"), G_DEFINE_ENUM_VALUE (BZ_BUS_POLICY_PERMISSION_TALK, "talk"), G_DEFINE_ENUM_VALUE (BZ_BUS_POLICY_PERMISSION_OWN, "own")) struct _BzAppPermissions { GObject parent; gboolean is_sealed; BzAppPermissionsFlags flags; GPtrArray *filesystem_read; GPtrArray *filesystem_full; GPtrArray *bus_policies; }; G_DEFINE_FINAL_TYPE (BzAppPermissions, bz_app_permissions, G_TYPE_OBJECT) static gint cmp_filesystem_path_pointers (gconstpointer item1, gconstpointer item2); static int cmp_bus_policy_qsort (const void *item1, const void *item2); static guint app_permissions_get_array_index (GPtrArray *array, BzFilesystemPathType type, const char *subpath); static guint get_strv_index (const gchar *const *strv, const gchar *value); static void bz_app_permissions_finalize (GObject *object) { BzAppPermissions *self = BZ_APP_PERMISSIONS (object); g_clear_pointer (&self->filesystem_read, g_ptr_array_unref); g_clear_pointer (&self->filesystem_full, g_ptr_array_unref); g_clear_pointer (&self->bus_policies, g_ptr_array_unref); G_OBJECT_CLASS (bz_app_permissions_parent_class)->finalize (object); } static void bz_app_permissions_class_init (BzAppPermissionsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = bz_app_permissions_finalize; } static void bz_app_permissions_init (BzAppPermissions *self) { } BzFilesystemPath * bz_filesystem_path_new (BzFilesystemPathType type, const char *subpath) { BzFilesystemPath *path = g_new0 (BzFilesystemPath, 1); path->type = type; path->subpath = g_strdup (subpath); return path; } void bz_filesystem_path_free (BzFilesystemPath *path) { g_return_if_fail (path != NULL); g_free (path->subpath); g_free (path); } char * bz_filesystem_path_to_display_string (const BzFilesystemPath *path) { g_return_val_if_fail (path != NULL, NULL); switch (path->type) { case BZ_FILESYSTEM_PATH_SYSTEM_ROOT: return g_strdup_printf (_ ("System folder %s"), path->subpath ? path->subpath : "/"); case BZ_FILESYSTEM_PATH_HOME_SUBDIR: return g_strdup_printf (_ ("Home subfolder %s"), path->subpath); case BZ_FILESYSTEM_PATH_HOST_OS: return g_strdup (_ ("Host system folders")); case BZ_FILESYSTEM_PATH_HOST_ETC: return g_strdup (_ ("Host system configuration from /etc")); case BZ_FILESYSTEM_PATH_XDG_DESKTOP: if (path->subpath) return g_strdup_printf (_ ("Desktop subfolder %s"), path->subpath); return g_strdup (_ ("Desktop folder")); case BZ_FILESYSTEM_PATH_XDG_DOCUMENTS: if (path->subpath) return g_strdup_printf (_ ("Documents subfolder %s"), path->subpath); return g_strdup (_ ("Documents folder")); case BZ_FILESYSTEM_PATH_XDG_MUSIC: if (path->subpath) return g_strdup_printf (_ ("Music subfolder %s"), path->subpath); return g_strdup (_ ("Music folder")); case BZ_FILESYSTEM_PATH_XDG_PICTURES: if (path->subpath) return g_strdup_printf (_ ("Pictures subfolder %s"), path->subpath); return g_strdup (_ ("Pictures folder")); case BZ_FILESYSTEM_PATH_XDG_PUBLIC_SHARE: if (path->subpath) return g_strdup_printf (_ ("Public Share subfolder %s"), path->subpath); return g_strdup (_ ("Public Share folder")); case BZ_FILESYSTEM_PATH_XDG_VIDEOS: if (path->subpath) return g_strdup_printf (_ ("Videos subfolder %s"), path->subpath); return g_strdup (_ ("Videos folder")); case BZ_FILESYSTEM_PATH_XDG_TEMPLATES: if (path->subpath) return g_strdup_printf (_ ("Templates subfolder %s"), path->subpath); return g_strdup (_ ("Templates folder")); case BZ_FILESYSTEM_PATH_XDG_CACHE: if (path->subpath) return g_strdup_printf (_ ("User cache subfolder %s"), path->subpath); return g_strdup (_ ("User cache folder")); case BZ_FILESYSTEM_PATH_XDG_CONFIG: if (path->subpath) return g_strdup_printf (_ ("User configuration subfolder %s"), path->subpath); return g_strdup (_ ("User configuration folder")); case BZ_FILESYSTEM_PATH_XDG_DATA: if (path->subpath) return g_strdup_printf (_ ("User data subfolder %s"), path->subpath); return g_strdup (_ ("User data folder")); case BZ_FILESYSTEM_PATH_XDG_RUN: if (path->subpath) return g_strdup_printf (_ ("User runtime subfolder %s"), path->subpath); return g_strdup (_ ("User runtime folder")); case BZ_FILESYSTEM_PATH_CUSTOM: return g_strdup_printf (_ ("Filesystem access to %s"), path->subpath); default: return g_strdup (_ ("Unknown filesystem path")); } } const char * bz_filesystem_path_to_icon_name (const BzFilesystemPath *path) { switch (path->type) { case BZ_FILESYSTEM_PATH_HOST_OS: return "computer-symbolic"; case BZ_FILESYSTEM_PATH_HOST_ETC: return "emblem-system-symbolic"; case BZ_FILESYSTEM_PATH_XDG_DESKTOP: return "user-desktop-symbolic"; case BZ_FILESYSTEM_PATH_XDG_DOCUMENTS: return "folder-documents-symbolic"; case BZ_FILESYSTEM_PATH_XDG_MUSIC: return "folder-music-symbolic"; case BZ_FILESYSTEM_PATH_XDG_PICTURES: return "folder-pictures-symbolic"; case BZ_FILESYSTEM_PATH_XDG_PUBLIC_SHARE: return "folder-publicshare-symbolic"; case BZ_FILESYSTEM_PATH_XDG_VIDEOS: return "folder-videos-symbolic"; case BZ_FILESYSTEM_PATH_XDG_CONFIG: return "emblem-system-symbolic"; case BZ_FILESYSTEM_PATH_SYSTEM_ROOT: case BZ_FILESYSTEM_PATH_HOME_SUBDIR: case BZ_FILESYSTEM_PATH_XDG_TEMPLATES: case BZ_FILESYSTEM_PATH_XDG_CACHE: case BZ_FILESYSTEM_PATH_XDG_DATA: case BZ_FILESYSTEM_PATH_XDG_RUN: case BZ_FILESYSTEM_PATH_CUSTOM: default: return "folder-symbolic"; } } BzBusPolicy * bz_bus_policy_new (GBusType bus_type, const char *bus_name, BzBusPolicyPermission permission) { BzBusPolicy *policy = NULL; g_return_val_if_fail (bus_type != G_BUS_TYPE_NONE, NULL); g_return_val_if_fail (bus_name != NULL && *bus_name != '\0', NULL); policy = g_new0 (BzBusPolicy, 1); policy->bus_type = bus_type; policy->bus_name = g_strdup (bus_name); policy->permission = permission; return policy; } void bz_bus_policy_free (BzBusPolicy *self) { g_return_if_fail (self != NULL); g_free (self->bus_name); g_free (self); } BzAppPermissions * bz_app_permissions_new (void) { return g_object_new (BZ_TYPE_APP_PERMISSIONS, NULL); } void bz_app_permissions_seal (BzAppPermissions *self) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); if (self->is_sealed) return; self->is_sealed = TRUE; if (self->filesystem_read) qsort (self->filesystem_read->pdata, self->filesystem_read->len, sizeof (gpointer), cmp_filesystem_path_pointers); if (self->filesystem_full) qsort (self->filesystem_full->pdata, self->filesystem_full->len, sizeof (gpointer), cmp_filesystem_path_pointers); if (self->bus_policies) qsort (self->bus_policies->pdata, self->bus_policies->len, sizeof (gpointer), cmp_bus_policy_qsort); } gboolean bz_app_permissions_is_sealed (BzAppPermissions *self) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), TRUE); return self->is_sealed; } gboolean bz_app_permissions_is_empty (BzAppPermissions *self) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), TRUE); return (self->flags == BZ_APP_PERMISSIONS_FLAGS_NONE && (self->filesystem_read == NULL || self->filesystem_read->len == 0) && (self->filesystem_full == NULL || self->filesystem_full->len == 0) && (self->bus_policies == NULL || self->bus_policies->len == 0)); } void bz_app_permissions_set_flags (BzAppPermissions *self, BzAppPermissionsFlags flags) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_assert (!self->is_sealed); self->flags = flags; } BzAppPermissionsFlags bz_app_permissions_get_flags (BzAppPermissions *self) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), BZ_APP_PERMISSIONS_FLAGS_NONE); return self->flags; } void bz_app_permissions_add_flag (BzAppPermissions *self, BzAppPermissionsFlags flags) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_return_if_fail (flags != BZ_APP_PERMISSIONS_FLAGS_NONE); g_assert (!self->is_sealed); self->flags = self->flags | flags; } void bz_app_permissions_remove_flag (BzAppPermissions *self, BzAppPermissionsFlags flags) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_return_if_fail (flags != BZ_APP_PERMISSIONS_FLAGS_NONE); g_assert (!self->is_sealed); self->flags = (self->flags & (~flags)); } void bz_app_permissions_add_filesystem_read (BzAppPermissions *self, BzFilesystemPathType type, const char *subpath) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_assert (!self->is_sealed); if (app_permissions_get_array_index (self->filesystem_read, type, subpath) != DOES_NOT_CONTAIN || app_permissions_get_array_index (self->filesystem_full, type, subpath) != DOES_NOT_CONTAIN) return; if (self->filesystem_read == NULL) self->filesystem_read = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_filesystem_path_free); g_ptr_array_add (self->filesystem_read, bz_filesystem_path_new (type, subpath)); } const GPtrArray * bz_app_permissions_get_filesystem_read (BzAppPermissions *self) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), NULL); return self->filesystem_read; } void bz_app_permissions_add_filesystem_full (BzAppPermissions *self, BzFilesystemPathType type, const char *subpath) { guint read_index = DOES_NOT_CONTAIN; g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_assert (!self->is_sealed); if (app_permissions_get_array_index (self->filesystem_full, type, subpath) != DOES_NOT_CONTAIN) return; if (self->filesystem_full == NULL) self->filesystem_full = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_filesystem_path_free); g_ptr_array_add (self->filesystem_full, bz_filesystem_path_new (type, subpath)); read_index = app_permissions_get_array_index (self->filesystem_read, type, subpath); if (read_index != DOES_NOT_CONTAIN) { g_ptr_array_remove_index (self->filesystem_read, read_index); if (self->filesystem_read->len == 0) g_clear_pointer (&self->filesystem_read, g_ptr_array_unref); } } const GPtrArray * bz_app_permissions_get_filesystem_full (BzAppPermissions *self) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), NULL); return self->filesystem_full; } void bz_app_permissions_add_bus_policy (BzAppPermissions *self, GBusType bus_type, const char *bus_name, BzBusPolicyPermission permission) { g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_return_if_fail (bus_type != G_BUS_TYPE_NONE); g_return_if_fail (bus_name != NULL && *bus_name != '\0'); g_return_if_fail (permission != BZ_BUS_POLICY_PERMISSION_UNKNOWN); g_assert (!self->is_sealed); for (unsigned int i = 0; self->bus_policies != NULL && i < self->bus_policies->len; i++) { BzBusPolicy *policy = g_ptr_array_index (self->bus_policies, i); if (policy->bus_type == bus_type && g_str_equal (policy->bus_name, bus_name)) { policy->permission = MAX (policy->permission, permission); return; } } if (permission == BZ_BUS_POLICY_PERMISSION_NONE) return; if (self->bus_policies == NULL) self->bus_policies = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_bus_policy_free); g_ptr_array_add (self->bus_policies, bz_bus_policy_new (bus_type, bus_name, permission)); } const BzBusPolicy *const * bz_app_permissions_get_bus_policies (BzAppPermissions *self, size_t *out_n_bus_policies) { g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), NULL); g_return_val_if_fail (self->is_sealed, NULL); if (out_n_bus_policies != NULL) *out_n_bus_policies = (self->bus_policies != NULL) ? self->bus_policies->len : 0; return (self->bus_policies != NULL && self->bus_policies->len > 0) ? (const BzBusPolicy *const *) self->bus_policies->pdata : NULL; } BzAppPermissions * bz_app_permissions_new_from_metadata (GKeyFile *keyfile, GError **error) { char **strv = NULL; BzAppPermissions *permissions = NULL; BzAppPermissionsFlags flags = BZ_APP_PERMISSIONS_FLAGS_NONE; g_autofree char *app_id = NULL; g_autofree char *mpris_id = NULL; g_autofree char *app_id_non_devel = NULL; g_autofree char *mpris_id_non_devel = NULL; g_return_val_if_fail (keyfile != NULL, NULL); permissions = bz_app_permissions_new (); app_id = g_key_file_get_value (keyfile, "Application", "name", NULL); strv = g_key_file_get_string_list (keyfile, "Context", "sockets", NULL, NULL); if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "system-bus")) flags |= BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS | BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX; if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "session-bus")) flags |= BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS | BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX; if (strv != NULL && !g_strv_contains ((const gchar *const *) strv, "fallback-x11") && g_strv_contains ((const gchar *const *) strv, "x11")) flags |= BZ_APP_PERMISSIONS_FLAGS_X11; if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "fallback-x11") && !g_strv_contains ((const gchar *const *) strv, "wayland")) flags |= BZ_APP_PERMISSIONS_FLAGS_X11; if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "pulseaudio")) flags |= BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES; if (strv != NULL && g_strv_contains ((const char *const *) strv, "gpg-agent")) flags |= BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX; g_strfreev (strv); strv = g_key_file_get_string_list (keyfile, "Context", "devices", NULL, NULL); if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "all")) flags |= BZ_APP_PERMISSIONS_FLAGS_DEVICES; if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "input")) flags |= BZ_APP_PERMISSIONS_FLAGS_INPUT_DEVICES; if (strv != NULL && (g_strv_contains ((const gchar *const *) strv, "shm") || g_strv_contains ((const gchar *const *) strv, "kvm"))) flags |= BZ_APP_PERMISSIONS_FLAGS_SYSTEM_DEVICES; g_strfreev (strv); strv = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL); if (strv != NULL && g_strv_contains ((const gchar *const *) strv, "network")) flags |= BZ_APP_PERMISSIONS_FLAGS_NETWORK; g_strfreev (strv); strv = g_key_file_get_string_list (keyfile, "Context", "filesystems", NULL, NULL); if (strv != NULL) { const struct { const gchar *key; BzAppPermissionsFlags perm; } filesystems_access[] = { { "home", BZ_APP_PERMISSIONS_FLAGS_HOME_FULL }, { "home:rw", BZ_APP_PERMISSIONS_FLAGS_HOME_FULL }, { "home:ro", BZ_APP_PERMISSIONS_FLAGS_HOME_READ }, { "~", BZ_APP_PERMISSIONS_FLAGS_HOME_FULL }, { "~:rw", BZ_APP_PERMISSIONS_FLAGS_HOME_FULL }, { "~:ro", BZ_APP_PERMISSIONS_FLAGS_HOME_READ }, { "host", BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL }, { "host:rw", BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL }, { "host:ro", BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ }, { "xdg-config/kdeglobals:ro", BZ_APP_PERMISSIONS_FLAGS_NONE }, { "xdg-download", BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL }, { "xdg-download:rw", BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL }, { "xdg-download:ro", BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ }, { "xdg-data/flatpak/overrides:create", BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX }, { "xdg-run/pipewire-0", BZ_APP_PERMISSIONS_FLAGS_SCREEN | BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES }, { "xdg-run/gvfsd", BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL }, }; guint filesystems_hits = 0; guint strv_len = g_strv_length (strv); for (guint i = 0; i < G_N_ELEMENTS (filesystems_access); i++) { guint index = get_strv_index ((const gchar *const *) strv, filesystems_access[i].key); if (index < strv_len) { flags |= filesystems_access[i].perm; filesystems_hits++; strv[index][0] = '\0'; } } if ((flags & BZ_APP_PERMISSIONS_FLAGS_HOME_FULL) != 0) flags = flags & ~BZ_APP_PERMISSIONS_FLAGS_HOME_READ; if ((flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL) != 0) flags = flags & ~BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ; if ((flags & BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL) != 0) flags = flags & ~BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ; if (strv_len > filesystems_hits) { const struct { const gchar *prefix; BzFilesystemPathType type; } filesystems_other[] = { { "/", BZ_FILESYSTEM_PATH_SYSTEM_ROOT }, { "home/", BZ_FILESYSTEM_PATH_HOME_SUBDIR }, { "~/", BZ_FILESYSTEM_PATH_HOME_SUBDIR }, { "host-os", BZ_FILESYSTEM_PATH_HOST_OS }, { "host-etc", BZ_FILESYSTEM_PATH_HOST_ETC }, { "xdg-desktop", BZ_FILESYSTEM_PATH_XDG_DESKTOP }, { "xdg-documents", BZ_FILESYSTEM_PATH_XDG_DOCUMENTS }, { "xdg-music", BZ_FILESYSTEM_PATH_XDG_MUSIC }, { "xdg-pictures", BZ_FILESYSTEM_PATH_XDG_PICTURES }, { "xdg-public-share", BZ_FILESYSTEM_PATH_XDG_PUBLIC_SHARE }, { "xdg-videos", BZ_FILESYSTEM_PATH_XDG_VIDEOS }, { "xdg-templates", BZ_FILESYSTEM_PATH_XDG_TEMPLATES }, { "xdg-cache", BZ_FILESYSTEM_PATH_XDG_CACHE }, { "xdg-config", BZ_FILESYSTEM_PATH_XDG_CONFIG }, { "xdg-data", BZ_FILESYSTEM_PATH_XDG_DATA }, { "xdg-run", BZ_FILESYSTEM_PATH_XDG_RUN } }; flags |= BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER; for (guint j = 0; strv[j]; j++) { gchar *perm = strv[j]; gboolean is_readonly = FALSE; gchar *colon = NULL; guint i = 0; const gchar *subpath = NULL; if (!perm[0]) continue; is_readonly = g_str_has_suffix (perm, ":ro"); colon = strrchr (perm, ':'); if (colon) *colon = '\0'; for (i = 0; i < G_N_ELEMENTS (filesystems_other); i++) { if (g_str_has_prefix (perm, filesystems_other[i].prefix)) { const gchar *slash = NULL; if (filesystems_other[i].type == BZ_FILESYSTEM_PATH_SYSTEM_ROOT) { if (perm[1] != '\0') subpath = perm + 1; else subpath = NULL; } else { slash = strchr (perm, '/'); if (slash && slash != perm) subpath = slash + 1; } if (is_readonly) bz_app_permissions_add_filesystem_read (permissions, filesystems_other[i].type, subpath); else bz_app_permissions_add_filesystem_full (permissions, filesystems_other[i].type, subpath); break; } } if (i == G_N_ELEMENTS (filesystems_other)) { if (is_readonly) bz_app_permissions_add_filesystem_read (permissions, BZ_FILESYSTEM_PATH_CUSTOM, perm); else bz_app_permissions_add_filesystem_full (permissions, BZ_FILESYSTEM_PATH_CUSTOM, perm); } } } } g_strfreev (strv); if (!(flags & (BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS | BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS))) { const struct { GBusType bus_type; const char *keyfile_group; BzAppPermissionsFlags unfiltered_flag; } bus_policy_types[] = { { G_BUS_TYPE_SESSION, "Session Bus Policy", BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS }, { G_BUS_TYPE_SYSTEM, "System Bus Policy", BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS }, }; if (app_id != NULL) { mpris_id = g_strconcat ("org.mpris.MediaPlayer2.", app_id, NULL); app_id_non_devel = g_str_has_suffix (app_id, ".Devel") ? g_strndup (app_id, strlen (app_id) - strlen (".Devel")) : NULL; mpris_id_non_devel = (app_id_non_devel != NULL) ? g_strconcat ("org.mpris.MediaPlayer2.", app_id_non_devel, NULL) : NULL; } for (size_t h = 0; h < G_N_ELEMENTS (bus_policy_types); h++) { g_auto (GStrv) bus_policies = NULL; if (flags & bus_policy_types[h].unfiltered_flag) continue; bus_policies = g_key_file_get_keys (keyfile, bus_policy_types[h].keyfile_group, NULL, NULL); for (size_t i = 0; bus_policies != NULL && bus_policies[i] != NULL; i++) { const struct { GBusType bus_type; const char *bus_name; gboolean is_prefix; BzBusPolicyPermission permission_is_at_least; BzAppPermissionsFlags flags; } bus_policy_permissions[] = { { G_BUS_TYPE_SESSION, "ca.desrt.dconf", FALSE, BZ_BUS_POLICY_PERMISSION_TALK, BZ_APP_PERMISSIONS_FLAGS_SETTINGS }, { G_BUS_TYPE_SESSION, "org.freedesktop.Flatpak", FALSE, BZ_BUS_POLICY_PERMISSION_TALK, BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX }, { G_BUS_TYPE_SESSION, "org.freedesktop.impl.portal.PermissionStore", FALSE, BZ_BUS_POLICY_PERMISSION_TALK, BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX }, { G_BUS_TYPE_SESSION, "org.gtk.vfs.", TRUE, BZ_BUS_POLICY_PERMISSION_TALK, BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL }, }; const char *bus_name_pattern = bus_policies[i]; g_autofree char *bus_policy_str = NULL; BzBusPolicyPermission bus_policy = BZ_BUS_POLICY_PERMISSION_UNKNOWN; size_t j = 0; bus_policy_str = g_key_file_get_string (keyfile, bus_policy_types[h].keyfile_group, bus_name_pattern, NULL); g_assert (bus_policy_str != NULL); if (g_str_equal (bus_policy_str, "none")) bus_policy = BZ_BUS_POLICY_PERMISSION_NONE; else if (g_str_equal (bus_policy_str, "see")) bus_policy = BZ_BUS_POLICY_PERMISSION_SEE; else if (g_str_equal (bus_policy_str, "talk")) bus_policy = BZ_BUS_POLICY_PERMISSION_TALK; else if (g_str_equal (bus_policy_str, "own")) bus_policy = BZ_BUS_POLICY_PERMISSION_OWN; else bus_policy = BZ_BUS_POLICY_PERMISSION_UNKNOWN; if (app_id != NULL && bus_policy_types[h].bus_type == G_BUS_TYPE_SESSION && (g_str_equal (bus_name_pattern, app_id) || (g_str_has_prefix (bus_name_pattern, app_id) && bus_name_pattern[strlen (app_id)] == '.') || g_str_equal (bus_name_pattern, mpris_id) || g_str_equal (bus_name_pattern, "org.freedesktop.DBus") || g_str_has_prefix (bus_name_pattern, "org.freedesktop.portal."))) continue; if (app_id_non_devel != NULL && bus_policy_types[h].bus_type == G_BUS_TYPE_SESSION && (g_str_equal (bus_name_pattern, app_id_non_devel) || (g_str_has_prefix (bus_name_pattern, app_id_non_devel) && bus_name_pattern[strlen (app_id_non_devel)] == '.') || g_str_equal (bus_name_pattern, mpris_id_non_devel))) continue; for (j = 0; j < G_N_ELEMENTS (bus_policy_permissions); j++) { if (bus_policy_permissions[j].bus_type == bus_policy_types[h].bus_type && ((!bus_policy_permissions[j].is_prefix && g_str_equal (bus_name_pattern, bus_policy_permissions[j].bus_name)) || (bus_policy_permissions[j].is_prefix && g_str_has_prefix (bus_name_pattern, bus_policy_permissions[j].bus_name))) && bus_policy >= bus_policy_permissions[j].permission_is_at_least) { flags |= bus_policy_permissions[j].flags; break; } } if (j == G_N_ELEMENTS (bus_policy_permissions)) { flags |= BZ_APP_PERMISSIONS_FLAGS_BUS_POLICY_OTHER; bz_app_permissions_add_bus_policy (permissions, bus_policy_types[h].bus_type, bus_name_pattern, bus_policy); } } } } bz_app_permissions_set_flags (permissions, flags); bz_app_permissions_seal (permissions); return permissions; } void bz_app_permissions_serialize (BzAppPermissions *self, GVariantBuilder *builder) { GFlagsClass *flags_class = NULL; guint i = 0; g_return_if_fail (BZ_IS_APP_PERMISSIONS (self)); g_return_if_fail (builder != NULL); flags_class = g_type_class_ref (BZ_TYPE_APP_PERMISSIONS_FLAGS); if (self->flags != BZ_APP_PERMISSIONS_FLAGS_NONE) { g_autoptr (GVariantBuilder) sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (i = 0; i < flags_class->n_values; i++) { if (self->flags & flags_class->values[i].value) g_variant_builder_add (sub_builder, "s", flags_class->values[i].value_nick); } g_variant_builder_add (builder, "{sv}", "permissions-flags", g_variant_builder_end (sub_builder)); } g_type_class_unref (flags_class); if (self->filesystem_read != NULL && self->filesystem_read->len > 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantBuilder) sub_builder = NULL; enum_class = g_type_class_ref (BZ_TYPE_FILESYSTEM_PATH_TYPE); sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)")); for (i = 0; i < self->filesystem_read->len; i++) { const BzFilesystemPath *path = g_ptr_array_index (self->filesystem_read, i); GEnumValue *enum_value = g_enum_get_value (enum_class, path->type); g_variant_builder_add (sub_builder, "(ss)", enum_value->value_nick, path->subpath ? path->subpath : ""); } g_variant_builder_add (builder, "{sv}", "permissions-filesystem-read", g_variant_builder_end (sub_builder)); g_type_class_unref (enum_class); } if (self->filesystem_full != NULL && self->filesystem_full->len > 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantBuilder) sub_builder = NULL; enum_class = g_type_class_ref (BZ_TYPE_FILESYSTEM_PATH_TYPE); sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)")); for (i = 0; i < self->filesystem_full->len; i++) { const BzFilesystemPath *path = g_ptr_array_index (self->filesystem_full, i); GEnumValue *enum_value = g_enum_get_value (enum_class, path->type); g_variant_builder_add (sub_builder, "(ss)", enum_value->value_nick, path->subpath ? path->subpath : ""); } g_variant_builder_add (builder, "{sv}", "permissions-filesystem-full", g_variant_builder_end (sub_builder)); g_type_class_unref (enum_class); } if (self->bus_policies != NULL && self->bus_policies->len > 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantBuilder) sub_builder = NULL; enum_class = g_type_class_ref (BZ_TYPE_BUS_POLICY_PERMISSION); sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(iss)")); for (i = 0; i < self->bus_policies->len; i++) { BzBusPolicy *policy = g_ptr_array_index (self->bus_policies, i); GEnumValue *enum_value = g_enum_get_value (enum_class, policy->permission); g_variant_builder_add (sub_builder, "(iss)", (gint32) policy->bus_type, policy->bus_name, enum_value->value_nick); } g_variant_builder_add (builder, "{sv}", "permissions-bus-policies", g_variant_builder_end (sub_builder)); g_type_class_unref (enum_class); } } gboolean bz_app_permissions_deserialize (BzAppPermissions *self, GVariant *import, GError **error) { g_autoptr (GVariantIter) iter = NULL; g_return_val_if_fail (BZ_IS_APP_PERMISSIONS (self), FALSE); g_return_val_if_fail (import != NULL, FALSE); iter = g_variant_iter_new (import); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "permissions-flags") == 0) { GFlagsClass *flags_class = NULL; g_autoptr (GVariantIter) flags_iter = NULL; flags_class = g_type_class_ref (BZ_TYPE_APP_PERMISSIONS_FLAGS); flags_iter = g_variant_iter_new (value); self->flags = BZ_APP_PERMISSIONS_FLAGS_NONE; for (;;) { g_autofree char *flag_nick = NULL; if (!g_variant_iter_next (flags_iter, "s", &flag_nick)) break; for (guint i = 0; i < flags_class->n_values; i++) { if (g_str_equal (flag_nick, flags_class->values[i].value_nick)) { self->flags |= flags_class->values[i].value; break; } } } g_type_class_unref (flags_class); } else if (g_strcmp0 (key, "permissions-filesystem-read") == 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantIter) paths_iter = NULL; enum_class = g_type_class_ref (BZ_TYPE_FILESYSTEM_PATH_TYPE); if (self->filesystem_read == NULL) self->filesystem_read = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_filesystem_path_free); paths_iter = g_variant_iter_new (value); for (;;) { g_autofree char *type_nick = NULL; g_autofree char *subpath = NULL; if (!g_variant_iter_next (paths_iter, "(ss)", &type_nick, &subpath)) break; for (guint i = 0; i < enum_class->n_values; i++) { if (g_str_equal (type_nick, enum_class->values[i].value_nick)) { g_ptr_array_add (self->filesystem_read, bz_filesystem_path_new (enum_class->values[i].value, subpath[0] ? subpath : NULL)); break; } } } g_type_class_unref (enum_class); } else if (g_strcmp0 (key, "permissions-filesystem-full") == 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantIter) paths_iter = NULL; enum_class = g_type_class_ref (BZ_TYPE_FILESYSTEM_PATH_TYPE); if (self->filesystem_full == NULL) self->filesystem_full = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_filesystem_path_free); paths_iter = g_variant_iter_new (value); for (;;) { g_autofree char *type_nick = NULL; g_autofree char *subpath = NULL; if (!g_variant_iter_next (paths_iter, "(ss)", &type_nick, &subpath)) break; for (guint i = 0; i < enum_class->n_values; i++) { if (g_str_equal (type_nick, enum_class->values[i].value_nick)) { g_ptr_array_add (self->filesystem_full, bz_filesystem_path_new (enum_class->values[i].value, subpath[0] ? subpath : NULL)); break; } } } g_type_class_unref (enum_class); } else if (g_strcmp0 (key, "permissions-bus-policies") == 0) { GEnumClass *enum_class = NULL; g_autoptr (GVariantIter) policies_iter = NULL; enum_class = g_type_class_ref (BZ_TYPE_BUS_POLICY_PERMISSION); if (self->bus_policies == NULL) self->bus_policies = g_ptr_array_new_with_free_func ((GDestroyNotify) bz_bus_policy_free); policies_iter = g_variant_iter_new (value); for (;;) { gint32 bus_type_int = 0; g_autofree char *bus_name = NULL; g_autofree char *permission_nick = NULL; if (!g_variant_iter_next (policies_iter, "(iss)", &bus_type_int, &bus_name, &permission_nick)) break; for (guint i = 0; i < enum_class->n_values; i++) { if (g_str_equal (permission_nick, enum_class->values[i].value_nick)) { g_ptr_array_add (self->bus_policies, bz_bus_policy_new ((GBusType) bus_type_int, bus_name, enum_class->values[i].value)); break; } } } g_type_class_unref (enum_class); } } bz_app_permissions_seal (self); return TRUE; } static gint cmp_filesystem_path_pointers (gconstpointer item1, gconstpointer item2) { const BzFilesystemPath *const *pitem1 = item1; const BzFilesystemPath *const *pitem2 = item2; const BzFilesystemPath *path1 = *pitem1; const BzFilesystemPath *path2 = *pitem2; if (path1->type != path2->type) return path1->type - path2->type; return g_strcmp0 (path1->subpath, path2->subpath); } static int cmp_bus_policy_qsort (const void *item1, const void *item2) { const BzBusPolicy *const *pitem1 = item1; const BzBusPolicy *const *pitem2 = item2; const BzBusPolicy *policy1 = *pitem1; const BzBusPolicy *policy2 = *pitem2; if (policy1->bus_type != policy2->bus_type) return policy1->bus_type - policy2->bus_type; return strcmp (policy1->bus_name, policy2->bus_name); } static guint app_permissions_get_array_index (GPtrArray *array, BzFilesystemPathType type, const char *subpath) { if (array == NULL) return DOES_NOT_CONTAIN; for (guint i = 0; i < array->len; i++) { const BzFilesystemPath *path = g_ptr_array_index (array, i); if (path->type == type && g_strcmp0 (path->subpath, subpath) == 0) return i; } return DOES_NOT_CONTAIN; } static guint get_strv_index (const gchar *const *strv, const gchar *value) { guint ii; for (ii = 0; strv[ii]; ii++) { if (g_str_equal (strv[ii], value)) break; } return ii; } kolunmi-bazaar-7b9c8e1/src/bz-app-permissions.h000066400000000000000000000145531514314607700215740ustar00rootroot00000000000000/* bz-app-permissions.h * * Copyright 2026 Alexander Vanhee * Copyright (C) 2022 Red Hat * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define BZ_TYPE_APP_PERMISSIONS (bz_app_permissions_get_type ()) G_DECLARE_FINAL_TYPE (BzAppPermissions, bz_app_permissions, BZ, APP_PERMISSIONS, GObject) typedef enum { BZ_APP_PERMISSIONS_FLAGS_NONE = 0, BZ_APP_PERMISSIONS_FLAGS_NETWORK = 1 << 0, BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS = 1 << 1, BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS = 1 << 2, BZ_APP_PERMISSIONS_FLAGS_DEVICES = 1 << 3, BZ_APP_PERMISSIONS_FLAGS_HOME_FULL = 1 << 4, BZ_APP_PERMISSIONS_FLAGS_HOME_READ = 1 << 5, BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL = 1 << 6, BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ = 1 << 7, BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL = 1 << 8, BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ = 1 << 9, BZ_APP_PERMISSIONS_FLAGS_SETTINGS = 1 << 10, BZ_APP_PERMISSIONS_FLAGS_X11 = 1 << 11, BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX = 1 << 12, BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER = 1 << 13, BZ_APP_PERMISSIONS_FLAGS_BUS_POLICY_OTHER = 1 << 14, BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES = 1 << 15, BZ_APP_PERMISSIONS_FLAGS_INPUT_DEVICES = 1 << 16, BZ_APP_PERMISSIONS_FLAGS_SYSTEM_DEVICES = 1 << 17, BZ_APP_PERMISSIONS_FLAGS_SCREEN = 1 << 18, } BzAppPermissionsFlags; #define BZ_TYPE_APP_PERMISSIONS_FLAGS (bz_app_permissions_flags_get_type ()) typedef enum { BZ_FILESYSTEM_PATH_SYSTEM_ROOT, BZ_FILESYSTEM_PATH_HOME_SUBDIR, BZ_FILESYSTEM_PATH_HOST_OS, BZ_FILESYSTEM_PATH_HOST_ETC, BZ_FILESYSTEM_PATH_XDG_DESKTOP, BZ_FILESYSTEM_PATH_XDG_DOCUMENTS, BZ_FILESYSTEM_PATH_XDG_MUSIC, BZ_FILESYSTEM_PATH_XDG_PICTURES, BZ_FILESYSTEM_PATH_XDG_PUBLIC_SHARE, BZ_FILESYSTEM_PATH_XDG_VIDEOS, BZ_FILESYSTEM_PATH_XDG_TEMPLATES, BZ_FILESYSTEM_PATH_XDG_CACHE, BZ_FILESYSTEM_PATH_XDG_CONFIG, BZ_FILESYSTEM_PATH_XDG_DATA, BZ_FILESYSTEM_PATH_XDG_RUN, BZ_FILESYSTEM_PATH_CUSTOM, } BzFilesystemPathType; #define BZ_TYPE_FILESYSTEM_PATH_TYPE (bz_filesystem_path_type_get_type ()) typedef enum { BZ_BUS_POLICY_PERMISSION_UNKNOWN = 0, BZ_BUS_POLICY_PERMISSION_NONE, BZ_BUS_POLICY_PERMISSION_SEE, BZ_BUS_POLICY_PERMISSION_TALK, BZ_BUS_POLICY_PERMISSION_OWN, } BzBusPolicyPermission; #define BZ_TYPE_BUS_POLICY_PERMISSION (bz_bus_policy_permission_get_type ()) typedef struct { BzFilesystemPathType type; char *subpath; } BzFilesystemPath; typedef struct { GBusType bus_type; char *bus_name; BzBusPolicyPermission permission; } BzBusPolicy; GType bz_app_permissions_flags_get_type (void) G_GNUC_CONST; GType bz_safety_rating_get_type (void) G_GNUC_CONST; GType bz_filesystem_path_type_get_type (void) G_GNUC_CONST; GType bz_bus_policy_permission_get_type (void) G_GNUC_CONST; BzFilesystemPath * bz_filesystem_path_new (BzFilesystemPathType type, const char *subpath); void bz_filesystem_path_free (BzFilesystemPath *self); char * bz_filesystem_path_to_display_string (const BzFilesystemPath *path); const char * bz_filesystem_path_to_icon_name (const BzFilesystemPath *path); BzBusPolicy * bz_bus_policy_new (GBusType bus_type, const char *bus_name, BzBusPolicyPermission permission); void bz_bus_policy_free (BzBusPolicy *self); G_DEFINE_AUTOPTR_CLEANUP_FUNC (BzFilesystemPath, bz_filesystem_path_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC (BzBusPolicy, bz_bus_policy_free) BzAppPermissions * bz_app_permissions_new (void); BzAppPermissions * bz_app_permissions_new_from_metadata (GKeyFile *keyfile, GError **error); void bz_app_permissions_seal (BzAppPermissions *self); gboolean bz_app_permissions_is_sealed (BzAppPermissions *self); gboolean bz_app_permissions_is_empty (BzAppPermissions *self); void bz_app_permissions_set_flags (BzAppPermissions *self, BzAppPermissionsFlags flags); BzAppPermissionsFlags bz_app_permissions_get_flags (BzAppPermissions *self); void bz_app_permissions_add_flag (BzAppPermissions *self, BzAppPermissionsFlags flags); void bz_app_permissions_remove_flag (BzAppPermissions *self, BzAppPermissionsFlags flags); void bz_app_permissions_add_filesystem_read (BzAppPermissions *self, BzFilesystemPathType type, const char *subpath); const GPtrArray * bz_app_permissions_get_filesystem_read (BzAppPermissions *self); void bz_app_permissions_add_filesystem_full (BzAppPermissions *self, BzFilesystemPathType type, const char *subpath); const GPtrArray * bz_app_permissions_get_filesystem_full (BzAppPermissions *self); void bz_app_permissions_add_bus_policy (BzAppPermissions *self, GBusType bus_type, const char *bus_name, BzBusPolicyPermission permission); const BzBusPolicy *const * bz_app_permissions_get_bus_policies (BzAppPermissions *self, size_t *out_n_bus_policies); void bz_app_permissions_serialize (BzAppPermissions *self, GVariantBuilder *builder); gboolean bz_app_permissions_deserialize (BzAppPermissions *self, GVariant *import, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-app-size-dialog.blp000066400000000000000000000053141514314607700217510ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAppSizeDialog: Adw.Dialog { content-height: 500; content-width: 600; child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: Adw.Clamp { maximum-size: 600; child: Box { orientation: vertical; margin-top: 6; margin-bottom: 18; margin-start: 18; margin-end: 18; Box { orientation: vertical; margin-bottom: 24; $BzLozenge { title: _("Download Size"); label: bind $format_size(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.size) as ; importance: neutral; } } Adw.PreferencesGroup { margin-bottom: 15; Adw.ActionRow { [prefix] Label { label: bind $format_size(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.size) as ; use-markup: true; valign: center; width-request: 90; margin-top: 8; margin-bottom: 8; styles [ "circular-lozenge", "title-4", "grey", ] } title: _("Download Size"); subtitle: _("Amount to download from the internet"); } Adw.ActionRow { [prefix] Label { label: bind $format_size(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.installed-size) as ; use-markup: true; valign: center; width-request: 90; margin-top: 8; margin-bottom: 8; styles [ "circular-lozenge", "title-4", "grey", ] } title: _("Installed Size"); subtitle: _("Size on Disk"); } Adw.ActionRow { visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.user-data-size ) as ) as ; [prefix] Label { label: bind $format_size(template.group as <$BzEntryGroup>.user-data-size) as ; use-markup: true; valign: center; width-request: 90; margin-top: 8; margin-bottom: 8; styles [ "circular-lozenge", "title-4", "grey", ] } title: _("User Data Size"); subtitle: _("Caches, settings, and other app data"); } } }; }; }; } kolunmi-bazaar-7b9c8e1/src/bz-app-size-dialog.c000066400000000000000000000105251514314607700214160ustar00rootroot00000000000000/* bz-app-size-dialog.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-app-size-dialog.h" #include "bz-entry-group.h" #include "bz-lozenge.h" #include struct _BzAppSizeDialog { AdwDialog parent_instance; BzEntryGroup *group; }; G_DEFINE_FINAL_TYPE (BzAppSizeDialog, bz_app_size_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_app_size_dialog_dispose (GObject *object) { BzAppSizeDialog *self = BZ_APP_SIZE_DIALOG (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_app_size_dialog_parent_class)->dispose (object); } static void bz_app_size_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAppSizeDialog *self = BZ_APP_SIZE_DIALOG (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, self->group); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_app_size_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAppSizeDialog *self = BZ_APP_SIZE_DIALOG (object); switch (prop_id) { case PROP_GROUP: g_clear_object (&self->group); self->group = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static char * format_size (gpointer object, guint64 value) { g_autofree char *size_str = g_format_size (value); char *space = g_strrstr (size_str, "\xC2\xA0"); if (space != NULL) { *space = '\0'; return g_strdup_printf ("%s %s", size_str, space + 2); } return g_strdup (size_str); } static gboolean is_zero (gpointer object, int value) { return value == 0; } static void bz_app_size_dialog_class_init (BzAppSizeDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_app_size_dialog_dispose; object_class->get_property = bz_app_size_dialog_get_property; object_class->set_property = bz_app_size_dialog_set_property; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LOZENGE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-app-size-dialog.ui"); gtk_widget_class_bind_template_callback (widget_class, format_size); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); } static void bz_app_size_dialog_init (BzAppSizeDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_app_size_dialog_new (BzEntryGroup *group) { BzAppSizeDialog *app_size_dialog = NULL; app_size_dialog = g_object_new ( BZ_TYPE_APP_SIZE_DIALOG, "group", group, NULL); return ADW_DIALOG (app_size_dialog); } kolunmi-bazaar-7b9c8e1/src/bz-app-size-dialog.h000066400000000000000000000021001514314607700214110ustar00rootroot00000000000000/* bz-app-size-dialog.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include G_BEGIN_DECLS #define BZ_TYPE_APP_SIZE_DIALOG (bz_app_size_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzAppSizeDialog, bz_app_size_dialog, BZ, APP_SIZE_DIALOG, AdwDialog) AdwDialog * bz_app_size_dialog_new (BzEntryGroup *group); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-app-tile.blp000066400000000000000000000042271514314607700205010ustar00rootroot00000000000000using Gtk 4.0; template $BzAppTile: Button { styles [ "card", "app-tile", ] child: Overlay { Box { margin-start: 12; margin-end: 12; margin-top: 12; margin-bottom: 12; orientation: horizontal; spacing: 15; can-focus: false; Image { pixel-size: 64; paintable: bind template.group as <$BzEntryGroup>.icon-paintable; styles ["icon-dropshadow"] } Box { valign: center; hexpand: true; orientation: vertical; spacing: 4; Box { orientation: horizontal; spacing: 6; Label { css-name: "app-tile-title"; styles [ "heading", ] xalign: 0.0; ellipsize: end; label: bind template.group as <$BzEntryGroup>.title; max-width-chars: 18; } Image { css-name: "app-tile-verified-check"; styles [ "verified", ] visible: bind template.group as <$BzEntryGroup>.is-verified; icon-name: "verified-checkmark-symbolic"; pixel-size: 14; } } Label { css-name: "app-tile-description"; xalign: 0.0; yalign: 0.0; wrap: true; ellipsize: end; vexpand: true; lines: bind $description_line_amount($is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; max-width-chars: 15; single-line-mode: true; label: bind template.group as <$BzEntryGroup>.description; } Box { css-name: "app-tile-installed-pill"; halign: start; spacing: 4; visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; styles ["small-pill", "installed-pill"] Image { icon-name: "app-installed-symbolic"; pixel-size: 12; } Label { // Translators: As in 'The app is installed'. label: _("Installed"); } } } } }; } kolunmi-bazaar-7b9c8e1/src/bz-app-tile.c000066400000000000000000000101641514314607700201430ustar00rootroot00000000000000/* bz-app-tile.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-app-tile.h" struct _BzAppTile { GtkButton parent_instance; BzEntryGroup *group; }; G_DEFINE_FINAL_TYPE (BzAppTile, bz_app_tile, GTK_TYPE_BUTTON); enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_app_tile_dispose (GObject *object) { BzAppTile *self = BZ_APP_TILE (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_app_tile_parent_class)->dispose (object); } static void bz_app_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAppTile *self = BZ_APP_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_app_tile_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_app_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAppTile *self = BZ_APP_TILE (object); switch (prop_id) { case PROP_GROUP: bz_app_tile_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean description_line_amount(gpointer object, bool value) { return value ? 2 : 1; } static void bz_app_tile_class_init (BzAppTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_app_tile_set_property; object_class->get_property = bz_app_tile_get_property; object_class->dispose = bz_app_tile_dispose; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-app-tile.ui"); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, description_line_amount); } static void bz_app_tile_init (BzAppTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_app_tile_new (void) { return g_object_new (BZ_TYPE_APP_TILE, NULL); } BzEntryGroup * bz_app_tile_get_group (BzAppTile *self) { g_return_val_if_fail (BZ_IS_APP_TILE (self), NULL); return self->group; } void bz_app_tile_set_group (BzAppTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_APP_TILE (self)); g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } /* End of bz-app-tile.c */ kolunmi-bazaar-7b9c8e1/src/bz-app-tile.h000066400000000000000000000022421514314607700201460ustar00rootroot00000000000000/* bz-app-tile.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry-group.h" G_BEGIN_DECLS #define BZ_TYPE_APP_TILE (bz_app_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzAppTile, bz_app_tile, BZ, APP_TILE, GtkButton) GtkWidget * bz_app_tile_new (void); BzEntryGroup * bz_app_tile_get_group (BzAppTile *self); void bz_app_tile_set_group (BzAppTile *self, BzEntryGroup *group); G_END_DECLS /* End of bz-app-tile.h */ kolunmi-bazaar-7b9c8e1/src/bz-application-map-factory.c000066400000000000000000000076621514314607700231640ustar00rootroot00000000000000/* bz-application-map-factory.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-application-map-factory.h" #include "bz-util.h" struct _BzApplicationMapFactory { GObject parent_instance; GtkMapListModelMapFunc func; gpointer user_data; GDestroyNotify ref_user_data; GDestroyNotify unref_user_data; GtkFilter *filter; }; G_DEFINE_FINAL_TYPE (BzApplicationMapFactory, bz_application_map_factory, G_TYPE_OBJECT); static void bz_application_map_factory_dispose (GObject *object) { BzApplicationMapFactory *self = BZ_APPLICATION_MAP_FACTORY (object); g_clear_object (&self->filter); if (self->unref_user_data != NULL) g_clear_pointer (&self->user_data, self->unref_user_data); G_OBJECT_CLASS (bz_application_map_factory_parent_class)->dispose (object); } static void bz_application_map_factory_class_init (BzApplicationMapFactoryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_application_map_factory_dispose; } static void bz_application_map_factory_init (BzApplicationMapFactory *self) { } BzApplicationMapFactory * bz_application_map_factory_new (GtkMapListModelMapFunc func, gpointer user_data, GDestroyNotify ref_user_data, GDestroyNotify unref_user_data, GtkFilter *filter) { BzApplicationMapFactory *self = NULL; g_return_val_if_fail (func != NULL, NULL); g_return_val_if_fail (filter == NULL || GTK_IS_FILTER (filter), NULL); self = g_object_new (BZ_TYPE_APPLICATION_MAP_FACTORY, NULL); self->func = func; self->user_data = user_data; self->ref_user_data = ref_user_data; self->unref_user_data = unref_user_data; self->filter = bz_maybe_ref (filter, g_object_ref_sink); return self; } GListModel * bz_application_map_factory_generate (BzApplicationMapFactory *self, GListModel *model) { g_autoptr (GListModel) backing = NULL; GtkMapListModel *map_model = NULL; g_return_val_if_fail (BZ_IS_APPLICATION_MAP_FACTORY (self), NULL); g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL); if (self->filter != NULL) { GtkFilterListModel *filter_model = NULL; filter_model = gtk_filter_list_model_new ( g_object_ref (model), g_object_ref (self->filter)); backing = G_LIST_MODEL (filter_model); } else backing = g_object_ref (model); if (self->ref_user_data != NULL && self->unref_user_data != NULL) self->ref_user_data (self->user_data); map_model = gtk_map_list_model_new ( g_steal_pointer (&backing), self->func, self->user_data, self->ref_user_data != NULL ? self->unref_user_data : NULL); return G_LIST_MODEL (map_model); } gpointer bz_application_map_factory_convert_one (BzApplicationMapFactory *self, gpointer item) { g_return_val_if_fail (BZ_IS_APPLICATION_MAP_FACTORY (self), NULL); g_return_val_if_fail (item != NULL, NULL); return self->func (item, self->user_data); } /* End of bz-application-map-factory.c */ kolunmi-bazaar-7b9c8e1/src/bz-application-map-factory.h000066400000000000000000000033101514314607700231530ustar00rootroot00000000000000/* bz-application-map-factory.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_APPLICATION_MAP_FACTORY (bz_application_map_factory_get_type ()) G_DECLARE_FINAL_TYPE (BzApplicationMapFactory, bz_application_map_factory, BZ, APPLICATION_MAP_FACTORY, GObject) BzApplicationMapFactory * bz_application_map_factory_new (GtkMapListModelMapFunc func, gpointer user_data, GDestroyNotify ref_user_data, GDestroyNotify unref_user_data, GtkFilter *filter); GListModel * bz_application_map_factory_generate (BzApplicationMapFactory *self, GListModel *model); gpointer bz_application_map_factory_convert_one (BzApplicationMapFactory *self, gpointer item); G_END_DECLS /* End of bz-application-map-factory.h */ kolunmi-bazaar-7b9c8e1/src/bz-application.c000066400000000000000000003303071514314607700207370ustar00rootroot00000000000000/* bz-application.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::CORE" #define BAZAAR_MODULE "core" #define MAX_IDS_PER_BLOCKLIST 2048 #include "config.h" #include #include #include "bz-application-map-factory.h" #include "bz-application.h" #include "bz-auth-state.h" #include "bz-backend-notification.h" #include "bz-content-provider.h" #include "bz-donations-dialog.h" #include "bz-entry-cache-manager.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-error.h" #include "bz-favorites-page.h" #include "bz-flathub-state.h" #include "bz-flatpak-entry.h" #include "bz-flatpak-instance.h" #include "bz-gnome-shell-search-provider.h" #include "bz-hash-table-object.h" #include "bz-inspector.h" #include "bz-io.h" #include "bz-login-page.h" #include "bz-newline-parser.h" #include "bz-parser.h" #include "bz-preferences-dialog.h" #include "bz-result.h" #include "bz-root-blocklist.h" #include "bz-root-curated-config.h" #include "bz-serializable.h" #include "bz-state-info.h" #include "bz-transaction-manager.h" #include "bz-util.h" #include "bz-window.h" #include "bz-yaml-parser.h" #include "progress-bar-designs/common.h" struct _BzApplication { AdwApplication parent_instance; BzApplicationMapFactory *application_factory; BzApplicationMapFactory *entry_factory; BzContentProvider *blocklists_provider; BzContentProvider *curated_provider; BzContentProvider *txt_blocklists_provider; BzEntryCacheManager *cache; BzFlathubState *flathub; BzFlathubState *tmp_flathub; BzFlatpakInstance *flatpak; BzGnomeShellSearchProvider *gs_search; BzMainConfig *config; BzNewlineParser *txt_blocklist_parser; BzSearchEngine *search_engine; BzStateInfo *state; BzTransactionManager *transactions; BzYamlParser *blocklist_parser; BzYamlParser *curated_parser; DexChannel *flatpak_notifs; DexFuture *notif_watch; DexFuture *sync; DexPromise *ready_to_open_files; GHashTable *eol_runtimes; GHashTable *ids_to_groups; GHashTable *ignore_eol_set; GHashTable *installed_set; GHashTable *sys_name_to_addons; GHashTable *usr_name_to_addons; GListStore *groups; GListStore *installed_apps; GNetworkMonitor *network; GPtrArray *blocklist_regexes; GPtrArray *txt_blocked_id_sets; GSettings *settings; GTimer *init_timer; GWeakRef main_window; GtkCustomFilter *appid_filter; GtkCustomFilter *group_filter; GtkFilterListModel *group_filter_model; GtkMapListModel *blocklists_to_files; GtkMapListModel *curated_configs_to_files; GtkMapListModel *txt_blocklists_to_files; GtkStringList *blocklists; GtkStringList *curated_configs; GtkStringList *txt_blocklists; gboolean running; guint periodic_timeout_source; int n_notifications_incoming; }; G_DEFINE_FINAL_TYPE (BzApplication, bz_application, ADW_TYPE_APPLICATION) BZ_DEFINE_DATA ( blocklist_regex, BlocklistRegex, { int priority; GRegex *block; GRegex *allow; }, BZ_RELEASE_DATA (block, g_regex_unref); BZ_RELEASE_DATA (allow, g_regex_unref)) BZ_DEFINE_DATA ( respond_to_flatpak, RespondToFlatpak, { GWeakRef *self; BzBackendNotification *notif; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (notif, g_object_unref)) BZ_DEFINE_DATA ( open_flatpakref, OpenFlatpakref, { GWeakRef *self; GFile *file; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (file, g_object_unref)) BZ_DEFINE_DATA ( open_appstream, OpenAppstream, { GWeakRef *self; char *id; }, BZ_RELEASE_DATA (self, g_object_unref); BZ_RELEASE_DATA (id, g_free)) static DexFuture * init_fiber (GWeakRef *wr); static DexFuture * cache_flathub_fiber (GWeakRef *wr); static DexFuture * respond_to_flatpak_fiber (RespondToFlatpakData *data); static DexFuture * open_appstream_fiber (OpenAppstreamData *data); static DexFuture * open_flatpakref_fiber (OpenFlatpakrefData *data); static DexFuture * backend_sync_finally (DexFuture *future, GWeakRef *wr); static DexFuture * init_fiber_finally (DexFuture *future, GWeakRef *wr); static DexFuture * init_sync_finally (DexFuture *future, GWeakRef *wr); static DexFuture * flathub_update_finally (DexFuture *future, GWeakRef *wr); static DexFuture * cache_write_back_finally (DexFuture *future, GWeakRef *wr); static DexFuture * sync_then (DexFuture *future, GWeakRef *wr); static DexFuture * watch_backend_notifs_then_loop_cb (DexFuture *future, GWeakRef *wr); static void fiber_replace_entry (BzApplication *self, BzEntry *entry); static void fiber_check_for_updates (BzApplication *self); static GFile * fiber_dup_flathub_cache_file (char **path_out, GError **error); static gboolean periodic_timeout_cb (BzApplication *self); static gboolean scheduled_timeout_cb (GWeakRef *wr); static void network_status_changed (BzApplication *self, GParamSpec *pspec, GNetworkMonitor *network); static void disable_blocklists_changed (BzApplication *self, GParamSpec *pspec, BzStateInfo *state); static void show_hide_app_setting_changed (BzApplication *self, const char *key, GSettings *settings); static gboolean window_close_request (BzApplication *self, GtkWidget *window); static void blocklists_changed (BzApplication *self, guint position, guint removed, guint added, GListModel *model); static void txt_blocklists_changed (BzApplication *self, guint position, guint removed, guint added, GListModel *model); static void init_service_struct (BzApplication *self, GtkStringList *blocklists, GtkStringList *txt_blocklists, GtkStringList *curated_configs); static GtkWindow * new_window (BzApplication *self); static void open_appstream_take (BzApplication *self, char *appstream); static void open_flatpakref_take (BzApplication *self, GFile *file); static void command_line_open_location (BzApplication *self, GApplicationCommandLine *cmdline, const char *path); static void open_generic_id (BzApplication *self, const char *generic_id); static gpointer map_strings_to_files (GtkStringObject *string, gpointer data); static gpointer map_generic_ids_to_groups (GtkStringObject *string, BzApplication *self); static gpointer map_ids_to_entries (GtkStringObject *string, BzApplication *self); static gboolean filter_application_ids (GtkStringObject *string, BzApplication *self); static gboolean filter_entry_groups (BzEntryGroup *group, BzApplication *self); static gint cmp_group (BzEntryGroup *a, BzEntryGroup *b, gpointer user_data); static gint cmp_entry (BzEntry *a, BzEntry *b, gpointer user_data); static gboolean validate_group_for_ui (BzApplication *self, BzEntryGroup *group); static DexFuture * make_sync_future (BzApplication *self); static void finish_with_background_task_label (BzApplication *self); static void bz_application_dispose (GObject *object) { BzApplication *self = BZ_APPLICATION (object); dex_clear (&self->flatpak_notifs); dex_clear (&self->notif_watch); dex_clear (&self->ready_to_open_files); dex_clear (&self->sync); g_clear_handle_id (&self->periodic_timeout_source, g_source_remove); g_clear_object (&self->appid_filter); g_clear_object (&self->application_factory); g_clear_object (&self->blocklist_parser); g_clear_object (&self->blocklists); g_clear_object (&self->blocklists_provider); g_clear_object (&self->blocklists_to_files); g_clear_object (&self->cache); g_clear_object (&self->curated_configs); g_clear_object (&self->curated_configs_to_files); g_clear_object (&self->curated_parser); g_clear_object (&self->curated_provider); g_clear_object (&self->entry_factory); g_clear_object (&self->flathub); g_clear_object (&self->flatpak); g_clear_object (&self->group_filter); g_clear_object (&self->group_filter_model); g_clear_object (&self->groups); g_clear_object (&self->gs_search); g_clear_object (&self->installed_apps); g_clear_object (&self->network); g_clear_object (&self->search_engine); g_clear_object (&self->settings); g_clear_object (&self->state); g_clear_object (&self->tmp_flathub); g_clear_object (&self->transactions); g_clear_object (&self->txt_blocklist_parser); g_clear_object (&self->txt_blocklists); g_clear_object (&self->txt_blocklists_provider); g_clear_object (&self->txt_blocklists_to_files); g_clear_pointer (&self->blocklist_regexes, g_ptr_array_unref); g_clear_pointer (&self->eol_runtimes, g_hash_table_unref); g_clear_pointer (&self->ids_to_groups, g_hash_table_unref); g_clear_pointer (&self->ignore_eol_set, g_hash_table_unref); g_clear_pointer (&self->init_timer, g_timer_destroy); g_clear_pointer (&self->installed_set, g_hash_table_unref); g_clear_pointer (&self->sys_name_to_addons, g_hash_table_unref); g_clear_pointer (&self->txt_blocked_id_sets, g_ptr_array_unref); g_clear_pointer (&self->usr_name_to_addons, g_hash_table_unref); g_weak_ref_clear (&self->main_window); G_OBJECT_CLASS (bz_application_parent_class)->dispose (object); } static void bz_application_activate (GApplication *app) { BzApplication *self = BZ_APPLICATION (app); new_window (self); } static int bz_application_command_line (GApplication *app, GApplicationCommandLine *cmdline) { BzApplication *self = BZ_APPLICATION (app); g_autoptr (GError) local_error = NULL; gint argc = 0; g_auto (GStrv) argv = NULL; gboolean help = FALSE; gboolean no_window = FALSE; g_auto (GStrv) blocklists_strv = NULL; g_auto (GStrv) content_configs_strv = NULL; g_auto (GStrv) locations = NULL; GOptionEntry main_entries[] = { { "help", 0, 0, G_OPTION_ARG_NONE, &help, "Print help" }, { "no-window", 0, 0, G_OPTION_ARG_NONE, &no_window, "Ensure the service is running without creating a new window" }, { "extra-blocklist", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &blocklists_strv, "Add an extra blocklist to read from" }, { "extra-curated-config", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &content_configs_strv, "Add an extra yaml file with which to configure the app browser" }, /* Here for backwards compat */ { "extra-content-config", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &content_configs_strv, "Add an extra yaml file with which to configure the app browser (backwards compat)" }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "flatpakref file to open" }, { NULL } }; argv = g_application_command_line_get_arguments (cmdline, &argc); g_debug ("Handling gapplication command line; argc=%d, argv= \\", argc); for (guint i = 0; i < argc; i++) { g_debug (" [%d] %s", i, argv[i]); } if (argv != NULL && argc > 0) { g_autofree GStrv argv_shallow = NULL; g_autoptr (GOptionContext) context = NULL; argv_shallow = g_memdup2 (argv, sizeof (*argv) * argc); context = g_option_context_new ("- an app center for GNOME"); g_option_context_set_help_enabled (context, FALSE); g_option_context_add_main_entries (context, main_entries, NULL); if (!g_option_context_parse (context, &argc, &argv_shallow, &local_error)) { g_application_command_line_printerr (cmdline, "%s\n", local_error->message); return EXIT_FAILURE; } if (help) { g_autofree char *help_text = NULL; if (self->running) g_application_command_line_printerr (cmdline, "The Bazaar service is running.\n\n"); else g_application_command_line_printerr (cmdline, "The Bazaar service is not running.\n\n"); help_text = g_option_context_get_help (context, TRUE, NULL); g_application_command_line_printerr (cmdline, "%s\n", help_text); return EXIT_SUCCESS; } } if (!self->running) { g_autoptr (GtkStringList) blocklists = NULL; g_autoptr (GtkStringList) txt_blocklists = NULL; g_autoptr (GtkStringList) content_configs = NULL; g_autoptr (DexFuture) init = NULL; g_debug ("Starting daemon!"); g_application_hold (G_APPLICATION (self)); self->running = TRUE; blocklists = gtk_string_list_new (NULL); txt_blocklists = gtk_string_list_new (NULL); content_configs = gtk_string_list_new (NULL); init_service_struct (self, blocklists, txt_blocklists, content_configs); #ifdef HARDCODED_BLOCKLIST g_debug ("Bazaar was configured with a hardcoded txt blocklist at %s, adding that now...", HARDCODED_BLOCKLIST); gtk_string_list_append (txt_blocklists, HARDCODED_BLOCKLIST); #endif if (blocklists_strv != NULL) gtk_string_list_splice ( txt_blocklists, g_list_model_get_n_items (G_LIST_MODEL (txt_blocklists)), 0, (const char *const *) blocklists_strv); #ifdef HARDCODED_CONTENT_CONFIG g_debug ("Bazaar was configured with a hardcoded curated content config at %s, adding that now...", HARDCODED_CONTENT_CONFIG); gtk_string_list_append (content_configs, HARDCODED_CONTENT_CONFIG); #endif if (content_configs_strv != NULL) gtk_string_list_splice ( content_configs, g_list_model_get_n_items (G_LIST_MODEL (content_configs)), 0, (const char *const *) content_configs_strv); g_timer_start (self->init_timer); init = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) init_fiber, bz_track_weak (self), bz_weak_release); init = dex_future_finally ( init, (DexFutureCallback) init_fiber_finally, bz_track_weak (self), bz_weak_release); dex_future_disown (g_steal_pointer (&init)); } if (!no_window) new_window (self); if (locations != NULL && *locations != NULL) command_line_open_location (self, cmdline, locations[0]); return EXIT_SUCCESS; } static gboolean bz_application_local_command_line (GApplication *application, gchar ***arguments, int *exit_status) { return FALSE; } static gboolean bz_application_dbus_register (GApplication *application, GDBusConnection *connection, const gchar *object_path, GError **error) { BzApplication *self = BZ_APPLICATION (application); return bz_gnome_shell_search_provider_set_connection (self->gs_search, connection, error); } static void bz_application_dbus_unregister (GApplication *application, GDBusConnection *connection, const gchar *object_path) { BzApplication *self = BZ_APPLICATION (application); bz_gnome_shell_search_provider_set_connection (self->gs_search, NULL, NULL); } static void bz_application_class_init (BzApplicationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GApplicationClass *app_class = G_APPLICATION_CLASS (klass); object_class->dispose = bz_application_dispose; app_class->activate = bz_application_activate; app_class->command_line = bz_application_command_line; app_class->local_command_line = bz_application_local_command_line; app_class->dbus_register = bz_application_dbus_register; app_class->dbus_unregister = bz_application_dbus_unregister; g_type_ensure (BZ_TYPE_RESULT); } static void bz_application_toggle_debug_mode_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; gboolean debug_mode = FALSE; debug_mode = bz_state_info_get_debug_mode (self->state); bz_state_info_set_debug_mode (self->state, !debug_mode); } static void bz_application_bazaar_inspector_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; BzInspector *inspector = NULL; g_assert (BZ_IS_APPLICATION (self)); inspector = bz_inspector_new (); bz_inspector_set_state (inspector, self->state); gtk_application_add_window (GTK_APPLICATION (self), GTK_WINDOW (inspector)); gtk_window_present (GTK_WINDOW (inspector)); } static void bz_application_donate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; AdwDialog *dialog = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); dialog = bz_donations_dialog_new (); bz_donations_dialog_set_state (BZ_DONATIONS_DIALOG (dialog), self->state); adw_dialog_present (dialog, GTK_WIDGET (window)); bz_state_info_set_donation_prompt_dismissed (self->state, TRUE); } static void bz_application_search_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; const char *initial_text = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); if (parameter != NULL) initial_text = g_variant_get_string (parameter, NULL); bz_window_search (BZ_WINDOW (window), initial_text); } static void bz_application_show_app_id_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; const char *app_id = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); if (parameter != NULL) { app_id = g_variant_get_string (parameter, NULL); bz_window_show_app_id (BZ_WINDOW (window), app_id); } } static void bz_application_sync_remotes_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; g_assert (BZ_IS_APPLICATION (self)); if (self->sync != NULL && dex_future_is_pending (self->sync)) return; dex_clear (&self->sync); self->sync = make_sync_future (self); } static void bz_application_about_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; AdwDialog *dialog = NULL; g_autoptr (GBytes) release_notes_bytes = NULL; const char *release_notes_text = NULL; const char *developers[] = { C_ ("About Dialog Developer Credit", "Adam Masciola "), C_ ("About Dialog Developer Credit", "Alexander Vanhee"), /* This array MUST be NULL terminated */ NULL }; const char *special_thanks[] = { "arewelibadwaitayet https://arewelibadwaitayet.com/", /* This array MUST be NULL terminated */ NULL }; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); dialog = adw_about_dialog_new (); release_notes_bytes = g_resources_lookup_data ( "/io/github/kolunmi/Bazaar/release-notes.xml", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); if (release_notes_bytes != NULL) release_notes_text = g_bytes_get_data (release_notes_bytes, NULL); g_object_set ( dialog, "application-name", "Bazaar", "application-icon", "io.github.kolunmi.Bazaar", "developer-name", _ ("Adam Masciola"), "developers", developers, // Translators: Put one translator per line, in the form NAME , YEAR1, YEAR2 "translator-credits", _ ("translator-credits"), "version", PACKAGE_VERSION, "copyright", "Š 2025 Adam Masciola", "license-type", GTK_LICENSE_GPL_3_0, "website", "https://github.com/kolunmi/bazaar", "issue-url", "https://github.com/kolunmi/bazaar/issues", "release-notes", release_notes_text, NULL); adw_about_dialog_add_acknowledgement_section ( ADW_ABOUT_DIALOG (dialog), _ ("Special Thanks"), special_thanks); adw_dialog_present (dialog, GTK_WIDGET (window)); } static void bz_application_preferences_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; AdwDialog *preferences = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); preferences = bz_preferences_dialog_new (self->state); adw_dialog_present (preferences, GTK_WIDGET (window)); } static void bz_application_flathub_login_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; BzAuthState *auth_state = NULL; AdwNavigationPage *login_page = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); auth_state = bz_state_info_get_auth_state (self->state); login_page = bz_login_page_new (auth_state); bz_window_push_page (BZ_WINDOW (window), login_page); } static void bz_application_flathub_logout_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = BZ_APPLICATION (user_data); GtkWindow *window = gtk_application_get_active_window (GTK_APPLICATION (self)); BzAuthState *auth_state = bz_state_info_get_auth_state (self->state); g_assert (BZ_IS_WINDOW (window)); bz_auth_state_clear (auth_state); bz_window_add_toast ( BZ_WINDOW (window), adw_toast_new (_ ("Logged Out Successfully!"))); } static void bz_application_flathub_favorites_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; GtkWindow *window = NULL; AdwNavigationPage *favorites_page = NULL; g_assert (BZ_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); favorites_page = ADW_NAVIGATION_PAGE (bz_favorites_page_new (self->state)); bz_window_push_page (BZ_WINDOW (window), favorites_page); } static void bz_application_quit_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { BzApplication *self = user_data; g_assert (BZ_IS_APPLICATION (self)); g_application_quit (G_APPLICATION (self)); } static const GActionEntry app_actions[] = { { "flathub-login", bz_application_flathub_login_action, NULL }, { "flathub-logout", bz_application_flathub_logout_action, NULL }, { "flathub-favorites", bz_application_flathub_favorites_action, NULL }, { "quit", bz_application_quit_action, NULL }, { "preferences", bz_application_preferences_action, NULL }, { "about", bz_application_about_action, NULL }, { "sync-remotes", bz_application_sync_remotes_action, NULL }, { "search", bz_application_search_action, "s" }, { "show-app-id", bz_application_show_app_id_action, "s" }, { "donate", bz_application_donate_action, NULL }, { "bazaar-inspector", bz_application_bazaar_inspector_action, NULL }, { "toggle-debug-mode", bz_application_toggle_debug_mode_action, NULL }, }; static void bz_application_init (BzApplication *self) { self->running = FALSE; g_weak_ref_init (&self->main_window, NULL); self->gs_search = bz_gnome_shell_search_provider_new (); g_action_map_add_action_entries ( G_ACTION_MAP (self), app_actions, G_N_ELEMENTS (app_actions), self); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.quit", (const char *[]) { "q", NULL }); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.preferences", (const char *[]) { "comma", NULL }); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.sync-remotes", (const char *[]) { "r", NULL }); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.search('')", (const char *[]) { "f", NULL }); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.bazaar-inspector", (const char *[]) { "i", NULL }); gtk_application_set_accels_for_action ( GTK_APPLICATION (self), "app.toggle-debug-mode", (const char *[]) { "d", NULL }); } BzStateInfo * bz_state_info_get_default (void) { GApplication *app = NULL; BzApplication *self = NULL; app = g_application_get_default (); if G_UNLIKELY (app == NULL) return NULL; self = (BzApplication *) app; g_assert (BZ_IS_APPLICATION (self)); return self->state; } static DexFuture * init_fiber (GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; g_autofree char *root_cache_dir = NULL; g_autoptr (GFile) root_cache_dir_file = NULL; g_autoptr (GListModel) repos = NULL; gboolean has_flathub = FALSE; gboolean result = FALSE; g_autoptr (GHashTable) cached_set = NULL; g_autofree char *flathub_cache = NULL; g_autoptr (GFile) flathub_cache_file = NULL; bz_weak_get_or_return_reject (self, wr); bz_state_info_set_online (self->state, TRUE); bz_state_info_set_busy (self->state, TRUE); bz_state_info_set_background_task_label (self->state, _ ("Performing setup...")); root_cache_dir = bz_dup_root_cache_dir (); root_cache_dir_file = g_file_new_for_path (root_cache_dir); if (dex_await (dex_file_query_exists (root_cache_dir_file), NULL)) { g_autofree char *cache_version_path = NULL; g_autoptr (GFile) cache_version_file = NULL; gboolean wipe_cache = TRUE; cache_version_path = g_build_filename (root_cache_dir, "cache-version", NULL); cache_version_file = g_file_new_for_path (cache_version_path); if (dex_await (dex_file_query_exists (cache_version_file), NULL)) { g_autoptr (GBytes) bytes = NULL; bytes = dex_await_boxed (dex_file_load_contents_bytes (cache_version_file), NULL); if (bytes != NULL) { g_autoptr (GVariant) variant = NULL; variant = g_variant_new_from_bytes (G_VARIANT_TYPE_STRING, bytes, FALSE); if (variant != NULL) { const char *version = NULL; version = g_variant_get_string (variant, NULL); wipe_cache = g_strcmp0 (version, PACKAGE_VERSION) != 0; } } } if (wipe_cache) { bz_state_info_set_donation_prompt_dismissed (self->state, FALSE); g_info ("Version incompatibility detected: clearing cache"); dex_await (bz_reap_file_dex (root_cache_dir_file), NULL); } if (dex_await (dex_file_make_directory_with_parents (root_cache_dir_file), NULL)) { g_autoptr (GVariant) variant = NULL; g_autoptr (GBytes) bytes = NULL; variant = g_variant_new_string (PACKAGE_VERSION); bytes = g_variant_get_data_as_bytes (variant); dex_await (dex_file_replace_contents_bytes ( cache_version_file, bytes, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION), NULL); } } else bz_state_info_set_donation_prompt_dismissed (self->state, FALSE); g_clear_object (&self->flatpak); self->flatpak = dex_await_object (bz_flatpak_instance_new (), &local_error); if (self->flatpak == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); bz_transaction_manager_set_backend (self->transactions, BZ_BACKEND (self->flatpak)); bz_state_info_set_backend (self->state, BZ_BACKEND (self->flatpak)); has_flathub = dex_await_boolean ( bz_flatpak_instance_has_flathub (self->flatpak, NULL), &local_error); if (local_error != NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (!has_flathub) { GtkWindow *window = NULL; g_autofree char *response = NULL; window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window != NULL) { AdwDialog *alert = NULL; alert = adw_alert_dialog_new (NULL, NULL); adw_alert_dialog_set_prefer_wide_layout (ADW_ALERT_DIALOG (alert), TRUE); adw_alert_dialog_format_heading ( ADW_ALERT_DIALOG (alert), _ ("Set Up Flathub")); adw_alert_dialog_format_body ( ADW_ALERT_DIALOG (alert), _ ("Flathub is not set up on this system. " "You will not be able to browse and install applications in Bazaar if its unavailable.\n\n" "You can still use Bazaar to browse and remove already installed apps.")); adw_alert_dialog_add_responses ( ADW_ALERT_DIALOG (alert), "later", _ ("Later"), "add", _ ("Set Up Flathub"), NULL); adw_alert_dialog_set_response_appearance ( ADW_ALERT_DIALOG (alert), "add", ADW_RESPONSE_SUGGESTED); adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (alert), "add"); adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (alert), "later"); adw_dialog_present (alert, GTK_WIDGET (window)); response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (alert)), NULL); } if (response != NULL && g_strcmp0 (response, "add") == 0) { result = dex_await ( bz_flatpak_instance_ensure_has_flathub (self->flatpak, NULL), &local_error); if (!result) { g_warning ("Failed to install flathub: %s", local_error->message); g_clear_error (&local_error); } } } self->installed_set = dex_await_boxed ( bz_backend_retrieve_install_ids ( BZ_BACKEND (self->flatpak), NULL), &local_error); if (self->installed_set == NULL) { g_warning ("Unable to enumerate installed entries from flatpak backend; " "no entries will appear to be installed: %s", local_error->message); g_clear_error (&local_error); self->installed_set = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_free); } repos = dex_await_object ( bz_backend_list_repositories (BZ_BACKEND (self->flatpak), NULL), &local_error); if (repos != NULL) bz_state_info_set_repositories (self->state, repos); else { g_warning ("Failed to enumerate repositories: %s", local_error->message); g_clear_error (&local_error); } /* Revive old cache from previous Bazaar process */ cached_set = dex_await_boxed ( bz_entry_cache_manager_enumerate_disk (self->cache), &local_error); if (cached_set != NULL) { g_autoptr (GPtrArray) futures = NULL; GHashTableIter iter = { 0 }; g_autoptr (GPtrArray) entries = NULL; futures = g_ptr_array_new_with_free_func (dex_unref); g_hash_table_iter_init (&iter, cached_set); for (;;) { char *checksum = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &checksum, NULL)) break; g_ptr_array_add ( futures, bz_entry_cache_manager_get_by_checksum ( self->cache, checksum)); } g_clear_pointer (&cached_set, g_hash_table_unref); if (futures->len > 0) dex_await (dex_future_allv ( (DexFuture *const *) futures->pdata, futures->len), NULL); entries = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < futures->len; i++) { DexFuture *future = NULL; const GValue *value = NULL; future = g_ptr_array_index (futures, i); value = dex_future_get_value (future, &local_error); if (value != NULL) g_ptr_array_add (entries, g_value_dup_object (value)); else { g_warning ("Unable to retrieve cached entry: %s", local_error->message); g_clear_error (&local_error); } } g_ptr_array_sort_values_with_data ( entries, (GCompareDataFunc) cmp_entry, NULL); for (guint i = 0; i < entries->len; i++) { BzEntry *entry = NULL; entry = g_ptr_array_index (entries, i); fiber_replace_entry (self, entry); } gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_LESS_STRICT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_LESS_STRICT); } else { g_warning ("Unable to enumerate cached entries: %s", local_error->message); g_clear_error (&local_error); } flathub_cache_file = fiber_dup_flathub_cache_file (&flathub_cache, &local_error); if (flathub_cache_file != NULL) { if (dex_await (dex_file_query_exists (flathub_cache_file), NULL)) { g_autoptr (GBytes) bytes = NULL; bytes = dex_await_boxed ( dex_file_load_contents_bytes (flathub_cache_file), &local_error); if (bytes != NULL) { g_autoptr (GVariant) variant = NULL; g_autoptr (BzFlathubState) flathub = NULL; variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARDICT, bytes, FALSE); if (variant == NULL) { g_warning ("Failed to interpret cached flathub state from %s: %s", flathub_cache, local_error->message); g_clear_error (&local_error); } flathub = bz_flathub_state_new (); result = bz_serializable_deserialize ( BZ_SERIALIZABLE (flathub), variant, &local_error); if (result) { self->flathub = g_steal_pointer (&flathub); bz_flathub_state_set_map_factory (self->flathub, self->application_factory); bz_state_info_set_flathub (self->state, self->flathub); bz_state_info_set_busy (self->state, FALSE); dex_promise_resolve_boolean (self->ready_to_open_files, TRUE); } else { g_warning ("Failed to deserialize cached flathub state from %s: %s", flathub_cache, local_error->message); g_clear_error (&local_error); } } else { g_warning ("Failed to decache cache flathub state from %s: %s", flathub_cache, local_error->message); g_clear_error (&local_error); } } } else { g_warning ("Unable to ensure cache directory: %s", local_error->message); g_clear_error (&local_error); } return dex_future_new_true (); } static DexFuture * cache_flathub_fiber (GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *flathub_cache = NULL; g_autoptr (GFile) flathub_cache_file = NULL; bz_weak_get_or_return_reject (self, wr); flathub_cache_file = fiber_dup_flathub_cache_file (&flathub_cache, &local_error); if (flathub_cache_file != NULL) { g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (GBytes) bytes = NULL; builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); bz_serializable_serialize (BZ_SERIALIZABLE (self->flathub), builder); variant = g_variant_builder_end (builder); bytes = g_variant_get_data_as_bytes (variant); result = dex_await ( dex_file_replace_contents_bytes ( flathub_cache_file, bytes, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION), &local_error); if (!result) { g_warning ("Failed to cache flathub state to %s: %s", flathub_cache, local_error->message); g_clear_error (&local_error); } } else { g_warning ("Unable to ensure cache directory: %s", local_error->message); g_clear_error (&local_error); } return dex_future_new_true (); } static DexFuture * respond_to_flatpak_fiber (RespondToFlatpakData *data) { g_autoptr (BzApplication) self = NULL; BzBackendNotification *notif = data->notif; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) build_futures = NULL; g_autoptr (DexFuture) read_future = NULL; g_autoptr (DexFuture) reread_timeout = NULL; gboolean update_labels = FALSE; gboolean update_filter = FALSE; bz_weak_get_or_return_reject (self, data->self); build_futures = g_ptr_array_new_with_free_func (dex_unref); read_future = dex_future_new_for_object (notif); /* `reread_timeout` defines how long we are allowed to spend adding to `build-futures` before we update the UI later */ reread_timeout = dex_timeout_new_msec (100); for (;;) { BzBackendNotificationKind kind = 0; if (!dex_future_is_resolved (read_future)) { g_autoptr (DexFuture) future = NULL; future = dex_future_all_race ( dex_ref (reread_timeout), dex_ref (read_future), NULL); dex_await (g_steal_pointer (&future), NULL); if (!dex_future_is_pending (reread_timeout)) break; } notif = g_value_get_object (dex_future_get_value (read_future, NULL)); kind = bz_backend_notification_get_kind (notif); switch (kind) { case BZ_BACKEND_NOTIFICATION_KIND_ERROR: { const char *error = NULL; GtkWindow *window = NULL; error = bz_backend_notification_get_error (notif); if (error == NULL) break; g_warning ("Received an error from the flatpak backend: %s", error); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window != NULL) bz_show_error_for_widget (GTK_WIDGET (window), error); } break; case BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING: { int n_incoming = 0; n_incoming = bz_backend_notification_get_n_incoming (notif); self->n_notifications_incoming += n_incoming; update_labels = TRUE; } break; case BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY: { BzEntry *entry = NULL; entry = bz_backend_notification_get_entry (notif); fiber_replace_entry (self, entry); g_ptr_array_add (build_futures, bz_entry_cache_manager_add (self->cache, entry)); if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) update_filter = TRUE; self->n_notifications_incoming--; update_labels = TRUE; } break; case BZ_BACKEND_NOTIFICATION_KIND_INSTALL_DONE: case BZ_BACKEND_NOTIFICATION_KIND_UPDATE_DONE: case BZ_BACKEND_NOTIFICATION_KIND_REMOVE_DONE: { const char *unique_id = NULL; g_autoptr (BzEntry) entry = NULL; unique_id = bz_backend_notification_get_unique_id (notif); entry = dex_await_object ( bz_entry_cache_manager_get (self->cache, unique_id), &local_error); if (entry == NULL) { g_warning ("Backend notification references an entry " "which couldn't be decached: %s", local_error->message); break; } switch (kind) { case BZ_BACKEND_NOTIFICATION_KIND_INSTALL_DONE: { const char *version = NULL; version = bz_backend_notification_get_version (notif); g_hash_table_replace (self->installed_set, g_strdup (unique_id), g_strdup (version)); bz_entry_set_installed_version (entry, version); bz_entry_set_installed (entry, TRUE); if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) { BzEntryGroup *group = NULL; group = g_hash_table_lookup (self->ids_to_groups, bz_entry_get_id (entry)); if (group != NULL) { gboolean found = FALSE; guint position = 0; found = g_list_store_find (self->installed_apps, group, &position); if (!found) g_list_store_insert_sorted (self->installed_apps, group, (GCompareDataFunc) cmp_group, NULL); } } } break; case BZ_BACKEND_NOTIFICATION_KIND_UPDATE_DONE: { const char *version = NULL; version = bz_backend_notification_get_version (notif); g_hash_table_replace (self->installed_set, g_strdup (unique_id), g_strdup (version)); } break; case BZ_BACKEND_NOTIFICATION_KIND_REMOVE_DONE: { bz_entry_set_installed_version (entry, NULL); bz_entry_set_installed (entry, FALSE); g_hash_table_remove (self->installed_set, unique_id); if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) { BzEntryGroup *group = NULL; group = g_hash_table_lookup (self->ids_to_groups, bz_entry_get_id (entry)); if (group != NULL && !bz_entry_group_get_removable (group)) { gboolean found = FALSE; guint position = 0; found = g_list_store_find (self->installed_apps, group, &position); if (found) g_list_store_remove (self->installed_apps, position); } } } break; case BZ_BACKEND_NOTIFICATION_KIND_ERROR: case BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING: case BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY: case BZ_BACKEND_NOTIFICATION_KIND_EXTERNAL_CHANGE: default: g_assert_not_reached (); }; g_ptr_array_add (build_futures, bz_entry_cache_manager_add (self->cache, entry)); } break; case BZ_BACKEND_NOTIFICATION_KIND_EXTERNAL_CHANGE: { g_autoptr (GHashTable) installed_set = NULL; g_autoptr (GPtrArray) diff_reads = NULL; GHashTableIter old_iter = { 0 }; GHashTableIter new_iter = { 0 }; g_autoptr (GPtrArray) diff_writes = NULL; bz_state_info_set_background_task_label (self->state, _ ("Synchronizing...")); installed_set = dex_await_boxed ( bz_backend_retrieve_install_ids ( BZ_BACKEND (self->flatpak), NULL), &local_error); if (installed_set == NULL) { g_warning ("Failed to enumerate installed entries: %s", local_error->message); finish_with_background_task_label (self); break; } diff_reads = g_ptr_array_new_with_free_func (dex_unref); g_hash_table_iter_init (&old_iter, self->installed_set); for (;;) { char *unique_id = NULL; if (!g_hash_table_iter_next ( &old_iter, (gpointer *) &unique_id, NULL)) break; if (!g_hash_table_contains (installed_set, unique_id)) g_ptr_array_add ( diff_reads, bz_entry_cache_manager_get (self->cache, unique_id)); } g_hash_table_iter_init (&new_iter, installed_set); for (;;) { char *unique_id = NULL; if (!g_hash_table_iter_next ( &new_iter, (gpointer *) &unique_id, NULL)) break; if (!g_hash_table_contains (self->installed_set, unique_id)) g_ptr_array_add ( diff_reads, bz_entry_cache_manager_get (self->cache, unique_id)); } if (diff_reads->len > 0) { dex_await (dex_future_allv ( (DexFuture *const *) diff_reads->pdata, diff_reads->len), NULL); diff_writes = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < diff_reads->len; i++) { DexFuture *future = NULL; future = g_ptr_array_index (diff_reads, i); if (dex_future_is_resolved (future)) { BzEntry *entry = NULL; const char *id = NULL; const char *unique_id = NULL; BzEntryGroup *group = NULL; gboolean installed = FALSE; const char *version = NULL; entry = g_value_get_object (dex_future_get_value (future, NULL)); id = bz_entry_get_id (entry); group = g_hash_table_lookup (self->ids_to_groups, id); if (group != NULL) bz_entry_group_connect_living (group, entry); unique_id = bz_entry_get_unique_id (entry); installed = g_hash_table_contains (installed_set, unique_id); version = g_hash_table_lookup (installed_set, unique_id); if (installed && version != NULL && *version != '\0') bz_entry_set_installed_version (entry, version); bz_entry_set_installed (entry, installed); if (group != NULL) { gboolean found = FALSE; guint position = 0; found = g_list_store_find (self->installed_apps, group, &position); if (installed && !found) g_list_store_insert_sorted ( self->installed_apps, group, (GCompareDataFunc) cmp_group, NULL); else if (!installed && found && bz_entry_group_get_removable (group) == 0) g_list_store_remove (self->installed_apps, position); } g_ptr_array_add ( diff_writes, bz_entry_cache_manager_add (self->cache, entry)); } } dex_await (dex_future_allv ( (DexFuture *const *) diff_writes->pdata, diff_writes->len), NULL); } g_clear_pointer (&self->installed_set, g_hash_table_unref); self->installed_set = g_steal_pointer (&installed_set); fiber_check_for_updates (self); finish_with_background_task_label (self); } break; default: g_assert_not_reached (); } dex_clear (&read_future); read_future = dex_channel_receive (self->flatpak_notifs); if (!dex_future_is_pending (reread_timeout)) break; } if (build_futures->len > 0) { g_autoptr (DexFuture) future = NULL; future = dex_future_allv ( (DexFuture *const *) build_futures->pdata, build_futures->len); if (update_filter) future = dex_future_finally ( future, (DexFutureCallback) cache_write_back_finally, bz_track_weak (self), bz_weak_release); dex_future_disown (g_steal_pointer (&future)); } if (update_labels) { if (self->n_notifications_incoming > 0) { g_autofree char *label = NULL; label = g_strdup_printf (_ ("Receiving %d entries..."), self->n_notifications_incoming); bz_state_info_set_background_task_label (self->state, label); } else { bz_state_info_set_background_task_label (self->state, _ ("Checking for updates")); fiber_check_for_updates (self); finish_with_background_task_label (self); } } return g_steal_pointer (&read_future); } static DexFuture * open_appstream_fiber (OpenAppstreamData *data) { g_autoptr (BzApplication) self = NULL; char *id = data->id; bz_weak_get_or_return_reject (self, data->self); dex_await (dex_ref (self->ready_to_open_files), NULL); open_generic_id (self, id); return dex_future_new_true (); } static DexFuture * open_flatpakref_fiber (OpenFlatpakrefData *data) { g_autoptr (BzApplication) self = NULL; GFile *file = data->file; g_autoptr (GError) local_error = NULL; g_autoptr (DexFuture) future = NULL; GtkWindow *window = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, data->self); dex_await (dex_ref (self->ready_to_open_files), NULL); future = bz_backend_load_local_package (BZ_BACKEND (self->flatpak), file, NULL); dex_await (dex_ref (future), NULL); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); value = dex_future_get_value (future, &local_error); if (value != NULL) { if (G_VALUE_HOLDS_OBJECT (value)) { BzEntry *entry = NULL; entry = g_value_get_object (value); bz_window_show_entry (BZ_WINDOW (window), entry); } else open_generic_id (self, g_value_get_string (value)); } else bz_show_error_for_widget (GTK_WIDGET (window), local_error->message); return dex_future_new_true (); } static DexFuture * init_fiber_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, &local_error); if (value != NULL) { g_autoptr (DexFuture) sync_future = NULL; self->flatpak_notifs = bz_backend_create_notification_channel ( BZ_BACKEND (self->flatpak)); self->notif_watch = dex_future_then_loop ( dex_channel_receive (self->flatpak_notifs), (DexFutureCallback) watch_backend_notifs_then_loop_cb, bz_track_weak (self), bz_weak_release); sync_future = make_sync_future (self); sync_future = dex_future_finally ( sync_future, (DexFutureCallback) init_sync_finally, bz_track_weak (self), bz_weak_release); self->sync = g_steal_pointer (&sync_future); self->periodic_timeout_source = g_timeout_add_seconds ( /* Check every day */ 60 * 60 * 24, (GSourceFunc) periodic_timeout_cb, self); } else { GtkWindow *window = NULL; bz_state_info_set_online (self->state, FALSE); bz_state_info_set_busy (self->state, FALSE); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window != NULL) { g_autofree char *error_string = NULL; error_string = g_strdup_printf ( "Could not initialize: %s", local_error->message); bz_show_error_for_widget (GTK_WIDGET (window), error_string); } } return dex_future_new_true (); } static DexFuture * init_sync_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; bz_weak_get_or_return_reject (self, wr); bz_state_info_set_busy (self->state, FALSE); finish_with_background_task_label (self); return dex_future_new_true (); } static DexFuture * backend_sync_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; bz_weak_get_or_return_reject (self, wr); bz_state_info_set_online (self->state, dex_future_is_resolved (future)); bz_state_info_set_syncing (self->state, FALSE); bz_state_info_set_allow_manual_sync (self->state, TRUE); return dex_future_new_true (); } static DexFuture * flathub_update_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; bz_weak_get_or_return_reject (self, wr); if (dex_future_is_resolved (future)) { g_clear_object (&self->flathub); g_assert (self->tmp_flathub != NULL); self->flathub = g_steal_pointer (&self->tmp_flathub); bz_flathub_state_set_map_factory (self->flathub, self->application_factory); bz_state_info_set_flathub (self->state, self->flathub); return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) cache_flathub_fiber, bz_track_weak (self), bz_weak_release); } else { g_clear_object (&self->tmp_flathub); return dex_ref (future); } } static DexFuture * cache_write_back_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; bz_weak_get_or_return_reject (self, wr); gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_LESS_STRICT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_LESS_STRICT); return dex_future_new_true (); } static DexFuture * sync_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; bz_weak_get_or_return_reject (self, wr); dex_promise_resolve_boolean (self->ready_to_open_files, TRUE); return dex_future_new_true (); } static DexFuture * watch_backend_notifs_then_loop_cb (DexFuture *future, GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; g_autoptr (GError) local_error = NULL; const GValue *value = NULL; BzBackendNotification *notif = NULL; g_autoptr (RespondToFlatpakData) data = NULL; g_autoptr (DexFuture) ret_future = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); g_assert (value != NULL); notif = g_value_get_object (value); data = respond_to_flatpak_data_new (); data->self = bz_track_weak (self); data->notif = g_object_ref (notif); ret_future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) respond_to_flatpak_fiber, respond_to_flatpak_data_ref (data), respond_to_flatpak_data_unref); return g_steal_pointer (&ret_future); } static void fiber_replace_entry (BzApplication *self, BzEntry *entry) { const char *id = NULL; const char *unique_id = NULL; const char *unique_id_checksum = NULL; gboolean user = FALSE; gboolean installed = FALSE; const char *flatpak_id = NULL; const char *version = NULL; id = bz_entry_get_id (entry); unique_id = bz_entry_get_unique_id (entry); unique_id_checksum = bz_entry_get_unique_id_checksum (entry); if (id == NULL || unique_id == NULL || unique_id_checksum == NULL) return; user = bz_flatpak_entry_is_user (BZ_FLATPAK_ENTRY (entry)); installed = g_hash_table_contains (self->installed_set, unique_id); bz_entry_set_installed (entry, installed); version = g_hash_table_lookup (self->installed_set, unique_id); if (version != NULL && *version != '\0') bz_entry_set_installed_version (entry, version); flatpak_id = bz_flatpak_entry_get_flatpak_id (BZ_FLATPAK_ENTRY (entry)); if (flatpak_id != NULL) { GPtrArray *addons = NULL; addons = g_hash_table_lookup ( user ? self->usr_name_to_addons : self->sys_name_to_addons, flatpak_id); if (addons != NULL) { g_debug ("Appending %d addons to %s", addons->len, unique_id); for (guint i = 0; i < addons->len; i++) { const char *addon_id = NULL; addon_id = g_ptr_array_index (addons, i); bz_entry_append_addon (entry, addon_id); } g_hash_table_remove ( user ? self->usr_name_to_addons : self->sys_name_to_addons, flatpak_id); addons = NULL; } } if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) { BzEntryGroup *group = NULL; gboolean ignore_eol = FALSE; const char *runtime_name = NULL; BzEntry *eol_runtime = NULL; group = g_hash_table_lookup (self->ids_to_groups, id); if (self->ignore_eol_set != NULL) ignore_eol = g_hash_table_contains (self->ignore_eol_set, id); runtime_name = bz_flatpak_entry_get_application_runtime (BZ_FLATPAK_ENTRY (entry)); if (!ignore_eol && runtime_name != NULL) eol_runtime = g_hash_table_lookup (self->eol_runtimes, runtime_name); if (group != NULL) { bz_entry_group_add (group, entry, eol_runtime, ignore_eol); if (installed && !g_list_store_find (self->installed_apps, group, NULL)) g_list_store_insert_sorted ( self->installed_apps, group, (GCompareDataFunc) cmp_group, NULL); } else { g_autoptr (BzEntryGroup) new_group = NULL; g_debug ("Creating new application group for id %s", id); new_group = bz_entry_group_new (self->entry_factory); bz_entry_group_add (new_group, entry, eol_runtime, ignore_eol); g_list_store_append (self->groups, new_group); g_hash_table_replace (self->ids_to_groups, g_strdup (id), g_object_ref (new_group)); if (installed) g_list_store_insert_sorted ( self->installed_apps, new_group, (GCompareDataFunc) cmp_group, NULL); } } if (flatpak_id != NULL && bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_RUNTIME) && g_str_has_prefix (flatpak_id, "runtime/")) { const char *stripped = NULL; const char *eol = NULL; stripped = flatpak_id + strlen ("runtime/"); eol = bz_entry_get_eol (entry); if (eol != NULL) g_hash_table_replace ( self->eol_runtimes, g_strdup (stripped), g_object_ref (entry)); else g_hash_table_remove (self->eol_runtimes, stripped); } if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_ADDON) && strstr (id, ".Debug") == NULL && strstr (id, ".Locale") == NULL) { const char *extension_of_what = NULL; extension_of_what = bz_flatpak_entry_get_addon_extension_of_ref ( BZ_FLATPAK_ENTRY (entry)); if (extension_of_what != NULL) { GPtrArray *addons = NULL; /* BzFlatpakInstance ensures addons come before applications */ addons = g_hash_table_lookup ( user ? self->usr_name_to_addons : self->sys_name_to_addons, extension_of_what); if (addons == NULL) { addons = g_ptr_array_new_with_free_func (g_free); g_hash_table_replace ( user ? self->usr_name_to_addons : self->sys_name_to_addons, g_strdup (extension_of_what), addons); } g_ptr_array_add (addons, g_strdup (unique_id)); } else g_warning ("Entry with unique id %s is an addon but " "does not seem to extend anything", unique_id); } } static void fiber_check_for_updates (BzApplication *self) { g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) update_ids = NULL; GtkWindow *window = NULL; g_debug ("Checking for updates..."); bz_state_info_set_checking_for_updates (self->state, TRUE); update_ids = dex_await_boxed ( bz_backend_retrieve_update_ids (BZ_BACKEND (self->flatpak), NULL), &local_error); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (update_ids != NULL && update_ids->len > 0) { g_autoptr (GPtrArray) futures = NULL; g_autoptr (GListStore) store = NULL; futures = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < update_ids->len; i++) { const char *unique_id = NULL; unique_id = g_ptr_array_index (update_ids, i); g_ptr_array_add (futures, bz_entry_cache_manager_get (self->cache, unique_id)); } dex_await ( dex_future_allv ((DexFuture *const *) futures->pdata, futures->len), NULL); store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < futures->len; i++) { DexFuture *future = NULL; const GValue *value = NULL; future = g_ptr_array_index (futures, i); value = dex_future_get_value (future, &local_error); if (value != NULL) g_list_store_append (store, g_value_get_object (value)); else { const char *unique_id = NULL; unique_id = g_ptr_array_index (update_ids, i); g_warning ("%s could not be resolved for the update list and thus will not be included: %s", unique_id, local_error->message); g_clear_pointer (&local_error, g_error_free); } } if (g_list_model_get_n_items (G_LIST_MODEL (store)) > 0) bz_state_info_set_available_updates (self->state, G_LIST_MODEL (store)); } else if (local_error != NULL) { g_warning ("Failed to check for updates: %s", local_error->message); if (window != NULL) bz_show_error_for_widget (GTK_WIDGET (window), local_error->message); } bz_state_info_set_checking_for_updates (self->state, FALSE); } static GFile * fiber_dup_flathub_cache_file (char **path_out, GError **error) { gboolean result = FALSE; g_autofree char *module_dir = NULL; g_autoptr (GFile) module_dir_file = NULL; g_autofree char *path = NULL; g_autoptr (GFile) file = NULL; module_dir = bz_dup_module_dir (); module_dir_file = g_file_new_for_path (module_dir); result = dex_await ( dex_file_make_directory_with_parents ( module_dir_file), error); if (!result) return NULL; path = g_build_filename (module_dir, "flathub-cache", NULL); file = g_file_new_for_path (path); if (path_out != NULL) *path_out = g_steal_pointer (&path); return g_steal_pointer (&file); } static gboolean periodic_timeout_cb (BzApplication *self) { gboolean have_connection = FALSE; gboolean metered_connection = FALSE; if (self->sync != NULL && dex_future_is_pending (self->sync)) /* If for some reason the last update check is still happening, let it finish */ goto done; dex_clear (&self->sync); have_connection = bz_state_info_get_have_connection (self->state); metered_connection = bz_state_info_get_metered_connection (self->state); if (have_connection && !metered_connection) /* Do not do periodic sync on metered connections. The user will have to manually refresh instead. */ self->sync = make_sync_future (self); done: return G_SOURCE_CONTINUE; } static gboolean scheduled_timeout_cb (GWeakRef *wr) { g_autoptr (BzApplication) self = NULL; gboolean have_connection = FALSE; /* Use weak ref here since the source tag of this callback won't be tracked by the main application obj */ self = g_weak_ref_get (wr); if (self == NULL) goto done; dex_clear (&self->sync); have_connection = bz_state_info_get_have_connection (self->state); if (have_connection) self->sync = make_sync_future (self); done: return G_SOURCE_REMOVE; } static void network_status_changed (BzApplication *self, GParamSpec *pspec, GNetworkMonitor *network) { gboolean was_connected = FALSE; gboolean was_metered = FALSE; GNetworkConnectivity connectivity = 0; gboolean have_connection = FALSE; gboolean is_metered = FALSE; was_connected = bz_state_info_get_have_connection (self->state); was_metered = bz_state_info_get_metered_connection (self->state); connectivity = g_network_monitor_get_connectivity (network); have_connection = connectivity == G_NETWORK_CONNECTIVITY_FULL; is_metered = g_network_monitor_get_network_metered (network); if (!bz_state_info_get_busy (self->state) && ((!was_connected && have_connection && !is_metered) || (was_metered && !is_metered))) /* Wait a bit to prevent flakiness */ g_timeout_add_full ( G_PRIORITY_DEFAULT, 500, (GSourceFunc) scheduled_timeout_cb, bz_track_weak (self), bz_weak_release); bz_state_info_set_have_connection (self->state, have_connection); bz_state_info_set_metered_connection (self->state, is_metered); } static void disable_blocklists_changed (BzApplication *self, GParamSpec *pspec, BzStateInfo *state) { gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_DIFFERENT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_DIFFERENT); } static void show_hide_app_setting_changed (BzApplication *self, const char *key, GSettings *settings) { g_object_freeze_notify (G_OBJECT (self->state)); bz_state_info_set_hide_eol (self->state, g_settings_get_boolean (self->settings, "hide-eol")); bz_state_info_set_show_only_foss (self->state, g_settings_get_boolean (self->settings, "show-only-foss")); bz_state_info_set_show_only_flathub (self->state, g_settings_get_boolean (self->settings, "show-only-flathub")); bz_state_info_set_show_only_verified (self->state, g_settings_get_boolean (self->settings, "show-only-verified")); gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_DIFFERENT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_DIFFERENT); g_object_thaw_notify (G_OBJECT (self->state)); } static gboolean window_close_request (BzApplication *self, GtkWidget *window) { int width = 0; int height = 0; width = gtk_widget_get_width (window); height = gtk_widget_get_height (window); g_settings_set (self->settings, "window-dimensions", "(ii)", width, height); /* Do not stop other handlers from being invoked for the signal */ return FALSE; } static void blocklists_changed (BzApplication *self, guint position, guint removed, guint added, GListModel *model) { g_autoptr (GError) local_error = NULL; if (removed > 0) g_ptr_array_remove_range (self->blocklist_regexes, position, removed); for (guint i = 0; i < added; i++) { g_autoptr (BzRootBlocklist) root = NULL; g_autoptr (GPtrArray) regex_datas = NULL; GListModel *blocklists = NULL; root = g_list_model_get_item (model, position + i); regex_datas = g_ptr_array_new_with_free_func (blocklist_regex_data_unref); blocklists = bz_root_blocklist_get_blocklists (root); if (blocklists != NULL) { guint n_blocklists = 0; n_blocklists = g_list_model_get_n_items (blocklists); for (guint j = 0; j < n_blocklists; j++) { g_autoptr (BzBlocklist) blocklist = NULL; GListModel *conditions = NULL; GListModel *allow = NULL; GListModel *allow_regex = NULL; GListModel *block = NULL; GListModel *block_regex = NULL; g_autoptr (BlocklistRegexData) data = NULL; blocklist = g_list_model_get_item (blocklists, j); allow = bz_blocklist_get_allow (blocklist); allow_regex = bz_blocklist_get_allow_regex (blocklist); block = bz_blocklist_get_block (blocklist); block_regex = bz_blocklist_get_block_regex (blocklist); if (allow == NULL && allow_regex == NULL && block == NULL && block_regex == NULL) { g_warning ("Blocklist file has an empty blocklist, ignoring"); continue; } conditions = bz_blocklist_get_conditions (blocklist); if (conditions != NULL) { guint n_conditions = 0; gboolean ignore = FALSE; n_conditions = g_list_model_get_n_items (conditions); for (guint k = 0; k < n_conditions; k++) { gboolean condition_result = FALSE; g_autoptr (BzBlocklistCondition) condition = NULL; BzBlocklistConditionMatchEnvvar *match_envvar = NULL; BzBlocklistConditionMatchLocale *match_locale = NULL; BzBlocklistConditionPostProcessKind postprocess = BZ_BLOCKLIST_CONDITION_POST_PROCESS_KIND_IDENTITY; condition = g_list_model_get_item (conditions, k); match_envvar = bz_blocklist_condition_get_match_envvar (condition); match_locale = bz_blocklist_condition_get_match_locale (condition); postprocess = bz_blocklist_condition_get_post_process (condition); if (match_envvar == NULL && match_locale == NULL) { g_warning ("Blocklist file has an empty condition"); continue; } if (!condition_result && match_envvar != NULL) { const char *var = NULL; const char *regex = NULL; var = bz_blocklist_condition_match_envvar_get_var (match_envvar); regex = bz_blocklist_condition_match_envvar_get_regex (match_envvar); if (var != NULL && regex != NULL) { g_autoptr (GRegex) compiled = NULL; const char *value = NULL; compiled = g_regex_new ( regex, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED, &local_error); if (compiled == NULL) { g_warning ("Blocklist condition contains invalid regex: %s", local_error->message); g_clear_error (&local_error); continue; } value = g_getenv (var); if (value != NULL && g_regex_match ( compiled, value, G_REGEX_MATCH_ANCHORED, NULL)) condition_result = TRUE; if (postprocess == BZ_BLOCKLIST_CONDITION_POST_PROCESS_KIND_INVERT) condition_result = !condition_result; } else g_warning ("Blocklist file has a envvar condition " "missing a var and/or a regex pattern"); } if (!condition_result && match_locale != NULL) { const char *regex = NULL; regex = bz_blocklist_condition_match_locale_get_regex (match_locale); if (regex != NULL) { g_autoptr (GRegex) compiled = NULL; const char *const *locales = NULL; compiled = g_regex_new ( regex, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED, &local_error); if (compiled == NULL) { g_warning ("Blocklist condition contains invalid regex: %s", local_error->message); g_clear_error (&local_error); continue; } locales = g_get_language_names (); for (guint l = 0; locales[l] != NULL; l++) { if (g_regex_match ( compiled, locales[i], G_REGEX_MATCH_ANCHORED, NULL)) condition_result = TRUE; if (condition_result) break; } if (postprocess == BZ_BLOCKLIST_CONDITION_POST_PROCESS_KIND_INVERT) condition_result = !condition_result; } else g_warning ("Blocklist file has a match-locale " "condition missing a regex pattern"); } if (!condition_result) { ignore = TRUE; break; } } if (ignore) continue; } data = blocklist_regex_data_new (); data->priority = bz_blocklist_get_priority (blocklist); #define BUILD_REGEX(_name, _builder) \ if (_name != NULL) \ { \ guint _n_strings = 0; \ \ _n_strings = g_list_model_get_n_items (_name); \ for (guint _i = 0; _i < _n_strings; _i++) \ { \ g_autoptr (GtkStringObject) _object = NULL; \ const char *_string = NULL; \ g_autoptr (GRegex) _regex = NULL; \ \ _object = g_list_model_get_item (_name, _i); \ _string = gtk_string_object_get_string (_object); \ _regex = g_regex_new (_string, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &local_error); \ \ if (_regex != NULL) \ g_strv_builder_add (_builder, _string); \ else \ { \ g_warning ("Blocklist file has an invalid " \ "regular expression '%s': %s", \ _string, local_error->message); \ g_clear_error (&local_error); \ } \ } \ } #define BUILD_REGEX_ESCAPED(_name, _builder) \ if (_name != NULL) \ { \ guint _n_strings = 0; \ \ _n_strings = g_list_model_get_n_items (_name); \ for (guint _i = 0; _i < _n_strings; _i++) \ { \ g_autoptr (GtkStringObject) _object = NULL; \ const char *_string = NULL; \ \ _object = g_list_model_get_item (_name, _i); \ _string = gtk_string_object_get_string (_object); \ \ g_strv_builder_take (_builder, g_regex_escape_string (_string, -1)); \ } \ } #define GATHER(name) \ if (name != NULL || \ name##_regex != NULL) \ { \ g_autoptr (GStrvBuilder) _builder = NULL; \ g_auto (GStrv) _patterns = NULL; \ \ _builder = g_strv_builder_new (); \ \ BUILD_REGEX_ESCAPED (name, _builder) \ BUILD_REGEX (name##_regex, _builder) \ \ _patterns = g_strv_builder_end (_builder); \ if (_patterns != NULL) \ { \ g_autofree char *_joined = NULL; \ g_autofree char *_regex_string = NULL; \ \ _joined = g_strjoinv ("|", _patterns); \ _regex_string = g_strdup_printf ("^(%s)$", _joined); \ data->name = g_regex_new (_regex_string, G_REGEX_OPTIMIZE, \ G_REGEX_MATCH_DEFAULT, NULL); \ } \ } GATHER (allow); GATHER (block); #undef GATHER #undef BUILD_REGEX_ESCAPED #undef BUILD_REGEX if (data->allow != NULL || data->block != NULL) g_ptr_array_add (regex_datas, g_steal_pointer (&data)); } } g_ptr_array_insert (self->blocklist_regexes, position + i, g_steal_pointer (®ex_datas)); } gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_DIFFERENT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_DIFFERENT); } static void txt_blocklists_changed (BzApplication *self, guint position, guint removed, guint added, GListModel *model) { if (removed > 0) g_ptr_array_remove_range (self->txt_blocked_id_sets, position, removed); for (guint i = 0; i < added; i++) { g_autoptr (BzHashTableObject) obj = NULL; GHashTable *set = NULL; obj = g_list_model_get_item (model, position + i); set = bz_hash_table_object_get_hash_table (obj); g_ptr_array_insert (self->txt_blocked_id_sets, position + i, g_hash_table_ref (set)); } gtk_filter_changed (GTK_FILTER (self->group_filter), GTK_FILTER_CHANGE_DIFFERENT); gtk_filter_changed (GTK_FILTER (self->appid_filter), GTK_FILTER_CHANGE_DIFFERENT); } static void init_service_struct (BzApplication *self, GtkStringList *blocklists, GtkStringList *txt_blocklists, GtkStringList *curated_configs) { const char *app_id = NULL; #ifdef HARDCODED_MAIN_CONFIG g_autoptr (GError) local_error = NULL; g_autoptr (GFile) config_file = NULL; g_autoptr (GBytes) config_bytes = NULL; #endif GtkCustomFilter *filter = NULL; GNetworkMonitor *network = NULL; g_autoptr (BzAuthState) auth_state = NULL; g_type_ensure (BZ_TYPE_MAIN_CONFIG); #ifdef HARDCODED_MAIN_CONFIG config_file = g_file_new_for_path (HARDCODED_MAIN_CONFIG); config_bytes = g_file_load_bytes (config_file, NULL, NULL, &local_error); if (config_bytes != NULL) { g_autoptr (BzYamlParser) parser = NULL; g_autoptr (GHashTable) parse_results = NULL; parser = bz_yaml_parser_new_for_resource_schema ( "/io/github/kolunmi/Bazaar/main-config-schema.xml"); parse_results = bz_parser_process_bytes ( BZ_PARSER (parser), config_bytes, &local_error); if (parse_results != NULL) { GListModel *override_eol_markings = NULL; self->config = g_value_dup_object (g_hash_table_lookup (parse_results, "/")); override_eol_markings = bz_main_config_get_override_eol_markings (self->config); if (override_eol_markings != NULL) { guint n_appids = 0; self->ignore_eol_set = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_free); n_appids = g_list_model_get_n_items (override_eol_markings); for (guint i = 0; i < n_appids; i++) { g_autoptr (GtkStringObject) string = NULL; const char *value = NULL; string = g_list_model_get_item (override_eol_markings, i); value = gtk_string_object_get_string (string); g_hash_table_replace (self->ignore_eol_set, g_strdup (value), NULL); } } } else g_warning ("Could not load main config at %s: %s", HARDCODED_MAIN_CONFIG, local_error->message); } g_clear_error (&local_error); #endif self->init_timer = g_timer_new (); self->ready_to_open_files = dex_promise_new (); if (self->config != NULL && bz_main_config_get_yaml_blocklist_paths (self->config) != NULL) { GListModel *paths = NULL; guint n_paths = 0; paths = bz_main_config_get_yaml_blocklist_paths (self->config); n_paths = g_list_model_get_n_items (paths); for (guint i = 0; i < n_paths; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (paths, i); gtk_string_list_append (blocklists, gtk_string_object_get_string (string)); } } self->blocklists = g_object_ref (blocklists); self->blocklists_to_files = gtk_map_list_model_new ( NULL, (GtkMapListModelMapFunc) map_strings_to_files, NULL, NULL); gtk_map_list_model_set_model ( self->blocklists_to_files, G_LIST_MODEL (self->blocklists)); if (self->config != NULL && bz_main_config_get_txt_blocklist_paths (self->config) != NULL) { GListModel *paths = NULL; guint n_paths = 0; paths = bz_main_config_get_txt_blocklist_paths (self->config); n_paths = g_list_model_get_n_items (paths); for (guint i = 0; i < n_paths; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (paths, i); gtk_string_list_append (txt_blocklists, gtk_string_object_get_string (string)); } } self->txt_blocklists = g_object_ref (txt_blocklists); self->txt_blocklists_to_files = gtk_map_list_model_new ( NULL, (GtkMapListModelMapFunc) map_strings_to_files, NULL, NULL); gtk_map_list_model_set_model ( self->txt_blocklists_to_files, G_LIST_MODEL (self->txt_blocklists)); if (self->config != NULL && bz_main_config_get_curated_config_paths (self->config) != NULL) { GListModel *paths = NULL; guint n_paths = 0; paths = bz_main_config_get_curated_config_paths (self->config); n_paths = g_list_model_get_n_items (paths); for (guint i = 0; i < n_paths; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (paths, i); gtk_string_list_append (curated_configs, gtk_string_object_get_string (string)); } } self->curated_configs = g_object_ref (curated_configs); self->curated_configs_to_files = gtk_map_list_model_new ( NULL, (GtkMapListModelMapFunc) map_strings_to_files, NULL, NULL); gtk_map_list_model_set_model ( self->curated_configs_to_files, G_LIST_MODEL (self->curated_configs)); g_type_ensure (BZ_TYPE_ROOT_BLOCKLIST); g_type_ensure (BZ_TYPE_BLOCKLIST); g_type_ensure (BZ_TYPE_BLOCKLIST_CONDITION); self->blocklist_parser = bz_yaml_parser_new_for_resource_schema ( "/io/github/kolunmi/Bazaar/blocklist-schema.xml"); self->txt_blocklist_parser = bz_newline_parser_new ( TRUE, MAX_IDS_PER_BLOCKLIST); g_type_ensure (BZ_TYPE_ROOT_CURATED_CONFIG); g_type_ensure (BZ_TYPE_CURATED_ROW); g_type_ensure (BZ_TYPE_CURATED_SECTION); self->curated_parser = bz_yaml_parser_new_for_resource_schema ( "/io/github/kolunmi/Bazaar/curated-config-schema.xml"); self->cache = bz_entry_cache_manager_new (); self->state = bz_state_info_new (); bz_state_info_set_busy (self->state, TRUE); bz_state_info_set_donation_prompt_dismissed (self->state, TRUE); g_signal_connect_swapped ( self->state, "notify::disable-blocklists", G_CALLBACK (disable_blocklists_changed), self); auth_state = bz_auth_state_new (); bz_state_info_set_auth_state (self->state, auth_state); g_object_bind_property ( auth_state, "authenticated", g_action_map_lookup_action (G_ACTION_MAP (self), "flathub-login"), "enabled", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); network = g_network_monitor_get_default (); if (network != NULL) { GNetworkConnectivity connectivity = 0; gboolean metered = FALSE; connectivity = g_network_monitor_get_connectivity (network); bz_state_info_set_have_connection (self->state, connectivity == G_NETWORK_CONNECTIVITY_FULL); metered = g_network_monitor_get_network_metered (network); bz_state_info_set_metered_connection (self->state, metered); g_signal_connect_swapped (network, "notify", G_CALLBACK (network_status_changed), self); } else g_warning ("Unable to detect networking device! Continuing anyway..."); app_id = g_application_get_application_id (G_APPLICATION (self)); g_assert (app_id != NULL); g_debug ("Constructing gsettings for %s ...", app_id); self->settings = g_settings_new (app_id); bz_state_info_set_hide_eol ( self->state, g_settings_get_boolean (self->settings, "hide-eol")); g_signal_connect_swapped ( self->settings, "changed::hide-eol", G_CALLBACK (show_hide_app_setting_changed), self); bz_state_info_set_show_only_foss ( self->state, g_settings_get_boolean (self->settings, "show-only-foss")); g_signal_connect_swapped ( self->settings, "changed::show-only-foss", G_CALLBACK (show_hide_app_setting_changed), self); bz_state_info_set_show_only_flathub ( self->state, g_settings_get_boolean (self->settings, "show-only-flathub")); g_signal_connect_swapped ( self->settings, "changed::show-only-flathub", G_CALLBACK (show_hide_app_setting_changed), self); bz_state_info_set_show_only_verified ( self->state, g_settings_get_boolean (self->settings, "show-only-verified")); g_signal_connect_swapped ( self->settings, "changed::show-only-verified", G_CALLBACK (show_hide_app_setting_changed), self); self->blocklist_regexes = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_ptr_array_unref); self->blocklists_provider = bz_content_provider_new (); bz_content_provider_set_parser (self->blocklists_provider, BZ_PARSER (self->blocklist_parser)); bz_content_provider_set_input_files ( self->blocklists_provider, G_LIST_MODEL (self->blocklists_to_files)); g_signal_connect_swapped (self->blocklists_provider, "items-changed", G_CALLBACK (blocklists_changed), self); self->txt_blocked_id_sets = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_hash_table_unref); self->txt_blocklists_provider = bz_content_provider_new (); bz_content_provider_set_parser (self->txt_blocklists_provider, BZ_PARSER (self->txt_blocklist_parser)); bz_content_provider_set_input_files ( self->txt_blocklists_provider, G_LIST_MODEL (self->txt_blocklists_to_files)); g_signal_connect_swapped (self->txt_blocklists_provider, "items-changed", G_CALLBACK (txt_blocklists_changed), self); self->groups = g_list_store_new (BZ_TYPE_ENTRY_GROUP); self->installed_apps = g_list_store_new (BZ_TYPE_ENTRY_GROUP); self->ids_to_groups = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_object_unref); self->eol_runtimes = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_object_unref); self->sys_name_to_addons = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); self->usr_name_to_addons = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); self->entry_factory = bz_application_map_factory_new ( (GtkMapListModelMapFunc) map_ids_to_entries, self, NULL, NULL, NULL); filter = gtk_custom_filter_new ( (GtkCustomFilterFunc) filter_application_ids, self, NULL); self->appid_filter = g_object_ref_sink (g_steal_pointer (&filter)); self->application_factory = bz_application_map_factory_new ( (GtkMapListModelMapFunc) map_generic_ids_to_groups, self, NULL, NULL, GTK_FILTER (self->appid_filter)); filter = gtk_custom_filter_new ( (GtkCustomFilterFunc) filter_entry_groups, self, NULL); self->group_filter = g_object_ref_sink (g_steal_pointer (&filter)); self->group_filter_model = gtk_filter_list_model_new ( g_object_ref (G_LIST_MODEL (self->groups)), g_object_ref (GTK_FILTER (self->group_filter))); self->search_engine = bz_search_engine_new (); bz_search_engine_set_model (self->search_engine, G_LIST_MODEL (self->group_filter_model)); bz_gnome_shell_search_provider_set_engine (self->gs_search, self->search_engine); self->curated_provider = bz_content_provider_new (); bz_content_provider_set_input_files ( self->curated_provider, G_LIST_MODEL (self->curated_configs_to_files)); bz_content_provider_set_parser (self->curated_provider, BZ_PARSER (self->curated_parser)); self->transactions = bz_transaction_manager_new (); bz_transaction_manager_set_config (self->transactions, self->config); bz_state_info_set_all_entry_groups (self->state, G_LIST_MODEL (self->groups)); bz_state_info_set_all_installed_entry_groups (self->state, G_LIST_MODEL (self->installed_apps)); bz_state_info_set_application_factory (self->state, self->application_factory); bz_state_info_set_blocklists (self->state, G_LIST_MODEL (self->blocklists)); bz_state_info_set_blocklists_provider (self->state, self->blocklists_provider); bz_state_info_set_curated_configs (self->state, G_LIST_MODEL (self->curated_configs)); bz_state_info_set_curated_provider (self->state, self->curated_provider); bz_state_info_set_entry_factory (self->state, self->entry_factory); bz_state_info_set_main_config (self->state, self->config); bz_state_info_set_search_engine (self->state, self->search_engine); bz_state_info_set_settings (self->state, self->settings); bz_state_info_set_transaction_manager (self->state, self->transactions); bz_state_info_set_txt_blocklists (self->state, G_LIST_MODEL (self->txt_blocklists)); bz_state_info_set_txt_blocklists_provider (self->state, self->txt_blocklists_provider); g_object_bind_property ( self->state, "allow-manual-sync", g_action_map_lookup_action (G_ACTION_MAP (self), "sync-remotes"), "enabled", G_BINDING_SYNC_CREATE); gtk_style_context_add_provider_for_display ( gdk_display_get_default (), bz_get_pride_style_provider (), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } static GtkWindow * new_window (BzApplication *self) { BzWindow *window = NULL; g_autoptr (GtkWidget) main_window = NULL; int width = 0; int height = 0; window = bz_window_new (self->state); gtk_application_add_window (GTK_APPLICATION (self), GTK_WINDOW (window)); main_window = g_weak_ref_get (&self->main_window); if (main_window != NULL) { width = gtk_widget_get_width (main_window); height = gtk_widget_get_height (main_window); g_settings_set (self->settings, "window-dimensions", "(ii)", width, height); } else { g_settings_get (self->settings, "window-dimensions", "(ii)", &width, &height); g_signal_connect_object ( window, "close-request", G_CALLBACK (window_close_request), self, G_CONNECT_SWAPPED); g_weak_ref_init (&self->main_window, window); } gtk_window_set_default_size (GTK_WINDOW (window), width, height); gtk_window_present (GTK_WINDOW (window)); return GTK_WINDOW (window); } static void open_appstream_take (BzApplication *self, char *appstream) { const char *id = NULL; g_autoptr (OpenAppstreamData) data = NULL; g_info ("Loading appstream link %s...", appstream); if (g_str_has_prefix (appstream, "appstream://")) id = appstream + strlen ("appstream://"); else id = appstream + strlen ("appstream:"); data = open_appstream_data_new (); data->self = bz_track_weak (self); data->id = g_strdup (id); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) open_appstream_fiber, open_appstream_data_ref (data), open_appstream_data_unref)); g_free (appstream); } static void open_flatpakref_take (BzApplication *self, GFile *file) { g_autofree char *path = NULL; g_autoptr (OpenFlatpakrefData) data = NULL; path = g_file_get_path (file); g_info ("Loading flatpakref at %s...", path); data = open_flatpakref_data_new (); data->self = bz_track_weak (self); data->file = g_steal_pointer (&file); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) open_flatpakref_fiber, open_flatpakref_data_ref (data), open_flatpakref_data_unref)); } static void command_line_open_location (BzApplication *self, GApplicationCommandLine *cmdline, const char *location) { if (g_uri_is_valid (location, G_URI_FLAGS_NONE, NULL)) { if (g_str_has_prefix (location, "appstream:")) open_appstream_take (self, g_strdup (location)); else open_flatpakref_take (self, g_file_new_for_uri (location)); } else if (g_path_is_absolute (location)) open_flatpakref_take (self, g_file_new_for_path (location)); else { const char *cwd = NULL; cwd = g_application_command_line_get_cwd (cmdline); if (cwd != NULL) open_flatpakref_take (self, g_file_new_build_filename (cwd, location, NULL)); else open_flatpakref_take (self, g_file_new_for_path (location)); } } static void open_generic_id (BzApplication *self, const char *generic_id) { BzEntryGroup *group = NULL; GtkWindow *window = NULL; group = g_hash_table_lookup (self->ids_to_groups, generic_id); window = gtk_application_get_active_window (GTK_APPLICATION (self)); if (window == NULL) window = new_window (self); if (group != NULL) bz_window_show_group (BZ_WINDOW (window), group); else { g_autofree char *message = NULL; message = g_strdup_printf ("ID '%s' was not found", generic_id); bz_show_error_for_widget (GTK_WIDGET (window), message); } } static gpointer map_strings_to_files (GtkStringObject *string, gpointer data) { const char *path = NULL; GFile *result = NULL; path = gtk_string_object_get_string (string); result = g_file_new_for_path (path); g_object_unref (string); return result; } static gpointer map_generic_ids_to_groups (GtkStringObject *string, BzApplication *self) { BzEntryGroup *group = NULL; group = g_hash_table_lookup ( self->ids_to_groups, gtk_string_object_get_string (string)); g_object_unref (string); return bz_object_maybe_ref (group); } static gpointer map_ids_to_entries (GtkStringObject *string, BzApplication *self) { g_autoptr (GError) local_error = NULL; const char *id = NULL; g_autoptr (DexFuture) future = NULL; g_autoptr (BzResult) result = NULL; id = gtk_string_object_get_string (string); future = bz_entry_cache_manager_get (self->cache, id); result = bz_result_new (future); g_object_unref (string); return g_steal_pointer (&result); } static gboolean filter_application_ids (GtkStringObject *string, BzApplication *self) { BzEntryGroup *group = NULL; group = g_hash_table_lookup ( self->ids_to_groups, gtk_string_object_get_string (string)); if (group != NULL) return validate_group_for_ui (self, group); else return FALSE; } static gboolean filter_entry_groups (BzEntryGroup *group, BzApplication *self) { return validate_group_for_ui (self, group); } static gint cmp_group (BzEntryGroup *a, BzEntryGroup *b, gpointer user_data) { const char *title_a = NULL; const char *title_b = NULL; title_a = bz_entry_group_get_title (a); title_b = bz_entry_group_get_title (b); if (title_a == NULL) return 1; if (title_b == NULL) return -1; return strcasecmp (title_a, title_b); } static gint cmp_entry (BzEntry *a, BzEntry *b, gpointer user_data) { gboolean a_is_runtime = FALSE; gboolean b_is_runtime = FALSE; gboolean a_is_addon = FALSE; gboolean b_is_addon = FALSE; a_is_runtime = bz_entry_is_of_kinds (a, BZ_ENTRY_KIND_RUNTIME); b_is_runtime = bz_entry_is_of_kinds (b, BZ_ENTRY_KIND_RUNTIME); if (a_is_runtime && !b_is_runtime) return -1; if (!a_is_runtime && b_is_runtime) return 1; a_is_addon = bz_entry_is_of_kinds (a, BZ_ENTRY_KIND_ADDON); b_is_addon = bz_entry_is_of_kinds (b, BZ_ENTRY_KIND_ADDON); if (a_is_addon && !b_is_addon) return -1; if (!a_is_addon && b_is_addon) return 1; return 0; } static gboolean validate_group_for_ui (BzApplication *self, BzEntryGroup *group) { const char *id = NULL; int allowed_priority = G_MAXINT; int blocked_priority = G_MAXINT; if (bz_state_info_get_hide_eol (self->state) && bz_entry_group_get_eol (group) != NULL) return FALSE; if (bz_state_info_get_show_only_foss (self->state) && !bz_entry_group_get_is_floss (group)) return FALSE; if (bz_state_info_get_show_only_flathub (self->state) && !bz_entry_group_get_is_flathub (group)) return FALSE; if (bz_state_info_get_show_only_verified (self->state) && !bz_entry_group_get_is_verified (group)) return FALSE; if (bz_state_info_get_disable_blocklists (self->state)) return TRUE; id = bz_entry_group_get_id (group); for (guint i = 0; i < self->txt_blocked_id_sets->len; i++) { GHashTable *set = NULL; set = g_ptr_array_index (self->txt_blocked_id_sets, i); if (g_hash_table_contains (set, id)) return FALSE; } for (guint i = 0; i < self->blocklist_regexes->len; i++) { GPtrArray *regex_datas = NULL; regex_datas = g_ptr_array_index (self->blocklist_regexes, i); for (guint j = 0; j < regex_datas->len; j++) { BlocklistRegexData *data = NULL; data = g_ptr_array_index (regex_datas, j); if (data->allow != NULL && data->priority < allowed_priority && g_regex_match (data->allow, id, G_REGEX_MATCH_DEFAULT, NULL)) allowed_priority = data->priority; if (data->block != NULL && data->priority < blocked_priority && g_regex_match (data->block, id, G_REGEX_MATCH_DEFAULT, NULL)) blocked_priority = data->priority; } } return allowed_priority <= blocked_priority; } static DexFuture * make_sync_future (BzApplication *self) { g_autoptr (DexFuture) backend_future = NULL; g_autoptr (DexFuture) flathub_future = NULL; g_autoptr (DexFuture) ret_future = NULL; bz_state_info_set_allow_manual_sync (self->state, FALSE); bz_state_info_set_syncing (self->state, TRUE); backend_future = bz_backend_retrieve_remote_entries (BZ_BACKEND (self->flatpak), NULL); backend_future = dex_future_finally ( backend_future, (DexFutureCallback) backend_sync_finally, bz_track_weak (self), bz_weak_release); g_clear_object (&self->tmp_flathub); self->tmp_flathub = bz_flathub_state_new (); flathub_future = bz_flathub_state_update_to_today (self->tmp_flathub); flathub_future = dex_future_finally ( flathub_future, (DexFutureCallback) flathub_update_finally, bz_track_weak (self), bz_weak_release); ret_future = dex_future_all ( dex_ref (backend_future), dex_ref (flathub_future), NULL); ret_future = dex_future_then ( ret_future, (DexFutureCallback) sync_then, bz_track_weak (self), bz_weak_release); return g_steal_pointer (&ret_future); } static void finish_with_background_task_label (BzApplication *self) { if (self->n_notifications_incoming > 0) { g_autofree char *label = NULL; label = g_strdup_printf (_ ("Receiving %d entries..."), self->n_notifications_incoming); bz_state_info_set_background_task_label (self->state, label); } else if (bz_state_info_get_syncing (self->state)) bz_state_info_set_background_task_label (self->state, _ ("Synchronizing...")); else if (bz_state_info_get_busy (self->state)) bz_state_info_set_background_task_label (self->state, _ ("Indexing Data...")); else bz_state_info_set_background_task_label (self->state, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-application.h000066400000000000000000000020221514314607700207320ustar00rootroot00000000000000/* bz-application.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_APPLICATION (bz_application_get_type ()) G_DECLARE_FINAL_TYPE (BzApplication, bz_application, BZ, APPLICATION, AdwApplication) BzStateInfo * bz_state_info_get_default (void); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-apps-page.blp000066400000000000000000000104301514314607700206340ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAppsPage: Adw.NavigationPage { Adw.ToolbarView { [top] Adw.HeaderBar { [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: menu { section { item { label: _("_Donate to Bazaar ❤️"); action: "app.donate"; } } section { item { label: _("_Preferences"); action: "app.preferences"; } item { label: _("_Login with Flathub"); action: "app.flathub-login"; hidden-when: "action-disabled"; } item { label: _("_Manage Leftover User Data"); action: "window.user-data"; } item { label: _("_Synchronize Remotes"); action: "app.sync-remotes"; } item { label: _("_Keyboard Shortcuts"); action: "app.shortcuts"; } item { label: _("_About Bazaar"); action: "app.about"; } } section { item { label: _("_Quit Bazaar"); action: "app.quit"; } } }; } } content: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Gtk.ScrolledWindow { hscrollbar-policy: never; Adw.Clamp { maximum-size: 1500; tightening-threshold: 1400; Box content_box { orientation: vertical; spacing: 10; margin-start: 30; margin-end: 30; margin-top: 8; margin-bottom: 50; $BzFeaturedCarousel { margin-start: 3; margin-end: 3; hexpand: true; visible: bind $is_not_null(template.carousel-applications) as ; model: SliceListModel { offset: 0; size: 7; model: bind template.carousel-applications; }; group-clicked => $featured_carousel_group_clicked_cb(template); } Box { margin-start: 3; orientation: vertical; Label title { styles [ "title-1", ] label: bind template.page-title; xalign: 0.0; wrap: true; wrap-mode: word_char; } Label subtitle { visible: bind $is_not_empty_string(template.page-subtitle) as ; label: bind template.page-subtitle; margin-top: 4; xalign: 0.0; } $BzSubcategoryList { margin-top: 12; margin-bottom: 8; category: bind template.category; flathub-state: bind template.flathub-state; } } $BzDynamicListView list_view { styles [ "flathub-page-section", ] hexpand: true; scroll: false; valign: start; noscroll-kind: flow-box; child-type: "BzAppTile"; child-prop: "group"; model: bind template.applications; bind-widget => $bind_widget_cb(template); unbind-widget => $unbind_widget_cb(template); } Button { label: _("Show All"); visible: bind $is_not_empty_list(template.all-applications) as ; halign: center; margin-top: 8; clicked => $show_all_cb(template); styles ["pill"] } } } }; Adw.Breakpoint { condition ("max-width: 700px") setters { content_box.margin-start: 10; content_box.margin-end: 10; list_view.column-spacing: 3; list_view.row-spacing: 3; title.halign: center; title.justify: center; subtitle.halign: center; } } }; } } kolunmi-bazaar-7b9c8e1/src/bz-apps-page.c000066400000000000000000000404021514314607700203030ustar00rootroot00000000000000/* bz-apps-page.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include "bz-all-apps-page.h" #include "bz-app-tile.h" #include "bz-application.h" #include "bz-apps-page.h" #include "bz-dynamic-list-view.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-flathub-category.h" #include "bz-subcategory-list.h" #include "bz-state-info.h" struct _BzAppsPage { AdwNavigationPage parent_instance; char *title; GListModel *applications; GListModel *all_applications; GListModel *carousel_applications; char *subtitle; BzFlathubCategory *category; /* Template widgets */ }; G_DEFINE_FINAL_TYPE (BzAppsPage, bz_apps_page, ADW_TYPE_NAVIGATION_PAGE) enum { PROP_0, PROP_PAGE_TITLE, PROP_APPLICATIONS, PROP_ALL_APPLICATIONS, PROP_CAROUSEL_APPLICATIONS, PROP_PAGE_SUBTITLE, PROP_CATEGORY, PROP_FLATHUB_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SELECT, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void tile_clicked (BzEntryGroup *group, GtkButton *button); static void bz_apps_page_dispose (GObject *object) { BzAppsPage *self = BZ_APPS_PAGE (object); g_clear_pointer (&self->title, g_free); g_clear_object (&self->applications); g_clear_object (&self->all_applications); g_clear_object (&self->carousel_applications); g_clear_pointer (&self->subtitle, g_free); g_clear_object (&self->category); G_OBJECT_CLASS (bz_apps_page_parent_class)->dispose (object); } static void bz_apps_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAppsPage *self = BZ_APPS_PAGE (object); switch (prop_id) { case PROP_PAGE_TITLE: g_value_set_string (value, self->title); break; case PROP_APPLICATIONS: g_value_set_object (value, self->applications); break; case PROP_ALL_APPLICATIONS: g_value_set_object (value, self->all_applications); break; case PROP_CAROUSEL_APPLICATIONS: g_value_set_object (value, self->carousel_applications); break; case PROP_PAGE_SUBTITLE: g_value_set_string (value, self->subtitle); break; case PROP_CATEGORY: g_value_set_object (value, self->category); break; case PROP_FLATHUB_STATE: g_value_set_object (value, bz_state_info_get_flathub(bz_state_info_get_default ())); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_apps_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAppsPage *self = BZ_APPS_PAGE (object); switch (prop_id) { case PROP_PAGE_TITLE: g_clear_pointer (&self->title, g_free); self->title = g_value_dup_string (value); break; case PROP_APPLICATIONS: g_clear_object (&self->applications); self->applications = g_value_dup_object (value); break; case PROP_ALL_APPLICATIONS: g_clear_object (&self->all_applications); self->all_applications = g_value_dup_object (value); break; case PROP_CAROUSEL_APPLICATIONS: g_clear_object (&self->carousel_applications); self->carousel_applications = g_value_dup_object (value); break; case PROP_PAGE_SUBTITLE: g_clear_pointer (&self->subtitle, g_free); self->subtitle = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bind_widget_cb (BzAppsPage *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (tile_clicked), group); } static void unbind_widget_cb (BzAppsPage *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (tile, G_CALLBACK (tile_clicked), group); } static gboolean is_not_null (gpointer object, GObject *value) { return value != NULL; } static gboolean is_not_empty_string (gpointer object, const char *str) { return str != NULL && str[0] != '\0'; } static gboolean is_not_empty_list (gpointer object, GListModel *list) { return list != NULL && g_list_model_get_n_items (list) > 0; } static void featured_carousel_group_clicked_cb (BzAppsPage *self, BzEntryGroup *group, GtkWidget *carousel) { g_signal_emit (self, signals[SIGNAL_SELECT], 0, group); } static void all_apps_select_cb (BzAllAppsPage *all_page, BzEntryGroup *group, BzAppsPage *self) { g_signal_emit (self, signals[SIGNAL_SELECT], 0, group); } static void show_all_cb (BzAppsPage *self, GtkButton *button) { GtkWidget *nav_view = NULL; AdwNavigationPage *all_page = NULL; g_autofree char *all_title = NULL; guint n_items = 0; g_return_if_fail (BZ_IS_APPS_PAGE (self)); if (self->all_applications == NULL) return; n_items = g_list_model_get_n_items (self->all_applications); if (n_items == 0) return; nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); if (nav_view == NULL) return; all_title = g_strdup_printf (_("All \"%s\""), self->title); all_page = bz_all_apps_page_new (all_title, g_object_ref (self->all_applications)); if (all_page == NULL) return; g_signal_connect (all_page, "select", G_CALLBACK (all_apps_select_cb), self); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), all_page); } static void bz_apps_page_class_init (BzAppsPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_apps_page_dispose; object_class->get_property = bz_apps_page_get_property; object_class->set_property = bz_apps_page_set_property; props[PROP_PAGE_TITLE] = g_param_spec_string ( "page-title", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_APPLICATIONS] = g_param_spec_object ( "applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_ALL_APPLICATIONS] = g_param_spec_object ( "all-applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_CAROUSEL_APPLICATIONS] = g_param_spec_object ( "carousel-applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_PAGE_SUBTITLE] = g_param_spec_string ( "page-subtitle", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CATEGORY] = g_param_spec_object ( "category", NULL, NULL, BZ_TYPE_FLATHUB_CATEGORY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_FLATHUB_STATE] = g_param_spec_object ( "flathub-state", NULL, NULL, BZ_TYPE_FLATHUB_STATE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SELECT] = g_signal_new ( "select", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_SELECT], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); g_type_ensure (BZ_TYPE_APP_TILE); g_type_ensure (BZ_TYPE_SUBCATEGORY_LIST); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-apps-page.ui"); gtk_widget_class_bind_template_callback (widget_class, is_not_null); gtk_widget_class_bind_template_callback (widget_class, is_not_empty_string); gtk_widget_class_bind_template_callback (widget_class, is_not_empty_list); gtk_widget_class_bind_template_callback (widget_class, bind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, featured_carousel_group_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, show_all_cb); } static void bz_apps_page_init (BzAppsPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwNavigationPage * bz_apps_page_new (const char *title, GListModel *applications) { return bz_apps_page_new_with_carousel (title, applications, NULL); } AdwNavigationPage * bz_apps_page_new_with_carousel (const char *title, GListModel *applications, GListModel *carousel_applications) { BzAppsPage *apps_page = NULL; apps_page = g_object_new ( BZ_TYPE_APPS_PAGE, "page-title", title, "applications", applications, "carousel-applications", carousel_applications, NULL); adw_navigation_page_set_title (ADW_NAVIGATION_PAGE (apps_page), title); return ADW_NAVIGATION_PAGE (apps_page); } static gboolean filter_by_category (BzEntryGroup *group, const char *category_name) { GListModel *categories = NULL; guint n_items = 0; g_return_val_if_fail (BZ_IS_ENTRY_GROUP (group), FALSE); g_return_val_if_fail (category_name != NULL, FALSE); categories = bz_entry_group_get_categories (group); if (categories == NULL) return FALSE; n_items = g_list_model_get_n_items (categories); for (guint i = 0; i < n_items; i++) { g_autoptr (BzFlathubCategory) category = NULL; const char *name = NULL; category = g_list_model_get_item (categories, i); name = bz_flathub_category_get_name (category); if (g_strcmp0 (name, category_name) == 0) return TRUE; } return FALSE; } static DexFuture * filter_applications_fiber (BzAppsPage *self) { g_autoptr (GError) error = NULL; g_autoptr (GtkFilterListModel) filtered_model = NULL; GListModel *all_model = NULL; const char *category_name = NULL; BzStateInfo *state_info = NULL; state_info = bz_state_info_get_default (); if (state_info == NULL) return NULL; all_model = bz_state_info_get_all_entry_groups (state_info); if (all_model == NULL) return NULL; category_name = g_object_get_data (G_OBJECT (self), "category-name"); if (category_name == NULL) return NULL; filtered_model = gtk_filter_list_model_new ( g_object_ref (all_model), GTK_FILTER (gtk_custom_filter_new ( (GtkCustomFilterFunc) filter_by_category, g_strdup (category_name), g_free))); g_set_object (&self->all_applications, G_LIST_MODEL (filtered_model)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALL_APPLICATIONS]); return NULL; } static AdwNavigationPage * create_split_page (const char *title, GListModel *model, GListModel *carousel_model) { AdwNavigationPage *apps_page = NULL; guint n_items = g_list_model_get_n_items (model); if (n_items > 48) { g_autoptr (GListModel) limited_model = NULL; limited_model = G_LIST_MODEL (gtk_slice_list_model_new ( g_object_ref (model), 0, 48)); if (carousel_model != NULL && g_list_model_get_n_items (carousel_model) > 0) apps_page = bz_apps_page_new_with_carousel (title, limited_model, carousel_model); else apps_page = bz_apps_page_new (title, limited_model); if (g_set_object (&BZ_APPS_PAGE (apps_page)->all_applications, model)) g_object_notify_by_pspec (G_OBJECT (apps_page), props[PROP_ALL_APPLICATIONS]); } else { if (carousel_model != NULL && g_list_model_get_n_items (carousel_model) > 0) apps_page = bz_apps_page_new_with_carousel (title, model, carousel_model); else apps_page = bz_apps_page_new (title, model); } return apps_page; } static AdwNavigationPage * create_standard_page (const char *title, GListModel *model, GListModel *carousel_model) { if (carousel_model != NULL && g_list_model_get_n_items (carousel_model) > 0) return bz_apps_page_new_with_carousel (title, model, carousel_model); else return bz_apps_page_new (title, model); } static void setup_category_filter (AdwNavigationPage *apps_page, const char *category_name) { if (apps_page == NULL || category_name == NULL || g_strcmp0 (category_name, "adwaita") == 0) return; g_object_set_data_full (G_OBJECT (apps_page), "category-name", g_strdup (category_name), g_free); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) filter_applications_fiber, g_object_ref (apps_page), g_object_unref)); } AdwNavigationPage * bz_apps_page_new_from_category (BzFlathubCategory *category) { g_autoptr (GListModel) model = NULL; g_autoptr (GListModel) carousel_model = NULL; AdwNavigationPage *apps_page = NULL; const char *title = NULL; const char *category_name = NULL; g_autofree char *subtitle = NULL; int total_entries = 0; guint n_items = 0; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (category), NULL); model = bz_flathub_category_dup_applications (category); if (model == NULL) return NULL; title = bz_flathub_category_get_display_name (category); category_name = bz_flathub_category_get_name (category); n_items = g_list_model_get_n_items (model); carousel_model = bz_flathub_category_dup_quality_applications (category); total_entries = bz_flathub_category_get_total_entries (category); if (n_items > 48) apps_page = create_split_page (title, model, carousel_model); else apps_page = create_standard_page (title, model, carousel_model); if (total_entries > 0 && !bz_flathub_category_get_is_spotlight (category)) { subtitle = g_strdup_printf (_ ("%d Applications"), total_entries); bz_apps_page_set_subtitle (BZ_APPS_PAGE (apps_page), subtitle); } BZ_APPS_PAGE(apps_page)->category = g_object_ref (category); g_object_notify_by_pspec (G_OBJECT (apps_page), props[PROP_CATEGORY]); if (n_items <= 48) setup_category_filter (apps_page, category_name); return apps_page; } void bz_apps_page_set_subtitle (BzAppsPage *self, const char *subtitle) { g_return_if_fail (BZ_IS_APPS_PAGE (self)); if (g_strcmp0 (self->subtitle, subtitle) == 0) return; g_clear_pointer (&self->subtitle, g_free); if (subtitle != NULL) self->subtitle = g_strdup (subtitle); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PAGE_SUBTITLE]); } static void tile_clicked (BzEntryGroup *group, GtkButton *button) { GtkWidget *self = NULL; self = gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_APPS_PAGE); g_signal_emit (self, signals[SIGNAL_SELECT], 0, group); } kolunmi-bazaar-7b9c8e1/src/bz-apps-page.h000066400000000000000000000027251514314607700203160ustar00rootroot00000000000000/* bz-apps-page.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-flathub-category.h" G_BEGIN_DECLS #define BZ_TYPE_APPS_PAGE (bz_apps_page_get_type ()) G_DECLARE_FINAL_TYPE (BzAppsPage, bz_apps_page, BZ, APPS_PAGE, AdwNavigationPage) AdwNavigationPage * bz_apps_page_new (const char *title, GListModel *applications); AdwNavigationPage * bz_apps_page_new_with_carousel (const char *title, GListModel *applications, GListModel *carousel_applications); AdwNavigationPage * bz_apps_page_new_from_category (BzFlathubCategory *category); void bz_apps_page_set_subtitle (BzAppsPage *self, const char *subtitle); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-appstream-description-render.blp000066400000000000000000000004111514314607700245470ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzAppstreamDescriptionRender: Adw.Bin { child: Box { orientation: vertical; TextView text_view { editable: false; cursor-visible: false; wrap-mode: word_char; height-request: 25; } }; }kolunmi-bazaar-7b9c8e1/src/bz-appstream-description-render.c000066400000000000000000000335701514314607700242300ustar00rootroot00000000000000/* bz-appstream-description-render.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::APPSTREAM-DESCRIPTION-RENDER" #include "config.h" #include #include "bz-appstream-description-render.h" enum { NO_ELEMENT, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CODE, EMPHASIS, }; struct _BzAppstreamDescriptionRender { AdwBin parent_instance; char *appstream_description; /* Template widgets */ GtkTextView *text_view; }; G_DEFINE_FINAL_TYPE (BzAppstreamDescriptionRender, bz_appstream_description_render, ADW_TYPE_BIN); enum { PROP_0, PROP_APPSTREAM_DESCRIPTION, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void setup_text_tags (GtkTextBuffer *buffer); static void regenerate (BzAppstreamDescriptionRender *self); static void insert (GtkTextBuffer *buffer, GtkTextIter *iter, const char *text); static void compile (BzAppstreamDescriptionRender *self, XbNode *node, GtkTextBuffer *buffer, GtkTextIter *iter, int parent_kind, int idx, gboolean is_last_sibling); static char * normalize_whitespace (const char *text); static void bz_appstream_description_render_dispose (GObject *object) { BzAppstreamDescriptionRender *self = BZ_APPSTREAM_DESCRIPTION_RENDER (object); g_clear_pointer (&self->appstream_description, g_free); G_OBJECT_CLASS (bz_appstream_description_render_parent_class)->dispose (object); } static void bz_appstream_description_render_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAppstreamDescriptionRender *self = BZ_APPSTREAM_DESCRIPTION_RENDER (object); switch (prop_id) { case PROP_APPSTREAM_DESCRIPTION: g_value_set_string (value, bz_appstream_description_render_get_appstream_description (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_appstream_description_render_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzAppstreamDescriptionRender *self = BZ_APPSTREAM_DESCRIPTION_RENDER (object); switch (prop_id) { case PROP_APPSTREAM_DESCRIPTION: bz_appstream_description_render_set_appstream_description (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_appstream_description_render_class_init (BzAppstreamDescriptionRenderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_appstream_description_render_set_property; object_class->get_property = bz_appstream_description_render_get_property; object_class->dispose = bz_appstream_description_render_dispose; props[PROP_APPSTREAM_DESCRIPTION] = g_param_spec_string ( "appstream-description", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-appstream-description-render.ui"); gtk_widget_class_bind_template_child (widget_class, BzAppstreamDescriptionRender, text_view); } static void setup_text_tags (GtkTextBuffer *buffer) { gtk_text_buffer_create_tag (buffer, "code", "family", "monospace", NULL); gtk_text_buffer_create_tag (buffer, "emphasis", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_create_tag (buffer, "paragraph", "pixels-below-lines", 12, NULL); gtk_text_buffer_create_tag (buffer, "list-item-ul", "left-margin", 10, "pixels-below-lines", 4, "indent", -12, NULL); gtk_text_buffer_create_tag (buffer, "list-item-ol", "left-margin", 10, "pixels-below-lines", 4, "indent", -18, NULL); gtk_text_buffer_create_tag (buffer, "list-number", "family", "monospace", "foreground", "gray", NULL); } static void bz_appstream_description_render_init (BzAppstreamDescriptionRender *self) { GtkTextBuffer *buffer = NULL; gtk_widget_init_template (GTK_WIDGET (self)); buffer = gtk_text_view_get_buffer (self->text_view); setup_text_tags (buffer); gtk_widget_remove_css_class (GTK_WIDGET (self->text_view), "view"); } BzAppstreamDescriptionRender * bz_appstream_description_render_new (void) { return g_object_new (BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER, NULL); } const char * bz_appstream_description_render_get_appstream_description (BzAppstreamDescriptionRender *self) { g_return_val_if_fail (BZ_IS_APPSTREAM_DESCRIPTION_RENDER (self), NULL); return self->appstream_description; } void bz_appstream_description_render_set_appstream_description (BzAppstreamDescriptionRender *self, const char *appstream_description) { g_return_if_fail (BZ_IS_APPSTREAM_DESCRIPTION_RENDER (self)); g_clear_pointer (&self->appstream_description, g_free); if (appstream_description != NULL) self->appstream_description = g_strdup (appstream_description); regenerate (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APPSTREAM_DESCRIPTION]); } static void regenerate (BzAppstreamDescriptionRender *self) { g_autoptr (GError) local_error = NULL; g_autoptr (XbSilo) silo = NULL; g_autoptr (XbNode) root = NULL; GtkTextBuffer *buffer = NULL; GtkTextIter iter = { 0 }; int node_count = 0; buffer = gtk_text_view_get_buffer (self->text_view); gtk_text_buffer_set_text (buffer, "", 0); if (self->appstream_description == NULL) return; silo = xb_silo_new_from_xml (self->appstream_description, &local_error); if (silo == NULL) { g_warning ("Failed to parse appstream description XML: %s", local_error->message); return; } gtk_text_buffer_get_end_iter (buffer, &iter); root = xb_silo_get_root (silo); for (XbNode *n = g_object_ref (root); n != NULL;) { XbNode *last = NULL; node_count++; last = n; n = xb_node_get_next (n); g_object_unref (last); } for (int i = 0; root != NULL; i++) { g_autoptr (XbNode) next = NULL; gboolean is_last = (i == node_count - 1); compile (self, root, buffer, &iter, NO_ELEMENT, i, is_last); next = xb_node_get_next (root); g_object_unref (root); root = g_steal_pointer (&next); } } static void insert (GtkTextBuffer *buffer, GtkTextIter *iter, const char *text) { g_auto (GStrv) parts = NULL; parts = g_strsplit (text, "**", -1); for (int j = 0; parts[j] != NULL; j++) { if (j % 2 == 0) { gtk_text_buffer_insert (buffer, iter, parts[j], -1); } else { GtkTextMark *m = NULL; GtkTextIter si = { 0 }; m = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); gtk_text_buffer_insert (buffer, iter, parts[j], -1); gtk_text_buffer_get_iter_at_mark (buffer, &si, m); gtk_text_buffer_apply_tag_by_name (buffer, "emphasis", &si, iter); gtk_text_buffer_delete_mark (buffer, m); } } } static void compile (BzAppstreamDescriptionRender *self, XbNode *node, GtkTextBuffer *buffer, GtkTextIter *iter, int parent_kind, int idx, gboolean is_last_sibling) { const char *element = NULL; const char *text = NULL; XbNode *child = NULL; int kind = NO_ELEMENT; GtkTextMark *start_mark = NULL; int child_count= 0; element = xb_node_get_element (node); text = xb_node_get_text (node); child = xb_node_get_child (node); kind = NO_ELEMENT; start_mark = NULL; if (element != NULL) { if (g_strcmp0 (element, "p") == 0) { kind = PARAGRAPH; start_mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); } else if (g_strcmp0 (element, "ol") == 0) kind = ORDERED_LIST; else if (g_strcmp0 (element, "ul") == 0) kind = UNORDERED_LIST; else if (g_strcmp0 (element, "li") == 0) { kind = LIST_ITEM; start_mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); if (parent_kind == ORDERED_LIST) { g_autofree char *prefix = NULL; GtkTextMark *prefix_start_mark; GtkTextIter prefix_start_iter; prefix_start_mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); prefix = g_strdup_printf ("%d.", idx + 1); gtk_text_buffer_insert (buffer, iter, prefix, -1); gtk_text_buffer_get_iter_at_mark (buffer, &prefix_start_iter, prefix_start_mark); gtk_text_buffer_apply_tag_by_name (buffer, "list-number", &prefix_start_iter, iter); gtk_text_buffer_delete_mark (buffer, prefix_start_mark); } else gtk_text_buffer_insert (buffer, iter, "• ", -1); } else if (g_strcmp0 (element, "code") == 0) { kind = CODE; start_mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); } else if (g_strcmp0 (element, "em") == 0) { kind = EMPHASIS; start_mark = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); } } if (text != NULL) { g_autofree char *normalized = NULL; normalized = normalize_whitespace (text); if (normalized != NULL && *normalized != '\0') insert (buffer, iter, normalized); } for (int i = 0; child != NULL; i++) { const char *tail = NULL; XbNode *next = NULL; next = xb_node_get_next (child); compile (self, child, buffer, iter, kind, i, next == NULL); tail = xb_node_get_tail (child); if (tail != NULL) { g_autofree char *normalized = NULL; normalized = normalize_whitespace (tail); if (normalized != NULL && *normalized != '\0') insert (buffer, iter, normalized); } g_object_unref (child); child = next; child_count++; } if (start_mark != NULL) { GtkTextIter start_iter = { 0 }; gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, start_mark); if (kind == CODE) gtk_text_buffer_apply_tag_by_name (buffer, "code", &start_iter, iter); else if (kind == EMPHASIS) gtk_text_buffer_apply_tag_by_name (buffer, "emphasis", &start_iter, iter); else if (kind == PARAGRAPH) gtk_text_buffer_apply_tag_by_name (buffer, "paragraph", &start_iter, iter); else if (kind == LIST_ITEM) { const char *tag_name = NULL; tag_name = (parent_kind == ORDERED_LIST) ? "list-item-ol" : "list-item-ul"; gtk_text_buffer_apply_tag_by_name (buffer, tag_name, &start_iter, iter); gtk_text_buffer_insert (buffer, iter, "\n", 1); } gtk_text_buffer_delete_mark (buffer, start_mark); } if (kind == PARAGRAPH && !is_last_sibling) gtk_text_buffer_insert (buffer, iter, "\n", 1); else if ((kind == ORDERED_LIST || kind == UNORDERED_LIST) && !is_last_sibling && child_count > 0) gtk_text_buffer_insert (buffer, iter, "\n", 1); } static char * normalize_whitespace (const char *text) { GString *result = NULL; gboolean in_space = FALSE; gboolean at_start = TRUE; if (text == NULL) return NULL; result = g_string_new (NULL); for (const char *p = text; p != NULL && *p != '\0'; p = g_utf8_next_char (p)) { gunichar ch = 0; ch = g_utf8_get_char (p); if (g_unichar_isspace (ch)) { if (!at_start && !in_space) { g_string_append_c (result, ' '); in_space = TRUE; } } else { g_string_append_unichar (result, ch); in_space = FALSE; at_start = FALSE; } } if (result->len > 0 && result->str[result->len - 1] == ' ') g_string_truncate (result, result->len - 1); return g_string_free (result, FALSE); } /* End of bz-appstream-description-render.c */ kolunmi-bazaar-7b9c8e1/src/bz-appstream-description-render.h000066400000000000000000000027411514314607700242310ustar00rootroot00000000000000/* bz-appstream-description-render.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER (bz_appstream_description_render_get_type ()) G_DECLARE_FINAL_TYPE (BzAppstreamDescriptionRender, bz_appstream_description_render, BZ, APPSTREAM_DESCRIPTION_RENDER, AdwBin) BzAppstreamDescriptionRender * bz_appstream_description_render_new (void); const char * bz_appstream_description_render_get_appstream_description (BzAppstreamDescriptionRender *self); void bz_appstream_description_render_set_appstream_description (BzAppstreamDescriptionRender *self, const char *appstream_description); G_END_DECLS /* End of bz-appstream-description-render.h */ kolunmi-bazaar-7b9c8e1/src/bz-appstream-parser.c000066400000000000000000000625011514314607700217200ustar00rootroot00000000000000/* bz-appstream-parser.c */ #define G_LOG_DOMAIN "BAZAAR::APPSTREAM-PARSER" #define BAZAAR_MODULE "appstream-parser" #include "config.h" #include #include "bz-appstream-parser.h" #include "bz-async-texture.h" #include "bz-flathub-category.h" #include "bz-io.h" #include "bz-release.h" #include "bz-url.h" #include "bz-verification-status.h" static guint parse_control_value (const char *value) { if (g_strcmp0 (value, "pointing") == 0) return BZ_CONTROL_POINTING; else if (g_strcmp0 (value, "keyboard") == 0) return BZ_CONTROL_KEYBOARD; else if (g_strcmp0 (value, "console") == 0) return BZ_CONTROL_CONSOLE; else if (g_strcmp0 (value, "tablet") == 0) return BZ_CONTROL_TABLET; else if (g_strcmp0 (value, "touch") == 0) return BZ_CONTROL_TOUCH; else if (g_strcmp0 (value, "gamepad") == 0) return BZ_CONTROL_GAMEPAD; else if (g_strcmp0 (value, "tv-remote") == 0) return BZ_CONTROL_TV_REMOTE; else if (g_strcmp0 (value, "voice") == 0) return BZ_CONTROL_VOICE; else if (g_strcmp0 (value, "vision") == 0) return BZ_CONTROL_VISION; else return 0; } static gboolean calculate_is_mobile_friendly (guint required_controls, guint supported_controls, gint min_display_length, gint max_display_length) { return (supported_controls & BZ_CONTROL_TOUCH) != 0; } static GdkPaintable * find_screenshot (GPtrArray *images, const char *caption, gboolean match_highest, guint target_width, guint target_height, gboolean require_flathub, const char *module_dir, const char *unique_id_checksum, const char *cache_filename, char **out_caption) { const char *best_url = NULL; gint best_diff = G_MAXINT; guint best_res = 0; guint target_pixels = target_width * target_height; if (images == NULL) return NULL; for (guint j = 0; j < images->len; j++) { AsImage *image_obj = g_ptr_array_index (images, j); const char *url = as_image_get_url (image_obj); guint width = as_image_get_width (image_obj); guint height = as_image_get_height (image_obj); guint pixels = width * height; if (url == NULL) continue; if (require_flathub && !g_str_has_prefix (url, "https://dl.flathub.org/")) continue; if (match_highest) { if (pixels > best_res) { best_url = url; best_res = pixels; } } else { gint diff = ABS ((gint) pixels - (gint) target_pixels); if (diff < best_diff) { best_url = url; best_diff = diff; } } } if (best_url != NULL) { g_autoptr (GFile) screenshot_file = NULL; g_autoptr (GFile) cache_file = NULL; BzAsyncTexture *texture = NULL; screenshot_file = g_file_new_for_uri (best_url); cache_file = g_file_new_build_filename ( module_dir, unique_id_checksum, cache_filename, NULL); texture = bz_async_texture_new_lazy (screenshot_file, cache_file); if (out_caption != NULL) *out_caption = g_strdup (caption ? caption : ""); return GDK_PAINTABLE (texture); } return NULL; } gboolean bz_appstream_parser_populate_entry (BzEntry *entry, AsComponent *component, const char *appstream_dir, const char *remote_name, const char *module_dir, const char *unique_id_checksum, const char *id, guint kinds, GError **error) { AsDeveloper *developer_obj = NULL; GPtrArray *screenshots = NULL; AsReleaseList *releases = NULL; GPtrArray *releases_arr = NULL; GPtrArray *icons = NULL; AsBranding *branding = NULL; GPtrArray *requires_relations = NULL; GPtrArray *recommends_relations = NULL; GPtrArray *supports_relations = NULL; const char *title = NULL; const char *description = NULL; const char *metadata_license = NULL; const char *project_license = NULL; gboolean is_floss = FALSE; const char *project_group = NULL; const char *developer = NULL; const char *developer_id = NULL; const char *long_description = NULL; const char *project_url = NULL; g_autoptr (GPtrArray) as_search_tokens = NULL; g_autofree char *search_tokens = NULL; g_autoptr (GdkPaintable) icon_paintable = NULL; g_autoptr (GIcon) mini_icon = NULL; g_autoptr (GListStore) screenshot_paintables = NULL; g_autoptr (GListStore) screenshot_captions = NULL; g_autoptr (GdkPaintable) thumbnail_paintable = NULL; g_autoptr (GListStore) share_urls = NULL; g_autofree char *donation_url = NULL; g_autofree char *forge_url = NULL; g_autoptr (GListStore) native_reviews = NULL; double average_rating = 0.0; g_autofree char *ratings_summary = NULL; g_autoptr (GListStore) version_history = NULL; const char *accent_color_light = NULL; const char *accent_color_dark = NULL; guint required_controls = 0; guint recommended_controls = 0; guint supported_controls = 0; gint min_display_length = 0; gint max_display_length = 0; gboolean is_mobile_friendly = FALSE; g_autoptr (AsContentRating) content_rating = NULL; GPtrArray *as_keywords = NULL; g_autoptr (GListStore) keywords = NULL; GPtrArray *as_categories = NULL; g_autoptr (GListModel) categories = NULL; g_autoptr (BzVerificationStatus) verification_status = NULL; g_return_val_if_fail (BZ_IS_ENTRY (entry), FALSE); g_return_val_if_fail (AS_IS_COMPONENT (component), FALSE); title = as_component_get_name (component); if (title == NULL) title = as_component_get_id (component); description = as_component_get_summary (component); metadata_license = as_component_get_metadata_license (component); project_license = as_component_get_project_license (component); is_floss = as_component_is_floss (component); project_group = as_component_get_project_group (component); project_url = as_component_get_url (component, AS_URL_KIND_HOMEPAGE); as_search_tokens = as_component_get_search_tokens (component); developer_obj = as_component_get_developer (component); if (developer_obj != NULL) { developer = as_developer_get_name (developer_obj); developer_id = as_developer_get_id (developer_obj); } long_description = as_component_get_description (component); screenshots = as_component_get_screenshots_all (component); if (screenshots != NULL) { screenshot_paintables = g_list_store_new (BZ_TYPE_ASYNC_TEXTURE); screenshot_captions = g_list_store_new (GTK_TYPE_STRING_OBJECT); for (guint i = 0; i < screenshots->len; i++) { AsScreenshot *screenshot = NULL; GPtrArray *images = NULL; const gchar *caption = NULL; g_autofree char *caption_str = NULL; g_autoptr (GdkPaintable) paintable = NULL; g_autofree char *cache_name = NULL; screenshot = g_ptr_array_index (screenshots, i); images = as_screenshot_get_images_all (screenshot); caption = as_screenshot_get_caption (screenshot); if (i == 0 && thumbnail_paintable == NULL) { thumbnail_paintable = find_screenshot (images, caption, FALSE, 400, 300, TRUE, module_dir, unique_id_checksum, "thumbnail.png", NULL); if (thumbnail_paintable == NULL) thumbnail_paintable = find_screenshot (images, caption, FALSE, 400, 300, FALSE, module_dir, unique_id_checksum, "thumbnail.png", NULL); } cache_name = g_strdup_printf ("screenshot_%u.png", i); paintable = find_screenshot (images, caption, TRUE, 0, 0, TRUE, module_dir, unique_id_checksum, cache_name, &caption_str); if (paintable == NULL) paintable = find_screenshot (images, caption, TRUE, 0, 0, FALSE, module_dir, unique_id_checksum, cache_name, &caption_str); if (paintable != NULL) { g_autoptr (GtkStringObject) caption_obj = NULL; g_list_store_append (screenshot_paintables, paintable); caption_obj = gtk_string_object_new (caption_str); g_list_store_append (screenshot_captions, caption_obj); } } } share_urls = g_list_store_new (BZ_TYPE_URL); if (kinds & BZ_ENTRY_KIND_APPLICATION && g_strcmp0 (remote_name, "flathub") == 0) { g_autofree char *flathub_url = NULL; g_autoptr (BzUrl) url = NULL; flathub_url = g_strdup_printf ("https://flathub.org/apps/%s", id); url = bz_url_new (); bz_url_set_name (url, C_ ("Project URL Type", "Flathub Page")); bz_url_set_url (url, flathub_url); bz_url_set_icon_name (url, "flathub-symbolic"); g_list_store_append (share_urls, url); } for (int e = AS_URL_KIND_UNKNOWN + 1; e < AS_URL_KIND_LAST; e++) { const char *url = NULL; url = as_component_get_url (component, e); if (url != NULL) { const char *enum_string = NULL; const char *icon_name = NULL; g_autoptr (BzUrl) share_url = NULL; switch (e) { case AS_URL_KIND_HOMEPAGE: enum_string = C_ ("Project URL Type", "Project Website"); icon_name = "globe-symbolic"; break; case AS_URL_KIND_BUGTRACKER: enum_string = C_ ("Project URL Type", "Issue Tracker"); icon_name = "computer-fail-symbolic"; break; case AS_URL_KIND_FAQ: enum_string = C_ ("Project URL Type", "FAQ"); icon_name = "help-faq-symbolic"; break; case AS_URL_KIND_HELP: enum_string = C_ ("Project URL Type", "Help"); icon_name = "help-browser-symbolic"; break; case AS_URL_KIND_DONATION: enum_string = C_ ("Project URL Type", "Donate"); icon_name = "heart-filled-symbolic"; g_clear_pointer (&donation_url, g_free); donation_url = g_strdup (url); break; case AS_URL_KIND_TRANSLATE: enum_string = C_ ("Project URL Type", "Translate"); icon_name = "translations-symbolic"; break; case AS_URL_KIND_CONTACT: enum_string = C_ ("Project URL Type", "Contact"); icon_name = "mail-send-symbolic"; break; case AS_URL_KIND_VCS_BROWSER: enum_string = C_ ("Project URL Type", "Source Code"); icon_name = "code-symbolic"; g_clear_pointer (&forge_url, g_free); forge_url = g_strdup (url); break; case AS_URL_KIND_CONTRIBUTE: enum_string = C_ ("Project URL Type", "Contribute"); icon_name = "system-users-symbolic"; break; default: break; } share_url = g_object_new ( BZ_TYPE_URL, "name", enum_string, "url", url, "icon-name", icon_name, NULL); g_list_store_append (share_urls, share_url); } } if (g_list_model_get_n_items (G_LIST_MODEL (share_urls)) == 0) g_clear_object (&share_urls); releases = as_component_load_releases (component, TRUE, error); if (releases == NULL) return FALSE; releases_arr = as_release_list_get_entries (releases); if (releases_arr != NULL) { version_history = g_list_store_new (BZ_TYPE_RELEASE); for (guint i = 0; i < releases_arr->len; i++) { AsRelease *as_release = NULL; const char *release_description = NULL; g_autoptr (BzRelease) release = NULL; as_release = g_ptr_array_index (releases_arr, i); release_description = as_release_get_description (as_release); release = g_object_new ( BZ_TYPE_RELEASE, "description", release_description, "timestamp", as_release_get_timestamp (as_release), "url", as_release_get_url (as_release, AS_RELEASE_URL_KIND_DETAILS), "version", as_release_get_version (as_release), NULL); g_list_store_append (version_history, release); } } icons = as_component_get_icons (component); if (icons != NULL) { g_autofree char *select = NULL; gboolean select_is_local = FALSE; int select_width = 0; int select_height = 0; for (guint i = 0; i < icons->len; i++) { AsIcon *icon = NULL; int width = 0; int height = 0; gboolean is_local = FALSE; icon = g_ptr_array_index (icons, i); width = as_icon_get_width (icon); height = as_icon_get_height (icon); is_local = as_icon_get_kind (icon) != AS_ICON_KIND_REMOTE; if (select == NULL || (is_local && !select_is_local) || (width > select_width && height > select_height)) { if (is_local) { const char *filename = NULL; g_autofree char *resolution = NULL; g_autofree char *path = NULL; filename = as_icon_get_filename (icon); if (filename == NULL) continue; resolution = g_strdup_printf ("%dx%d", width, height); path = g_build_filename ( appstream_dir, "icons", "flatpak", resolution, filename, NULL); if (!g_file_test (path, G_FILE_TEST_EXISTS)) continue; g_clear_pointer (&select, g_free); select = g_steal_pointer (&path); select_is_local = TRUE; select_width = width; select_height = height; } else { const char *url = NULL; url = as_icon_get_url (icon); if (url == NULL) continue; g_clear_pointer (&select, g_free); select = g_strdup (url); select_is_local = FALSE; select_width = width; select_height = height; } } } if (select != NULL) { g_autofree char *select_uri = NULL; g_autoptr (GFile) source = NULL; g_autoptr (GFile) cache_into = NULL; BzAsyncTexture *texture = NULL; if (select_is_local) select_uri = g_strdup_printf ("file://%s", select); else select_uri = g_steal_pointer (&select); source = g_file_new_for_uri (select_uri); cache_into = g_file_new_build_filename ( module_dir, unique_id_checksum, "icon-paintable.png", NULL); texture = bz_async_texture_new_lazy (source, cache_into); icon_paintable = GDK_PAINTABLE (texture); if (select_is_local) mini_icon = bz_load_mini_icon_sync (unique_id_checksum, select); } } branding = as_component_get_branding (component); if (branding != NULL) { accent_color_light = as_branding_get_color ( branding, AS_COLOR_KIND_PRIMARY, AS_COLOR_SCHEME_KIND_LIGHT); accent_color_dark = as_branding_get_color ( branding, AS_COLOR_KIND_PRIMARY, AS_COLOR_SCHEME_KIND_DARK); } content_rating = as_component_get_content_rating (component, "oars-1.1"); if (content_rating != NULL) { g_object_ref (content_rating); } else { content_rating = as_component_get_content_rating (component, "oars-1.0"); if (content_rating != NULL) g_object_ref (content_rating); } requires_relations = as_component_get_requires (component); recommends_relations = as_component_get_recommends (component); supports_relations = as_component_get_supports (component); if (requires_relations != NULL) { for (guint i = 0; i < requires_relations->len; i++) { AsRelation *relation = g_ptr_array_index (requires_relations, i); AsRelationItemKind item_kind = as_relation_get_item_kind (relation); if (item_kind == AS_RELATION_ITEM_KIND_CONTROL) { AsControlKind control_kind = as_relation_get_value_control_kind (relation); const char *control_str = as_control_kind_to_string (control_kind); if (control_str != NULL) required_controls |= parse_control_value (control_str); } else if (item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { AsRelationCompare compare = as_relation_get_compare (relation); gint value = as_relation_get_value_int (relation); if (compare == AS_RELATION_COMPARE_GE) min_display_length = value; } } } if (recommends_relations != NULL) { for (guint i = 0; i < recommends_relations->len; i++) { AsRelation *relation = g_ptr_array_index (recommends_relations, i); AsRelationItemKind item_kind = as_relation_get_item_kind (relation); if (item_kind == AS_RELATION_ITEM_KIND_CONTROL) { AsControlKind control_kind = as_relation_get_value_control_kind (relation); const char *control_str = as_control_kind_to_string (control_kind); if (control_str != NULL) recommended_controls |= parse_control_value (control_str); } } } if (supports_relations != NULL) { for (guint i = 0; i < supports_relations->len; i++) { AsRelation *relation = g_ptr_array_index (supports_relations, i); AsRelationItemKind item_kind = as_relation_get_item_kind (relation); if (item_kind == AS_RELATION_ITEM_KIND_CONTROL) { AsControlKind control_kind = as_relation_get_value_control_kind (relation); const char *control_str = as_control_kind_to_string (control_kind); if (control_str != NULL) supported_controls |= parse_control_value (control_str); } else if (item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { AsRelationCompare compare = as_relation_get_compare (relation); gint value = as_relation_get_value_int (relation); if (compare == AS_RELATION_COMPARE_LE) max_display_length = value; } } } is_mobile_friendly = calculate_is_mobile_friendly (required_controls, supported_controls, min_display_length, max_display_length); if (as_search_tokens != NULL) { g_autoptr (GStrvBuilder) builder = NULL; g_auto (GStrv) strv = NULL; builder = g_strv_builder_new (); for (guint i = 0; i < as_search_tokens->len; i++) { const char *token = NULL; token = g_ptr_array_index (as_search_tokens, i); g_strv_builder_add (builder, token); } strv = g_strv_builder_end (builder); search_tokens = g_strjoinv (" ", strv); } as_keywords = as_component_get_keywords (component); if (as_keywords != NULL && as_keywords->len > 0) { keywords = g_list_store_new (GTK_TYPE_STRING_OBJECT); for (guint i = 0; i < as_keywords->len; i++) { const char *keyword = NULL; g_autoptr (GtkStringObject) keyword_obj = NULL; keyword = g_ptr_array_index (as_keywords, i); keyword_obj = gtk_string_object_new (keyword); g_list_store_append (keywords, keyword_obj); } } as_categories = as_component_get_categories (component); if (as_categories != NULL && as_categories->len > 0) { categories = bz_flathub_category_list_from_appstream (as_categories); } if (g_strcmp0 (remote_name, "flathub") == 0) { const char *verified_str = NULL; const char *method = NULL; const char *website = NULL; const char *login_name = NULL; const char *login_provider = NULL; const char *timestamp = NULL; const char *login_is_org_str = NULL; gboolean verified = FALSE; gboolean login_is_org = FALSE; GHashTable *custom_fields = NULL; custom_fields = as_component_get_custom (component); if (custom_fields != NULL) { verified_str = g_hash_table_lookup (custom_fields, "flathub::verification::verified"); method = g_hash_table_lookup (custom_fields, "flathub::verification::method"); website = g_hash_table_lookup (custom_fields, "flathub::verification::website"); login_name = g_hash_table_lookup (custom_fields, "flathub::verification::login_name"); login_provider = g_hash_table_lookup (custom_fields, "flathub::verification::login_provider"); timestamp = g_hash_table_lookup (custom_fields, "flathub::verification::timestamp"); login_is_org_str = g_hash_table_lookup (custom_fields, "flathub::verification::login_is_organization"); } verified = (verified_str != NULL && g_strcmp0 (verified_str, "true") == 0); login_is_org = (login_is_org_str != NULL && g_strcmp0 (login_is_org_str, "true") == 0); verification_status = bz_verification_status_new (); g_object_set (verification_status, "verified", verified, "method", method, "website", website, "login-name", login_name, "login-provider", login_provider, "timestamp", timestamp, "login-is-organization", login_is_org, NULL); } g_object_set ( entry, "title", title, "description", description, "long-description", long_description, "url", project_url, "search-tokens", search_tokens, "metadata-license", metadata_license, "project-license", project_license, "is-floss", is_floss, "project-group", project_group, "developer", developer, "developer-id", developer_id, "icon-paintable", icon_paintable, "mini-icon", mini_icon, "screenshot-paintables", screenshot_paintables, "screenshot-captions", screenshot_captions, "thumbnail-paintable", thumbnail_paintable, "share-urls", share_urls, "donation-url", donation_url, "forge-url", forge_url, "reviews", native_reviews, "average-rating", average_rating, "ratings-summary", ratings_summary, "version-history", version_history, "light-accent-color", accent_color_light, "dark-accent-color", accent_color_dark, "required-controls", required_controls, "recommended-controls", recommended_controls, "supported-controls", supported_controls, "min-display-length", min_display_length, "max-display-length", max_display_length, "is-mobile-friendly", is_mobile_friendly, "content-rating", content_rating, "keywords", keywords, "categories", categories, "verification-status", verification_status, NULL); return TRUE; } kolunmi-bazaar-7b9c8e1/src/bz-appstream-parser.h000066400000000000000000000027271514314607700217310ustar00rootroot00000000000000/* bz-appstream-parser.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include #include G_BEGIN_DECLS gboolean bz_appstream_parser_populate_entry (BzEntry *entry, AsComponent *component, const char *appstream_dir, const char *remote_name, const char *module_dir, const char *unique_id_checksum, const char *id, guint kinds, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-async-texture.c000066400000000000000000000731301514314607700212450ustar00rootroot00000000000000/* bz-async-texture.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::ASYNC-TEXTURE" #define MAX_CONCURRENT_GLYCIN 32 #define CACHE_INVALID_AGE (G_TIME_SPAN_DAY * 1) #define HTTP_TIMEOUT_SECONDS 5 #define MAX_LOAD_RETRIES 3 #define RETRY_INTERVAL_SECONDS 1 #include "config.h" #include #include #include "bz-async-texture.h" #include "bz-download-worker.h" #include "bz-env.h" #include "bz-io.h" #include "bz-util.h" BZ_DEFINE_DATA ( load, Load, { GFile *source; char *source_uri; GFile *cache_into; char *cache_into_path; GCancellable *cancellable; int retries; GWeakRef self; }, BZ_RELEASE_DATA (source, g_object_unref); BZ_RELEASE_DATA (source_uri, g_free); BZ_RELEASE_DATA (cache_into, g_object_unref); BZ_RELEASE_DATA (cache_into_path, g_free); BZ_RELEASE_DATA (cancellable, g_object_unref); g_weak_ref_clear (&self->self);) struct _BzAsyncTexture { GObject parent_instance; GFile *source; char *source_uri; GFile *cache_into; char *cache_into_path; gboolean lazy; DexFuture *task; GCancellable *cancellable; int retries; DexFuture *retry_future; GdkPaintable *paintable; GMutex texture_mutex; }; static void paintable_iface_init (GdkPaintableInterface *iface); G_DEFINE_TYPE_WITH_CODE ( BzAsyncTexture, bz_async_texture, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, paintable_iface_init)) enum { PROP_0, PROP_SOURCE, PROP_CACHE_INTO, PROP_LOADED, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * load_fiber_work (LoadData *data); static DexFuture * load_finally (DexFuture *future, LoadData *data); static void maybe_load (BzAsyncTexture *self); static DexFuture * retry_cb (DexFuture *future, LoadData *data); static gboolean idle_notify (BzAsyncTexture *self); static void bz_async_texture_dispose (GObject *object) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); if (self->cancellable != NULL) g_cancellable_cancel (self->cancellable); dex_clear (&self->task); g_clear_object (&self->cancellable); dex_clear (&self->retry_future); g_clear_object (&self->source); g_clear_pointer (&self->source_uri, g_free); g_clear_object (&self->cache_into); g_clear_pointer (&self->cache_into_path, g_free); g_clear_object (&self->paintable); g_mutex_clear (&self->texture_mutex); G_OBJECT_CLASS (bz_async_texture_parent_class)->dispose (object); } static void bz_async_texture_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); switch (prop_id) { case PROP_SOURCE: g_value_set_object (value, bz_async_texture_get_source (self)); break; case PROP_CACHE_INTO: g_value_set_object (value, bz_async_texture_get_cache_into (self)); break; case PROP_LOADED: g_value_set_boolean (value, bz_async_texture_get_loaded (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_async_texture_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { // BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); switch (prop_id) { case PROP_SOURCE: case PROP_CACHE_INTO: case PROP_LOADED: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_async_texture_class_init (BzAsyncTextureClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_async_texture_dispose; object_class->get_property = bz_async_texture_get_property; object_class->set_property = bz_async_texture_set_property; props[PROP_SOURCE] = g_param_spec_object ( "source", NULL, NULL, G_TYPE_FILE, G_PARAM_READABLE); props[PROP_CACHE_INTO] = g_param_spec_object ( "cache-into", NULL, NULL, G_TYPE_FILE, G_PARAM_READABLE); props[PROP_LOADED] = g_param_spec_boolean ( "loaded", NULL, NULL, FALSE, G_PARAM_READABLE); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_async_texture_init (BzAsyncTexture *self) { self->retries = 0; self->paintable = NULL; g_mutex_init (&self->texture_mutex); } static void paintable_snapshot (GdkPaintable *paintable, GdkSnapshot *snapshot, double width, double height) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->paintable != NULL) gdk_paintable_snapshot (self->paintable, snapshot, width, height); } static GdkPaintable * paintable_get_current_image (GdkPaintable *paintable) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->paintable != NULL) return gdk_paintable_get_current_image (self->paintable); return NULL; } static GdkPaintableFlags paintable_get_flags (GdkPaintable *paintable) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); return 0; } static int paintable_get_intrinsic_width (GdkPaintable *paintable) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->paintable != NULL) return gdk_paintable_get_intrinsic_width (self->paintable); return 0; } static int paintable_get_intrinsic_height (GdkPaintable *paintable) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->paintable != NULL) return gdk_paintable_get_intrinsic_height (self->paintable); return 0; } static double paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable) { BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->paintable != NULL) return gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); return 0.0; } static void paintable_iface_init (GdkPaintableInterface *iface) { iface->snapshot = paintable_snapshot; iface->get_current_image = paintable_get_current_image; iface->get_flags = paintable_get_flags; iface->get_intrinsic_width = paintable_get_intrinsic_width; iface->get_intrinsic_height = paintable_get_intrinsic_height; iface->get_intrinsic_aspect_ratio = paintable_get_intrinsic_aspect_ratio; } BzAsyncTexture * bz_async_texture_new (GFile *source, GFile *cache_into) { BzAsyncTexture *self = NULL; g_return_val_if_fail (G_IS_FILE (source), NULL); g_return_val_if_fail (cache_into == NULL || G_IS_FILE (cache_into), NULL); self = g_object_new (BZ_TYPE_ASYNC_TEXTURE, NULL); self->source = g_object_ref (source); self->source_uri = g_file_get_uri (source); self->cache_into = bz_object_maybe_ref (cache_into); self->cache_into_path = bz_maybe (cache_into, g_file_get_path); self->lazy = FALSE; maybe_load (self); return self; } BzAsyncTexture * bz_async_texture_new_lazy (GFile *source, GFile *cache_into) { BzAsyncTexture *self = NULL; g_return_val_if_fail (G_IS_FILE (source), NULL); g_return_val_if_fail (cache_into == NULL || G_IS_FILE (cache_into), NULL); self = g_object_new (BZ_TYPE_ASYNC_TEXTURE, NULL); self->source = g_object_ref (source); self->source_uri = g_file_get_uri (source); self->cache_into = bz_object_maybe_ref (cache_into); self->cache_into_path = bz_maybe (cache_into, g_file_get_path); self->lazy = TRUE; return self; } GFile * bz_async_texture_get_source (BzAsyncTexture *self) { g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); return self->source; } const char * bz_async_texture_get_source_uri (BzAsyncTexture *self) { g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); return self->source_uri; } GFile * bz_async_texture_get_cache_into (BzAsyncTexture *self) { g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); return self->cache_into; } const char * bz_async_texture_get_cache_into_path (BzAsyncTexture *self) { g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); return self->cache_into_path; } gboolean bz_async_texture_get_loaded (BzAsyncTexture *self) { g_autoptr (GMutexLocker) locker = NULL; g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); locker = g_mutex_locker_new (&self->texture_mutex); return GDK_IS_TEXTURE (self->paintable); } GdkTexture * bz_async_texture_dup_texture (BzAsyncTexture *self) { g_autoptr (GMutexLocker) locker = NULL; g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), NULL); locker = g_mutex_locker_new (&self->texture_mutex); if (GDK_IS_TEXTURE (self->paintable)) return (GdkTexture *) g_object_ref (self->paintable); else return NULL; } DexFuture * bz_async_texture_dup_future (BzAsyncTexture *self) { g_autoptr (GMutexLocker) locker = NULL; g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), NULL); locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); if (self->task != NULL) return dex_ref (self->task); else if (GDK_IS_TEXTURE (self->paintable)) return dex_future_new_for_object (self->paintable); else return dex_future_new_reject ( G_IO_ERROR, G_IO_ERROR_FAILED, "texture is in an invalid state"); } void bz_async_texture_ensure (BzAsyncTexture *self) { g_autoptr (GMutexLocker) locker = NULL; g_return_if_fail (BZ_IS_ASYNC_TEXTURE (self)); locker = g_mutex_locker_new (&self->texture_mutex); maybe_load (self); } void bz_async_texture_cancel (BzAsyncTexture *self) { g_return_if_fail (BZ_IS_ASYNC_TEXTURE (self)); if (self->cancellable != NULL) g_cancellable_cancel (self->cancellable); dex_clear (&self->task); g_clear_object (&self->cancellable); self->retries = G_MAXINT; } gboolean bz_async_texture_is_loading (BzAsyncTexture *self) { g_return_val_if_fail (BZ_IS_ASYNC_TEXTURE (self), FALSE); return self->task != NULL && dex_future_is_pending (self->task); } static void maybe_load (BzAsyncTexture *self) { g_autoptr (LoadData) data = NULL; g_autoptr (DexFuture) future = NULL; if (GDK_IS_TEXTURE (self->paintable) || (self->task != NULL && dex_future_is_pending (self->task)) || self->retries >= MAX_LOAD_RETRIES) return; if (self->cancellable != NULL) g_cancellable_cancel (self->cancellable); dex_clear (&self->task); g_clear_object (&self->cancellable); self->cancellable = g_cancellable_new (); data = load_data_new (); data->source = g_object_ref (self->source); data->source_uri = g_strdup (self->source_uri); data->cache_into = bz_object_maybe_ref (self->cache_into); data->cache_into_path = bz_maybe_strdup (self->cache_into_path); data->cancellable = g_object_ref (self->cancellable); data->retries = self->retries; g_weak_ref_init (&data->self, self); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) load_fiber_work, load_data_ref (data), load_data_unref); future = dex_future_finally ( future, (DexFutureCallback) load_finally, load_data_ref (data), load_data_unref); self->task = g_steal_pointer (&future); } static DexFuture * load_fiber_work (LoadData *data) { static GMutex queueing_mutex = { 0 }; static guint concurrent_io = 8; static guint io_queued[MAX_CONCURRENT_GLYCIN] = { 0 }; static BzGuard *io_gates[MAX_CONCURRENT_GLYCIN] = { 0 }; static GMutex io_mutexes[MAX_CONCURRENT_GLYCIN] = { 0 }; static guint concurrent_glycin = 0; static guint glycin_queued[MAX_CONCURRENT_GLYCIN] = { 0 }; static BzGuard *glycin_gates[MAX_CONCURRENT_GLYCIN] = { 0 }; static GMutex glycin_mutexes[MAX_CONCURRENT_GLYCIN] = { 0 }; GFile *source = data->source; char *source_uri = data->source_uri; GFile *cache_into = data->cache_into; char *cache_into_path = data->cache_into_path; GCancellable *cancellable = data->cancellable; gboolean result = FALSE; g_autoptr (GError) local_error = NULL; g_autoptr (GMutexLocker) locker = NULL; g_autoptr (BzGuard) slot_guard = NULL; guint slot_queued = G_MAXUINT; gboolean is_http = FALSE; g_autoptr (GDateTime) now = NULL; g_autofree char *async_tex_data_path = NULL; g_autoptr (GFile) async_tex_data_file = NULL; g_autoptr (GdkTexture) texture = NULL; g_autoptr (GlyFrame) frame = NULL; locker = g_mutex_locker_new (&queueing_mutex); if (concurrent_glycin == 0) { /* Ensure we don't overload the system with work; aim for # of logical processors divided by 2 See: https://github.com/kolunmi/bazaar/issues/497 https://docs.gtk.org/glib/func.get_num_processors.html Eva Thu, 23 Oct 2025 14:19:44 -0700 */ concurrent_glycin = MIN ( MAX_CONCURRENT_GLYCIN, MAX (1, g_get_num_processors () / 2)); g_debug ("Allowing %d concurrent texture glycin", concurrent_glycin); } g_clear_pointer (&locker, g_mutex_locker_free); #define FIND_LOCK(name, _idx) \ G_STMT_START \ { \ locker = g_mutex_locker_new (&queueing_mutex); \ \ for (guint i = 0; i < concurrent_##name; i++) \ { \ if (name##_queued[i] < slot_queued) \ { \ slot_queued = name##_queued[i]; \ (_idx) = i; \ } \ } \ \ name##_queued[(_idx)]++; \ g_clear_pointer (&locker, g_mutex_locker_free); \ } \ G_STMT_END #define FINISH_LOCK(name, _idx) \ G_STMT_START \ { \ locker = g_mutex_locker_new (&queueing_mutex); \ name##_queued[(_idx)]--; \ g_clear_pointer (&locker, g_mutex_locker_free); \ } \ G_STMT_END #define LOCK_INDEX(name, _idx) \ G_STMT_START \ { \ FIND_LOCK (name, (_idx)); \ locker = g_mutex_locker_new (&name##_mutexes[(_idx)]); \ } \ G_STMT_END #define UNLOCK_INDEX(name, _idx) \ G_STMT_START \ { \ g_clear_pointer (&locker, g_mutex_locker_free); \ FINISH_LOCK (name, (_idx)); \ } \ G_STMT_END #define RATE_LIMIT_BEGIN(name) \ G_STMT_START \ { \ guint _slot_index = 0; \ \ FIND_LOCK (name, _slot_index); \ BZ_BEGIN_GUARD_WITH_CONTEXT (&slot_guard, \ &name##_mutexes[_slot_index], \ &name##_gates[_slot_index]); \ FINISH_LOCK (name, _slot_index); \ } \ G_STMT_END #define RATE_LIMIT_END() bz_clear_guard (&slot_guard) is_http = g_str_has_prefix (source_uri, "http"); now = g_date_time_new_now_utc (); if (cache_into != NULL) { async_tex_data_path = g_strdup_printf ("%s.bz-async-texture-data", cache_into_path); async_tex_data_file = g_file_new_for_path (async_tex_data_path); } if (cache_into != NULL) { RATE_LIMIT_BEGIN (io); if (g_file_query_exists (cache_into, NULL) && g_file_query_exists (async_tex_data_file, NULL)) { g_autoptr (GBytes) bytes = NULL; g_autoptr (GVariant) variant = NULL; GTimeSpan age_span = 0; g_autoptr (GlyLoader) loader = NULL; g_autoptr (GlyImage) image = NULL; bytes = g_file_load_bytes (async_tex_data_file, NULL, NULL, &local_error); if (bytes != NULL) variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("a{sv}"), bytes, FALSE); if (variant != NULL) { gint64 birth_unix_stamp = 0; g_autoptr (GDateTime) birth_date_time = NULL; if (g_variant_lookup ( variant, "birth-unix-stamp", "x", &birth_unix_stamp)) { birth_date_time = g_date_time_new_from_unix_utc (birth_unix_stamp); age_span = g_date_time_difference (now, birth_date_time); } else local_error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "key \"birth-unix-stamp\" was not found"); } if (variant != NULL && age_span > 0) { if (age_span < CACHE_INVALID_AGE) { RATE_LIMIT_END (); RATE_LIMIT_BEGIN (glycin); loader = gly_loader_new (cache_into); /* We assume we exported this file, so uhhh it is safe to not use sandboxing, since it is faster :-) */ gly_loader_set_sandbox_selector (loader, GLY_SANDBOX_SELECTOR_NOT_SANDBOXED); image = gly_loader_load (loader, &local_error); if (image != NULL) frame = gly_image_next_frame (image, &local_error); RATE_LIMIT_END (); RATE_LIMIT_BEGIN (io); } else g_debug ("Metadata file %s for cached texture at %s indicates this resource is too old (GTimeSpan: %zu), " "reaping and fetching from original source at %s instead", async_tex_data_path, cache_into_path, age_span, source_uri); } else { g_warning ("Couldn't load associated metadata file %s for cached texture at %s, " "reaping and fetching from original source at %s instead: %s", async_tex_data_path, cache_into_path, source_uri, local_error->message); g_clear_pointer (&local_error, g_error_free); } if (frame == NULL) { if (local_error != NULL) g_warning ("An attempt to revive cached texture at %s has failed, " "reaping and fetching from original source at %s instead: %s", cache_into_path, source_uri, local_error->message); g_clear_pointer (&local_error, g_error_free); if (!g_file_delete (cache_into, NULL, &local_error)) { g_warning ("Couldn't reap cached texture at %s, this " "might lead to unexpected behavior: %s", cache_into_path, local_error->message); g_clear_pointer (&local_error, g_error_free); } } } RATE_LIMIT_END (); } if (frame == NULL) { g_autoptr (GFile) load_file = NULL; g_autoptr (GlyLoader) loader = NULL; g_autoptr (GlyImage) image = NULL; if (cache_into != NULL) { g_autoptr (GFile) parent = NULL; gboolean reconstruct = FALSE; parent = g_file_get_parent (cache_into); RATE_LIMIT_BEGIN (io); if (g_file_query_exists (parent, NULL)) { GFileType parent_type = G_FILE_TYPE_UNKNOWN; parent_type = g_file_query_file_type (parent, G_FILE_QUERY_INFO_NONE, NULL); if (parent_type != G_FILE_TYPE_DIRECTORY) { reconstruct = TRUE; result = g_file_delete (parent, cancellable, &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); } } else reconstruct = TRUE; if (reconstruct) { result = g_file_make_directory_with_parents ( parent, cancellable, &local_error); if (!result) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_pointer (&local_error, g_error_free); else return dex_future_new_for_error (g_steal_pointer (&local_error)); } } RATE_LIMIT_END (); } if (is_http) { if (cache_into != NULL) load_file = g_object_ref (cache_into); else { g_autofree char *basename = NULL; g_autofree char *tmpl = NULL; g_autoptr (GFileIOStream) io = NULL; RATE_LIMIT_BEGIN (io); basename = g_file_get_basename (source); tmpl = g_strdup_printf ("XXXXXX-%s", basename); load_file = g_file_new_tmp (tmpl, &io, &local_error); if (load_file == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); g_io_stream_close (G_IO_STREAM (io), NULL, NULL); RATE_LIMIT_END (); } result = dex_await ( dex_future_first ( bz_download_worker_invoke ( bz_download_worker_get_default (), source, load_file), /* increase the timeout as more failures stack up */ dex_timeout_new_seconds ((data->retries + 1) * HTTP_TIMEOUT_SECONDS), NULL), &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); } else { if (cache_into != NULL) { RATE_LIMIT_BEGIN (io); result = g_file_copy ( source, cache_into, G_FILE_COPY_OVERWRITE | G_FILE_COPY_ALL_METADATA, cancellable, NULL, NULL, &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); RATE_LIMIT_END (); load_file = g_object_ref (cache_into); } else load_file = g_object_ref (source); } RATE_LIMIT_BEGIN (glycin); loader = gly_loader_new (load_file); #ifdef SANDBOXED_LIBFLATPAK gly_loader_set_sandbox_selector (loader, GLY_SANDBOX_SELECTOR_NOT_SANDBOXED); #endif image = gly_loader_load (loader, &local_error); if (is_http && cache_into == NULL) /* delete tmp file */ g_file_delete (load_file, NULL, NULL); if (image == NULL || local_error != NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); frame = gly_image_next_frame (image, &local_error); if (frame == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); RATE_LIMIT_END (); if (async_tex_data_file != NULL) { g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (GFileOutputStream) output = NULL; builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add ( builder, "{sv}", "birth-unix-stamp", g_variant_new_int64 (g_date_time_to_unix (now))); variant = g_variant_builder_end (builder); bytes = g_variant_get_data_as_bytes (variant); RATE_LIMIT_BEGIN (io); output = g_file_replace ( async_tex_data_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); if (output != NULL) { gssize bytes_written = 0; bytes_written = g_output_stream_write_bytes (G_OUTPUT_STREAM (output), bytes, NULL, &local_error); if (bytes_written > 0) g_output_stream_close (G_OUTPUT_STREAM (output), NULL, &local_error); } RATE_LIMIT_END (); if (local_error != NULL) g_warning ("Failed to write async-tex cache metadata to %s ;" "The image will be fully reloaded next time: %s", async_tex_data_path, local_error->message); g_clear_pointer (&local_error, g_error_free); } } texture = gly_gtk_frame_get_texture (frame); if (texture == NULL) return dex_future_new_reject ( G_IO_ERROR, G_IO_ERROR_FAILED, "texture loading failed"); return dex_future_new_for_object (texture); } static DexFuture * load_finally (DexFuture *future, LoadData *data) { g_autoptr (GError) local_error = NULL; g_autoptr (BzAsyncTexture) self = NULL; g_autoptr (GMutexLocker) locker = NULL; bz_weak_get_or_return_reject (self, &data->self); locker = g_mutex_locker_new (&self->texture_mutex); dex_clear (&self->task); if (dex_future_is_resolved (future)) { g_clear_object (&self->paintable); self->paintable = g_value_dup_object (dex_future_get_value (future, NULL)); g_idle_add_full ( G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) idle_notify, g_object_ref (self), g_object_unref); return dex_future_new_for_object (self->paintable); } else { dex_future_get_value (future, &local_error); if (self->retries < MAX_LOAD_RETRIES) { if (self->retries == MAX_LOAD_RETRIES - 1) g_warning ("Loading %s failed: %s. Retrying in %d seconds. This will " "be the last retry, after which this texture will remain invalid", self->source_uri, local_error->message, RETRY_INTERVAL_SECONDS); else g_warning ("Loading %s failed: %s. Retrying in %d seconds. Retries left: %d", self->source_uri, local_error->message, RETRY_INTERVAL_SECONDS, MAX_LOAD_RETRIES - self->retries); self->retries++; dex_clear (&self->retry_future); self->retry_future = dex_future_then ( dex_timeout_new_seconds (RETRY_INTERVAL_SECONDS), (DexFutureCallback) retry_cb, load_data_ref (data), load_data_unref); } return dex_ref (future); } } static DexFuture * retry_cb (DexFuture *future, LoadData *data) { g_autoptr (BzAsyncTexture) self = NULL; g_autoptr (GMutexLocker) locker = NULL; bz_weak_get_or_return_reject (self, &data->self); locker = g_mutex_locker_new (&self->texture_mutex); dex_clear (&self->retry_future); maybe_load (self); return NULL; } static gboolean idle_notify (BzAsyncTexture *self) { g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LOADED]); gdk_paintable_invalidate_contents (GDK_PAINTABLE (self)); gdk_paintable_invalidate_size (GDK_PAINTABLE (self)); return G_SOURCE_REMOVE; } kolunmi-bazaar-7b9c8e1/src/bz-async-texture.h000066400000000000000000000034441514314607700212530ustar00rootroot00000000000000/* bz-async-texture.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define BZ_TYPE_ASYNC_TEXTURE (bz_async_texture_get_type ()) G_DECLARE_FINAL_TYPE (BzAsyncTexture, bz_async_texture, BZ, ASYNC_TEXTURE, GObject) BzAsyncTexture * bz_async_texture_new (GFile *source, GFile *cache_into); BzAsyncTexture * bz_async_texture_new_lazy (GFile *source, GFile *cache_into); GFile * bz_async_texture_get_source (BzAsyncTexture *self); const char * bz_async_texture_get_source_uri (BzAsyncTexture *self); GFile * bz_async_texture_get_cache_into (BzAsyncTexture *self); const char * bz_async_texture_get_cache_into_path (BzAsyncTexture *self); gboolean bz_async_texture_get_loaded (BzAsyncTexture *self); GdkTexture * bz_async_texture_dup_texture (BzAsyncTexture *self); DexFuture * bz_async_texture_dup_future (BzAsyncTexture *self); void bz_async_texture_ensure (BzAsyncTexture *self); void bz_async_texture_cancel (BzAsyncTexture *self); gboolean bz_async_texture_is_loading (BzAsyncTexture *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-auth-state.c000066400000000000000000000342141514314607700205110ustar00rootroot00000000000000/* bz-auth-state.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-async-texture.h" #include "bz-auth-state.h" #define SECRET_SCHEMA_NAME "io.github.kolunmi.Bazaar.FlathubAuth" #define SECRET_LABEL "Flathub Authentication" struct _BzAuthState { GObject parent_instance; char *name; char *token; char *profile_icon_url; GDateTime *token_expires; BzAsyncTexture *paintable; gboolean loading; guint expiration_timeout_id; }; G_DEFINE_FINAL_TYPE (BzAuthState, bz_auth_state, G_TYPE_OBJECT) enum { PROP_0, PROP_NAME, PROP_TOKEN, PROP_PROFILE_ICON_URL, PROP_AUTHENTICATED, PROP_PAINTABLE, N_PROPS }; static GParamSpec *properties[N_PROPS]; static const SecretSchema * get_secret_schema (void) { static const SecretSchema schema = { SECRET_SCHEMA_NAME, SECRET_SCHEMA_NONE, { { "service", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "NULL", 0 }, } }; return &schema; } static gboolean on_token_expired (gpointer user_data) { BzAuthState *self = BZ_AUTH_STATE (user_data); self->expiration_timeout_id = 0; bz_auth_state_clear (self); return G_SOURCE_REMOVE; } static void schedule_token_expiration (BzAuthState *self) { GDateTime *now; gint64 seconds_until_expiration; if (self->expiration_timeout_id != 0) g_source_remove (self->expiration_timeout_id); self->expiration_timeout_id = 0; if (self->token_expires == NULL) return; now = g_date_time_new_now_utc (); seconds_until_expiration = g_date_time_difference (self->token_expires, now) / G_TIME_SPAN_SECOND; g_date_time_unref (now); if (seconds_until_expiration <= 0) { bz_auth_state_clear (self); return; } if (seconds_until_expiration > G_MAXUINT / 1000) self->expiration_timeout_id = g_timeout_add_seconds (G_MAXUINT / 1000, on_token_expired, self); else self->expiration_timeout_id = g_timeout_add_seconds (seconds_until_expiration, on_token_expired, self); } static void save_to_secrets (BzAuthState *self) { GHashTable *attributes; GError *error = NULL; g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autofree char *serialized = NULL; if (self->loading) return; attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert (attributes, g_strdup ("service"), g_strdup ("flathub")); builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); if (self->name != NULL) g_variant_builder_add (builder, "{sv}", "name", g_variant_new_string (self->name)); if (self->token != NULL) g_variant_builder_add (builder, "{sv}", "token", g_variant_new_string (self->token)); if (self->token_expires != NULL) { g_autofree char *expires = g_date_time_format_iso8601 (self->token_expires); g_variant_builder_add (builder, "{sv}", "token-expires", g_variant_new_string (expires)); } if (self->profile_icon_url != NULL) g_variant_builder_add (builder, "{sv}", "profile-icon-url", g_variant_new_string (self->profile_icon_url)); variant = g_variant_builder_end (builder); serialized = g_variant_print (variant, FALSE); secret_password_storev_sync ( get_secret_schema (), attributes, NULL, SECRET_LABEL, serialized, NULL, &error); g_hash_table_unref (attributes); if (error != NULL) { g_warning ("Failed to save authentication to secrets: %s", error->message); g_error_free (error); } } static void load_from_secrets (BzAuthState *self) { GHashTable *attributes; GError *error = NULL; g_autofree char *secret = NULL; attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert (attributes, g_strdup ("service"), g_strdup ("flathub")); secret = secret_password_lookupv_sync ( get_secret_schema (), attributes, NULL, &error); g_hash_table_unref (attributes); if (error != NULL) { if (!g_error_matches (error, SECRET_ERROR, SECRET_ERROR_NO_SUCH_OBJECT)) g_warning ("Failed to load authentication from secrets: %s", error->message); g_error_free (error); return; } if (secret != NULL) { g_autoptr (GVariant) variant = NULL; g_autoptr (GVariantIter) iter = NULL; variant = g_variant_parse (G_VARIANT_TYPE_VARDICT, secret, NULL, NULL, &error); if (error != NULL) { g_warning ("Failed to parse secret: %s", error->message); g_error_free (error); return; } if (variant != NULL) { iter = g_variant_iter_new (variant); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "name") == 0) { g_clear_pointer (&self->name, g_free); self->name = g_variant_dup_string (value, NULL); } else if (g_strcmp0 (key, "token") == 0) { g_clear_pointer (&self->token, g_free); self->token = g_variant_dup_string (value, NULL); } else if (g_strcmp0 (key, "token-expires") == 0) { g_autoptr (GDateTime) dt = g_date_time_new_from_iso8601 (g_variant_get_string (value, NULL), NULL); if (dt != NULL) { g_clear_pointer (&self->token_expires, g_date_time_unref); self->token_expires = g_steal_pointer (&dt); } } else if (g_strcmp0 (key, "profile-icon-url") == 0) { g_clear_pointer (&self->profile_icon_url, g_free); self->profile_icon_url = g_variant_dup_string (value, NULL); g_clear_object (&self->paintable); if (self->profile_icon_url != NULL && self->profile_icon_url[0] != '\0') { g_autoptr (GFile) file = g_file_new_for_uri (self->profile_icon_url); self->paintable = bz_async_texture_new (file, NULL); } } } } } if (self->token_expires != NULL) { GDateTime *now = g_date_time_new_now_utc (); if (g_date_time_compare (now, self->token_expires) >= 0) { g_date_time_unref (now); bz_auth_state_clear (self); return; } g_date_time_unref (now); schedule_token_expiration (self); } } static void clear_secrets (BzAuthState *self) { gboolean result = FALSE; g_autoptr (GError) local_error = NULL; g_autoptr (GHashTable) attributes = NULL; attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_replace (attributes, g_strdup ("service"), g_strdup ("flathub")); result = secret_password_clearv_sync ( get_secret_schema (), attributes, NULL, &local_error); if (!result) g_warning ("Failed to clear auth values from secrets: %s", local_error->message); } static void bz_auth_state_dispose (GObject *object) { BzAuthState *self = BZ_AUTH_STATE (object); g_clear_handle_id (&self->expiration_timeout_id, g_source_remove); g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->token, g_free); g_clear_pointer (&self->profile_icon_url, g_free); g_clear_pointer (&self->token_expires, g_date_time_unref); g_clear_object (&self->paintable); G_OBJECT_CLASS (bz_auth_state_parent_class)->dispose (object); } static void bz_auth_state_finalize (GObject *object) { BzAuthState *self = BZ_AUTH_STATE (object); g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->token, g_free); g_clear_pointer (&self->profile_icon_url, g_free); g_clear_pointer (&self->token_expires, g_date_time_unref); G_OBJECT_CLASS (bz_auth_state_parent_class)->finalize (object); } static void bz_auth_state_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzAuthState *self = BZ_AUTH_STATE (object); switch (prop_id) { case PROP_NAME: g_value_set_string (value, self->name); break; case PROP_TOKEN: g_value_set_string (value, self->token); break; case PROP_PROFILE_ICON_URL: g_value_set_string (value, self->profile_icon_url); break; case PROP_AUTHENTICATED: g_value_set_boolean (value, bz_auth_state_is_authenticated (self)); break; case PROP_PAINTABLE: g_value_set_object (value, bz_auth_state_get_paintable (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_auth_state_class_init (BzAuthStateClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_auth_state_dispose; object_class->finalize = bz_auth_state_finalize; object_class->get_property = bz_auth_state_get_property; properties[PROP_NAME] = g_param_spec_string ( "name", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); properties[PROP_TOKEN] = g_param_spec_string ( "token", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); properties[PROP_PROFILE_ICON_URL] = g_param_spec_string ( "profile-icon-url", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); properties[PROP_AUTHENTICATED] = g_param_spec_boolean ( "authenticated", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); properties[PROP_PAINTABLE] = g_param_spec_object ( "paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); } static void bz_auth_state_init (BzAuthState *self) { self->loading = TRUE; load_from_secrets (self); self->loading = FALSE; } BzAuthState * bz_auth_state_new (void) { return g_object_new (BZ_TYPE_AUTH_STATE, NULL); } const char * bz_auth_state_get_name (BzAuthState *self) { g_return_val_if_fail (BZ_IS_AUTH_STATE (self), NULL); return self->name; } const char * bz_auth_state_get_token (BzAuthState *self) { g_return_val_if_fail (BZ_IS_AUTH_STATE (self), NULL); return self->token; } const char * bz_auth_state_get_profile_icon_url (BzAuthState *self) { g_return_val_if_fail (BZ_IS_AUTH_STATE (self), NULL); return self->profile_icon_url; } gboolean bz_auth_state_is_authenticated (BzAuthState *self) { g_return_val_if_fail (BZ_IS_AUTH_STATE (self), FALSE); return self->token != NULL && self->token[0] != '\0'; } GdkPaintable * bz_auth_state_get_paintable (BzAuthState *self) { g_return_val_if_fail (BZ_IS_AUTH_STATE (self), NULL); return GDK_PAINTABLE (self->paintable); } void bz_auth_state_set_authenticated (BzAuthState *self, const char *name, const char *token, GDateTime *token_expires, const char *profile_icon_url) { gboolean was_authenticated = FALSE; gboolean name_changed = FALSE; gboolean token_changed = FALSE; gboolean icon_changed = FALSE; g_return_if_fail (BZ_IS_AUTH_STATE (self)); was_authenticated = bz_auth_state_is_authenticated (self); if (g_strcmp0 (self->name, name) != 0) { g_clear_pointer (&self->name, g_free); self->name = g_strdup (name); name_changed = TRUE; } if (g_strcmp0 (self->token, token) != 0) { g_clear_pointer (&self->token, g_free); self->token = g_strdup (token); token_changed = TRUE; } g_clear_pointer (&self->token_expires, g_date_time_unref); if (token_expires != NULL) self->token_expires = g_date_time_ref (token_expires); if (g_strcmp0 (self->profile_icon_url, profile_icon_url) != 0) { g_clear_pointer (&self->profile_icon_url, g_free); self->profile_icon_url = g_strdup (profile_icon_url); icon_changed = TRUE; g_clear_object (&self->paintable); if (profile_icon_url != NULL && profile_icon_url[0] != '\0') { g_autoptr (GFile) file = g_file_new_for_uri (profile_icon_url); self->paintable = bz_async_texture_new (file, NULL); } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PAINTABLE]); } if (name_changed) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NAME]); if (token_changed) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TOKEN]); if (icon_changed) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PROFILE_ICON_URL]); if (!!was_authenticated != !!bz_auth_state_is_authenticated (self)) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_AUTHENTICATED]); schedule_token_expiration (self); save_to_secrets (self); } void bz_auth_state_clear (BzAuthState *self) { g_return_if_fail (BZ_IS_AUTH_STATE (self)); g_clear_handle_id (&self->expiration_timeout_id, g_source_remove); clear_secrets (self); bz_auth_state_set_authenticated (self, NULL, NULL, NULL, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-auth-state.h000066400000000000000000000032061514314607700205130ustar00rootroot00000000000000/* bz-auth-state.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define BZ_TYPE_AUTH_STATE (bz_auth_state_get_type ()) G_DECLARE_FINAL_TYPE (BzAuthState, bz_auth_state, BZ, AUTH_STATE, GObject) BzAuthState *bz_auth_state_new (void); const char * bz_auth_state_get_name (BzAuthState *self); const char * bz_auth_state_get_token (BzAuthState *self); const char * bz_auth_state_get_profile_icon_url (BzAuthState *self); gboolean bz_auth_state_is_authenticated (BzAuthState *self); GdkPaintable * bz_auth_state_get_paintable (BzAuthState *self); void bz_auth_state_set_authenticated (BzAuthState *self, const char *name, const char *token, GDateTime *token_expires, const char *profile_icon_url); void bz_auth_state_clear (BzAuthState *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-backend-notification.txt000066400000000000000000000010121514314607700230700ustar00rootroot00000000000000prefix=bz name=backend_notification parent-prefix=g parent-name=object author=AUTOGEN enum=bz backend_notification_kind error tell_incoming replace_entry install_done update_done remove_done external_change include="bz-entry.h" property=kind BzBackendNotificationKind BZ_TYPE_BACKEND_NOTIFICATION_KIND enum property=error char G_TYPE_STRING string property=n_incoming int G_TYPE_INT int property=entry BzEntry BZ_TYPE_ENTRY object property=version char G_TYPE_STRING string property=unique_id char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-backend-transaction-op-payload.txt000066400000000000000000000004641514314607700250040ustar00rootroot00000000000000prefix=bz name=backend_transaction_op_payload parent-prefix=g parent-name=object author=AUTOGEN include="bz-entry.h" property=name char G_TYPE_STRING string property=entry BzEntry BZ_TYPE_ENTRY object property=download_size guint64 G_TYPE_UINT64 uint64 property=installed_size guint64 G_TYPE_UINT64 uint64 kolunmi-bazaar-7b9c8e1/src/bz-backend-transaction-op-progress-payload.txt000066400000000000000000000010351514314607700266410ustar00rootroot00000000000000prefix=bz name=backend_transaction_op_progress_payload parent-prefix=g parent-name=object author=AUTOGEN include="bz-backend-transaction-op-payload.h" property=op BzBackendTransactionOpPayload BZ_TYPE_BACKEND_TRANSACTION_OP_PAYLOAD object property=status char G_TYPE_STRING string property=is_estimating gboolean G_TYPE_BOOLEAN boolean property=progress double G_TYPE_DOUBLE double property=total_progress double G_TYPE_DOUBLE double property=bytes_transferred guint64 G_TYPE_UINT64 uint64 property=start_time guint64 G_TYPE_UINT64 uint64 kolunmi-bazaar-7b9c8e1/src/bz-backend.c000066400000000000000000000216011514314607700200150ustar00rootroot00000000000000/* bz-backend.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-backend.h" #include "bz-transaction.h" G_DEFINE_INTERFACE (BzBackend, bz_backend, G_TYPE_OBJECT) static DexChannel * bz_backend_real_create_notification_channel (BzBackend *self) { return NULL; } static DexFuture * bz_backend_real_load_local_package (BzBackend *self, GFile *file, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static DexFuture * bz_backend_real_retrieve_remote_entries (BzBackend *self, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static DexFuture * bz_backend_real_retrieve_install_ids (BzBackend *self, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static DexFuture * bz_backend_real_retrieve_update_ids (BzBackend *self, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static DexFuture * bz_backend_real_list_repositories (BzBackend *self, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static DexFuture * bz_backend_real_schedule_transaction (BzBackend *self, BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals, DexChannel *channel, GCancellable *cancellable) { return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unimplemented"); } static void bz_backend_default_init (BzBackendInterface *iface) { iface->create_notification_channel = bz_backend_real_create_notification_channel; iface->load_local_package = bz_backend_real_load_local_package; iface->retrieve_remote_entries = bz_backend_real_retrieve_remote_entries; iface->retrieve_install_ids = bz_backend_real_retrieve_install_ids; iface->retrieve_update_ids = bz_backend_real_retrieve_update_ids; iface->list_repositories = bz_backend_real_list_repositories; iface->schedule_transaction = bz_backend_real_schedule_transaction; } DexChannel * bz_backend_create_notification_channel (BzBackend *self) { g_return_val_if_fail (BZ_IS_BACKEND (self), NULL); return BZ_BACKEND_GET_IFACE (self)->create_notification_channel (self); } DexFuture * bz_backend_load_local_package (BzBackend *self, GFile *file, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); dex_return_error_if_fail (G_IS_FILE (file)); dex_return_error_if_fail (cancellable == NULL || G_IS_CANCELLABLE (self)); return BZ_BACKEND_GET_IFACE (self)->load_local_package (self, file, cancellable); } DexFuture * bz_backend_retrieve_remote_entries (BzBackend *self, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); dex_return_error_if_fail (cancellable == NULL || G_IS_CANCELLABLE (self)); return BZ_BACKEND_GET_IFACE (self)->retrieve_remote_entries (self, cancellable); } DexFuture * bz_backend_retrieve_install_ids (BzBackend *self, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); return BZ_BACKEND_GET_IFACE (self)->retrieve_install_ids (self, cancellable); } DexFuture * bz_backend_retrieve_update_ids (BzBackend *self, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); return BZ_BACKEND_GET_IFACE (self)->retrieve_update_ids (self, cancellable); } DexFuture * bz_backend_list_repositories (BzBackend *self, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); dex_return_error_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); return BZ_BACKEND_GET_IFACE (self)->list_repositories (self, cancellable); } DexFuture * bz_backend_schedule_transaction (BzBackend *self, BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals, DexChannel *channel, GCancellable *cancellable) { dex_return_error_if_fail (BZ_IS_BACKEND (self)); dex_return_error_if_fail ((installs != NULL && n_installs > 0) || (updates != NULL && n_updates > 0) || (removals != NULL && n_removals)); if (installs != NULL) { for (guint i = 0; i < n_installs; i++) dex_return_error_if_fail (BZ_IS_ENTRY (installs[i])); } if (updates != NULL) { for (guint i = 0; i < n_updates; i++) dex_return_error_if_fail (BZ_IS_ENTRY (updates[i])); } if (removals != NULL) { for (guint i = 0; i < n_removals; i++) dex_return_error_if_fail (BZ_IS_ENTRY (removals[i])); } return BZ_BACKEND_GET_IFACE (self)->schedule_transaction ( self, installs, n_installs, updates, n_updates, removals, n_removals, channel, cancellable); } DexFuture * bz_backend_merge_and_schedule_transactions (BzBackend *self, GListModel *transactions, DexChannel *channel, GCancellable *cancellable) { guint n_items = 0; g_autoptr (GPtrArray) installs_pa = NULL; g_autoptr (GPtrArray) updates_pa = NULL; g_autoptr (GPtrArray) removals_pa = NULL; dex_return_error_if_fail (G_IS_LIST_MODEL (transactions)); n_items = g_list_model_get_n_items (transactions); dex_return_error_if_fail (n_items > 0); installs_pa = g_ptr_array_new_with_free_func (g_object_unref); updates_pa = g_ptr_array_new_with_free_func (g_object_unref); removals_pa = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < n_items; i++) { g_autoptr (BzTransaction) transaction = NULL; GListModel *installs = NULL; GListModel *updates = NULL; GListModel *removals = NULL; guint n_installs = 0; guint n_updates = 0; guint n_removals = 0; transaction = g_list_model_get_item (transactions, i); installs = bz_transaction_get_installs (transaction); updates = bz_transaction_get_updates (transaction); removals = bz_transaction_get_removals (transaction); if (installs != NULL) n_installs = g_list_model_get_n_items (installs); if (updates != NULL) n_updates = g_list_model_get_n_items (updates); if (removals != NULL) n_removals = g_list_model_get_n_items (removals); for (guint j = 0; j < n_installs; j++) g_ptr_array_add (installs_pa, g_list_model_get_item (installs, j)); for (guint j = 0; j < n_updates; j++) g_ptr_array_add (updates_pa, g_list_model_get_item (updates, j)); for (guint j = 0; j < n_removals; j++) g_ptr_array_add (removals_pa, g_list_model_get_item (removals, j)); } return bz_backend_schedule_transaction ( self, (BzEntry **) installs_pa->pdata, installs_pa->len, (BzEntry **) updates_pa->pdata, updates_pa->len, (BzEntry **) removals_pa->pdata, removals_pa->len, channel, cancellable); } kolunmi-bazaar-7b9c8e1/src/bz-backend.h000066400000000000000000000100351514314607700200210ustar00rootroot00000000000000/* bz-backend.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry.h" G_BEGIN_DECLS #define BZ_TYPE_BACKEND (bz_backend_get_type ()) G_DECLARE_INTERFACE (BzBackend, bz_backend, BZ, BACKEND, GObject) struct _BzBackendInterface { GTypeInterface parent_iface; DexChannel *(*create_notification_channel) (BzBackend *self); /* DexFuture* -> char*|BzEntry* */ DexFuture *(*load_local_package) (BzBackend *self, GFile *file, GCancellable *cancellable); /* DexFuture* -> gboolean */ DexFuture *(*retrieve_remote_entries) (BzBackend *self, GCancellable *cancellable); /* DexFuture* -> GHashTable* */ DexFuture *(*retrieve_install_ids) (BzBackend *self, GCancellable *cancellable); /* DexFuture* -> GPtrArray* -> char* */ DexFuture *(*retrieve_update_ids) (BzBackend *self, GCancellable *cancellable); /* DexFuture* -> GListModel* (of BzRepository objects) */ DexFuture *(*list_repositories) (BzBackend *self, GCancellable *cancellable); /* DexFuture* -> gboolean */ DexFuture *(*schedule_transaction) (BzBackend *self, BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals, DexChannel *channel, GCancellable *cancellable); }; DexChannel * bz_backend_create_notification_channel (BzBackend *self); DexFuture * bz_backend_load_local_package (BzBackend *self, GFile *file, GCancellable *cancellable); DexFuture * bz_backend_retrieve_remote_entries (BzBackend *self, GCancellable *cancellable); DexFuture * bz_backend_retrieve_install_ids (BzBackend *self, GCancellable *cancellable); DexFuture * bz_backend_retrieve_update_ids (BzBackend *self, GCancellable *cancellable); DexFuture * bz_backend_list_repositories (BzBackend *self, GCancellable *cancellable); DexFuture * bz_backend_schedule_transaction (BzBackend *self, BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals, DexChannel *channel, GCancellable *cancellable); DexFuture * bz_backend_merge_and_schedule_transactions (BzBackend *self, GListModel *transactions, DexChannel *channel, GCancellable *cancellable); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-blocklist-condition-match-envvar.txt000066400000000000000000000002631514314607700253670ustar00rootroot00000000000000prefix=bz name=blocklist_condition_match_envvar parent-prefix=g parent-name=object author=AUTOGEN property=var char G_TYPE_STRING string property=regex char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-blocklist-condition-match-locale.txt000066400000000000000000000002141514314607700253210ustar00rootroot00000000000000prefix=bz name=blocklist_condition_match_locale parent-prefix=g parent-name=object author=AUTOGEN property=regex char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-blocklist-condition.txt000066400000000000000000000010601514314607700227720ustar00rootroot00000000000000prefix=bz name=blocklist_condition parent-prefix=g parent-name=object author=AUTOGEN enum=bz blocklist_condition_post_process_kind identity invert include="bz-blocklist-condition-match-envvar.h" include="bz-blocklist-condition-match-locale.h" property=match_envvar BzBlocklistConditionMatchEnvvar BZ_TYPE_BLOCKLIST_CONDITION_MATCH_ENVVAR object property=match_locale BzBlocklistConditionMatchLocale BZ_TYPE_BLOCKLIST_CONDITION_MATCH_LOCALE object property=post_process BzBlocklistConditionPostProcessKind BZ_TYPE_BLOCKLIST_CONDITION_POST_PROCESS_KIND enum kolunmi-bazaar-7b9c8e1/src/bz-blocklist.txt000066400000000000000000000007401514314607700210120ustar00rootroot00000000000000prefix=bz name=blocklist parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-blocklist-condition.h" ensure=BZ_TYPE_BLOCKLIST_CONDITION property=priority int G_TYPE_INT int property=conditions GListModel G_TYPE_LIST_MODEL object property=allow GListModel G_TYPE_LIST_MODEL object property=allow_regex GListModel G_TYPE_LIST_MODEL object property=block GListModel G_TYPE_LIST_MODEL object property=block_regex GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-bulk-install-dialog-result.txt000066400000000000000000000003331514314607700241740ustar00rootroot00000000000000prefix=bz name=bulk_install_dialog_result parent-prefix=g parent-name=object author=AUTOGEN include="bz-entry.h" property=entries GListModel G_TYPE_LIST_MODEL object property=confirmed gboolean G_TYPE_BOOLEAN boolean kolunmi-bazaar-7b9c8e1/src/bz-carousel-indicator-dots.c000066400000000000000000000242011514314607700231630ustar00rootroot00000000000000/* bz-carousel-indicator-dots.c * * Copyright (C) 2020 Alice Mikhaylenko * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "bz-carousel-indicator-dots.h" #include "config.h" #include #define DOTS_RADIUS 3 #define DOTS_RADIUS_SELECTED 4 #define DOTS_OPACITY 0.3 #define DOTS_OPACITY_SELECTED 0.9 #define DOTS_SPACING 7 #define DOTS_MARGIN 6 struct _BzCarouselIndicatorDots { GtkWidget parent_instance; BzCarousel *carousel; GtkOrientation orientation; }; G_DEFINE_FINAL_TYPE_WITH_CODE (BzCarouselIndicatorDots, bz_carousel_indicator_dots, GTK_TYPE_WIDGET, G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)) enum { PROP_0, PROP_CAROUSEL, PROP_ORIENTATION, LAST_PROP = PROP_CAROUSEL + 1, }; static GParamSpec *props[LAST_PROP]; static double lerp (double a, double b, double t) { return a + (b - a) * t; } static void snapshot_dots (GtkWidget *widget, GtkSnapshot *snapshot, GtkOrientation orientation, double position, guint n_pages) { GdkRGBA color; int i, widget_length, widget_thickness; double x, y, indicator_length, dot_size, full_size; double current_position, remaining_progress; graphene_rect_t rect; gtk_widget_get_color (widget, &color); dot_size = 2 * DOTS_RADIUS_SELECTED + DOTS_SPACING; indicator_length = n_pages * dot_size - DOTS_SPACING; if (orientation == GTK_ORIENTATION_HORIZONTAL) { widget_length = gtk_widget_get_width (widget); widget_thickness = gtk_widget_get_height (widget); } else { widget_length = gtk_widget_get_height (widget); widget_thickness = gtk_widget_get_width (widget); } full_size = round (indicator_length / dot_size) * dot_size; if ((widget_length - (int) full_size) % 2 == 0) widget_length--; if (orientation == GTK_ORIENTATION_HORIZONTAL) { x = (widget_length - indicator_length) / 2.0; y = widget_thickness / 2; } else { x = widget_thickness / 2; y = (widget_length - indicator_length) / 2.0; } current_position = 0; remaining_progress = 1; graphene_rect_init (&rect, -DOTS_RADIUS, -DOTS_RADIUS, DOTS_RADIUS * 2, DOTS_RADIUS * 2); for (i = 0; i < n_pages; i++) { double progress, radius, opacity; GskRoundedRect clip; if (orientation == GTK_ORIENTATION_HORIZONTAL) x += dot_size / 2.0; else y += dot_size / 2.0; current_position += 1; progress = CLAMP (current_position - position, 0, remaining_progress); remaining_progress -= progress; radius = lerp (DOTS_RADIUS, DOTS_RADIUS_SELECTED, progress); opacity = lerp (DOTS_OPACITY, DOTS_OPACITY_SELECTED, progress); gsk_rounded_rect_init_from_rect (&clip, &rect, radius); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); gtk_snapshot_scale (snapshot, radius / DOTS_RADIUS, radius / DOTS_RADIUS); gtk_snapshot_push_rounded_clip (snapshot, &clip); gtk_snapshot_push_opacity (snapshot, opacity); gtk_snapshot_append_color (snapshot, &color, &rect); gtk_snapshot_pop (snapshot); gtk_snapshot_pop (snapshot); gtk_snapshot_restore (snapshot); if (orientation == GTK_ORIENTATION_HORIZONTAL) x += dot_size / 2.0; else y += dot_size / 2.0; } } static void bz_carousel_indicator_dots_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzCarouselIndicatorDots *self = BZ_CAROUSEL_INDICATOR_DOTS (widget); int size = 0; if (orientation == self->orientation) { guint n_pages = 0; double indicator_length, dot_size; if (self->carousel) g_object_get (self->carousel, "n-pages", &n_pages, NULL); dot_size = 2 * DOTS_RADIUS_SELECTED + DOTS_SPACING; indicator_length = n_pages * dot_size - DOTS_SPACING; size = ceil (indicator_length); } else { size = 2 * DOTS_RADIUS_SELECTED; } size += 2 * DOTS_MARGIN; if (minimum) *minimum = size; if (natural) *natural = size; if (minimum_baseline) *minimum_baseline = -1; if (natural_baseline) *natural_baseline = -1; } static void bz_carousel_indicator_dots_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzCarouselIndicatorDots *self = BZ_CAROUSEL_INDICATOR_DOTS (widget); guint n_pages; double position; if (!self->carousel) return; g_object_get (self->carousel, "n-pages", &n_pages, "position", &position, NULL); if (n_pages < 2) return; if (self->orientation == GTK_ORIENTATION_HORIZONTAL && gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) position = n_pages - 1 - position; snapshot_dots (widget, snapshot, self->orientation, position, n_pages); } static void bz_carousel_indicator_dots_dispose (GObject *object) { BzCarouselIndicatorDots *self = BZ_CAROUSEL_INDICATOR_DOTS (object); bz_carousel_indicator_dots_set_carousel (self, NULL); G_OBJECT_CLASS (bz_carousel_indicator_dots_parent_class)->dispose (object); } static void bz_carousel_indicator_dots_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCarouselIndicatorDots *self = BZ_CAROUSEL_INDICATOR_DOTS (object); switch (prop_id) { case PROP_CAROUSEL: g_value_set_object (value, bz_carousel_indicator_dots_get_carousel (self)); break; case PROP_ORIENTATION: g_value_set_enum (value, self->orientation); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_carousel_indicator_dots_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCarouselIndicatorDots *self = BZ_CAROUSEL_INDICATOR_DOTS (object); switch (prop_id) { case PROP_CAROUSEL: bz_carousel_indicator_dots_set_carousel (self, g_value_get_object (value)); break; case PROP_ORIENTATION: { GtkOrientation orientation = g_value_get_enum (value); if (orientation != self->orientation) { self->orientation = orientation; gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify (G_OBJECT (self), "orientation"); } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_carousel_indicator_dots_class_init (BzCarouselIndicatorDotsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_carousel_indicator_dots_dispose; object_class->get_property = bz_carousel_indicator_dots_get_property; object_class->set_property = bz_carousel_indicator_dots_set_property; widget_class->measure = bz_carousel_indicator_dots_measure; widget_class->snapshot = bz_carousel_indicator_dots_snapshot; props[PROP_CAROUSEL] = g_param_spec_object ("carousel", NULL, NULL, BZ_TYPE_CAROUSEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation"); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_css_name (widget_class, "carouselindicatordots"); } static void bz_carousel_indicator_dots_init (BzCarouselIndicatorDots *self) { } GtkWidget * bz_carousel_indicator_dots_new (void) { return g_object_new (BZ_TYPE_CAROUSEL_INDICATOR_DOTS, NULL); } BzCarousel * bz_carousel_indicator_dots_get_carousel (BzCarouselIndicatorDots *self) { g_return_val_if_fail (BZ_IS_CAROUSEL_INDICATOR_DOTS (self), NULL); return self->carousel; } void bz_carousel_indicator_dots_set_carousel (BzCarouselIndicatorDots *self, BzCarousel *carousel) { g_return_if_fail (BZ_IS_CAROUSEL_INDICATOR_DOTS (self)); g_return_if_fail (carousel == NULL || BZ_IS_CAROUSEL (carousel)); if (self->carousel == carousel) return; if (self->carousel) { g_signal_handlers_disconnect_by_func (self->carousel, gtk_widget_queue_draw, self); } g_set_object (&self->carousel, carousel); if (self->carousel) { g_signal_connect_object (self->carousel, "notify::position", G_CALLBACK (gtk_widget_queue_draw), self, G_CONNECT_SWAPPED); g_signal_connect_object (self->carousel, "notify::n-pages", G_CALLBACK (gtk_widget_queue_resize), self, G_CONNECT_SWAPPED); } gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CAROUSEL]); } kolunmi-bazaar-7b9c8e1/src/bz-carousel-indicator-dots.h000066400000000000000000000026541514314607700232000ustar00rootroot00000000000000/* bz-carousel-indicator-dots.h * * Copyright (C) 2020 Alice Mikhaylenko * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include "bz-carousel.h" #include G_BEGIN_DECLS #define BZ_TYPE_CAROUSEL_INDICATOR_DOTS (bz_carousel_indicator_dots_get_type ()) G_DECLARE_FINAL_TYPE (BzCarouselIndicatorDots, bz_carousel_indicator_dots, BZ, CAROUSEL_INDICATOR_DOTS, GtkWidget) GtkWidget *bz_carousel_indicator_dots_new (void) G_GNUC_WARN_UNUSED_RESULT; BzCarousel *bz_carousel_indicator_dots_get_carousel (BzCarouselIndicatorDots *self); void bz_carousel_indicator_dots_set_carousel (BzCarouselIndicatorDots *self, BzCarousel *carousel); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-carousel.c000066400000000000000000000572451514314607700202600ustar00rootroot00000000000000/* bz-carousel.c * * Copyright 2025 Alexander Vanhee * Copyright (C) 2019 Alice Mikhaylenko * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-carousel.h" #include #include typedef struct { GtkWidget *widget; int position; gboolean visible; double snap_point; int actual_size; } ChildInfo; struct _BzCarousel { GtkWidget parent_instance; GList *children; double distance; double position; guint spacing; GtkOrientation orientation; double animation_source_position; AdwAnimation *animation; ChildInfo *animation_target_child; AdwSwipeTracker *tracker; guint scroll_timeout_id; gboolean is_being_allocated; }; static void bz_carousel_buildable_init (GtkBuildableIface *iface); static void bz_carousel_swipeable_init (AdwSwipeableInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzCarousel, bz_carousel, GTK_TYPE_WIDGET, G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL); G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, bz_carousel_buildable_init); G_IMPLEMENT_INTERFACE (ADW_TYPE_SWIPEABLE, bz_carousel_swipeable_init);) static GtkBuildableIface *parent_buildable_iface; enum { PROP_0, PROP_N_PAGES, PROP_POSITION, PROP_ORIENTATION, LAST_PROP = PROP_POSITION + 1, }; static GParamSpec *props[LAST_PROP]; enum { SIGNAL_PAGE_CHANGED, SIGNAL_LAST_SIGNAL, }; static guint signals[SIGNAL_LAST_SIGNAL]; static ChildInfo * find_child_info (BzCarousel *self, GtkWidget *widget) { GList *l; for (l = self->children; l; l = l->next) { ChildInfo *info = l->data; if (widget == info->widget) return info; } return NULL; } static int find_child_index (BzCarousel *self, GtkWidget *widget) { GList *l; int i; i = 0; for (l = self->children; l; l = l->next) { ChildInfo *info = l->data; if (widget == info->widget) return i; i++; } return -1; } static GList * get_nth_link (BzCarousel *self, int n) { GList *l; int i; i = n; for (l = self->children; l; l = l->next) { if (i-- == 0) return l; } return NULL; } static ChildInfo * get_closest_child_at (BzCarousel *self, double position) { GList *l; ChildInfo *closest_child = NULL; for (l = self->children; l; l = l->next) { ChildInfo *child = l->data; if (!closest_child || ABS (closest_child->snap_point - position) > ABS (child->snap_point - position)) closest_child = child; } return closest_child; } static inline void get_range (BzCarousel *self, double *lower, double *upper) { GList *l = g_list_last (self->children); ChildInfo *child = l ? l->data : NULL; if (lower) *lower = 0; if (upper) *upper = MAX (0, child ? child->snap_point : 0); } static GtkWidget * get_page_at_position (BzCarousel *self, double position) { double lower = 0, upper = 0; ChildInfo *child; get_range (self, &lower, &upper); position = CLAMP (position, lower, upper); child = get_closest_child_at (self, position); if (!child) return NULL; return child->widget; } static void set_position (BzCarousel *self, double position) { double lower = 0, upper = 0; get_range (self, &lower, &upper); position = CLAMP (position, lower, upper); self->position = position; gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_POSITION]); } static void scroll_animation_value_cb (double value, BzCarousel *self) { set_position (self, value); gtk_widget_queue_allocate (GTK_WIDGET (self)); } static void scroll_animation_done_cb (BzCarousel *self) { GtkWidget *child; int index; self->animation_source_position = 0; self->animation_target_child = NULL; child = get_page_at_position (self, self->position); index = find_child_index (self, child); g_signal_emit (self, signals[SIGNAL_PAGE_CHANGED], 0, index); } static void scroll_to (BzCarousel *self, GtkWidget *widget, double velocity) { self->animation_target_child = find_child_info (self, widget); if (self->animation_target_child == NULL) return; self->animation_source_position = self->position; adw_spring_animation_set_value_from (ADW_SPRING_ANIMATION (self->animation), self->animation_source_position); adw_spring_animation_set_value_to (ADW_SPRING_ANIMATION (self->animation), self->animation_target_child->snap_point); adw_spring_animation_set_initial_velocity (ADW_SPRING_ANIMATION (self->animation), velocity); adw_animation_play (self->animation); } static inline double get_closest_snap_point (BzCarousel *self) { ChildInfo *closest_child = get_closest_child_at (self, self->position); if (!closest_child) return 0; return closest_child->snap_point; } static void begin_swipe_cb (AdwSwipeTracker *tracker, BzCarousel *self) { adw_animation_pause (self->animation); } static void update_swipe_cb (AdwSwipeTracker *tracker, double progress, BzCarousel *self) { set_position (self, progress); } static void end_swipe_cb (AdwSwipeTracker *tracker, double velocity, double to, BzCarousel *self) { GtkWidget *child = get_page_at_position (self, to); scroll_to (self, child, velocity); } static void set_orientable_style_classes (GtkOrientable *orientable) { GtkOrientation orientation = gtk_orientable_get_orientation (orientable); GtkWidget *widget = GTK_WIDGET (orientable); if (orientation == GTK_ORIENTATION_HORIZONTAL) { gtk_widget_add_css_class (widget, "horizontal"); gtk_widget_remove_css_class (widget, "vertical"); } else { gtk_widget_add_css_class (widget, "vertical"); gtk_widget_remove_css_class (widget, "horizontal"); } } static void update_orientation (BzCarousel *self) { gboolean reversed = self->orientation == GTK_ORIENTATION_HORIZONTAL && gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL; gtk_orientable_set_orientation (GTK_ORIENTABLE (self->tracker), self->orientation); adw_swipe_tracker_set_reversed (self->tracker, reversed); set_orientable_style_classes (GTK_ORIENTABLE (self)); } static void bz_carousel_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzCarousel *self = BZ_CAROUSEL (widget); GList *children; if (minimum) *minimum = 0; if (natural) *natural = 0; if (minimum_baseline) *minimum_baseline = -1; if (natural_baseline) *natural_baseline = -1; for (children = self->children; children; children = children->next) { ChildInfo *child_info = children->data; GtkWidget *child = child_info->widget; int child_min, child_nat; if (!gtk_widget_get_visible (child)) continue; gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, NULL, NULL); if (minimum) *minimum = MAX (*minimum, child_min); if (natural) *natural = MAX (*natural, child_nat); } } static void bz_carousel_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzCarousel *self; GList *children; double x, y; gboolean is_rtl; double snap_point; double total_size; double current_offset; guint n_pages; double remaining_position; double center_offset_size; ChildInfo *current_child; ChildInfo *next_child; self = BZ_CAROUSEL (widget); total_size = 0; for (children = self->children; children; children = children->next) { ChildInfo *child_info; GtkWidget *child; int min, nat; int child_size; child_info = children->data; child = child_info->widget; if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { gtk_widget_measure (child, self->orientation, height, &min, &nat, NULL, NULL); if (gtk_widget_get_hexpand (child)) child_size = width; else child_size = CLAMP (nat, min, width); } else { gtk_widget_measure (child, self->orientation, width, &min, &nat, NULL, NULL); if (gtk_widget_get_vexpand (child)) child_size = height; else child_size = CLAMP (nat, min, height); } child_info->actual_size = child_size; total_size += child_size; } n_pages = bz_carousel_get_n_pages (self); if (n_pages > 0 && total_size > 0) self->distance = total_size / n_pages; else self->distance = 1; snap_point = 0; for (children = self->children; children; children = children->next) { ChildInfo *child_info; child_info = children->data; child_info->snap_point = snap_point; snap_point += 1.0; if (child_info == self->animation_target_child) adw_spring_animation_set_value_to (ADW_SPRING_ANIMATION (self->animation), child_info->snap_point); } x = 0; y = 0; is_rtl = (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL); current_offset = 0; remaining_position = self->position; center_offset_size = 0; current_child = NULL; next_child = NULL; for (children = self->children; children; children = children->next) { ChildInfo *child_info; child_info = children->data; if (remaining_position < 1.0) { GList *next; double fraction; current_child = child_info; next = children->next; if (next) { next_child = next->data; } current_offset += child_info->actual_size * remaining_position; fraction = remaining_position; if (next_child) { center_offset_size = child_info->actual_size * (1.0 - fraction) + next_child->actual_size * fraction; } else { center_offset_size = child_info->actual_size; } break; } current_offset += child_info->actual_size; remaining_position -= 1.0; } if (!current_child && self->children) { ChildInfo *child_info = self->children->data; center_offset_size = child_info->actual_size; } if (self->orientation == GTK_ORIENTATION_VERTICAL) { y = -current_offset + (height - center_offset_size) / 2.0; } else if (is_rtl) { x = current_offset + (width - center_offset_size) / 2.0; } else { x = -current_offset + (width - center_offset_size) / 2.0; } for (children = self->children; children; children = children->next) { ChildInfo *child_info; GskTransform *transform; int child_width, child_height; child_info = children->data; transform = gsk_transform_new (); if (!gtk_widget_get_visible (child_info->widget)) continue; if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { child_width = child_info->actual_size; child_height = height; } else { child_width = width; child_height = child_info->actual_size; } if (self->orientation == GTK_ORIENTATION_VERTICAL) { child_info->position = y; child_info->visible = child_info->position < height && child_info->position + child_height > 0; transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (0, child_info->position)); y += child_info->actual_size; } else { child_info->position = x; child_info->visible = child_info->position < width && child_info->position + child_width > 0; transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (child_info->position, 0)); if (is_rtl) x -= child_info->actual_size; else x += child_info->actual_size; } gtk_widget_allocate (child_info->widget, child_width, child_height, baseline, transform); } self->is_being_allocated = FALSE; } static void bz_carousel_direction_changed (GtkWidget *widget, GtkTextDirection previous_direction) { BzCarousel *self = BZ_CAROUSEL (widget); update_orientation (self); } static void bz_carousel_constructed (GObject *object) { BzCarousel *self = (BzCarousel *) object; update_orientation (self); G_OBJECT_CLASS (bz_carousel_parent_class)->constructed (object); } static void bz_carousel_dispose (GObject *object) { BzCarousel *self = BZ_CAROUSEL (object); while (self->children) { ChildInfo *info = self->children->data; gtk_widget_unparent (info->widget); self->children = g_list_remove (self->children, info); g_free (info); } g_clear_object (&self->tracker); g_clear_object (&self->animation); g_clear_handle_id (&self->scroll_timeout_id, g_source_remove); G_OBJECT_CLASS (bz_carousel_parent_class)->dispose (object); } static void bz_carousel_finalize (GObject *object) { BzCarousel *self = BZ_CAROUSEL (object); g_list_free_full (self->children, (GDestroyNotify) g_free); G_OBJECT_CLASS (bz_carousel_parent_class)->finalize (object); } static void bz_carousel_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCarousel *self = BZ_CAROUSEL (object); switch (prop_id) { case PROP_N_PAGES: g_value_set_uint (value, bz_carousel_get_n_pages (self)); break; case PROP_POSITION: g_value_set_double (value, bz_carousel_get_position (self)); break; case PROP_ORIENTATION: g_value_set_enum (value, self->orientation); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_carousel_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCarousel *self = BZ_CAROUSEL (object); switch (prop_id) { case PROP_ORIENTATION: { GtkOrientation orientation = g_value_get_enum (value); if (orientation != self->orientation) { self->orientation = orientation; update_orientation (self); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify (G_OBJECT (self), "orientation"); } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_carousel_class_init (BzCarouselClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->constructed = bz_carousel_constructed; object_class->dispose = bz_carousel_dispose; object_class->finalize = bz_carousel_finalize; object_class->get_property = bz_carousel_get_property; object_class->set_property = bz_carousel_set_property; widget_class->measure = bz_carousel_measure; widget_class->size_allocate = bz_carousel_size_allocate; widget_class->direction_changed = bz_carousel_direction_changed; props[PROP_N_PAGES] = g_param_spec_uint ("n-pages", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_POSITION] = g_param_spec_double ("position", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation"); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_PAGE_CHANGED] = g_signal_new ("page-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); gtk_widget_class_set_css_name (widget_class, "carousel"); } static void bz_carousel_init (BzCarousel *self) { GtkEventController *controller; AdwAnimationTarget *target; self->spacing = 0; self->orientation = GTK_ORIENTATION_HORIZONTAL; gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN); self->tracker = adw_swipe_tracker_new (ADW_SWIPEABLE (self)); adw_swipe_tracker_set_enabled (self->tracker, TRUE); adw_swipe_tracker_set_allow_mouse_drag (self->tracker, TRUE); adw_swipe_tracker_set_allow_long_swipes (self->tracker, TRUE); g_signal_connect_object (self->tracker, "begin-swipe", G_CALLBACK (begin_swipe_cb), self, 0); g_signal_connect_object (self->tracker, "update-swipe", G_CALLBACK (update_swipe_cb), self, 0); g_signal_connect_object (self->tracker, "end-swipe", G_CALLBACK (end_swipe_cb), self, 0); controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES); gtk_widget_add_controller (GTK_WIDGET (self), controller); target = adw_callback_animation_target_new ((AdwAnimationTargetFunc) scroll_animation_value_cb, self, NULL); self->animation = adw_spring_animation_new (GTK_WIDGET (self), 0, 0, adw_spring_params_new (1, 0.5, 500), target); adw_spring_animation_set_clamp (ADW_SPRING_ANIMATION (self->animation), TRUE); g_signal_connect_swapped (self->animation, "done", G_CALLBACK (scroll_animation_done_cb), self); } static void bz_carousel_buildable_add_child (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const char *type) { parent_buildable_iface->add_child (buildable, builder, child, type); } static void bz_carousel_buildable_init (GtkBuildableIface *iface) { parent_buildable_iface = g_type_interface_peek_parent (iface); iface->add_child = bz_carousel_buildable_add_child; } static double bz_carousel_get_distance (AdwSwipeable *swipeable) { BzCarousel *self = BZ_CAROUSEL (swipeable); return self->distance; } static double * bz_carousel_get_snap_points (AdwSwipeable *swipeable, int *n_snap_points) { BzCarousel *self = BZ_CAROUSEL (swipeable); guint i, n_pages; double *points; GList *l; n_pages = MAX (g_list_length (self->children), 1); points = g_new0 (double, n_pages); i = 0; for (l = self->children; l; l = l->next) { ChildInfo *info = l->data; points[i++] = info->snap_point; } if (n_snap_points) *n_snap_points = n_pages; return points; } static double bz_carousel_get_progress (AdwSwipeable *swipeable) { BzCarousel *self = BZ_CAROUSEL (swipeable); return bz_carousel_get_position (self); } static double bz_carousel_get_cancel_progress (AdwSwipeable *swipeable) { BzCarousel *self = BZ_CAROUSEL (swipeable); return get_closest_snap_point (self); } static void bz_carousel_swipeable_init (AdwSwipeableInterface *iface) { iface->get_distance = bz_carousel_get_distance; iface->get_snap_points = bz_carousel_get_snap_points; iface->get_progress = bz_carousel_get_progress; iface->get_cancel_progress = bz_carousel_get_cancel_progress; } GtkWidget * bz_carousel_new (void) { return g_object_new (BZ_TYPE_CAROUSEL, NULL); } void bz_carousel_set_widgets (BzCarousel *self, GList *widgets) { GList *l; g_return_if_fail (BZ_IS_CAROUSEL (self)); while (self->children) { ChildInfo *info = self->children->data; gtk_widget_unparent (info->widget); self->children = g_list_remove (self->children, info); g_free (info); } for (l = widgets; l; l = l->next) { GtkWidget *widget = GTK_WIDGET (l->data); ChildInfo *info; g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (gtk_widget_get_parent (widget) == NULL); info = g_new0 (ChildInfo, 1); info->widget = widget; self->children = g_list_append (self->children, info); gtk_widget_set_parent (widget, GTK_WIDGET (self)); } self->position = 0; gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_N_PAGES]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_POSITION]); } static void do_scroll_to (BzCarousel *self, GtkWidget *widget, gboolean animate) { scroll_to (self, widget, 0); if (!animate) adw_animation_skip (self->animation); } typedef struct { BzCarousel *carousel; GtkWidget *widget; gboolean animate; } ScrollData; static void scroll_to_idle_cb (ScrollData *data) { do_scroll_to (data->carousel, data->widget, data->animate); g_object_unref (data->carousel); g_object_unref (data->widget); g_free (data); } void bz_carousel_scroll_to (BzCarousel *self, GtkWidget *widget, gboolean animate) { ScrollData *data; g_return_if_fail (BZ_IS_CAROUSEL (self)); g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (self)); data = g_new (ScrollData, 1); data->carousel = g_object_ref (self); data->widget = g_object_ref (widget); data->animate = animate; g_idle_add_once ((GSourceOnceFunc) scroll_to_idle_cb, data); } GtkWidget * bz_carousel_get_nth_page (BzCarousel *self, guint n) { ChildInfo *info; g_return_val_if_fail (BZ_IS_CAROUSEL (self), NULL); g_return_val_if_fail (n < bz_carousel_get_n_pages (self), NULL); info = get_nth_link (self, n)->data; return info->widget; } guint bz_carousel_get_n_pages (BzCarousel *self) { g_return_val_if_fail (BZ_IS_CAROUSEL (self), 0); return g_list_length (self->children); } double bz_carousel_get_position (BzCarousel *self) { g_return_val_if_fail (BZ_IS_CAROUSEL (self), 0.0); return self->position; } kolunmi-bazaar-7b9c8e1/src/bz-carousel.h000066400000000000000000000030101514314607700202420ustar00rootroot00000000000000/* bz-carousel.h * * Copyright 2025 Alexander Vanhee * Copyright (C) 2019 Alice Mikhaylenko * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define BZ_TYPE_CAROUSEL (bz_carousel_get_type ()) G_DECLARE_FINAL_TYPE (BzCarousel, bz_carousel, BZ, CAROUSEL, GtkWidget) GtkWidget *bz_carousel_new (void) G_GNUC_WARN_UNUSED_RESULT; void bz_carousel_set_widgets (BzCarousel *self, GList *widgets); void bz_carousel_scroll_to (BzCarousel *self, GtkWidget *widget, gboolean animate); GtkWidget *bz_carousel_get_nth_page (BzCarousel *self, guint n); guint bz_carousel_get_n_pages (BzCarousel *self); double bz_carousel_get_position (BzCarousel *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-category-tile.blp000066400000000000000000000013551514314607700215350ustar00rootroot00000000000000using Gtk 4.0; template $BzCategoryTile: Button { styles [ "card", "category-tile", ] child: Box { margin-start: 16; margin-end: 16; margin-top: 24; margin-bottom: 24; orientation: vertical; spacing: 12; valign: center; halign: center; Image { pixel-size: 48; icon-name: bind template.category as <$BzFlathubCategory>.icon-name; visible: bind $invert_boolean($is_null(template.category as <$BzFlathubCategory>.icon-name) as ) as ; styles [ "icon-dropshadow", ] } Label { css-name: "category-tile-label"; halign: center; xalign: 0.5; label: bind template.category as <$BzFlathubCategory>.short-name; } }; } kolunmi-bazaar-7b9c8e1/src/bz-category-tile.c000066400000000000000000000107531514314607700212040ustar00rootroot00000000000000/* bz-category-tile.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-category-tile.h" struct _BzCategoryTile { GtkButton parent_instance; BzFlathubCategory *category; }; G_DEFINE_FINAL_TYPE (BzCategoryTile, bz_category_tile, GTK_TYPE_BUTTON); enum { PROP_0, PROP_CATEGORY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_category_tile_dispose (GObject *object) { BzCategoryTile *self = BZ_CATEGORY_TILE (object); g_clear_object (&self->category); G_OBJECT_CLASS (bz_category_tile_parent_class)->dispose (object); } static void bz_category_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCategoryTile *self = BZ_CATEGORY_TILE (object); switch (prop_id) { case PROP_CATEGORY: g_value_set_object (value, bz_category_tile_get_category (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_category_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCategoryTile *self = BZ_CATEGORY_TILE (object); switch (prop_id) { case PROP_CATEGORY: bz_category_tile_set_category (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static void bz_category_tile_class_init (BzCategoryTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_category_tile_set_property; object_class->get_property = bz_category_tile_get_property; object_class->dispose = bz_category_tile_dispose; props[PROP_CATEGORY] = g_param_spec_object ( "category", NULL, NULL, BZ_TYPE_FLATHUB_CATEGORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-category-tile.ui"); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); } static void bz_category_tile_init (BzCategoryTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_add_css_class (GTK_WIDGET (self), "category-tile"); } GtkWidget * bz_category_tile_new (void) { return g_object_new (BZ_TYPE_CATEGORY_TILE, NULL); } BzFlathubCategory * bz_category_tile_get_category (BzCategoryTile *self) { g_return_val_if_fail (BZ_IS_CATEGORY_TILE (self), NULL); return self->category; } void bz_category_tile_set_category (BzCategoryTile *self, BzFlathubCategory *category) { const char *category_name; g_autofree char *css_class = NULL; g_return_if_fail (BZ_IS_CATEGORY_TILE (self)); g_clear_object (&self->category); if (category != NULL) { self->category = g_object_ref (category); category_name = bz_flathub_category_get_name (category); if (category_name != NULL) { g_autofree char *lowercase_name = g_ascii_strdown (category_name, -1); css_class = g_strdup_printf ("category-%s", lowercase_name); g_strdelimit (css_class, " &/", '-'); gtk_widget_add_css_class (GTK_WIDGET (self), css_class); } } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORY]); }kolunmi-bazaar-7b9c8e1/src/bz-category-tile.h000066400000000000000000000023561514314607700212110ustar00rootroot00000000000000/* bz-category-tile.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-flathub-category.h" G_BEGIN_DECLS #define BZ_TYPE_CATEGORY_TILE (bz_category_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzCategoryTile, bz_category_tile, BZ, CATEGORY_TILE, GtkButton) GtkWidget * bz_category_tile_new (void); BzFlathubCategory * bz_category_tile_get_category (BzCategoryTile *self); void bz_category_tile_set_category (BzCategoryTile *self, BzFlathubCategory *category); G_END_DECLSkolunmi-bazaar-7b9c8e1/src/bz-comet-overlay.c000066400000000000000000000440571514314607700212260ustar00rootroot00000000000000/* bz-comet-overlay.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-comet-overlay.h" typedef struct { double x; double y; double progress; } PulseState; struct _BzCometOverlay { GtkWidget parent_instance; GtkWidget *child; GHashTable *nodes; GArray *pulses; GdkRGBA *pulse_color; }; G_DEFINE_FINAL_TYPE (BzCometOverlay, bz_comet_overlay, GTK_TYPE_WIDGET) enum { PROP_0, PROP_CHILD, PROP_PULSE_COLOR, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void progress_changed (BzComet *comet, GParamSpec *pspec, BzCometOverlay *self); static void animation_done (AdwAnimation *animation, BzCometOverlay *self); static void update_params (BzCometOverlay *self, BzComet *comet, int width, int height); static void pulse_cb (double value, GtkWidget *widget); static void append_pulse (GtkSnapshot *snapshot, double size, double opacity, GdkRGBA *color); static void bz_comet_overlay_dispose (GObject *object) { BzCometOverlay *self = BZ_COMET_OVERLAY (object); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_pointer (&self->nodes, g_hash_table_unref); g_clear_pointer (&self->pulses, g_array_unref); g_clear_pointer (&self->pulse_color, gdk_rgba_free); G_OBJECT_CLASS (bz_comet_overlay_parent_class)->dispose (object); } static void bz_comet_overlay_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCometOverlay *self = BZ_COMET_OVERLAY (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_comet_overlay_get_child (self)); break; case PROP_PULSE_COLOR: g_value_set_boxed (value, bz_comet_overlay_get_pulse_color (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_comet_overlay_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCometOverlay *self = BZ_COMET_OVERLAY (object); switch (prop_id) { case PROP_CHILD: bz_comet_overlay_set_child (self, g_value_get_object (value)); break; case PROP_PULSE_COLOR: bz_comet_overlay_set_pulse_color (self, g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_comet_overlay_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzCometOverlay *self = BZ_COMET_OVERLAY (widget); // GHashTableIter iter = { 0 }; if (self->child != NULL && gtk_widget_should_layout (self->child)) gtk_widget_allocate (self->child, width, height, baseline, NULL); /* This causes visual hiccups, keeping for reference */ // g_hash_table_iter_init (&iter, self->nodes); // for (;;) // { // BzComet *comet = NULL; // GskRenderNode *node = NULL; // // if (!g_hash_table_iter_next ( // &iter, (gpointer *) &comet, (gpointer *) &node)) // break; // // update_params (self, comet, width, height); // } } static void bz_comet_overlay_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzCometOverlay *self = BZ_COMET_OVERLAY (widget); GdkRGBA *color = NULL; GHashTableIter iter = { 0 }; if (self->child != NULL) gtk_widget_snapshot_child (widget, self->child, snapshot); color = bz_comet_overlay_get_pulse_color (self); g_hash_table_iter_init (&iter, self->nodes); for (;;) { BzComet *comet = NULL; GskRenderNode *node = NULL; double progress = 0.0; GskPath *path = NULL; double path_length = 0.0; g_autoptr (GskPathMeasure) path_measure = NULL; GskPathPoint path_point = { 0 }; graphene_point_t end_position = { 0 }; double pulse_radius = 0.0; GskRoundedRect clip = { 0 }; graphene_point_t paintable_position = { 0 }; GdkRGBA clip_color = { 0 }; if (!g_hash_table_iter_next ( &iter, (gpointer *) &comet, (gpointer *) &node)) break; progress = bz_comet_get_progress (comet); path = bz_comet_get_path (comet); path_length = bz_comet_get_path_length (comet); gsk_path_get_end_point (path, &path_point); gsk_path_point_get_position (&path_point, path, &end_position); pulse_radius = progress / path_length * 150.0; clip_color = *color; clip_color.alpha = color->alpha * (1.0 - (progress / path_length)); clip.bounds = GRAPHENE_RECT_INIT ( end_position.x - pulse_radius, end_position.y - pulse_radius, pulse_radius * 2.0, pulse_radius * 2.0); clip.corner[0].width = pulse_radius; clip.corner[0].height = pulse_radius; clip.corner[1].width = pulse_radius; clip.corner[1].height = pulse_radius; clip.corner[2].width = pulse_radius; clip.corner[2].height = pulse_radius; clip.corner[3].width = pulse_radius; clip.corner[3].height = pulse_radius; gtk_snapshot_push_rounded_clip (snapshot, &clip); gtk_snapshot_append_color (snapshot, &clip_color, &clip.bounds); gtk_snapshot_pop (snapshot); path_measure = gsk_path_measure_new (path); gsk_path_measure_get_point (path_measure, progress, &path_point); gsk_path_point_get_position (&path_point, path, &paintable_position); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &paintable_position); gtk_snapshot_append_node (snapshot, node); gtk_snapshot_restore (snapshot); } for (guint i = 0; i < self->pulses->len; i++) { PulseState *pulse = NULL; pulse = &g_array_index (self->pulses, PulseState, i); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (pulse->x, pulse->y)); append_pulse (snapshot, pulse->progress * 200.0, 1.0 - pulse->progress, color); gtk_snapshot_restore (snapshot); } g_array_set_size (self->pulses, 0); } static void bz_comet_overlay_class_init (BzCometOverlayClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_comet_overlay_dispose; object_class->get_property = bz_comet_overlay_get_property; object_class->set_property = bz_comet_overlay_set_property; props[PROP_CHILD] = g_param_spec_object ( "child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PULSE_COLOR] = g_param_spec_boxed ( "pulse-color", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->size_allocate = bz_comet_overlay_size_allocate; widget_class->snapshot = bz_comet_overlay_snapshot; } static void bz_comet_overlay_init (BzCometOverlay *self) { AdwStyleManager *style_manager = NULL; self->nodes = g_hash_table_new_full ( g_direct_hash, g_direct_equal, g_object_unref, (GDestroyNotify) gsk_render_node_unref); self->pulses = g_array_new (FALSE, FALSE, sizeof (PulseState)); style_manager = adw_style_manager_get_default (); self->pulse_color = adw_style_manager_get_accent_color_rgba (style_manager); } GtkWidget * bz_comet_overlay_new (void) { return g_object_new (BZ_TYPE_COMET_OVERLAY, NULL); } void bz_comet_overlay_set_child (BzCometOverlay *self, GtkWidget *child) { g_return_if_fail (BZ_IS_COMET_OVERLAY (self)); g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (self->child == child) return; if (child != NULL) g_return_if_fail (gtk_widget_get_parent (child) == NULL); g_clear_pointer (&self->child, gtk_widget_unparent); self->child = child; if (child != NULL) gtk_widget_set_parent (child, GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]); } GtkWidget * bz_comet_overlay_get_child (BzCometOverlay *self) { g_return_val_if_fail (BZ_IS_COMET_OVERLAY (self), NULL); return self->child; } void bz_comet_overlay_set_pulse_color (BzCometOverlay *self, GdkRGBA *color) { g_return_if_fail (BZ_IS_COMET_OVERLAY (self)); if (self->pulse_color != NULL && color != NULL && gdk_rgba_equal (self->pulse_color, color)) return; g_clear_pointer (&self->pulse_color, gdk_rgba_free); if (color != NULL) self->pulse_color = gdk_rgba_copy (color); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PULSE_COLOR]); } GdkRGBA * bz_comet_overlay_get_pulse_color (BzCometOverlay *self) { AdwStyleManager *style_manager = NULL; g_return_val_if_fail (BZ_IS_COMET_OVERLAY (self), NULL); if (self->pulse_color != NULL) return self->pulse_color; style_manager = adw_style_manager_get_default (); return adw_style_manager_get_accent_color_rgba (style_manager); } void bz_comet_overlay_spawn (BzCometOverlay *self, BzComet *comet) { AdwAnimationTarget *target = NULL; AdwSpringParams *spring = NULL; GtkWidget *from = NULL; GtkWidget *to = NULL; GdkPaintable *paintable = NULL; g_autoptr (AdwAnimation) animation = NULL; g_return_if_fail (BZ_IS_COMET_OVERLAY (self)); g_return_if_fail (BZ_IS_COMET (comet)); from = bz_comet_get_from (comet); to = bz_comet_get_to (comet); paintable = bz_comet_get_paintable (comet); g_return_if_fail (from != NULL && gtk_widget_is_ancestor (from, GTK_WIDGET (self))); g_return_if_fail (to != NULL && gtk_widget_is_ancestor (to, GTK_WIDGET (self))); g_return_if_fail (paintable != NULL); target = adw_property_animation_target_new (G_OBJECT (comet), "progress"); spring = adw_spring_params_new (1.0, 0.1, 3.0); animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, spring, target); adw_spring_animation_set_epsilon ( ADW_SPRING_ANIMATION (animation), 0.0001); g_object_bind_property (comet, "path-length", animation, "value-to", G_BINDING_DEFAULT); update_params ( self, comet, gtk_widget_get_width (GTK_WIDGET (self)), gtk_widget_get_height (GTK_WIDGET (self))); g_signal_connect (comet, "notify::progress", G_CALLBACK (progress_changed), self); bz_comet_set_progress (comet, 0.0); g_signal_connect (animation, "done", G_CALLBACK (animation_done), self); g_object_notify (G_OBJECT (comet), "progress"); adw_animation_play (animation); } void bz_comet_overlay_pulse_child (BzCometOverlay *self, GtkWidget *child) { AdwAnimationTarget *target = NULL; AdwSpringParams *spring = NULL; g_autoptr (AdwAnimation) animation = NULL; g_return_if_fail (BZ_IS_COMET_OVERLAY (self)); g_return_if_fail (GTK_IS_WIDGET (child) && gtk_widget_is_ancestor (child, GTK_WIDGET (self))); target = adw_callback_animation_target_new ( (AdwAnimationTargetFunc) pulse_cb, g_object_ref (child), g_object_unref); spring = adw_spring_params_new (1.5, 0.1, 5.0); animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 1.0, spring, target); adw_spring_animation_set_epsilon ( ADW_SPRING_ANIMATION (animation), 0.0001); adw_animation_play (animation); } static void progress_changed (BzComet *comet, GParamSpec *pspec, BzCometOverlay *self) { double path_length = 0.0; double progress = 0.0; GdkPaintable *paintable = NULL; double intrinsic_width = 0; double t = 0.0; double size_scale = 0.0; double icon_size = 0.0; double grad_size = 0.0; GdkRGBA *color = NULL; g_autoptr (GtkSnapshot) snapshot = NULL; path_length = bz_comet_get_path_length (comet); progress = bz_comet_get_progress (comet); paintable = bz_comet_get_paintable (comet); intrinsic_width = gdk_paintable_get_intrinsic_width (paintable); t = progress / path_length; size_scale = 1.0 - 4.0 * (t - 0.5) * (t - 0.5); icon_size = size_scale * intrinsic_width; grad_size = MAX (1.0, (path_length - progress) / path_length * intrinsic_width * 2.0); color = bz_comet_overlay_get_pulse_color (self); snapshot = gtk_snapshot_new (); append_pulse (snapshot, grad_size, 1.0 - (path_length - progress), color); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-icon_size / 2.0, -icon_size / 2.0)); gdk_paintable_snapshot (paintable, snapshot, icon_size, icon_size); gtk_snapshot_restore (snapshot); g_hash_table_replace (self->nodes, g_object_ref (comet), gtk_snapshot_to_node (snapshot)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void animation_done (AdwAnimation *animation, BzCometOverlay *self) { AdwAnimationTarget *target = NULL; GObject *comet = NULL; target = adw_animation_get_target (animation); comet = adw_property_animation_target_get_object ( ADW_PROPERTY_ANIMATION_TARGET (target)); g_hash_table_remove (self->nodes, comet); } static void update_params (BzCometOverlay *self, BzComet *comet, int width, int height) { GtkWidget *from = NULL; GtkWidget *to = NULL; graphene_rect_t from_rect = { 0 }; graphene_rect_t to_rect = { 0 }; graphene_point_t from_center = { 0 }; graphene_point_t to_center = { 0 }; graphene_point_t low_interp = { 0 }; graphene_point_t high_interp = { 0 }; // GskPath *last_path = NULL; g_autoptr (GskPathBuilder) path_builder = NULL; g_autoptr (GskPath) path = NULL; g_autoptr (GskPathMeasure) path_measure = NULL; float distance = 0.0; from = bz_comet_get_from (comet); to = bz_comet_get_to (comet); g_assert (from != NULL); g_assert (to != NULL); g_assert (gtk_widget_compute_bounds (from, GTK_WIDGET (self), &from_rect)); g_assert (gtk_widget_compute_bounds (to, GTK_WIDGET (self), &to_rect)); graphene_rect_get_center (&from_rect, &from_center); graphene_rect_get_center (&to_rect, &to_center); graphene_point_interpolate (&from_center, &to_center, 0.333, &low_interp); graphene_point_interpolate (&to_center, &from_center, 0.333, &high_interp); path_builder = gsk_path_builder_new (); gsk_path_builder_move_to (path_builder, from_center.x, from_center.y); gsk_path_builder_cubic_to ( path_builder, high_interp.x, from_center.y, to_center.x, low_interp.y, to_center.x, to_center.y); path = gsk_path_builder_to_path (path_builder); path_measure = gsk_path_measure_new (path); distance = gsk_path_measure_get_length (path_measure); bz_comet_set_path (comet, path); bz_comet_set_path_length (comet, distance); } static void pulse_cb (double value, GtkWidget *widget) { BzCometOverlay *self = NULL; graphene_rect_t rect = { 0 }; gboolean result = FALSE; PulseState pulse = { 0 }; self = (BzCometOverlay *) gtk_widget_get_ancestor (widget, BZ_TYPE_COMET_OVERLAY); if (self == NULL) { g_warning ("Couldn't find ancestor BzCometOverlay for pulse!"); return; } result = gtk_widget_compute_bounds (widget, GTK_WIDGET (self), &rect); if (!result) { g_warning ("Couldn't compute bounds of widget for pulse!"); return; } pulse.x = rect.origin.x + rect.size.width / 2.0; pulse.y = rect.origin.y + rect.size.height / 2.0; pulse.progress = value; g_array_append_val (self->pulses, pulse); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void append_pulse (GtkSnapshot *snapshot, double size, double opacity, GdkRGBA *color) { const GdkRGBA transparent = { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 0.0 }; GdkRGBA pulse_color = { 0 }; GskColorStop grad_stops[2] = { 0 }; if (size < 1.0) return; pulse_color = *color; pulse_color.alpha = color->alpha * 0.75 * opacity; grad_stops[0].color = pulse_color; grad_stops[0].offset = 0.9; grad_stops[1].color = transparent; grad_stops[1].offset = 0.9; gtk_snapshot_append_radial_gradient ( snapshot, &GRAPHENE_RECT_INIT (-size / 2.0, -size / 2.0, size, size), &GRAPHENE_POINT_INIT (0.0, 0.0), size / 2.0, size / 2.0, 0.0, 1.0, grad_stops, G_N_ELEMENTS (grad_stops)); } kolunmi-bazaar-7b9c8e1/src/bz-comet-overlay.h000066400000000000000000000031071514314607700212220ustar00rootroot00000000000000/* bz-comet-overlay.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-comet.h" G_BEGIN_DECLS #define BZ_TYPE_COMET_OVERLAY (bz_comet_overlay_get_type ()) G_DECLARE_FINAL_TYPE (BzCometOverlay, bz_comet_overlay, BZ, COMET_OVERLAY, GtkWidget) GtkWidget * bz_comet_overlay_new (void); void bz_comet_overlay_set_child (BzCometOverlay *self, GtkWidget *child); GtkWidget * bz_comet_overlay_get_child (BzCometOverlay *self); void bz_comet_overlay_set_pulse_color (BzCometOverlay *self, GdkRGBA *color); GdkRGBA * bz_comet_overlay_get_pulse_color (BzCometOverlay *self); void bz_comet_overlay_spawn (BzCometOverlay *self, BzComet *comet); void bz_comet_overlay_pulse_child (BzCometOverlay *self, GtkWidget *child); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-comet.txt000066400000000000000000000007001514314607700201270ustar00rootroot00000000000000prefix=bz name=comet parent-prefix=g parent-name=object author=AUTOGEN include= property=name char G_TYPE_STRING string property=from GtkWidget GTK_TYPE_WIDGET object property=to GtkWidget GTK_TYPE_WIDGET object property=paintable GdkPaintable GDK_TYPE_PAINTABLE object property=path GskPath GSK_TYPE_PATH boxed gsk_path_unref gsk_path_ref property=path_length double G_TYPE_DOUBLE double property=progress double G_TYPE_DOUBLE double kolunmi-bazaar-7b9c8e1/src/bz-content-provider.c000066400000000000000000000444771514314607700217500ustar00rootroot00000000000000/* bz-content-provider.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::CONTENT-PROVIDER" #include "config.h" #include #include #include "bz-content-provider.h" #include "bz-env.h" #include "bz-io.h" #include "bz-util.h" struct _BzContentProvider { GObject parent_instance; GListModel *input_files; BzParser *parser; GListStore *input_mirror; GHashTable *input_tracking; GListStore *outputs; GtkFlattenListModel *impl_model; }; static void list_model_iface_init (GListModelInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzContentProvider, bz_content_provider, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init)) enum { PROP_0, PROP_INPUT_FILES, PROP_PARSER, PROP_HAS_INPUTS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; BZ_DEFINE_DATA ( input_init, InputInit, { GFile *file; }, BZ_RELEASE_DATA (file, g_object_unref)) static DexFuture * input_init_fiber (InputInitData *data); BZ_DEFINE_DATA ( input_load, InputLoad, { GFile *file; BzParser *parser; }, BZ_RELEASE_DATA (file, g_object_unref); BZ_RELEASE_DATA (parser, g_object_unref)) static DexFuture * input_load_fiber (InputLoadData *data); BZ_DEFINE_DATA ( input_tracking, InputTracking, { GMutex mutex; GWeakRef self; char *path; GFileMonitor *monitor; GListStore *output; DexFuture *init; DexFuture *task; }, g_mutex_clear (&self->mutex); g_weak_ref_clear (&self->self); BZ_RELEASE_DATA (path, g_free); BZ_RELEASE_DATA (monitor, g_object_unref); BZ_RELEASE_DATA (output, g_object_unref); BZ_RELEASE_DATA (init, dex_unref); BZ_RELEASE_DATA (task, dex_unref)) static DexFuture * input_init_finally (DexFuture *future, InputTrackingData *data); static DexFuture * input_load_finally (DexFuture *future, InputTrackingData *data); static void impl_model_changed (BzContentProvider *self, guint position, guint removed, guint added, GListModel *impl_model); static void input_files_changed (BzContentProvider *self, guint position, guint removed, guint added, GListModel *input_files); static void input_file_changed_on_disk (InputTrackingData *data, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GFileMonitor *monitor); static gboolean commence_reload (InputTrackingData *data); static void bz_content_provider_dispose (GObject *object) { BzContentProvider *self = BZ_CONTENT_PROVIDER (object); g_clear_object (&self->input_files); g_clear_object (&self->parser); g_clear_object (&self->input_mirror); g_clear_pointer (&self->input_tracking, g_hash_table_unref); g_clear_object (&self->outputs); g_clear_object (&self->impl_model); G_OBJECT_CLASS (bz_content_provider_parent_class)->dispose (object); } static void bz_content_provider_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzContentProvider *self = BZ_CONTENT_PROVIDER (object); switch (prop_id) { case PROP_INPUT_FILES: g_value_set_object (value, bz_content_provider_get_input_files (self)); break; case PROP_PARSER: g_value_set_object (value, bz_content_provider_get_parser (self)); break; case PROP_HAS_INPUTS: g_value_set_boolean (value, bz_content_provider_get_has_inputs (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_content_provider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzContentProvider *self = BZ_CONTENT_PROVIDER (object); switch (prop_id) { case PROP_INPUT_FILES: bz_content_provider_set_input_files (self, g_value_get_object (value)); break; case PROP_PARSER: bz_content_provider_set_parser (self, g_value_get_object (value)); break; case PROP_HAS_INPUTS: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_content_provider_class_init (BzContentProviderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_content_provider_set_property; object_class->get_property = bz_content_provider_get_property; object_class->dispose = bz_content_provider_dispose; props[PROP_INPUT_FILES] = g_param_spec_object ( "input-files", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PARSER] = g_param_spec_object ( "parser", NULL, NULL, BZ_TYPE_PARSER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_HAS_INPUTS] = g_param_spec_boolean ( "has-inputs", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_content_provider_init (BzContentProvider *self) { self->input_mirror = g_list_store_new (G_TYPE_FILE); self->input_tracking = g_hash_table_new_full ( g_direct_hash, g_direct_equal, g_object_unref, input_tracking_data_unref); self->outputs = g_list_store_new (G_TYPE_LIST_MODEL); self->impl_model = gtk_flatten_list_model_new (g_object_ref (G_LIST_MODEL (self->outputs))); g_signal_connect_swapped ( self->impl_model, "items-changed", G_CALLBACK (impl_model_changed), self); } static GType list_model_get_item_type (GListModel *list) { return G_TYPE_OBJECT; } static guint list_model_get_n_items (GListModel *list) { BzContentProvider *self = BZ_CONTENT_PROVIDER (list); return g_list_model_get_n_items (G_LIST_MODEL (self->impl_model)); } static gpointer list_model_get_item (GListModel *list, guint position) { BzContentProvider *self = BZ_CONTENT_PROVIDER (list); return g_list_model_get_item (G_LIST_MODEL (self->impl_model), position); } static void list_model_iface_init (GListModelInterface *iface) { iface->get_item_type = list_model_get_item_type; iface->get_n_items = list_model_get_n_items; iface->get_item = list_model_get_item; } BzContentProvider * bz_content_provider_new (void) { return g_object_new (BZ_TYPE_CONTENT_PROVIDER, NULL); } void bz_content_provider_set_input_files (BzContentProvider *self, GListModel *input_files) { guint old_length = 0; g_return_if_fail (BZ_IS_CONTENT_PROVIDER (self)); g_return_if_fail (input_files == NULL || G_IS_LIST_MODEL (input_files)); if (self->input_files != NULL) { old_length = g_list_model_get_n_items (self->input_files); g_signal_handlers_disconnect_by_func ( self->input_files, input_files_changed, self); } g_clear_object (&self->input_files); g_hash_table_remove_all (self->input_tracking); g_list_store_remove_all (self->input_mirror); g_list_store_remove_all (self->outputs); if (input_files != NULL) { self->input_files = g_object_ref (input_files); g_signal_connect_swapped ( input_files, "items-changed", G_CALLBACK (input_files_changed), self); input_files_changed ( self, 0, old_length, g_list_model_get_n_items (input_files), input_files); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INPUT_FILES]); } GListModel * bz_content_provider_get_input_files (BzContentProvider *self) { g_return_val_if_fail (BZ_IS_CONTENT_PROVIDER (self), NULL); return self->input_files; } void bz_content_provider_set_parser (BzContentProvider *self, BzParser *parser) { GHashTableIter iter = { 0 }; g_return_if_fail (BZ_IS_CONTENT_PROVIDER (self)); g_return_if_fail (parser == NULL || BZ_IS_PARSER (parser)); g_clear_object (&self->parser); if (parser != NULL) self->parser = g_object_ref (parser); g_hash_table_iter_init (&iter, self->input_tracking); for (;;) { GFile *file = NULL; InputTrackingData *data = NULL; if (!g_hash_table_iter_next ( &iter, (gpointer *) &file, (gpointer *) &data)) break; commence_reload (data); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PARSER]); } BzParser * bz_content_provider_get_parser (BzContentProvider *self) { g_return_val_if_fail (BZ_IS_CONTENT_PROVIDER (self), NULL); return self->parser; } gboolean bz_content_provider_get_has_inputs (BzContentProvider *self) { g_return_val_if_fail (BZ_IS_CONTENT_PROVIDER (self), FALSE); return self->input_files != NULL && g_list_model_get_n_items (self->input_files) > 0 && g_list_model_get_n_items (G_LIST_MODEL (self)) > 0; } static void impl_model_changed (BzContentProvider *self, guint position, guint removed, guint added, GListModel *impl_model) { g_list_model_items_changed ( G_LIST_MODEL (self), position, removed, added); } static void input_files_changed (BzContentProvider *self, guint position, guint removed, guint added, GListModel *input_files) { gboolean emit_has_inputs = FALSE; g_autofree GFile **additions = NULL; g_autofree GListStore **new_outputs = NULL; emit_has_inputs = g_list_model_get_n_items (input_files) == 0 || g_list_model_get_n_items (G_LIST_MODEL (self->input_mirror)) == 0; if (removed > 0) { for (guint i = 0; i < removed; i++) { g_autoptr (GFile) removal = NULL; InputTrackingData *data = NULL; removal = g_list_model_get_item ( G_LIST_MODEL (self->input_mirror), position + i); data = g_hash_table_lookup (self->input_tracking, removal); g_assert (data != NULL); g_mutex_lock (&data->mutex); dex_clear (&data->task); g_mutex_unlock (&data->mutex); g_hash_table_remove (self->input_tracking, removal); } } if (added > 0) { additions = g_malloc0_n (added, sizeof (*additions)); for (guint i = 0; i < added; i++) additions[i] = g_list_model_get_item ( G_LIST_MODEL (self->input_files), position + i); new_outputs = g_malloc0_n (added, sizeof (*new_outputs)); for (guint i = 0; i < added; i++) new_outputs[i] = g_list_store_new (G_TYPE_OBJECT); } g_list_store_splice (self->input_mirror, position, removed, (gpointer *) additions, added); g_list_store_splice (self->outputs, position, removed, (gpointer *) new_outputs, added); for (guint i = 0; i < added; i++) { g_autoptr (InputInitData) init_data = NULL; g_autoptr (InputTrackingData) tracking_data = NULL; g_autoptr (DexFuture) future = NULL; init_data = input_init_data_new (); init_data->file = g_object_ref (additions[i]); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) input_init_fiber, input_init_data_ref (init_data), input_init_data_unref); tracking_data = input_tracking_data_new (); g_mutex_init (&tracking_data->mutex); g_weak_ref_init (&tracking_data->self, self); tracking_data->path = g_file_get_path (additions[i]); tracking_data->output = g_steal_pointer (&new_outputs[i]); g_mutex_lock (&tracking_data->mutex); future = dex_future_finally ( future, (DexFutureCallback) input_init_finally, input_tracking_data_ref (tracking_data), input_tracking_data_unref); tracking_data->init = g_steal_pointer (&future); g_mutex_unlock (&tracking_data->mutex); g_hash_table_replace ( self->input_tracking, g_steal_pointer (&additions[i]), input_tracking_data_ref (tracking_data)); } if (emit_has_inputs) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_INPUTS]); } static void input_file_changed_on_disk (InputTrackingData *data, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GFileMonitor *monitor) { if (event_type == G_FILE_MONITOR_EVENT_CHANGED || event_type == G_FILE_MONITOR_EVENT_CREATED || event_type == G_FILE_MONITOR_EVENT_DELETED) g_idle_add_full ( G_PRIORITY_DEFAULT, (GSourceFunc) commence_reload, input_tracking_data_ref (data), input_tracking_data_unref); } static DexFuture * input_init_fiber (InputInitData *data) { GFile *file = data->file; g_autoptr (GError) local_error = NULL; g_autoptr (GFileMonitor) monitor = NULL; monitor = g_file_monitor_file ( file, G_FILE_MONITOR_NONE, NULL, &local_error); if (monitor == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); return dex_future_new_for_object (monitor); } static DexFuture * input_init_finally (DexFuture *future, InputTrackingData *data) { g_autoptr (BzContentProvider) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GMutexLocker) locker = NULL; const GValue *value = NULL; locker = g_mutex_locker_new (&data->mutex); dex_clear (&data->init); bz_weak_get_or_return_reject (self, &data->self); g_list_store_remove_all (data->output); value = dex_future_get_value (future, &local_error); if (value != NULL) { data->monitor = g_value_dup_object (value); g_signal_connect_swapped ( data->monitor, "changed", G_CALLBACK (input_file_changed_on_disk), data); g_clear_pointer (&locker, g_mutex_locker_free); commence_reload (data); } else g_warning ("Could not init object watch at path %s: %s", data->path, local_error->message); return NULL; } static DexFuture * input_load_fiber (InputLoadData *data) { GFile *file = data->file; BzParser *parser = data->parser; g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (GHashTable) parse_results = NULL; GObject *object = NULL; bytes = dex_await_boxed (dex_file_load_contents_bytes (file), &local_error); if (bytes == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); parse_results = bz_parser_process_bytes (parser, bytes, &local_error); if (parse_results == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); object = g_value_get_object (g_hash_table_lookup (parse_results, "/")); if (object == NULL) return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Parser returned invalid results"); return dex_future_new_for_object (object); } static DexFuture * input_load_finally (DexFuture *future, InputTrackingData *data) { g_autoptr (BzContentProvider) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GMutexLocker) locker = NULL; const GValue *value = NULL; locker = g_mutex_locker_new (&data->mutex); g_list_store_remove_all (data->output); bz_weak_get_or_return_reject (self, &data->self); value = dex_future_get_value (future, &local_error); if (value != NULL) g_list_store_append (data->output, g_value_get_object (value)); else if (local_error->domain != G_IO_ERROR) g_warning ("Could not load object at path %s: %s", data->path, local_error->message); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_INPUTS]); return NULL; } static gboolean commence_reload (InputTrackingData *data) { g_autoptr (BzContentProvider) self = NULL; g_autoptr (GMutexLocker) locker = NULL; g_autoptr (InputLoadData) load_data = NULL; g_autoptr (DexFuture) future = NULL; locker = g_mutex_locker_new (&data->mutex); dex_clear (&data->task); self = g_weak_ref_get (&data->self); if (self == NULL) goto done; if (self->parser == NULL) goto done; load_data = input_load_data_new (); load_data->file = g_file_new_for_path (data->path); load_data->parser = g_object_ref (self->parser); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) input_load_fiber, input_load_data_ref (load_data), input_load_data_unref); future = dex_future_finally ( future, (DexFutureCallback) input_load_finally, input_tracking_data_ref (data), input_tracking_data_unref); data->task = g_steal_pointer (&future); done: return G_SOURCE_REMOVE; } kolunmi-bazaar-7b9c8e1/src/bz-content-provider.h000066400000000000000000000030101514314607700217270ustar00rootroot00000000000000/* bz-content-provider.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-parser.h" G_BEGIN_DECLS #define BZ_TYPE_CONTENT_PROVIDER (bz_content_provider_get_type ()) G_DECLARE_FINAL_TYPE (BzContentProvider, bz_content_provider, BZ, CONTENT_PROVIDER, GObject) BzContentProvider * bz_content_provider_new (void); void bz_content_provider_set_input_files (BzContentProvider *self, GListModel *input_files); GListModel * bz_content_provider_get_input_files (BzContentProvider *self); void bz_content_provider_set_parser (BzContentProvider *self, BzParser *parser); BzParser * bz_content_provider_get_parser (BzContentProvider *self); gboolean bz_content_provider_get_has_inputs (BzContentProvider *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-context-row.c000066400000000000000000000054221514314607700207220ustar00rootroot00000000000000/* bz-context-row.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-context-row.h" GType bz_importance_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GEnumValue values[] = { { BZ_IMPORTANCE_UNIMPORTANT, "BZ_IMPORTANCE_UNIMPORTANT", "unimportant" }, { BZ_IMPORTANCE_NEUTRAL, "BZ_IMPORTANCE_NEUTRAL", "neutral" }, { BZ_IMPORTANCE_INFORMATION, "BZ_IMPORTANCE_INFORMATION", "information" }, { BZ_IMPORTANCE_WARNING, "BZ_IMPORTANCE_WARNING", "warning" }, { BZ_IMPORTANCE_IMPORTANT, "BZ_IMPORTANCE_IMPORTANT", "important" }, { 0, NULL, NULL } }; type = g_enum_register_static ("BzImportance", values); } return type; } const gchar * bz_context_row_importance_to_css_class (BzImportance importance) { switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: return "green"; case BZ_IMPORTANCE_NEUTRAL: return "grey"; case BZ_IMPORTANCE_INFORMATION: return "yellow"; case BZ_IMPORTANCE_WARNING: return "orange"; case BZ_IMPORTANCE_IMPORTANT: return "red"; default: return "grey"; } } AdwActionRow * bz_context_row_new (const gchar *icon_name, BzImportance importance, const gchar *title, const gchar *subtitle) { AdwActionRow *row; GtkWidget *icon; const gchar *css_class; g_return_val_if_fail (icon_name != NULL, NULL); g_return_val_if_fail (title != NULL, NULL); row = ADW_ACTION_ROW (adw_action_row_new ()); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), title); if (subtitle != NULL) adw_action_row_set_subtitle (row, subtitle); icon = gtk_image_new_from_icon_name (icon_name); gtk_widget_set_valign (icon, GTK_ALIGN_CENTER); gtk_widget_add_css_class (icon, "circular-lozenge"); css_class = bz_context_row_importance_to_css_class (importance); gtk_widget_add_css_class (icon, css_class); adw_action_row_add_prefix (row, icon); return row; } kolunmi-bazaar-7b9c8e1/src/bz-context-row.h000066400000000000000000000025271514314607700207320ustar00rootroot00000000000000/* bz-context-row.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS typedef enum { BZ_IMPORTANCE_UNIMPORTANT, BZ_IMPORTANCE_NEUTRAL, BZ_IMPORTANCE_INFORMATION, BZ_IMPORTANCE_WARNING, BZ_IMPORTANCE_IMPORTANT, } BzImportance; #define BZ_TYPE_IMPORTANCE (bz_importance_get_type ()) GType bz_importance_get_type (void) G_GNUC_CONST; AdwActionRow * bz_context_row_new (const gchar *icon_name, BzImportance importance, const gchar *title, const gchar *subtitle); const gchar * bz_context_row_importance_to_css_class (BzImportance importance); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-context-tile.blp000066400000000000000000000011621514314607700214000ustar00rootroot00000000000000using Gtk 4.0; template $BzContextTile: Button { styles [ "context-tile", "flat", ] focusable: false; Box { orientation: vertical; spacing: 4; hexpand: true; Button ring_button { styles [ "lozenge-ring-button", ] halign: center; valign: center; margin-bottom: 4; child: Box lozenge { styles [ "lozenge", ] halign: center; }; } Label label { styles [ "context-tile-text", ] justify: center; wrap: true; wrap-mode: word_char; xalign: 0.5; } } } kolunmi-bazaar-7b9c8e1/src/bz-context-tile.c000066400000000000000000000167521514314607700210600ustar00rootroot00000000000000/* bz-context-tile.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-context-tile.h" #include struct _BzContextTile { GtkButton parent_instance; char *lozenge_style; /* Template widgets */ GtkButton *ring_button; GtkBox *lozenge; GtkLabel *label; }; G_DEFINE_FINAL_TYPE (BzContextTile, bz_context_tile, GTK_TYPE_BUTTON) enum { PROP_0, PROP_LOZENGE_CHILD, PROP_LABEL, PROP_LOZENGE_STYLE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_context_tile_dispose (GObject *object) { BzContextTile *self = BZ_CONTEXT_TILE (object); g_clear_pointer (&self->lozenge_style, g_free); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_CONTEXT_TILE); G_OBJECT_CLASS (bz_context_tile_parent_class)->dispose (object); } static void bz_context_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzContextTile *self = BZ_CONTEXT_TILE (object); switch (prop_id) { case PROP_LOZENGE_CHILD: g_value_set_object (value, bz_context_tile_get_lozenge_child (self)); break; case PROP_LABEL: g_value_set_string (value, bz_context_tile_get_label (self)); break; case PROP_LOZENGE_STYLE: g_value_set_string (value, bz_context_tile_get_lozenge_style (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_context_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzContextTile *self = BZ_CONTEXT_TILE (object); switch (prop_id) { case PROP_LOZENGE_CHILD: bz_context_tile_set_lozenge_child (self, g_value_get_object (value)); break; case PROP_LABEL: bz_context_tile_set_label (self, g_value_get_string (value)); break; case PROP_LOZENGE_STYLE: bz_context_tile_set_lozenge_style (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_context_tile_class_init (BzContextTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_context_tile_set_property; object_class->get_property = bz_context_tile_get_property; object_class->dispose = bz_context_tile_dispose; props[PROP_LOZENGE_CHILD] = g_param_spec_object ( "lozenge-child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_LABEL] = g_param_spec_string ( "label", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_LOZENGE_STYLE] = g_param_spec_string ( "lozenge-style", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-context-tile.ui"); gtk_widget_class_bind_template_child (widget_class, BzContextTile, lozenge); gtk_widget_class_bind_template_child (widget_class, BzContextTile, label); gtk_widget_class_bind_template_child (widget_class, BzContextTile, ring_button); } static void on_enter_notify (GtkEventController *controller, gpointer user_data) { g_autoptr (GdkCursor) cursor = gdk_cursor_new_from_name ("pointer", NULL); gtk_widget_set_cursor (GTK_WIDGET (user_data), cursor); } static void on_leave_notify (GtkEventController *controller, gpointer user_data) { gtk_widget_set_cursor (GTK_WIDGET (user_data), NULL); } static void on_ring_button_clicked (GtkButton *ring_button, gpointer user_data) { BzContextTile *self = BZ_CONTEXT_TILE (user_data); g_signal_emit_by_name (self, "clicked"); } static void bz_context_tile_init (BzContextTile *self) { GtkEventController *enter_leave = gtk_event_controller_motion_new (); gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect (self->ring_button, "clicked", G_CALLBACK (on_ring_button_clicked), self); g_signal_connect (enter_leave, "enter", G_CALLBACK (on_enter_notify), GTK_WIDGET (self)); g_signal_connect (enter_leave, "leave", G_CALLBACK (on_leave_notify), GTK_WIDGET (self)); gtk_widget_add_controller (GTK_WIDGET (self), enter_leave); } BzContextTile * bz_context_tile_new (void) { return g_object_new (BZ_TYPE_CONTEXT_TILE, NULL); } GtkWidget * bz_context_tile_get_lozenge_child (BzContextTile *self) { g_return_val_if_fail (BZ_IS_CONTEXT_TILE (self), NULL); return gtk_widget_get_first_child (GTK_WIDGET (self->lozenge)); } void bz_context_tile_set_lozenge_child (BzContextTile *self, GtkWidget *child) { GtkWidget *old_child; g_return_if_fail (BZ_IS_CONTEXT_TILE (self)); old_child = gtk_widget_get_first_child (GTK_WIDGET (self->lozenge)); if (old_child == child) return; if (old_child != NULL) gtk_box_remove (self->lozenge, old_child); if (child != NULL) gtk_box_append (self->lozenge, child); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LOZENGE_CHILD]); } const char * bz_context_tile_get_label (BzContextTile *self) { g_return_val_if_fail (BZ_IS_CONTEXT_TILE (self), NULL); return gtk_label_get_label (self->label); } void bz_context_tile_set_label (BzContextTile *self, const char *label) { g_return_if_fail (BZ_IS_CONTEXT_TILE (self)); if (g_strcmp0 (gtk_label_get_label (self->label), label) == 0) return; gtk_label_set_label (self->label, label); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LABEL]); } const char * bz_context_tile_get_lozenge_style (BzContextTile *self) { g_return_val_if_fail (BZ_IS_CONTEXT_TILE (self), NULL); return self->lozenge_style; } void bz_context_tile_set_lozenge_style (BzContextTile *self, const char *style) { g_return_if_fail (BZ_IS_CONTEXT_TILE (self)); if (style != NULL && *style == '\0') style = NULL; if (g_strcmp0 (self->lozenge_style, style) == 0) return; if (self->lozenge_style != NULL) gtk_widget_remove_css_class (GTK_WIDGET (self->lozenge), self->lozenge_style); g_clear_pointer (&self->lozenge_style, g_free); if (style != NULL) { self->lozenge_style = g_strdup (style); gtk_widget_add_css_class (GTK_WIDGET (self->lozenge), self->lozenge_style); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LOZENGE_STYLE]); } kolunmi-bazaar-7b9c8e1/src/bz-context-tile.h000066400000000000000000000031121514314607700210470ustar00rootroot00000000000000/* bz-context-tile.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_CONTEXT_TILE (bz_context_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzContextTile, bz_context_tile, BZ, CONTEXT_TILE, GtkButton) BzContextTile *bz_context_tile_new (void); GtkWidget *bz_context_tile_get_lozenge_child (BzContextTile *self); void bz_context_tile_set_lozenge_child (BzContextTile *self, GtkWidget *child); const char *bz_context_tile_get_label (BzContextTile *self); void bz_context_tile_set_label (BzContextTile *self, const char *label); const char *bz_context_tile_get_lozenge_style (BzContextTile *self); void bz_context_tile_set_lozenge_style (BzContextTile *self, const char *style); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-country-data-point.txt000066400000000000000000000002571514314607700225700ustar00rootroot00000000000000prefix=bz name=country_data_point parent-prefix=g parent-name=object author=AUTOGEN property=country_code char G_TYPE_STRING string property=downloads guint G_TYPE_UINT uint kolunmi-bazaar-7b9c8e1/src/bz-country.txt000066400000000000000000000004771514314607700205360ustar00rootroot00000000000000prefix=bz name=country parent-prefix=g parent-name=object author=AUTOGEN include= property=name char G_TYPE_STRING string property=iso_code char G_TYPE_STRING string property=coordinates JsonArray JSON_TYPE_ARRAY boxed json_array_unref json_array_ref property=value double G_TYPE_DOUBLE double kolunmi-bazaar-7b9c8e1/src/bz-curated-app-tile.blp000066400000000000000000000002461514314607700221230ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzCuratedAppTile: Adw.Bin { child: $BzAppTile { group: bind template.group; clicked => $clicked_cb(template); }; } kolunmi-bazaar-7b9c8e1/src/bz-curated-app-tile.c000066400000000000000000000110421514314607700215640ustar00rootroot00000000000000/* bz-curated-app-tile.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-curated-app-tile.h" #include "bz-app-tile.h" struct _BzCuratedAppTile { AdwBin parent_instance; BzEntryGroup *group; }; G_DEFINE_FINAL_TYPE (BzCuratedAppTile, bz_curated_app_tile, ADW_TYPE_BIN); enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_CLICKED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void bz_curated_app_tile_dispose (GObject *object) { BzCuratedAppTile *self = BZ_CURATED_APP_TILE (object); g_clear_pointer (&self->group, g_object_unref); G_OBJECT_CLASS (bz_curated_app_tile_parent_class)->dispose (object); } static void bz_curated_app_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCuratedAppTile *self = BZ_CURATED_APP_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_curated_app_tile_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_curated_app_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCuratedAppTile *self = BZ_CURATED_APP_TILE (object); switch (prop_id) { case PROP_GROUP: bz_curated_app_tile_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void clicked_cb (BzCuratedAppTile *self, BzAppTile *tile) { g_signal_emit (self, signals[SIGNAL_CLICKED], 0, NULL); } static void bz_curated_app_tile_class_init (BzCuratedAppTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_curated_app_tile_set_property; object_class->get_property = bz_curated_app_tile_get_property; object_class->dispose = bz_curated_app_tile_dispose; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_CLICKED] = g_signal_new ( "clicked", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_CLICKED], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__VOIDv); gtk_widget_class_set_css_name (widget_class, "app-tile"); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-curated-app-tile.ui"); gtk_widget_class_bind_template_callback (widget_class, clicked_cb); } static void bz_curated_app_tile_init (BzCuratedAppTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzCuratedAppTile * bz_curated_app_tile_new (void) { return g_object_new (BZ_TYPE_CURATED_APP_TILE, NULL); } BzEntryGroup * bz_curated_app_tile_get_group (BzCuratedAppTile *self) { g_return_val_if_fail (BZ_IS_CURATED_APP_TILE (self), NULL); return self->group; } void bz_curated_app_tile_set_group (BzCuratedAppTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_CURATED_APP_TILE (self)); g_clear_pointer (&self->group, g_object_unref); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } /* End of bz-curated-app-tile.c */ kolunmi-bazaar-7b9c8e1/src/bz-curated-app-tile.h000066400000000000000000000024141514314607700215740ustar00rootroot00000000000000/* bz-curated-app-tile.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry-group.h" G_BEGIN_DECLS #define BZ_TYPE_CURATED_APP_TILE (bz_curated_app_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzCuratedAppTile, bz_curated_app_tile, BZ, CURATED_APP_TILE, AdwBin) BzCuratedAppTile * bz_curated_app_tile_new (void); BzEntryGroup * bz_curated_app_tile_get_group (BzCuratedAppTile *self); void bz_curated_app_tile_set_group (BzCuratedAppTile *self, BzEntryGroup *group); G_END_DECLS /* End of bz-curated-app-tile.h */ kolunmi-bazaar-7b9c8e1/src/bz-curated-category-info.txt000066400000000000000000000014011514314607700232120ustar00rootroot00000000000000prefix=bz name=curated_category_info parent-prefix=g parent-name=object author=AUTOGEN include= property=title char G_TYPE_STRING string property=subtitle char G_TYPE_STRING string property=description char G_TYPE_STRING string property=banner char G_TYPE_STRING string property=light_banner char G_TYPE_STRING string property=dark_banner char G_TYPE_STRING string property=banner_height int G_TYPE_INT int property=banner_fit GtkContentFit GTK_TYPE_CONTENT_FIT enum property=banner_text_halign GtkAlign GTK_TYPE_ALIGN enum property=banner_text_valign GtkAlign GTK_TYPE_ALIGN enum property=banner_text_label_xalign double G_TYPE_DOUBLE double property=appids GListModel G_TYPE_LIST_MODEL object property=enable_bulk_install gboolean G_TYPE_BOOLEAN boolean kolunmi-bazaar-7b9c8e1/src/bz-curated-image-info.txt000066400000000000000000000006311514314607700224630ustar00rootroot00000000000000prefix=bz name=curated_image_info parent-prefix=g parent-name=object author=AUTOGEN include= property=uri char G_TYPE_STRING string property=light_uri char G_TYPE_STRING string property=dark_uri char G_TYPE_STRING string property=width int G_TYPE_INT int property=height int G_TYPE_INT int property=can_shrink gboolean G_TYPE_BOOLEAN boolean property=fit GtkContentFit GTK_TYPE_CONTENT_FIT enum kolunmi-bazaar-7b9c8e1/src/bz-curated-markdown-info.txt000066400000000000000000000002021514314607700232150ustar00rootroot00000000000000prefix=bz name=curated_markdown_info parent-prefix=g parent-name=object author=AUTOGEN property=string char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-curated-row.txt000066400000000000000000000002441514314607700212570ustar00rootroot00000000000000prefix=bz name=curated_row parent-prefix=g parent-name=object author=AUTOGEN include="bz-curated-section.h" property=sections GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-curated-section.txt000066400000000000000000000013611514314607700221150ustar00rootroot00000000000000prefix=bz name=curated_section parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-entry-group.h" include="bz-curated-category-info.h" include="bz-curated-markdown-info.h" include="bz-curated-image-info.h" property=expand_horizontally gboolean G_TYPE_BOOLEAN boolean property=expand_vertically gboolean G_TYPE_BOOLEAN boolean property=classes GListModel G_TYPE_LIST_MODEL object property=light_classes GListModel G_TYPE_LIST_MODEL object property=dark_classes GListModel G_TYPE_LIST_MODEL object property=category BzCuratedCategoryInfo BZ_TYPE_CURATED_CATEGORY_INFO object property=markdown BzCuratedMarkdownInfo BZ_TYPE_CURATED_MARKDOWN_INFO object property=image BzCuratedImageInfo BZ_TYPE_CURATED_IMAGE_INFO object kolunmi-bazaar-7b9c8e1/src/bz-curated-view.blp000066400000000000000000000035261514314607700213660ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzCuratedView: Adw.Bin { child: Adw.ViewStack stack { enable-transitions: true; transition-duration: 400; Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "starred-symbolic"; title: _("No Curation"); description: _("There is no curation information provided on this system. You can still browse applications on Flathub"); child: Button { label: _("Browse Flathub"); halign: center; clicked => $browse_flathub_cb(template); styles ["pill"] }; }; } Adw.ViewStackPage { name: "offline"; title: _("Offline"); child: Adw.StatusPage { icon-name: "connected-squares-x"; title: _("Offline"); }; } Adw.ViewStackPage { name: "content"; title: _("Browser"); child: ScrolledWindow { hscrollbar-policy: never; child: Adw.ClampScrollable { maximum-size: 1500; tightening-threshold: 1400; child: ListView { css-name: "curated-list-view"; model: NoSelection { model: bind template.state as <$BzStateInfo>.curated-provider; }; factory: BuilderListItemFactory { template ListItem { activatable: false; selectable: false; focusable: false; child: $BzDynamicListView { hexpand: true; scroll: false; noscroll-kind: list-box; child-type: "BzRowView"; child-prop: "row"; model: bind template.item as <$BzRootCuratedConfig>.rows; }; } }; }; }; }; } }; } kolunmi-bazaar-7b9c8e1/src/bz-curated-view.c000066400000000000000000000220701514314607700210260ustar00rootroot00000000000000/* bz-curated-view.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-curated-row.h" #include "bz-curated-view.h" #include "bz-dynamic-list-view.h" #include "bz-entry-group.h" #include "bz-inhibited-scrollable.h" #include "bz-root-curated-config.h" #include "bz-row-view.h" struct _BzCuratedView { AdwBin parent_instance; BzStateInfo *state; BzContentProvider *curated_provider; GPtrArray *css_providers; /* Template widgets */ AdwViewStack *stack; }; G_DEFINE_FINAL_TYPE (BzCuratedView, bz_curated_view, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_GROUP_SELECTED, SIGNAL_BROWSE_FLATHUB, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void items_changed (BzCuratedView *self, guint position, guint removed, guint added, GListModel *model); static void online_changed (BzCuratedView *self, GParamSpec *pspec, BzStateInfo *info); static void set_page (BzCuratedView *self); static void release_css_provider (gpointer ptr); static void bz_curated_view_dispose (GObject *object) { BzCuratedView *self = BZ_CURATED_VIEW (object); if (self->state != NULL) g_signal_handlers_disconnect_by_func ( self->state, online_changed, self); if (self->curated_provider != NULL) g_signal_handlers_disconnect_by_func ( self->curated_provider, items_changed, self); g_clear_object (&self->state); g_clear_object (&self->curated_provider); g_clear_pointer (&self->css_providers, g_ptr_array_unref); G_OBJECT_CLASS (bz_curated_view_parent_class)->dispose (object); } static void bz_curated_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzCuratedView *self = BZ_CURATED_VIEW (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_curated_view_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_curated_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzCuratedView *self = BZ_CURATED_VIEW (object); switch (prop_id) { case PROP_STATE: bz_curated_view_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void browse_flathub_cb (BzCuratedView *self, GtkButton *button) { g_signal_emit (self, signals[SIGNAL_BROWSE_FLATHUB], 0); } static void bz_curated_view_class_init (BzCuratedViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_curated_view_dispose; object_class->get_property = bz_curated_view_get_property; object_class->set_property = bz_curated_view_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_GROUP_SELECTED] = g_signal_new ( "group-selected", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_signal_set_va_marshaller ( signals[SIGNAL_GROUP_SELECTED], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_BROWSE_FLATHUB] = g_signal_new ( "browse-flathub", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_ensure (BZ_TYPE_ROW_VIEW); g_type_ensure (BZ_TYPE_ROOT_CURATED_CONFIG); g_type_ensure (BZ_TYPE_CURATED_ROW); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_INHIBITED_SCROLLABLE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-curated-view.ui"); gtk_widget_class_bind_template_child (widget_class, BzCuratedView, stack); gtk_widget_class_bind_template_callback (widget_class, browse_flathub_cb); } static void bz_curated_view_init (BzCuratedView *self) { self->css_providers = g_ptr_array_new_with_free_func (release_css_provider); gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_curated_view_new (void) { return g_object_new (BZ_TYPE_CURATED_VIEW, NULL); } void bz_curated_view_set_state (BzCuratedView *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_CURATED_VIEW (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); if (self->state != NULL) g_signal_handlers_disconnect_by_func ( self->state, online_changed, self); if (self->curated_provider != NULL) { g_signal_handlers_disconnect_by_func ( self->curated_provider, items_changed, self); items_changed ( self, 0, g_list_model_get_n_items (G_LIST_MODEL (self->curated_provider)), 0, G_LIST_MODEL (self->curated_provider)); } g_clear_object (&self->state); g_clear_object (&self->curated_provider); if (state != NULL) { self->state = g_object_ref (state); g_signal_connect_swapped ( state, "notify::online", G_CALLBACK (online_changed), self); g_object_get ( state, "curated-provider", &self->curated_provider, NULL); if (self->curated_provider != NULL) { items_changed ( self, 0, 0, g_list_model_get_n_items (G_LIST_MODEL (self->curated_provider)), G_LIST_MODEL (self->curated_provider)); g_signal_connect_swapped ( self->curated_provider, "items-changed", G_CALLBACK (items_changed), self); } } else set_page (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } BzStateInfo * bz_curated_view_get_state (BzCuratedView *self) { g_return_val_if_fail (BZ_IS_CURATED_VIEW (self), NULL); return self->state; } static void items_changed (BzCuratedView *self, guint position, guint removed, guint added, GListModel *model) { if (removed > 0) g_ptr_array_remove_range (self->css_providers, position, removed); for (guint i = 0; i < added; i++) { g_autoptr (BzRootCuratedConfig) config = NULL; const char *css = NULL; g_autoptr (GtkCssProvider) provider = NULL; config = g_list_model_get_item (model, position + i); css = bz_root_curated_config_get_css (config); provider = gtk_css_provider_new (); if (css != NULL) gtk_css_provider_load_from_string (provider, css); gtk_style_context_add_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER); g_ptr_array_insert (self->css_providers, position + i, g_steal_pointer (&provider)); } set_page (self); } static void online_changed (BzCuratedView *self, GParamSpec *pspec, BzStateInfo *info) { set_page (self); } static void set_page (BzCuratedView *self) { const char *page = NULL; if (self->state != NULL && !bz_state_info_get_online (self->state)) page = "offline"; else if (self->curated_provider != NULL && g_list_model_get_n_items (G_LIST_MODEL (self->curated_provider)) > 0) page = "content"; else page = "empty"; adw_view_stack_set_visible_child_name (self->stack, page); } static void release_css_provider (gpointer ptr) { GtkCssProvider *provider = ptr; gtk_style_context_remove_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (provider)); g_object_unref (provider); } kolunmi-bazaar-7b9c8e1/src/bz-curated-view.h000066400000000000000000000023201514314607700210270ustar00rootroot00000000000000/* bz-curated-view.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-content-provider.h" #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_CURATED_VIEW (bz_curated_view_get_type ()) G_DECLARE_FINAL_TYPE (BzCuratedView, bz_curated_view, BZ, CURATED_VIEW, AdwBin) GtkWidget * bz_curated_view_new (void); void bz_curated_view_set_state (BzCuratedView *self, BzStateInfo *state); BzStateInfo * bz_curated_view_get_state (BzCuratedView *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-data-graph.c000066400000000000000000001040431514314607700204400ustar00rootroot00000000000000/* bz-data-graph.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-data-graph.h" #include "bz-data-point.h" #include #define LABEL_MARGIN 75.0 #define LABEL_MARGIN_RIGHT 35.0 #define TICK_LENGTH 5.0 struct _BzDataGraph { GtkWidget parent_instance; GListModel *model; char *independent_axis_label; char *dependent_axis_label; char *tooltip_prefix; int independent_decimals; int dependent_decimals; double transition_progress; double rounded_axis_max; AdwStyleManager *style_manager; GskPath *path; GskPathMeasure *path_measure; GskRenderNode *fg; gboolean wants_animate_open; GtkEventController *motion; double motion_x; double motion_y; GtkGesture *gesture; GtkWidget *tooltip_box; GtkWidget *tooltip_label1; GtkWidget *tooltip_prefix_label; GtkWidget *tooltip_label2; }; G_DEFINE_FINAL_TYPE (BzDataGraph, bz_data_graph, GTK_TYPE_WIDGET) enum { PROP_0, PROP_MODEL, PROP_INDEPENDENT_AXIS_LABEL, PROP_DEPENDENT_AXIS_LABEL, PROP_TOOLTIP_PREFIX, PROP_INDEPENDENT_DECIMALS, PROP_DEPENDENT_DECIMALS, PROP_TRANSITION_PROGRESS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void items_changed (GListModel *model, guint position, guint removed, guint added, BzDataGraph *self); static void refresh_path (BzDataGraph *self, double width, double height); static double calculate_axis_tick_value (double value, gboolean round_up); static void on_style_changed (BzDataGraph *self, GParamSpec *pspec, AdwStyleManager *style_manager); static void bz_data_graph_dispose (GObject *object) { BzDataGraph *self = BZ_DATA_GRAPH (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func ( self->model, items_changed, self); g_signal_handlers_disconnect_by_func (self->style_manager, on_style_changed, self); g_clear_object (&self->model); g_clear_pointer (&self->independent_axis_label, g_free); g_clear_pointer (&self->dependent_axis_label, g_free); g_clear_pointer (&self->tooltip_prefix, g_free); g_clear_pointer (&self->path, gsk_path_unref); g_clear_pointer (&self->path_measure, gsk_path_measure_unref); g_clear_pointer (&self->fg, gsk_render_node_unref); if (self->tooltip_box != NULL) gtk_widget_unparent (self->tooltip_box); G_OBJECT_CLASS (bz_data_graph_parent_class)->dispose (object); } static void bz_data_graph_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDataGraph *self = BZ_DATA_GRAPH (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_data_graph_get_model (self)); break; case PROP_INDEPENDENT_AXIS_LABEL: g_value_set_string (value, bz_data_graph_get_independent_axis_label (self)); break; case PROP_DEPENDENT_AXIS_LABEL: g_value_set_string (value, bz_data_graph_get_dependent_axis_label (self)); break; case PROP_TOOLTIP_PREFIX: g_value_set_string (value, bz_data_graph_get_tooltip_prefix (self)); break; case PROP_INDEPENDENT_DECIMALS: g_value_set_int (value, bz_data_graph_get_independent_decimals (self)); break; case PROP_DEPENDENT_DECIMALS: g_value_set_int (value, bz_data_graph_get_dependent_decimals (self)); break; case PROP_TRANSITION_PROGRESS: g_value_set_double (value, bz_data_graph_get_transition_progress (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_data_graph_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDataGraph *self = BZ_DATA_GRAPH (object); switch (prop_id) { case PROP_MODEL: bz_data_graph_set_model (self, g_value_get_object (value)); break; case PROP_INDEPENDENT_AXIS_LABEL: bz_data_graph_set_independent_axis_label (self, g_value_get_string (value)); break; case PROP_DEPENDENT_AXIS_LABEL: bz_data_graph_set_dependent_axis_label (self, g_value_get_string (value)); break; case PROP_TOOLTIP_PREFIX: bz_data_graph_set_tooltip_prefix (self, g_value_get_string (value)); break; case PROP_INDEPENDENT_DECIMALS: bz_data_graph_set_independent_decimals (self, g_value_get_int (value)); break; case PROP_DEPENDENT_DECIMALS: bz_data_graph_set_dependent_decimals (self, g_value_get_int (value)); break; case PROP_TRANSITION_PROGRESS: bz_data_graph_set_transition_progress (self, g_value_get_double (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_data_graph_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzDataGraph *self = BZ_DATA_GRAPH (widget); refresh_path (self, (double) width - LABEL_MARGIN - LABEL_MARGIN_RIGHT, (double) height - LABEL_MARGIN); gtk_widget_queue_draw (widget); } static void on_style_changed (BzDataGraph *self, GParamSpec *pspec, AdwStyleManager *style_manager) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void bz_data_graph_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzDataGraph *self = BZ_DATA_GRAPH (widget); double widget_width = 0.0; double widget_height = 0.0; AdwStyleManager *style_manager = NULL; g_autoptr (GdkRGBA) accent_color = NULL; GdkRGBA widget_color = { 0 }; g_autoptr (GskPath) transitioning = NULL; g_autoptr (GskStroke) stroke = NULL; if (self->path == NULL) return; widget_width = gtk_widget_get_width (widget); widget_height = gtk_widget_get_height (widget); style_manager = adw_style_manager_get_default (); accent_color = adw_style_manager_get_accent_color_rgba (style_manager); gtk_widget_get_color (widget, &widget_color); if (self->transition_progress > 0.0 && self->transition_progress < 1.0) { GskPathPoint point0 = { 0 }; double path_distance = 0.0; GskPathPoint point1 = { 0 }; g_autoptr (GskPathBuilder) builder = NULL; gsk_path_get_start_point (self->path, &point0); path_distance = gsk_path_measure_get_length (self->path_measure) * self->transition_progress; gsk_path_measure_get_point (self->path_measure, path_distance, &point1); builder = gsk_path_builder_new (); gsk_path_builder_add_segment (builder, self->path, &point0, &point1); transitioning = gsk_path_builder_to_path (builder); } stroke = gsk_stroke_new (3.0); gsk_stroke_set_line_cap (stroke, GSK_LINE_CAP_ROUND); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (LABEL_MARGIN, 0.0)); if (self->fg != NULL) { graphene_rect_t bounds = { 0 }; gsk_render_node_get_bounds (self->fg, &bounds); gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_ALPHA); gtk_snapshot_append_node (snapshot, self->fg); gtk_snapshot_pop (snapshot); gtk_snapshot_append_color (snapshot, &widget_color, &bounds); gtk_snapshot_pop (snapshot); } if (self->transition_progress > 0.0) gtk_snapshot_append_stroke ( snapshot, transitioning != NULL ? transitioning : self->path, stroke, accent_color); gtk_snapshot_restore (snapshot); if (self->motion_x >= LABEL_MARGIN && self->motion_y >= 0.0 && self->motion_x < widget_width - LABEL_MARGIN_RIGHT && self->motion_y < widget_height - LABEL_MARGIN) { guint n_items = 0; guint hovered_idx = 0; g_autoptr (BzDataPoint) point = NULL; g_autoptr (GskStroke) crosshair_stroke = NULL; double graph_height = 0.0; double graph_width = 0.0; double fraction = 0.0; double point_x = 0.0; double point_y = 0.0; GskRoundedRect rounded_rect = { { { 0 } } }; GdkRGBA line_color = { 0 }; double card_x = 0.0; double card_y = 0.0; double rounded_axis_max = 0.0; const char *prefix = NULL; g_autofree char *line2_text = NULL; GtkRequisition natural_size; n_items = g_list_model_get_n_items (self->model); graph_width = widget_width - LABEL_MARGIN - LABEL_MARGIN_RIGHT; fraction = (self->motion_x - LABEL_MARGIN) / graph_width; hovered_idx = floor ((double) n_items * fraction); if (hovered_idx >= n_items) hovered_idx = n_items - 1; point = g_list_model_get_item (self->model, hovered_idx); if (self->rounded_axis_max > 0.0) { rounded_axis_max = self->rounded_axis_max; } else { double max_dependent = 0.0; for (guint i = 0; i < n_items; i++) { g_autoptr (BzDataPoint) p = g_list_model_get_item (self->model, i); double dep = bz_data_point_get_dependent (p); if (i == 0 || dep > max_dependent) max_dependent = dep; } rounded_axis_max = calculate_axis_tick_value (max_dependent, TRUE); } graph_height = widget_height - LABEL_MARGIN; point_x = ((double) hovered_idx / (double) (n_items - 1)) * graph_width + LABEL_MARGIN; point_y = (1.0 - bz_data_point_get_dependent (point) / rounded_axis_max) * graph_height; line_color = widget_color; line_color.alpha = 0.5; crosshair_stroke = gsk_stroke_new (1.0); #define APPEND_LINE(x0, y0, x1, y1, color) \ G_STMT_START \ { \ g_autoptr (GskPathBuilder) builder = NULL; \ g_autoptr (GskPath) path = NULL; \ \ builder = gsk_path_builder_new (); \ gsk_path_builder_move_to (builder, (x0), (y0)); \ gsk_path_builder_line_to (builder, (x1), (y1)); \ \ path = gsk_path_builder_to_path (builder); \ gtk_snapshot_append_stroke (snapshot, path, crosshair_stroke, (color)); \ } \ G_STMT_END APPEND_LINE (self->motion_x, 0.0, self->motion_x, widget_height - LABEL_MARGIN, &line_color); #undef APPEND_LINE gsk_rounded_rect_init_from_rect ( &rounded_rect, &GRAPHENE_RECT_INIT (point_x - 4.0, point_y - 4.0, 8.0, 8.0), 4.0); gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect); gtk_snapshot_append_color (snapshot, accent_color, &rounded_rect.bounds); gtk_snapshot_pop (snapshot); gtk_label_set_text (GTK_LABEL (self->tooltip_label1), bz_data_point_get_label (point)); prefix = self->tooltip_prefix != NULL ? self->tooltip_prefix : ""; gtk_label_set_text (GTK_LABEL (self->tooltip_prefix_label), prefix); line2_text = g_strdup_printf ("%'.0f", bz_data_point_get_dependent (point)); gtk_label_set_text (GTK_LABEL (self->tooltip_label2), line2_text); gtk_widget_get_preferred_size (self->tooltip_box, NULL, &natural_size); gtk_widget_allocate (self->tooltip_box, natural_size.width, natural_size.height, -1, NULL); if (self->motion_x > widget_width / 2.0) card_x = self->motion_x - natural_size.width - 10.0; else card_x = self->motion_x + 10.0; card_y = self->motion_y + 10.0; gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (card_x, card_y)); gtk_widget_snapshot_child (widget, self->tooltip_box, snapshot); gtk_snapshot_restore (snapshot); } if (self->wants_animate_open) { AdwAnimationTarget *transition_target = NULL; AdwSpringParams *transition_spring = NULL; g_autoptr (AdwAnimation) transition = NULL; self->wants_animate_open = FALSE; transition_target = adw_property_animation_target_new (G_OBJECT (self), "transition-progress"); transition_spring = adw_spring_params_new (1.0, 1.0, 80.0); transition = adw_spring_animation_new (GTK_WIDGET (self), 0.0, 1.0, transition_spring, transition_target); adw_spring_animation_set_epsilon (ADW_SPRING_ANIMATION (transition), 0.000001); adw_animation_play (transition); } } static void bz_data_graph_class_init (BzDataGraphClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_data_graph_dispose; object_class->get_property = bz_data_graph_get_property; object_class->set_property = bz_data_graph_set_property; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_INDEPENDENT_AXIS_LABEL] = g_param_spec_string ( "independent-axis-label", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_DEPENDENT_AXIS_LABEL] = g_param_spec_string ( "dependent-axis-label", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TOOLTIP_PREFIX] = g_param_spec_string ( "tooltip-prefix", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_INDEPENDENT_DECIMALS] = g_param_spec_int ( "independent-decimals", NULL, NULL, -1, 4, (int) 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_DEPENDENT_DECIMALS] = g_param_spec_int ( "dependent-decimals", NULL, NULL, -1, 4, (int) 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TRANSITION_PROGRESS] = g_param_spec_double ( "transition-progress", NULL, NULL, 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->size_allocate = bz_data_graph_size_allocate; widget_class->snapshot = bz_data_graph_snapshot; } static void update_cursor (BzDataGraph *self, gdouble x, gdouble y) { double widget_width = gtk_widget_get_width (GTK_WIDGET (self)); double widget_height = gtk_widget_get_height (GTK_WIDGET (self)); if (x >= LABEL_MARGIN && y >= 0.0 && x < widget_width - LABEL_MARGIN_RIGHT && y < widget_height - LABEL_MARGIN) gtk_widget_set_cursor_from_name (GTK_WIDGET (self), "crosshair"); else gtk_widget_set_cursor (GTK_WIDGET (self), NULL); } static void motion_enter (BzDataGraph *self, gdouble x, gdouble y, GtkEventControllerMotion *controller) { self->motion_x = x; self->motion_y = y; update_cursor (self, x, y); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void motion_event (BzDataGraph *self, gdouble x, gdouble y, GtkEventControllerMotion *controller) { self->motion_x = x; self->motion_y = y; update_cursor (self, x, y); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void motion_leave (BzDataGraph *self, GtkEventControllerMotion *controller) { self->motion_x = -1.0; self->motion_y = -1.0; gtk_widget_set_cursor (GTK_WIDGET (self), NULL); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void gesture_begin (BzDataGraph *self, double start_x, double start_y, GtkGestureDrag *gesture) { self->motion_x = start_x; self->motion_y = start_y; gtk_widget_queue_draw (GTK_WIDGET (self)); } static void gesture_update (BzDataGraph *self, double offset_x, double offset_y, GtkGestureDrag *gesture) { double start_x, start_y; gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y); self->motion_x = start_x + offset_x; self->motion_y = start_y + offset_y; gtk_widget_queue_draw (GTK_WIDGET (self)); } static void gesture_end (BzDataGraph *self, double offset_x, double offset_y, GtkGestureDrag *gesture) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void bz_data_graph_init (BzDataGraph *self) { GtkWidget *inner_box = NULL; GtkWidget *label2_box = NULL; GtkWidget *icon_image = NULL; self->style_manager = adw_style_manager_get_default (); g_signal_connect_swapped (self->style_manager, "notify::dark", G_CALLBACK (on_style_changed), self); g_signal_connect_swapped (self->style_manager, "notify::accent-color", G_CALLBACK (on_style_changed), self); self->motion = gtk_event_controller_motion_new (); g_signal_connect_swapped (self->motion, "enter", G_CALLBACK (motion_enter), self); g_signal_connect_swapped (self->motion, "motion", G_CALLBACK (motion_event), self); g_signal_connect_swapped (self->motion, "leave", G_CALLBACK (motion_leave), self); gtk_widget_add_controller (GTK_WIDGET (self), self->motion); self->gesture = gtk_gesture_drag_new (); gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (self->gesture), TRUE); g_signal_connect_swapped (self->gesture, "drag-begin", G_CALLBACK (gesture_begin), self); g_signal_connect_swapped (self->gesture, "drag-update", G_CALLBACK (gesture_update), self); g_signal_connect_swapped (self->gesture, "drag-end", G_CALLBACK (gesture_end), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->gesture)); self->motion_x = -1.0; self->motion_y = -1.0; self->rounded_axis_max = 0.0; self->tooltip_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_widget_add_css_class (self->tooltip_box, "card"); gtk_widget_add_css_class (self->tooltip_box, "floating-tooltip"); inner_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); gtk_widget_set_margin_start (inner_box, 12); gtk_widget_set_margin_end (inner_box, 12); gtk_widget_set_margin_top (inner_box, 12); gtk_widget_set_margin_bottom (inner_box, 12); self->tooltip_label1 = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_label1, "heading"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_label1), 0.0); gtk_box_append (GTK_BOX (inner_box), self->tooltip_label1); label2_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); icon_image = gtk_image_new_from_icon_name ("square-filled-symbolic"); gtk_widget_add_css_class (icon_image, "accent"); gtk_box_append (GTK_BOX (label2_box), icon_image); self->tooltip_prefix_label = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_prefix_label, "body"); gtk_widget_add_css_class (self->tooltip_prefix_label, "dim-label"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_prefix_label), 0.0); gtk_box_append (GTK_BOX (label2_box), self->tooltip_prefix_label); self->tooltip_label2 = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_label2, "monospace"); gtk_widget_add_css_class (self->tooltip_label2, "dimmed"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_label2), 0.0); gtk_box_append (GTK_BOX (label2_box), self->tooltip_label2); gtk_box_append (GTK_BOX (inner_box), label2_box); gtk_box_append (GTK_BOX (self->tooltip_box), inner_box); gtk_widget_set_parent (self->tooltip_box, GTK_WIDGET (self)); } GtkWidget * bz_data_graph_new (void) { return g_object_new (BZ_TYPE_DATA_GRAPH, NULL); } GListModel * bz_data_graph_get_model (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), NULL); return self->model; } const char * bz_data_graph_get_independent_axis_label (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), NULL); return self->independent_axis_label; } const char * bz_data_graph_get_dependent_axis_label (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), NULL); return self->dependent_axis_label; } const char * bz_data_graph_get_tooltip_prefix (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), NULL); return self->tooltip_prefix; } int bz_data_graph_get_independent_decimals (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), 0); return self->independent_decimals; } int bz_data_graph_get_dependent_decimals (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), 0); return self->dependent_decimals; } double bz_data_graph_get_transition_progress (BzDataGraph *self) { g_return_val_if_fail (BZ_IS_DATA_GRAPH (self), 0.0); return self->transition_progress; } void bz_data_graph_set_model (BzDataGraph *self, GListModel *model) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); if (self->model != NULL) g_signal_handlers_disconnect_by_func ( self->model, items_changed, self); g_clear_object (&self->model); if (model != NULL) self->model = g_object_ref (model); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } void bz_data_graph_set_independent_axis_label (BzDataGraph *self, const char *independent_axis_label) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); g_clear_pointer (&self->independent_axis_label, g_free); if (independent_axis_label != NULL) self->independent_axis_label = g_strdup (independent_axis_label); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INDEPENDENT_AXIS_LABEL]); } void bz_data_graph_set_dependent_axis_label (BzDataGraph *self, const char *dependent_axis_label) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); g_clear_pointer (&self->dependent_axis_label, g_free); if (dependent_axis_label != NULL) self->dependent_axis_label = g_strdup (dependent_axis_label); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEPENDENT_AXIS_LABEL]); } void bz_data_graph_set_tooltip_prefix (BzDataGraph *self, const char *tooltip_prefix) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); g_clear_pointer (&self->tooltip_prefix, g_free); if (tooltip_prefix != NULL) self->tooltip_prefix = g_strdup (tooltip_prefix); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TOOLTIP_PREFIX]); } void bz_data_graph_set_independent_decimals (BzDataGraph *self, int independent_decimals) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); self->independent_decimals = CLAMP (independent_decimals, -1, 4); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INDEPENDENT_DECIMALS]); } void bz_data_graph_set_dependent_decimals (BzDataGraph *self, int dependent_decimals) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); self->dependent_decimals = CLAMP (dependent_decimals, -1, 4); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEPENDENT_DECIMALS]); } void bz_data_graph_set_transition_progress (BzDataGraph *self, double transition_progress) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); self->transition_progress = transition_progress; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_PROGRESS]); } void bz_data_graph_animate_open (BzDataGraph *self) { g_return_if_fail (BZ_IS_DATA_GRAPH (self)); self->wants_animate_open = TRUE; gtk_widget_queue_draw (GTK_WIDGET (self)); } static void items_changed (GListModel *model, guint position, guint removed, guint added, BzDataGraph *self) { gtk_widget_queue_allocate (GTK_WIDGET (self)); } static double calculate_axis_tick_value (double value, gboolean round_up) { double exponent = 0.0; double fraction = 0.0; double rounded_axis_fraction = 0.0; exponent = floor (log10 (value)); fraction = value / pow (10, exponent); if (round_up) { if (fraction <= 1.0) rounded_axis_fraction = 1.0; else if (fraction <= 2.0) rounded_axis_fraction = 2.0; else if (fraction <= 5.0) rounded_axis_fraction = 5.0; else rounded_axis_fraction = 10.0; } else if (fraction < 1.5) rounded_axis_fraction = 1.0; else if (fraction < 3.0) rounded_axis_fraction = 2.0; else if (fraction < 7.0) rounded_axis_fraction = 5.0; else rounded_axis_fraction = 10.0; return rounded_axis_fraction * pow (10, exponent); } static void refresh_path (BzDataGraph *self, double width, double height) { guint n_items = 0; double min_independent = 0.0; double max_independent = 0.0; double max_dependent = 0.0; PangoContext *pango = NULL; PangoFontMetrics *metrics = NULL; double font_height = 0.0; int independent_label_step = 0; g_autoptr (GskPathBuilder) curve_builder = NULL; g_autoptr (GtkSnapshot) snapshot = NULL; g_autoptr (GskPathBuilder) grid_builder = NULL; g_autoptr (GskPath) grid = NULL; g_autoptr (GskStroke) grid_stroke = NULL; double rounded_axis_max = 0.0; double tick_spacing = 0.0; int num_ticks = 0; g_clear_pointer (&self->path, gsk_path_unref); g_clear_pointer (&self->path_measure, gsk_path_measure_unref); g_clear_pointer (&self->fg, gsk_render_node_unref); if (self->model == NULL) return; if (width < LABEL_MARGIN || height < LABEL_MARGIN) return; n_items = g_list_model_get_n_items (self->model); if (n_items <= 1) return; for (guint i = 0; i < n_items; i++) { g_autoptr (BzDataPoint) point = NULL; double independent = 0.0; double dependent = 0.0; point = g_list_model_get_item (self->model, i); independent = bz_data_point_get_independent (point); dependent = bz_data_point_get_dependent (point); if (i == 0) { min_independent = independent; max_independent = independent; max_dependent = dependent; } else { min_independent = MIN (independent, min_independent); max_independent = MAX (independent, max_independent); max_dependent = MAX (dependent, max_dependent); } } rounded_axis_max = calculate_axis_tick_value (max_dependent, TRUE); pango = gtk_widget_get_pango_context (GTK_WIDGET (self)); metrics = pango_context_get_metrics (pango, NULL, NULL); font_height = (double) (int) PANGO_PIXELS_CEIL (pango_font_metrics_get_height (metrics)); g_clear_pointer (&metrics, pango_font_metrics_unref); num_ticks = MIN (5, floor (height / (font_height + 25.0))); if (num_ticks < 2) num_ticks = 2; tick_spacing = calculate_axis_tick_value (rounded_axis_max / (double) num_ticks, FALSE); if (tick_spacing == 0.0) tick_spacing = 1.0; rounded_axis_max = ceil (max_dependent / tick_spacing) * tick_spacing; self->rounded_axis_max = rounded_axis_max; independent_label_step = MAX (1, n_items / MAX (1, floor (width / MAX (font_height + 10.0, LABEL_MARGIN)))) * 1.5; curve_builder = gsk_path_builder_new (); snapshot = gtk_snapshot_new (); grid_builder = gsk_path_builder_new (); for (guint i = 0; i < n_items; i++) { g_autoptr (BzDataPoint) point = NULL; double independent = 0.0; double dependent = 0.0; double x = 0.0; double y = 0.0; point = g_list_model_get_item (self->model, i); independent = bz_data_point_get_independent (point); dependent = bz_data_point_get_dependent (point); x = (independent - min_independent) / (max_independent - min_independent) * width; y = (1.0 - dependent / rounded_axis_max) * height; if (i == 0) gsk_path_builder_move_to (curve_builder, x, y); else gsk_path_builder_line_to (curve_builder, x, y); if (i % independent_label_step == 0) { const char *label = NULL; char buf[32] = { 0 }; g_autoptr (PangoLayout) layout = NULL; PangoRectangle extents; label = bz_data_point_get_label (point); if (label == NULL) { switch (self->independent_decimals) { case 0: g_snprintf (buf, sizeof (buf), "%d", (int) round (independent)); break; case 1: g_snprintf (buf, sizeof (buf), "%.1f", independent); break; case 2: g_snprintf (buf, sizeof (buf), "%.2f", independent); break; case 3: g_snprintf (buf, sizeof (buf), "%.3f", independent); break; default: g_snprintf (buf, sizeof (buf), "%f", independent); break; } label = buf; } layout = pango_layout_new (pango); pango_layout_set_text (layout, label, -1); pango_layout_get_pixel_extents (layout, NULL, &extents); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, height + LABEL_MARGIN / 10.0)); gtk_snapshot_rotate (snapshot, -LABEL_MARGIN_RIGHT); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-extents.width, 0)); gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA) { 1.0, 1.0, 1.0, 1.0 }); gtk_snapshot_restore (snapshot); gsk_path_builder_move_to (grid_builder, x, height); gsk_path_builder_line_to (grid_builder, x, height + TICK_LENGTH); } } gsk_path_builder_move_to (grid_builder, 0.0, height); gsk_path_builder_line_to (grid_builder, width, height); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-LABEL_MARGIN * 0.75, -font_height / 2.0)); for (double value = 0.0; value <= rounded_axis_max; value += tick_spacing) { char buf[32] = { 0 }; g_autoptr (PangoLayout) layout = NULL; double y_pos = (1.0 - value / rounded_axis_max) * height; switch (self->dependent_decimals) { case 0: g_snprintf (buf, sizeof (buf), "%d", (int) round (value)); break; case 1: g_snprintf (buf, sizeof (buf), "%.1f", value); break; case 2: g_snprintf (buf, sizeof (buf), "%.2f", value); break; case 3: g_snprintf (buf, sizeof (buf), "%.3f", value); break; default: g_snprintf (buf, sizeof (buf), "%f", value); break; } layout = pango_layout_new (pango); pango_layout_set_text (layout, buf, -1); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, y_pos)); gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA) { 1.0, 1.0, 1.0, 1.0 }); gtk_snapshot_restore (snapshot); gsk_path_builder_move_to (grid_builder, -TICK_LENGTH, y_pos); gsk_path_builder_line_to (grid_builder, 0.0, y_pos); } gtk_snapshot_restore (snapshot); gsk_path_builder_move_to (grid_builder, 0.0, 0.0); gsk_path_builder_line_to (grid_builder, 0.0, height); grid = gsk_path_builder_to_path (grid_builder); grid_stroke = gsk_stroke_new (1.0); gtk_snapshot_append_stroke (snapshot, grid, grid_stroke, &(GdkRGBA) { 1.0, 1.0, 1.0, 1.0 }); self->path = gsk_path_builder_to_path (curve_builder); self->path_measure = gsk_path_measure_new (self->path); self->fg = gtk_snapshot_to_node (snapshot); } kolunmi-bazaar-7b9c8e1/src/bz-data-graph.h000066400000000000000000000046131514314607700204470ustar00rootroot00000000000000/* bz-data-graph.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_DATA_GRAPH (bz_data_graph_get_type ()) G_DECLARE_FINAL_TYPE (BzDataGraph, bz_data_graph, BZ, DATA_GRAPH, GtkWidget) GtkWidget * bz_data_graph_new (void); GListModel * bz_data_graph_get_model (BzDataGraph *self); const char * bz_data_graph_get_independent_axis_label (BzDataGraph *self); const char * bz_data_graph_get_dependent_axis_label (BzDataGraph *self); int bz_data_graph_get_independent_decimals (BzDataGraph *self); int bz_data_graph_get_dependent_decimals (BzDataGraph *self); double bz_data_graph_get_transition_progress (BzDataGraph *self); void bz_data_graph_set_model (BzDataGraph *self, GListModel *model); void bz_data_graph_set_independent_axis_label (BzDataGraph *self, const char *independent_axis_label); void bz_data_graph_set_dependent_axis_label (BzDataGraph *self, const char *dependent_axis_label); void bz_data_graph_set_independent_decimals (BzDataGraph *self, int independent_decimals); void bz_data_graph_set_dependent_decimals (BzDataGraph *self, int dependent_decimals); const char *bz_data_graph_get_tooltip_prefix (BzDataGraph *self); void bz_data_graph_set_tooltip_prefix (BzDataGraph *self, const char *tooltip_prefix); void bz_data_graph_set_transition_progress (BzDataGraph *self, double transition_progress); void bz_data_graph_animate_open (BzDataGraph *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-data-point.txt000066400000000000000000000003261514314607700210640ustar00rootroot00000000000000prefix=bz name=data_point parent-prefix=g parent-name=object author=AUTOGEN property=independent double G_TYPE_DOUBLE double property=dependent double G_TYPE_DOUBLE double property=label char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-decorated-screenshot.blp000066400000000000000000000004171514314607700230700ustar00rootroot00000000000000using Gtk 4.0; template $BzDecoratedScreenshot: Button { halign: center; focus-on-click: false; styles [ "flat", "decorated-screenshot" ] child: Gtk.Picture { paintable: bind template.async-texture; content-fit: contain; halign: center; }; }kolunmi-bazaar-7b9c8e1/src/bz-decorated-screenshot.c000066400000000000000000000116661514314607700225450ustar00rootroot00000000000000/* bz-decorated-screenshot.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-decorated-screenshot.h" #include "bz-screenshot.h" #include struct _BzDecoratedScreenshot { GtkButton parent_instance; BzAsyncTexture *async_texture; /* Template widgets */ }; G_DEFINE_FINAL_TYPE (BzDecoratedScreenshot, bz_decorated_screenshot, GTK_TYPE_BUTTON) enum { PROP_0, PROP_ASYNC_TEXTURE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_decorated_screenshot_dispose (GObject *object) { BzDecoratedScreenshot *self = BZ_DECORATED_SCREENSHOT (object); g_clear_pointer (&self->async_texture, g_object_unref); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_DECORATED_SCREENSHOT); G_OBJECT_CLASS (bz_decorated_screenshot_parent_class)->dispose (object); } static void bz_decorated_screenshot_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDecoratedScreenshot *self = BZ_DECORATED_SCREENSHOT (object); switch (prop_id) { case PROP_ASYNC_TEXTURE: g_value_set_object (value, bz_decorated_screenshot_get_async_texture (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_decorated_screenshot_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDecoratedScreenshot *self = BZ_DECORATED_SCREENSHOT (object); switch (prop_id) { case PROP_ASYNC_TEXTURE: bz_decorated_screenshot_set_async_texture (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_decorated_screenshot_class_init (BzDecoratedScreenshotClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_decorated_screenshot_set_property; object_class->get_property = bz_decorated_screenshot_get_property; object_class->dispose = bz_decorated_screenshot_dispose; props[PROP_ASYNC_TEXTURE] = g_param_spec_object ( "async-texture", NULL, NULL, BZ_TYPE_ASYNC_TEXTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-decorated-screenshot.ui"); } static void on_enter_notify (GtkEventController *controller, gpointer user_data) { g_autoptr (GdkCursor) cursor = gdk_cursor_new_from_name ("pointer", NULL); gtk_widget_set_cursor (GTK_WIDGET (user_data), cursor); } static void on_leave_notify (GtkEventController *controller, gpointer user_data) { gtk_widget_set_cursor (GTK_WIDGET (user_data), NULL); } static void bz_decorated_screenshot_init (BzDecoratedScreenshot *self) { GtkEventController *enter_leave = gtk_event_controller_motion_new (); gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect (enter_leave, "enter", G_CALLBACK (on_enter_notify), GTK_WIDGET (self)); g_signal_connect (enter_leave, "leave", G_CALLBACK (on_leave_notify), GTK_WIDGET (self)); gtk_widget_add_controller (GTK_WIDGET (self), enter_leave); } BzDecoratedScreenshot * bz_decorated_screenshot_new (void) { return g_object_new (BZ_TYPE_DECORATED_SCREENSHOT, NULL); } BzAsyncTexture * bz_decorated_screenshot_get_async_texture (BzDecoratedScreenshot *self) { g_return_val_if_fail (BZ_IS_DECORATED_SCREENSHOT (self), NULL); return self->async_texture; } void bz_decorated_screenshot_set_async_texture (BzDecoratedScreenshot *self, BzAsyncTexture *async_texture) { g_return_if_fail (BZ_IS_DECORATED_SCREENSHOT (self)); g_clear_pointer (&self->async_texture, g_object_unref); if (async_texture != NULL) self->async_texture = g_object_ref (async_texture); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ASYNC_TEXTURE]); } /* End of bz-decorated-screenshot.c */ kolunmi-bazaar-7b9c8e1/src/bz-decorated-screenshot.h000066400000000000000000000025611514314607700225440ustar00rootroot00000000000000/* bz-decorated-screenshot.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-async-texture.h" #include G_BEGIN_DECLS #define BZ_TYPE_DECORATED_SCREENSHOT (bz_decorated_screenshot_get_type ()) G_DECLARE_FINAL_TYPE (BzDecoratedScreenshot, bz_decorated_screenshot, BZ, DECORATED_SCREENSHOT, GtkButton) BzDecoratedScreenshot * bz_decorated_screenshot_new (void); BzAsyncTexture * bz_decorated_screenshot_get_async_texture (BzDecoratedScreenshot *self); void bz_decorated_screenshot_set_async_texture (BzDecoratedScreenshot *self, BzAsyncTexture *async_texture); G_END_DECLS /* End of bz-decorated-screenshot.h */ kolunmi-bazaar-7b9c8e1/src/bz-developer-badge.blp000066400000000000000000000024171514314607700220120ustar00rootroot00000000000000using Gtk 4.0; template $BzDeveloperBadge: Box { orientation: horizontal; spacing: 3; halign: start; visible: bind $invert_boolean($is_null(template.entry as <$BzEntry>.developer) as ) as ; Label developer_label { label: bind $get_developer_name(template.entry) as ; xalign: 0.0; wrap: true; wrap-mode: word_char; natural-wrap-mode: word; styles [ "app-developer", ] } MenuButton info_button { icon-name: bind $get_icon_name(template.entry as <$BzEntry>.verification-status) as ; popover: popover; visible: bind $invert_boolean($is_null(template.entry as <$BzEntry>.verification-status) as ) as ; styles [ "developer-badge", ] EventControllerMotion { enter => $on_info_button_enter(); leave => $on_info_button_leave(); } } } Popover popover { has-arrow: true; position: right; child: Box { orientation: vertical; margin-top: 12; margin-bottom: 12; margin-start: 12; margin-end: 12; Label popover_label { label: bind $get_popover_text(template.entry, template.entry as <$BzEntry>.verification-status) as ; wrap: true; xalign: 0.0; max-width-chars: 40; use-markup: true; } }; } kolunmi-bazaar-7b9c8e1/src/bz-developer-badge.c000066400000000000000000000232651514314607700214630ustar00rootroot00000000000000/* bz-developer-badge.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-developer-badge.h" #include "bz-verification-status.h" struct _BzDeveloperBadge { GtkBox parent_instance; BzEntry *entry; GtkLabel *developer_label; GtkMenuButton *info_button; GtkPopover *popover; GtkLabel *popover_label; }; G_DEFINE_FINAL_TYPE (BzDeveloperBadge, bz_developer_badge, GTK_TYPE_BOX) enum { PROP_0, PROP_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static char * get_developer_name (gpointer object, GObject *entry) { if (entry == NULL || !BZ_IS_ENTRY (entry)) return NULL; return g_strdup (bz_entry_get_developer (BZ_ENTRY (entry))); } static char * get_icon_name (gpointer object, GObject *status) { gboolean verified = FALSE; if (status == NULL) return g_strdup ("info-outline-symbolic"); g_object_get (status, "verified", &verified, NULL); return g_strdup (verified ? "verified-checkmark-symbolic" : "info-outline-symbolic"); } static char * format_app_id (const char *app_id) { return g_strdup_printf ("%s", app_id); } static char * format_website_url (const char *website) { return g_strdup_printf ("%s", website, website); } static char * format_provider_name (const char *login_provider) { if (g_strcmp0 (login_provider, "github") == 0) return g_strdup ("GitHub"); else if (g_strcmp0 (login_provider, "gitlab") == 0) return g_strdup ("GitLab"); else if (g_strcmp0 (login_provider, "gnome") == 0) return g_strdup ("GNOME GitLab"); else if (g_strcmp0 (login_provider, "kde") == 0) return g_strdup ("KDE GitLab"); else return g_strdup (login_provider); } static char * get_popover_text (gpointer object, GObject *entry_obj, GObject *status_obj) { BzVerificationStatus *status = NULL; const char *app_id = NULL; const char *website = NULL; const char *method = NULL; const char *login_name = NULL; const char *login_provider = NULL; gboolean verified = FALSE; g_autofree char *formatted_app_id = NULL; g_autofree char *formatted_website = NULL; g_autofree char *provider_name = NULL; if (entry_obj == NULL || !BZ_IS_ENTRY (entry_obj)) return g_strdup (_ ("Developer information not available.")); app_id = bz_entry_get_id (BZ_ENTRY (entry_obj)); formatted_app_id = format_app_id (app_id); if (status_obj == NULL) return g_strdup_printf (_ ("The ownership of the %s app ID has not been verified and it may be a community package."), formatted_app_id); status = BZ_VERIFICATION_STATUS (status_obj); g_object_get (status, "verified", &verified, "method", &method, "website", &website, "login-name", &login_name, "login-provider", &login_provider, NULL); if (!verified) return g_strdup_printf (_ ("The ownership of the %s app ID has not been verified and it may be a community package."), formatted_app_id); if (g_strcmp0 (method, "manual") == 0) return g_strdup_printf (_ ("The ownership of the %s app ID has been manually verified by the Flathub team."), formatted_app_id); if (g_strcmp0 (method, "login_provider") == 0 && login_name != NULL && login_provider != NULL) { provider_name = format_provider_name (login_provider); return g_strdup_printf (_ ("The ownership of the %1$s app ID has been verified by %2$s on %3$s."), formatted_app_id, login_name, provider_name); } if (website != NULL && *website != '\0') { formatted_website = format_website_url (website); return g_strdup_printf (_ ("The ownership of the %1$s app ID has been verified using %2$s."), formatted_app_id, formatted_website); } return g_strdup_printf (_ ("The ownership of the %s app ID has been verified."), formatted_app_id); } static void on_info_button_enter (GtkEventControllerMotion *controller, gdouble x, gdouble y, gpointer user_data) { GtkWidget *widget = GTK_WIDGET (user_data); gtk_widget_set_cursor_from_name (widget, "pointer"); } static void on_info_button_leave (GtkEventControllerMotion *controller, gpointer user_data) { GtkWidget *widget = GTK_WIDGET (user_data); gtk_widget_set_cursor (widget, NULL); } static void bz_developer_badge_dispose (GObject *object) { BzDeveloperBadge *self = BZ_DEVELOPER_BADGE (object); g_clear_object (&self->entry); G_OBJECT_CLASS (bz_developer_badge_parent_class)->dispose (object); } static void bz_developer_badge_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDeveloperBadge *self = BZ_DEVELOPER_BADGE (object); switch (prop_id) { case PROP_ENTRY: g_value_set_object (value, bz_developer_badge_get_entry (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_developer_badge_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDeveloperBadge *self = BZ_DEVELOPER_BADGE (object); switch (prop_id) { case PROP_ENTRY: bz_developer_badge_set_entry (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_developer_badge_class_init (BzDeveloperBadgeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_developer_badge_dispose; object_class->get_property = bz_developer_badge_get_property; object_class->set_property = bz_developer_badge_set_property; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-developer-badge.ui"); gtk_widget_class_bind_template_child (widget_class, BzDeveloperBadge, developer_label); gtk_widget_class_bind_template_child (widget_class, BzDeveloperBadge, info_button); gtk_widget_class_bind_template_child (widget_class, BzDeveloperBadge, popover); gtk_widget_class_bind_template_child (widget_class, BzDeveloperBadge, popover_label); gtk_widget_class_bind_template_callback (widget_class, on_info_button_enter); gtk_widget_class_bind_template_callback (widget_class, on_info_button_leave); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, get_developer_name); gtk_widget_class_bind_template_callback (widget_class, get_icon_name); gtk_widget_class_bind_template_callback (widget_class, get_popover_text); } static void bz_developer_badge_init (BzDeveloperBadge *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_developer_badge_new (void) { return g_object_new (BZ_TYPE_DEVELOPER_BADGE, NULL); } BzEntry * bz_developer_badge_get_entry (BzDeveloperBadge *self) { g_return_val_if_fail (BZ_IS_DEVELOPER_BADGE (self), NULL); return self->entry; } void bz_developer_badge_set_entry (BzDeveloperBadge *self, BzEntry *entry) { BzVerificationStatus *status = NULL; gboolean verified = FALSE; g_return_if_fail (BZ_IS_DEVELOPER_BADGE (self)); g_return_if_fail (entry == NULL || BZ_IS_ENTRY (entry)); if (g_set_object (&self->entry, entry)) { gtk_widget_remove_css_class (GTK_WIDGET (self), "verified"); gtk_widget_remove_css_class (GTK_WIDGET (self), "dimmed"); if (entry != NULL) { g_object_get (entry, "verification-status", &status, NULL); if (status != NULL) { g_object_get (status, "verified", &verified, NULL); g_object_unref (status); } gtk_widget_add_css_class (GTK_WIDGET (self), verified ? "verified" : "dimmed"); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY]); } } kolunmi-bazaar-7b9c8e1/src/bz-developer-badge.h000066400000000000000000000023351514314607700214630ustar00rootroot00000000000000/* bz-developer-badge.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include G_BEGIN_DECLS #define BZ_TYPE_DEVELOPER_BADGE (bz_developer_badge_get_type ()) G_DECLARE_FINAL_TYPE (BzDeveloperBadge, bz_developer_badge, BZ, DEVELOPER_BADGE, GtkButton) GtkWidget *bz_developer_badge_new (void); BzEntry *bz_developer_badge_get_entry (BzDeveloperBadge *self); void bz_developer_badge_set_entry (BzDeveloperBadge *self, BzEntry *entry); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-donations-dialog.blp000066400000000000000000000037231514314607700222210ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzDonationsDialog: Adw.Dialog { width-request: 300; height-request: 400; content-width: 350; content-height: 750; child: Adw.ToolbarView { styles [ "bz-donations-dialog", ] [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { hscrollbar-policy: never; child: Box { valign: center; margin-start: 15; margin-end: 15; margin-top: 10; margin-bottom: 10; orientation: vertical; Label title { styles [ "title-1", ] wrap: true; justify: center; margin-bottom: 20; } Button { styles [ "pill", ] margin-start: 20; margin-end: 20; margin-bottom: 20; label: _("View the Release Page"); clicked => $release_page_clicked(template); } Separator { margin-top: 20; margin-bottom: 20; } Image { icon-name: "heart-filled-symbolic"; pixel-size: 128; margin-bottom: 10; } Label { styles [ "title-2", ] margin-bottom: 10; wrap: true; justify: center; label: _("This Bazaar Release Was Made Possible By Users Like You!"); } Label { margin-bottom: 20; wrap: true; justify: center; use-markup: true; label: _("I love making Bazaar, but I cannot do it alone. If you would like to help support further development, please consider donating to the project at my ko-fi:"); } Button { styles [ "pill", ] margin-start: 20; margin-end: 20; margin-bottom: 20; label: _("Donate to Bazaar"); clicked => $donate_clicked(template); } }; }; }; } kolunmi-bazaar-7b9c8e1/src/bz-donations-dialog.c000066400000000000000000000123211514314607700216600ustar00rootroot00000000000000/* bz-donations-dialog.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-appstream-description-render.h" #include "bz-donations-dialog.h" #include "bz-template-callbacks.h" struct _BzDonationsDialog { AdwDialog parent_instance; BzStateInfo *state; /* Template widgets */ GtkLabel *title; }; G_DEFINE_FINAL_TYPE (BzDonationsDialog, bz_donations_dialog, ADW_TYPE_DIALOG); enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_donations_dialog_dispose (GObject *object) { BzDonationsDialog *self = BZ_DONATIONS_DIALOG (object); g_clear_pointer (&self->state, g_object_unref); G_OBJECT_CLASS (bz_donations_dialog_parent_class)->dispose (object); } static void bz_donations_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDonationsDialog *self = BZ_DONATIONS_DIALOG (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_donations_dialog_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_donations_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDonationsDialog *self = BZ_DONATIONS_DIALOG (object); switch (prop_id) { case PROP_STATE: bz_donations_dialog_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void donate_clicked (BzDonationsDialog *self, GtkButton *button) { g_app_info_launch_default_for_uri ( DONATE_LINK, NULL, NULL); } static void release_page_clicked (BzDonationsDialog *self, GtkButton *button) { g_app_info_launch_default_for_uri ( RELEASE_PAGE, NULL, NULL); } static void bz_donations_dialog_class_init (BzDonationsDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_donations_dialog_set_property; object_class->get_property = bz_donations_dialog_get_property; object_class->dispose = bz_donations_dialog_dispose; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-donations-dialog.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzDonationsDialog, title); gtk_widget_class_bind_template_callback (widget_class, donate_clicked); gtk_widget_class_bind_template_callback (widget_class, release_page_clicked); } static void bz_donations_dialog_init (BzDonationsDialog *self) { g_autofree char *ui_version = NULL; char *space = NULL; g_autofree char *title_str = NULL; gtk_widget_init_template (GTK_WIDGET (self)); ui_version = g_strdup (PACKAGE_VERSION); space = g_utf8_strchr (ui_version, strlen (PACKAGE_VERSION), ' '); if (space != NULL) *space = '\0'; /* Translators: the %s format specifier will be something along the lines of "0.7.6" etc */ title_str = g_strdup_printf (_("What's New in Version %s?"), ui_version); gtk_label_set_label (self->title, title_str); } AdwDialog * bz_donations_dialog_new (void) { return g_object_new (BZ_TYPE_DONATIONS_DIALOG, NULL); } BzStateInfo * bz_donations_dialog_get_state (BzDonationsDialog *self) { g_return_val_if_fail (BZ_IS_DONATIONS_DIALOG (self), NULL); return self->state; } void bz_donations_dialog_set_state (BzDonationsDialog *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_DONATIONS_DIALOG (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); if (state == self->state) return; g_clear_pointer (&self->state, g_object_unref); if (state != NULL) self->state = g_object_ref (state); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } /* End of bz-donations-dialog.c */ kolunmi-bazaar-7b9c8e1/src/bz-donations-dialog.h000066400000000000000000000024021514314607700216640ustar00rootroot00000000000000/* bz-donations-dialog.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_DONATIONS_DIALOG (bz_donations_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzDonationsDialog, bz_donations_dialog, BZ, DONATIONS_DIALOG, AdwDialog) AdwDialog * bz_donations_dialog_new (void); BzStateInfo * bz_donations_dialog_get_state (BzDonationsDialog *self); void bz_donations_dialog_set_state (BzDonationsDialog *self, BzStateInfo *state); G_END_DECLS /* End of bz-donations-dialog.h */ kolunmi-bazaar-7b9c8e1/src/bz-download-worker.c000066400000000000000000000376431514314607700215610ustar00rootroot00000000000000/* bz-download-worker.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-download-worker.h" #include "bz-env.h" #include "bz-util.h" struct _BzDownloadWorker { GObject parent_instance; char *name; GSubprocess *subprocess; GHashTable *waiting; GMutex read_mutex; DexFuture *task; BzGuard *write_gate; GMutex write_mutex; }; static void initable_iface_init (GInitableIface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzDownloadWorker, bz_download_worker, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)); enum { PROP_0, PROP_NAME, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * monitor_worker_fiber (GWeakRef *wr); BZ_DEFINE_DATA ( invoke_worker, InvokeWorker, { GWeakRef *self; DexPromise *promise; GFile *src; GFile *dest; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (promise, dex_unref); BZ_RELEASE_DATA (src, g_object_unref); BZ_RELEASE_DATA (dest, g_object_unref)); static DexFuture * invoke_worker_fiber (InvokeWorkerData *data); static void terminate (BzDownloadWorker *self); static void plumb_data_input_stream_read_line_async (GDataInputStream *stream, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); static char * plumb_data_input_stream_read_line_finish (GDataInputStream *stream, GAsyncResult *result, gpointer user_data); static void bz_download_worker_dispose (GObject *object) { BzDownloadWorker *self = BZ_DOWNLOAD_WORKER (object); terminate (self); dex_clear (&self->task); g_clear_object (&self->subprocess); g_mutex_clear (&self->write_mutex); bz_clear_guard (&self->write_gate); g_mutex_clear (&self->read_mutex); g_clear_pointer (&self->waiting, g_hash_table_unref); g_clear_pointer (&self->name, g_free); G_OBJECT_CLASS (bz_download_worker_parent_class)->dispose (object); } static void bz_download_worker_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDownloadWorker *self = BZ_DOWNLOAD_WORKER (object); switch (prop_id) { case PROP_NAME: g_value_set_string (value, bz_download_worker_get_name (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_download_worker_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDownloadWorker *self = BZ_DOWNLOAD_WORKER (object); switch (prop_id) { case PROP_NAME: bz_download_worker_set_name (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_download_worker_class_init (BzDownloadWorkerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_download_worker_set_property; object_class->get_property = bz_download_worker_get_property; object_class->dispose = bz_download_worker_dispose; props[PROP_NAME] = g_param_spec_string ( "name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_download_worker_init (BzDownloadWorker *self) { g_mutex_init (&self->read_mutex); g_mutex_init (&self->write_mutex); self->waiting = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, dex_unref); } static gboolean bz_download_worker_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { BzDownloadWorker *self = BZ_DOWNLOAD_WORKER (initable); self->subprocess = g_subprocess_new ( G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, error, DL_WORKER_BIN_NAME, NULL); if (self->subprocess == NULL) return FALSE; self->task = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) monitor_worker_fiber, bz_track_weak (self), bz_weak_release); return TRUE; } static void initable_iface_init (GInitableIface *iface) { iface->init = bz_download_worker_initable_init; } BzDownloadWorker * bz_download_worker_new (const char *name, GError **error) { return g_initable_new ( BZ_TYPE_DOWNLOAD_WORKER, NULL, error, "name", name, NULL); } const char * bz_download_worker_get_name (BzDownloadWorker *self) { g_return_val_if_fail (BZ_IS_DOWNLOAD_WORKER (self), NULL); return self->name; } void bz_download_worker_set_name (BzDownloadWorker *self, const char *name) { g_return_if_fail (BZ_IS_DOWNLOAD_WORKER (self)); g_clear_pointer (&self->name, g_free); if (name != NULL) self->name = g_strdup (name); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NAME]); } DexFuture * bz_download_worker_invoke (BzDownloadWorker *self, GFile *src, GFile *dest) { g_autoptr (DexPromise) promise = NULL; g_autoptr (InvokeWorkerData) data = NULL; dex_return_error_if_fail (BZ_IS_DOWNLOAD_WORKER (self)); dex_return_error_if_fail (G_IS_FILE (src)); dex_return_error_if_fail (G_IS_FILE (dest)); promise = dex_promise_new (); data = invoke_worker_data_new (); data->self = bz_track_weak (self); data->promise = dex_ref (promise); data->src = g_object_ref (src); data->dest = g_object_ref (dest); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) invoke_worker_fiber, invoke_worker_data_ref (data), invoke_worker_data_unref)); return DEX_FUTURE (g_steal_pointer (&promise)); } BzDownloadWorker * bz_download_worker_get_default (void) { static GMutex mutex = { 0 }; static GPtrArray *workers = NULL; static guint next = 0; g_autoptr (GMutexLocker) locker = NULL; BzDownloadWorker *ret = NULL; locker = g_mutex_locker_new (&mutex); if (workers == NULL) { workers = g_ptr_array_new_with_free_func (g_object_unref); /* TODO: make number of workers controllable with envvar */ #define N_WORKERS 8 for (guint i = 0; i < N_WORKERS; i++) { g_autoptr (GError) local_error = NULL; g_autoptr (BzDownloadWorker) worker = NULL; worker = bz_download_worker_new ("default", &local_error); if (worker == NULL) g_warning ("FATAL!!! The default download worker could not be spawned: %s", local_error->message); g_assert (worker != NULL); g_ptr_array_add (workers, g_steal_pointer (&worker)); } } /* Check if any of the subprocesses need to be recreated */ for (guint i = 0; i < workers->len; i++) { BzDownloadWorker **loc = NULL; loc = (BzDownloadWorker **) &g_ptr_array_index (workers, i); if (g_subprocess_get_identifier ((*loc)->subprocess) == NULL) { g_autoptr (GError) local_error = NULL; g_autoptr (BzDownloadWorker) worker = NULL; g_clear_object (loc); worker = bz_download_worker_new ("default", &local_error); if (worker == NULL) g_warning ("FATAL!!! The default download worker could not be spawned: %s", local_error->message); g_assert (worker != NULL); *loc = g_steal_pointer (&worker); } } ret = g_ptr_array_index (workers, next); next = (next + 1) % workers->len; return ret; } static DexFuture * monitor_worker_fiber (GWeakRef *wr) { g_autoptr (BzDownloadWorker) self = NULL; g_autoptr (GInputStream) input_stream = NULL; g_autoptr (GDataInputStream) subprocess_stdout = NULL; bz_weak_get_or_return_reject (self, wr); input_stream = g_object_ref (g_subprocess_get_stdout_pipe (self->subprocess)); subprocess_stdout = g_data_input_stream_new (g_object_ref (input_stream)); g_clear_object (&self); for (;;) { g_autoptr (GError) local_error = NULL; g_autofree char *line = NULL; line = dex_await_string ( dex_async_pair_new ( subprocess_stdout, &DEX_ASYNC_PAIR_INFO_STRING ( plumb_data_input_stream_read_line_async, plumb_data_input_stream_read_line_finish)), &local_error); if (line == NULL) { if (local_error != NULL) g_warning ("Could not read stdout from download worker subprocess: %s", local_error->message); goto err; } do { g_autoptr (GVariant) variant = NULL; g_autofree char *dest_path = NULL; gboolean success = FALSE; DexPromise *promise = NULL; if (line == NULL) { line = g_data_input_stream_read_line_utf8 (subprocess_stdout, NULL, NULL, &local_error); if (line == NULL) { if (local_error != NULL) g_warning ("Could not read stdout from download worker subprocess: %s", local_error->message); goto err; } } variant = g_variant_parse (G_VARIANT_TYPE ("(sb)"), line, NULL, NULL, &local_error); if (variant == NULL) { g_warning ("Could not interpret stdout from download worker subprocess: %s", local_error->message); goto err; } g_variant_get (variant, "(sb)", &dest_path, &success); bz_weak_get_or_return_reject (self, wr); g_mutex_lock (&self->read_mutex); promise = g_hash_table_lookup (self->waiting, dest_path); if (promise != NULL) { if (success) dex_promise_resolve_boolean (promise, TRUE); else dex_promise_reject ( promise, g_error_new (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "The subprocess reported an error downloading '%s'", dest_path)); promise = NULL; g_hash_table_remove (self->waiting, dest_path); } g_mutex_unlock (&self->read_mutex); g_clear_object (&self); g_clear_pointer (&line, g_free); } while (g_input_stream_has_pending (input_stream)); } return dex_future_new_true (); err: bz_weak_get_or_return_reject (self, wr); /* give up on this subprocess and wait to be disposed */ g_mutex_lock (&self->read_mutex); terminate (self); g_mutex_unlock (&self->read_mutex); return dex_future_new_false (); } static DexFuture * invoke_worker_fiber (InvokeWorkerData *data) { DexPromise *promise = data->promise; GFile *src = data->src; GFile *dest = data->dest; g_autoptr (BzDownloadWorker) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (BzGuard) guard = NULL; g_autofree char *src_uri = NULL; g_autofree char *dest_path = NULL; DexPromise *existing = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (GString) output = NULL; g_autoptr (GOutputStream) stdin_stream = NULL; gint64 bytes_written = -1; src_uri = g_file_get_uri (src); dest_path = g_file_get_path (dest); bz_weak_get_or_return_reject (self, data->self); g_mutex_lock (&self->read_mutex); existing = g_hash_table_lookup (self->waiting, dest_path); if (existing != NULL) { dex_promise_reject ( existing, g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "The operation was replaced")); existing = NULL; } g_hash_table_replace (self->waiting, g_strdup (dest_path), dex_ref (promise)); g_mutex_unlock (&self->read_mutex); variant = g_variant_new ("(ss)", src_uri, dest_path); output = g_string_new (NULL); output = g_variant_print_string (variant, g_steal_pointer (&output), TRUE); g_string_append_c (output, '\n'); stdin_stream = g_object_ref (g_subprocess_get_stdin_pipe (self->subprocess)); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &self->write_mutex, &self->write_gate); g_clear_object (&self); bytes_written = dex_await_int64 ( dex_future_first ( dex_output_stream_write ( stdin_stream, output->str, output->len, G_PRIORITY_DEFAULT_IDLE), dex_ref (promise), NULL), &local_error); bz_clear_guard (&guard); /* Check if we've been cancelled */ if (!dex_future_is_pending (DEX_FUTURE (promise))) return dex_future_new_false (); if (bytes_written < 0) { bz_weak_get_or_return_reject (self, data->self); g_mutex_lock (&self->read_mutex); g_hash_table_remove (self->waiting, dest_path); dex_promise_reject (promise, g_steal_pointer (&local_error)); g_mutex_unlock (&self->read_mutex); g_clear_object (&self); } return dex_future_new_true (); } static void terminate (BzDownloadWorker *self) { GHashTableIter waiting_iter = { 0 }; g_hash_table_iter_init (&waiting_iter, self->waiting); for (;;) { g_autofree char *dest_path = NULL; g_autoptr (DexPromise) promise = NULL; if (!g_hash_table_iter_next ( &waiting_iter, (gpointer *) &dest_path, (gpointer *) &promise)) break; g_hash_table_iter_steal (&waiting_iter); dex_promise_reject ( promise, g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "The subprocess was terminated")); } } static void plumb_data_input_stream_read_line_async (GDataInputStream *stream, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_data_input_stream_read_line_async ( stream, G_PRIORITY_DEFAULT_IDLE, cancellable, callback, user_data); } static char * plumb_data_input_stream_read_line_finish (GDataInputStream *stream, GAsyncResult *result, gpointer user_data) { return g_data_input_stream_read_line_finish_utf8 ( stream, result, NULL, user_data); } /* End of bz-download-worker.c */ kolunmi-bazaar-7b9c8e1/src/bz-download-worker.h000066400000000000000000000027671514314607700215650ustar00rootroot00000000000000/* bz-download-worker.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_DOWNLOAD_WORKER (bz_download_worker_get_type ()) G_DECLARE_FINAL_TYPE (BzDownloadWorker, bz_download_worker, BZ, DOWNLOAD_WORKER, GObject) BzDownloadWorker * bz_download_worker_new (const char *name, GError **error); const char * bz_download_worker_get_name (BzDownloadWorker *self); void bz_download_worker_set_name (BzDownloadWorker *self, const char *name); DexFuture * bz_download_worker_invoke (BzDownloadWorker *self, GFile *src, GFile *dest); BzDownloadWorker * bz_download_worker_get_default (void); G_END_DECLS /* End of bz-download-worker.h */ kolunmi-bazaar-7b9c8e1/src/bz-dynamic-list-view.c000066400000000000000000000664251514314607700220100ustar00rootroot00000000000000/* bz-dynamic-list-view.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-dynamic-list-view.h" #include "bz-marshalers.h" G_DEFINE_ENUM_TYPE ( BzDynamicListViewKind, bz_dynamic_list_view_kind, G_DEFINE_ENUM_VALUE (BZ_DYNAMIC_LIST_VIEW_KIND_HBOX, "h-box"), G_DEFINE_ENUM_VALUE (BZ_DYNAMIC_LIST_VIEW_KIND_VBOX, "v-box"), G_DEFINE_ENUM_VALUE (BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX, "list-box"), G_DEFINE_ENUM_VALUE (BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX, "flow-box"), G_DEFINE_ENUM_VALUE (BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL, "carousel")) struct _BzDynamicListView { AdwBin parent_instance; GListModel *model; gboolean scroll; BzDynamicListViewKind noscroll_kind; GType child_type; char *child_prop; char *object_prop; guint max_children_per_line; guint row_spacing; guint column_spacing; char *child_type_string; GtkScrolledWindow *scrolled_window; GPtrArray *box_children; }; G_DEFINE_FINAL_TYPE (BzDynamicListView, bz_dynamic_list_view, ADW_TYPE_BIN); enum { PROP_0, PROP_MODEL, PROP_SCROLL, PROP_NOSCROLL_KIND, PROP_CHILD_TYPE, PROP_CHILD_PROP, PROP_OBJECT_PROP, PROP_MAX_CHILDREN_PER_LINE, PROP_VADJUSTMENT, PROP_ROW_SPACING, PROP_COLUMN_SPACING, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_BIND_WIDGET, SIGNAL_UNBIND_WIDGET, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void refresh (BzDynamicListView *self); static void list_item_factory_setup (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory); static void list_item_factory_teardown (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory); static void list_item_factory_bind (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory); static void list_item_factory_unbind (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory); static GtkWidget * create_child_widget (GObject *object, BzDynamicListView *self); static void items_changed (GListModel *model, guint position, guint removed, guint added, BzDynamicListView *self); static void bz_dynamic_list_view_dispose (GObject *object) { BzDynamicListView *self = BZ_DYNAMIC_LIST_VIEW (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); g_clear_pointer (&self->child_prop, g_free); g_clear_pointer (&self->object_prop, g_free); g_clear_pointer (&self->child_type_string, g_free); g_clear_pointer (&self->box_children, g_ptr_array_unref); G_OBJECT_CLASS (bz_dynamic_list_view_parent_class)->dispose (object); } static void bz_dynamic_list_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzDynamicListView *self = BZ_DYNAMIC_LIST_VIEW (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_dynamic_list_view_get_model (self)); break; case PROP_SCROLL: g_value_set_boolean (value, bz_dynamic_list_view_get_scroll (self)); break; case PROP_NOSCROLL_KIND: g_value_set_enum (value, bz_dynamic_list_view_get_noscroll_kind (self)); break; case PROP_CHILD_TYPE: g_value_set_string (value, bz_dynamic_list_view_get_child_type (self)); break; case PROP_CHILD_PROP: g_value_set_string (value, bz_dynamic_list_view_get_child_prop (self)); break; case PROP_OBJECT_PROP: g_value_set_string (value, bz_dynamic_list_view_get_object_prop (self)); break; case PROP_MAX_CHILDREN_PER_LINE: g_value_set_uint (value, bz_dynamic_list_view_get_max_children_per_line (self)); break; case PROP_VADJUSTMENT: g_value_set_object (value, bz_dynamic_list_view_get_vadjustment (self)); break; case PROP_ROW_SPACING: g_value_set_uint (value, bz_dynamic_list_view_get_row_spacing (self)); break; case PROP_COLUMN_SPACING: g_value_set_uint (value, bz_dynamic_list_view_get_column_spacing (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_dynamic_list_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzDynamicListView *self = BZ_DYNAMIC_LIST_VIEW (object); switch (prop_id) { case PROP_MODEL: bz_dynamic_list_view_set_model (self, g_value_get_object (value)); break; case PROP_SCROLL: bz_dynamic_list_view_set_scroll (self, g_value_get_boolean (value)); break; case PROP_NOSCROLL_KIND: bz_dynamic_list_view_set_noscroll_kind (self, g_value_get_enum (value)); break; case PROP_CHILD_TYPE: bz_dynamic_list_view_set_child_type (self, g_value_get_string (value)); break; case PROP_CHILD_PROP: bz_dynamic_list_view_set_child_prop (self, g_value_get_string (value)); break; case PROP_OBJECT_PROP: bz_dynamic_list_view_set_object_prop (self, g_value_get_string (value)); break; case PROP_MAX_CHILDREN_PER_LINE: bz_dynamic_list_view_set_max_children_per_line (self, g_value_get_uint (value)); break; case PROP_ROW_SPACING: bz_dynamic_list_view_set_row_spacing (self, g_value_get_uint (value)); break; case PROP_COLUMN_SPACING: bz_dynamic_list_view_set_column_spacing (self, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_dynamic_list_view_class_init (BzDynamicListViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_dynamic_list_view_set_property; object_class->get_property = bz_dynamic_list_view_get_property; object_class->dispose = bz_dynamic_list_view_dispose; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SCROLL] = g_param_spec_boolean ( "scroll", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_NOSCROLL_KIND] = g_param_spec_enum ( "noscroll-kind", NULL, NULL, BZ_TYPE_DYNAMIC_LIST_VIEW_KIND, BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MAX_CHILDREN_PER_LINE] = g_param_spec_uint ( "max-children-per-line", NULL, NULL, 1, G_MAXUINT, 4, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ROW_SPACING] = g_param_spec_uint ( "row-spacing", NULL, NULL, 0, G_MAXUINT, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_COLUMN_SPACING] = g_param_spec_uint ( "column-spacing", NULL, NULL, 0, G_MAXUINT, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CHILD_TYPE] = g_param_spec_string ( "child-type", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CHILD_PROP] = g_param_spec_string ( "child-prop", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_OBJECT_PROP] = g_param_spec_string ( "object-prop", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_VADJUSTMENT] = g_param_spec_object ( "vadjustment", NULL, NULL, GTK_TYPE_ADJUSTMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_BIND_WIDGET] = g_signal_new ( "bind-widget", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, bz_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 1, GTK_TYPE_WIDGET); g_signal_set_va_marshaller ( signals[SIGNAL_BIND_WIDGET], G_TYPE_FROM_CLASS (klass), bz_marshal_VOID__OBJECT_OBJECTv); signals[SIGNAL_UNBIND_WIDGET] = g_signal_new ( "unbind-widget", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, bz_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 1, GTK_TYPE_WIDGET); g_signal_set_va_marshaller ( signals[SIGNAL_UNBIND_WIDGET], G_TYPE_FROM_CLASS (klass), bz_marshal_VOID__OBJECT_OBJECTv); } static void bz_dynamic_list_view_init (BzDynamicListView *self) { self->child_type = G_TYPE_INVALID; self->noscroll_kind = BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX; self->max_children_per_line = 4; self->row_spacing = 5; self->column_spacing = 5; self->box_children = g_ptr_array_new (); } BzDynamicListView * bz_dynamic_list_view_new (void) { return g_object_new (BZ_TYPE_DYNAMIC_LIST_VIEW, NULL); } GListModel * bz_dynamic_list_view_get_model (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), NULL); return self->model; } gboolean bz_dynamic_list_view_get_scroll (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), FALSE); return self->scroll; } BzDynamicListViewKind bz_dynamic_list_view_get_noscroll_kind (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), FALSE); return self->noscroll_kind; } const char * bz_dynamic_list_view_get_child_type (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), NULL); return self->child_type_string; } const char * bz_dynamic_list_view_get_child_prop (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), NULL); return self->child_prop; } const char * bz_dynamic_list_view_get_object_prop (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), NULL); return self->object_prop; } guint bz_dynamic_list_view_get_max_children_per_line (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), 4); return self->max_children_per_line; } GtkAdjustment * bz_dynamic_list_view_get_vadjustment (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), NULL); if (self->scrolled_window == NULL) return NULL; return gtk_scrolled_window_get_vadjustment (self->scrolled_window); } void bz_dynamic_list_view_set_model (BzDynamicListView *self, GListModel *model) { g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); if (model != NULL) self->model = g_object_ref (model); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } void bz_dynamic_list_view_set_scroll (BzDynamicListView *self, gboolean scroll) { g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); self->scroll = scroll; refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SCROLL]); } void bz_dynamic_list_view_set_noscroll_kind (BzDynamicListView *self, BzDynamicListViewKind noscroll_kind) { g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); g_return_if_fail (noscroll_kind >= 0 && noscroll_kind < BZ_DYNAMIC_LIST_VIEW_N_KINDS); self->noscroll_kind = noscroll_kind; refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NOSCROLL_KIND]); } void bz_dynamic_list_view_set_child_type (BzDynamicListView *self, const char *child_type) { GType type = G_TYPE_INVALID; g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); if (child_type != NULL) { type = g_type_from_name (child_type); g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET)); } g_clear_pointer (&self->child_type_string, g_free); self->child_type = type; if (child_type != NULL) self->child_type_string = g_strdup (child_type); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TYPE]); } void bz_dynamic_list_view_set_child_prop (BzDynamicListView *self, const char *child_prop) { g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); g_clear_pointer (&self->child_prop, g_free); if (child_prop != NULL) self->child_prop = g_strdup (child_prop); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_PROP]); } void bz_dynamic_list_view_set_object_prop (BzDynamicListView *self, const char *object_prop) { g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); g_clear_pointer (&self->object_prop, g_free); if (object_prop != NULL) self->object_prop = g_strdup (object_prop); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_OBJECT_PROP]); } void bz_dynamic_list_view_set_max_children_per_line (BzDynamicListView *self, guint max_children) { GtkWidget *child; g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); g_return_if_fail (max_children > 0); self->max_children_per_line = max_children; child = adw_bin_get_child (ADW_BIN (self)); if (child != NULL && self->noscroll_kind == BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX && !self->scroll) { gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (child), max_children); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MAX_CHILDREN_PER_LINE]); } guint bz_dynamic_list_view_get_row_spacing (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), 5); return self->row_spacing; } guint bz_dynamic_list_view_get_column_spacing (BzDynamicListView *self) { g_return_val_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self), 5); return self->column_spacing; } void bz_dynamic_list_view_set_row_spacing (BzDynamicListView *self, guint row_spacing) { GtkWidget *child; g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); self->row_spacing = row_spacing; child = adw_bin_get_child (ADW_BIN (self)); if (child != NULL && self->noscroll_kind == BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX && !self->scroll) { gtk_flow_box_set_row_spacing (GTK_FLOW_BOX (child), row_spacing); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ROW_SPACING]); } void bz_dynamic_list_view_set_column_spacing (BzDynamicListView *self, guint column_spacing) { GtkWidget *child; g_return_if_fail (BZ_IS_DYNAMIC_LIST_VIEW (self)); self->column_spacing = column_spacing; child = adw_bin_get_child (ADW_BIN (self)); if (child != NULL && self->noscroll_kind == BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX && !self->scroll) { gtk_flow_box_set_column_spacing (GTK_FLOW_BOX (child), column_spacing); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COLUMN_SPACING]); } static void refresh (BzDynamicListView *self) { if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); self->scrolled_window = NULL; g_ptr_array_set_size (self->box_children, 0); adw_bin_set_child (ADW_BIN (self), NULL); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VADJUSTMENT]); if (self->model == NULL || self->child_prop == NULL || self->child_type == G_TYPE_INVALID) return; if (self->scroll) { GtkWidget *window = NULL; GtkNoSelection *selection = NULL; GtkListItemFactory *factory = NULL; GtkWidget *view = NULL; window = gtk_scrolled_window_new (); selection = gtk_no_selection_new (g_object_ref (self->model)); factory = gtk_signal_list_item_factory_new (); view = gtk_list_view_new (GTK_SELECTION_MODEL (selection), factory); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_widget_add_css_class (view, "navigation-sidebar"); gtk_list_view_set_single_click_activate (GTK_LIST_VIEW (view), TRUE); g_signal_connect_swapped (factory, "setup", G_CALLBACK (list_item_factory_setup), self); g_signal_connect_swapped (factory, "teardown", G_CALLBACK (list_item_factory_teardown), self); g_signal_connect_swapped (factory, "bind", G_CALLBACK (list_item_factory_bind), self); g_signal_connect_swapped (factory, "unbind", G_CALLBACK (list_item_factory_unbind), self); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (window), view); self->scrolled_window = GTK_SCROLLED_WINDOW (window); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VADJUSTMENT]); adw_bin_set_child (ADW_BIN (self), window); } else { switch (self->noscroll_kind) { case BZ_DYNAMIC_LIST_VIEW_KIND_HBOX: case BZ_DYNAMIC_LIST_VIEW_KIND_VBOX: { GtkWidget *widget = NULL; if (self->noscroll_kind == BZ_DYNAMIC_LIST_VIEW_KIND_VBOX) widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); else widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); g_signal_connect ( self->model, "items-changed", G_CALLBACK (items_changed), self); adw_bin_set_child (ADW_BIN (self), widget); items_changed (self->model, 0, 0, g_list_model_get_n_items (self->model), self); } break; case BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX: { GtkWidget *widget = NULL; widget = gtk_list_box_new (); gtk_list_box_set_selection_mode ( GTK_LIST_BOX (widget), GTK_SELECTION_NONE); gtk_list_box_bind_model ( GTK_LIST_BOX (widget), self->model, (GtkListBoxCreateWidgetFunc) create_child_widget, self, NULL); adw_bin_set_child (ADW_BIN (self), widget); } break; case BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX: { GtkWidget *widget = NULL; widget = gtk_flow_box_new (); gtk_flow_box_set_homogeneous (GTK_FLOW_BOX (widget), TRUE); gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (widget), self->max_children_per_line); gtk_flow_box_set_row_spacing (GTK_FLOW_BOX (widget), self->row_spacing); gtk_flow_box_set_column_spacing (GTK_FLOW_BOX (widget), self->column_spacing); gtk_flow_box_set_selection_mode (GTK_FLOW_BOX (widget), GTK_SELECTION_NONE); gtk_flow_box_bind_model ( GTK_FLOW_BOX (widget), self->model, (GtkFlowBoxCreateWidgetFunc) create_child_widget, self, NULL); adw_bin_set_child (ADW_BIN (self), widget); } break; case BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL: { GtkWidget *widget = NULL; widget = adw_carousel_new (); adw_carousel_set_allow_scroll_wheel (ADW_CAROUSEL (widget), FALSE); g_signal_connect ( self->model, "items-changed", G_CALLBACK (items_changed), self); adw_bin_set_child (ADW_BIN (self), widget); items_changed (self->model, 0, 0, g_list_model_get_n_items (self->model), self); } break; case BZ_DYNAMIC_LIST_VIEW_N_KINDS: default: g_assert_not_reached (); } } } static void list_item_factory_setup (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory) { GtkWidget *child = NULL; child = g_object_new (self->child_type, NULL); gtk_list_item_set_child (item, child); } static void list_item_factory_teardown (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory) { gtk_list_item_set_child (item, NULL); } static void list_item_factory_bind (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory) { GObject *object = NULL; GtkWidget *child = NULL; object = gtk_list_item_get_item (item); child = gtk_list_item_get_child (item); gtk_list_item_set_focusable (item, FALSE); gtk_list_item_set_selectable (item, FALSE); gtk_list_item_set_activatable (item, FALSE); if (self->object_prop != NULL) { GBinding *binding = NULL; binding = g_object_bind_property ( object, self->object_prop, child, self->child_prop, G_BINDING_SYNC_CREATE); g_object_set_data_full ( G_OBJECT (item), "binding", binding, g_object_unref); } else g_object_set (child, self->child_prop, object, NULL); g_signal_emit (self, signals[SIGNAL_BIND_WIDGET], 0, child, object); } static void list_item_factory_unbind (BzDynamicListView *self, GtkListItem *item, GtkSignalListItemFactory *factory) { GtkWidget *child = NULL; GBinding *binding = NULL; g_autoptr (GObject) object = NULL; child = gtk_list_item_get_child (item); binding = g_object_steal_data (G_OBJECT (item), "binding"); if (binding != NULL) { object = g_binding_dup_source (binding); g_binding_unbind (binding); g_object_unref (binding); } else { g_object_get (child, self->child_prop, &object, NULL); g_object_set (child, self->child_prop, NULL, NULL); } g_signal_emit (self, signals[SIGNAL_UNBIND_WIDGET], 0, child, object); } static GtkWidget * create_child_widget (GObject *object, BzDynamicListView *self) { GtkWidget *widget = NULL; widget = g_object_new (self->child_type, NULL); if (self->object_prop != NULL) g_object_bind_property ( object, self->object_prop, widget, self->child_prop, G_BINDING_SYNC_CREATE); else g_object_set (widget, self->child_prop, object, NULL); gtk_widget_set_receives_default (widget, TRUE); g_signal_emit (self, signals[SIGNAL_BIND_WIDGET], 0, widget, object); switch (self->noscroll_kind) { case BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX: { GtkWidget *child = NULL; child = gtk_list_box_row_new (); gtk_widget_add_css_class (GTK_WIDGET (child), "disable-adw-flow-box-styling"); gtk_widget_set_focusable (GTK_WIDGET (child), FALSE); gtk_list_box_row_set_selectable (GTK_LIST_BOX_ROW (child), FALSE); gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (child), widget); return child; } case BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX: { GtkWidget *child = NULL; child = gtk_flow_box_child_new (); gtk_widget_add_css_class (GTK_WIDGET (child), "disable-adw-flow-box-styling"); gtk_widget_set_focusable (GTK_WIDGET (child), FALSE); gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (child), widget); return child; } case BZ_DYNAMIC_LIST_VIEW_KIND_HBOX: case BZ_DYNAMIC_LIST_VIEW_KIND_VBOX: case BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL: case BZ_DYNAMIC_LIST_VIEW_N_KINDS: default: return widget; } } static void items_changed (GListModel *model, guint position, guint removed, guint added, BzDynamicListView *self) { GtkWidget *bin_child = NULL; bin_child = adw_bin_get_child (ADW_BIN (self)); for (guint i = 0; i < removed; i++) { switch (self->noscroll_kind) { case BZ_DYNAMIC_LIST_VIEW_KIND_HBOX: case BZ_DYNAMIC_LIST_VIEW_KIND_VBOX: { GtkWidget *child = NULL; child = g_ptr_array_index (self->box_children, position); gtk_box_remove (GTK_BOX (bin_child), g_steal_pointer (&child)); g_ptr_array_remove_index (self->box_children, position); } break; case BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL: adw_carousel_remove ( ADW_CAROUSEL (bin_child), adw_carousel_get_nth_page (ADW_CAROUSEL (bin_child), position)); break; case BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX: case BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX: case BZ_DYNAMIC_LIST_VIEW_N_KINDS: default: g_assert_not_reached (); } } for (guint i = 0; i < added; i++) { g_autoptr (GObject) object = NULL; GtkWidget *widget = NULL; object = g_list_model_get_item (model, position + i); widget = create_child_widget (object, self); switch (self->noscroll_kind) { case BZ_DYNAMIC_LIST_VIEW_KIND_HBOX: case BZ_DYNAMIC_LIST_VIEW_KIND_VBOX: { if (position + i < self->box_children->len) { GtkWidget *sibling = NULL; sibling = g_ptr_array_index (self->box_children, position + i); gtk_box_insert_child_after (GTK_BOX (bin_child), widget, sibling); } else gtk_box_append (GTK_BOX (bin_child), widget); } break; case BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL: adw_carousel_insert (ADW_CAROUSEL (bin_child), widget, position + i); break; case BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX: case BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX: case BZ_DYNAMIC_LIST_VIEW_N_KINDS: default: g_assert_not_reached (); } } } /* End of bz-dynamic-list-view.c */ kolunmi-bazaar-7b9c8e1/src/bz-dynamic-list-view.h000066400000000000000000000066741514314607700220150ustar00rootroot00000000000000/* bz-dynamic-list-view.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS typedef enum { BZ_DYNAMIC_LIST_VIEW_KIND_HBOX, BZ_DYNAMIC_LIST_VIEW_KIND_VBOX, BZ_DYNAMIC_LIST_VIEW_KIND_LIST_BOX, BZ_DYNAMIC_LIST_VIEW_KIND_FLOW_BOX, BZ_DYNAMIC_LIST_VIEW_KIND_CAROUSEL, /*< private >*/ BZ_DYNAMIC_LIST_VIEW_N_KINDS, } BzDynamicListViewKind; GType bz_dynamic_list_view_kind_get_type (void); #define BZ_TYPE_DYNAMIC_LIST_VIEW_KIND (bz_dynamic_list_view_kind_get_type ()) #define BZ_TYPE_DYNAMIC_LIST_VIEW (bz_dynamic_list_view_get_type ()) G_DECLARE_FINAL_TYPE (BzDynamicListView, bz_dynamic_list_view, BZ, DYNAMIC_LIST_VIEW, AdwBin) BzDynamicListView * bz_dynamic_list_view_new (void); GListModel * bz_dynamic_list_view_get_model (BzDynamicListView *self); gboolean bz_dynamic_list_view_get_scroll (BzDynamicListView *self); BzDynamicListViewKind bz_dynamic_list_view_get_noscroll_kind (BzDynamicListView *self); const char * bz_dynamic_list_view_get_child_type (BzDynamicListView *self); const char * bz_dynamic_list_view_get_child_prop (BzDynamicListView *self); const char * bz_dynamic_list_view_get_object_prop (BzDynamicListView *self); void bz_dynamic_list_view_set_model (BzDynamicListView *self, GListModel *model); void bz_dynamic_list_view_set_scroll (BzDynamicListView *self, gboolean scroll); void bz_dynamic_list_view_set_noscroll_kind (BzDynamicListView *self, BzDynamicListViewKind noscroll_kind); void bz_dynamic_list_view_set_child_type (BzDynamicListView *self, const char *child_type); void bz_dynamic_list_view_set_child_prop (BzDynamicListView *self, const char *child_prop); void bz_dynamic_list_view_set_object_prop (BzDynamicListView *self, const char *object_prop); guint bz_dynamic_list_view_get_max_children_per_line (BzDynamicListView *self); void bz_dynamic_list_view_set_max_children_per_line (BzDynamicListView *self, guint max_children); guint bz_dynamic_list_view_get_row_spacing (BzDynamicListView *self); void bz_dynamic_list_view_set_row_spacing (BzDynamicListView *self, guint row_spacing); guint bz_dynamic_list_view_get_column_spacing (BzDynamicListView *self); void bz_dynamic_list_view_set_column_spacing (BzDynamicListView *self, guint column_spacing); GtkAdjustment *bz_dynamic_list_view_get_vadjustment (BzDynamicListView *self); G_END_DECLS /* End of bz-dynamic-list-view.h */ kolunmi-bazaar-7b9c8e1/src/bz-entry-cache-manager.c000066400000000000000000000720501514314607700222440ustar00rootroot00000000000000/* bz-entry-cache-manager.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::ENTRY-CACHE" #define BAZAAR_MODULE "entry-cache" #define MAX_CONCURRENT_WRITES 16 #define WATCH_CLEANUP_INTERVAL_MSEC 5000 #include #include "bz-entry-cache-manager.h" #include "bz-env.h" #include "bz-flatpak-entry.h" #include "bz-io.h" #include "bz-serializable.h" #include "bz-util.h" /* clang-format off */ G_DEFINE_QUARK (bz-entry-cache-error-quark, bz_entry_cache_error); /* clang-format on */ BZ_DEFINE_DATA ( ongoing_task, OngoingTask, { DexScheduler *scheduler; DexPromise *init; GHashTable *alive_hash; GHashTable *writing_hash; GHashTable *reading_hash; BzGuard *ongoing_gates[MAX_CONCURRENT_WRITES]; GMutex ongoing_mutexes[MAX_CONCURRENT_WRITES]; guint ongoing_queued[MAX_CONCURRENT_WRITES]; GMutex ongoing_queueing_mutex; BzGuard *alive_gate; GMutex alive_mutex; BzGuard *reading_gate; GMutex reading_mutex; BzGuard *writing_gate; GMutex writing_mutex; }, BZ_RELEASE_DATA (scheduler, dex_unref); BZ_RELEASE_DATA (init, dex_unref); BZ_RELEASE_DATA (alive_hash, g_hash_table_unref); BZ_RELEASE_DATA (writing_hash, g_hash_table_unref); BZ_RELEASE_DATA (reading_hash, g_hash_table_unref); for (guint i = 0; i < G_N_ELEMENTS (self->ongoing_gates); i++) BZ_RELEASE_DATA (ongoing_gates[i], bz_guard_destroy); for (guint i = 0; i < G_N_ELEMENTS (self->ongoing_mutexes); i++) g_mutex_clear (&self->ongoing_mutexes[i]); g_mutex_clear (&self->ongoing_queueing_mutex); BZ_RELEASE_DATA (alive_gate, bz_guard_destroy); BZ_RELEASE_DATA (reading_gate, bz_guard_destroy); BZ_RELEASE_DATA (writing_gate, bz_guard_destroy); g_mutex_clear (&self->alive_mutex); g_mutex_clear (&self->reading_mutex); g_mutex_clear (&self->writing_mutex);); struct _BzEntryCacheManager { GObject parent_instance; guint64 max_memory_usage; DexScheduler *scheduler; guint64 memory_usage; OngoingTaskData *task_data; DexFuture *watch_task; }; G_DEFINE_FINAL_TYPE (BzEntryCacheManager, bz_entry_cache_manager, G_TYPE_OBJECT); enum { PROP_0, PROP_MAX_MEMORY_USAGE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * watch_init_fiber (OngoingTaskData *task_data); static DexFuture * watch_cb (DexFuture *future, OngoingTaskData *task_data); static DexFuture * watch_work_fiber (OngoingTaskData *task_data); BZ_DEFINE_DATA ( living_entry, LivingEntry, { GWeakRef wr; BzGuard *gate; GMutex mutex; GTimer *cached; }, BZ_RELEASE_DATA (gate, bz_guard_destroy); g_mutex_clear (&self->mutex); g_weak_ref_clear (&self->wr); BZ_RELEASE_DATA (cached, g_timer_destroy)); BZ_DEFINE_DATA ( write_task, WriteTask, { OngoingTaskData *task_data; char *unique_id_checksum; BzEntry *entry; }, BZ_RELEASE_DATA (task_data, ongoing_task_data_unref); BZ_RELEASE_DATA (unique_id_checksum, g_free); BZ_RELEASE_DATA (entry, g_object_unref);) static DexFuture * write_task_fiber (WriteTaskData *data); BZ_DEFINE_DATA ( read_task, ReadTask, { OngoingTaskData *task_data; char *unique_id_checksum; }, BZ_RELEASE_DATA (task_data, ongoing_task_data_unref); BZ_RELEASE_DATA (unique_id_checksum, g_free)) static DexFuture * read_task_fiber (ReadTaskData *data); static DexFuture * enumerate_disk_fiber (OngoingTaskData *data); static void bz_entry_cache_manager_dispose (GObject *object) { BzEntryCacheManager *self = BZ_ENTRY_CACHE_MANAGER (object); dex_clear (&self->scheduler); dex_clear (&self->watch_task); g_clear_pointer (&self->task_data, ongoing_task_data_unref); G_OBJECT_CLASS (bz_entry_cache_manager_parent_class)->dispose (object); } static void bz_entry_cache_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzEntryCacheManager *self = BZ_ENTRY_CACHE_MANAGER (object); switch (prop_id) { case PROP_MAX_MEMORY_USAGE: g_value_set_uint64 (value, bz_entry_cache_manager_get_max_memory_usage (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_cache_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzEntryCacheManager *self = BZ_ENTRY_CACHE_MANAGER (object); switch (prop_id) { case PROP_MAX_MEMORY_USAGE: bz_entry_cache_manager_set_max_memory_usage (self, g_value_get_uint64 (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_cache_manager_class_init (BzEntryCacheManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_entry_cache_manager_set_property; object_class->get_property = bz_entry_cache_manager_get_property; object_class->dispose = bz_entry_cache_manager_dispose; props[PROP_MAX_MEMORY_USAGE] = g_param_spec_uint64 ( "max-memory-usage", NULL, NULL, 0, G_MAXUINT64, 0xccccccc, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_entry_cache_manager_init (BzEntryCacheManager *self) { static DexScheduler *global_scheduler = NULL; g_autoptr (OngoingTaskData) task_data = NULL; if (g_once_init_enter_pointer (&global_scheduler)) g_once_init_leave_pointer (&global_scheduler, dex_thread_pool_scheduler_new ()); self->scheduler = dex_ref (global_scheduler); self->memory_usage = 0; task_data = ongoing_task_data_new (); task_data->scheduler = dex_ref (self->scheduler); task_data->init = dex_promise_new (); task_data->alive_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, living_entry_data_unref); task_data->writing_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, dex_unref); task_data->reading_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, dex_unref); for (guint i = 0; i < G_N_ELEMENTS (task_data->ongoing_mutexes); i++) g_mutex_init (&task_data->ongoing_mutexes[i]); g_mutex_init (&task_data->ongoing_queueing_mutex); g_mutex_init (&task_data->alive_mutex); g_mutex_init (&task_data->reading_mutex); g_mutex_init (&task_data->writing_mutex); self->task_data = g_steal_pointer (&task_data); self->watch_task = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) watch_init_fiber, ongoing_task_data_ref (self->task_data), ongoing_task_data_unref); } BzEntryCacheManager * bz_entry_cache_manager_new (void) { return g_object_new (BZ_TYPE_ENTRY_CACHE_MANAGER, NULL); } guint64 bz_entry_cache_manager_get_max_memory_usage (BzEntryCacheManager *self) { g_return_val_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self), 0); return self->max_memory_usage; } void bz_entry_cache_manager_set_max_memory_usage (BzEntryCacheManager *self, guint64 max_memory_usage) { g_return_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self)); self->max_memory_usage = max_memory_usage; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MAX_MEMORY_USAGE]); } DexFuture * bz_entry_cache_manager_add (BzEntryCacheManager *self, BzEntry *entry) { g_autoptr (WriteTaskData) data = NULL; g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self)); dex_return_error_if_fail (BZ_IS_ENTRY (entry)); dex_return_error_if_fail (!bz_entry_is_holding (entry)); data = write_task_data_new (); data->task_data = ongoing_task_data_ref (self->task_data); data->unique_id_checksum = g_strdup (bz_entry_get_unique_id_checksum (entry)); data->entry = g_object_ref (entry); future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) write_task_fiber, write_task_data_ref (data), write_task_data_unref); return g_steal_pointer (&future); } DexFuture * bz_entry_cache_manager_get (BzEntryCacheManager *self, const char *unique_id) { g_autoptr (ReadTaskData) data = NULL; g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self)); dex_return_error_if_fail (unique_id != NULL); data = read_task_data_new (); data->task_data = ongoing_task_data_ref (self->task_data); data->unique_id_checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, unique_id, -1); future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) read_task_fiber, read_task_data_ref (data), read_task_data_unref); return g_steal_pointer (&future); } DexFuture * bz_entry_cache_manager_get_by_checksum (BzEntryCacheManager *self, const char *unique_id_checksum) { g_autoptr (ReadTaskData) data = NULL; g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self)); dex_return_error_if_fail (unique_id_checksum != NULL); data = read_task_data_new (); data->task_data = ongoing_task_data_ref (self->task_data); data->unique_id_checksum = g_strdup (unique_id_checksum); future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) read_task_fiber, read_task_data_ref (data), read_task_data_unref); return g_steal_pointer (&future); } DexFuture * bz_entry_cache_manager_enumerate_disk (BzEntryCacheManager *self) { g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (BZ_IS_ENTRY_CACHE_MANAGER (self)); future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) enumerate_disk_fiber, ongoing_task_data_ref (self->task_data), ongoing_task_data_unref); return g_steal_pointer (&future); } static DexFuture * write_task_fiber (WriteTaskData *data) { OngoingTaskData *task_data = data->task_data; char *unique_id_checksum = data->unique_id_checksum; BzEntry *entry = data->entry; g_autoptr (GError) local_error = NULL; g_autoptr (BzGuard) slot_guard = NULL; g_autoptr (BzGuard) other_guard = NULL; g_autoptr (GMutexLocker) locker = NULL; guint slot_queued = G_MAXUINT; guint slot_index = 0; DexFuture *writing_future = NULL; g_autoptr (LivingEntryData) living = NULL; g_autoptr (DexPromise) promise = NULL; g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (GBytes) bytes = NULL; gsize bytes_size = 0; gconstpointer bytes_data = 0; g_autofree char *main_cache = NULL; g_autoptr (GFile) parent_file = NULL; g_autofree char *save_file_path = NULL; g_autoptr (GFile) save_file = NULL; gsize existing_contents_size = 0; g_autofree char *existing_contents = NULL; g_autoptr (GFileOutputStream) output = NULL; gssize bytes_written = 0; gboolean result = FALSE; g_autoptr (GError) ret_error = NULL; if (!BZ_IS_FLATPAK_ENTRY (entry)) return dex_future_new_reject ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Entry with unique ID checksum '%s' cannot be " "cached because it is not a flatpak entry", unique_id_checksum); /* Rate limit to reduce competition for resources * when refresh triggers a flood of requests * * Here we make sure to pick the slot with the * least tasks waiting in line */ locker = g_mutex_locker_new (&task_data->ongoing_queueing_mutex); for (guint i = 0; i < G_N_ELEMENTS (task_data->ongoing_gates); i++) { if (task_data->ongoing_queued[i] < slot_queued) { slot_queued = task_data->ongoing_queued[i]; slot_index = i; } } task_data->ongoing_queued[slot_index]++; g_clear_pointer (&locker, g_mutex_locker_free); BZ_BEGIN_GUARD_WITH_CONTEXT (&slot_guard, &task_data->ongoing_mutexes[slot_index], &task_data->ongoing_gates[slot_index]); locker = g_mutex_locker_new (&task_data->ongoing_queueing_mutex); task_data->ongoing_queued[slot_index]--; g_clear_pointer (&locker, g_mutex_locker_free); dex_await (dex_ref (task_data->init), NULL); BZ_BEGIN_GUARD_WITH_CONTEXT (&other_guard, &task_data->writing_mutex, &task_data->writing_gate); { writing_future = g_hash_table_lookup (task_data->writing_hash, unique_id_checksum); if (writing_future != NULL) return dex_future_new_reject ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Entry with unique ID '%s' is already being cached right now", unique_id_checksum); promise = dex_promise_new (); g_hash_table_replace (task_data->writing_hash, g_strdup (unique_id_checksum), dex_ref (promise)); } bz_clear_guard (&other_guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&other_guard, &task_data->alive_mutex, &task_data->alive_gate); { living = g_hash_table_lookup (task_data->alive_hash, unique_id_checksum); if (living != NULL) living_entry_data_ref (living); else { living = living_entry_data_new (); g_weak_ref_init (&living->wr, NULL); g_mutex_init (&living->mutex); living->cached = g_timer_new (); g_hash_table_replace (task_data->alive_hash, g_strdup (unique_id_checksum), living_entry_data_ref (living)); } } bz_clear_guard (&other_guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&other_guard, &living->mutex, &living->gate); { builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); bz_serializable_serialize (BZ_SERIALIZABLE (entry), builder); variant = g_variant_builder_end (builder); bytes = g_variant_get_data_as_bytes (variant); bytes_data = g_bytes_get_data (bytes, &bytes_size); main_cache = bz_dup_module_dir (); parent_file = g_file_new_for_path (main_cache); result = g_file_make_directory_with_parents (parent_file, NULL, &local_error); if (!result) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_pointer (&local_error, g_error_free); else { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Failed to make parent directory '%s' when caching '%s': %s", main_cache, unique_id_checksum, local_error->message); goto done; } } save_file_path = g_build_filename (main_cache, unique_id_checksum, NULL); save_file = g_file_new_for_path (save_file_path); result = g_file_get_contents ( save_file_path, &existing_contents, &existing_contents_size, NULL); /* Only write if the file has definitely changed */ if (!result || existing_contents_size != bytes_size || memcmp (existing_contents, bytes_data, bytes_size) != 0) { output = g_file_replace ( save_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); if (output == NULL) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Failed to open write stream when caching '%s': %s", unique_id_checksum, local_error->message); goto done; } bytes_written = g_output_stream_write_bytes (G_OUTPUT_STREAM (output), bytes, NULL, &local_error); if (bytes_written < 0) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Failed to write data to stream when caching '%s': %s", unique_id_checksum, local_error->message); goto done; } result = g_output_stream_close (G_OUTPUT_STREAM (output), NULL, &local_error); if (!result) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_CACHE_FAILED, "Failed to close stream when caching '%s': %s", unique_id_checksum, local_error->message); goto done; } } g_timer_start (living->cached); } done: bz_clear_guard (&slot_guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&other_guard, &task_data->writing_mutex, &task_data->writing_gate); { if (ret_error != NULL) dex_promise_reject (promise, g_error_copy (ret_error)); else dex_promise_resolve_boolean (promise, TRUE); g_hash_table_remove (task_data->writing_hash, unique_id_checksum); } bz_clear_guard (&other_guard); if (ret_error != NULL) return dex_future_new_for_error (g_steal_pointer (&ret_error)); else return dex_future_new_true (); } static DexFuture * read_task_fiber (ReadTaskData *data) { OngoingTaskData *task_data = data->task_data; char *unique_id_checksum = data->unique_id_checksum; g_autoptr (GError) local_error = NULL; g_autoptr (BzGuard) guard = NULL; g_autoptr (GMutexLocker) locker = NULL; g_autoptr (DexFuture) writing_future = NULL; g_autoptr (LivingEntryData) living = NULL; DexFuture *reading_future = NULL; g_autoptr (DexPromise) promise = NULL; g_autofree char *main_cache = NULL; g_autofree char *path = NULL; g_autoptr (GFile) file = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (GVariant) variant = NULL; g_autoptr (BzFlatpakEntry) entry = NULL; gboolean result = FALSE; g_autoptr (GError) ret_error = NULL; dex_await (dex_ref (task_data->init), NULL); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &task_data->writing_mutex, &task_data->writing_gate); { writing_future = g_hash_table_lookup (task_data->writing_hash, unique_id_checksum); if (writing_future != NULL) { dex_ref (writing_future); bz_clear_guard (&guard); dex_await (g_steal_pointer (&writing_future), NULL); } } bz_clear_guard (&guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &task_data->reading_mutex, &task_data->reading_gate); { reading_future = g_hash_table_lookup (task_data->reading_hash, unique_id_checksum); if (reading_future != NULL) return dex_ref (reading_future); promise = dex_promise_new (); g_hash_table_replace (task_data->reading_hash, g_strdup (unique_id_checksum), dex_ref (promise)); } bz_clear_guard (&guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &task_data->alive_mutex, &task_data->alive_gate); { living = g_hash_table_lookup (task_data->alive_hash, unique_id_checksum); if (living != NULL) { g_autoptr (BzEntry) living_entry = NULL; living_entry_data_ref (living); bz_clear_guard (&guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &living->mutex, &living->gate); living_entry = g_weak_ref_get (&living->wr); if (living_entry != NULL) { bz_clear_guard (&guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &task_data->reading_mutex, &task_data->reading_gate); { g_hash_table_remove (task_data->reading_hash, unique_id_checksum); } bz_clear_guard (&guard); dex_promise_resolve_object (promise, g_object_ref (living_entry)); return dex_future_new_for_object (living_entry); } } else { living = living_entry_data_new (); g_weak_ref_init (&living->wr, NULL); g_mutex_init (&living->mutex); living->cached = g_timer_new (); g_hash_table_replace (task_data->alive_hash, g_strdup (unique_id_checksum), living_entry_data_ref (living)); bz_clear_guard (&guard); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &living->mutex, &living->gate); } } /* living data was guarded */ main_cache = bz_dup_module_dir (); path = g_build_filename (main_cache, unique_id_checksum, NULL); file = g_file_new_for_path (path); bytes = g_file_load_bytes (file, NULL, NULL, &local_error); if (bytes == NULL) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_DECACHE_FAILED, "Failed to de-cache variant from file: %s", local_error->message); goto done; } variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARDICT, bytes, FALSE); if (variant == NULL) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_DECACHE_FAILED, "Failed to interpret variant from %s: %s", path, local_error->message); goto done; } entry = g_object_new (BZ_TYPE_FLATPAK_ENTRY, NULL); result = bz_serializable_deserialize (BZ_SERIALIZABLE (entry), variant, &local_error); if (!result) { ret_error = g_error_new ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_DECACHE_FAILED, "Failed to deserialize entry from %s: %s", path, local_error->message); goto done; } g_weak_ref_init (&living->wr, entry); done: BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &task_data->reading_mutex, &task_data->reading_gate); { if (ret_error != NULL) dex_promise_reject (promise, g_error_copy (ret_error)); else dex_promise_resolve_object (promise, g_object_ref (entry)); g_hash_table_remove (task_data->reading_hash, unique_id_checksum); } bz_clear_guard (&guard); if (ret_error != NULL) return dex_future_new_for_error (g_steal_pointer (&ret_error)); else return dex_future_new_for_object (entry); } static DexFuture * enumerate_disk_fiber (OngoingTaskData *data) { g_autoptr (GError) local_error = NULL; g_autoptr (BzGuard) guard = NULL; g_autoptr (GHashTable) set = NULL; g_autofree char *main_cache = NULL; g_autoptr (GFile) main_cache_file = NULL; g_autoptr (GFileEnumerator) enumerator = NULL; set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &data->alive_mutex, &data->alive_gate); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &data->reading_mutex, &data->reading_gate); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard, &data->writing_mutex, &data->writing_gate); main_cache = bz_dup_module_dir (); if (!g_file_test (main_cache, G_FILE_TEST_EXISTS)) goto done; main_cache_file = g_file_new_for_path (main_cache); enumerator = g_file_enumerate_children ( main_cache_file, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); if (enumerator == NULL) return dex_future_new_reject ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_ENUMERATE_FAILED, "Could not initialize directory enumerator at %s: %s", main_cache, local_error->message); for (;;) { g_autoptr (GFileInfo) info = NULL; g_autoptr (GFile) child = NULL; g_autofree char *basename = NULL; info = g_file_enumerator_next_file (enumerator, NULL, &local_error); if (info == NULL) { if (local_error != NULL) return dex_future_new_reject ( BZ_ENTRY_CACHE_ERROR, BZ_ENTRY_CACHE_ERROR_ENUMERATE_FAILED, "Could not enumerate children of cache directory at %s: %s", main_cache, local_error->message); else break; } child = g_file_enumerator_get_child (enumerator, info); if (g_file_info_get_is_symlink (info) || g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR) continue; basename = g_file_get_basename (child); if (basename != NULL) g_hash_table_replace (set, g_steal_pointer (&basename), NULL); } done: return dex_future_new_take_boxed (G_TYPE_HASH_TABLE, g_steal_pointer (&set)); } static DexFuture * watch_init_fiber (OngoingTaskData *task_data) { // bz_discard_module_dir (); dex_promise_resolve_boolean (task_data->init, TRUE); return dex_future_finally_loop ( dex_timeout_new_msec (WATCH_CLEANUP_INTERVAL_MSEC), (DexFutureCallback) watch_cb, ongoing_task_data_ref (task_data), ongoing_task_data_unref); } static DexFuture * watch_cb (DexFuture *future, OngoingTaskData *task_data) { return dex_scheduler_spawn ( task_data->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) watch_work_fiber, ongoing_task_data_ref (task_data), ongoing_task_data_unref); } static DexFuture * watch_work_fiber (OngoingTaskData *task_data) { g_autoptr (BzGuard) guard0 = NULL; GHashTableIter iter = { 0 }; g_autoptr (GTimer) timer = NULL; guint total = 0; guint active = 0; guint alive = 0; guint pruned = 0; timer = g_timer_new (); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard0, &task_data->alive_mutex, &task_data->alive_gate); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard0, &task_data->reading_mutex, &task_data->reading_gate); BZ_BEGIN_GUARD_WITH_CONTEXT (&guard0, &task_data->writing_mutex, &task_data->writing_gate); g_hash_table_iter_init (&iter, task_data->alive_hash); for (;;) { char *unique_id_checksum = NULL; LivingEntryData *living = NULL; g_autoptr (BzGuard) guard1 = NULL; g_autoptr (BzEntry) entry = NULL; if (!g_hash_table_iter_next (&iter, (gpointer *) &unique_id_checksum, (gpointer *) &living)) break; total++; if (g_hash_table_contains (task_data->reading_hash, unique_id_checksum) || g_hash_table_contains (task_data->writing_hash, unique_id_checksum)) { active++; continue; } BZ_BEGIN_GUARD_WITH_CONTEXT (&guard1, &living->mutex, &living->gate); entry = g_weak_ref_get (&living->wr); if (entry != NULL) alive++; else { bz_clear_guard (&guard1); g_hash_table_iter_remove (&iter); pruned++; } } bz_clear_guard (&guard0); #ifdef __GLIBC__ malloc_trim (0); #endif g_debug ("Sweep report: finished in %.4f seconds, including time to acquire guards\n" " Out of a total of %d entries considered:\n" " %d were skipped due to active tasks being associated with them\n" " %d application entries were otherwise kept alive\n" " %d entries were forgotten by the application and were pruned\n" " Another sweep will take place in %d msec", g_timer_elapsed (timer, NULL), total, active, alive, pruned, WATCH_CLEANUP_INTERVAL_MSEC); return dex_timeout_new_msec (WATCH_CLEANUP_INTERVAL_MSEC); } /* End of bz-entry-cache-manager.c */ kolunmi-bazaar-7b9c8e1/src/bz-entry-cache-manager.h000066400000000000000000000041171514314607700222500ustar00rootroot00000000000000/* bz-entry-cache-manager.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry.h" G_BEGIN_DECLS #define BZ_ENTRY_CACHE_ERROR (bz_entry_cache_error_quark ()) GQuark bz_entry_cache_error_quark (void); typedef enum { BZ_ENTRY_CACHE_ERROR_CACHE_FAILED = 0, BZ_ENTRY_CACHE_ERROR_DECACHE_FAILED, BZ_ENTRY_CACHE_ERROR_ENUMERATE_FAILED, } BzEntry_CacheError; #define BZ_TYPE_ENTRY_CACHE_MANAGER (bz_entry_cache_manager_get_type ()) G_DECLARE_FINAL_TYPE (BzEntryCacheManager, bz_entry_cache_manager, BZ, ENTRY_CACHE_MANAGER, GObject) BzEntryCacheManager * bz_entry_cache_manager_new (void); guint64 bz_entry_cache_manager_get_max_memory_usage (BzEntryCacheManager *self); void bz_entry_cache_manager_set_max_memory_usage (BzEntryCacheManager *self, guint64 max_memory_usage); DexFuture * bz_entry_cache_manager_add (BzEntryCacheManager *self, BzEntry *entry); DexFuture * bz_entry_cache_manager_get (BzEntryCacheManager *self, const char *unique_id); DexFuture * bz_entry_cache_manager_get_by_checksum (BzEntryCacheManager *self, const char *unique_id_checksum); DexFuture * bz_entry_cache_manager_enumerate_disk (BzEntryCacheManager *self); G_END_DECLS /* End of bz-entry-cache-manager.h */ kolunmi-bazaar-7b9c8e1/src/bz-entry-group-util.c000066400000000000000000000100371514314607700216750ustar00rootroot00000000000000/* bz-entry-group-util.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include "bz-entry-group-util.h" #include "bz-error.h" BzEntry * bz_entry_group_find_entry (BzEntryGroup *group, gboolean (*test) (BzEntry *entry), GtkWidget *window, GError **error) { g_autoptr (GListModel) model = NULL; guint n_items = 0; g_autoptr (GPtrArray) candidates = NULL; g_return_val_if_fail (BZ_IS_ENTRY_GROUP (group), NULL); model = dex_await_object (bz_entry_group_dup_all_into_store (group), error); if (model == NULL) return NULL; n_items = g_list_model_get_n_items (model); candidates = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = NULL; entry = g_list_model_get_item (model, i); if (bz_entry_is_installed (entry) && (test == NULL || test (entry))) g_ptr_array_add (candidates, g_steal_pointer (&entry)); } if (candidates->len == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "BUG: No entry candidates satisfied this test condition"); return NULL; } else if (candidates->len == 1) return g_ptr_array_steal_index_fast (candidates, 0); else if (window != NULL) { AdwDialog *alert = NULL; g_autofree char *response = NULL; alert = adw_alert_dialog_new (NULL, NULL); adw_alert_dialog_set_prefer_wide_layout (ADW_ALERT_DIALOG (alert), TRUE); adw_alert_dialog_format_heading ( ADW_ALERT_DIALOG (alert), _ ("Choose an Installation")); adw_alert_dialog_format_body ( ADW_ALERT_DIALOG (alert), _ ("You have multiple versions of this app installed. Which " "one would you like to proceed with?")); adw_alert_dialog_add_responses ( ADW_ALERT_DIALOG (alert), "cancel", _ ("Cancel"), NULL); adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (alert), "cancel"); adw_alert_dialog_set_response_appearance ( ADW_ALERT_DIALOG (alert), "cancel", ADW_RESPONSE_DESTRUCTIVE); for (guint i = 0; i < candidates->len; i++) { BzEntry *entry = NULL; const char *unique_id = NULL; entry = g_ptr_array_index (candidates, i); unique_id = bz_entry_get_unique_id (entry); adw_alert_dialog_add_responses ( ADW_ALERT_DIALOG (alert), unique_id, unique_id, NULL); if (i == 0) adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (alert), unique_id); } adw_dialog_present (alert, GTK_WIDGET (window)); response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (alert)), NULL); if (response != NULL) { for (guint i = 0; i < candidates->len; i++) { BzEntry *entry = NULL; const char *unique_id = NULL; entry = g_ptr_array_index (candidates, i); unique_id = bz_entry_get_unique_id (entry); if (g_strcmp0 (unique_id, response) == 0) return g_object_ref (entry); } } } return NULL; } kolunmi-bazaar-7b9c8e1/src/bz-entry-group-util.h000066400000000000000000000021231514314607700216770ustar00rootroot00000000000000/* bz-entry-group-util.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include "bz-entry.h" #include G_BEGIN_DECLS BzEntry * bz_entry_group_find_entry (BzEntryGroup *group, gboolean (*test) (BzEntry *entry), GtkWidget *window, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-entry-group.c000066400000000000000000001246021514314607700207260ustar00rootroot00000000000000/* bz-entry-group.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::ENTRY-GROUP" #define BAZAAR_MODULE "entry-group" #include "bz-entry-group.h" #include "bz-async-texture.h" #include "bz-env.h" #include "bz-flatpak-entry.h" #include "bz-io.h" #include "bz-util.h" struct _BzEntryGroup { GObject parent_instance; BzApplicationMapFactory *factory; GtkStringList *unique_ids; GtkStringList *installed_versions; char *id; char *title; char *developer; char *description; GdkPaintable *icon_paintable; GIcon *mini_icon; gboolean is_floss; char *light_accent_color; char *dark_accent_color; gboolean is_flathub; gboolean is_verified; char *search_tokens; char *remote_repos_string; char *eol; guint64 installed_size; int n_addons; char *donation_url; GListModel *categories; int max_usefulness; int installable; int updatable; int removable; int installable_available; int updatable_available; int removable_available; gboolean read_only; gboolean searchable; guint64 user_data_size; DexFuture *user_data_size_future; DexFuture *reap_user_data_future; GWeakRef ui_entry; BzResult *standalone_ui_entry; GMutex mutex; }; G_DEFINE_FINAL_TYPE (BzEntryGroup, bz_entry_group, G_TYPE_OBJECT) enum { PROP_0, PROP_MODEL, PROP_INSTALLED_VERSIONS, PROP_ID, PROP_TITLE, PROP_DEVELOPER, PROP_DESCRIPTION, PROP_ICON_PAINTABLE, PROP_MINI_ICON, PROP_IS_FLOSS, PROP_LIGHT_ACCENT_COLOR, PROP_DARK_ACCENT_COLOR, PROP_IS_FLATHUB, PROP_IS_VERIFIED, PROP_SEARCH_TOKENS, PROP_UI_ENTRY, PROP_REMOTE_REPOS_STRING, PROP_EOL, PROP_INSTALLED_SIZE, PROP_N_ADDONS, PROP_DONATION_URL, PROP_CATEGORIES, PROP_INSTALLABLE, PROP_UPDATABLE, PROP_REMOVABLE, PROP_INSTALLABLE_AND_AVAILABLE, PROP_UPDATABLE_AND_AVAILABLE, PROP_REMOVABLE_AND_AVAILABLE, PROP_USER_DATA_SIZE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void installed_changed (BzEntryGroup *self, GParamSpec *pspec, BzEntry *entry); static void holding_changed (BzEntryGroup *self, GParamSpec *pspec, BzEntry *entry); static DexFuture * dup_all_into_store_fiber (BzEntryGroup *self); static DexFuture * user_data_size_then (DexFuture *future, GWeakRef *wr); static void check_user_data_size (BzEntryGroup *self); static void bz_entry_group_dispose (GObject *object) { BzEntryGroup *self = BZ_ENTRY_GROUP (object); dex_clear (&self->user_data_size_future); dex_clear (&self->reap_user_data_future); g_clear_object (&self->factory); g_clear_object (&self->unique_ids); g_clear_object (&self->installed_versions); g_clear_pointer (&self->id, g_free); g_clear_pointer (&self->title, g_free); g_clear_pointer (&self->developer, g_free); g_clear_pointer (&self->description, g_free); g_clear_pointer (&self->light_accent_color, g_free); g_clear_pointer (&self->dark_accent_color, g_free); g_clear_object (&self->icon_paintable); g_clear_object (&self->mini_icon); g_clear_pointer (&self->search_tokens, g_free); g_clear_pointer (&self->remote_repos_string, g_free); g_clear_pointer (&self->eol, g_free); g_clear_pointer (&self->donation_url, g_free); g_clear_object (&self->categories); g_weak_ref_clear (&self->ui_entry); g_clear_object (&self->standalone_ui_entry); g_mutex_clear (&self->mutex); G_OBJECT_CLASS (bz_entry_group_parent_class)->dispose (object); } static void bz_entry_group_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzEntryGroup *self = BZ_ENTRY_GROUP (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_entry_group_get_model (self)); break; case PROP_INSTALLED_VERSIONS: g_value_set_object (value, bz_entry_group_get_installed_versions (self)); break; case PROP_ID: g_value_set_string (value, bz_entry_group_get_id (self)); break; case PROP_TITLE: g_value_set_string (value, bz_entry_group_get_title (self)); break; case PROP_DEVELOPER: g_value_set_string (value, bz_entry_group_get_developer (self)); break; case PROP_DESCRIPTION: g_value_set_string (value, bz_entry_group_get_description (self)); break; case PROP_ICON_PAINTABLE: g_value_set_object (value, bz_entry_group_get_icon_paintable (self)); break; case PROP_MINI_ICON: g_value_set_object (value, bz_entry_group_get_mini_icon (self)); break; case PROP_IS_FLOSS: g_value_set_boolean (value, bz_entry_group_get_is_floss (self)); break; case PROP_LIGHT_ACCENT_COLOR: g_value_set_string (value, bz_entry_group_get_light_accent_color (self)); break; case PROP_DARK_ACCENT_COLOR: g_value_set_string (value, bz_entry_group_get_dark_accent_color (self)); break; case PROP_IS_FLATHUB: g_value_set_boolean (value, bz_entry_group_get_is_flathub (self)); break; case PROP_IS_VERIFIED: g_value_set_boolean (value, bz_entry_group_get_is_verified (self)); break; case PROP_SEARCH_TOKENS: g_value_set_boxed (value, bz_entry_group_get_search_tokens (self)); break; case PROP_EOL: g_value_set_string (value, bz_entry_group_get_eol (self)); break; case PROP_INSTALLED_SIZE: g_value_set_uint64 (value, bz_entry_group_get_installed_size (self)); break; case PROP_N_ADDONS: g_value_set_int (value, bz_entry_group_get_n_addons (self)); break; case PROP_DONATION_URL: g_value_set_string (value, bz_entry_group_get_donation_url (self)); break; case PROP_CATEGORIES: g_value_set_object (value, bz_entry_group_get_categories (self)); break; case PROP_UI_ENTRY: g_value_take_object (value, bz_entry_group_dup_ui_entry (self)); break; case PROP_REMOTE_REPOS_STRING: g_value_set_string (value, self->remote_repos_string); break; case PROP_INSTALLABLE: g_value_set_int (value, bz_entry_group_get_installable (self)); break; case PROP_UPDATABLE: g_value_set_int (value, bz_entry_group_get_updatable (self)); break; case PROP_REMOVABLE: g_value_set_int (value, bz_entry_group_get_removable (self)); break; case PROP_INSTALLABLE_AND_AVAILABLE: g_value_set_int (value, bz_entry_group_get_installable_and_available (self)); break; case PROP_UPDATABLE_AND_AVAILABLE: g_value_set_int (value, bz_entry_group_get_updatable_and_available (self)); break; case PROP_REMOVABLE_AND_AVAILABLE: g_value_set_int (value, bz_entry_group_get_removable_and_available (self)); break; case PROP_USER_DATA_SIZE: g_value_set_uint64 (value, bz_entry_group_get_user_data_size (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_group_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { // BzEntryGroup *self = BZ_ENTRY_GROUP (object); switch (prop_id) { case PROP_MODEL: case PROP_ID: case PROP_TITLE: case PROP_DEVELOPER: case PROP_DESCRIPTION: case PROP_ICON_PAINTABLE: case PROP_MINI_ICON: case PROP_IS_FLOSS: case PROP_LIGHT_ACCENT_COLOR: case PROP_DARK_ACCENT_COLOR: case PROP_IS_FLATHUB: case PROP_IS_VERIFIED: case PROP_SEARCH_TOKENS: case PROP_EOL: case PROP_UI_ENTRY: case PROP_REMOTE_REPOS_STRING: case PROP_INSTALLABLE: case PROP_UPDATABLE: case PROP_REMOVABLE: case PROP_INSTALLABLE_AND_AVAILABLE: case PROP_UPDATABLE_AND_AVAILABLE: case PROP_REMOVABLE_AND_AVAILABLE: case PROP_USER_DATA_SIZE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_group_class_init (BzEntryGroupClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_entry_group_set_property; object_class->get_property = bz_entry_group_get_property; object_class->dispose = bz_entry_group_dispose; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE); props[PROP_INSTALLED_VERSIONS] = g_param_spec_object ( "installed-versions", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE); props[PROP_ID] = g_param_spec_string ( "id", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_TITLE] = g_param_spec_string ( "title", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_DEVELOPER] = g_param_spec_string ( "developer", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_DESCRIPTION] = g_param_spec_string ( "description", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_ICON_PAINTABLE] = g_param_spec_object ( "icon-paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READABLE); props[PROP_MINI_ICON] = g_param_spec_object ( "mini-icon", NULL, NULL, G_TYPE_ICON, G_PARAM_READABLE); props[PROP_IS_FLOSS] = g_param_spec_boolean ( "is-floss", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_LIGHT_ACCENT_COLOR] = g_param_spec_string ( "light-accent-color", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_DARK_ACCENT_COLOR] = g_param_spec_string ( "dark-accent-color", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_IS_FLATHUB] = g_param_spec_boolean ( "is-flathub", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_IS_VERIFIED] = g_param_spec_boolean ( "is-verified", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_SEARCH_TOKENS] = g_param_spec_string ( "search-tokens", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_EOL] = g_param_spec_string ( "eol", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_INSTALLED_SIZE] = g_param_spec_uint64 ( "installed-size", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE); props[PROP_N_ADDONS] = g_param_spec_int ( "n-addons", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_DONATION_URL] = g_param_spec_string ( "donation-url", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_CATEGORIES] = g_param_spec_object ( "categories", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE); props[PROP_UI_ENTRY] = g_param_spec_object ( "ui-entry", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READABLE); props[PROP_REMOTE_REPOS_STRING] = g_param_spec_string ( "remote-repos-string", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_INSTALLABLE] = g_param_spec_int ( "installable", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_UPDATABLE] = g_param_spec_int ( "updatable", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_REMOVABLE] = g_param_spec_int ( "removable", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_INSTALLABLE_AND_AVAILABLE] = g_param_spec_int ( "installable-and-available", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_UPDATABLE_AND_AVAILABLE] = g_param_spec_int ( "updatable-and-available", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_REMOVABLE_AND_AVAILABLE] = g_param_spec_int ( "removable-and-available", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE); props[PROP_USER_DATA_SIZE] = g_param_spec_uint64 ( "user-data-size", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_entry_group_init (BzEntryGroup *self) { self->unique_ids = gtk_string_list_new (NULL); self->installed_versions = gtk_string_list_new (NULL); self->max_usefulness = -1; g_weak_ref_init (&self->ui_entry, NULL); self->standalone_ui_entry = NULL; g_mutex_init (&self->mutex); } BzEntryGroup * bz_entry_group_new (BzApplicationMapFactory *factory) { BzEntryGroup *group = NULL; g_return_val_if_fail (BZ_IS_APPLICATION_MAP_FACTORY (factory), NULL); group = g_object_new (BZ_TYPE_ENTRY_GROUP, NULL); group->factory = g_object_ref (factory); return group; } BzEntryGroup * bz_entry_group_new_for_single_entry (BzEntry *entry) { BzEntryGroup *group = NULL; const char *id = NULL; const char *unique_id = NULL; const char *title = NULL; const char *developer = NULL; const char *description = NULL; GdkPaintable *icon_paintable = NULL; GIcon *mini_icon = NULL; const char *search_tokens = NULL; gboolean is_floss = FALSE; const char *light_accent_color = NULL; const char *dark_accent_color = NULL; gboolean is_flathub = FALSE; gboolean is_verified = FALSE; const char *eol = NULL; guint64 installed_size = 0; const char *donation_url = NULL; GListModel *entry_categories = NULL; DexFuture *future = NULL; g_return_val_if_fail (BZ_IS_ENTRY (entry), NULL); group = g_object_new (BZ_TYPE_ENTRY_GROUP, NULL); id = bz_entry_get_id (entry); unique_id = bz_entry_get_unique_id (entry); title = bz_entry_get_title (entry); developer = bz_entry_get_developer (entry); description = bz_entry_get_description (entry); icon_paintable = bz_entry_get_icon_paintable (entry); mini_icon = bz_entry_get_mini_icon (entry); search_tokens = bz_entry_get_search_tokens (entry); is_floss = bz_entry_get_is_foss (entry); light_accent_color = bz_entry_get_light_accent_color (entry); dark_accent_color = bz_entry_get_dark_accent_color (entry); is_flathub = bz_entry_get_is_flathub (entry); is_verified = bz_entry_is_verified (entry); eol = bz_entry_get_eol (entry); installed_size = bz_entry_get_installed_size (entry); donation_url = bz_entry_get_donation_url (entry); entry_categories = bz_entry_get_categories (entry); if (id != NULL) group->id = g_strdup (id); if (title != NULL) group->title = g_strdup (title); if (developer != NULL) group->developer = g_strdup (developer); if (description != NULL) group->description = g_strdup (description); if (icon_paintable != NULL) group->icon_paintable = g_object_ref (icon_paintable); if (mini_icon != NULL) group->mini_icon = g_object_ref (mini_icon); if (search_tokens != NULL) group->search_tokens = g_strdup (search_tokens); group->is_floss = is_floss; if (light_accent_color != NULL) group->light_accent_color = g_strdup (light_accent_color); if (dark_accent_color != NULL) group->dark_accent_color = g_strdup (dark_accent_color); group->is_flathub = is_flathub; group->is_verified = is_verified; if (eol != NULL) group->eol = g_strdup (eol); group->installed_size = installed_size; if (donation_url != NULL) group->donation_url = g_strdup (donation_url); if (entry_categories != NULL) group->categories = g_object_ref (entry_categories); if (unique_id != NULL) gtk_string_list_append (group->unique_ids, unique_id); future = dex_future_new_for_object (entry); group->standalone_ui_entry = bz_result_new (future); dex_unref (future); return group; } GMutexLocker * bz_entry_group_lock (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return g_mutex_locker_new (&self->mutex); } GListModel * bz_entry_group_get_model (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return G_LIST_MODEL (self->unique_ids); } GListModel * bz_entry_group_get_installed_versions (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return G_LIST_MODEL (self->installed_versions); } const char * bz_entry_group_get_id (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->id; } const char * bz_entry_group_get_title (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->title; } const char * bz_entry_group_get_developer (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->developer; } const char * bz_entry_group_get_description (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->description; } GdkPaintable * bz_entry_group_get_icon_paintable (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->icon_paintable; } GIcon * bz_entry_group_get_mini_icon (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->mini_icon; } gboolean bz_entry_group_get_is_floss (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), FALSE); return self->is_floss; } const char * bz_entry_group_get_light_accent_color (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->light_accent_color; } const char * bz_entry_group_get_dark_accent_color (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->dark_accent_color; } gboolean bz_entry_group_get_is_flathub (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), FALSE); return self->is_flathub; } gboolean bz_entry_group_get_is_verified (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), FALSE); return self->is_verified; } const char * bz_entry_group_get_search_tokens (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->search_tokens; } const char * bz_entry_group_get_eol (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->eol; } guint64 bz_entry_group_get_installed_size (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->installed_size; } int bz_entry_group_get_n_addons (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->n_addons; } const char * bz_entry_group_get_donation_url (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->donation_url; } GListModel * bz_entry_group_get_categories (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); return self->categories; } guint64 bz_entry_group_get_user_data_size (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); check_user_data_size (self); return self->user_data_size; } BzResult * bz_entry_group_dup_ui_entry (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); if (self->standalone_ui_entry != NULL) return g_object_ref (self->standalone_ui_entry); if (g_list_model_get_n_items (G_LIST_MODEL (self->unique_ids)) > 0) { g_autoptr (BzResult) result = NULL; result = g_weak_ref_get (&self->ui_entry); if (result == NULL) { g_autoptr (GtkStringObject) id = NULL; id = g_list_model_get_item (G_LIST_MODEL (self->unique_ids), 0); result = bz_application_map_factory_convert_one (self->factory, g_steal_pointer (&id)); if (result == NULL) return NULL; g_weak_ref_set (&self->ui_entry, result); } return g_steal_pointer (&result); } else return NULL; } char * bz_entry_group_dup_ui_entry_id (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); if (g_list_model_get_n_items (G_LIST_MODEL (self->unique_ids)) > 0) { g_autoptr (GtkStringObject) id = NULL; id = g_list_model_get_item (G_LIST_MODEL (self->unique_ids), 0); return g_strdup (gtk_string_object_get_string (id)); } else return NULL; } int bz_entry_group_get_installable (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); if (self->read_only) return 0; return self->installable; } int bz_entry_group_get_updatable (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->updatable; } int bz_entry_group_get_removable (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); if (self->read_only) return 0; return self->removable; } int bz_entry_group_get_installable_and_available (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->installable_available; } int bz_entry_group_get_updatable_and_available (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->updatable_available; } int bz_entry_group_get_removable_and_available (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), 0); return self->removable_available; } gboolean bz_entry_group_is_searchable (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), TRUE); return self->searchable; } void bz_entry_group_add (BzEntryGroup *self, BzEntry *entry, BzEntry *runtime, gboolean ignore_eol) { g_autoptr (GMutexLocker) locker = NULL; const char *unique_id = NULL; const char *installed_version = NULL; gint usefulness = 0; const char *eol = NULL; const char *title = NULL; const char *developer = NULL; const char *description = NULL; GdkPaintable *icon_paintable = NULL; GIcon *mini_icon = NULL; const char *search_tokens = NULL; gboolean is_floss = FALSE; const char *light_accent_color = NULL; const char *dark_accent_color = NULL; gboolean is_flathub = FALSE; gboolean is_verified = FALSE; guint64 installed_size = 0; GListModel *addons = NULL; int n_addons = 0; const char *donation_url = NULL; GListModel *entry_categories = NULL; guint existing = 0; gboolean is_searchable = FALSE; g_return_if_fail (BZ_IS_ENTRY_GROUP (self)); g_return_if_fail (BZ_IS_ENTRY (entry)); g_return_if_fail (runtime == NULL || BZ_IS_ENTRY (runtime)); locker = g_mutex_locker_new (&self->mutex); if (self->id == NULL) { self->id = g_strdup (bz_entry_get_id (entry)); self->read_only = g_strcmp0 (self->id, g_application_get_application_id (g_application_get_default ())) == 0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ID]); } unique_id = bz_entry_get_unique_id (entry); installed_version = bz_entry_get_installed_version (entry); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_VERSIONS]); if (!ignore_eol) { eol = bz_entry_get_eol (entry); if (eol == NULL && runtime != NULL) eol = bz_entry_get_eol (runtime); if (eol != NULL) { g_clear_pointer (&self->eol, g_free); self->eol = g_strdup (eol); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_EOL]); } } title = bz_entry_get_title (entry); developer = bz_entry_get_developer (entry); description = bz_entry_get_description (entry); icon_paintable = bz_entry_get_icon_paintable (entry); mini_icon = bz_entry_get_mini_icon (entry); search_tokens = bz_entry_get_search_tokens (entry); is_floss = bz_entry_get_is_foss (entry); light_accent_color = bz_entry_get_light_accent_color (entry); dark_accent_color = bz_entry_get_dark_accent_color (entry); is_flathub = bz_entry_get_is_flathub (entry); is_verified = bz_entry_is_verified (entry); installed_size = bz_entry_get_installed_size (entry); donation_url = bz_entry_get_donation_url (entry); entry_categories = bz_entry_get_categories (entry); addons = bz_entry_get_addons (entry); is_searchable = bz_entry_is_searchable (entry); if (addons != NULL) n_addons = g_list_model_get_n_items (addons); usefulness = bz_entry_calc_usefulness (entry); existing = gtk_string_list_find (self->unique_ids, unique_id); if (usefulness >= self->max_usefulness) { if (existing != G_MAXUINT) { gtk_string_list_remove (self->unique_ids, existing); gtk_string_list_remove (self->installed_versions, existing); } gtk_string_list_splice (self->unique_ids, 0, 0, (const char *const[]) { unique_id, NULL }); gtk_string_list_splice (self->installed_versions, 0, 0, (const char *const[]) { installed_version != NULL ? installed_version : "", NULL }); if (title != NULL) { g_clear_pointer (&self->title, g_free); self->title = g_strdup (title); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE]); } if (developer != NULL) { g_clear_pointer (&self->developer, g_free); self->developer = g_strdup (developer); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEVELOPER]); } if (description != NULL) { g_clear_pointer (&self->description, g_free); self->description = g_strdup (description); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DESCRIPTION]); } /* only grab icon paintable if we don't have it already to reduce flickering in UI */ if (icon_paintable != NULL && (self->icon_paintable == NULL || (BZ_IS_ASYNC_TEXTURE (self->icon_paintable) && !bz_async_texture_get_loaded (BZ_ASYNC_TEXTURE (self->icon_paintable)) && !bz_async_texture_is_loading (BZ_ASYNC_TEXTURE (self->icon_paintable))))) { g_clear_object (&self->icon_paintable); self->icon_paintable = g_object_ref (icon_paintable); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_PAINTABLE]); } if (mini_icon != NULL) { g_clear_object (&self->mini_icon); self->mini_icon = g_object_ref (mini_icon); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MINI_ICON]); } if (search_tokens != NULL) { g_clear_pointer (&self->search_tokens, g_free); self->search_tokens = g_strdup (search_tokens); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SEARCH_TOKENS]); } if (!!is_floss != !!self->is_floss) { self->is_floss = is_floss; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_FLOSS]); } if (light_accent_color != NULL) { g_clear_pointer (&self->light_accent_color, g_free); self->light_accent_color = g_strdup (light_accent_color); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LIGHT_ACCENT_COLOR]); } if (dark_accent_color != NULL) { g_clear_pointer (&self->dark_accent_color, g_free); self->dark_accent_color = g_strdup (dark_accent_color); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DARK_ACCENT_COLOR]); } if (!!is_flathub != !!self->is_flathub) { self->is_flathub = is_flathub; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_FLATHUB]); } if (!!is_verified != !!self->is_verified) { self->is_verified = is_verified; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_VERIFIED]); } if (installed_size != self->installed_size) { self->installed_size = installed_size; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_SIZE]); } if (n_addons != self->n_addons) { self->n_addons = n_addons; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_N_ADDONS]); } if (donation_url != NULL) { g_clear_pointer (&self->donation_url, g_free); self->donation_url = g_strdup (donation_url); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DONATION_URL]); } if (entry_categories != NULL && g_list_model_get_n_items (entry_categories) > 0) { g_clear_object (&self->categories); self->categories = g_object_ref (entry_categories); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORIES]); } self->max_usefulness = usefulness; } else { if (existing == G_MAXUINT) { gtk_string_list_append (self->unique_ids, unique_id); gtk_string_list_append (self->installed_versions, installed_version != NULL ? installed_version : ""); } if (title != NULL && self->title == NULL) { self->title = g_strdup (title); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE]); } if (developer != NULL && self->developer == NULL) { self->developer = g_strdup (developer); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEVELOPER]); } if (description != NULL && self->description == NULL) { self->description = g_strdup (description); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DESCRIPTION]); } if (icon_paintable != NULL && self->icon_paintable == NULL) { self->icon_paintable = g_object_ref (icon_paintable); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_PAINTABLE]); } if (mini_icon != NULL && self->mini_icon == NULL) { self->mini_icon = g_object_ref (mini_icon); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MINI_ICON]); } if (search_tokens != NULL && self->search_tokens == NULL) { self->search_tokens = g_strdup (search_tokens); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SEARCH_TOKENS]); } if (light_accent_color != NULL && self->light_accent_color == NULL) { self->light_accent_color = g_strdup (light_accent_color); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LIGHT_ACCENT_COLOR]); } if (dark_accent_color != NULL && self->dark_accent_color == NULL) { self->dark_accent_color = g_strdup (dark_accent_color); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DARK_ACCENT_COLOR]); } if (installed_size > 0 && self->installed_size == 0) { self->installed_size = installed_size; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_SIZE]); } if (donation_url != NULL && self->donation_url == NULL) { self->donation_url = g_strdup (donation_url); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DONATION_URL]); } } if (existing == G_MAXUINT) { const char *remote_repo = NULL; remote_repo = bz_entry_get_remote_repo_name (entry); if (remote_repo != NULL) { g_autofree char *capitalized_repo = NULL; if (remote_repo[0] != '\0') { capitalized_repo = g_strdup (remote_repo); capitalized_repo[0] = g_ascii_toupper (capitalized_repo[0]); } else { capitalized_repo = g_strdup (remote_repo); } if (self->remote_repos_string != NULL) { g_autofree char *old_string = NULL; if (strstr (self->remote_repos_string, capitalized_repo) == NULL) { old_string = g_steal_pointer (&self->remote_repos_string); self->remote_repos_string = g_strdup_printf ("%s • %s", old_string, capitalized_repo); } } else { self->remote_repos_string = g_strdup (capitalized_repo); } } if (bz_entry_is_installed (entry)) { self->removable++; if (!bz_entry_is_holding (entry)) { self->removable_available++; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AND_AVAILABLE]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE]); } else { gboolean is_installed_ref = FALSE; if (BZ_IS_FLATPAK_ENTRY (entry)) is_installed_ref = bz_flatpak_entry_is_installed_ref (BZ_FLATPAK_ENTRY (entry)); if (!is_installed_ref) { self->installable++; if (!bz_entry_is_holding (entry)) { self->installable_available++; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE_AND_AVAILABLE]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE]); } } } if (is_searchable && !self->searchable) { self->searchable = TRUE; } } void bz_entry_group_connect_living (BzEntryGroup *self, BzEntry *entry) { g_autoptr (GMutexLocker) locker = NULL; g_return_if_fail (BZ_IS_ENTRY_GROUP (self)); g_return_if_fail (BZ_IS_ENTRY (entry)); locker = g_mutex_locker_new (&self->mutex); g_signal_handlers_disconnect_by_func (entry, installed_changed, self); g_signal_handlers_disconnect_by_func (entry, holding_changed, self); g_signal_connect_object (entry, "notify::installed", G_CALLBACK (installed_changed), self, G_CONNECT_SWAPPED); g_signal_connect_object (entry, "notify::holding", G_CALLBACK (holding_changed), self, G_CONNECT_SWAPPED); } DexFuture * bz_entry_group_dup_all_into_store (BzEntryGroup *self) { g_return_val_if_fail (BZ_IS_ENTRY_GROUP (self), NULL); /* _must_ be the main scheduler since invokations * of BzApplicationMapFactory functions expect this */ return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) dup_all_into_store_fiber, g_object_ref (self), g_object_unref); } static void installed_changed (BzEntryGroup *self, GParamSpec *pspec, BzEntry *entry) { g_autoptr (GMutexLocker) locker = NULL; gboolean is_installed_ref = FALSE; const char *unique_id = NULL; const char *version = NULL; guint index = 0; locker = g_mutex_locker_new (&self->mutex); if (BZ_IS_FLATPAK_ENTRY (entry)) is_installed_ref = bz_flatpak_entry_is_installed_ref (BZ_FLATPAK_ENTRY (entry)); unique_id = bz_entry_get_unique_id (entry); version = bz_entry_get_installed_version (entry); index = gtk_string_list_find (self->unique_ids, unique_id); if (index != G_MAXUINT) { gtk_string_list_splice (self->installed_versions, index, 1, (const char *const[]) { version != NULL ? version : "", NULL }); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_VERSIONS]); if (bz_entry_is_installed (entry)) { self->installable--; self->removable++; if (!bz_entry_is_holding (entry)) { self->installable_available--; self->removable_available++; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE_AND_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AND_AVAILABLE]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE]); } else { self->removable--; if (!is_installed_ref) self->installable++; if (!bz_entry_is_holding (entry)) { self->removable_available--; if (!is_installed_ref) self->installable_available++; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AND_AVAILABLE]); if (!is_installed_ref) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE_AND_AVAILABLE]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE]); if (!is_installed_ref) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE]); } dex_clear (&self->user_data_size_future); self->user_data_size = 0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); } static void holding_changed (BzEntryGroup *self, GParamSpec *pspec, BzEntry *entry) { g_autoptr (GMutexLocker) locker = NULL; locker = g_mutex_locker_new (&self->mutex); if (bz_entry_is_holding (entry)) { if (bz_entry_is_installed (entry)) self->removable_available--; else self->installable_available--; } else { if (bz_entry_is_installed (entry)) self->removable_available++; else self->installable_available++; } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REMOVABLE_AND_AVAILABLE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLABLE_AND_AVAILABLE]); } static DexFuture * dup_all_into_store_fiber (BzEntryGroup *self) { g_autoptr (GPtrArray) futures = NULL; guint n_items = 0; g_autoptr (GListStore) store = NULL; guint n_resolved = 0; futures = g_ptr_array_new_with_free_func (dex_unref); n_items = g_list_model_get_n_items (G_LIST_MODEL (self->unique_ids)); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; g_autoptr (BzResult) result = NULL; string = g_list_model_get_item (G_LIST_MODEL (self->unique_ids), i); result = bz_application_map_factory_convert_one (self->factory, g_steal_pointer (&string)); g_ptr_array_add (futures, bz_result_dup_future (result)); } dex_await (dex_future_allv ( (DexFuture *const *) futures->pdata, futures->len), NULL); store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < futures->len; i++) { DexFuture *future = NULL; future = g_ptr_array_index (futures, i); if (dex_future_is_resolved (future)) { BzEntry *entry = NULL; entry = g_value_get_object (dex_future_get_value (future, NULL)); bz_entry_group_connect_living (self, entry); g_list_store_append (store, entry); } } n_resolved = g_list_model_get_n_items (G_LIST_MODEL (store)); if (n_resolved == 0) { g_warning ("No entries for %s were able to be resolved", self->id); return dex_future_new_reject ( G_IO_ERROR, G_IO_ERROR_UNKNOWN, "No entries for %s were able to be resolved", self->id); } if (n_resolved != n_items) g_warning ("Some entries for %s failed to resolve", self->id); return dex_future_new_for_object (store); } static DexFuture * reap_user_data_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzEntryGroup) self = NULL; guint64 old_size = 0; bz_weak_get_or_return_reject (self, wr); dex_clear (&self->reap_user_data_future); old_size = self->user_data_size; self->user_data_size = 0; if (old_size != 0) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); return dex_future_new_true (); } void bz_entry_group_reap_user_data (BzEntryGroup *self) { g_return_if_fail (BZ_IS_ENTRY_GROUP (self)); g_return_if_fail (self->id != NULL); if (self->reap_user_data_future != NULL) return; self->reap_user_data_future = dex_future_then ( bz_reap_user_data_dex (self->id), (DexFutureCallback) reap_user_data_then, bz_track_weak (self), bz_weak_release); } static DexFuture * user_data_size_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzEntryGroup) self = NULL; g_autoptr (GError) error = NULL; guint64 size = 0; guint64 old_size = 0; bz_weak_get_or_return_reject (self, wr); dex_clear (&self->user_data_size_future); size = dex_await_uint64 (dex_ref (future), &error); if (error != NULL) size = 0; old_size = self->user_data_size; self->user_data_size = size; if (old_size != size) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USER_DATA_SIZE]); return dex_future_new_true (); } static void check_user_data_size (BzEntryGroup *self) { g_autoptr (DexFuture) future = NULL; if (self->user_data_size_future != NULL || self->id == NULL) return; if (self->reap_user_data_future != NULL) return; future = bz_get_user_data_size_dex (self->id); future = dex_future_then ( future, (DexFutureCallback) user_data_size_then, bz_track_weak (self), bz_weak_release); self->user_data_size_future = g_steal_pointer (&future); } kolunmi-bazaar-7b9c8e1/src/bz-entry-group.h000066400000000000000000000070041514314607700207270ustar00rootroot00000000000000/* bz-entry-group.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-application-map-factory.h" #include "bz-entry.h" #include "bz-result.h" G_BEGIN_DECLS #define BZ_TYPE_ENTRY_GROUP (bz_entry_group_get_type ()) G_DECLARE_FINAL_TYPE (BzEntryGroup, bz_entry_group, BZ, ENTRY_GROUP, GObject) BzEntryGroup * bz_entry_group_new (BzApplicationMapFactory *factory); BzEntryGroup * bz_entry_group_new_for_single_entry (BzEntry *entry); /* Only necessary if reading props from another thread, writing is always prohibited */ GMutexLocker * bz_entry_group_lock (BzEntryGroup *self); GListModel * bz_entry_group_get_model (BzEntryGroup *self); GListModel * bz_entry_group_get_installed_versions (BzEntryGroup *self); const char * bz_entry_group_get_id (BzEntryGroup *self); const char * bz_entry_group_get_title (BzEntryGroup *self); const char * bz_entry_group_get_developer (BzEntryGroup *self); const char * bz_entry_group_get_description (BzEntryGroup *self); GdkPaintable * bz_entry_group_get_icon_paintable (BzEntryGroup *self); GIcon * bz_entry_group_get_mini_icon (BzEntryGroup *self); gboolean bz_entry_group_get_is_floss (BzEntryGroup *self); const char * bz_entry_group_get_light_accent_color (BzEntryGroup *self); const char * bz_entry_group_get_dark_accent_color (BzEntryGroup *self); gboolean bz_entry_group_get_is_flathub (BzEntryGroup *self); gboolean bz_entry_group_get_is_verified (BzEntryGroup *self); const char * bz_entry_group_get_search_tokens (BzEntryGroup *self); const char * bz_entry_group_get_eol (BzEntryGroup *self); guint64 bz_entry_group_get_installed_size (BzEntryGroup *self); int bz_entry_group_get_n_addons (BzEntryGroup *self); const char * bz_entry_group_get_donation_url (BzEntryGroup *self); GListModel * bz_entry_group_get_categories (BzEntryGroup *self); BzResult * bz_entry_group_dup_ui_entry (BzEntryGroup *self); char * bz_entry_group_dup_ui_entry_id (BzEntryGroup *self); int bz_entry_group_get_installable (BzEntryGroup *self); int bz_entry_group_get_updatable (BzEntryGroup *self); int bz_entry_group_get_removable (BzEntryGroup *self); int bz_entry_group_get_installable_and_available (BzEntryGroup *self); int bz_entry_group_get_updatable_and_available (BzEntryGroup *self); int bz_entry_group_get_removable_and_available (BzEntryGroup *self); gboolean bz_entry_group_is_searchable (BzEntryGroup *self); guint64 bz_entry_group_get_user_data_size (BzEntryGroup *self); void bz_entry_group_reap_user_data (BzEntryGroup *self); void bz_entry_group_add (BzEntryGroup *self, BzEntry *entry, BzEntry *runtime, gboolean ignore_eol); void bz_entry_group_connect_living (BzEntryGroup *self, BzEntry *entry); DexFuture * bz_entry_group_dup_all_into_store (BzEntryGroup *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-entry-inspector.blp000066400000000000000000000045431514314607700221340ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzEntryInspector: Adw.Window { title: "Entry Inspector"; default-width: 600; default-height: 800; width-request: 300; height-request: 600; Adw.ToolbarView { top-bar-style: raised_border; bottom-bar-style: raised_border; reveal-bottom-bars: false; content: Box { orientation: vertical; spacing: 5; Label { xalign: 0.0; label: bind template.result as <$BzResult>.message as ; } Label { styles [ "heading", ] xalign: 0.0; selectable: true; label: bind template.result as <$BzResult>.object as <$BzEntry>.title; } Label { xalign: 0.0; selectable: true; label: bind template.result as <$BzResult>.object as <$BzEntry>.unique_id; } Label { xalign: 0.0; selectable: true; label: bind template.result as <$BzResult>.object as <$BzEntry>.unique_id_checksum; } Label { xalign: 0.0; selectable: true; label: bind template.result as <$BzResult>.object as <$BzEntry>.id; } Box { orientation: horizontal; spacing: 5; Image { pixel-size: 16; paintable: bind template.result as <$BzResult>.object as <$BzEntry>.icon-paintable; } Image { pixel-size: 32; paintable: bind template.result as <$BzResult>.object as <$BzEntry>.icon-paintable; } Image { pixel-size: 64; paintable: bind template.result as <$BzResult>.object as <$BzEntry>.icon-paintable; } Image { pixel-size: 128; paintable: bind template.result as <$BzResult>.object as <$BzEntry>.icon-paintable; } } Box { orientation: horizontal; Button { label: "Serialize"; clicked => $gen_serialized(template); } CheckButton convert_to_json { label: "Convert to JSON"; active: true; } } ScrolledWindow { propagate-natural-height: true; child: TextView { styles [ "monospace", ] // wrap-mode: word_char; buffer: TextBuffer text_buffer {}; }; } }; [top] Adw.HeaderBar top_header_bar {} } } kolunmi-bazaar-7b9c8e1/src/bz-entry-inspector.c000066400000000000000000000126431514314607700216010ustar00rootroot00000000000000/* bz-entry-inspector.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-entry-inspector.h" #include "bz-entry.h" #include "bz-serializable.h" struct _BzEntryInspector { AdwWindow parent_instance; BzResult *result; /* Template widgets */ GtkTextBuffer *text_buffer; GtkCheckButton *convert_to_json; }; G_DEFINE_FINAL_TYPE (BzEntryInspector, bz_entry_inspector, ADW_TYPE_WINDOW); enum { PROP_0, PROP_RESULT, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_entry_inspector_dispose (GObject *object) { BzEntryInspector *self = BZ_ENTRY_INSPECTOR (object); g_clear_pointer (&self->result, g_object_unref); G_OBJECT_CLASS (bz_entry_inspector_parent_class)->dispose (object); } static void bz_entry_inspector_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzEntryInspector *self = BZ_ENTRY_INSPECTOR (object); switch (prop_id) { case PROP_RESULT: g_value_set_object (value, bz_entry_inspector_get_result (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_inspector_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzEntryInspector *self = BZ_ENTRY_INSPECTOR (object); switch (prop_id) { case PROP_RESULT: bz_entry_inspector_set_result (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gen_serialized (BzEntryInspector *self, GtkButton *button) { if (bz_result_get_resolved (self->result)) { BzEntry *entry = NULL; g_autoptr (GVariantBuilder) builder = NULL; g_autoptr (GVariant) variant = NULL; g_autofree char *string = NULL; entry = bz_result_get_object (self->result); builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); bz_serializable_serialize (BZ_SERIALIZABLE (entry), builder); variant = g_variant_builder_end (builder); if (gtk_check_button_get_active (self->convert_to_json)) { g_autoptr (JsonNode) node = NULL; g_autoptr (JsonGenerator) generator = NULL; node = json_gvariant_serialize (variant); generator = json_generator_new (); json_generator_set_pretty (generator, TRUE); json_generator_set_root (generator, node); string = json_generator_to_data (generator, NULL); } else string = g_variant_print (variant, FALSE); gtk_text_buffer_set_text (self->text_buffer, string, -1); } else gtk_text_buffer_set_text (self->text_buffer, "!!! The entry has not resolved", -1); } static void bz_entry_inspector_class_init (BzEntryInspectorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_entry_inspector_set_property; object_class->get_property = bz_entry_inspector_get_property; object_class->dispose = bz_entry_inspector_dispose; props[PROP_RESULT] = g_param_spec_object ( "result", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-entry-inspector.ui"); gtk_widget_class_bind_template_child (widget_class, BzEntryInspector, text_buffer); gtk_widget_class_bind_template_child (widget_class, BzEntryInspector, convert_to_json); gtk_widget_class_bind_template_callback (widget_class, gen_serialized); } static void bz_entry_inspector_init (BzEntryInspector *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzEntryInspector * bz_entry_inspector_new (void) { return g_object_new (BZ_TYPE_ENTRY_INSPECTOR, NULL); } BzResult * bz_entry_inspector_get_result (BzEntryInspector *self) { g_return_val_if_fail (BZ_IS_ENTRY_INSPECTOR (self), NULL); return self->result; } void bz_entry_inspector_set_result (BzEntryInspector *self, BzResult *result) { g_return_if_fail (BZ_IS_ENTRY_INSPECTOR (self)); g_clear_pointer (&self->result, g_object_unref); if (result != NULL) self->result = g_object_ref (result); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESULT]); } /* End of bz-entry-inspector.c */ kolunmi-bazaar-7b9c8e1/src/bz-entry-inspector.h000066400000000000000000000024001514314607700215740ustar00rootroot00000000000000/* bz-entry-inspector.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-result.h" G_BEGIN_DECLS #define BZ_TYPE_ENTRY_INSPECTOR (bz_entry_inspector_get_type ()) G_DECLARE_FINAL_TYPE (BzEntryInspector, bz_entry_inspector, BZ, ENTRY_INSPECTOR, AdwWindow) BzEntryInspector * bz_entry_inspector_new (void); BzResult * bz_entry_inspector_get_result (BzEntryInspector *self); void bz_entry_inspector_set_result (BzEntryInspector *self, BzResult *result); G_END_DECLS /* End of bz-entry-inspector.h */ kolunmi-bazaar-7b9c8e1/src/bz-entry-selection-row.blp000066400000000000000000000010631514314607700227120ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzEntrySelectionRow: Adw.ActionRow { activatable-widget: radio; [prefix] CheckButton radio { valign: center; } [suffix] Image { visible: bind template.repository as <$BzRepository>.is-user; icon-name: "person-symbolic"; has-tooltip: true; tooltip-text: _("For this user only"); } title: bind template.repository as <$BzRepository>.title; subtitle: bind $get_subtitle(template.entry as <$BzFlatpakEntry>.flatpak-version, template.repository as <$BzRepository>.is-user) as ; } kolunmi-bazaar-7b9c8e1/src/bz-entry-selection-row.c000066400000000000000000000114621514314607700223630ustar00rootroot00000000000000/* bz-entry-selection-row.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-entry-selection-row.h" #include "bz-flatpak-entry.h" #include "bz-template-callbacks.h" struct _BzEntrySelectionRow { AdwActionRow parent_instance; GtkCheckButton *radio; BzFlatpakEntry *entry; BzRepository *repository; }; G_DEFINE_FINAL_TYPE (BzEntrySelectionRow, bz_entry_selection_row, ADW_TYPE_ACTION_ROW) enum { PROP_0, PROP_ENTRY, PROP_REPOSITORY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_entry_selection_row_dispose (GObject *object) { BzEntrySelectionRow *self = BZ_ENTRY_SELECTION_ROW (object); g_clear_object (&self->entry); g_clear_object (&self->repository); G_OBJECT_CLASS (bz_entry_selection_row_parent_class)->dispose (object); } static void bz_entry_selection_row_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzEntrySelectionRow *self = BZ_ENTRY_SELECTION_ROW (object); switch (prop_id) { case PROP_ENTRY: g_value_set_object (value, self->entry); break; case PROP_REPOSITORY: g_value_set_object (value, self->repository); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_selection_row_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzEntrySelectionRow *self = BZ_ENTRY_SELECTION_ROW (object); switch (prop_id) { case PROP_ENTRY: g_clear_object (&self->entry); self->entry = g_value_dup_object (value); break; case PROP_REPOSITORY: g_clear_object (&self->repository); self->repository = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * get_subtitle (gpointer object, const char *version, gboolean is_user) { const char *scope = is_user ? _ ("this user") : _ ("all users"); return g_strdup_printf ("%s • %s", version, scope); } static void bz_entry_selection_row_class_init (BzEntrySelectionRowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_entry_selection_row_dispose; object_class->get_property = bz_entry_selection_row_get_property; object_class->set_property = bz_entry_selection_row_set_property; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_FLATPAK_ENTRY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_REPOSITORY] = g_param_spec_object ( "repository", NULL, NULL, BZ_TYPE_REPOSITORY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_REPOSITORY); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-entry-selection-row.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_callback (widget_class, get_subtitle); gtk_widget_class_bind_template_child (widget_class, BzEntrySelectionRow, radio); } static void bz_entry_selection_row_init (BzEntrySelectionRow *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzEntrySelectionRow * bz_entry_selection_row_new (BzFlatpakEntry *entry, BzRepository *repository) { g_return_val_if_fail (BZ_IS_ENTRY (entry), NULL); return g_object_new (BZ_TYPE_ENTRY_SELECTION_ROW, "entry", entry, "repository", repository, NULL); } GtkCheckButton * bz_entry_selection_row_get_radio (BzEntrySelectionRow *self) { g_return_val_if_fail (BZ_IS_ENTRY_SELECTION_ROW (self), NULL); return self->radio; } kolunmi-bazaar-7b9c8e1/src/bz-entry-selection-row.h000066400000000000000000000024021514314607700223620ustar00rootroot00000000000000/* bz-entry-selection-row.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-flatpak-entry.h" #include "bz-repository.h" G_BEGIN_DECLS #define BZ_TYPE_ENTRY_SELECTION_ROW (bz_entry_selection_row_get_type ()) G_DECLARE_FINAL_TYPE (BzEntrySelectionRow, bz_entry_selection_row, BZ, ENTRY_SELECTION_ROW, AdwActionRow) BzEntrySelectionRow * bz_entry_selection_row_new (BzFlatpakEntry *entry, BzRepository *repository); GtkCheckButton * bz_entry_selection_row_get_radio (BzEntrySelectionRow *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-entry.c000066400000000000000000002734761514314607700176120ustar00rootroot00000000000000/* bz-entry.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ /* TODO: clean this mess up */ #define G_LOG_DOMAIN "BAZAAR::ENTRY" #define BAZAAR_MODULE "entry" #include #include "bz-app-permissions.h" #include "bz-async-texture.h" #include "bz-country-data-point.h" #include "bz-data-point.h" #include "bz-entry.h" #include "bz-env.h" #include "bz-flathub-category.h" #include "bz-global-net.h" #include "bz-io.h" #include "bz-release.h" #include "bz-repository.h" #include "bz-serializable.h" #include "bz-url.h" #include "bz-util.h" #include "bz-verification-status.h" G_DEFINE_FLAGS_TYPE ( BzEntryKind, bz_entry_kind, G_DEFINE_ENUM_VALUE (BZ_ENTRY_KIND_APPLICATION, "application"), G_DEFINE_ENUM_VALUE (BZ_ENTRY_KIND_RUNTIME, "runtime"), G_DEFINE_ENUM_VALUE (BZ_ENTRY_KIND_ADDON, "addon")) G_DEFINE_FLAGS_TYPE ( BzControlType, bz_control_type, G_DEFINE_ENUM_VALUE (BZ_CONTROL_NONE, "none"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_POINTING, "pointing"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_KEYBOARD, "keyboard"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_CONSOLE, "console"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_TABLET, "tablet"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_TOUCH, "touch"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_GAMEPAD, "gamepad"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_TV_REMOTE, "tv-remote"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_VOICE, "voice"), G_DEFINE_ENUM_VALUE (BZ_CONTROL_VISION, "vision")) G_DEFINE_ENUM_TYPE ( BzRelationType, bz_relation_type, G_DEFINE_ENUM_VALUE (BZ_RELATION_REQUIRES, "requires"), G_DEFINE_ENUM_VALUE (BZ_RELATION_RECOMMENDS, "recommends"), G_DEFINE_ENUM_VALUE (BZ_RELATION_SUPPORTS, "supports")) typedef struct { gint hold; gboolean installed; char *installed_version; gboolean searchable; guint kinds; GListModel *addons; char *id; char *unique_id; char *unique_id_checksum; char *title; char *eol; char *description; char *long_description; char *remote_repo_name; char *url; guint64 size; guint64 installed_size; GdkPaintable *icon_paintable; GIcon *mini_icon; GdkPaintable *remote_repo_icon; char *search_tokens; char *metadata_license; char *project_license; gboolean is_floss; char *project_group; char *developer; char *developer_id; GListModel *developer_apps; GListModel *screenshot_paintables; GListModel *screenshot_captions; GdkPaintable *thumbnail_paintable; GListModel *share_urls; char *donation_url; char *forge_url; GListModel *reviews; double average_rating; char *ratings_summary; GListModel *version_history; char *light_accent_color; char *dark_accent_color; gboolean is_mobile_friendly; guint required_controls; guint recommended_controls; guint supported_controls; gint min_display_length; gint max_display_length; AsContentRating *content_rating; GListModel *keywords; GListModel *categories; BzAppPermissions *permissions; gboolean is_flathub; BzVerificationStatus *verification_status; GListModel *download_stats; GListModel *download_stats_per_country; int recent_downloads; int total_downloads; int favorites_count; GHashTable *flathub_prop_queries; DexFuture *mini_icon_future; } BzEntryPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BzEntry, bz_entry, G_TYPE_OBJECT); enum { PROP_0, PROP_HOLDING, PROP_INSTALLED, PROP_INSTALLED_VERSION, PROP_SEARCHABLE, PROP_KINDS, PROP_ADDONS, PROP_ID, PROP_UNIQUE_ID, PROP_UNIQUE_ID_CHECKSUM, PROP_TITLE, PROP_EOL, PROP_DESCRIPTION, PROP_DOWNLOAD_STATS_PER_COUNTRY, PROP_LONG_DESCRIPTION, PROP_REMOTE_REPO_NAME, PROP_URL, PROP_SIZE, PROP_INSTALLED_SIZE, PROP_ICON_PAINTABLE, PROP_MINI_ICON, PROP_SEARCH_TOKENS, PROP_REMOTE_REPO_ICON, PROP_METADATA_LICENSE, PROP_PROJECT_LICENSE, PROP_IS_FLOSS, PROP_PROJECT_GROUP, PROP_DEVELOPER, PROP_DEVELOPER_ID, PROP_DEVELOPER_APPS, PROP_SCREENSHOT_PAINTABLES, PROP_SCREENSHOT_CAPTIONS, PROP_THUMBNAIL_PAINTABLE, PROP_SHARE_URLS, PROP_DONATION_URL, PROP_FORGE_URL, PROP_REVIEWS, PROP_AVERAGE_RATING, PROP_RATINGS_SUMMARY, PROP_VERSION_HISTORY, PROP_IS_FLATHUB, PROP_VERIFICATION_STATUS, PROP_DOWNLOAD_STATS, PROP_RECENT_DOWNLOADS, PROP_TOTAL_DOWNLOADS, PROP_FAVORITES_COUNT, PROP_LIGHT_ACCENT_COLOR, PROP_DARK_ACCENT_COLOR, PROP_IS_MOBILE_FRIENDLY, PROP_REQUIRED_CONTROLS, PROP_RECOMMENDED_CONTROLS, PROP_SUPPORTED_CONTROLS, PROP_MIN_DISPLAY_LENGTH, PROP_MAX_DISPLAY_LENGTH, PROP_CONTENT_RATING, PROP_KEYWORDS, PROP_CATEGORIES, PROP_PERMISSIONS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; BZ_DEFINE_DATA ( query_flathub, QueryFlathub, { GWeakRef self; int prop; char *id; char *developer; }, g_weak_ref_clear (&self->self); BZ_RELEASE_DATA (id, g_free); BZ_RELEASE_DATA (developer, g_free)); static DexFuture * query_flathub_fiber (QueryFlathubData *data); static DexFuture * query_flathub_then (DexFuture *future, QueryFlathubData *data); static void query_flathub (BzEntry *self, int prop); static void download_stats_per_day_foreach (JsonObject *object, const gchar *member_name, JsonNode *member_node, GListStore *store); static void download_stats_per_country_foreach (JsonObject *object, const gchar *member_name, JsonNode *member_node, GListStore *store); static gboolean maybe_save_paintable (BzEntryPrivate *priv, const char *key, GdkPaintable *paintable, GVariantBuilder *builder); static GdkPaintable * make_async_texture (GVariant *parse); static DexFuture * icon_paintable_future_then (DexFuture *future, GWeakRef *wr); BZ_DEFINE_DATA ( load_mini_icon, LoadMiniIcon, { BzEntry *self; char *path; GIcon *result; }, BZ_RELEASE_DATA (self, g_object_unref); BZ_RELEASE_DATA (path, g_free); BZ_RELEASE_DATA (result, g_object_unref)) static DexFuture * load_mini_icon_fiber (LoadMiniIconData *data); static DexFuture * load_mini_icon_notify (LoadMiniIconData *data); static GIcon * load_mini_icon_sync (const char *unique_id_checksum, const char *path); static void clear_entry (BzEntry *self); static void bz_entry_dispose (GObject *object) { BzEntry *self = BZ_ENTRY (object); clear_entry (self); G_OBJECT_CLASS (bz_entry_parent_class)->dispose (object); } static void bz_entry_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzEntry *self = BZ_ENTRY (object); BzEntryPrivate *priv = bz_entry_get_instance_private (self); switch (prop_id) { case PROP_HOLDING: g_value_set_boolean (value, bz_entry_is_holding (self)); break; case PROP_INSTALLED: g_value_set_boolean (value, priv->installed); break; case PROP_INSTALLED_VERSION: g_value_set_string (value, priv->installed_version); break; case PROP_SEARCHABLE: g_value_set_boolean (value, priv->searchable); break; case PROP_ADDONS: g_value_set_object (value, priv->addons); break; case PROP_KINDS: g_value_set_flags (value, priv->kinds); break; case PROP_ID: g_value_set_string (value, priv->id); break; case PROP_UNIQUE_ID: g_value_set_string (value, priv->unique_id); break; case PROP_UNIQUE_ID_CHECKSUM: g_value_set_string (value, priv->unique_id_checksum); break; case PROP_TITLE: g_value_set_string (value, priv->title); break; case PROP_EOL: g_value_set_string (value, priv->eol); break; case PROP_DESCRIPTION: g_value_set_string (value, priv->description); break; case PROP_LONG_DESCRIPTION: g_value_set_string (value, priv->long_description); break; case PROP_REMOTE_REPO_NAME: g_value_set_string (value, priv->remote_repo_name); break; case PROP_URL: g_value_set_string (value, priv->url); break; case PROP_SIZE: g_value_set_uint64 (value, priv->size); break; case PROP_INSTALLED_SIZE: g_value_set_uint64 (value, priv->installed_size); break; case PROP_ICON_PAINTABLE: g_value_set_object (value, priv->icon_paintable); dex_unref (bz_entry_load_mini_icon (self)); break; case PROP_MINI_ICON: g_value_set_object (value, priv->mini_icon); break; case PROP_SEARCH_TOKENS: g_value_set_boxed (value, priv->search_tokens); break; case PROP_REMOTE_REPO_ICON: g_value_set_object (value, priv->remote_repo_icon); break; case PROP_METADATA_LICENSE: g_value_set_string (value, priv->metadata_license); break; case PROP_PROJECT_LICENSE: g_value_set_string (value, priv->project_license); break; case PROP_IS_FLOSS: g_value_set_boolean (value, priv->is_floss); break; case PROP_PROJECT_GROUP: g_value_set_string (value, priv->project_group); break; case PROP_DEVELOPER: g_value_set_string (value, priv->developer); break; case PROP_DEVELOPER_ID: g_value_set_string (value, priv->developer_id); break; case PROP_DEVELOPER_APPS: query_flathub (self, PROP_DEVELOPER_APPS); g_value_set_object (value, priv->developer_apps); break; case PROP_SCREENSHOT_PAINTABLES: g_value_set_object (value, priv->screenshot_paintables); break; case PROP_SCREENSHOT_CAPTIONS: g_value_set_object (value, priv->screenshot_captions); break; case PROP_THUMBNAIL_PAINTABLE: g_value_set_object (value, priv->thumbnail_paintable); break; case PROP_SHARE_URLS: g_value_set_object (value, priv->share_urls); break; case PROP_DONATION_URL: g_value_set_string (value, priv->donation_url); break; case PROP_FORGE_URL: g_value_set_string (value, priv->forge_url); break; case PROP_REVIEWS: g_value_set_object (value, priv->reviews); break; case PROP_AVERAGE_RATING: g_value_set_double (value, priv->average_rating); break; case PROP_RATINGS_SUMMARY: g_value_set_string (value, priv->ratings_summary); break; case PROP_VERSION_HISTORY: g_value_set_object (value, priv->version_history); break; case PROP_LIGHT_ACCENT_COLOR: g_value_set_string (value, priv->light_accent_color); break; case PROP_DARK_ACCENT_COLOR: g_value_set_string (value, priv->dark_accent_color); break; case PROP_IS_MOBILE_FRIENDLY: g_value_set_boolean (value, priv->is_mobile_friendly); break; case PROP_REQUIRED_CONTROLS: g_value_set_flags (value, priv->required_controls); break; case PROP_RECOMMENDED_CONTROLS: g_value_set_flags (value, priv->recommended_controls); break; case PROP_SUPPORTED_CONTROLS: g_value_set_flags (value, priv->supported_controls); break; case PROP_MIN_DISPLAY_LENGTH: g_value_set_int (value, priv->min_display_length); break; case PROP_MAX_DISPLAY_LENGTH: g_value_set_int (value, priv->max_display_length); break; case PROP_CONTENT_RATING: g_value_set_object (value, priv->content_rating); break; case PROP_KEYWORDS: g_value_set_object (value, priv->keywords); break; case PROP_CATEGORIES: g_value_set_object (value, priv->categories); break; case PROP_PERMISSIONS: g_value_set_object (value, priv->permissions); break; case PROP_IS_FLATHUB: g_value_set_boolean (value, priv->is_flathub); break; case PROP_VERIFICATION_STATUS: g_value_set_object (value, priv->verification_status); break; case PROP_DOWNLOAD_STATS: query_flathub (self, PROP_DOWNLOAD_STATS); g_value_set_object (value, priv->download_stats); break; case PROP_DOWNLOAD_STATS_PER_COUNTRY: query_flathub (self, PROP_DOWNLOAD_STATS_PER_COUNTRY); g_value_set_object (value, priv->download_stats_per_country); break; case PROP_RECENT_DOWNLOADS: query_flathub (self, PROP_DOWNLOAD_STATS); g_value_set_int (value, priv->recent_downloads); break; case PROP_TOTAL_DOWNLOADS: query_flathub (self, PROP_TOTAL_DOWNLOADS); g_value_set_int (value, priv->total_downloads); break; case PROP_FAVORITES_COUNT: query_flathub (self, PROP_FAVORITES_COUNT); g_value_set_int (value, priv->favorites_count); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzEntry *self = BZ_ENTRY (object); BzEntryPrivate *priv = bz_entry_get_instance_private (self); switch (prop_id) { case PROP_INSTALLED: priv->installed = g_value_get_boolean (value); break; case PROP_INSTALLED_VERSION: g_clear_pointer (&priv->installed_version, g_free); priv->installed_version = g_value_dup_string (value); break; case PROP_SEARCHABLE: priv->searchable = g_value_get_boolean (value); break; case PROP_ADDONS: g_clear_object (&priv->addons); priv->addons = g_value_dup_object (value); break; case PROP_KINDS: priv->kinds = g_value_get_flags (value); break; case PROP_ID: g_clear_pointer (&priv->id, g_free); priv->id = g_value_dup_string (value); break; case PROP_UNIQUE_ID: g_clear_pointer (&priv->unique_id, g_free); priv->unique_id = g_value_dup_string (value); break; case PROP_UNIQUE_ID_CHECKSUM: g_clear_pointer (&priv->unique_id_checksum, g_free); priv->unique_id_checksum = g_value_dup_string (value); break; case PROP_TITLE: g_clear_pointer (&priv->title, g_free); priv->title = g_value_dup_string (value); break; case PROP_EOL: g_clear_pointer (&priv->eol, g_free); priv->eol = g_value_dup_string (value); break; case PROP_DESCRIPTION: g_clear_pointer (&priv->description, g_free); priv->description = g_value_dup_string (value); break; case PROP_LONG_DESCRIPTION: g_clear_pointer (&priv->long_description, g_free); priv->long_description = g_value_dup_string (value); break; case PROP_REMOTE_REPO_NAME: g_clear_pointer (&priv->remote_repo_name, g_free); priv->remote_repo_name = g_value_dup_string (value); priv->is_flathub = g_strcmp0 (priv->remote_repo_name, "flathub") == 0; g_object_notify_by_pspec (object, props[PROP_IS_FLATHUB]); break; case PROP_URL: g_clear_pointer (&priv->url, g_free); priv->url = g_value_dup_string (value); break; case PROP_SIZE: priv->size = g_value_get_uint64 (value); break; case PROP_INSTALLED_SIZE: priv->installed_size = g_value_get_uint64 (value); break; case PROP_ICON_PAINTABLE: g_clear_object (&priv->icon_paintable); priv->icon_paintable = g_value_dup_object (value); break; case PROP_MINI_ICON: g_clear_object (&priv->mini_icon); priv->mini_icon = g_value_dup_object (value); break; case PROP_SEARCH_TOKENS: g_clear_pointer (&priv->search_tokens, g_free); priv->search_tokens = g_value_dup_string (value); break; case PROP_REMOTE_REPO_ICON: g_clear_object (&priv->remote_repo_icon); priv->remote_repo_icon = g_value_dup_object (value); break; case PROP_METADATA_LICENSE: g_clear_pointer (&priv->metadata_license, g_free); priv->metadata_license = g_value_dup_string (value); break; case PROP_PROJECT_LICENSE: g_clear_pointer (&priv->project_license, g_free); priv->project_license = g_value_dup_string (value); break; case PROP_IS_FLOSS: priv->is_floss = g_value_get_boolean (value); break; case PROP_PROJECT_GROUP: g_clear_pointer (&priv->project_group, g_free); priv->project_group = g_value_dup_string (value); break; case PROP_DEVELOPER: g_clear_pointer (&priv->developer, g_free); priv->developer = g_value_dup_string (value); break; case PROP_DEVELOPER_ID: g_clear_pointer (&priv->developer_id, g_free); priv->developer_id = g_value_dup_string (value); break; case PROP_DEVELOPER_APPS: g_clear_object (&priv->developer_apps); priv->developer_apps = g_value_dup_object (value); break; case PROP_SCREENSHOT_PAINTABLES: g_clear_object (&priv->screenshot_paintables); priv->screenshot_paintables = g_value_dup_object (value); break; case PROP_SCREENSHOT_CAPTIONS: g_clear_object (&priv->screenshot_captions); priv->screenshot_captions = g_value_dup_object (value); break; case PROP_THUMBNAIL_PAINTABLE: g_clear_object (&priv->thumbnail_paintable); priv->thumbnail_paintable = g_value_dup_object (value); break; case PROP_SHARE_URLS: g_clear_object (&priv->share_urls); priv->share_urls = g_value_dup_object (value); break; case PROP_DONATION_URL: g_clear_pointer (&priv->donation_url, g_free); priv->donation_url = g_value_dup_string (value); break; case PROP_FORGE_URL: g_clear_pointer (&priv->forge_url, g_free); priv->forge_url = g_value_dup_string (value); break; case PROP_REVIEWS: g_clear_object (&priv->reviews); priv->reviews = g_value_dup_object (value); break; case PROP_AVERAGE_RATING: priv->average_rating = g_value_get_double (value); break; case PROP_RATINGS_SUMMARY: g_clear_pointer (&priv->ratings_summary, g_free); priv->ratings_summary = g_value_dup_string (value); break; case PROP_VERSION_HISTORY: g_clear_object (&priv->version_history); priv->version_history = g_value_dup_object (value); break; case PROP_LIGHT_ACCENT_COLOR: g_clear_pointer (&priv->light_accent_color, g_free); priv->light_accent_color = g_value_dup_string (value); break; case PROP_DARK_ACCENT_COLOR: g_clear_pointer (&priv->dark_accent_color, g_free); priv->dark_accent_color = g_value_dup_string (value); break; case PROP_IS_MOBILE_FRIENDLY: priv->is_mobile_friendly = g_value_get_boolean (value); break; case PROP_REQUIRED_CONTROLS: priv->required_controls = g_value_get_flags (value); break; case PROP_RECOMMENDED_CONTROLS: priv->recommended_controls = g_value_get_flags (value); break; case PROP_SUPPORTED_CONTROLS: priv->supported_controls = g_value_get_flags (value); break; case PROP_MIN_DISPLAY_LENGTH: priv->min_display_length = g_value_get_int (value); break; case PROP_MAX_DISPLAY_LENGTH: priv->max_display_length = g_value_get_int (value); break; case PROP_CONTENT_RATING: g_clear_object (&priv->content_rating); priv->content_rating = g_value_dup_object (value); break; case PROP_KEYWORDS: g_clear_object (&priv->keywords); priv->keywords = g_value_dup_object (value); break; case PROP_CATEGORIES: g_clear_object (&priv->categories); priv->categories = g_value_dup_object (value); break; case PROP_PERMISSIONS: g_clear_object (&priv->permissions); priv->permissions = g_value_dup_object (value); break; case PROP_IS_FLATHUB: priv->is_flathub = g_value_get_boolean (value); break; case PROP_VERIFICATION_STATUS: g_clear_object (&priv->verification_status); priv->verification_status = g_value_dup_object (value); break; case PROP_DOWNLOAD_STATS: case PROP_DOWNLOAD_STATS_PER_COUNTRY: { if (prop_id == PROP_DOWNLOAD_STATS) { g_clear_object (&priv->download_stats); priv->download_stats = g_value_dup_object (value); if (priv->download_stats != NULL) { guint n_items = 0; guint start = 0; guint recent_downloads = 0; n_items = g_list_model_get_n_items (priv->download_stats); start = n_items - MIN (n_items, 30); for (guint i = start; i < n_items; i++) { g_autoptr (BzDataPoint) point = NULL; point = g_list_model_get_item (priv->download_stats, i); recent_downloads += bz_data_point_get_dependent (point); } priv->recent_downloads = recent_downloads; } else priv->recent_downloads = 0; g_object_notify_by_pspec (object, props[PROP_RECENT_DOWNLOADS]); } else { g_clear_object (&priv->download_stats_per_country); priv->download_stats_per_country = g_value_dup_object (value); } } break; case PROP_RECENT_DOWNLOADS: priv->recent_downloads = g_value_get_int (value); break; case PROP_TOTAL_DOWNLOADS: priv->total_downloads = g_value_get_int (value); break; case PROP_FAVORITES_COUNT: priv->favorites_count = g_value_get_int (value); break; case PROP_HOLDING: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_entry_class_init (BzEntryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_entry_set_property; object_class->get_property = bz_entry_get_property; object_class->dispose = bz_entry_dispose; props[PROP_HOLDING] = g_param_spec_boolean ( "holding", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_INSTALLED] = g_param_spec_boolean ( "installed", NULL, NULL, FALSE, G_PARAM_READWRITE); props[PROP_INSTALLED_VERSION] = g_param_spec_string ( "installed-version", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_SEARCHABLE] = g_param_spec_boolean ( "searchable", NULL, NULL, TRUE, G_PARAM_READWRITE); props[PROP_ADDONS] = g_param_spec_object ( "addons", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_KINDS] = g_param_spec_flags ( "kinds", NULL, NULL, BZ_TYPE_ENTRY_KIND, 0, G_PARAM_READWRITE); props[PROP_ID] = g_param_spec_string ( "id", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_UNIQUE_ID] = g_param_spec_string ( "unique-id", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_UNIQUE_ID_CHECKSUM] = g_param_spec_string ( "unique-id-checksum", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_TITLE] = g_param_spec_string ( "title", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_EOL] = g_param_spec_string ( "eol", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_DESCRIPTION] = g_param_spec_string ( "description", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_LONG_DESCRIPTION] = g_param_spec_string ( "long-description", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_URL] = g_param_spec_string ( "url", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_REMOTE_REPO_NAME] = g_param_spec_string ( "remote-repo-name", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_SIZE] = g_param_spec_uint64 ( "size", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READWRITE); props[PROP_INSTALLED_SIZE] = g_param_spec_uint64 ( "installed-size", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READWRITE); props[PROP_ICON_PAINTABLE] = g_param_spec_object ( "icon-paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READWRITE); props[PROP_MINI_ICON] = g_param_spec_object ( "mini-icon", NULL, NULL, G_TYPE_ICON, G_PARAM_READWRITE); props[PROP_SEARCH_TOKENS] = g_param_spec_string ( "search-tokens", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_REMOTE_REPO_ICON] = g_param_spec_object ( "remote-repo-icon", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READWRITE); props[PROP_METADATA_LICENSE] = g_param_spec_string ( "metadata-license", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_PROJECT_LICENSE] = g_param_spec_string ( "project-license", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_IS_FLOSS] = g_param_spec_boolean ( "is-floss", NULL, NULL, FALSE, G_PARAM_READWRITE); props[PROP_PROJECT_GROUP] = g_param_spec_string ( "project-group", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_DEVELOPER] = g_param_spec_string ( "developer", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_DEVELOPER_ID] = g_param_spec_string ( "developer-id", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_DEVELOPER_APPS] = g_param_spec_object ( "developer-apps", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_SCREENSHOT_PAINTABLES] = g_param_spec_object ( "screenshot-paintables", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_SCREENSHOT_CAPTIONS] = g_param_spec_object ( "screenshot-captions", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_THUMBNAIL_PAINTABLE] = g_param_spec_object ( "thumbnail-paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READWRITE); props[PROP_SHARE_URLS] = g_param_spec_object ( "share-urls", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_DONATION_URL] = g_param_spec_string ( "donation-url", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_FORGE_URL] = g_param_spec_string ( "forge-url", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_REVIEWS] = g_param_spec_object ( "reviews", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_AVERAGE_RATING] = g_param_spec_double ( "average-rating", NULL, NULL, 0.0, 1.0, 0.0, G_PARAM_READWRITE); props[PROP_RATINGS_SUMMARY] = g_param_spec_string ( "ratings-summary", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_VERSION_HISTORY] = g_param_spec_object ( "version-history", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_LIGHT_ACCENT_COLOR] = g_param_spec_string ( "light-accent-color", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_DARK_ACCENT_COLOR] = g_param_spec_string ( "dark-accent-color", NULL, NULL, NULL, G_PARAM_READWRITE); props[PROP_IS_MOBILE_FRIENDLY] = g_param_spec_boolean ( "is-mobile-friendly", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_REQUIRED_CONTROLS] = g_param_spec_flags ( "required-controls", NULL, NULL, BZ_TYPE_CONTROL_TYPE, BZ_CONTROL_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_RECOMMENDED_CONTROLS] = g_param_spec_flags ( "recommended-controls", NULL, NULL, BZ_TYPE_CONTROL_TYPE, BZ_CONTROL_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_SUPPORTED_CONTROLS] = g_param_spec_flags ( "supported-controls", NULL, NULL, BZ_TYPE_CONTROL_TYPE, BZ_CONTROL_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_MIN_DISPLAY_LENGTH] = g_param_spec_int ( "min-display-length", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_MAX_DISPLAY_LENGTH] = g_param_spec_int ( "max-display-length", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_CONTENT_RATING] = g_param_spec_object ( "content-rating", NULL, NULL, AS_TYPE_CONTENT_RATING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_KEYWORDS] = g_param_spec_object ( "keywords", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_CATEGORIES] = g_param_spec_object ( "categories", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_PERMISSIONS] = g_param_spec_object ( "permissions", NULL, NULL, BZ_TYPE_APP_PERMISSIONS, G_PARAM_READWRITE); props[PROP_IS_FLATHUB] = g_param_spec_boolean ( "is-flathub", NULL, NULL, FALSE, G_PARAM_READWRITE); props[PROP_VERIFICATION_STATUS] = g_param_spec_object ( "verification-status", NULL, NULL, BZ_TYPE_VERIFICATION_STATUS, G_PARAM_READWRITE); props[PROP_DOWNLOAD_STATS] = g_param_spec_object ( "download-stats", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_DOWNLOAD_STATS_PER_COUNTRY] = g_param_spec_object ( "download-stats-per-country", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_RECENT_DOWNLOADS] = g_param_spec_int ( "recent-downloads", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE); props[PROP_TOTAL_DOWNLOADS] = g_param_spec_int ( "total-downloads", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE); props[PROP_FAVORITES_COUNT] = g_param_spec_int ( "favorites-count", NULL, NULL, -1, G_MAXINT, -1, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_entry_init (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); priv->hold = 0; priv->searchable = TRUE; priv->favorites_count = -1; } static void bz_entry_real_serialize (BzSerializable *serializable, GVariantBuilder *builder) { BzEntry *self = BZ_ENTRY (serializable); BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_variant_builder_add (builder, "{sv}", "installed", g_variant_new_boolean (priv->installed)); if (priv->installed_version != NULL) g_variant_builder_add (builder, "{sv}", "installed-version", g_variant_new_string (priv->installed_version)); g_variant_builder_add (builder, "{sv}", "kinds", g_variant_new_uint32 (priv->kinds)); g_variant_builder_add (builder, "{sv}", "searchable", g_variant_new_boolean (priv->searchable)); if (priv->addons != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->addons); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (priv->addons, i); g_variant_builder_add (sub_builder, "s", gtk_string_object_get_string (string)); } g_variant_builder_add (builder, "{sv}", "addons", g_variant_builder_end (sub_builder)); } } if (priv->id != NULL) g_variant_builder_add (builder, "{sv}", "id", g_variant_new_string (priv->id)); if (priv->unique_id != NULL) g_variant_builder_add (builder, "{sv}", "unique-id", g_variant_new_string (priv->unique_id)); if (priv->unique_id_checksum != NULL) g_variant_builder_add (builder, "{sv}", "unique-id-checksum", g_variant_new_string (priv->unique_id_checksum)); if (priv->title != NULL) g_variant_builder_add (builder, "{sv}", "title", g_variant_new_string (priv->title)); if (priv->eol != NULL) g_variant_builder_add (builder, "{sv}", "eol", g_variant_new_string (priv->eol)); if (priv->description != NULL) g_variant_builder_add (builder, "{sv}", "description", g_variant_new_string (priv->description)); if (priv->long_description != NULL) g_variant_builder_add (builder, "{sv}", "long-description", g_variant_new_string (priv->long_description)); if (priv->remote_repo_name != NULL) g_variant_builder_add (builder, "{sv}", "remote-repo-name", g_variant_new_string (priv->remote_repo_name)); if (priv->url != NULL) g_variant_builder_add (builder, "{sv}", "url", g_variant_new_string (priv->url)); if (priv->size > 0) g_variant_builder_add (builder, "{sv}", "size", g_variant_new_uint64 (priv->size)); if (priv->installed_size > 0) g_variant_builder_add (builder, "{sv}", "installed-size", g_variant_new_uint64 (priv->installed_size)); if (priv->icon_paintable != NULL) maybe_save_paintable (priv, "icon-paintable", priv->icon_paintable, builder); if (priv->mini_icon != NULL) { g_autoptr (GVariant) serialized = NULL; serialized = g_icon_serialize (priv->mini_icon); g_variant_builder_add (builder, "{sv}", "mini-icon", serialized); } if (priv->remote_repo_icon != NULL) maybe_save_paintable (priv, "remote-repo-icon", priv->remote_repo_icon, builder); if (priv->search_tokens != NULL) g_variant_builder_add (builder, "{sv}", "search-tokens", g_variant_new_string (priv->search_tokens)); if (priv->metadata_license != NULL) g_variant_builder_add (builder, "{sv}", "metadata-license", g_variant_new_string (priv->metadata_license)); if (priv->project_license != NULL) g_variant_builder_add (builder, "{sv}", "project-license", g_variant_new_string (priv->project_license)); g_variant_builder_add (builder, "{sv}", "is-floss", g_variant_new_boolean (priv->is_floss)); if (priv->project_group != NULL) g_variant_builder_add (builder, "{sv}", "project-group", g_variant_new_string (priv->project_group)); if (priv->developer != NULL) g_variant_builder_add (builder, "{sv}", "developer", g_variant_new_string (priv->developer)); if (priv->developer_id != NULL) g_variant_builder_add (builder, "{sv}", "developer-id", g_variant_new_string (priv->developer_id)); if (priv->screenshot_paintables != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->screenshot_paintables); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); for (guint i = 0; i < n_items; i++) { g_autoptr (GdkPaintable) paintable = NULL; g_autofree char *key = NULL; paintable = g_list_model_get_item (priv->screenshot_paintables, i); key = g_strdup_printf ("screenshot_%d.png", i); maybe_save_paintable (priv, key, paintable, sub_builder); } g_variant_builder_add (builder, "{sv}", "screenshot-paintables", g_variant_builder_end (sub_builder)); } } if (priv->screenshot_captions != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->screenshot_captions); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (priv->screenshot_captions, i); g_variant_builder_add (sub_builder, "s", gtk_string_object_get_string (string)); } g_variant_builder_add (builder, "{sv}", "screenshot-captions", g_variant_builder_end (sub_builder)); } } if (priv->thumbnail_paintable != NULL) maybe_save_paintable (priv, "thumbnail-paintable", priv->thumbnail_paintable, builder); if (priv->share_urls != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->share_urls); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(sss)")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzUrl) url = NULL; const char *name = NULL; const char *url_str = NULL; const char *icon_name = NULL; url = g_list_model_get_item (priv->share_urls, i); name = bz_url_get_name (url); url_str = bz_url_get_url (url); icon_name = bz_url_get_icon_name (url); g_variant_builder_add (sub_builder, "(sss)", name, url_str, icon_name ? icon_name : ""); } g_variant_builder_add (builder, "{sv}", "share-urls", g_variant_builder_end (sub_builder)); } } if (priv->donation_url != NULL) g_variant_builder_add (builder, "{sv}", "donation-url", g_variant_new_string (priv->donation_url)); if (priv->forge_url != NULL) g_variant_builder_add (builder, "{sv}", "forge-url", g_variant_new_string (priv->forge_url)); if (priv->version_history != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->version_history); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(mstmsms)")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzRelease) release = NULL; guint64 timestamp = 0; const char *url = NULL; const char *version = NULL; const char *description = NULL; release = g_list_model_get_item (priv->version_history, i); timestamp = bz_release_get_timestamp (release); url = bz_release_get_url (release); version = bz_release_get_version (release); description = bz_release_get_description (release); g_variant_builder_add ( sub_builder, "(mstmsms)", description, timestamp, url, version); } g_variant_builder_add (builder, "{sv}", "version-history", g_variant_builder_end (sub_builder)); } } if (priv->light_accent_color != NULL) g_variant_builder_add (builder, "{sv}", "light-accent-color", g_variant_new_string (priv->light_accent_color)); if (priv->dark_accent_color != NULL) g_variant_builder_add (builder, "{sv}", "dark-accent-color", g_variant_new_string (priv->dark_accent_color)); g_variant_builder_add (builder, "{sv}", "is-mobile-friendly", g_variant_new_boolean (priv->is_mobile_friendly)); if (priv->required_controls != BZ_CONTROL_NONE) g_variant_builder_add (builder, "{sv}", "required-controls", g_variant_new_uint32 (priv->required_controls)); if (priv->recommended_controls != BZ_CONTROL_NONE) g_variant_builder_add (builder, "{sv}", "recommended-controls", g_variant_new_uint32 (priv->recommended_controls)); if (priv->supported_controls != BZ_CONTROL_NONE) g_variant_builder_add (builder, "{sv}", "supported-controls", g_variant_new_uint32 (priv->supported_controls)); if (priv->min_display_length > 0) g_variant_builder_add (builder, "{sv}", "min-display-length", g_variant_new_int32 (priv->min_display_length)); if (priv->max_display_length > 0) g_variant_builder_add (builder, "{sv}", "max-display-length", g_variant_new_int32 (priv->max_display_length)); if (priv->content_rating != NULL) { const gchar *kind = as_content_rating_get_kind (priv->content_rating); g_autoptr (GVariantBuilder) sub_builder = NULL; g_autofree const gchar **rating_ids = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)")); rating_ids = as_content_rating_get_all_rating_ids (); for (gsize i = 0; rating_ids[i] != NULL; i++) { AsContentRatingValue value = as_content_rating_get_value (priv->content_rating, rating_ids[i]); const gchar *value_str = as_content_rating_value_to_string (value); if (value != AS_CONTENT_RATING_VALUE_UNKNOWN) g_variant_builder_add (sub_builder, "(ss)", rating_ids[i], value_str); } g_variant_builder_add (builder, "{sv}", "content-rating-kind", g_variant_new_string (kind ? kind : "oars-1.1")); g_variant_builder_add (builder, "{sv}", "content-rating-values", g_variant_builder_end (sub_builder)); } if (priv->keywords != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->keywords); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (priv->keywords, i); g_variant_builder_add (sub_builder, "s", gtk_string_object_get_string (string)); } g_variant_builder_add (builder, "{sv}", "keywords", g_variant_builder_end (sub_builder)); } } if (priv->categories != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->categories); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzFlathubCategory) category = NULL; const char *category_name = NULL; category = g_list_model_get_item (priv->categories, i); category_name = bz_flathub_category_get_name (category); if (category_name != NULL) g_variant_builder_add (sub_builder, "s", category_name); } g_variant_builder_add (builder, "{sv}", "categories", g_variant_builder_end (sub_builder)); } } if (priv->verification_status != NULL) { gboolean verified = FALSE; g_autofree char *method = NULL; g_autofree char *website = NULL; g_autofree char *login_name = NULL; g_autofree char *login_provider = NULL; g_autofree char *timestamp = NULL; gboolean login_is_organization = FALSE; g_object_get (priv->verification_status, "verified", &verified, "method", &method, "website", &website, "login-name", &login_name, "login-provider", &login_provider, "timestamp", ×tamp, "login-is-organization", &login_is_organization, NULL); g_variant_builder_add (builder, "{sv}", "verification-verified", g_variant_new_boolean (verified)); if (method != NULL) g_variant_builder_add (builder, "{sv}", "verification-method", g_variant_new_string (method)); if (website != NULL) g_variant_builder_add (builder, "{sv}", "verification-website", g_variant_new_string (website)); if (login_name != NULL) g_variant_builder_add (builder, "{sv}", "verification-login-name", g_variant_new_string (login_name)); if (login_provider != NULL) g_variant_builder_add (builder, "{sv}", "verification-login-provider", g_variant_new_string (login_provider)); if (timestamp != NULL) g_variant_builder_add (builder, "{sv}", "verification-timestamp", g_variant_new_string (timestamp)); g_variant_builder_add (builder, "{sv}", "verification-login-is-organization", g_variant_new_boolean (login_is_organization)); } if (priv->permissions != NULL) { bz_app_permissions_serialize (priv->permissions, builder); } g_variant_builder_add (builder, "{sv}", "is-flathub", g_variant_new_boolean (priv->is_flathub)); if (priv->is_flathub) { if (priv->flathub_prop_queries != NULL) { if (g_hash_table_contains (priv->flathub_prop_queries, GINT_TO_POINTER (PROP_DOWNLOAD_STATS)) && priv->download_stats != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (priv->download_stats); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ddms)")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzDataPoint) point = NULL; double independent = 0.0; double dependent = 0.0; const char *label = NULL; point = g_list_model_get_item (priv->download_stats, i); independent = bz_data_point_get_independent (point); dependent = bz_data_point_get_dependent (point); label = bz_data_point_get_label (point); g_variant_builder_add (sub_builder, "(ddms)", independent, dependent, label); } g_variant_builder_add (builder, "{sv}", "download-stats", g_variant_builder_end (sub_builder)); } } if (g_hash_table_contains (priv->flathub_prop_queries, GINT_TO_POINTER (PROP_RECENT_DOWNLOADS))) g_variant_builder_add (builder, "{sv}", "recent-downloads", g_variant_new_int32 (priv->recent_downloads)); if (g_hash_table_contains (priv->flathub_prop_queries, GINT_TO_POINTER (PROP_FAVORITES_COUNT))) g_variant_builder_add (builder, "{sv}", "favorites-count", g_variant_new_int32 (priv->favorites_count)); } } } static gboolean bz_entry_real_deserialize (BzSerializable *serializable, GVariant *import, GError **error) { BzEntry *self = BZ_ENTRY (serializable); BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_autoptr (GVariantIter) iter = NULL; clear_entry (self); iter = g_variant_iter_new (import); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "installed") == 0) priv->installed = g_variant_get_boolean (value); else if (g_strcmp0 (key, "installed-version") == 0) priv->installed_version = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "kinds") == 0) priv->kinds = g_variant_get_uint32 (value); else if (g_strcmp0 (key, "searchable") == 0) priv->searchable = g_variant_get_boolean (value); else if (g_strcmp0 (key, "addons") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) addon_iter = NULL; store = g_list_store_new (GTK_TYPE_STRING_OBJECT); addon_iter = g_variant_iter_new (value); for (;;) { g_autofree char *unique_id = NULL; g_autoptr (GtkStringObject) string = NULL; if (!g_variant_iter_next (addon_iter, "s", &unique_id)) break; string = gtk_string_object_new (unique_id); g_list_store_append (store, string); } priv->addons = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "id") == 0) priv->id = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "unique-id") == 0) priv->unique_id = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "unique-id-checksum") == 0) priv->unique_id_checksum = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "title") == 0) priv->title = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "eol") == 0) priv->eol = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "description") == 0) priv->description = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "long-description") == 0) priv->long_description = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "remote-repo-name") == 0) priv->remote_repo_name = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "url") == 0) priv->url = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "size") == 0) priv->size = g_variant_get_uint64 (value); else if (g_strcmp0 (key, "installed-size") == 0) priv->installed_size = g_variant_get_uint64 (value); else if (g_strcmp0 (key, "icon-paintable") == 0) priv->icon_paintable = make_async_texture (value); else if (g_strcmp0 (key, "mini-icon") == 0) priv->mini_icon = g_icon_deserialize (value); else if (g_strcmp0 (key, "remote-repo-icon") == 0) priv->remote_repo_icon = make_async_texture (value); else if (g_strcmp0 (key, "search-tokens") == 0) priv->search_tokens = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "metadata-license") == 0) priv->metadata_license = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "project-license") == 0) priv->project_license = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "is-floss") == 0) priv->is_floss = g_variant_get_boolean (value); else if (g_strcmp0 (key, "developer") == 0) priv->developer = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "developer-id") == 0) priv->developer_id = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "screenshot-paintables") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) screenshot_iter = NULL; store = g_list_store_new (BZ_TYPE_ASYNC_TEXTURE); screenshot_iter = g_variant_iter_new (value); for (;;) { g_autofree char *basename = NULL; g_autoptr (GVariant) screenshot = NULL; g_autoptr (GdkPaintable) texture = NULL; if (!g_variant_iter_next (screenshot_iter, "{sv}", &basename, &screenshot)) break; texture = make_async_texture (screenshot); g_list_store_append (store, texture); } priv->screenshot_paintables = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "screenshot-captions") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) caption_iter = NULL; store = g_list_store_new (GTK_TYPE_STRING_OBJECT); caption_iter = g_variant_iter_new (value); for (;;) { g_autofree char *caption = NULL; g_autoptr (GtkStringObject) string = NULL; if (!g_variant_iter_next (caption_iter, "s", &caption)) break; string = gtk_string_object_new (caption); g_list_store_append (store, string); } priv->screenshot_captions = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "thumbnail-paintable") == 0) priv->thumbnail_paintable = make_async_texture (value); else if (g_strcmp0 (key, "share-urls") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) url_iter = NULL; store = g_list_store_new (BZ_TYPE_URL); url_iter = g_variant_iter_new (value); for (;;) { g_autofree char *name = NULL; g_autofree char *url_str = NULL; g_autoptr (BzUrl) url = NULL; g_autofree char *icon_name = NULL; if (!g_variant_iter_next (url_iter, "(sss)", &name, &url_str, &icon_name)) break; url = bz_url_new (); bz_url_set_name (url, name); bz_url_set_url (url, url_str); bz_url_set_icon_name (url, icon_name); g_list_store_append (store, url); } priv->share_urls = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "donation-url") == 0) priv->donation_url = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "forge-url") == 0) priv->forge_url = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "version-history") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) version_iter = NULL; store = g_list_store_new (BZ_TYPE_RELEASE); version_iter = g_variant_iter_new (value); for (;;) { guint64 timestamp = 0; g_autofree char *url = NULL; g_autofree char *description = NULL; g_autofree char *version = NULL; g_autoptr (BzRelease) release = NULL; if (!g_variant_iter_next (version_iter, "(mstmsms)", &description, ×tamp, &url, &version)) break; release = bz_release_new (); bz_release_set_timestamp (release, timestamp); bz_release_set_url (release, url); bz_release_set_version (release, version); bz_release_set_description (release, description); g_list_store_append (store, release); } priv->version_history = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "light-accent-color") == 0) priv->light_accent_color = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "dark-accent-color") == 0) priv->dark_accent_color = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "is-mobile-friendly") == 0) priv->is_mobile_friendly = g_variant_get_boolean (value); else if (g_strcmp0 (key, "required-controls") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) priv->required_controls = g_variant_get_uint32 (value); else if (g_strcmp0 (key, "recommended-controls") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) priv->recommended_controls = g_variant_get_uint32 (value); else if (g_strcmp0 (key, "supported-controls") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) priv->supported_controls = g_variant_get_uint32 (value); else if (g_strcmp0 (key, "min-display-length") == 0) priv->min_display_length = g_variant_get_int32 (value); else if (g_strcmp0 (key, "max-display-length") == 0) priv->max_display_length = g_variant_get_int32 (value); else if (g_strcmp0 (key, "content-rating-kind") == 0) { g_autofree gchar *kind = NULL; kind = g_variant_dup_string (value, NULL); if (priv->content_rating == NULL) priv->content_rating = as_content_rating_new (); as_content_rating_set_kind (priv->content_rating, kind); } else if (g_strcmp0 (key, "content-rating-values") == 0) { g_autoptr (GVariantIter) rating_iter = NULL; if (priv->content_rating == NULL) priv->content_rating = as_content_rating_new (); rating_iter = g_variant_iter_new (value); for (;;) { g_autofree gchar *rating_id = NULL; g_autofree gchar *rating_value_str = NULL; AsContentRatingValue rating_value; if (!g_variant_iter_next (rating_iter, "(ss)", &rating_id, &rating_value_str)) break; rating_value = as_content_rating_value_from_string (rating_value_str); if (rating_value != AS_CONTENT_RATING_VALUE_UNKNOWN) as_content_rating_set_value (priv->content_rating, rating_id, rating_value); } } else if (g_strcmp0 (key, "keywords") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) keywords_iter = NULL; store = g_list_store_new (GTK_TYPE_STRING_OBJECT); keywords_iter = g_variant_iter_new (value); for (;;) { g_autofree char *keyword = NULL; g_autoptr (GtkStringObject) string = NULL; if (!g_variant_iter_next (keywords_iter, "s", &keyword)) break; string = gtk_string_object_new (keyword); g_list_store_append (store, string); } priv->keywords = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "categories") == 0) { g_autoptr (GListStore) store = NULL; g_autoptr (GVariantIter) categories_iter = NULL; store = g_list_store_new (BZ_TYPE_FLATHUB_CATEGORY); categories_iter = g_variant_iter_new (value); for (;;) { g_autofree char *category_name = NULL; g_autoptr (BzFlathubCategory) category = NULL; if (!g_variant_iter_next (categories_iter, "s", &category_name)) break; category = bz_flathub_category_new (); bz_flathub_category_set_name (category, category_name); g_list_store_append (store, category); } priv->categories = G_LIST_MODEL (g_steal_pointer (&store)); } else if (g_strcmp0 (key, "verification-verified") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "verified", g_variant_get_boolean (value), NULL); } else if (g_strcmp0 (key, "verification-method") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "method", g_variant_get_string (value, NULL), NULL); } else if (g_strcmp0 (key, "verification-website") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "website", g_variant_get_string (value, NULL), NULL); } else if (g_strcmp0 (key, "verification-login-name") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "login-name", g_variant_get_string (value, NULL), NULL); } else if (g_strcmp0 (key, "verification-login-provider") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "login-provider", g_variant_get_string (value, NULL), NULL); } else if (g_strcmp0 (key, "verification-timestamp") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "timestamp", g_variant_get_string (value, NULL), NULL); } else if (g_strcmp0 (key, "verification-login-is-organization") == 0) { if (priv->verification_status == NULL) priv->verification_status = bz_verification_status_new (); g_object_set (priv->verification_status, "login-is-organization", g_variant_get_boolean (value), NULL); } else if (g_strcmp0 (key, "is-flathub") == 0) priv->is_flathub = g_variant_get_boolean (value); else if (g_str_has_prefix (key, "permissions-")) { continue; } } if (priv->permissions == NULL) priv->permissions = bz_app_permissions_new (); if (!bz_app_permissions_deserialize (priv->permissions, import, error)) { g_warning ("Failed to deserialize app permissions"); } return TRUE; } void bz_entry_hold (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_if_fail (BZ_IS_ENTRY (self)); priv = bz_entry_get_instance_private (self); if (++priv->hold == 1) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HOLDING]); } void bz_entry_release (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_if_fail (BZ_IS_ENTRY (self)); priv = bz_entry_get_instance_private (self); if (--priv->hold == 0) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HOLDING]); } gboolean bz_entry_is_holding (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); return priv->hold > 0; } gboolean bz_entry_is_installed (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); return priv->installed; } void bz_entry_set_installed (BzEntry *self, gboolean installed) { BzEntryPrivate *priv = NULL; g_return_if_fail (BZ_IS_ENTRY (self)); priv = bz_entry_get_instance_private (self); priv->installed = installed; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED]); } const char * bz_entry_get_installed_version (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->installed_version; } void bz_entry_set_installed_version (BzEntry *self, const char *version) { BzEntryPrivate *priv = NULL; g_return_if_fail (BZ_IS_ENTRY (self)); priv = bz_entry_get_instance_private (self); g_clear_pointer (&priv->installed_version, g_free); priv->installed_version = g_strdup (version); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INSTALLED_VERSION]); } gboolean bz_entry_is_of_kinds (BzEntry *self, guint kinds) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); return (priv->kinds & kinds) == kinds; } gboolean bz_entry_is_searchable (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), TRUE); priv = bz_entry_get_instance_private (self); return priv->searchable; } void bz_entry_append_addon (BzEntry *self, const char *id) { BzEntryPrivate *priv = NULL; g_autoptr (GtkStringObject) string = NULL; g_return_if_fail (BZ_IS_ENTRY (self)); g_return_if_fail (id != NULL); priv = bz_entry_get_instance_private (self); string = gtk_string_object_new (id); if (priv->addons == NULL) { priv->addons = (GListModel *) g_list_store_new (GTK_TYPE_STRING_OBJECT); g_list_store_append (G_LIST_STORE (priv->addons), string); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ADDONS]); } else g_list_store_append (G_LIST_STORE (priv->addons), string); } GListModel * bz_entry_get_addons (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->addons; } const char * bz_entry_get_id (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->id; } const char * bz_entry_get_unique_id (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->unique_id; } const char * bz_entry_get_unique_id_checksum (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->unique_id_checksum; } const char * bz_entry_get_title (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->title; } const char * bz_entry_get_developer (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->developer; } gboolean bz_entry_is_verified (BzEntry *self) { BzEntryPrivate *priv = NULL; gboolean verified = FALSE; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); if (priv->verification_status != NULL) g_object_get (priv->verification_status, "verified", &verified, NULL); return verified; } const char * bz_entry_get_eol (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), 0); priv = bz_entry_get_instance_private (self); return priv->eol; } const char * bz_entry_get_description (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->description; } const char * bz_entry_get_long_description (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->long_description; } const char * bz_entry_get_remote_repo_name (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->remote_repo_name; } guint64 bz_entry_get_size (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), 0); priv = bz_entry_get_instance_private (self); return priv->size; } guint64 bz_entry_get_installed_size (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), 0); priv = bz_entry_get_instance_private (self); return priv->installed_size; } GdkPaintable * bz_entry_get_icon_paintable (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->icon_paintable; } GListModel * bz_entry_get_screenshot_paintables (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->screenshot_paintables; } GIcon * bz_entry_get_mini_icon (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->mini_icon; } const char * bz_entry_get_search_tokens (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->search_tokens; } GListModel * bz_entry_get_share_urls (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->share_urls; } const char * bz_entry_get_url (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->url; } const char * bz_entry_get_donation_url (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->donation_url; } const char * bz_entry_get_forge_url (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->forge_url; } BzRepository * bz_entry_get_repository (BzEntry *self, GListModel *repos) { BzEntryPrivate *priv = NULL; guint n_repos = 0; g_auto (GStrv) parts = NULL; const char *scope = NULL; const char *repo_name = NULL; gboolean is_user = FALSE; priv = bz_entry_get_instance_private (self); if (priv->unique_id == NULL) return NULL; parts = g_strsplit (priv->unique_id, "::", -1); if (g_strv_length (parts) < 3) return NULL; scope = parts[0]; repo_name = parts[1]; is_user = g_strcmp0 (scope, "FLATPAK-USER") == 0; n_repos = g_list_model_get_n_items (repos); for (guint i = 0; i < n_repos; i++) { g_autoptr (BzRepository) repo = g_list_model_get_item (repos, i); const char *name = bz_repository_get_name (repo); gboolean repo_is_user = bz_repository_get_is_user (repo); if (repo_is_user == is_user && g_strcmp0 (name, repo_name) == 0) return g_object_ref (repo); } return NULL; } gboolean bz_entry_get_is_foss (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); return priv->is_floss; } const char * bz_entry_get_light_accent_color (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->light_accent_color; } const char * bz_entry_get_dark_accent_color (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->dark_accent_color; } gboolean bz_entry_get_is_mobile_friendly (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); return priv->is_mobile_friendly; } guint bz_entry_get_required_controls (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), BZ_CONTROL_NONE); return priv->required_controls; } guint bz_entry_get_recommended_controls (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), BZ_CONTROL_NONE); return priv->recommended_controls; } guint bz_entry_get_supported_controls (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), BZ_CONTROL_NONE); return priv->supported_controls; } gboolean bz_entry_has_control (BzEntry *self, BzControlType control, BzRelationType relation) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); switch (relation) { case BZ_RELATION_REQUIRES: return (priv->required_controls & control) != 0; case BZ_RELATION_RECOMMENDS: return (priv->recommended_controls & control) != 0; case BZ_RELATION_SUPPORTS: return (priv->supported_controls & control) != 0; default: return FALSE; } } gint bz_entry_get_min_display_length (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), 0); return priv->min_display_length; } gint bz_entry_get_max_display_length (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), 0); return priv->max_display_length; } gboolean bz_entry_supports_form_factor (BzEntry *self, guint available_controls, gint display_length) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); if (priv->required_controls != BZ_CONTROL_NONE) { if ((priv->required_controls & available_controls) != priv->required_controls) return FALSE; } if (priv->min_display_length > 0 && display_length < priv->min_display_length) return FALSE; if (priv->max_display_length > 0 && display_length > priv->max_display_length) return FALSE; return TRUE; } AsContentRating * bz_entry_get_content_rating (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); return priv->content_rating; } GListModel * bz_entry_get_categories (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), NULL); priv = bz_entry_get_instance_private (self); return priv->categories; } gboolean bz_entry_get_is_flathub (BzEntry *self) { BzEntryPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); return priv->is_flathub; } DexFuture * bz_entry_load_mini_icon (BzEntry *self) { BzEntryPrivate *priv = NULL; dex_return_error_if_fail (BZ_IS_ENTRY (self)); priv = bz_entry_get_instance_private (self); if (priv->mini_icon == NULL && priv->mini_icon_future == NULL && BZ_IS_ASYNC_TEXTURE (priv->icon_paintable)) { dex_clear (&priv->mini_icon_future); priv->mini_icon_future = dex_future_then ( bz_async_texture_dup_future (BZ_ASYNC_TEXTURE (priv->icon_paintable)), (DexFutureCallback) icon_paintable_future_then, bz_track_weak (self), bz_weak_release); return dex_ref (priv->mini_icon_future); } else return dex_future_new_true (); } GIcon * bz_load_mini_icon_sync (const char *unique_id_checksum, const char *path) { return load_mini_icon_sync (unique_id_checksum, path); } gint bz_entry_calc_usefulness (BzEntry *self) { BzEntryPrivate *priv = NULL; gint score = 0; g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); priv = bz_entry_get_instance_private (self); score += priv->is_flathub ? 1000 : 0; score += priv->title != NULL ? 5 : 0; score += priv->description != NULL ? 1 : 0; score += priv->long_description != NULL ? 5 : 0; score += priv->url != NULL ? 1 : 0; score += priv->size > 0 ? 1 : 0; score += priv->icon_paintable != NULL ? 15 : 0; score += priv->remote_repo_icon != NULL ? 1 : 0; score += priv->metadata_license != NULL ? 1 : 0; score += priv->project_license != NULL ? 1 : 0; score += priv->project_group != NULL ? 1 : 0; score += priv->developer != NULL ? 1 : 0; score += priv->developer_id != NULL ? 1 : 0; score += priv->screenshot_paintables != NULL ? 5 : 0; score += priv->share_urls != NULL ? 5 : 0; score -= priv->eol != NULL ? 500 : 0; return score; } void bz_entry_serialize (BzEntry *self, GVariantBuilder *builder) { g_return_if_fail (BZ_IS_ENTRY (self)); g_return_if_fail (builder != NULL); return bz_entry_real_serialize (BZ_SERIALIZABLE (self), builder); } gboolean bz_entry_deserialize (BzEntry *self, GVariant *import, GError **error) { g_return_val_if_fail (BZ_IS_ENTRY (self), FALSE); g_return_val_if_fail (import != NULL, FALSE); return bz_entry_real_deserialize (BZ_SERIALIZABLE (self), import, error); } static void query_flathub (BzEntry *self, int prop) { BzEntryPrivate *priv = NULL; g_autoptr (QueryFlathubData) data = NULL; g_autoptr (DexFuture) future = NULL; gboolean is_download_stat = FALSE; priv = bz_entry_get_instance_private (self); is_download_stat = (prop == PROP_DOWNLOAD_STATS || prop == PROP_DOWNLOAD_STATS_PER_COUNTRY || prop == PROP_TOTAL_DOWNLOADS); if (!is_download_stat && !priv->is_flathub) return; if (priv->id == NULL) return; if (priv->flathub_prop_queries == NULL) priv->flathub_prop_queries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, dex_unref); else if (g_hash_table_contains (priv->flathub_prop_queries, GINT_TO_POINTER (prop))) return; data = query_flathub_data_new (); g_weak_ref_init (&data->self, self); data->prop = prop; data->id = g_strdup (priv->id); data->developer = g_strdup (priv->developer); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) query_flathub_fiber, query_flathub_data_ref (data), query_flathub_data_unref); future = dex_future_then ( future, (DexFutureCallback) query_flathub_then, query_flathub_data_ref (data), query_flathub_data_unref); g_hash_table_replace ( priv->flathub_prop_queries, GINT_TO_POINTER (prop), g_steal_pointer (&future)); } static gint compare_dates (BzDataPoint *a, BzDataPoint *b) { double date_a = bz_data_point_get_independent (a); double date_b = bz_data_point_get_independent (b); return (date_a > date_b) - (date_a < date_b); } static DexFuture * query_flathub_fiber (QueryFlathubData *data) { int prop = data->prop; char *id = data->id; char *developer = data->developer; g_autoptr (GError) local_error = NULL; g_autofree char *request = NULL; g_autoptr (JsonNode) node = NULL; switch (prop) { case PROP_DOWNLOAD_STATS: case PROP_DOWNLOAD_STATS_PER_COUNTRY: case PROP_TOTAL_DOWNLOADS: request = g_strdup_printf ("/stats/%s?all=false&days=175", id); break; case PROP_DEVELOPER_APPS: request = g_strdup_printf ("/collection/developer/%s", developer); break; case PROP_FAVORITES_COUNT: request = g_strdup_printf ("/favorites/%s/count", id); break; default: g_assert_not_reached (); return NULL; } node = dex_await_boxed (bz_query_flathub_v2_json (request), &local_error); if (node == NULL) { if (!g_error_matches (local_error, DEX_ERROR, DEX_ERROR_FIBER_CANCELLED)) g_warning ("Could not retrieve property %s for %s from flathub: %s", props[prop]->name, id, local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } switch (prop) { case PROP_DOWNLOAD_STATS: { JsonObject *per_day = NULL; g_autoptr (GListStore) store = NULL; if (!JSON_NODE_HOLDS_OBJECT (node)) { g_debug ("No data for property %s for %s from flathub", props[prop]->name, id); return dex_future_new_for_error ( g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unexpected JSON response format")); } per_day = json_object_get_object_member ( json_node_get_object (node), "installs_per_day"); store = g_list_store_new (BZ_TYPE_DATA_POINT); json_object_foreach_member ( per_day, (JsonObjectForeach) download_stats_per_day_foreach, store); g_list_store_sort (store, (GCompareDataFunc) compare_dates, NULL); return dex_future_new_for_object (store); } break; case PROP_DOWNLOAD_STATS_PER_COUNTRY: { JsonObject *per_country = NULL; g_autoptr (GListStore) store = NULL; per_country = json_object_get_object_member ( json_node_get_object (node), "installs_per_country"); store = g_list_store_new (BZ_TYPE_COUNTRY_DATA_POINT); json_object_foreach_member ( per_country, (JsonObjectForeach) download_stats_per_country_foreach, store); return dex_future_new_for_object (store); } break; case PROP_TOTAL_DOWNLOADS: { int total_downloads = 0; if (json_object_has_member (json_node_get_object (node), "installs_total")) total_downloads = json_object_get_int_member (json_node_get_object (node), "installs_total"); return dex_future_new_for_int (total_downloads); } break; case PROP_DEVELOPER_APPS: { JsonObject *response_obj = NULL; JsonArray *apps_array = NULL; g_autoptr (GtkStringList) app_ids = NULL; response_obj = json_node_get_object (node); apps_array = json_object_get_array_member (response_obj, "hits"); app_ids = gtk_string_list_new (NULL); for (guint i = 0; i < json_array_get_length (apps_array); i++) { JsonObject *app_obj = json_array_get_object_element (apps_array, i); const char *app_id = json_object_get_string_member (app_obj, "app_id"); if (app_id != NULL) gtk_string_list_append (app_ids, app_id); } return dex_future_new_for_object (app_ids); } break; case PROP_FAVORITES_COUNT: { int favorites_count = 0; if (json_object_has_member (json_node_get_object (node), "favorites_count")) favorites_count = json_object_get_int_member (json_node_get_object (node), "favorites_count"); return dex_future_new_for_int (favorites_count); } break; default: g_assert_not_reached (); return NULL; } } static DexFuture * query_flathub_then (DexFuture *future, QueryFlathubData *data) { g_autoptr (BzEntry) self = NULL; int prop = data->prop; const GValue *value = NULL; self = g_weak_ref_get (&data->self); if (self == NULL) return NULL; value = dex_future_get_value (future, NULL); g_object_set_property (G_OBJECT (self), props[prop]->name, value); return NULL; } static void download_stats_per_day_foreach (JsonObject *object, const gchar *member_name, JsonNode *member_node, GListStore *store) { double independent = 0; double dependent = 0; g_autoptr (BzDataPoint) point = NULL; g_autoptr (GDateTime) date = NULL; g_autofree char *formatted_label = NULL; g_autofree char *iso_with_tz = NULL; dependent = json_node_get_int (member_node); iso_with_tz = g_strdup_printf ("%sT00:00:00Z", member_name); date = g_date_time_new_from_iso8601 (iso_with_tz, NULL); formatted_label = g_date_time_format (date, "%-d %b"); independent = (double) g_date_time_to_unix (date); point = g_object_new ( BZ_TYPE_DATA_POINT, "independent", independent, "dependent", dependent, "label", formatted_label, NULL); g_list_store_append (store, point); } static void download_stats_per_country_foreach (JsonObject *object, const gchar *member_name, JsonNode *member_node, GListStore *store) { guint downloads = 0; g_autoptr (BzCountryDataPoint) point = NULL; downloads = json_node_get_int (member_node); point = g_object_new ( BZ_TYPE_COUNTRY_DATA_POINT, "country-code", member_name, "downloads", downloads, NULL); g_list_store_append (store, point); } static gboolean maybe_save_paintable (BzEntryPrivate *priv, const char *key, GdkPaintable *paintable, GVariantBuilder *builder) { g_autoptr (GError) local_error = NULL; const char *source_uri = NULL; const char *cache_into_path = NULL; g_autoptr (GdkTexture) texture = NULL; g_autoptr (GFile) save_file = NULL; gboolean result = FALSE; if (!BZ_IS_ASYNC_TEXTURE (paintable)) { g_warning ("Paintable must be of type BzAsyncTexture to be serialized!"); return FALSE; } source_uri = bz_async_texture_get_source_uri (BZ_ASYNC_TEXTURE (paintable)); cache_into_path = bz_async_texture_get_cache_into_path (BZ_ASYNC_TEXTURE (paintable)); if (cache_into_path == NULL) goto done; if (bz_async_texture_get_loaded (BZ_ASYNC_TEXTURE (paintable))) texture = bz_async_texture_dup_texture (BZ_ASYNC_TEXTURE (paintable)); else goto done; save_file = g_file_new_for_path (cache_into_path); if (!g_file_query_exists (save_file, NULL)) { g_autoptr (GFile) parent_file = NULL; g_autoptr (GBytes) png_bytes = NULL; g_autoptr (GFileOutputStream) output = NULL; gssize bytes_written = 0; parent_file = g_file_get_parent (save_file); result = g_file_make_directory_with_parents ( parent_file, NULL, &local_error); if (!result) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_pointer (&local_error, g_error_free); else { g_warning ("Couldn't serialize texture to %s: %s\n", cache_into_path, local_error->message); goto done; } } png_bytes = gdk_texture_save_to_png_bytes (texture); if (png_bytes == NULL) goto done; output = g_file_replace ( save_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); if (output == NULL) { g_warning ("Couldn't serialize texture to %s: %s\n", cache_into_path, local_error->message); goto done; } bytes_written = g_output_stream_write_bytes ( G_OUTPUT_STREAM (output), png_bytes, NULL, &local_error); if (bytes_written < 0) { g_warning ("Couldn't serialize texture to %s: %s\n", cache_into_path, local_error->message); goto done; } result = g_output_stream_close (G_OUTPUT_STREAM (output), NULL, &local_error); if (!result) { g_warning ("Couldn't serialize texture to %s: %s\n", cache_into_path, local_error->message); goto done; } } done: g_variant_builder_add (builder, "{sv}", key, g_variant_new ("(sms)", source_uri, cache_into_path)); return TRUE; } static GdkPaintable * make_async_texture (GVariant *parse) { g_autofree char *source = NULL; g_autofree char *cache_into = NULL; g_autoptr (GFile) source_file = NULL; g_autoptr (GFile) cache_into_file = NULL; g_autoptr (BzAsyncTexture) texture = NULL; g_variant_get (parse, "(sms)", &source, &cache_into); source_file = g_file_new_for_uri (source); if (cache_into != NULL) cache_into_file = g_file_new_for_path (cache_into); texture = bz_async_texture_new_lazy (source_file, cache_into_file); return GDK_PAINTABLE (g_steal_pointer (&texture)); } static DexFuture * icon_paintable_future_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzEntry) self = NULL; BzEntryPrivate *priv = NULL; const char *icon_path = NULL; g_autoptr (LoadMiniIconData) data = NULL; bz_weak_get_or_return_reject (self, wr); priv = bz_entry_get_instance_private (self); /* ? */ if (!BZ_IS_ASYNC_TEXTURE (priv->icon_paintable)) return NULL; icon_path = bz_async_texture_get_cache_into_path (BZ_ASYNC_TEXTURE (priv->icon_paintable)); if (icon_path == NULL) return NULL; data = load_mini_icon_data_new (); data->self = g_object_ref (self); data->path = g_strdup (icon_path); return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) load_mini_icon_fiber, load_mini_icon_data_ref (data), load_mini_icon_data_unref); } static DexFuture * load_mini_icon_fiber (LoadMiniIconData *data) { BzEntry *self = data->self; char *path = data->path; data->result = load_mini_icon_sync ( bz_entry_get_unique_id_checksum (BZ_ENTRY (self)), path); return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) load_mini_icon_notify, load_mini_icon_data_ref (data), load_mini_icon_data_unref); } static GIcon * load_mini_icon_sync (const char *unique_id_checksum, const char *path) { g_autofree char *main_cache = NULL; g_autoptr (GString) mini_icon_basename = NULL; g_autofree char *mini_icon_path = NULL; g_autoptr (GBytes) bytes = NULL; cairo_surface_t *surface_in = NULL; int width = 0; int height = 0; cairo_surface_t *surface_out = NULL; cairo_t *cairo = NULL; g_autoptr (GFile) parent_file = NULL; g_autoptr (GFile) mini_icon_file = NULL; g_autoptr (GIcon) mini_icon = NULL; main_cache = bz_dup_module_dir (); mini_icon_basename = g_string_new (unique_id_checksum); g_string_append (mini_icon_basename, "-24x24.png"); mini_icon_path = g_build_filename (main_cache, mini_icon_basename->str, NULL); if (g_file_test (mini_icon_path, G_FILE_TEST_EXISTS)) /* Assume the icon left behind by last writer */ goto done; surface_in = cairo_image_surface_create_from_png (path); width = cairo_image_surface_get_width (surface_in); height = cairo_image_surface_get_height (surface_in); /* 24x24 for the gnome-shell search provider */ surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 24, 24); cairo = cairo_create (surface_out); cairo_scale (cairo, 24.0 / (double) width, 24.0 / (double) height); cairo_set_source_surface (cairo, surface_in, 0, 0); cairo_paint (cairo); cairo_restore (cairo); parent_file = g_file_new_for_path (main_cache); g_file_make_directory_with_parents (parent_file, NULL, NULL); cairo_surface_flush (surface_out); cairo_surface_write_to_png (surface_out, mini_icon_path); cairo_destroy (cairo); cairo_surface_destroy (surface_in); cairo_surface_destroy (surface_out); done: mini_icon_file = g_file_new_for_path (mini_icon_path); mini_icon = g_file_icon_new (mini_icon_file); return g_steal_pointer (&mini_icon); } static DexFuture * load_mini_icon_notify (LoadMiniIconData *data) { BzEntry *self = data->self; GIcon *result = data->result; g_object_set ( self, "mini-icon", result, NULL); return dex_future_new_true (); } static void clear_entry (BzEntry *self) { BzEntryPrivate *priv = bz_entry_get_instance_private (self); dex_clear (&priv->mini_icon_future); g_clear_pointer (&priv->flathub_prop_queries, g_hash_table_unref); g_clear_object (&priv->addons); g_clear_pointer (&priv->id, g_free); g_clear_pointer (&priv->unique_id, g_free); g_clear_pointer (&priv->unique_id_checksum, g_free); g_clear_pointer (&priv->installed_version, g_free); g_clear_pointer (&priv->title, g_free); g_clear_pointer (&priv->eol, g_free); g_clear_pointer (&priv->description, g_free); g_clear_pointer (&priv->long_description, g_free); g_clear_pointer (&priv->remote_repo_name, g_free); g_clear_pointer (&priv->url, g_free); g_clear_object (&priv->icon_paintable); g_clear_object (&priv->mini_icon); g_clear_object (&priv->remote_repo_icon); g_clear_pointer (&priv->search_tokens, g_free); g_clear_pointer (&priv->metadata_license, g_free); g_clear_pointer (&priv->project_license, g_free); g_clear_pointer (&priv->project_group, g_free); g_clear_pointer (&priv->developer, g_free); g_clear_pointer (&priv->developer_id, g_free); g_clear_object (&priv->developer_apps); g_clear_object (&priv->screenshot_paintables); g_clear_object (&priv->screenshot_captions); g_clear_object (&priv->thumbnail_paintable); g_clear_object (&priv->share_urls); g_clear_pointer (&priv->donation_url, g_free); g_clear_pointer (&priv->forge_url, g_free); g_clear_object (&priv->reviews); g_clear_pointer (&priv->ratings_summary, g_free); g_clear_object (&priv->version_history); g_clear_pointer (&priv->light_accent_color, g_free); g_clear_pointer (&priv->dark_accent_color, g_free); g_clear_object (&priv->verification_status); g_clear_object (&priv->download_stats); g_clear_object (&priv->download_stats_per_country); g_clear_object (&priv->content_rating); g_clear_object (&priv->keywords); g_clear_object (&priv->categories); g_clear_object (&priv->permissions); } kolunmi-bazaar-7b9c8e1/src/bz-entry.h000066400000000000000000000124231514314607700175760ustar00rootroot00000000000000/* bz-entry.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include #include "bz-repository.h" G_BEGIN_DECLS typedef enum { BZ_ENTRY_KIND_APPLICATION = 1 << 0, BZ_ENTRY_KIND_RUNTIME = 1 << 1, BZ_ENTRY_KIND_ADDON = 1 << 2, } BzEntryKind; GType bz_entry_kind_get_type (void); #define BZ_TYPE_ENTRY_KIND (bz_entry_kind_get_type ()) typedef enum { BZ_CONTROL_NONE = 0, BZ_CONTROL_POINTING = 1 << 0, BZ_CONTROL_KEYBOARD = 1 << 1, BZ_CONTROL_CONSOLE = 1 << 2, BZ_CONTROL_TABLET = 1 << 3, BZ_CONTROL_TOUCH = 1 << 4, BZ_CONTROL_GAMEPAD = 1 << 5, BZ_CONTROL_TV_REMOTE = 1 << 6, BZ_CONTROL_VOICE = 1 << 7, BZ_CONTROL_VISION = 1 << 8, } BzControlType; GType bz_control_type_get_type (void); #define BZ_TYPE_CONTROL_TYPE (bz_control_type_get_type ()) typedef enum { BZ_RELATION_REQUIRES, BZ_RELATION_RECOMMENDS, BZ_RELATION_SUPPORTS, } BzRelationType; GType bz_relation_type_get_type (void); #define BZ_TYPE_RELATION_TYPE (bz_relation_type_get_type ()) #define BZ_TYPE_ENTRY (bz_entry_get_type ()) G_DECLARE_DERIVABLE_TYPE (BzEntry, bz_entry, BZ, ENTRY, GObject) struct _BzEntryClass { GObjectClass parent_class; }; void bz_entry_hold (BzEntry *self); void bz_entry_release (BzEntry *self); gboolean bz_entry_is_holding (BzEntry *self); gboolean bz_entry_is_installed (BzEntry *self); const char * bz_entry_get_installed_version (BzEntry *self); void bz_entry_set_installed_version (BzEntry *self, const char *version); void bz_entry_set_installed (BzEntry *self, gboolean installed); gboolean bz_entry_is_searchable (BzEntry *self); gboolean bz_entry_is_of_kinds (BzEntry *self, guint kinds); void bz_entry_append_addon (BzEntry *self, const char *id); GListModel * bz_entry_get_addons (BzEntry *self); const char * bz_entry_get_id (BzEntry *self); const char * bz_entry_get_unique_id (BzEntry *self); const char * bz_entry_get_unique_id_checksum (BzEntry *self); const char * bz_entry_get_title (BzEntry *self); const char * bz_entry_get_developer (BzEntry *self); GList * bz_entry_get_developer_apps (BzEntry *self); const char * bz_entry_get_eol (BzEntry *self); const char * bz_entry_get_description (BzEntry *self); gboolean bz_entry_is_verified (BzEntry *self); const char * bz_entry_get_long_description (BzEntry *self); const char * bz_entry_get_remote_repo_name (BzEntry *self); guint64 bz_entry_get_size (BzEntry *self); guint64 bz_entry_get_installed_size (BzEntry *self); GdkPaintable * bz_entry_get_icon_paintable (BzEntry *self); GListModel * bz_entry_get_screenshot_paintables (BzEntry *self); GIcon * bz_entry_get_mini_icon (BzEntry *self); const char * bz_entry_get_search_tokens (BzEntry *self); GListModel * bz_entry_get_share_urls (BzEntry *self); const char * bz_entry_get_url (BzEntry *self); const char * bz_entry_get_donation_url (BzEntry *self); const char * bz_entry_get_forge_url (BzEntry *self); BzRepository * bz_entry_get_repository (BzEntry *self, GListModel *repos); gboolean bz_entry_get_is_foss (BzEntry *self); const char * bz_entry_get_light_accent_color (BzEntry *self); const char * bz_entry_get_dark_accent_color (BzEntry *self); gboolean bz_entry_get_is_flathub (BzEntry *self); gboolean bz_entry_get_is_mobile_friendly (BzEntry *self); guint bz_entry_get_required_controls (BzEntry *self); guint bz_entry_get_recommended_controls (BzEntry *self); guint bz_entry_get_supported_controls (BzEntry *self); gboolean bz_entry_has_control (BzEntry *self, BzControlType control, BzRelationType relation); gint bz_entry_get_min_display_length (BzEntry *self); gint bz_entry_get_max_display_length (BzEntry *self); gboolean bz_entry_supports_form_factor (BzEntry *self, guint available_controls, gint display_length); gint bz_entry_get_age_rating (BzEntry *self); AsContentRating * bz_entry_get_content_rating (BzEntry *self); GListModel * bz_entry_get_categories (BzEntry *self); DexFuture * bz_entry_load_mini_icon (BzEntry *self); gint bz_entry_calc_usefulness (BzEntry *self); void bz_entry_serialize (BzEntry *self, GVariantBuilder *builder); gboolean bz_entry_deserialize (BzEntry *self, GVariant *import, GError **error); GIcon * bz_load_mini_icon_sync (const char *unique_id_checksum, const char *path); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-env.c000066400000000000000000000042141514314607700172170ustar00rootroot00000000000000/* bz-env.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-env.h" gsize bz_get_dex_stack_size (void) { static guint64 stack_size = 0; if (g_once_init_enter (&stack_size)) { const char *envvar = NULL; guint64 value = 0; /* Ensure we have enough space for gtk/glycin Some routines try to optimize by putting stuff on the stack, see https://gitlab.gnome.org/GNOME/libdex/-/issues/27#note_2582332 2025-10-21 22:47:02 eva */ value = MAX (8388608, dex_get_min_stack_size ()); envvar = g_getenv ("BAZAAR_DEX_STACK_SIZE"); if (envvar != NULL) { g_autoptr (GError) local_error = NULL; g_autoptr (GVariant) variant = NULL; variant = g_variant_parse ( G_VARIANT_TYPE_UINT64, envvar, NULL, NULL, &local_error); if (variant != NULL) { guint64 parse_result = 0; parse_result = g_variant_get_uint64 (variant); if (parse_result < dex_get_min_stack_size ()) g_warning ("BAZAAR_DEX_STACK_SIZE must be greater than %zu on this system", dex_get_min_stack_size ()); else value = parse_result; } else g_warning ("BAZAAR_DEX_STACK_SIZE is invalid: %s", local_error->message); } g_once_init_leave (&stack_size, value); } return stack_size; } kolunmi-bazaar-7b9c8e1/src/bz-env.h000066400000000000000000000015171514314607700172270ustar00rootroot00000000000000/* bz-env.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS gsize bz_get_dex_stack_size (void); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-error.c000066400000000000000000000105661514314607700175670ustar00rootroot00000000000000/* bz-error.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include "bz-error.h" static void show_alert (GtkWidget *widget, const char *title, const char *text, gboolean markup); static void error_alert_response (AdwAlertDialog *alert, gchar *response, GtkWidget *widget); static void await_alert_response (AdwAlertDialog *alert, gchar *response, DexPromise *promise); static void unref_dex_closure (gpointer data, GClosure *closure); void bz_show_alert_for_widget (GtkWidget *widget, const char *title, const char *text, gboolean markup) { g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (title != NULL); g_return_if_fail (text != NULL); show_alert (widget, title, text, markup); } void bz_show_error_for_widget (GtkWidget *widget, const char *text) { g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (text != NULL); show_alert (widget, _ ("An Error Occurred"), text, FALSE); } static void show_alert (GtkWidget *widget, const char *title, const char *text, gboolean markup) { AdwDialog *alert = NULL; alert = adw_alert_dialog_new (NULL, NULL); adw_alert_dialog_set_prefer_wide_layout (ADW_ALERT_DIALOG (alert), TRUE); adw_alert_dialog_set_heading ( ADW_ALERT_DIALOG (alert), title); adw_alert_dialog_set_body ( ADW_ALERT_DIALOG (alert), text); adw_alert_dialog_set_body_use_markup ( ADW_ALERT_DIALOG (alert), markup); adw_alert_dialog_add_responses ( ADW_ALERT_DIALOG (alert), "close", _ ("Close"), "copy", _ ("Copy and Close"), NULL); adw_alert_dialog_set_response_appearance ( ADW_ALERT_DIALOG (alert), "copy", ADW_RESPONSE_SUGGESTED); adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (alert), "close"); adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (alert), "close"); g_signal_connect (alert, "response", G_CALLBACK (error_alert_response), widget); adw_dialog_present (alert, GTK_WIDGET (widget)); } DexFuture * bz_make_alert_dialog_future (AdwAlertDialog *dialog) { g_autoptr (DexPromise) promise = NULL; dex_return_error_if_fail (ADW_IS_ALERT_DIALOG (dialog)); promise = dex_promise_new (); g_signal_connect_data ( dialog, "response", G_CALLBACK (await_alert_response), dex_ref (promise), unref_dex_closure, G_CONNECT_DEFAULT); return DEX_FUTURE (g_steal_pointer (&promise)); } static void error_alert_response (AdwAlertDialog *alert, gchar *response, GtkWidget *widget) { if (g_strcmp0 (response, "copy") == 0) { const char *body = NULL; GdkClipboard *clipboard; body = adw_alert_dialog_get_body (alert); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, body); } } static void await_alert_response (AdwAlertDialog *alert, gchar *response, DexPromise *promise) { dex_promise_resolve_string (promise, g_strdup (response)); } static void unref_dex_closure (gpointer data, GClosure *closure) { DexPromise *promise = data; if (dex_future_is_pending (DEX_FUTURE (promise))) dex_promise_reject ( promise, g_error_new ( DEX_ERROR, DEX_ERROR_UNKNOWN, "The signal was disconnected")); dex_unref (promise); } kolunmi-bazaar-7b9c8e1/src/bz-error.h000066400000000000000000000022431514314607700175650ustar00rootroot00000000000000/* bz-error.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS void bz_show_alert_for_widget (GtkWidget *widget, const char *title, const char *text, gboolean markup); void bz_show_error_for_widget (GtkWidget *widget, const char *text); DexFuture * bz_make_alert_dialog_future (AdwAlertDialog *dialog); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-fading-clamp.c000066400000000000000000000265751514314607700207670ustar00rootroot00000000000000/* bz-fading-clamp.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-fading-clamp.h" #define FADE_HEIGHT 75 #define CLAMP_LEEWAY 100 struct _BzFadingClamp { GtkWidget parent_instance; GtkWidget *child; int max_height; int min_max_height; AdwAnimation *animation; int current_height; int allocated_width; gboolean animating_max_height; gboolean will_change; }; enum { PROP_0, PROP_CHILD, PROP_MAX_HEIGHT, PROP_MIN_MAX_HEIGHT, PROP_WILL_CHANGE, N_PROPS }; static GParamSpec *properties[N_PROPS]; G_DEFINE_TYPE (BzFadingClamp, bz_fading_clamp, GTK_TYPE_WIDGET) static void on_animation_value_changed (double value, BzFadingClamp *self) { self->current_height = (int) value; gtk_widget_queue_resize (GTK_WIDGET (self)); } static void on_animation_done (AdwAnimation *animation, BzFadingClamp *self) { self->animating_max_height = FALSE; } static void bz_fading_clamp_update_will_change (BzFadingClamp *self) { gboolean new_value = FALSE; int natural_height; int width; if (self->child) { if (self->allocated_width > 0) width = self->allocated_width; else gtk_widget_measure (self->child, GTK_ORIENTATION_HORIZONTAL, -1, NULL, &width, NULL, NULL); gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, width, NULL, &natural_height, NULL, NULL); new_value = natural_height > self->min_max_height + CLAMP_LEEWAY; } if (self->will_change != new_value) { self->will_change = new_value; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WILL_CHANGE]); } } static void bz_fading_clamp_dispose (GObject *object) { BzFadingClamp *self = BZ_FADING_CLAMP (object); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_object (&self->animation); G_OBJECT_CLASS (bz_fading_clamp_parent_class)->dispose (object); } static void bz_fading_clamp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFadingClamp *self = BZ_FADING_CLAMP (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, self->child); break; case PROP_MAX_HEIGHT: g_value_set_int (value, self->max_height); break; case PROP_MIN_MAX_HEIGHT: g_value_set_int (value, self->min_max_height); break; case PROP_WILL_CHANGE: g_value_set_boolean (value, self->will_change); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_fading_clamp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFadingClamp *self = BZ_FADING_CLAMP (object); switch (prop_id) { case PROP_CHILD: bz_fading_clamp_set_child (self, g_value_get_object (value)); break; case PROP_MAX_HEIGHT: bz_fading_clamp_set_max_height (self, g_value_get_int (value)); break; case PROP_MIN_MAX_HEIGHT: self->min_max_height = g_value_get_int (value); bz_fading_clamp_update_will_change (self); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MIN_MAX_HEIGHT]); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static GtkSizeRequestMode bz_fading_clamp_get_request_mode (GtkWidget *widget) { return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; } static void bz_fading_clamp_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { int target_height; BzFadingClamp *self = BZ_FADING_CLAMP (widget); if (!self->child) { *minimum = 0; *natural = 0; return; } if (orientation == GTK_ORIENTATION_HORIZONTAL) { gtk_widget_measure (self->child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); } else { gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, for_size, minimum, natural, minimum_baseline, natural_baseline); if (*natural <= self->max_height + CLAMP_LEEWAY) target_height = *natural; else target_height = self->max_height; bz_fading_clamp_update_will_change (self); if (!self->animating_max_height && target_height != self->current_height) { self->current_height = target_height; } *minimum = MIN (*minimum, self->current_height); *natural = MIN (*natural, self->current_height); } } static void bz_fading_clamp_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzFadingClamp *self = BZ_FADING_CLAMP (widget); if (self->allocated_width != width) { self->allocated_width = width; bz_fading_clamp_update_will_change (self); } if (self->child) { int child_height = height; int natural_height; gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, width, NULL, &natural_height, NULL, NULL); if (natural_height > height) child_height = natural_height; gtk_widget_allocate (self->child, width, child_height, baseline, NULL); } } static void bz_fading_clamp_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzFadingClamp *self = BZ_FADING_CLAMP (widget); int width, height, natural_height; int gradient_start; graphene_rect_t gradient_rect; GskColorStop stops[2]; graphene_point_t start_point, end_point; int effective_fade_height; float stop_offset; if (!self->child || !gtk_widget_get_visible (self->child)) return; width = gtk_widget_get_width (widget); height = gtk_widget_get_height (widget); if (height <= 0) return; gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, width, NULL, &natural_height, NULL, NULL); if (natural_height <= height) { gtk_widget_snapshot_child (widget, self->child, snapshot); return; } effective_fade_height = MIN (natural_height - height, FADE_HEIGHT); gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_ALPHA); gradient_start = height - effective_fade_height; graphene_rect_init (&gradient_rect, 0, 0, width, height); stop_offset = CLAMP ((float) gradient_start / height, 0.0f, 1.0f); stops[0] = (GskColorStop) { stop_offset, { 1, 1, 1, 1 } }; stops[1] = (GskColorStop) { 1.0, { 1, 1, 1, 0 } }; graphene_point_init (&start_point, 0, 0); graphene_point_init (&end_point, 0, height); gtk_snapshot_append_linear_gradient (snapshot, &gradient_rect, &start_point, &end_point, stops, 2); gtk_snapshot_pop (snapshot); gtk_widget_snapshot_child (widget, self->child, snapshot); gtk_snapshot_pop (snapshot); } static void bz_fading_clamp_class_init (BzFadingClampClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_fading_clamp_dispose; object_class->get_property = bz_fading_clamp_get_property; object_class->set_property = bz_fading_clamp_set_property; widget_class->get_request_mode = bz_fading_clamp_get_request_mode; widget_class->measure = bz_fading_clamp_measure; widget_class->size_allocate = bz_fading_clamp_size_allocate; widget_class->snapshot = bz_fading_clamp_snapshot; properties[PROP_CHILD] = g_param_spec_object ("child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); properties[PROP_MAX_HEIGHT] = g_param_spec_int ("max-height", NULL, NULL, 0, G_MAXINT, 300, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); properties[PROP_MIN_MAX_HEIGHT] = g_param_spec_int ("min-max-height", NULL, NULL, 0, G_MAXINT, 150, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); properties[PROP_WILL_CHANGE] = g_param_spec_boolean ("will-change", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, N_PROPS, properties); } static void bz_fading_clamp_init (BzFadingClamp *self) { AdwAnimationTarget *target; self->max_height = 300; self->min_max_height = 150; self->current_height = 0; self->allocated_width = 0; self->animating_max_height = FALSE; self->will_change = FALSE; target = adw_callback_animation_target_new ((AdwAnimationTargetFunc) on_animation_value_changed, self, NULL); self->animation = adw_timed_animation_new (GTK_WIDGET (self), 0, 300, 250, target); g_signal_connect (self->animation, "done", G_CALLBACK (on_animation_done), self); } GtkWidget * bz_fading_clamp_new (void) { return g_object_new (BZ_TYPE_FADING_CLAMP, NULL); } void bz_fading_clamp_set_child (BzFadingClamp *self, GtkWidget *child) { g_return_if_fail (BZ_IS_FADING_CLAMP (self)); g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (self->child == child) return; g_clear_pointer (&self->child, gtk_widget_unparent); if (child) { self->child = child; gtk_widget_set_parent (child, GTK_WIDGET (self)); self->current_height = 0; } bz_fading_clamp_update_will_change (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHILD]); gtk_widget_queue_resize (GTK_WIDGET (self)); } GtkWidget * bz_fading_clamp_get_child (BzFadingClamp *self) { g_return_val_if_fail (BZ_IS_FADING_CLAMP (self), NULL); return self->child; } void bz_fading_clamp_set_max_height (BzFadingClamp *self, int max_height) { int natural_height, target_height; int width; g_return_if_fail (BZ_IS_FADING_CLAMP (self)); if (self->max_height == max_height) return; self->max_height = max_height; if (self->child) { if (self->allocated_width > 0) width = self->allocated_width; else gtk_widget_measure (self->child, GTK_ORIENTATION_HORIZONTAL, -1, NULL, &width, NULL, NULL); gtk_widget_measure (self->child, GTK_ORIENTATION_VERTICAL, width, NULL, &natural_height, NULL, NULL); if (natural_height <= max_height + CLAMP_LEEWAY) target_height = natural_height; else target_height = max_height; } else { target_height = max_height; } self->animating_max_height = TRUE; adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->animation), self->current_height); adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->animation), target_height); adw_animation_play (self->animation); bz_fading_clamp_update_will_change (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MAX_HEIGHT]); } int bz_fading_clamp_get_max_height (BzFadingClamp *self) { g_return_val_if_fail (BZ_IS_FADING_CLAMP (self), 0); return self->max_height; } kolunmi-bazaar-7b9c8e1/src/bz-fading-clamp.h000066400000000000000000000025221514314607700207560ustar00rootroot00000000000000/* bz-fading-clamp.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_FADING_CLAMP (bz_fading_clamp_get_type ()) G_DECLARE_FINAL_TYPE (BzFadingClamp, bz_fading_clamp, BZ, FADING_CLAMP, GtkWidget) GtkWidget *bz_fading_clamp_new (void); GtkWidget *bz_fading_clamp_get_child (BzFadingClamp *self); void bz_fading_clamp_set_child (BzFadingClamp *self, GtkWidget *child); int bz_fading_clamp_get_max_height (BzFadingClamp *self); void bz_fading_clamp_set_max_height (BzFadingClamp *self, int max_height); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-favorite-button.blp000066400000000000000000000020601514314607700221070ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFavoriteButton: Button { styles [ "small-pill", "suggested-action", "favorite", ] margin-top: 8; valign: start; halign: start; has-tooltip: true; tooltip-text: _("Favorite Count"); visible: bind template.entry as <$BzEntry>.is-flathub; clicked => $button_clicked_cb() swapped; child: Stack stack { transition-type: crossfade; StackPage { name: "content"; child: Box box { Image icon { icon-name: "bookmark-outline-symbolic"; } Revealer count_revealer { reveal-child: bind $is_positive(template.entry as <$BzEntry>.favorites-count) as ; transition-type: slide_left; child: Label count_label { margin-start: 4; label: bind $format_favorites_count(template.entry as <$BzEntry>.favorites-count) as ; }; } }; } StackPage { name: "spinner"; child: Adw.Spinner { halign: center; width-request: 16; }; } }; }kolunmi-bazaar-7b9c8e1/src/bz-favorite-button.c000066400000000000000000000314111514314607700215560ustar00rootroot00000000000000/* bz-favorite-button.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include "bz-entry.h" #include "bz-env.h" #include "bz-error.h" #include "bz-favorite-button.h" #include "bz-global-net.h" #include "bz-state-info.h" struct _BzFavoriteButton { GtkButton parent_instance; BzEntry *entry; BzStateInfo *state; GtkBox *box; GtkImage *icon; GtkRevealer *count_revealer; GtkLabel *count_label; GtkStack *stack; gboolean is_favorited; }; G_DEFINE_FINAL_TYPE (BzFavoriteButton, bz_favorite_button, GTK_TYPE_BUTTON) enum { PROP_0, PROP_ENTRY, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * fetch_favorite_status_fiber (BzFavoriteButton *button); static DexFuture * toggle_favorite_fiber (BzFavoriteButton *button); static void button_clicked_cb (BzFavoriteButton *self, GtkButton *button); static void update_icon (BzFavoriteButton *self); static void update_count (BzFavoriteButton *self); static void on_login_button_clicked (GtkButton *button, GtkPopover *popover); static void show_login_popover (BzFavoriteButton *self); static gboolean is_positive (gpointer object, int value); static char * format_favorites_count (gpointer object, int count); static void bz_favorite_button_dispose (GObject *object) { BzFavoriteButton *self = BZ_FAVORITE_BUTTON (object); g_clear_object (&self->entry); g_clear_object (&self->state); G_OBJECT_CLASS (bz_favorite_button_parent_class)->dispose (object); } static void bz_favorite_button_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFavoriteButton *self = BZ_FAVORITE_BUTTON (object); switch (prop_id) { case PROP_ENTRY: g_value_set_object (value, bz_favorite_button_get_entry (self)); break; case PROP_STATE: g_value_set_object (value, bz_favorite_button_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_favorite_button_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFavoriteButton *self = BZ_FAVORITE_BUTTON (object); switch (prop_id) { case PROP_ENTRY: bz_favorite_button_set_entry (self, g_value_get_object (value)); break; case PROP_STATE: bz_favorite_button_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_favorite_button_class_init (BzFavoriteButtonClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_favorite_button_dispose; object_class->get_property = bz_favorite_button_get_property; object_class->set_property = bz_favorite_button_set_property; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-favorite-button.ui"); gtk_widget_class_bind_template_child (widget_class, BzFavoriteButton, box); gtk_widget_class_bind_template_child (widget_class, BzFavoriteButton, icon); gtk_widget_class_bind_template_child (widget_class, BzFavoriteButton, count_revealer); gtk_widget_class_bind_template_child (widget_class, BzFavoriteButton, count_label); gtk_widget_class_bind_template_child (widget_class, BzFavoriteButton, stack); gtk_widget_class_bind_template_callback (widget_class, is_positive); gtk_widget_class_bind_template_callback (widget_class, format_favorites_count); gtk_widget_class_bind_template_callback (widget_class, button_clicked_cb); } static void bz_favorite_button_init (BzFavoriteButton *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->is_favorited = FALSE; } GtkWidget * bz_favorite_button_new (void) { return g_object_new (BZ_TYPE_FAVORITE_BUTTON, NULL); } void bz_favorite_button_set_entry (BzFavoriteButton *self, BzEntry *entry) { g_return_if_fail (BZ_IS_FAVORITE_BUTTON (self)); g_return_if_fail (entry == NULL || BZ_IS_ENTRY (entry)); if (g_set_object (&self->entry, entry)) { update_count (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY]); if (self->state != NULL && self->entry != NULL) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) fetch_favorite_status_fiber, g_object_ref (self), g_object_unref)); } } } BzEntry * bz_favorite_button_get_entry (BzFavoriteButton *self) { g_return_val_if_fail (BZ_IS_FAVORITE_BUTTON (self), NULL); return self->entry; } void bz_favorite_button_set_state (BzFavoriteButton *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_FAVORITE_BUTTON (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); if (g_set_object (&self->state, state)) { g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); if (self->state != NULL && self->entry != NULL) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) fetch_favorite_status_fiber, g_object_ref (self), g_object_unref)); } } } BzStateInfo * bz_favorite_button_get_state (BzFavoriteButton *self) { g_return_val_if_fail (BZ_IS_FAVORITE_BUTTON (self), NULL); return self->state; } static gboolean is_positive (gpointer object, int value) { return value > 0; } static char * format_favorites_count (gpointer object, int count) { if (count >= 1000000) return g_strdup_printf ("%.1fM", count / 1000000.0); else if (count >= 1000) return g_strdup_printf ("%.1fK", count / 1000.0); else return g_strdup_printf ("%d", count); } static void update_icon (BzFavoriteButton *self) { if (self->is_favorited) gtk_image_set_from_icon_name (self->icon, "bookmark-filled-symbolic"); else gtk_image_set_from_icon_name (self->icon, "bookmark-outline-symbolic"); } static void update_count (BzFavoriteButton *self) { int count = 0; if (self->entry != NULL) g_object_get (self->entry, "favorites-count", &count, NULL); gtk_revealer_set_reveal_child (self->count_revealer, count > 0); if (count > 0) { g_autofree char *formatted = format_favorites_count (NULL, count); gtk_label_set_label (self->count_label, formatted); } } static DexFuture * fetch_favorite_status_fiber (BzFavoriteButton *button) { g_autoptr (GError) local_error = NULL; g_autoptr (JsonNode) node = NULL; g_autofree char *request = NULL; BzAuthState *auth_state = NULL; const char *token = NULL; const char *app_id = NULL; if (button->state == NULL || button->entry == NULL) return NULL; auth_state = bz_state_info_get_auth_state (button->state); if (!bz_auth_state_is_authenticated (auth_state)) return NULL; token = bz_auth_state_get_token (auth_state); if (token == NULL) return NULL; g_object_get (button->entry, "id", &app_id, NULL); request = g_strdup_printf ("/favorites/%s", app_id); node = dex_await_boxed ( bz_query_flathub_v2_json_authenticated (request, token), &local_error); if (local_error == NULL && node != NULL && JSON_NODE_HOLDS_VALUE (node)) { button->is_favorited = json_node_get_boolean (node); update_icon (button); } return NULL; } static DexFuture * toggle_favorite_fiber (BzFavoriteButton *button) { g_autoptr (GError) local_error = NULL; g_autofree char *request = NULL; BzAuthState *auth_state = NULL; const char *token = NULL; const char *app_id = NULL; int current_count = 0; if (button->state == NULL || button->entry == NULL) goto err; auth_state = bz_state_info_get_auth_state (button->state); if (!bz_auth_state_is_authenticated (auth_state)) goto err; token = bz_auth_state_get_token (auth_state); if (token == NULL) goto err; g_object_get (button->entry, "id", &app_id, "favorites-count", ¤t_count, NULL); if (button->is_favorited) request = g_strdup_printf ("/favorites/%s/remove", app_id); else request = g_strdup_printf ("/favorites/%s/add", app_id); if (button->is_favorited) dex_await ( bz_query_flathub_v2_json_authenticated_delete (request, token), &local_error); else dex_await ( bz_query_flathub_v2_json_authenticated_post (request, token), &local_error); if (local_error != NULL) { GtkWidget *window = NULL; gtk_stack_set_visible_child_name (button->stack, "content"); window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW); if (window != NULL) bz_show_error_for_widget (window, local_error->message); } else { button->is_favorited = !button->is_favorited; g_object_set (button->entry, "favorites-count", button->is_favorited ? current_count + 1 : current_count - 1, NULL); update_icon (button); update_count (button); gtk_stack_set_visible_child_name (button->stack, "content"); } return NULL; err: gtk_stack_set_visible_child_name (button->stack, "content"); return NULL; } static void on_login_button_clicked (GtkButton *button, GtkPopover *popover) { gtk_popover_popdown (popover); } static void show_login_popover (BzFavoriteButton *self) { GtkWidget *popover; GtkWidget *box; GtkWidget *label; GtkWidget *button; popover = gtk_popover_new (); gtk_widget_set_parent (popover, GTK_WIDGET (self)); box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_widget_set_margin_top (box, 6); gtk_widget_set_margin_bottom (box, 6); gtk_widget_set_margin_start (box, 6); gtk_widget_set_margin_end (box, 6); label = gtk_label_new (_ ("Log in with Flathub to manage favorites")); gtk_label_set_wrap (GTK_LABEL (label), TRUE); gtk_label_set_max_width_chars (GTK_LABEL (label), 17); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); gtk_box_append (GTK_BOX (box), label); button = gtk_button_new_with_label (_ ("Log In")); gtk_widget_add_css_class (button, "suggested-action"); gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "app.flathub-login"); g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked), popover); gtk_box_append (GTK_BOX (box), button); gtk_popover_set_child (GTK_POPOVER (popover), box); gtk_popover_popup (GTK_POPOVER (popover)); } static void button_clicked_cb (BzFavoriteButton *self, GtkButton *button) { BzAuthState *auth_state = NULL; if (self->state == NULL) return; auth_state = bz_state_info_get_auth_state (self->state); if (!bz_auth_state_is_authenticated (auth_state)) { show_login_popover (self); return; } gtk_stack_set_visible_child_name (self->stack, "spinner"); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) toggle_favorite_fiber, g_object_ref (self), g_object_unref)); } kolunmi-bazaar-7b9c8e1/src/bz-favorite-button.h000066400000000000000000000026501514314607700215660ustar00rootroot00000000000000/* bz-favorite-button.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include "bz-state-info.h" #include G_BEGIN_DECLS #define BZ_TYPE_FAVORITE_BUTTON (bz_favorite_button_get_type ()) G_DECLARE_FINAL_TYPE (BzFavoriteButton, bz_favorite_button, BZ, FAVORITE_BUTTON, GtkButton) GtkWidget * bz_favorite_button_new (void); void bz_favorite_button_set_entry (BzFavoriteButton *self, BzEntry *entry); BzEntry * bz_favorite_button_get_entry (BzFavoriteButton *self); void bz_favorite_button_set_state (BzFavoriteButton *self, BzStateInfo *state); BzStateInfo * bz_favorite_button_get_state (BzFavoriteButton *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-favorites-page.blp000066400000000000000000000071141514314607700217000ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFavoritesPage: Adw.NavigationPage { title: _("Favorites"); Adw.ToolbarView { [top] Adw.HeaderBar { [end] Button { styles [ "flat", "global-progress-button", ] can-target: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; action-name: "window.open-library"; has-tooltip: true; tooltip-text: _("Open App Library"); child: $BzGlobalProgress { expand-size: 125; active: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; pending: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.pending; fraction: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.current-progress; settings: bind template.state as <$BzStateInfo>.settings; }; } [end] Button install_all_button { styles [ "flat", ] has-tooltip: true; tooltip-text: _("Install All"); icon-name: "list-add-symbolic"; sensitive: bind $invert_boolean($is_empty(template.favorites) as ) as ; clicked => $install_all_cb() swapped; } } content: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Adw.ViewStack stack { enable-transitions: true; transition-duration: 400; Adw.ViewStackPage { name: "loading"; title: _("Loading"); child: Adw.Spinner { halign: fill; valign: center; width-request: 64; height-request: 64; margin-bottom: 18; }; } Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "starred-symbolic"; title: _("No Favorites"); description: _("Applications you mark as favorite will appear here"); }; } Adw.ViewStackPage { name: "content"; title: _("Favorites"); child: ScrolledWindow { hscrollbar-policy: never; child: Adw.ClampScrollable { maximum-size: 650; child: ListView list_view { styles [ "navigation-sidebar", "installed-list-view", "no-vertical-margin" ] margin-start: 25; margin-end: 25; overflow: visible; model: NoSelection { model: bind template.model; }; factory: BuilderListItemFactory { template ListItem { activatable: true; selectable: false; focusable: true; child: Revealer { reveal-child: true; overflow: visible; child: $BzFavoritesTile { group: bind template.item as <$BzEntryGroup>; activated => $tile_activated_cb(); unfavorited => $unfavorite_cb(); }; }; } }; }; }; }; } }; Adw.Breakpoint { condition ("max-width: 700px") setters { list_view.margin-start: 8; list_view.margin-end: 8; } } }; } }kolunmi-bazaar-7b9c8e1/src/bz-favorites-page.c000066400000000000000000000360351514314607700213510ustar00rootroot00000000000000/* bz-favorites-page.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include "bz-application-map-factory.h" #include "bz-entry-group-util.h" #include "bz-env.h" #include "bz-error.h" #include "bz-favorites-page.h" #include "bz-favorites-tile.h" #include "bz-global-net.h" #include "bz-io.h" #include "bz-util.h" struct _BzFavoritesPage { AdwNavigationPage parent_instance; BzStateInfo *state; GListModel *model; GListModel *favorites; gboolean show_sidebar; AdwViewStack *stack; }; G_DEFINE_FINAL_TYPE (BzFavoritesPage, bz_favorites_page, ADW_TYPE_NAVIGATION_PAGE) enum { PROP_0, PROP_STATE, PROP_MODEL, PROP_FAVORITES, PROP_SHOW_SIDEBAR, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_INSTALL, SIGNAL_REMOVE, SIGNAL_SHOW, SIGNAL_BULK_INSTALL, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static DexFuture * fetch_favorites_fiber (GWeakRef *wr); static void favorites_changed (BzFavoritesPage *self, guint position, guint removed, guint added, GListModel *model); static void set_page (BzFavoritesPage *self); static void bz_favorites_page_dispose (GObject *object) { BzFavoritesPage *self = BZ_FAVORITES_PAGE (object); if (self->favorites != NULL) g_signal_handlers_disconnect_by_func (self->favorites, favorites_changed, self); g_clear_object (&self->favorites); g_clear_object (&self->model); g_clear_object (&self->state); G_OBJECT_CLASS (bz_favorites_page_parent_class)->dispose (object); } static void bz_favorites_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFavoritesPage *self = BZ_FAVORITES_PAGE (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, self->state); break; case PROP_MODEL: g_value_set_object (value, self->model); break; case PROP_FAVORITES: g_value_set_object (value, self->favorites); break; case PROP_SHOW_SIDEBAR: g_value_set_boolean (value, self->show_sidebar); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_favorites_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFavoritesPage *self = BZ_FAVORITES_PAGE (object); switch (prop_id) { case PROP_STATE: self->state = g_value_dup_object (value); break; case PROP_SHOW_SIDEBAR: self->show_sidebar = g_value_get_boolean (value); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SHOW_SIDEBAR]); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_favorites_page_constructed (GObject *object) { BzFavoritesPage *self = BZ_FAVORITES_PAGE (object); g_autoptr (DexFuture) future = NULL; G_OBJECT_CLASS (bz_favorites_page_parent_class)->constructed (object); future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) fetch_favorites_fiber, bz_track_weak (self), bz_weak_release); dex_future_disown (g_steal_pointer (&future)); } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_empty (gpointer object, GListModel *model) { if (model == NULL) return TRUE; return g_list_model_get_n_items (model) == 0; } static gboolean is_favorited (GListModel *favorites, BzEntryGroup *group) { if (favorites == NULL || group == NULL) return FALSE; return g_list_store_find (G_LIST_STORE (favorites), group, NULL); } static DexFuture * tile_activated_fiber (GWeakRef *wr) { g_autoptr (BzFavoritesTile) tile = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (BzEntry) entry = NULL; g_autoptr (GListModel) all_entries = NULL; BzFavoritesPage *self = NULL; GtkWidget *window = NULL; BzEntryGroup *group = NULL; bz_weak_get_or_return_reject (tile, wr); self = (BzFavoritesPage *) gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_FAVORITES_PAGE); if (self == NULL) return NULL; if (self->model == NULL) goto err; window = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_WINDOW); if (window == NULL) goto err; group = bz_favorites_tile_get_group (tile); if (group == NULL) goto err; entry = bz_entry_group_find_entry (group, NULL, window, &local_error); if (entry == NULL) { if (local_error != NULL) g_clear_error (&local_error); all_entries = dex_await_object ( bz_entry_group_dup_all_into_store (group), &local_error); if (all_entries == NULL || g_list_model_get_n_items (all_entries) == 0) goto err; entry = g_list_model_get_item (all_entries, 0); } g_signal_emit (self, signals[SIGNAL_SHOW], 0, entry); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return NULL; } static void tile_activated_cb (BzFavoritesTile *tile) { g_assert (BZ_IS_FAVORITES_TILE (tile)); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) tile_activated_fiber, bz_track_weak (tile), bz_weak_release)); } static void unfavorite_cb (BzFavoritesTile *tile, BzEntryGroup *group, gpointer user_data) { BzFavoritesPage *self = NULL; guint position = 0; g_assert (BZ_IS_FAVORITES_TILE (tile)); g_assert (BZ_IS_ENTRY_GROUP (group)); self = BZ_FAVORITES_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_FAVORITES_PAGE)); if (self == NULL) return; if (self->favorites == NULL) return; if (g_list_store_find (G_LIST_STORE (self->favorites), group, &position)) { g_list_store_remove (G_LIST_STORE (self->favorites), position); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FAVORITES]); } } static void install_all_cb (BzFavoritesPage *self, GtkButton *button) { g_autoptr (GListStore) installable_groups = NULL; guint n_items = 0; g_return_if_fail (BZ_IS_FAVORITES_PAGE (self)); if (self->model == NULL || self->favorites == NULL) return; installable_groups = g_list_store_new (BZ_TYPE_ENTRY_GROUP); n_items = g_list_model_get_n_items (self->favorites); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntryGroup) group = NULL; group = g_list_model_get_item (self->favorites, i); if (!is_favorited (self->favorites, group)) continue; g_list_store_append (installable_groups, group); } g_signal_emit (self, signals[SIGNAL_BULK_INSTALL], 0, G_LIST_MODEL (installable_groups)); } static void bz_favorites_page_class_init (BzFavoritesPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_favorites_page_dispose; object_class->constructed = bz_favorites_page_constructed; object_class->get_property = bz_favorites_page_get_property; object_class->set_property = bz_favorites_page_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_FAVORITES] = g_param_spec_object ( "favorites", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_SHOW_SIDEBAR] = g_param_spec_boolean ( "show-sidebar", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_INSTALL] = g_signal_new ( "install", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); signals[SIGNAL_REMOVE] = g_signal_new ( "remove", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); signals[SIGNAL_SHOW] = g_signal_new ( "show-entry", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); signals[SIGNAL_BULK_INSTALL] = g_signal_new ( "bulk-install", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_LIST_MODEL); g_type_ensure (BZ_TYPE_FAVORITES_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-favorites-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzFavoritesPage, stack); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_empty); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); gtk_widget_class_bind_template_callback (widget_class, unfavorite_cb); gtk_widget_class_bind_template_callback (widget_class, install_all_cb); } static void bz_favorites_page_init (BzFavoritesPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_favorites_page_new (BzStateInfo *state) { return g_object_new (BZ_TYPE_FAVORITES_PAGE, "state", state, NULL); } static void favorites_changed (BzFavoritesPage *self, guint position, guint removed, guint added, GListModel *model) { set_page (self); } static void set_page (BzFavoritesPage *self) { if (self->favorites != NULL && g_list_model_get_n_items (self->favorites) > 0) adw_view_stack_set_visible_child_name (self->stack, "content"); else adw_view_stack_set_visible_child_name (self->stack, "empty"); } static int compare_entry_groups_by_title (BzEntryGroup *group_a, BzEntryGroup *group_b) { const char *title_a = bz_entry_group_get_title (group_a); const char *title_b = bz_entry_group_get_title (group_b); return g_utf8_collate (title_a, title_b); } static DexFuture * fetch_favorites_fiber (GWeakRef *wr) { g_autoptr (BzFavoritesPage) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GtkStringList) id_list = NULL; g_autoptr (GListModel) model = NULL; g_autoptr (GListStore) sorted_store = NULL; g_autoptr (GListStore) favorites_store = NULL; g_autoptr (JsonNode) node = NULL; BzApplicationMapFactory *factory = NULL; BzAuthState *auth_state = NULL; const char *token = NULL; JsonArray *array = NULL; guint n_favorites = 0; guint n_items = 0; self = g_weak_ref_get (wr); if (self == NULL) return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Page destroyed"); id_list = gtk_string_list_new (NULL); auth_state = bz_state_info_get_auth_state (self->state); token = bz_auth_state_get_token (auth_state); if (token != NULL && bz_auth_state_is_authenticated (auth_state)) { node = dex_await_boxed ( bz_query_flathub_v2_json_authenticated ("/favorites", token), &local_error); if (node == NULL) { g_warning ("Failed to fetch favorites from Flathub: %s", local_error->message); goto done; } if (!JSON_NODE_HOLDS_ARRAY (node)) { g_warning ("Unexpected response format from Flathub favorites API"); goto done; } array = json_node_get_array (node); n_favorites = json_array_get_length (array); for (guint i = 0; i < n_favorites; i++) { JsonObject *favorite_obj = NULL; const char *app_id = NULL; favorite_obj = json_array_get_object_element (array, i); app_id = json_object_get_string_member (favorite_obj, "app_id"); if (app_id != NULL) gtk_string_list_append (id_list, app_id); } } done: factory = bz_state_info_get_application_factory (self->state); model = bz_application_map_factory_generate (factory, G_LIST_MODEL (id_list)); sorted_store = g_list_store_new (BZ_TYPE_ENTRY_GROUP); favorites_store = g_list_store_new (BZ_TYPE_ENTRY_GROUP); n_items = g_list_model_get_n_items (model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntryGroup) group = g_list_model_get_item (model, i); g_list_store_append (sorted_store, group); g_list_store_append (favorites_store, group); } g_list_store_sort (sorted_store, (GCompareDataFunc) compare_entry_groups_by_title, NULL); g_clear_object (&self->model); self->model = G_LIST_MODEL (g_steal_pointer (&sorted_store)); if (self->favorites != NULL) g_signal_handlers_disconnect_by_func (self->favorites, favorites_changed, self); g_clear_object (&self->favorites); self->favorites = G_LIST_MODEL (g_steal_pointer (&favorites_store)); g_signal_connect_swapped (self->favorites, "items-changed", G_CALLBACK (favorites_changed), self); set_page (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FAVORITES]); return dex_future_new_true (); } kolunmi-bazaar-7b9c8e1/src/bz-favorites-page.h000066400000000000000000000021001514314607700213400ustar00rootroot00000000000000/* bz-favorites-page.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_FAVORITES_PAGE (bz_favorites_page_get_type ()) G_DECLARE_FINAL_TYPE (BzFavoritesPage, bz_favorites_page, BZ, FAVORITES_PAGE, AdwNavigationPage) GtkWidget *bz_favorites_page_new (BzStateInfo *state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-favorites-tile.blp000066400000000000000000000077411514314607700217270ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFavoritesTile: $BzListTile { accessibility { labelled-by: title_label; described-by: description_label; } child: Box { orientation: horizontal; spacing: 10; Picture icon_picture { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 48; width-request: 48; paintable: bind template.group as <$BzEntryGroup>.icon-paintable; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.icon-paintable) as ) as ; styles ["icon-dropshadow"] } Image fallback_icon { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 48; width-request: 48; pixel-size: 48; icon-name: "application-x-executable"; visible: bind $is_null(template.group as <$BzEntryGroup>.icon-paintable) as ; styles ["icon-dropshadow"] } Box { orientation: vertical; valign: center; spacing: 4; Label title_label { xalign: 0.0; ellipsize: end; single-line-mode: true; has-tooltip: true; tooltip-text: bind template.group as <$BzEntryGroup>.id; label: bind template.group as <$BzEntryGroup>.title; } Label description_label { halign: start; label: bind template.group as <$BzEntryGroup>.description; xalign: 0.0; ellipsize: end; single-line-mode: true; styles ["dim-label", "caption"] } } Button support_button { styles [ "circular", "flat", "suggested-action", "support" ] has-tooltip: true; tooltip-text: _("Support this application"); width-request: 32; height-request: 32; valign: center; icon-name: "heart-filled-symbolic"; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.donation-url) as ) as ; clicked => $support_cb() swapped; } Box { orientation: horizontal; spacing: 8; margin-end: 8; hexpand: true; halign: end; Button install_remove_button { styles [ "flat", ] width-request: 32; height-request: 32; valign: center; has-tooltip: true; visible: bind $invert_boolean($logical_and($is_zero(template.group as <$BzEntryGroup>.removable) as , $is_zero(template.group as <$BzEntryGroup>.installable) as ) as ) as ; tooltip-text: bind $get_install_remove_tooltip(template.group as <$BzEntryGroup>.removable) as ; sensitive: bind $switch_bool( template.group as <$BzEntryGroup>.removable, $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as , $invert_boolean($is_zero(template.group as <$BzEntryGroup>.installable-and-available) as ) as , ) as ; icon-name: bind $get_install_remove_icon(template.group as <$BzEntryGroup>.removable) as ; clicked => $install_remove_cb() swapped; } Stack unfavorite_stack { transition-type: crossfade; StackPage { name: "button"; child: Button unfavorite_button { styles [ "flat", ] width-request: 32; height-request: 32; valign: center; has-tooltip: true; tooltip-text: _("Remove from Favorites"); icon-name: "bookmark-filled-symbolic"; clicked => $unfavorite_cb() swapped; }; } StackPage { name: "spinner"; child: Adw.Spinner { halign: center; width-request: 16; }; } } Image { pixel-size: 14; icon-name: "go-next-symbolic"; margin-end: 4; styles ["dimmed"] } } }; }kolunmi-bazaar-7b9c8e1/src/bz-favorites-tile.c000066400000000000000000000330051514314607700213640ustar00rootroot00000000000000/* bz-favorites-tile.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-entry-group-util.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-error.h" #include "bz-favorites-page.h" #include "bz-favorites-tile.h" #include "bz-global-net.h" #include "bz-state-info.h" #include "bz-window.h" struct _BzFavoritesTile { BzListTile parent_instance; BzEntryGroup *group; GtkPicture *icon_picture; GtkImage *fallback_icon; GtkLabel *title_label; GtkLabel *description_label; GtkButton *install_remove_button; GtkButton *support_button; GtkButton *unfavorite_button; GtkStack *unfavorite_stack; }; G_DEFINE_FINAL_TYPE (BzFavoritesTile, bz_favorites_tile, BZ_TYPE_LIST_TILE) enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_UNFAVORITED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static gboolean test_is_support (BzEntry *entry); static BzEntry * find_entry (BzEntryGroup *group, gboolean (*test) (BzEntry *entry), GtkWidget *window, GError **error); static DexFuture * install_remove_fiber (BzFavoritesTile *tile); static void install_remove_cb (BzFavoritesTile *self, GtkButton *button); static DexFuture * support_fiber (BzFavoritesTile *tile); static void support_cb (BzFavoritesTile *self, GtkButton *button); static DexFuture * unfavorite_fiber (BzFavoritesTile *tile); static void unfavorite_cb (BzFavoritesTile *self, GtkButton *button); static void bz_favorites_tile_dispose (GObject *object) { BzFavoritesTile *self = BZ_FAVORITES_TILE (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_favorites_tile_parent_class)->dispose (object); } static void bz_favorites_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFavoritesTile *self = BZ_FAVORITES_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_favorites_tile_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_favorites_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFavoritesTile *self = BZ_FAVORITES_TILE (object); switch (prop_id) { case PROP_GROUP: bz_favorites_tile_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static char * get_install_remove_tooltip (gpointer object, int removable) { if (removable > 0) return g_strdup (_ ("Uninstall")); else return g_strdup (_ ("Install")); } static char * get_install_remove_icon (gpointer object, int removable) { if (removable > 0) return g_strdup ("user-trash-symbolic"); else return g_strdup ("document-save-symbolic"); } static gboolean switch_bool (gpointer object, gboolean condition, gboolean true_value, gboolean false_value) { return condition ? true_value : false_value; } static gboolean logical_and (gpointer object, gboolean value1, gboolean value2) { return value1 && value2; } static void bz_favorites_tile_class_init (BzFavoritesTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_favorites_tile_dispose; object_class->get_property = bz_favorites_tile_get_property; object_class->set_property = bz_favorites_tile_set_property; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_UNFAVORITED] = g_signal_new ( "unfavorited", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_type_ensure (BZ_TYPE_LIST_TILE); g_type_ensure (BZ_TYPE_ENTRY_GROUP); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-favorites-tile.ui"); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, icon_picture); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, fallback_icon); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, title_label); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, description_label); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, install_remove_button); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, support_button); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, unfavorite_button); gtk_widget_class_bind_template_child (widget_class, BzFavoritesTile, unfavorite_stack); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, switch_bool); gtk_widget_class_bind_template_callback (widget_class, logical_and); gtk_widget_class_bind_template_callback (widget_class, get_install_remove_tooltip); gtk_widget_class_bind_template_callback (widget_class, get_install_remove_icon); gtk_widget_class_bind_template_callback (widget_class, install_remove_cb); gtk_widget_class_bind_template_callback (widget_class, unfavorite_cb); gtk_widget_class_bind_template_callback (widget_class, support_cb); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_favorites_tile_init (BzFavoritesTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_favorites_tile_new (void) { return g_object_new (BZ_TYPE_FAVORITES_TILE, NULL); } void bz_favorites_tile_set_group (BzFavoritesTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_FAVORITES_TILE (self)); g_return_if_fail (group == NULL || BZ_IS_ENTRY_GROUP (group)); g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } BzEntryGroup * bz_favorites_tile_get_group (BzFavoritesTile *self) { g_return_val_if_fail (BZ_IS_FAVORITES_TILE (self), NULL); return self->group; } static gboolean test_is_support (BzEntry *entry) { return bz_entry_get_donation_url (entry) != NULL; } static BzEntry * find_entry (BzEntryGroup *group, gboolean (*test) (BzEntry *entry), GtkWidget *window, GError **error) { g_autoptr (GError) local_error = NULL; g_autoptr (BzEntry) entry = NULL; g_autoptr (GListModel) all_entries = NULL; entry = bz_entry_group_find_entry (group, test, window, &local_error); if (entry != NULL) return g_steal_pointer (&entry); g_clear_error (&local_error); all_entries = dex_await_object ( bz_entry_group_dup_all_into_store (group), error); if (all_entries == NULL) return NULL; if (test == NULL) { if (g_list_model_get_n_items (all_entries) == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No entries found in group"); return NULL; } return g_list_model_get_item (all_entries, 0); } for (guint i = 0; i < g_list_model_get_n_items (all_entries); i++) { g_autoptr (BzEntry) candidate = g_list_model_get_item (all_entries, i); if (test (candidate)) return g_steal_pointer (&candidate); } g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No entry matching criteria found"); return NULL; } static DexFuture * install_remove_fiber (BzFavoritesTile *tile) { g_autoptr (GError) local_error = NULL; g_autoptr (BzEntry) entry = NULL; BzFavoritesPage *page = NULL; GtkWidget *window = NULL; int removable = 0; page = BZ_FAVORITES_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_FAVORITES_PAGE)); g_assert (page != NULL); window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); g_assert (window != NULL); removable = bz_entry_group_get_removable (tile->group); if (removable > 0) entry = bz_entry_group_find_entry (tile->group, NULL, window, &local_error); else entry = find_entry (tile->group, NULL, window, &local_error); if (entry == NULL) goto err; if (removable > 0) g_signal_emit_by_name (page, "remove", entry); else g_signal_emit_by_name (page, "install", entry); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return NULL; } static void install_remove_cb (BzFavoritesTile *self, GtkButton *button) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) install_remove_fiber, g_object_ref (self), g_object_unref)); } static DexFuture * support_fiber (BzFavoritesTile *tile) { g_autoptr (GError) local_error = NULL; g_autoptr (BzEntry) entry = NULL; GtkWidget *window = NULL; const char *url = NULL; window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); g_assert (window != NULL); entry = find_entry (tile->group, test_is_support, window, &local_error); if (entry == NULL) goto err; url = bz_entry_get_donation_url (entry); g_app_info_launch_default_for_uri (url, NULL, NULL); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return NULL; } static void support_cb (BzFavoritesTile *self, GtkButton *button) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) support_fiber, g_object_ref (self), g_object_unref)); } static DexFuture * unfavorite_fiber (BzFavoritesTile *tile) { g_autoptr (GError) local_error = NULL; g_autoptr (BzStateInfo) state = NULL; g_autofree char *request = NULL; BzFavoritesPage *page = NULL; BzAuthState *auth_state = NULL; const char *token = NULL; const char *app_id = NULL; GtkWidget *revealer = NULL; GtkWidget *row = NULL; revealer = gtk_widget_get_parent (GTK_WIDGET (tile)); row = gtk_widget_get_parent (GTK_WIDGET (revealer)); page = BZ_FAVORITES_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_FAVORITES_PAGE)); if (page == NULL) return NULL; g_object_get (page, "state", &state, NULL); if (state == NULL) return NULL; auth_state = bz_state_info_get_auth_state (state); token = bz_auth_state_get_token (auth_state); if (token == NULL || !bz_auth_state_is_authenticated (auth_state)) return NULL; app_id = bz_entry_group_get_id (tile->group); request = g_strdup_printf ("/favorites/%s/remove", app_id); dex_await ( bz_query_flathub_v2_json_authenticated_delete (request, token), &local_error); if (local_error != NULL) { GtkWidget *window = NULL; gtk_stack_set_visible_child_name (tile->unfavorite_stack, "button"); window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); if (window != NULL) bz_show_error_for_widget (window, local_error->message); } else { gtk_widget_set_overflow (revealer, GTK_OVERFLOW_HIDDEN); gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE); gtk_widget_add_css_class (row, "hidden"); g_signal_emit (tile, signals[SIGNAL_UNFAVORITED], 0, tile->group); } return NULL; } static void unfavorite_cb (BzFavoritesTile *self, GtkButton *button) { gtk_stack_set_visible_child_name (self->unfavorite_stack, "spinner"); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) unfavorite_fiber, g_object_ref (self), g_object_unref)); } kolunmi-bazaar-7b9c8e1/src/bz-favorites-tile.h000066400000000000000000000023731514314607700213750ustar00rootroot00000000000000/* bz-favorites-tile.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include "bz-list-tile.h" #include G_BEGIN_DECLS #define BZ_TYPE_FAVORITES_TILE (bz_favorites_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzFavoritesTile, bz_favorites_tile, BZ, FAVORITES_TILE, BzListTile) GtkWidget * bz_favorites_tile_new (void); void bz_favorites_tile_set_group (BzFavoritesTile *self, BzEntryGroup *group); BzEntryGroup * bz_favorites_tile_get_group (BzFavoritesTile *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-featured-carousel.blp000066400000000000000000000022521514314607700223740ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFeaturedCarousel: Box { orientation: vertical; spacing: 12; styles [ "featured-carousel", ] Overlay { [overlay] Button previous_button { halign: start; valign: center; width-request: 48; height-request: 48; margin-start: 12; icon-name: "go-previous-symbolic"; clicked => $previous_button_clicked_cb(); styles [ "circular", "flat", "image-button", ] accessibility { label: _("Previous"); } } [overlay] Button next_button { halign: end; valign: center; width-request: 48; height-request: 48; margin-end: 12; icon-name: "go-next-symbolic"; clicked => $next_button_clicked_cb(); styles [ "circular", "flat", "image-button", ] accessibility { label: _("Next"); } } Adw.Carousel carousel { styles ["card"] notify::position => $carousel_notify_position_cb(); } } Adw.CarouselIndicatorDots dots { carousel: carousel; } EventControllerKey { key-pressed => $key_pressed_cb(); } }kolunmi-bazaar-7b9c8e1/src/bz-featured-carousel.c000066400000000000000000000344521514314607700220500ustar00rootroot00000000000000/* bz-featured-carousel.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-featured-carousel.h" #include "bz-entry-group.h" #include "bz-featured-tile.h" #define FEATURED_ROTATE_TIME 5 struct _BzFeaturedCarousel { GtkBox parent_instance; GListModel *model; gboolean is_aotd; guint rotation_timer_id; unsigned long settings_notify_id; AdwCarousel *carousel; GtkButton *next_button; GtkButton *previous_button; AdwCarouselIndicatorDots *dots; }; G_DEFINE_FINAL_TYPE (BzFeaturedCarousel, bz_featured_carousel, GTK_TYPE_BOX) enum { PROP_0, PROP_MODEL, PROP_IS_AOTD, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL, }; enum { SIGNAL_GROUP_CLICKED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0, }; static void show_relative_page (BzFeaturedCarousel *self, gint delta, gboolean use_custom_spring) { gdouble current_page; guint n_pages; guint new_page; GtkWidget *new_page_widget; gboolean animate; current_page = adw_carousel_get_position (self->carousel); n_pages = adw_carousel_get_n_pages (self->carousel); animate = TRUE; if (n_pages == 0) return; new_page = ((guint) current_page + delta + n_pages) % n_pages; new_page_widget = adw_carousel_get_nth_page (self->carousel, new_page); g_assert (new_page_widget != NULL); if ((new_page == 0 && delta > 0) || (new_page == n_pages - 1 && delta < 0)) animate = FALSE; if (!adw_get_enable_animations (GTK_WIDGET (self))) animate = FALSE; if (use_custom_spring) { g_autoptr (AdwSpringParams) spring_params = NULL; spring_params = adw_spring_params_new (0.90, 1.65, 100.0); adw_carousel_set_scroll_params (self->carousel, spring_params); } else { g_autoptr (AdwSpringParams) spring_params = NULL; spring_params = adw_spring_params_new (1, 0.5, 500); adw_carousel_set_scroll_params (self->carousel, spring_params); } adw_carousel_scroll_to (self->carousel, new_page_widget, animate); } static gboolean rotate_cb (gpointer user_data) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (user_data); show_relative_page (self, +1, TRUE); return G_SOURCE_CONTINUE; } static void start_rotation_timer (BzFeaturedCarousel *self) { if (self->rotation_timer_id == 0) { self->rotation_timer_id = g_timeout_add_seconds (FEATURED_ROTATE_TIME, rotate_cb, self); } } static void stop_rotation_timer (BzFeaturedCarousel *self) { if (self->rotation_timer_id != 0) { g_source_remove (self->rotation_timer_id); self->rotation_timer_id = 0; } } static void maybe_start_rotation_timer (BzFeaturedCarousel *self) { if (!adw_get_enable_animations (GTK_WIDGET (self))) { stop_rotation_timer (self); return; } if (self->model != NULL && g_list_model_get_n_items (self->model) > 0 && gtk_widget_get_mapped (GTK_WIDGET (self))) start_rotation_timer (self); } static void carousel_notify_position_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (user_data); stop_rotation_timer (self); maybe_start_rotation_timer (self); } static void carousel_notify_settings_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (user_data); maybe_start_rotation_timer (self); } static void next_button_clicked_cb (GtkButton *button, gpointer user_data) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (user_data); show_relative_page (self, +1, FALSE); } static void previous_button_clicked_cb (GtkButton *button, gpointer user_data) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (user_data); show_relative_page (self, -1, FALSE); } static void tile_clicked_cb (BzFeaturedTile *tile, gpointer user_data) { BzFeaturedCarousel *self; BzEntryGroup *group; self = BZ_FEATURED_CAROUSEL (user_data); group = bz_featured_tile_get_group (tile); g_signal_emit (self, signals[SIGNAL_GROUP_CLICKED], 0, group); } static gboolean key_pressed_cb (GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, BzFeaturedCarousel *self) { if (gtk_widget_is_visible (GTK_WIDGET (self->previous_button)) && gtk_widget_is_sensitive (GTK_WIDGET (self->previous_button)) && ((gtk_widget_get_direction (GTK_WIDGET (self->previous_button)) == GTK_TEXT_DIR_LTR && keyval == GDK_KEY_Left) || (gtk_widget_get_direction (GTK_WIDGET (self->previous_button)) == GTK_TEXT_DIR_RTL && keyval == GDK_KEY_Right))) { gtk_widget_activate (GTK_WIDGET (self->previous_button)); return GDK_EVENT_STOP; } if (gtk_widget_is_visible (GTK_WIDGET (self->next_button)) && gtk_widget_is_sensitive (GTK_WIDGET (self->next_button)) && ((gtk_widget_get_direction (GTK_WIDGET (self->next_button)) == GTK_TEXT_DIR_LTR && keyval == GDK_KEY_Right) || (gtk_widget_get_direction (GTK_WIDGET (self->next_button)) == GTK_TEXT_DIR_RTL && keyval == GDK_KEY_Left))) { gtk_widget_activate (GTK_WIDGET (self->next_button)); return GDK_EVENT_STOP; } return GDK_EVENT_PROPAGATE; } static void rebuild_carousel (BzFeaturedCarousel *self) { guint n_items; stop_rotation_timer (self); while (adw_carousel_get_n_pages (self->carousel) > 0) adw_carousel_remove (self->carousel, adw_carousel_get_nth_page (self->carousel, 0)); if (self->model == NULL) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); gtk_widget_set_visible (GTK_WIDGET (self->next_button), FALSE); gtk_widget_set_visible (GTK_WIDGET (self->previous_button), FALSE); return; } n_items = g_list_model_get_n_items (self->model); gtk_widget_set_visible (GTK_WIDGET (self), n_items > 0); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntryGroup) group = NULL; BzFeaturedTile *tile; group = g_list_model_get_item (self->model, i); tile = bz_featured_tile_new (group); bz_featured_tile_set_is_aotd (tile, self->is_aotd && (i == 0)); gtk_widget_set_hexpand (GTK_WIDGET (tile), TRUE); gtk_widget_set_vexpand (GTK_WIDGET (tile), TRUE); gtk_widget_set_can_focus (GTK_WIDGET (tile), FALSE); g_signal_connect (tile, "clicked", G_CALLBACK (tile_clicked_cb), self); adw_carousel_append (self->carousel, GTK_WIDGET (tile)); } gtk_widget_set_visible (GTK_WIDGET (self->next_button), n_items > 1); gtk_widget_set_visible (GTK_WIDGET (self->previous_button), n_items > 1); maybe_start_rotation_timer (self); } static void model_items_changed_cb (BzFeaturedCarousel *self, guint position, guint removed, guint added, GListModel *model) { rebuild_carousel (self); } static void bz_featured_carousel_map (GtkWidget *widget) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (widget); GTK_WIDGET_CLASS (bz_featured_carousel_parent_class)->map (widget); maybe_start_rotation_timer (self); } static void bz_featured_carousel_unmap (GtkWidget *widget) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (widget); stop_rotation_timer (self); GTK_WIDGET_CLASS (bz_featured_carousel_parent_class)->unmap (widget); } static void bz_featured_carousel_dispose (GObject *object) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, model_items_changed_cb, self); stop_rotation_timer (self); g_clear_signal_handler (&self->settings_notify_id, gtk_widget_get_settings (GTK_WIDGET (self))); g_clear_object (&self->model); G_OBJECT_CLASS (bz_featured_carousel_parent_class)->dispose (object); } static void bz_featured_carousel_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_featured_carousel_get_model (self)); break; case PROP_IS_AOTD: g_value_set_boolean (value, bz_featured_carousel_get_is_aotd (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void bz_featured_carousel_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFeaturedCarousel *self; self = BZ_FEATURED_CAROUSEL (object); switch (prop_id) { case PROP_MODEL: bz_featured_carousel_set_model (self, g_value_get_object (value)); break; case PROP_IS_AOTD: bz_featured_carousel_set_is_aotd (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void bz_featured_carousel_class_init (BzFeaturedCarouselClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->get_property = bz_featured_carousel_get_property; object_class->set_property = bz_featured_carousel_set_property; object_class->dispose = bz_featured_carousel_dispose; widget_class->map = bz_featured_carousel_map; widget_class->unmap = bz_featured_carousel_unmap; props[PROP_MODEL] = g_param_spec_object ("model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); props[PROP_IS_AOTD] = g_param_spec_boolean ("is-aotd", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_GROUP_CLICKED] = g_signal_new ("group-clicked", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-featured-carousel.ui"); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GROUP); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, carousel); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, next_button); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, previous_button); gtk_widget_class_bind_template_child (widget_class, BzFeaturedCarousel, dots); gtk_widget_class_bind_template_callback (widget_class, carousel_notify_position_cb); gtk_widget_class_bind_template_callback (widget_class, next_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, previous_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, key_pressed_cb); } static void bz_featured_carousel_init (BzFeaturedCarousel *self) { GtkSettings *settings; gtk_widget_init_template (GTK_WIDGET (self)); adw_carousel_set_allow_scroll_wheel (self->carousel, FALSE); settings = gtk_widget_get_settings (GTK_WIDGET (self)); self->settings_notify_id = g_signal_connect (settings, "notify::gtk-enable-animations", G_CALLBACK (carousel_notify_settings_cb), self); } BzFeaturedCarousel * bz_featured_carousel_new (void) { return g_object_new (BZ_TYPE_FEATURED_CAROUSEL, NULL); } GListModel * bz_featured_carousel_get_model (BzFeaturedCarousel *self) { g_return_val_if_fail (BZ_IS_FEATURED_CAROUSEL (self), NULL); return self->model; } void bz_featured_carousel_set_model (BzFeaturedCarousel *self, GListModel *model) { g_return_if_fail (BZ_IS_FEATURED_CAROUSEL (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); if (model != NULL && model == self->model) return; if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, model_items_changed_cb, self); g_set_object (&self->model, model); if (model != NULL) g_signal_connect_swapped (model, "items-changed", G_CALLBACK (model_items_changed_cb), self); rebuild_carousel (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } gboolean bz_featured_carousel_get_is_aotd (BzFeaturedCarousel *self) { g_return_val_if_fail (BZ_IS_FEATURED_CAROUSEL (self), FALSE); return self->is_aotd; } void bz_featured_carousel_set_is_aotd (BzFeaturedCarousel *self, gboolean is_aotd) { g_return_if_fail (BZ_IS_FEATURED_CAROUSEL (self)); if (self->is_aotd == is_aotd) return; self->is_aotd = is_aotd; rebuild_carousel (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_AOTD]); } kolunmi-bazaar-7b9c8e1/src/bz-featured-carousel.h000066400000000000000000000026611514314607700220520ustar00rootroot00000000000000/* bz-featured-carousel.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_FEATURED_CAROUSEL (bz_featured_carousel_get_type ()) G_DECLARE_FINAL_TYPE (BzFeaturedCarousel, bz_featured_carousel, BZ, FEATURED_CAROUSEL, GtkBox) BzFeaturedCarousel *bz_featured_carousel_new (void); GListModel *bz_featured_carousel_get_model (BzFeaturedCarousel *self); void bz_featured_carousel_set_model (BzFeaturedCarousel *self, GListModel *model); gboolean bz_featured_carousel_get_is_aotd (BzFeaturedCarousel *self); void bz_featured_carousel_set_is_aotd (BzFeaturedCarousel *self, gboolean is_aotd); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-featured-tile.blp000066400000000000000000000044611514314607700215200ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFeaturedTile: Button { styles [ "featured-tile", ] Overlay { [overlay] Image { halign: end; valign: start; icon-name: "app-installed-symbolic"; icon-size: normal; visible: bind template.group as <$BzEntryGroup>.removable; margin-top: 12; margin-end: 12; } Box content_box { halign: center; orientation: horizontal; margin-start: 10; margin-end: 10; Box { orientation: vertical; valign: center; margin-top: 50; margin-bottom: 50; Image image { paintable: bind template.group as <$BzEntryGroup>.icon-paintable; margin-bottom: 12; pixel-size: 128; styles [ "icon-dropshadow", ] } Label title { xalign: 0.5; halign: center; ellipsize: end; label: bind template.group as <$BzEntryGroup>.title; styles [ "title-1", ] } Adw.Clamp { maximum-size: 350; tightening-threshold: 350; Box { orientation: vertical; Label description { ellipsize: end; xalign: 0.5; lines: 1; justify: center; label: bind template.group as <$BzEntryGroup>.description; styles [ "caption", ] } Box { spacing: 4; halign: center; margin-top: 4; visible: bind template.is-aotd; Image { icon-name: "starred-symbolic"; pixel-size: 12; } Label { ellipsize: end; xalign: 0.5; lines: 1; justify: center; label: _("App of the Day"); styles [ "caption", ] } } } } } $BzScreenshot screenshot { visible: bind $invert_boolean(template.narrow) as ; paintable: bind template.first-screenshot; rounded-corners: true; top-half: true; valign: end; margin-top: 20; } } } } kolunmi-bazaar-7b9c8e1/src/bz-featured-tile.c000066400000000000000000000370511514314607700211660ustar00rootroot00000000000000/* bz-featured-tile.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-featured-tile.h" #include "bz-entry.h" #include "bz-group-tile-css-watcher.h" #include "bz-screenshot.h" #include "bz-util.h" #define BZ_TYPE_FEATURED_TILE_LAYOUT (bz_featured_tile_layout_get_type ()) G_DECLARE_FINAL_TYPE (BzFeaturedTileLayout, bz_featured_tile_layout, BZ, FEATURED_TILE_LAYOUT, GtkLayoutManager) struct _BzFeaturedTileLayout { GtkLayoutManager parent_instance; gboolean narrow_mode; GtkWidget *content_box; int last_width; }; G_DEFINE_FINAL_TYPE (BzFeaturedTileLayout, bz_featured_tile_layout, GTK_TYPE_LAYOUT_MANAGER) enum { LAYOUT_SIGNAL_NARROW_MODE_CHANGED, LAYOUT_SIGNAL_LAST }; static guint layout_signals[LAYOUT_SIGNAL_LAST] = { 0 }; static void bz_featured_tile_layout_measure (GtkLayoutManager *layout_manager, GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { GtkWidget *child; *minimum = 0; *natural = 0; *minimum_baseline = -1; *natural_baseline = -1; for (child = gtk_widget_get_first_child (widget); child != NULL; child = gtk_widget_get_next_sibling (child)) { int child_min; int child_nat; if (!gtk_widget_should_layout (child)) continue; gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, NULL, NULL); *minimum = MAX (*minimum, child_min); *natural = MAX (*natural, child_nat); } } static void bz_featured_tile_layout_allocate (GtkLayoutManager *layout_manager, GtkWidget *widget, gint width, gint height, gint baseline) { BzFeaturedTileLayout *self; GtkWidget *child; gboolean narrow_mode; int spacing; const int NARROW_THRESHOLD = 950; const int MIN_SPACING = 15; const int MAX_SPACING = 128; const int MAX_WIDTH = 1300; self = BZ_FEATURED_TILE_LAYOUT (layout_manager); narrow_mode = (width < NARROW_THRESHOLD); if (self->content_box != NULL && self->last_width != width) { self->last_width = width; if (narrow_mode) { spacing = 100; } else { if (width < NARROW_THRESHOLD) spacing = MIN_SPACING; else if (width >= MAX_WIDTH) spacing = MAX_SPACING; else spacing = MIN_SPACING + ((width - NARROW_THRESHOLD) * (MAX_SPACING - MIN_SPACING)) / (MAX_WIDTH - NARROW_THRESHOLD); } gtk_box_set_spacing (GTK_BOX (self->content_box), spacing); } for (child = gtk_widget_get_first_child (widget); child != NULL; child = gtk_widget_get_next_sibling (child)) { if (gtk_widget_should_layout (child)) gtk_widget_allocate (child, width, height, -1, NULL); } if (self->narrow_mode != narrow_mode) { self->narrow_mode = narrow_mode; g_signal_emit (self, layout_signals[LAYOUT_SIGNAL_NARROW_MODE_CHANGED], 0, self->narrow_mode); } } static void bz_featured_tile_layout_class_init (BzFeaturedTileLayoutClass *klass) { GtkLayoutManagerClass *layout_manager_class; layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass); layout_manager_class->measure = bz_featured_tile_layout_measure; layout_manager_class->allocate = bz_featured_tile_layout_allocate; layout_signals[LAYOUT_SIGNAL_NARROW_MODE_CHANGED] = g_signal_new ("narrow-mode-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } static void bz_featured_tile_layout_init (BzFeaturedTileLayout *self) { self->last_width = -1; } struct _BzFeaturedTile { GtkButton parent_instance; BzEntryGroup *group; gboolean narrow_mode; gboolean is_aotd; guint refresh_id; BzGroupTileCssWatcher *css; GtkWidget *stack; GtkWidget *image; GtkWidget *title; GtkWidget *description; GtkWidget *screenshot; GtkWidget *content_box; GdkPaintable *first_screenshot; gboolean has_screenshot; DexFuture *ui_entry_resolve; }; G_DEFINE_FINAL_TYPE (BzFeaturedTile, bz_featured_tile, GTK_TYPE_BUTTON) enum { PROP_0, PROP_GROUP, PROP_FIRST_SCREENSHOT, PROP_HAS_SCREENSHOT, PROP_NARROW, PROP_IS_AOTD, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL, }; static void bz_featured_tile_refresh (BzFeaturedTile *self); static void update_screenshot (BzFeaturedTile *self); static gboolean bz_featured_tile_refresh_idle_cb (GWeakRef *wr) { g_autoptr (BzFeaturedTile) self = NULL; self = g_weak_ref_get (wr); if (self == NULL) goto done; self->refresh_id = 0; bz_featured_tile_refresh (self); done: return G_SOURCE_REMOVE; } static void schedule_refresh (BzFeaturedTile *self) { if (self->refresh_id != 0) return; self->refresh_id = g_idle_add_full ( G_PRIORITY_DEFAULT, (GSourceFunc) bz_featured_tile_refresh_idle_cb, bz_track_weak (self), bz_weak_release); } static void bz_featured_tile_layout_narrow_mode_changed_cb (GtkLayoutManager *layout_manager, gboolean narrow_mode, gpointer user_data) { BzFeaturedTile *self; self = BZ_FEATURED_TILE (user_data); if (self->narrow_mode != narrow_mode) { self->narrow_mode = narrow_mode; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NARROW]); schedule_refresh (self); } } static inline void notify_properties (BzFeaturedTile *self, gboolean has_screenshot) { if (self->has_screenshot != has_screenshot) { self->has_screenshot = has_screenshot; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_SCREENSHOT]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FIRST_SCREENSHOT]); } static DexFuture * ui_entry_resolved_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzFeaturedTile) self = NULL; const GValue *value = NULL; gboolean has_screenshot = FALSE; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); if (value != NULL) { BzEntry *ui_entry = NULL; g_autoptr (GListModel) screenshots = NULL; ui_entry = g_value_get_object (value); g_object_get (ui_entry, "screenshot-paintables", &screenshots, NULL); if (screenshots != NULL && g_list_model_get_n_items (screenshots) > 0) { self->first_screenshot = g_list_model_get_item (screenshots, 0); has_screenshot = TRUE; } } dex_clear (&self->ui_entry_resolve); notify_properties (self, has_screenshot); return NULL; } /* FIXME: duplicate code from rich-app-tile */ static void update_screenshot (BzFeaturedTile *self) { g_autoptr (BzResult) ui_entry_result = NULL; g_autoptr (GListModel) screenshots = NULL; dex_clear (&self->ui_entry_resolve); g_clear_object (&self->first_screenshot); if (self->group == NULL) { notify_properties (self, FALSE); return; } ui_entry_result = bz_entry_group_dup_ui_entry (self->group); self->ui_entry_resolve = dex_future_finally ( bz_result_dup_future (ui_entry_result), (DexFutureCallback) ui_entry_resolved_finally, bz_track_weak (self), bz_weak_release); } static void bz_featured_tile_refresh (BzFeaturedTile *self) { gtk_label_set_wrap (GTK_LABEL (self->description), self->narrow_mode); gtk_label_set_lines (GTK_LABEL (self->description), self->narrow_mode ? 2 : 1); update_screenshot (self); } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static int get_start_margin (gpointer object, gboolean narrow) { return narrow ? 20 : 50; } static void bz_featured_tile_dispose (GObject *object) { BzFeaturedTile *self; self = BZ_FEATURED_TILE (object); g_clear_handle_id (&self->refresh_id, g_source_remove); if (self->group != NULL) g_signal_handlers_disconnect_by_func (self->group, schedule_refresh, self); g_clear_object (&self->group); g_clear_object (&self->css); g_clear_object (&self->first_screenshot); G_OBJECT_CLASS (bz_featured_tile_parent_class)->dispose (object); } static void bz_featured_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFeaturedTile *self; self = BZ_FEATURED_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_featured_tile_get_group (self)); break; case PROP_FIRST_SCREENSHOT: g_value_set_object (value, self->first_screenshot); break; case PROP_HAS_SCREENSHOT: g_value_set_boolean (value, self->has_screenshot); break; case PROP_NARROW: g_value_set_boolean (value, self->narrow_mode); break; case PROP_IS_AOTD: g_value_set_boolean (value, bz_featured_tile_get_is_aotd (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void bz_featured_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFeaturedTile *self; self = BZ_FEATURED_TILE (object); switch (prop_id) { case PROP_GROUP: bz_featured_tile_set_group (self, g_value_get_object (value)); break; case PROP_IS_AOTD: bz_featured_tile_set_is_aotd (self, g_value_get_boolean (value)); break; case PROP_FIRST_SCREENSHOT: case PROP_HAS_SCREENSHOT: case PROP_NARROW: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void bz_featured_tile_class_init (BzFeaturedTileClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_featured_tile_dispose; object_class->get_property = bz_featured_tile_get_property; object_class->set_property = bz_featured_tile_set_property; props[PROP_GROUP] = g_param_spec_object ("group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); props[PROP_FIRST_SCREENSHOT] = g_param_spec_object ("first-screenshot", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_HAS_SCREENSHOT] = g_param_spec_boolean ("has-screenshot", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_NARROW] = g_param_spec_boolean ("narrow", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_IS_AOTD] = g_param_spec_boolean ("is-aotd", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_SCREENSHOT); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-featured-tile.ui"); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, get_start_margin); gtk_widget_class_bind_template_child (widget_class, BzFeaturedTile, image); gtk_widget_class_bind_template_child (widget_class, BzFeaturedTile, title); gtk_widget_class_bind_template_child (widget_class, BzFeaturedTile, description); gtk_widget_class_bind_template_child (widget_class, BzFeaturedTile, screenshot); gtk_widget_class_bind_template_child (widget_class, BzFeaturedTile, content_box); gtk_widget_class_set_css_name (widget_class, "featured-tile"); gtk_widget_class_set_layout_manager_type (widget_class, BZ_TYPE_FEATURED_TILE_LAYOUT); } static void bz_featured_tile_init (BzFeaturedTile *self) { GtkLayoutManager *layout_manager; BzFeaturedTileLayout *tile_layout; gtk_widget_init_template (GTK_WIDGET (self)); self->css = bz_group_tile_css_watcher_new (); bz_group_tile_css_watcher_set_widget (self->css, GTK_WIDGET (self)); layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self)); g_warn_if_fail (layout_manager != NULL); tile_layout = BZ_FEATURED_TILE_LAYOUT (layout_manager); tile_layout->content_box = self->content_box; g_signal_connect_object (layout_manager, "narrow-mode-changed", G_CALLBACK (bz_featured_tile_layout_narrow_mode_changed_cb), self, 0); } BzFeaturedTile * bz_featured_tile_new (BzEntryGroup *group) { return g_object_new (BZ_TYPE_FEATURED_TILE, "group", group, NULL); } BzEntryGroup * bz_featured_tile_get_group (BzFeaturedTile *self) { g_return_val_if_fail (BZ_IS_FEATURED_TILE (self), NULL); return self->group; } void bz_featured_tile_set_group (BzFeaturedTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_FEATURED_TILE (self)); g_return_if_fail (group == NULL || BZ_IS_ENTRY_GROUP (group)); g_clear_handle_id (&self->refresh_id, g_source_remove); if (self->group != NULL) g_signal_handlers_disconnect_by_func (self->group, schedule_refresh, self); g_clear_object (&self->group); if (group != NULL) { self->group = g_object_ref (group); g_signal_connect_swapped (group, "notify", G_CALLBACK (schedule_refresh), self); schedule_refresh (self); } bz_group_tile_css_watcher_set_group (self->css, group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } gboolean bz_featured_tile_get_is_aotd (BzFeaturedTile *self) { g_return_val_if_fail (BZ_IS_FEATURED_TILE (self), FALSE); return self->is_aotd; } void bz_featured_tile_set_is_aotd (BzFeaturedTile *self, gboolean is_aotd) { g_return_if_fail (BZ_IS_FEATURED_TILE (self)); if (self->is_aotd == is_aotd) return; self->is_aotd = is_aotd; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_AOTD]); } kolunmi-bazaar-7b9c8e1/src/bz-featured-tile.h000066400000000000000000000026211514314607700211660ustar00rootroot00000000000000/* bz-featured-tile.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include G_BEGIN_DECLS #define BZ_TYPE_FEATURED_TILE (bz_featured_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzFeaturedTile, bz_featured_tile, BZ, FEATURED_TILE, GtkButton) BzFeaturedTile *bz_featured_tile_new (BzEntryGroup *group); BzEntryGroup *bz_featured_tile_get_group (BzFeaturedTile *self); void bz_featured_tile_set_group (BzFeaturedTile *self, BzEntryGroup *group); gboolean bz_featured_tile_get_is_aotd (BzFeaturedTile *self); void bz_featured_tile_set_is_aotd (BzFeaturedTile *self, gboolean is_aotd); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-flathub-auth-provider.txt000066400000000000000000000002511514314607700232350ustar00rootroot00000000000000prefix=bz name=flathub_auth_provider parent-prefix=g parent-name=object author=AUTOGEN property=method char G_TYPE_STRING string property=name char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-flathub-category-section.blp000066400000000000000000000021341514314607700236630ustar00rootroot00000000000000using Gtk 4.0; template $BzFlathubCategorySection : Box { orientation: vertical; spacing: 10; visible: bind $invert_boolean($is_null(template.category as <$BzFlathubCategory>) as ) as ; margin-bottom: 12; Label section_title { styles [ "title-1", ] visible: bind $invert_boolean(template.category as <$BzFlathubCategory>.is-spotlight) as ; xalign: 0.0; hexpand: true; margin-start: 3; margin-end: 3; margin-bottom: 5; ellipsize: end; } $BzDynamicListView section_list { styles [ "flathub-page-section", ] hexpand: true; scroll: false; noscroll-kind: flow-box; child-type: "BzAppTile"; child-prop: "group"; row-spacing: bind $get_spacing(template.compact) as ; column-spacing: bind $get_spacing(template.compact) as ; bind-widget => $bind_widget_cb(); unbind-widget => $unbind_widget_cb(); } Button more_button { styles [ "pill", ] can-shrink: true; halign: center; valign: center; margin-top: 5; clicked => $on_more_button_clicked(); } }kolunmi-bazaar-7b9c8e1/src/bz-flathub-category-section.c000066400000000000000000000263101514314607700233320ustar00rootroot00000000000000/* bz-flathub-category-section.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-apps-page.h" #include "bz-entry-group.h" #include "bz-flathub-category-section.h" #include "bz-flathub-category.h" #include "bz-flathub-page.h" struct _BzFlathubCategorySection { GtkBox parent_instance; GtkLabel *section_title; GtkWidget *section_list; GtkButton *more_button; BzFlathubCategory *category; gboolean compact; guint min_items; GtkSliceListModel *slice_model; }; G_DEFINE_FINAL_TYPE (BzFlathubCategorySection, bz_flathub_category_section, GTK_TYPE_BOX) enum { PROP_0, PROP_CATEGORY, PROP_COMPACT, PROP_MIN_ITEMS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_GROUP_SELECTED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void apps_page_select_cb_forwarding (BzFlathubPage *flathub_page, BzEntryGroup *group, BzAppsPage *page) { g_signal_emit_by_name (flathub_page, "group-selected", group); } static void tile_clicked (BzEntryGroup *group, GtkButton *button) { BzFlathubCategorySection *self = NULL; self = BZ_FLATHUB_CATEGORY_SECTION (gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_FLATHUB_CATEGORY_SECTION)); if (self != NULL) g_signal_emit (self, signals[SIGNAL_GROUP_SELECTED], 0, group); } static void on_more_button_clicked (GtkButton *button, BzFlathubCategorySection *self) { GtkWidget *flathub_page = NULL; GtkWidget *nav_view = NULL; AdwNavigationPage *apps_page = NULL; if (self->category == NULL) return; flathub_page = gtk_widget_get_ancestor (GTK_WIDGET (self), BZ_TYPE_FLATHUB_PAGE); if (flathub_page == NULL) return; nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); if (nav_view == NULL) return; apps_page = bz_apps_page_new_from_category (self->category); if (apps_page == NULL) return; g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb_forwarding), flathub_page); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void bind_widget_cb (BzFlathubCategorySection *self, GtkWidget *tile, BzEntryGroup *group, GtkWidget *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (tile_clicked), group); } static void unbind_widget_cb (BzFlathubCategorySection *self, GtkWidget *tile, BzEntryGroup *group, GtkWidget *view) { g_signal_handlers_disconnect_by_func (tile, G_CALLBACK (tile_clicked), group); } static int get_spacing (gpointer object, gboolean compact) { return compact ? 3 : 5; } static void update_model (BzFlathubCategorySection *self) { GtkExpression *expression; guint max_items; if (self->category == NULL) return; max_items = self->compact ? 6 : 12; max_items = MAX (max_items, self->min_items); if (self->slice_model != NULL) { gtk_slice_list_model_set_size (self->slice_model, max_items); return; } expression = gtk_property_expression_new (BZ_TYPE_FLATHUB_CATEGORY, NULL, "applications"); self->slice_model = gtk_slice_list_model_new (NULL, 0, max_items); gtk_expression_bind (expression, self->slice_model, "model", self->category); g_object_set (self->section_list, "model", self->slice_model, NULL); } static void bz_flathub_category_section_dispose (GObject *object) { BzFlathubCategorySection *self = BZ_FLATHUB_CATEGORY_SECTION (object); g_clear_object (&self->category); g_clear_object (&self->slice_model); G_OBJECT_CLASS (bz_flathub_category_section_parent_class)->dispose (object); } static void bz_flathub_category_section_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFlathubCategorySection *self = BZ_FLATHUB_CATEGORY_SECTION (object); switch (prop_id) { case PROP_CATEGORY: g_value_set_object (value, bz_flathub_category_section_get_category (self)); break; case PROP_COMPACT: g_value_set_boolean (value, bz_flathub_category_section_get_compact (self)); break; case PROP_MIN_ITEMS: g_value_set_uint (value, bz_flathub_category_section_get_min_items (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_category_section_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFlathubCategorySection *self = BZ_FLATHUB_CATEGORY_SECTION (object); switch (prop_id) { case PROP_CATEGORY: bz_flathub_category_section_set_category (self, g_value_get_object (value)); break; case PROP_COMPACT: bz_flathub_category_section_set_compact (self, g_value_get_boolean (value)); break; case PROP_MIN_ITEMS: bz_flathub_category_section_set_min_items (self, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static void bz_flathub_category_section_class_init (BzFlathubCategorySectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_flathub_category_section_dispose; object_class->get_property = bz_flathub_category_section_get_property; object_class->set_property = bz_flathub_category_section_set_property; props[PROP_CATEGORY] = g_param_spec_object ( "category", NULL, NULL, BZ_TYPE_FLATHUB_CATEGORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_COMPACT] = g_param_spec_boolean ( "compact", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MIN_ITEMS] = g_param_spec_uint ( "min-items", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_GROUP_SELECTED] = g_signal_new ( "group-selected", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_signal_set_va_marshaller ( signals[SIGNAL_GROUP_SELECTED], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-flathub-category-section.ui"); gtk_widget_class_bind_template_child (widget_class, BzFlathubCategorySection, section_title); gtk_widget_class_bind_template_child (widget_class, BzFlathubCategorySection, section_list); gtk_widget_class_bind_template_child (widget_class, BzFlathubCategorySection, more_button); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, on_more_button_clicked); gtk_widget_class_bind_template_callback (widget_class, bind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, get_spacing); } static void bz_flathub_category_section_init (BzFlathubCategorySection *self) { self->compact = FALSE; self->min_items = 0; gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_flathub_category_section_new (void) { return g_object_new (BZ_TYPE_FLATHUB_CATEGORY_SECTION, NULL); } void bz_flathub_category_section_set_category (BzFlathubCategorySection *self, BzFlathubCategory *category) { const char *display_name; g_autofree char *more_label = NULL; g_return_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self)); g_return_if_fail (category == NULL || BZ_IS_FLATHUB_CATEGORY (category)); if (self->category == category) return; g_clear_object (&self->category); g_clear_object (&self->slice_model); if (category != NULL) { self->category = g_object_ref (category); display_name = bz_flathub_category_get_display_name (category); gtk_label_set_text (self->section_title, display_name); more_label = g_strdup (bz_flathub_category_get_more_of_name (category)); gtk_button_set_label (self->more_button, more_label); update_model (self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORY]); } BzFlathubCategory * bz_flathub_category_section_get_category (BzFlathubCategorySection *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self), NULL); return self->category; } void bz_flathub_category_section_set_compact (BzFlathubCategorySection *self, gboolean compact) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self)); if (self->compact == compact) return; self->compact = compact; update_model (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COMPACT]); } gboolean bz_flathub_category_section_get_compact (BzFlathubCategorySection *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self), FALSE); return self->compact; } void bz_flathub_category_section_set_min_items (BzFlathubCategorySection *self, guint min_items) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self)); if (self->min_items == min_items) return; self->min_items = min_items; update_model (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MIN_ITEMS]); } guint bz_flathub_category_section_get_min_items (BzFlathubCategorySection *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY_SECTION (self), 0); return self->min_items; } kolunmi-bazaar-7b9c8e1/src/bz-flathub-category-section.h000066400000000000000000000035241514314607700233410ustar00rootroot00000000000000/* bz-flathub-category-section.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-flathub-category.h" #include G_BEGIN_DECLS #define BZ_TYPE_FLATHUB_CATEGORY_SECTION (bz_flathub_category_section_get_type ()) G_DECLARE_FINAL_TYPE (BzFlathubCategorySection, bz_flathub_category_section, BZ, FLATHUB_CATEGORY_SECTION, GtkBox) GtkWidget *bz_flathub_category_section_new (void); void bz_flathub_category_section_set_category (BzFlathubCategorySection *self, BzFlathubCategory *category); BzFlathubCategory *bz_flathub_category_section_get_category (BzFlathubCategorySection *self); void bz_flathub_category_section_set_compact (BzFlathubCategorySection *self, gboolean compact); gboolean bz_flathub_category_section_get_compact (BzFlathubCategorySection *self); void bz_flathub_category_section_set_min_items (BzFlathubCategorySection *self, guint min_items); guint bz_flathub_category_section_get_min_items (BzFlathubCategorySection *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-flathub-category.c000066400000000000000000000575241514314607700217030ustar00rootroot00000000000000/* bz-flathub-category.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "appstream.h" #include "bz-flathub-category.h" #include "bz-flathub-sub-category.h" #include "bz-serializable.h" struct _BzFlathubCategory { GObject parent_instance; BzApplicationMapFactory *map_factory; char *name; GListModel *applications; GListModel *quality_applications; int total_entries; gboolean is_spotlight; GListModel *subcategories; }; static void serializable_iface_init (BzSerializableInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzFlathubCategory, bz_flathub_category, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (BZ_TYPE_SERIALIZABLE, serializable_iface_init)); enum { PROP_0, PROP_MAP_FACTORY, PROP_NAME, PROP_DISPLAY_NAME, PROP_SHORT_NAME, PROP_ICON_NAME, PROP_APPLICATIONS, PROP_QUALITY_APPLICATIONS, PROP_TOTAL_ENTRIES, PROP_IS_SPOTLIGHT, PROP_SUBCATEGORIES, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void clear (BzFlathubCategory *self); typedef struct { const char *id; const char *display_name; const char *short_name; const char *more_of_name; const char *icon_name; const void *subcategories; } CategoryInfo; typedef struct { const char *display_name; const char *category_id; } Subcategory; static const Subcategory audiovideo_subcategories[] = { { N_ ("Editing"), "AudioVideoEditing" }, { N_ ("Midi"), "Midi" }, { N_ ("Mixer"), "Mixer" }, { N_ ("Music"), "Music" }, { N_ ("Player"), "Player" }, { N_ ("Recorder"), "Recorder" }, { N_ ("Sequencer"), "Sequencer" }, { N_ ("Tuner"), "Tuner" }, { N_ ("TV"), "TV" }, { NULL, NULL } }; static const Subcategory game_subcategories[] = { { N_ ("Emulation"), "Emulator" }, { N_ ("Action"), "ActionGame" }, { N_ ("Adventure"), "AdventureGame" }, { N_ ("Arcade"), "ArcadeGame" }, { N_ ("Blocks"), "BlocksGame" }, { N_ ("Board"), "BoardGame" }, { N_ ("Card"), "CardGame" }, { N_ ("Kids"), "KidsGame" }, { N_ ("Logic"), "LogicGame" }, { N_ ("Role Playing"), "RolePlaying" }, { N_ ("Shooter"), "Shooter" }, { N_ ("Simulation"), "Simulation" }, { N_ ("Sports"), "SportsGame" }, { N_ ("Strategy"), "StrategyGame" }, { NULL, NULL } }; static const CategoryInfo category_info[] = { { "audiovideo", N_ ("Audio & Video"), N_ ("Media"), N_ ("More Audio & Video"), "io.github.kolumni.Bazaar.Audiovideo", audiovideo_subcategories }, { "development", N_ ("Developer Tools"), N_ ("Develop"), N_ ("More Developer Tools"), "io.github.kolumni.Bazaar.Develop", NULL }, { "education", N_ ("Education"), N_ ("Learn"), N_ ("More Education"), "io.github.kolumni.Bazaar.Learn", NULL }, { "game", N_ ("Gaming"), N_ ("Play"), N_ ("More Gaming"), "io.github.kolumni.Bazaar.Play", game_subcategories }, { "graphics", N_ ("Graphics & Photography"), N_ ("Create"), N_ ("More Graphics & Photography"), "io.github.kolumni.Bazaar.Create", NULL }, { "network", N_ ("Networking"), N_ ("Internet"), N_ ("More Networking"), "io.github.kolumni.Bazaar.Network", NULL }, { "office", N_ ("Productivity"), N_ ("Work"), N_ ("More Productivity"), "io.github.kolumni.Bazaar.Work", NULL }, { "science", N_ ("Science"), N_ ("Science"), N_ ("More Science"), "io.github.kolumni.Bazaar.Science", NULL }, { "system", N_ ("System"), N_ ("System"), N_ ("More System"), "io.github.kolumni.Bazaar.System", NULL }, { "utility", N_ ("Utilities"), N_ ("Tools"), N_ ("More Utilities"), "io.github.kolumni.Bazaar.Utilities", NULL }, { "trending", N_ ("Trending"), N_ ("Trending"), N_ ("More Trending"), "io.github.kolumni.Bazaar.Trending", NULL }, { "popular", N_ ("Popular"), N_ ("Popular"), N_ ("More Popular"), "io.github.kolumni.Bazaar.Popular", NULL }, { "recently-added", N_ ("Recently Added"), N_ ("New"), N_ ("More New"), "io.github.kolumni.Bazaar.New", NULL }, { "recently-updated", N_ ("Recently Updated"), N_ ("Updated"), N_ ("More Updated"), "io.github.kolumni.Bazaar.Updated", NULL }, { "mobile", N_ ("Mobile"), N_ ("Mobile"), N_ ("More Mobile"), "io.github.kolumni.Bazaar.Mobile", NULL }, { "adwaita", N_ ("Adwaita"), N_ ("Adwaita"), N_ ("More Adwaita"), "io.github.kolumni.Bazaar.Adwaita", NULL }, { "kde", N_ ("KDE Apps"), N_ ("KDE Apps"), N_ ("More KDE Apps"), "io.github.kolumni.Bazaar.Kde", NULL }, { NULL, NULL, NULL, NULL, NULL, NULL } }; static const CategoryInfo * get_category_info (const char *category_id) { for (int i = 0; category_info[i].id != NULL; i++) { if (g_strcmp0 (category_info[i].id, category_id) == 0) return &category_info[i]; } return NULL; } static GListModel * create_subcategories (const Subcategory *subcategories) { GListStore *store; store = g_list_store_new (BZ_TYPE_FLATHUB_SUB_CATEGORY); for (gsize i = 0; subcategories[i].display_name != NULL; i++) g_list_store_append (store, g_object_new (BZ_TYPE_FLATHUB_SUB_CATEGORY, "name", _(subcategories[i].display_name), "id", subcategories[i].category_id, NULL)); return G_LIST_MODEL (store); } static void bz_flathub_category_dispose (GObject *object) { BzFlathubCategory *self = BZ_FLATHUB_CATEGORY (object); clear (self); G_OBJECT_CLASS (bz_flathub_category_parent_class)->dispose (object); } static void bz_flathub_category_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFlathubCategory *self = BZ_FLATHUB_CATEGORY (object); switch (prop_id) { case PROP_MAP_FACTORY: g_value_set_object (value, bz_flathub_category_get_map_factory (self)); break; case PROP_NAME: g_value_set_string (value, bz_flathub_category_get_name (self)); break; case PROP_APPLICATIONS: g_value_take_object (value, bz_flathub_category_dup_applications (self)); break; case PROP_QUALITY_APPLICATIONS: g_value_take_object (value, bz_flathub_category_dup_quality_applications (self)); break; case PROP_DISPLAY_NAME: g_value_set_string (value, bz_flathub_category_get_display_name (self)); break; case PROP_SHORT_NAME: g_value_set_string (value, bz_flathub_category_get_short_name (self)); break; case PROP_ICON_NAME: g_value_set_string (value, bz_flathub_category_get_icon_name (self)); break; case PROP_TOTAL_ENTRIES: g_value_set_int (value, bz_flathub_category_get_total_entries (self)); break; case PROP_IS_SPOTLIGHT: g_value_set_boolean (value, bz_flathub_category_get_is_spotlight (self)); break; case PROP_SUBCATEGORIES: g_value_set_object (value, bz_flathub_category_get_subcategories (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_category_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFlathubCategory *self = BZ_FLATHUB_CATEGORY (object); switch (prop_id) { case PROP_MAP_FACTORY: bz_flathub_category_set_map_factory (self, g_value_get_object (value)); break; case PROP_NAME: bz_flathub_category_set_name (self, g_value_get_string (value)); break; case PROP_APPLICATIONS: bz_flathub_category_set_applications (self, g_value_get_object (value)); break; case PROP_QUALITY_APPLICATIONS: bz_flathub_category_set_quality_applications (self, g_value_get_object (value)); break; case PROP_TOTAL_ENTRIES: bz_flathub_category_set_total_entries (self, g_value_get_int (value)); break; case PROP_IS_SPOTLIGHT: bz_flathub_category_set_is_spotlight (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_category_class_init (BzFlathubCategoryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_flathub_category_set_property; object_class->get_property = bz_flathub_category_get_property; object_class->dispose = bz_flathub_category_dispose; props[PROP_MAP_FACTORY] = g_param_spec_object ( "map-factory", NULL, NULL, BZ_TYPE_APPLICATION_MAP_FACTORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_NAME] = g_param_spec_string ( "name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_DISPLAY_NAME] = g_param_spec_string ( "display-name", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_SHORT_NAME] = g_param_spec_string ( "short-name", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_ICON_NAME] = g_param_spec_string ( "icon-name", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_APPLICATIONS] = g_param_spec_object ( "applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_QUALITY_APPLICATIONS] = g_param_spec_object ( "quality-applications", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TOTAL_ENTRIES] = g_param_spec_int ( "total-entries", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_IS_SPOTLIGHT] = g_param_spec_boolean ( "is-spotlight", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SUBCATEGORIES] = g_param_spec_object ( "subcategories", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_flathub_category_init (BzFlathubCategory *self) { } static void bz_flathub_category_real_serialize (BzSerializable *serializable, GVariantBuilder *builder) { BzFlathubCategory *self = BZ_FLATHUB_CATEGORY (serializable); if (self->name != NULL) g_variant_builder_add (builder, "{sv}", "name", g_variant_new_string (self->name)); if (self->applications != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (self->applications); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (self->applications, i); g_variant_builder_add (sub_builder, "s", gtk_string_object_get_string (string)); } g_variant_builder_add (builder, "{sv}", "applications", g_variant_builder_end (sub_builder)); } } if (self->quality_applications != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (self->quality_applications); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) string = NULL; string = g_list_model_get_item (self->quality_applications, i); g_variant_builder_add (sub_builder, "s", gtk_string_object_get_string (string)); } g_variant_builder_add (builder, "{sv}", "quality-applications", g_variant_builder_end (sub_builder)); } } g_variant_builder_add (builder, "{sv}", "total-entries", g_variant_new_int32 (self->total_entries)); g_variant_builder_add (builder, "{sv}", "is-spotlight", g_variant_new_boolean (self->is_spotlight)); } static gboolean bz_flathub_category_real_deserialize (BzSerializable *serializable, GVariant *import, GError **error) { BzFlathubCategory *self = BZ_FLATHUB_CATEGORY (serializable); g_autoptr (GVariantIter) iter = NULL; clear (self); iter = g_variant_iter_new (import); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; /* TODO automate this, this is awful */ if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "name") == 0) bz_flathub_category_set_name (self, g_variant_get_string (value, NULL)); else if (g_strcmp0 (key, "applications") == 0) { g_autoptr (GtkStringList) list = NULL; g_autoptr (GVariantIter) list_iter = NULL; list = gtk_string_list_new (NULL); list_iter = g_variant_iter_new (value); for (;;) { g_autofree char *id = NULL; if (!g_variant_iter_next (list_iter, "s", &id)) break; gtk_string_list_append (list, id); } self->applications = (GListModel *) g_steal_pointer (&list); } else if (g_strcmp0 (key, "quality-applications") == 0) { g_autoptr (GtkStringList) list = NULL; g_autoptr (GVariantIter) list_iter = NULL; list = gtk_string_list_new (NULL); list_iter = g_variant_iter_new (value); for (;;) { g_autofree char *id = NULL; if (!g_variant_iter_next (list_iter, "s", &id)) break; gtk_string_list_append (list, id); } self->quality_applications = (GListModel *) g_steal_pointer (&list); } else if (g_strcmp0 (key, "total-entries") == 0) self->total_entries = g_variant_get_int32 (value); else if (g_strcmp0 (key, "is-spotlight") == 0) self->is_spotlight = g_variant_get_boolean (value); } return TRUE; } static void serializable_iface_init (BzSerializableInterface *iface) { iface->serialize = bz_flathub_category_real_serialize; iface->deserialize = bz_flathub_category_real_deserialize; } BzFlathubCategory * bz_flathub_category_new (void) { return g_object_new (BZ_TYPE_FLATHUB_CATEGORY, NULL); } BzApplicationMapFactory * bz_flathub_category_get_map_factory (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); return self->map_factory; } const char * bz_flathub_category_get_name (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); return self->name; } GListModel * bz_flathub_category_dup_applications (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); if (self->applications != NULL) { if (self->map_factory != NULL) return bz_application_map_factory_generate ( self->map_factory, G_LIST_MODEL (self->applications)); else return G_LIST_MODEL (g_object_ref (self->applications)); } else return NULL; } GListModel * bz_flathub_category_dup_quality_applications (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); if (self->quality_applications != NULL) { if (self->map_factory != NULL) return bz_application_map_factory_generate ( self->map_factory, G_LIST_MODEL (self->quality_applications)); else return G_LIST_MODEL (g_object_ref (self->quality_applications)); } else return NULL; } int bz_flathub_category_get_total_entries (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), 0); return self->total_entries; } gboolean bz_flathub_category_get_is_spotlight (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), FALSE); return self->is_spotlight; } void bz_flathub_category_set_map_factory (BzFlathubCategory *self, BzApplicationMapFactory *map_factory) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); g_return_if_fail (map_factory == NULL || BZ_IS_APPLICATION_MAP_FACTORY (map_factory)); g_clear_object (&self->map_factory); if (map_factory != NULL) self->map_factory = g_object_ref (map_factory); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MAP_FACTORY]); } void bz_flathub_category_set_name (BzFlathubCategory *self, const char *name) { const CategoryInfo *info; g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); g_clear_pointer (&self->name, g_free); self->name = g_strdup (name); info = get_category_info (name); if (info != NULL && info->subcategories != NULL) { g_clear_object (&self->subcategories); self->subcategories = create_subcategories ((const Subcategory *) info->subcategories); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBCATEGORIES]); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NAME]); } void bz_flathub_category_set_applications (BzFlathubCategory *self, GListModel *applications) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); g_clear_pointer (&self->applications, g_object_unref); if (applications != NULL) self->applications = g_object_ref (applications); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APPLICATIONS]); } void bz_flathub_category_set_quality_applications (BzFlathubCategory *self, GListModel *applications) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); g_clear_pointer (&self->quality_applications, g_object_unref); if (applications != NULL) self->quality_applications = g_object_ref (applications); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_QUALITY_APPLICATIONS]); } void bz_flathub_category_set_total_entries (BzFlathubCategory *self, int total_entries) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); if (self->total_entries == total_entries) return; self->total_entries = total_entries; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TOTAL_ENTRIES]); } void bz_flathub_category_set_is_spotlight (BzFlathubCategory *self, gboolean is_spotlight) { g_return_if_fail (BZ_IS_FLATHUB_CATEGORY (self)); if (self->is_spotlight == is_spotlight) return; self->is_spotlight = is_spotlight; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_SPOTLIGHT]); } const char * bz_flathub_category_get_display_name (BzFlathubCategory *self) { const CategoryInfo *info; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); info = get_category_info (self->name); return info ? _ (info->display_name) : self->name; } const char * bz_flathub_category_get_short_name (BzFlathubCategory *self) { const CategoryInfo *info; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); info = get_category_info (self->name); return info ? _ (info->short_name) : self->name; } const char * bz_flathub_category_get_more_of_name (BzFlathubCategory *self) { const CategoryInfo *info; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); info = get_category_info (self->name); return info ? _ (info->more_of_name) : self->name; } const char * bz_flathub_category_get_icon_name (BzFlathubCategory *self) { const CategoryInfo *info; g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); info = get_category_info (self->name); return info ? info->icon_name : NULL; } GListModel * bz_flathub_category_get_subcategories (BzFlathubCategory *self) { g_return_val_if_fail (BZ_IS_FLATHUB_CATEGORY (self), NULL); return self->subcategories; } static void clear (BzFlathubCategory *self) { g_clear_pointer (&self->map_factory, g_object_unref); g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->applications, g_object_unref); g_clear_pointer (&self->quality_applications, g_object_unref); g_clear_object (&self->subcategories); } static const char * bz_flathub_category_map_appstream_id (const char *as_category_id) { g_autofree char *lowercase = NULL; const CategoryInfo *info = NULL; g_return_val_if_fail (as_category_id != NULL, NULL); lowercase = g_ascii_strdown (as_category_id, -1); info = get_category_info (lowercase); return info ? info->id : NULL; } GListModel * bz_flathub_category_list_from_appstream (GPtrArray *as_categories) { g_autoptr (GListStore) categories = NULL; g_return_val_if_fail (as_categories != NULL, NULL); if (as_categories->len == 0) return NULL; categories = g_list_store_new (BZ_TYPE_FLATHUB_CATEGORY); for (guint i = 0; i < as_categories->len; i++) { const char *category_id = NULL; const char *mapped_id = NULL; category_id = (const char *) g_ptr_array_index (as_categories, i); if (category_id == NULL) continue; mapped_id = bz_flathub_category_map_appstream_id (category_id); if (mapped_id != NULL) { g_autoptr (BzFlathubCategory) category = NULL; category = bz_flathub_category_new (); bz_flathub_category_set_name (category, mapped_id); g_list_store_append (categories, category); } } if (g_list_model_get_n_items (G_LIST_MODEL (categories)) == 0) return NULL; return G_LIST_MODEL (g_steal_pointer (&categories)); } /* End of bz-flathub-category.c */ kolunmi-bazaar-7b9c8e1/src/bz-flathub-category.h000066400000000000000000000055271514314607700217040ustar00rootroot00000000000000/* bz-flathub-category.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-application-map-factory.h" G_BEGIN_DECLS #define BZ_TYPE_FLATHUB_CATEGORY (bz_flathub_category_get_type ()) G_DECLARE_FINAL_TYPE (BzFlathubCategory, bz_flathub_category, BZ, FLATHUB_CATEGORY, GObject) BzFlathubCategory * bz_flathub_category_new (void); BzApplicationMapFactory * bz_flathub_category_get_map_factory (BzFlathubCategory *self); const char * bz_flathub_category_get_name (BzFlathubCategory *self); GListModel * bz_flathub_category_dup_applications (BzFlathubCategory *self); GListModel * bz_flathub_category_dup_quality_applications (BzFlathubCategory *self); void bz_flathub_category_set_map_factory (BzFlathubCategory *self, BzApplicationMapFactory *map_factory); void bz_flathub_category_set_name (BzFlathubCategory *self, const char *name); void bz_flathub_category_set_applications (BzFlathubCategory *self, GListModel *applications); void bz_flathub_category_set_quality_applications (BzFlathubCategory *self, GListModel *applications); const char * bz_flathub_category_get_display_name (BzFlathubCategory *self); const char * bz_flathub_category_get_short_name (BzFlathubCategory *self); const char * bz_flathub_category_get_more_of_name (BzFlathubCategory *self); const char * bz_flathub_category_get_icon_name (BzFlathubCategory *self); int bz_flathub_category_get_total_entries (BzFlathubCategory *self); void bz_flathub_category_set_total_entries (BzFlathubCategory *self, int total_entries); gboolean bz_flathub_category_get_is_spotlight (BzFlathubCategory *self); void bz_flathub_category_set_is_spotlight (BzFlathubCategory *self, gboolean is_spotlight); GListModel * bz_flathub_category_get_subcategories (BzFlathubCategory *self); GListModel * bz_flathub_category_list_from_appstream (GPtrArray *as_categories); G_END_DECLS /* End of bz-flathub-category.h */ kolunmi-bazaar-7b9c8e1/src/bz-flathub-page.blp000066400000000000000000000521461514314607700213300ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzFlathubPage: Adw.Bin { child: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Adw.ViewStack stack { enable-transitions: true; transition-duration: 400; Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "flathub-symbolic"; title: _("Flathub Not Added"); description: _("The Flathub remote was not found on any of your Flatpak installations"); }; } Adw.ViewStackPage { name: "offline"; title: _("Offline"); child: Adw.StatusPage { icon-name: "connected-squares-x"; title: _("Offline"); description: _("Flathub returned an error"); child: Button { styles ["pill"] halign: center; sensitive: bind $invert_boolean(template.state as <$BzStateInfo>.syncing as ) as ; label: _("Retry Flathub Connection"); action-name: "app.sync-remotes"; }; }; } Adw.ViewStackPage { name: "content"; title: _("Browser"); child: Box { Adw.StatusPage { visible: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.has-connection-error; hexpand: true; icon-name: "flathub-symbolic"; title: _("Flathub Unavailable"); description: _("We could not connect to Flathub. You can still manage and search for applications."); child: Button { label: _("Search Apps"); halign: center; clicked => $open_search_cb(template); styles ["pill"] }; } ScrolledWindow { visible: bind $invert_boolean(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.has-connection-error) as ; styles [ "transparent", ] hscrollbar-policy: never; child: Adw.ClampScrollable { maximum-size: 1500; tightening-threshold: 1400; child: Viewport { child: Box content_box { margin-start: 30; margin-end: 30; margin-top: 5; margin-bottom: 50; orientation: vertical; spacing: 15; $BzFeaturedCarousel { margin-start: 3; margin-end: 3; styles [ "flathub-page-section", ] margin-top: 16; hexpand: true; model: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.apps_of_the_week; group-clicked => $featured_carousel_group_clicked_cb(template); } Box section_toggles_box { halign: center; width-request: 800; Adw.ToggleGroup section_toggles { hexpand: true; halign: fill; homogeneous: true; styles [ "round", "huge" ] Adw.Toggle { label: _("Trending"); name: "trending"; enabled: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "trending") as <$BzFlathubCategory>) as ) as ; } Adw.Toggle { label: _("Popular"); name: "popular"; enabled: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "popular") as <$BzFlathubCategory>) as ) as ; } Adw.Toggle { label: _("New"); name: "recently-added"; enabled: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "recently-added") as <$BzFlathubCategory>) as ) as ; } Adw.Toggle { label: _("Updated"); name: "recently-updated"; enabled: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "recently-updated") as <$BzFlathubCategory>) as ) as ; } } } Adw.ViewStack sections_stack { enable-transitions: true; vhomogeneous: false; transition-duration: 300; visible-child-name: bind section_toggles.active-name bidirectional; Adw.ViewStackPage { name: "trending"; title: _("Trending"); child: $BzFlathubCategorySection section_trending { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "trending") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; min-items: 12; }; } Adw.ViewStackPage { name: "recently-updated"; title: _("Recently Updated"); child: $BzFlathubCategorySection section_recently_updated { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "recently-updated") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; min-items: 12; }; } Adw.ViewStackPage { name: "recently-added"; title: _("Recently Added"); child: $BzFlathubCategorySection section_recently_added { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "recently-added") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; min-items: 12; }; } Adw.ViewStackPage { name: "popular"; title: _("Popular"); child: $BzFlathubCategorySection section_popular { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "popular") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; min-items: 12; }; } } $BzFlathubCategorySection section_productivity { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "office") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFeaturedCarousel { margin-start: 3; margin-end: 3; styles [ "flathub-page-section", ] margin-top: 16; hexpand: true; model: SliceListModel { offset: 0; size: 1; model: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.apps_of_the_day_week; }; is-aotd: true; group-clicked => $featured_carousel_group_clicked_cb(template); } $BzFlathubCategorySection section_graphics { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "graphics") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFlathubCategorySection section_audiovideo { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "audiovideo") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } Box otg_box { visible: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "mobile") as <$BzFlathubCategory>) as ) as ; margin-start: 3; margin-end: 3; margin-top: 8; margin-bottom: 8; styles [ "sp-section", "otg", "card", ] Box otg_padding_box { orientation: horizontal; margin-start: 24; margin-end: 24; margin-top: 24; margin-bottom: 24; Box otg_title_box { orientation: vertical; spacing: 12; width-request: 285; valign: center; Image otg_image { icon-name: "on-the-go-symbolic"; can-target: false; pixel-size: 256; margin-bottom: 10; halign: start; styles [ "sp-section-image", ] } Label otg_title { label: _("On the Go"); halign: start; wrap: true; wrap-mode: word_char; styles [ "sp-section-title", "title-1", ] } Label otg_subtitle { label: _("Apps for your Linux phones and tablets"); halign: start; wrap: true; wrap-mode: word_char; } Button otg_more_button_top { styles [ "pill", ] label: _("More Mobile Apps"); halign: start; valign: center; clicked => $show_more_mobile_cb(template); } } $BzDynamicListView otg_list { styles [ "flathub-page-section", ] hexpand: true; scroll: false; noscroll-kind: flow-box; child-type: "BzAppTile"; child-prop: "group"; max-children-per-line: 3; model: SliceListModel otg_slice { offset: 0; size: 9; model: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "mobile") as <$BzFlathubCategory>.applications; }; bind-widget => $bind_widget_cb(template); unbind-widget => $unbind_widget_cb(template); } Button otg_more_button_bottom { styles [ "pill", ] visible: false; label: _("More Mobile Apps"); halign: center; valign: center; margin-bottom: 12; clicked => $show_more_mobile_cb(template); } } } $BzFlathubCategorySection section_education { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "education") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFlathubCategorySection section_network { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "network") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } Box { visible: bind $invert_boolean($is_null($get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "game") as <$BzFlathubCategory>) as ) as ; margin-start: 3; margin-end: 3; margin-top: 8; margin-bottom: 8; styles [ "sp-section", "wlg", "card", ] Box gaming_padding_box { orientation: vertical; margin-start: 24; margin-end: 24; margin-top: 24; margin-bottom: 24; Box { orientation: vertical; spacing: 12; width-request: 285; margin-bottom: 12; valign: center; Image { icon-name: "we-love-games-symbolic"; can-target: false; pixel-size: 256; margin-bottom: 10; halign: center; styles [ "sp-section-image", ] } Label { label: _("We​ ♥​ Games"); halign: center; justify: center; wrap: true; wrap-mode: word_char; styles [ "sp-section-title", "title-1", ] } Label { label: _("Games and apps to run your favorite titles"); halign: center; justify: center; wrap: true; wrap-mode: word_char; } } $BzDynamicListView game_list { styles [ "flathub-page-section", ] hexpand: true; scroll: false; noscroll-kind: flow-box; child-type: "BzAppTile"; child-prop: "group"; max-children-per-line: 4; model: SliceListModel game_slice { offset: 0; size: 12; model: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "game") as <$BzFlathubCategory>.applications; }; bind-widget => $bind_widget_cb(template); unbind-widget => $unbind_widget_cb(template); } Button { styles [ "pill", ] label: _("More Games"); halign: center; valign: center; margin-top: 12; margin-bottom: 12; clicked => $show_more_gaming_cb(template); } } } $BzFlathubCategorySection section_development { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "development") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFlathubCategorySection section_science { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "science") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFlathubCategorySection section_system { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "system") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } $BzFlathubCategorySection section_utility { category: bind $get_category_by_name_cb(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories, "utility") as <$BzFlathubCategory>; group-selected => $category_section_group_selected_cb() swapped; } }; }; }; } }; } }; Adw.Breakpoint { condition ("max-width: 1150sp") setters { otg_list.max-children-per-line: 2; otg_slice.size: 6; } } Adw.Breakpoint { condition ("max-width: 700px") setters { content_box.margin-start: 10; content_box.margin-end: 10; otg_padding_box.margin-start: 6; otg_padding_box.margin-end: 6; otg_padding_box.margin-bottom: 6; gaming_padding_box.margin-start: 6; gaming_padding_box.margin-end: 6; gaming_padding_box.margin-bottom: 6; section_toggles.homogeneous: false; section_trending.compact: true; section_popular.compact: true; section_recently_added.compact: true; section_recently_updated.compact: true; section_productivity.compact: true; section_graphics.compact: true; section_audiovideo.compact: true; section_education.compact: true; section_network.compact: true; section_development.compact: true; section_science.compact: true; section_system.compact: true; section_utility.compact: true; otg_slice.size: 6; game_slice.size: 6; } } }; Adw.Breakpoint { condition ("max-width: 900px") setters { section_toggles_box.width-request: -1; otg_padding_box.orientation: vertical; otg_padding_box.spacing: 6; otg_title_box.halign: center; otg_title_box.width-request: -1; otg_title.justify: center; otg_subtitle.justify: center; otg_image.halign: center; otg_image.margin-top: 15; otg_image.margin-bottom: 5; otg_title.halign: center; otg_subtitle.halign: center; otg_more_button_bottom.visible: true; otg_more_button_top.visible: false; } } }; } kolunmi-bazaar-7b9c8e1/src/bz-flathub-page.c000066400000000000000000000271551514314607700207770ustar00rootroot00000000000000/* bz-flathub-page.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-app-tile.h" #include "bz-apps-page.h" #include "bz-dynamic-list-view.h" #include "bz-entry-group.h" #include "bz-featured-carousel.h" #include "bz-flathub-category-section.h" #include "bz-flathub-category.h" #include "bz-flathub-page.h" #include "bz-inhibited-scrollable.h" #include "bz-section-view.h" struct _BzFlathubPage { AdwBin parent_instance; BzStateInfo *state; /* Template widgets */ AdwViewStack *stack; }; G_DEFINE_FINAL_TYPE (BzFlathubPage, bz_flathub_page, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_GROUP_SELECTED, SIGNAL_OPEN_SEARCH, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static BzFlathubCategory * get_category_by_name (GListModel *categories, const char *name); static void invalidating_state_changed (BzFlathubPage *self, GParamSpec *pspec, BzStateInfo *info); static void check_online (BzFlathubPage *self); static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static void tile_clicked (BzEntryGroup *group, GtkButton *button); static void show_more_clicked (BzFlathubPage *self, GtkButton *button, const char *category_name); static void apps_page_select_cb (BzFlathubPage *self, BzEntryGroup *group, BzAppsPage *page); static void category_section_group_selected_cb (BzFlathubPage *self, BzEntryGroup *group, BzFlathubCategorySection *section); static void featured_carousel_group_clicked_cb (BzFlathubPage *self, BzEntryGroup *group, BzFeaturedCarousel *carousel) { g_signal_emit (self, signals[SIGNAL_GROUP_SELECTED], 0, group); } static void bz_flathub_page_dispose (GObject *object) { BzFlathubPage *self = BZ_FLATHUB_PAGE (object); if (self->state != NULL) g_signal_handlers_disconnect_by_func (self->state, invalidating_state_changed, self); g_clear_object (&self->state); G_OBJECT_CLASS (bz_flathub_page_parent_class)->dispose (object); } static void bz_flathub_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFlathubPage *self = BZ_FLATHUB_PAGE (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_flathub_page_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFlathubPage *self = BZ_FLATHUB_PAGE (object); switch (prop_id) { case PROP_STATE: bz_flathub_page_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bind_widget_cb (BzFlathubPage *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (tile_clicked), group); } static void unbind_widget_cb (BzFlathubPage *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (tile, G_CALLBACK (tile_clicked), group); } static void show_more_mobile_cb (BzFlathubPage *self, GtkButton *button) { show_more_clicked (self, button, "mobile"); } static void show_more_gaming_cb (BzFlathubPage *self, GtkButton *button) { show_more_clicked (self, button, "game"); } static BzFlathubCategory * get_category_by_name (GListModel *categories, const char *name) { guint n_items; guint i; if (categories == NULL) return NULL; n_items = g_list_model_get_n_items (categories); for (i = 0; i < n_items; i++) { g_autoptr (BzFlathubCategory) category = g_list_model_get_item (categories, i); const char *category_name; category_name = bz_flathub_category_get_name (category); if (g_strcmp0 (category_name, name) == 0) return g_object_ref (category); } return NULL; } static gpointer get_category_by_name_cb (gpointer object, gpointer categories_obj, const char *name) { return get_category_by_name (G_LIST_MODEL (categories_obj), name); } static void open_search_cb (BzFlathubPage *self, GtkButton *button) { g_signal_emit (self, signals[SIGNAL_OPEN_SEARCH], 0); } static void bz_flathub_page_class_init (BzFlathubPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_flathub_page_dispose; object_class->get_property = bz_flathub_page_get_property; object_class->set_property = bz_flathub_page_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_GROUP_SELECTED] = g_signal_new ( "group-selected", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_signal_set_va_marshaller ( signals[SIGNAL_GROUP_SELECTED], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_OPEN_SEARCH] = g_signal_new ( "open-search", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_ensure (BZ_TYPE_SECTION_VIEW); g_type_ensure (BZ_TYPE_FLATHUB_CATEGORY_SECTION); g_type_ensure (BZ_TYPE_FLATHUB_CATEGORY); g_type_ensure (BZ_TYPE_INHIBITED_SCROLLABLE); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_APP_TILE); g_type_ensure (BZ_TYPE_FEATURED_CAROUSEL); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-flathub-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzFlathubPage, stack); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, bind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, category_section_group_selected_cb); gtk_widget_class_bind_template_callback (widget_class, get_category_by_name_cb); gtk_widget_class_bind_template_callback (widget_class, show_more_mobile_cb); gtk_widget_class_bind_template_callback (widget_class, show_more_gaming_cb); gtk_widget_class_bind_template_callback (widget_class, featured_carousel_group_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, open_search_cb); } static void bz_flathub_page_init (BzFlathubPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_flathub_page_new (void) { return g_object_new (BZ_TYPE_FLATHUB_PAGE, NULL); } void bz_flathub_page_set_state (BzFlathubPage *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_FLATHUB_PAGE (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); if (self->state != NULL) g_signal_handlers_disconnect_by_func (self->state, invalidating_state_changed, self); g_clear_object (&self->state); if (state != NULL) { self->state = g_object_ref (state); g_signal_connect_swapped ( state, "notify::flathub", G_CALLBACK (invalidating_state_changed), self); g_signal_connect_swapped ( state, "notify::online", G_CALLBACK (invalidating_state_changed), self); } check_online (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } BzStateInfo * bz_flathub_page_get_state (BzFlathubPage *self) { g_return_val_if_fail (BZ_IS_FLATHUB_PAGE (self), NULL); return self->state; } static void tile_clicked (BzEntryGroup *group, GtkButton *button) { GtkWidget *self = NULL; self = gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_FLATHUB_PAGE); g_signal_emit (self, signals[SIGNAL_GROUP_SELECTED], 0, group); } static void show_more_clicked (BzFlathubPage *self, GtkButton *button, const char *category_name) { g_autoptr (BzFlathubCategory) category = NULL; GtkWidget *nav_view = NULL; AdwNavigationPage *apps_page = NULL; category = get_category_by_name ( bz_flathub_state_get_categories ( bz_state_info_get_flathub (self->state)), category_name); if (category == NULL) return; apps_page = bz_apps_page_new_from_category (category); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); g_assert (nav_view != NULL); g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb), self); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void apps_page_select_cb (BzFlathubPage *self, BzEntryGroup *group, BzAppsPage *page) { g_signal_emit (self, signals[SIGNAL_GROUP_SELECTED], 0, group); } static void category_section_group_selected_cb (BzFlathubPage *self, BzEntryGroup *group, BzFlathubCategorySection *section) { g_signal_emit (self, signals[SIGNAL_GROUP_SELECTED], 0, group); } static void invalidating_state_changed (BzFlathubPage *self, GParamSpec *pspec, BzStateInfo *info) { check_online (self); } static void check_online (BzFlathubPage *self) { BzFlathubState *flathub = NULL; const char *page = NULL; if (self->state != NULL) flathub = bz_state_info_get_flathub (self->state); if (flathub != NULL) page = "content"; else page = "offline"; adw_view_stack_set_visible_child_name (self->stack, page); } kolunmi-bazaar-7b9c8e1/src/bz-flathub-page.h000066400000000000000000000022571514314607700210000ustar00rootroot00000000000000/* bz-flathub-page.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_FLATHUB_PAGE (bz_flathub_page_get_type ()) G_DECLARE_FINAL_TYPE (BzFlathubPage, bz_flathub_page, BZ, FLATHUB_PAGE, AdwBin) GtkWidget * bz_flathub_page_new (void); void bz_flathub_page_set_state (BzFlathubPage *self, BzStateInfo *state); BzStateInfo * bz_flathub_page_get_state (BzFlathubPage *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-flathub-state.c000066400000000000000000000775451514314607700212130ustar00rootroot00000000000000/* bz-flathub-state.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::FLATHUB" #define COLLECTION_FETCH_SIZE 192 #define CATEGORY_FETCH_SIZE 48 #define QUALITY_MODERATION_PAGE_SIZE 300 #define KEYWORD_SEARCH_PAGE_SIZE 48 #define ADWAITA_URL "https://arewelibadwaitayet.com" #include #include #include "bz-env.h" #include "bz-flathub-category.h" #include "bz-flathub-state.h" #include "bz-global-net.h" #include "bz-io.h" #include "bz-serializable.h" #include "bz-util.h" struct _BzFlathubState { GObject parent_instance; char *for_day; BzApplicationMapFactory *map_factory; char *app_of_the_day; GtkStringList *apps_of_the_week; GListStore *categories; gboolean has_connection_error; DexFuture *initializing; }; typedef enum { QUALITY_MODE_NONE, QUALITY_MODE_FIRST, QUALITY_MODE_RANDOM } QualityMode; static void serializable_iface_init (BzSerializableInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzFlathubState, bz_flathub_state, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (BZ_TYPE_SERIALIZABLE, serializable_iface_init)) static GListModel *bz_flathub_state_dup_apps_of_the_day_week (BzFlathubState *self); enum { PROP_0, PROP_FOR_DAY, PROP_MAP_FACTORY, PROP_APP_OF_THE_DAY, PROP_APP_OF_THE_DAY_GROUP, PROP_APPS_OF_THE_WEEK, PROP_APPS_OF_THE_DAY_WEEK, PROP_CATEGORIES, PROP_HAS_CONNECTION_ERROR, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * initialize_fiber (GWeakRef *wr); static DexFuture * initialize_finally (DexFuture *future, GWeakRef *wr); static void notify_all (BzFlathubState *self); static void clear (BzFlathubState *self); static void bz_flathub_state_dispose (GObject *object) { BzFlathubState *self = BZ_FLATHUB_STATE (object); dex_clear (&self->initializing); g_clear_pointer (&self->map_factory, g_object_unref); clear (self); G_OBJECT_CLASS (bz_flathub_state_parent_class)->dispose (object); } static void bz_flathub_state_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFlathubState *self = BZ_FLATHUB_STATE (object); switch (prop_id) { case PROP_FOR_DAY: g_value_set_string (value, bz_flathub_state_get_for_day (self)); break; case PROP_MAP_FACTORY: g_value_set_object (value, bz_flathub_state_get_map_factory (self)); break; case PROP_APP_OF_THE_DAY: g_value_set_string (value, bz_flathub_state_get_app_of_the_day (self)); break; case PROP_APP_OF_THE_DAY_GROUP: g_value_take_object (value, bz_flathub_state_dup_app_of_the_day_group (self)); break; case PROP_APPS_OF_THE_WEEK: g_value_take_object (value, bz_flathub_state_dup_apps_of_the_week (self)); break; case PROP_APPS_OF_THE_DAY_WEEK: g_value_take_object (value, bz_flathub_state_dup_apps_of_the_day_week (self)); break; case PROP_CATEGORIES: g_value_set_object (value, bz_flathub_state_get_categories (self)); break; case PROP_HAS_CONNECTION_ERROR: g_value_set_boolean (value, bz_flathub_state_get_has_connection_error (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_state_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFlathubState *self = BZ_FLATHUB_STATE (object); switch (prop_id) { case PROP_FOR_DAY: dex_future_disown (bz_flathub_state_set_for_day (self, g_value_get_string (value))); break; case PROP_MAP_FACTORY: bz_flathub_state_set_map_factory (self, g_value_get_object (value)); break; case PROP_APP_OF_THE_DAY: case PROP_APP_OF_THE_DAY_GROUP: case PROP_APPS_OF_THE_WEEK: case PROP_APPS_OF_THE_DAY_WEEK: case PROP_CATEGORIES: case PROP_HAS_CONNECTION_ERROR: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flathub_state_class_init (BzFlathubStateClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_flathub_state_set_property; object_class->get_property = bz_flathub_state_get_property; object_class->dispose = bz_flathub_state_dispose; props[PROP_FOR_DAY] = g_param_spec_string ( "for-day", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MAP_FACTORY] = g_param_spec_object ( "map-factory", NULL, NULL, BZ_TYPE_APPLICATION_MAP_FACTORY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_APP_OF_THE_DAY] = g_param_spec_string ( "app-of-the-day", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_APP_OF_THE_DAY_GROUP] = g_param_spec_object ( "app-of-the-day-group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_APPS_OF_THE_WEEK] = g_param_spec_object ( "apps-of-the-week", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_APPS_OF_THE_DAY_WEEK] = g_param_spec_object ( "apps-of-the-day-week", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CATEGORIES] = g_param_spec_object ( "categories", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_HAS_CONNECTION_ERROR] = g_param_spec_boolean ( "has-connection-error", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_flathub_state_init (BzFlathubState *self) { } static void bz_flathub_state_real_serialize (BzSerializable *serializable, GVariantBuilder *builder) { BzFlathubState *self = BZ_FLATHUB_STATE (serializable); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return; if (self->for_day != NULL) g_variant_builder_add (builder, "{sv}", "for-day", g_variant_new_string (self->for_day)); if (self->app_of_the_day != NULL) g_variant_builder_add (builder, "{sv}", "app-of-the-day", g_variant_new_string (self->app_of_the_day)); if (self->apps_of_the_week != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (G_LIST_MODEL (self->apps_of_the_week)); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < n_items; i++) { const char *string = NULL; string = gtk_string_list_get_string (self->apps_of_the_week, i); g_variant_builder_add (sub_builder, "s", string); } g_variant_builder_add (builder, "{sv}", "apps-of-the-week", g_variant_builder_end (sub_builder)); } } if (self->categories != NULL) { guint n_items = 0; n_items = g_list_model_get_n_items (G_LIST_MODEL (self->categories)); if (n_items > 0) { g_autoptr (GVariantBuilder) sub_builder = NULL; sub_builder = g_variant_builder_new (G_VARIANT_TYPE ("av")); for (guint i = 0; i < n_items; i++) { g_autoptr (BzFlathubCategory) category = NULL; g_autoptr (GVariantBuilder) category_builder = NULL; category = g_list_model_get_item (G_LIST_MODEL (self->categories), i); category_builder = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); bz_serializable_serialize (BZ_SERIALIZABLE (category), category_builder); g_variant_builder_add (sub_builder, "v", g_variant_builder_end (category_builder)); } g_variant_builder_add (builder, "{sv}", "categories", g_variant_builder_end (sub_builder)); } } } static gboolean bz_flathub_state_real_deserialize (BzSerializable *serializable, GVariant *import, GError **error) { BzFlathubState *self = BZ_FLATHUB_STATE (serializable); gboolean result = FALSE; g_autoptr (GVariantIter) iter = NULL; if (self->initializing != NULL && !dex_future_is_pending (self->initializing)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_BUSY, "Cannot perform serialization operations while initializing!"); return FALSE; } clear (self); iter = g_variant_iter_new (import); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; /* TODO automate this, this is awful */ if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "for-day") == 0) self->for_day = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "app-of-the-day") == 0) self->app_of_the_day = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "apps-of-the-week") == 0) { g_autoptr (GtkStringList) list = NULL; g_autoptr (GVariantIter) list_iter = NULL; list = gtk_string_list_new (NULL); list_iter = g_variant_iter_new (value); for (;;) { g_autofree char *id = NULL; if (!g_variant_iter_next (list_iter, "s", &id)) break; gtk_string_list_append (list, id); } self->apps_of_the_week = g_steal_pointer (&list); } else if (g_strcmp0 (key, "categories") == 0) { g_autoptr (GListStore) categories = NULL; g_autoptr (GVariantIter) categories_iter = NULL; categories = g_list_store_new (BZ_TYPE_FLATHUB_CATEGORY); categories_iter = g_variant_iter_new (value); for (;;) { g_autoptr (GVariant) category_import = NULL; g_autoptr (BzFlathubCategory) category = NULL; if (!g_variant_iter_next (categories_iter, "v", &category_import)) break; category = bz_flathub_category_new (); result = bz_serializable_deserialize ( BZ_SERIALIZABLE (category), category_import, error); if (!result) return FALSE; g_object_bind_property (self, "map-factory", category, "map-factory", G_BINDING_SYNC_CREATE); g_list_store_append (categories, category); } self->categories = g_steal_pointer (&categories); } } notify_all (self); return TRUE; } static void serializable_iface_init (BzSerializableInterface *iface) { iface->serialize = bz_flathub_state_real_serialize; iface->deserialize = bz_flathub_state_real_deserialize; } BzFlathubState * bz_flathub_state_new (void) { return g_object_new (BZ_TYPE_FLATHUB_STATE, NULL); } const char * bz_flathub_state_get_for_day (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); return self->for_day; } BzApplicationMapFactory * bz_flathub_state_get_map_factory (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); return self->map_factory; } const char * bz_flathub_state_get_app_of_the_day (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return NULL; return self->app_of_the_day; } BzEntryGroup * bz_flathub_state_dup_app_of_the_day_group (BzFlathubState *self) { g_autoptr (GtkStringObject) string = NULL; g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return NULL; g_return_val_if_fail (self->map_factory != NULL, NULL); string = gtk_string_object_new (self->app_of_the_day); return bz_application_map_factory_convert_one (self->map_factory, string); } GListModel * bz_flathub_state_dup_apps_of_the_week (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return NULL; if (self->apps_of_the_week != NULL) { if (self->map_factory != NULL) return bz_application_map_factory_generate ( self->map_factory, G_LIST_MODEL (self->apps_of_the_week)); else return G_LIST_MODEL (g_object_ref (self->apps_of_the_week)); } else return NULL; } GListModel * bz_flathub_state_dup_apps_of_the_day_week (BzFlathubState *self) { g_autoptr (GtkStringList) combined_list = NULL; g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return NULL; combined_list = gtk_string_list_new (NULL); if (self->app_of_the_day != NULL) gtk_string_list_append (combined_list, self->app_of_the_day); if (self->apps_of_the_week != NULL) { guint n_items = g_list_model_get_n_items (G_LIST_MODEL (self->apps_of_the_week)); for (guint i = 0; i < n_items; i++) { const char *app_id = gtk_string_list_get_string (self->apps_of_the_week, i); gtk_string_list_append (combined_list, app_id); } } if (self->map_factory != NULL) return bz_application_map_factory_generate (self->map_factory, G_LIST_MODEL (combined_list)); else return G_LIST_MODEL (g_object_ref (combined_list)); } GListModel * bz_flathub_state_get_categories (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), NULL); if (self->initializing != NULL && dex_future_is_pending (self->initializing)) return NULL; return G_LIST_MODEL (self->categories); } gboolean bz_flathub_state_get_has_connection_error (BzFlathubState *self) { g_return_val_if_fail (BZ_IS_FLATHUB_STATE (self), FALSE); return self->has_connection_error; } DexFuture * bz_flathub_state_set_for_day (BzFlathubState *self, const char *for_day) { dex_return_error_if_fail (BZ_IS_FLATHUB_STATE (self)); dex_clear (&self->initializing); clear (self); if (for_day != NULL) { g_autoptr (DexFuture) future = NULL; self->for_day = g_strdup (for_day); self->apps_of_the_week = gtk_string_list_new (NULL); self->categories = g_list_store_new (BZ_TYPE_FLATHUB_CATEGORY); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) initialize_fiber, bz_track_weak (self), bz_weak_release); future = dex_future_finally ( future, (DexFutureCallback) initialize_finally, bz_track_weak (self), bz_weak_release); self->initializing = g_steal_pointer (&future); return dex_ref (self->initializing); } else { notify_all (self); return dex_future_new_false (); } } DexFuture * bz_flathub_state_update_to_today (BzFlathubState *self) { g_autoptr (GDateTime) datetime = NULL; g_autofree gchar *for_day = NULL; dex_return_error_if_fail (BZ_IS_FLATHUB_STATE (self)); datetime = g_date_time_new_now_utc (); for_day = g_date_time_format (datetime, "%F"); g_debug ("Syncing with flathub for day: %s", for_day); return bz_flathub_state_set_for_day (self, for_day); } void bz_flathub_state_set_map_factory (BzFlathubState *self, BzApplicationMapFactory *map_factory) { g_return_if_fail (BZ_IS_FLATHUB_STATE (self)); g_return_if_fail (map_factory == NULL || BZ_IS_APPLICATION_MAP_FACTORY (map_factory)); g_clear_object (&self->map_factory); if (map_factory != NULL) self->map_factory = g_object_ref (map_factory); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MAP_FACTORY]); } static gboolean is_kde_plasma (void) { const char *desktop = g_getenv ("XDG_CURRENT_DESKTOP"); if (desktop == NULL) return FALSE; return g_str_equal (desktop, "KDE") || g_strstr_len (desktop, -1, "KDE") != NULL; } static void add_category (BzFlathubState *self, const char *name, JsonNode *node, GHashTable *quality_set, gboolean is_json_object, QualityMode quality_mode, gboolean is_spotlight) { JsonObject *object = NULL; JsonObjectIter iter; JsonArray *hits_array = NULL; const char *key = NULL; const char *app = NULL; g_autoptr (BzFlathubCategory) category = NULL; g_autoptr (GtkStringList) store = NULL; g_autoptr (GtkStringList) quality_store = NULL; g_autoptr (GPtrArray) quality_apps = NULL; guint app_count = 0; guint quality_count = 0; guint random_index = 0; guint i = 0; int total_entries = 0; category = bz_flathub_category_new (); store = gtk_string_list_new (NULL); quality_store = gtk_string_list_new (NULL); bz_flathub_category_set_name (category, name); bz_flathub_category_set_is_spotlight (category, is_spotlight); bz_flathub_category_set_applications (category, G_LIST_MODEL (store)); object = json_node_get_object (node); if (is_json_object) { if (quality_mode == QUALITY_MODE_RANDOM) quality_apps = g_ptr_array_new_with_free_func (g_free); json_object_iter_init (&iter, object); while (json_object_iter_next (&iter, &key, NULL)) { gtk_string_list_append (store, key); if (g_hash_table_contains (quality_set, key)) { if (quality_mode == QUALITY_MODE_RANDOM) g_ptr_array_add (quality_apps, g_strdup (key)); else if (quality_mode == QUALITY_MODE_FIRST) gtk_string_list_append (quality_store, key); } app_count++; } total_entries = json_object_get_size (object); } else { if (quality_mode == QUALITY_MODE_RANDOM) quality_apps = g_ptr_array_new_with_free_func (g_free); hits_array = json_object_get_array_member (object, "hits"); app_count = json_array_get_length (hits_array); for (i = 0; i < app_count; i++) { JsonObject *element = NULL; const char *app_id = NULL; element = json_array_get_object_element (hits_array, i); app_id = json_object_get_string_member (element, "app_id"); gtk_string_list_append (store, app_id); if (g_hash_table_contains (quality_set, app_id)) { if (quality_mode == QUALITY_MODE_RANDOM) g_ptr_array_add (quality_apps, g_strdup (app_id)); else if (quality_mode == QUALITY_MODE_FIRST) gtk_string_list_append (quality_store, app_id); } } total_entries = json_object_get_int_member (object, "totalHits"); } if (quality_mode == QUALITY_MODE_RANDOM && quality_apps != NULL) { quality_count = MIN (7, quality_apps->len); for (i = 0; i < quality_count; i++) { random_index = g_random_int_range (0, quality_apps->len); app = g_ptr_array_index (quality_apps, random_index); gtk_string_list_append (quality_store, app); g_ptr_array_remove_index_fast (quality_apps, random_index); } } bz_flathub_category_set_total_entries (category, total_entries); bz_flathub_category_set_quality_applications (category, G_LIST_MODEL (quality_store)); g_list_store_append (self->categories, category); } static DexFuture * initialize_fiber (GWeakRef *wr) { g_autoptr (BzFlathubState) self = NULL; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; gboolean is_kde = is_kde_plasma (); g_autoptr (GHashTable) quality_set = NULL; g_autoptr (DexFuture) aotd_f = NULL; g_autoptr (DexFuture) aotw_f = NULL; g_autoptr (DexFuture) categories_f = NULL; g_autoptr (DexFuture) updated_f = NULL; g_autoptr (DexFuture) added_f = NULL; g_autoptr (DexFuture) popular_f = NULL; g_autoptr (DexFuture) trending_f = NULL; g_autoptr (DexFuture) mobile_f = NULL; g_autoptr (DexFuture) passing_f = NULL; g_autoptr (DexFuture) adwaita_f = NULL; g_autoptr (DexFuture) toolkit_f = NULL; bz_weak_get_or_return_reject (self, wr); quality_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); #define ADD_REQUEST(_var, ...) \ G_STMT_START \ { \ g_autofree char *_request = NULL; \ \ _request = g_strdup_printf (__VA_ARGS__); \ (_var) = bz_query_flathub_v2_json_take (g_steal_pointer (&_request)); \ if (!dex_await (dex_ref ((_var)), &local_error)) \ { \ g_warning ("Failed to complete request to flathub: %s", local_error->message); \ return dex_future_new_for_error (g_steal_pointer (&local_error)); \ } \ } \ G_STMT_END if (is_kde) ADD_REQUEST (toolkit_f, "/collection/developer/kde?locale=en"); else { adwaita_f = bz_https_query_json (ADWAITA_URL "/api/apps"); if (!dex_await (dex_ref (adwaita_f), &local_error)) { g_warning ("Failed to complete request to arewelibadwaitayet: %s", local_error->message); g_clear_error (&local_error); adwaita_f = NULL; } } ADD_REQUEST (passing_f, "/quality-moderation/passing-apps?page=1&page_size=%d", QUALITY_MODERATION_PAGE_SIZE); ADD_REQUEST (aotd_f, "/app-picks/app-of-the-day/%s", self->for_day); ADD_REQUEST (aotw_f, "/app-picks/apps-of-the-week/%s", self->for_day); ADD_REQUEST (categories_f, "/collection/category"); ADD_REQUEST (updated_f, "/collection/recently-updated?page=0&per_page=%d", COLLECTION_FETCH_SIZE); ADD_REQUEST (added_f, "/collection/recently-added?page=0&per_page=%d", COLLECTION_FETCH_SIZE); ADD_REQUEST (popular_f, "/collection/popular?page=0&per_page=%d", COLLECTION_FETCH_SIZE); ADD_REQUEST (trending_f, "/collection/trending?page=0&per_page=%d", COLLECTION_FETCH_SIZE); ADD_REQUEST (mobile_f, "/collection/mobile?page=0&per_page=%d", COLLECTION_FETCH_SIZE); #undef ADD_REQUEST #define GET_BOXED(_future) g_value_get_boxed (dex_future_get_value ((_future), NULL)) { JsonObject *object = NULL; JsonArray *array = NULL; guint length = 0; object = json_node_get_object (GET_BOXED (passing_f)); array = json_object_get_array_member (object, "apps"); length = json_array_get_length (array); for (guint i = 0; i < length; i++) { const char *app_id = NULL; app_id = json_array_get_string_element (array, i); g_hash_table_replace (quality_set, g_strdup (app_id), NULL); } } { JsonObject *object = NULL; object = json_node_get_object (GET_BOXED (aotd_f)); self->app_of_the_day = g_strdup (json_object_get_string_member (object, "app_id")); } { JsonObject *object = NULL; JsonArray *array = NULL; guint length = 0; object = json_node_get_object (GET_BOXED (aotw_f)); array = json_object_get_array_member (object, "apps"); length = json_array_get_length (array); for (guint i = 0; i < length; i++) { JsonObject *element = NULL; element = json_array_get_object_element (array, i); gtk_string_list_append ( self->apps_of_the_week, json_object_get_string_member (element, "app_id")); } } add_category (self, "trending", GET_BOXED (trending_f), quality_set, FALSE, QUALITY_MODE_NONE, TRUE); add_category (self, "popular", GET_BOXED (popular_f), quality_set, FALSE, QUALITY_MODE_NONE, TRUE); add_category (self, "recently-added", GET_BOXED (added_f), quality_set, FALSE, QUALITY_MODE_NONE, TRUE); add_category (self, "recently-updated", GET_BOXED (updated_f), quality_set, FALSE, QUALITY_MODE_NONE, TRUE); add_category (self, "mobile", GET_BOXED (mobile_f), quality_set, FALSE, QUALITY_MODE_NONE, TRUE); { JsonArray *array = NULL; guint length = 0; g_autoptr (GPtrArray) category_futures = NULL; array = json_node_get_array (GET_BOXED (categories_f)); length = json_array_get_length (array); category_futures = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < length; i++) { const char *category = NULL; g_autofree char *request = NULL; g_autoptr (DexFuture) future = NULL; category = json_array_get_string_element (array, i); request = g_strdup_printf ( "/collection/category/%s?page=0&per_page=%d", category, CATEGORY_FETCH_SIZE); future = bz_query_flathub_v2_json_take (g_steal_pointer (&request)); result = dex_await (dex_ref (future), &local_error); if (!result) { g_warning ("Failed to complete request to flathub: %s", local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } g_ptr_array_add (category_futures, dex_ref (future)); } for (guint i = 0; i < length; i++) { DexFuture *future = NULL; JsonNode *node = NULL; const char *name = NULL; future = g_ptr_array_index (category_futures, i); node = GET_BOXED (future); name = json_array_get_string_element (array, i); add_category (self, name, node, quality_set, FALSE, QUALITY_MODE_FIRST, FALSE); } } if (is_kde) add_category (self, "kde", GET_BOXED (toolkit_f), quality_set, FALSE, QUALITY_MODE_RANDOM, FALSE); else if (adwaita_f != NULL) add_category (self, "adwaita", GET_BOXED (adwaita_f), quality_set, TRUE, QUALITY_MODE_RANDOM, FALSE); return dex_future_new_true (); } static DexFuture * initialize_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzFlathubState) self = NULL; bz_weak_get_or_return_reject (self, wr); if (dex_future_is_resolved (future)) { guint n_categories = 0; n_categories = g_list_model_get_n_items (G_LIST_MODEL (self->categories)); for (guint i = 0; i < n_categories; i++) { g_autoptr (BzFlathubCategory) category = NULL; category = g_list_model_get_item (G_LIST_MODEL (self->categories), i); g_object_bind_property (self, "map-factory", category, "map-factory", G_BINDING_SYNC_CREATE); } g_debug ("Done syncing flathub state; notifying property listeners..."); notify_all (self); } else clear (self); return dex_ref (future); } static DexFuture * search_collection_fiber (char *route) { g_autoptr (GError) local_error = NULL; g_autoptr (GtkStringList) results = NULL; g_autoptr (JsonNode) node = NULL; g_autofree char *request = NULL; JsonObject *object = NULL; JsonArray *array = NULL; guint length = 0; request = g_strdup_printf ("%s&page=1&per_page=%d&locale=en", route, KEYWORD_SEARCH_PAGE_SIZE); node = dex_await_boxed ( bz_query_flathub_v2_json_take ( g_steal_pointer (&request)), &local_error); if (node == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); results = gtk_string_list_new (NULL); object = json_node_get_object (node); array = json_object_get_array_member (object, "hits"); length = json_array_get_length (array); for (guint i = 0; i < length; i++) { JsonObject *element = NULL; const char *app_id = NULL; element = json_array_get_object_element (array, i); app_id = json_object_get_string_member (element, "app_id"); gtk_string_list_append (results, app_id); } return dex_future_new_take_object (g_steal_pointer (&results)); } static DexFuture * search_collection_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzFlathubState) self = NULL; const GValue *value = NULL; GListModel *model = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); if (value == NULL) return dex_ref (future); model = g_value_get_object (value); if (self->map_factory != NULL) return dex_future_new_take_object ( bz_application_map_factory_generate (self->map_factory, model)); return dex_ref (future); } DexFuture * bz_flathub_state_search_collection (BzFlathubState *self, const char *route) { g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (BZ_IS_FLATHUB_STATE (self)); dex_return_error_if_fail (route != NULL); future = dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) search_collection_fiber, g_strdup (route), g_free); future = dex_future_finally ( future, (DexFutureCallback) search_collection_finally, bz_track_weak (self), bz_weak_release); return g_steal_pointer (&future); } static void notify_all (BzFlathubState *self) { g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FOR_DAY]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_CONNECTION_ERROR]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APP_OF_THE_DAY]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APP_OF_THE_DAY_GROUP]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APPS_OF_THE_WEEK]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APPS_OF_THE_DAY_WEEK]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORIES]); } static void clear (BzFlathubState *self) { g_clear_pointer (&self->for_day, g_free); g_clear_pointer (&self->app_of_the_day, g_free); g_clear_pointer (&self->apps_of_the_week, g_object_unref); g_clear_pointer (&self->categories, g_object_unref); self->has_connection_error = FALSE; } /* End of bz-flathub-state.c */ kolunmi-bazaar-7b9c8e1/src/bz-flathub-state.h000066400000000000000000000041011514314607700211720ustar00rootroot00000000000000/* bz-flathub-state.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-application-map-factory.h" #include "bz-entry-group.h" G_BEGIN_DECLS #define BZ_TYPE_FLATHUB_STATE (bz_flathub_state_get_type ()) G_DECLARE_FINAL_TYPE (BzFlathubState, bz_flathub_state, BZ, FLATHUB_STATE, GObject) BzFlathubState * bz_flathub_state_new (void); DexFuture * bz_flathub_state_set_for_day (BzFlathubState *self, const char *for_day); void bz_flathub_state_set_map_factory (BzFlathubState *self, BzApplicationMapFactory *map_factory); const char * bz_flathub_state_get_for_day (BzFlathubState *self); BzApplicationMapFactory * bz_flathub_state_get_map_factory (BzFlathubState *self); const char * bz_flathub_state_get_app_of_the_day (BzFlathubState *self); BzEntryGroup * bz_flathub_state_dup_app_of_the_day_group (BzFlathubState *self); GListModel * bz_flathub_state_dup_apps_of_the_week (BzFlathubState *self); GListModel * bz_flathub_state_get_categories (BzFlathubState *self); gboolean bz_flathub_state_get_has_connection_error (BzFlathubState *self); DexFuture * bz_flathub_state_update_to_today (BzFlathubState *self); DexFuture * bz_flathub_state_search_collection (BzFlathubState *self, const char *route); G_END_DECLS /* End of bz-flathub-state.h */ kolunmi-bazaar-7b9c8e1/src/bz-flathub-sub-category.txt000066400000000000000000000002441514314607700230520ustar00rootroot00000000000000prefix=bz name=flathub_sub_category parent-prefix=g parent-name=object author=AUTOGEN property=name char G_TYPE_STRING string property=id char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-flatpak-entry.c000066400000000000000000000607011514314607700212130ustar00rootroot00000000000000/* bz-flatpak-entry.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::FLATPAK-ENTRY" #define BAZAAR_MODULE "entry" #include "config.h" #include #include #include "bz-app-permissions.h" #include "bz-appstream-parser.h" #include "bz-flatpak-private.h" #include "bz-io.h" #include "bz-serializable.h" struct _BzFlatpakEntry { BzEntry parent_instance; gboolean user; gboolean is_bundle; gboolean is_installed_ref; char *flatpak_name; char *flatpak_id; char *flatpak_version; char *application_name; char *application_runtime; char *application_command; char *runtime_name; char *addon_extension_of_ref; FlatpakRef *ref; }; static void serializable_iface_init (BzSerializableInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzFlatpakEntry, bz_flatpak_entry, BZ_TYPE_ENTRY, G_IMPLEMENT_INTERFACE (BZ_TYPE_SERIALIZABLE, serializable_iface_init)) enum { PROP_0, PROP_USER, PROP_FLATPAK_NAME, PROP_IS_BUNDLE, PROP_FLATPAK_ID, PROP_FLATPAK_VERSION, PROP_APPLICATION_NAME, PROP_APPLICATION_RUNTIME, PROP_APPLICATION_COMMAND, PROP_RUNTIME_NAME, PROP_ADDON_OF_REF, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void clear_entry (BzFlatpakEntry *self); static void bz_flatpak_entry_dispose (GObject *object) { BzFlatpakEntry *self = BZ_FLATPAK_ENTRY (object); clear_entry (self); g_clear_object (&self->ref); G_OBJECT_CLASS (bz_flatpak_entry_parent_class)->dispose (object); } static void bz_flatpak_entry_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFlatpakEntry *self = BZ_FLATPAK_ENTRY (object); switch (prop_id) { case PROP_USER: g_value_set_boolean (value, self->user); break; case PROP_FLATPAK_ID: g_value_set_string (value, self->flatpak_id); break; case PROP_FLATPAK_VERSION: g_value_set_string (value, self->flatpak_version); break; case PROP_APPLICATION_NAME: g_value_set_string (value, self->application_name); break; case PROP_IS_BUNDLE: g_value_set_boolean (value, self->is_bundle); break; case PROP_APPLICATION_RUNTIME: g_value_set_string (value, self->application_runtime); break; case PROP_APPLICATION_COMMAND: g_value_set_string (value, self->application_command); break; case PROP_RUNTIME_NAME: g_value_set_string (value, self->runtime_name); break; case PROP_ADDON_OF_REF: g_value_set_string (value, self->addon_extension_of_ref); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flatpak_entry_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { // BzFlatpakEntry *self = BZ_FLATPAK_ENTRY (object); switch (prop_id) { case PROP_USER: case PROP_FLATPAK_NAME: case PROP_FLATPAK_ID: case PROP_FLATPAK_VERSION: case PROP_APPLICATION_NAME: case PROP_IS_BUNDLE: case PROP_APPLICATION_RUNTIME: case PROP_APPLICATION_COMMAND: case PROP_RUNTIME_NAME: case PROP_ADDON_OF_REF: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_flatpak_entry_class_init (BzFlatpakEntryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_flatpak_entry_set_property; object_class->get_property = bz_flatpak_entry_get_property; object_class->dispose = bz_flatpak_entry_dispose; props[PROP_USER] = g_param_spec_boolean ( "user", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_FLATPAK_NAME] = g_param_spec_string ( "flatpak-name", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_FLATPAK_ID] = g_param_spec_string ( "flatpak-id", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_FLATPAK_VERSION] = g_param_spec_string ( "flatpak-version", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_APPLICATION_NAME] = g_param_spec_string ( "application-name", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_IS_BUNDLE] = g_param_spec_boolean ( "is-bundle", NULL, NULL, FALSE, G_PARAM_READABLE); props[PROP_APPLICATION_RUNTIME] = g_param_spec_string ( "application-runtime", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_APPLICATION_COMMAND] = g_param_spec_string ( "application-command", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_RUNTIME_NAME] = g_param_spec_string ( "runtime-name", NULL, NULL, NULL, G_PARAM_READABLE); props[PROP_ADDON_OF_REF] = g_param_spec_string ( "addon-extension-of-ref", NULL, NULL, NULL, G_PARAM_READABLE); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_flatpak_entry_init (BzFlatpakEntry *self) { } static void bz_flatpak_entry_real_serialize (BzSerializable *serializable, GVariantBuilder *builder) { BzFlatpakEntry *self = BZ_FLATPAK_ENTRY (serializable); g_variant_builder_add (builder, "{sv}", "user", g_variant_new_boolean (self->user)); g_variant_builder_add (builder, "{sv}", "is-installed-ref", g_variant_new_boolean (self->is_installed_ref)); if (self->flatpak_name != NULL) g_variant_builder_add (builder, "{sv}", "flatpak-name", g_variant_new_string (self->flatpak_name)); if (self->flatpak_id != NULL) g_variant_builder_add (builder, "{sv}", "flatpak-id", g_variant_new_string (self->flatpak_id)); if (self->flatpak_version != NULL) g_variant_builder_add (builder, "{sv}", "flatpak-version", g_variant_new_string (self->flatpak_version)); if (self->application_name != NULL) g_variant_builder_add (builder, "{sv}", "application-name", g_variant_new_string (self->application_name)); if (self->application_runtime != NULL) g_variant_builder_add (builder, "{sv}", "application-runtime", g_variant_new_string (self->application_runtime)); if (self->application_command != NULL) g_variant_builder_add (builder, "{sv}", "application-command", g_variant_new_string (self->application_command)); if (self->runtime_name != NULL) g_variant_builder_add (builder, "{sv}", "runtime-name", g_variant_new_string (self->runtime_name)); if (self->addon_extension_of_ref != NULL) g_variant_builder_add (builder, "{sv}", "addon-extension-of-ref", g_variant_new_string (self->addon_extension_of_ref)); bz_entry_serialize (BZ_ENTRY (self), builder); } static gboolean bz_flatpak_entry_real_deserialize (BzSerializable *serializable, GVariant *import, GError **error) { BzFlatpakEntry *self = BZ_FLATPAK_ENTRY (serializable); g_autoptr (GVariantIter) iter = NULL; clear_entry (self); iter = g_variant_iter_new (import); for (;;) { g_autofree char *key = NULL; g_autoptr (GVariant) value = NULL; if (!g_variant_iter_next (iter, "{sv}", &key, &value)) break; if (g_strcmp0 (key, "user") == 0) self->user = g_variant_get_boolean (value); else if (g_strcmp0 (key, "is-installed-ref") == 0) self->is_installed_ref = g_variant_get_boolean (value); else if (g_strcmp0 (key, "flatpak-name") == 0) self->flatpak_name = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "flatpak-id") == 0) self->flatpak_id = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "flatpak-version") == 0) self->flatpak_version = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "application-name") == 0) self->application_name = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "application-runtime") == 0) self->application_runtime = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "application-command") == 0) self->application_command = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "runtime-name") == 0) self->runtime_name = g_variant_dup_string (value, NULL); else if (g_strcmp0 (key, "addon-extension-of-ref") == 0) self->addon_extension_of_ref = g_variant_dup_string (value, NULL); } return bz_entry_deserialize (BZ_ENTRY (self), import, error); } static void serializable_iface_init (BzSerializableInterface *iface) { iface->serialize = bz_flatpak_entry_real_serialize; iface->deserialize = bz_flatpak_entry_real_deserialize; } BzFlatpakEntry * bz_flatpak_entry_new_for_ref (FlatpakRef *ref, FlatpakRemote *remote, gboolean user, AsComponent *component, const char *appstream_dir, GError **error) { g_autoptr (BzFlatpakEntry) self = NULL; GBytes *bytes = NULL; g_autoptr (GKeyFile) key_file = NULL; gboolean result = FALSE; guint kinds = 0; g_autofree char *module_dir = NULL; const char *id = NULL; g_autofree char *unique_id = NULL; g_autofree char *unique_id_checksum = NULL; guint64 download_size = 0; guint64 installed_size = 0; const char *title = NULL; const char *eol = NULL; const char *remote_name = NULL; g_autoptr (GdkPaintable) icon_paintable = NULL; g_autoptr (BzAppPermissions) permissions = NULL; gboolean searchable = FALSE; g_return_val_if_fail (FLATPAK_IS_REF (ref), NULL); g_return_val_if_fail (FLATPAK_IS_REMOTE_REF (ref) || FLATPAK_IS_BUNDLE_REF (ref) || FLATPAK_IS_INSTALLED_REF (ref), NULL); g_return_val_if_fail (component == NULL || appstream_dir != NULL || FLATPAK_IS_BUNDLE_REF (ref) || FLATPAK_IS_INSTALLED_REF (ref), NULL); self = g_object_new (BZ_TYPE_FLATPAK_ENTRY, NULL); self->user = user; self->is_bundle = FLATPAK_IS_BUNDLE_REF (ref); self->is_installed_ref = FLATPAK_IS_INSTALLED_REF (ref); self->ref = g_object_ref (ref); key_file = g_key_file_new (); if (FLATPAK_IS_REMOTE_REF (ref)) bytes = flatpak_remote_ref_get_metadata (FLATPAK_REMOTE_REF (ref)); else if (FLATPAK_IS_BUNDLE_REF (ref)) bytes = flatpak_bundle_ref_get_metadata (FLATPAK_BUNDLE_REF (ref)); else if (FLATPAK_IS_INSTALLED_REF (ref)) bytes = flatpak_installed_ref_load_metadata (FLATPAK_INSTALLED_REF (ref), NULL, error); result = g_key_file_load_from_bytes ( key_file, bytes, G_KEY_FILE_NONE, error); if (!result) return NULL; #define GET_STRING(member, group_name, key) \ G_STMT_START \ { \ self->member = g_key_file_get_string ( \ key_file, group_name, key, error); \ if (self->member == NULL) \ return NULL; \ } \ G_STMT_END if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN)) { gsize n_groups = 0; g_auto (GStrv) groups = NULL; g_print ("Debug Key File Data for %s - groups:\n", flatpak_ref_get_name (ref)); groups = g_key_file_get_groups (key_file, &n_groups); for (gsize i = 0; i < n_groups; i++) { gsize n_keys = 0; g_auto (GStrv) keys = NULL; g_print (" group %s\n", groups[i]); keys = g_key_file_get_keys (key_file, groups[i], &n_keys, NULL); for (gsize j = 0; j < n_keys; j++) { g_autofree char *value = NULL; value = g_key_file_get_value (key_file, groups[i], keys[j], NULL); g_print (" %s=%s\n", keys[j], value); } } } if (g_key_file_has_group (key_file, "Application")) { kinds |= BZ_ENTRY_KIND_APPLICATION; GET_STRING (application_name, "Application", "name"); GET_STRING (application_runtime, "Application", "runtime"); if (g_key_file_has_key (key_file, "Application", "command", NULL)) GET_STRING (application_command, "Application", "command"); } if (g_key_file_has_group (key_file, "ExtensionOf")) { kinds |= BZ_ENTRY_KIND_ADDON; GET_STRING (addon_extension_of_ref, "ExtensionOf", "ref"); } if (g_key_file_has_group (key_file, "Runtime")) { kinds |= BZ_ENTRY_KIND_RUNTIME; GET_STRING (runtime_name, "Runtime", "name"); } #undef GET_STRING // if (kinds == 0) // { // g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, // "Key file presented no useful information"); // return NULL; // } module_dir = bz_dup_module_dir (); self->flatpak_name = g_strdup (flatpak_ref_get_name (ref)); self->flatpak_id = flatpak_ref_format_ref (ref); self->flatpak_version = g_strdup (flatpak_ref_get_branch (ref)); id = flatpak_ref_get_name (ref); unique_id = bz_flatpak_ref_format_unique (ref, user); unique_id_checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, unique_id, -1); if (remote != NULL) remote_name = flatpak_remote_get_name (remote); else if (FLATPAK_IS_BUNDLE_REF (ref)) remote_name = flatpak_bundle_ref_get_origin (FLATPAK_BUNDLE_REF (ref)); else if (FLATPAK_IS_INSTALLED_REF (ref)) remote_name = flatpak_installed_ref_get_origin (FLATPAK_INSTALLED_REF (ref)); if (FLATPAK_IS_REMOTE_REF (ref)) download_size = flatpak_remote_ref_get_download_size (FLATPAK_REMOTE_REF (ref)); else if (FLATPAK_IS_BUNDLE_REF (ref)) { g_autoptr (GFileInfo) file_info = NULL; GFile *bundle_file = flatpak_bundle_ref_get_file (FLATPAK_BUNDLE_REF (ref)); file_info = g_file_query_info (bundle_file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (file_info != NULL) download_size = g_file_info_get_size (file_info); } if (FLATPAK_IS_REMOTE_REF (ref)) installed_size = flatpak_remote_ref_get_installed_size (FLATPAK_REMOTE_REF (ref)); else if (FLATPAK_IS_BUNDLE_REF (ref)) installed_size = flatpak_bundle_ref_get_installed_size (FLATPAK_BUNDLE_REF (ref)); else if (FLATPAK_IS_INSTALLED_REF (ref)) installed_size = flatpak_installed_ref_get_installed_size (FLATPAK_INSTALLED_REF (ref)); if (component != NULL) { result = bz_appstream_parser_populate_entry (BZ_ENTRY (self), component, appstream_dir, remote_name, module_dir, unique_id_checksum, id, kinds, error); if (!result) return NULL; } g_object_get (self, "icon-paintable", &icon_paintable, NULL); if (icon_paintable == NULL) { if (FLATPAK_IS_BUNDLE_REF (ref)) { for (int size = 128; size > 0; size -= 64) { g_autoptr (GBytes) icon_bytes = NULL; GdkTexture *texture = NULL; icon_bytes = flatpak_bundle_ref_get_icon (FLATPAK_BUNDLE_REF (ref), size); if (icon_bytes == NULL) continue; texture = gdk_texture_new_from_bytes (icon_bytes, NULL); /* don't error out even if loading fails */ if (texture != NULL) { icon_paintable = (GdkPaintable *) g_steal_pointer (&texture); break; } } } else if (FLATPAK_IS_INSTALLED_REF (ref)) { const char *icon_name = flatpak_ref_get_name (ref); const int sizes[] = { 512, 256, 128, 64, 48 }; for (int i = 0; i < G_N_ELEMENTS (sizes); i++) { g_autofree char *size = NULL; g_autofree char *basename = NULL; g_autofree char *icon_path = NULL; size = g_strdup_printf ("%dx%d", sizes[i], sizes[i]); basename = g_strdup_printf ("%s.png", icon_name); if (user) icon_path = g_build_filename ( g_get_home_dir (), ".local/share/flatpak/exports/share/icons/hicolor", size, "apps", basename, NULL); else icon_path = g_build_filename ( "/var/lib/flatpak/exports/share/icons/hicolor", size, "apps", basename, NULL); if (g_file_test (icon_path, G_FILE_TEST_EXISTS)) { g_autoptr (GFile) icon_file = NULL; GdkTexture *texture = NULL; icon_file = g_file_new_for_path (icon_path); texture = gdk_texture_new_from_file (icon_file, NULL); if (texture != NULL) { icon_paintable = (GdkPaintable *) g_steal_pointer (&texture); break; } } } } } g_object_get (self, "title", &title, NULL); if (title == NULL) { if (self->application_name != NULL) title = self->application_name; else if (self->runtime_name != NULL) title = self->runtime_name; else title = self->flatpak_id; } if (FLATPAK_IS_REMOTE_REF (ref)) eol = flatpak_remote_ref_get_eol (FLATPAK_REMOTE_REF (ref)); else if (FLATPAK_IS_INSTALLED_REF (ref)) eol = flatpak_installed_ref_get_eol (FLATPAK_INSTALLED_REF (ref)); permissions = bz_app_permissions_new_from_metadata (key_file, error); if (permissions == NULL) return NULL; searchable = !FLATPAK_IS_INSTALLED_REF (ref); g_object_set ( self, "kinds", kinds, "id", id, "unique-id", unique_id, "unique-id-checksum", unique_id_checksum, "title", title, "eol", eol, "remote-repo-name", remote_name, "size", download_size, "installed-size", installed_size, "icon-paintable", icon_paintable, "permissions", permissions, "searchable", searchable, NULL); return g_steal_pointer (&self); } char * bz_flatpak_ref_parts_format_unique (const char *origin, const char *fmt, gboolean user) { return g_strdup_printf ( "FLATPAK-%s::%s::%s", user ? "USER" : "SYSTEM", origin, fmt); } char * bz_flatpak_ref_format_unique (FlatpakRef *ref, gboolean user) { g_autofree char *fmt = NULL; const char *origin = NULL; fmt = flatpak_ref_format_ref (FLATPAK_REF (ref)); if (FLATPAK_IS_REMOTE_REF (ref)) origin = flatpak_remote_ref_get_remote_name (FLATPAK_REMOTE_REF (ref)); else if (FLATPAK_IS_BUNDLE_REF (ref)) origin = flatpak_bundle_ref_get_origin (FLATPAK_BUNDLE_REF (ref)); else if (FLATPAK_IS_INSTALLED_REF (ref)) origin = flatpak_installed_ref_get_origin (FLATPAK_INSTALLED_REF (ref)); return bz_flatpak_ref_parts_format_unique (origin, fmt, user); } FlatpakRef * bz_flatpak_entry_get_ref (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); if (self->ref == NULL) self->ref = flatpak_ref_parse (self->flatpak_id, NULL); return self->ref; } char * bz_flatpak_id_format_unique (const char *flatpak_id, gboolean user) { g_autoptr (FlatpakRef) ref = NULL; ref = flatpak_ref_parse (flatpak_id, NULL); if (ref == NULL) return NULL; return bz_flatpak_ref_format_unique (ref, user); } gboolean bz_flatpak_entry_is_user (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), FALSE); return self->user; } const char * bz_flatpak_entry_get_flatpak_name (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->flatpak_name; } const char * bz_flatpak_entry_get_flatpak_id (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->flatpak_id; } const char * bz_flatpak_entry_get_flatpak_version (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->flatpak_version; } const char * bz_flatpak_entry_get_application_name (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->application_name; } const char * bz_flatpak_entry_get_application_runtime (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->application_runtime; } const char * bz_flatpak_entry_get_runtime_name (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->runtime_name; } const char * bz_flatpak_entry_get_addon_extension_of_ref (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), NULL); return self->addon_extension_of_ref; } gboolean bz_flatpak_entry_is_bundle (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), FALSE); return self->is_bundle; } gboolean bz_flatpak_entry_is_installed_ref (BzFlatpakEntry *self) { g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), FALSE); return self->is_installed_ref; } gboolean bz_flatpak_entry_launch (BzFlatpakEntry *self, BzFlatpakInstance *flatpak, GError **error) { FlatpakRef *ref = NULL; #ifdef SANDBOXED_LIBFLATPAK g_autofree char *fmt = NULL; g_autofree char *cmdline = NULL; #else FlatpakInstallation *installation = NULL; #endif g_return_val_if_fail (BZ_IS_FLATPAK_ENTRY (self), FALSE); g_return_val_if_fail (BZ_IS_FLATPAK_INSTANCE (flatpak), FALSE); ref = bz_flatpak_entry_get_ref (self); #ifdef SANDBOXED_LIBFLATPAK fmt = flatpak_ref_format_ref (FLATPAK_REF (ref)); if (g_file_test ("/run/systemd", G_FILE_TEST_EXISTS)) cmdline = g_strdup_printf ("flatpak-spawn --host systemd-run --user --pipe flatpak run %s", fmt); else cmdline = g_strdup_printf ("flatpak-spawn --host flatpak run %s", fmt); return g_spawn_command_line_async (cmdline, error); #else installation = self->user ? bz_flatpak_instance_get_user_installation (flatpak) : bz_flatpak_instance_get_system_installation (flatpak); /* async? */ return flatpak_installation_launch ( installation, flatpak_ref_get_name (ref), flatpak_ref_get_arch (ref), flatpak_ref_get_branch (ref), flatpak_ref_get_commit (ref), NULL, error); #endif } static void clear_entry (BzFlatpakEntry *self) { g_clear_pointer (&self->flatpak_name, g_free); g_clear_pointer (&self->flatpak_id, g_free); g_clear_pointer (&self->flatpak_version, g_free); g_clear_pointer (&self->application_name, g_free); g_clear_pointer (&self->application_runtime, g_free); g_clear_pointer (&self->application_command, g_free); g_clear_pointer (&self->runtime_name, g_free); g_clear_pointer (&self->addon_extension_of_ref, g_free); } kolunmi-bazaar-7b9c8e1/src/bz-flatpak-entry.h000066400000000000000000000037071514314607700212230ustar00rootroot00000000000000/* bz-flatpak-entry.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include "bz-flatpak-instance.h" G_BEGIN_DECLS #define BZ_TYPE_FLATPAK_ENTRY (bz_flatpak_entry_get_type ()) G_DECLARE_FINAL_TYPE (BzFlatpakEntry, bz_flatpak_entry, BZ, FLATPAK_ENTRY, BzEntry) char * bz_flatpak_id_format_unique (const char *flatpak_id, gboolean user); gboolean bz_flatpak_entry_is_user (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_flatpak_name (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_flatpak_id (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_flatpak_version (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_application_name (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_application_runtime (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_runtime_name (BzFlatpakEntry *self); gboolean bz_flatpak_entry_is_bundle (BzFlatpakEntry *self); gboolean bz_flatpak_entry_is_installed_ref (BzFlatpakEntry *self); const char * bz_flatpak_entry_get_addon_extension_of_ref (BzFlatpakEntry *self); gboolean bz_flatpak_entry_launch (BzFlatpakEntry *self, BzFlatpakInstance *flatpak, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-flatpak-instance.c000066400000000000000000002572641514314607700216720ustar00rootroot00000000000000/* bz-flatpak-instance.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::FLATPAK" #define BAZAAR_MODULE "flatpak" #include #include #include "config.h" #include "bz-backend-notification.h" #include "bz-backend-transaction-op-payload.h" #include "bz-backend-transaction-op-progress-payload.h" #include "bz-backend.h" #include "bz-env.h" #include "bz-flatpak-private.h" #include "bz-global-net.h" #include "bz-io.h" #include "bz-repository.h" #include "bz-util.h" /* clang-format off */ G_DEFINE_QUARK (bz-flatpak-error-quark, bz_flatpak_error); /* clang-format on */ struct _BzFlatpakInstance { GObject parent_instance; DexScheduler *scheduler; FlatpakInstallation *system; GFileMonitor *system_events; int system_mute; FlatpakInstallation *user; GFileMonitor *user_events; int user_mute; GMutex mute_mutex; GMutex notif_mutex; GPtrArray *notif_channels; DexFuture *notif_send; }; static void backend_iface_init (BzBackendInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzFlatpakInstance, bz_flatpak_instance, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (BZ_TYPE_BACKEND, backend_iface_init)); BZ_DEFINE_DATA ( init, Init, { BzFlatpakInstance *self; }, BZ_RELEASE_DATA (self, g_object_unref)) static DexFuture * init_fiber (InitData *data); BZ_DEFINE_DATA ( check_has_flathub, CheckHasFlathub, { GWeakRef *self; GCancellable *cancellable; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (cancellable, g_object_unref)); static DexFuture * check_has_flathub_fiber (CheckHasFlathubData *data); BZ_DEFINE_DATA ( ensure_flathub, EnsureFlathub, { GWeakRef *self; GCancellable *cancellable; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (cancellable, g_object_unref)); static DexFuture * ensure_flathub_fiber (EnsureFlathubData *data); BZ_DEFINE_DATA ( load_local_ref, LoadLocalRef, { GWeakRef *self; GCancellable *cancellable; GFile *file; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (cancellable, g_object_unref); BZ_RELEASE_DATA (file, g_object_unref)); static DexFuture * load_local_ref_fiber (LoadLocalRefData *data); BZ_DEFINE_DATA ( gather_refs, GatherRefs, { GWeakRef *self; GCancellable *cancellable; guint total; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (cancellable, g_object_unref)); static DexFuture * retrieve_remote_refs_fiber (GatherRefsData *data); static DexFuture * retrieve_installs_fiber (GatherRefsData *data); static DexFuture * retrieve_updates_fiber (GatherRefsData *data); BZ_DEFINE_DATA ( list_repos, ListRepos, { GWeakRef *self; GCancellable *cancellable; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (cancellable, g_object_unref)); static DexFuture * list_repositories_fiber (ListReposData *data); BZ_DEFINE_DATA ( retrieve_refs_for_remote, RetrieveRefsForRemote, { GatherRefsData *parent; FlatpakInstallation *installation; FlatpakRemote *remote; }, BZ_RELEASE_DATA (parent, gather_refs_data_unref); BZ_RELEASE_DATA (installation, g_object_unref); BZ_RELEASE_DATA (remote, g_object_unref)); static DexFuture * retrieve_refs_for_remote_fiber (RetrieveRefsForRemoteData *data); static void gather_refs_update_progress (const char *status, guint progress, gboolean estimating, GatherRefsData *data); BZ_DEFINE_DATA ( transaction, Transaction, { GWeakRef *self; GMutex mutex; GCancellable *cancellable; GPtrArray *installs; GPtrArray *updates; GPtrArray *removals; DexChannel *channel; GPtrArray *send_futures; GHashTable *ref_to_entry_hash; GHashTable *op_to_progress_hash; guint unidentified_op_cnt; }, BZ_RELEASE_DATA (self, bz_weak_release); g_mutex_clear (&self->mutex); BZ_RELEASE_DATA (cancellable, g_object_unref); BZ_RELEASE_DATA (installs, g_ptr_array_unref); BZ_RELEASE_DATA (updates, g_ptr_array_unref); BZ_RELEASE_DATA (removals, g_ptr_array_unref); BZ_RELEASE_DATA (channel, dex_unref); BZ_RELEASE_DATA (send_futures, g_ptr_array_unref); BZ_RELEASE_DATA (ref_to_entry_hash, g_hash_table_unref); BZ_RELEASE_DATA (op_to_progress_hash, g_hash_table_unref)); static DexFuture * transaction_fiber (TransactionData *data); BZ_DEFINE_DATA ( transaction_job, TransactionJob, { TransactionData *parent; FlatpakTransaction *transaction; }, BZ_RELEASE_DATA (parent, transaction_data_unref); BZ_RELEASE_DATA (transaction, g_object_unref)); static DexFuture * transaction_job_fiber (TransactionJobData *data); static void transaction_new_operation (FlatpakTransaction *object, FlatpakTransactionOperation *operation, FlatpakTransactionProgress *progress, TransactionData *data); static void transaction_operation_done (FlatpakTransaction *object, FlatpakTransactionOperation *operation, gchar *commit, gint result, TransactionData *data); static gboolean transaction_operation_error (FlatpakTransaction *object, FlatpakTransactionOperation *operation, GError *error, gint details, TransactionData *data); static gboolean transaction_ready (FlatpakTransaction *object, TransactionData *data); static BzFlatpakEntry * find_entry_from_operation (TransactionData *data, FlatpakTransactionOperation *operation); BZ_DEFINE_DATA ( transaction_operation, TransactionOperation, { TransactionData *parent; BzFlatpakEntry *entry; BzBackendTransactionOpPayload *op; }, BZ_RELEASE_DATA (parent, transaction_data_unref); BZ_RELEASE_DATA (entry, g_object_unref); BZ_RELEASE_DATA (op, g_object_unref)); static void transaction_progress_changed (FlatpakTransactionProgress *object, TransactionOperationData *data); static void installation_event (BzFlatpakInstance *self, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GFileMonitor *monitor); static void send_notif (BzFlatpakInstance *self, DexChannel *channel, BzBackendNotification *notif, gboolean lock); static void send_notif_all (BzFlatpakInstance *self, BzBackendNotification *notif, gboolean lock); #define SEND_AND_RETURN_ERROR(_self, _lock, _error, ...) \ G_STMT_START \ { \ g_autofree char *_error_string = NULL; \ g_autoptr (BzBackendNotification) _notif = NULL; \ \ _error_string = g_strdup_printf (__VA_ARGS__); \ \ _notif = bz_backend_notification_new (); \ bz_backend_notification_set_kind (_notif, BZ_BACKEND_NOTIFICATION_KIND_ERROR); \ bz_backend_notification_set_error (_notif, _error_string); \ send_notif_all ((_self), _notif, (_lock)); \ \ return dex_future_new_for_error ( \ g_error_new_literal (BZ_FLATPAK_ERROR, \ (_error), \ _error_string)); \ } \ G_STMT_END BZ_DEFINE_DATA ( wait_notif, WaitNotif, { GWeakRef self; DexChannel *channel; BzBackendNotification *notif; }, g_weak_ref_clear (&self->self); BZ_RELEASE_DATA (channel, dex_unref); BZ_RELEASE_DATA (notif, g_object_unref)); static DexFuture * wait_notif_finally (DexFuture *future, WaitNotifData *data); static gint cmp_rref (FlatpakRemoteRef *a, FlatpakRemoteRef *b, GHashTable *hash); static AsComponent * parse_component_for_node (XbNode *node, GError **error); static GBytes * decompress_appstream_gz (GBytes *appstream_gz, GCancellable *cancellable, GError **error); static XbSilo * build_silo (XbBuilderSource *source, GCancellable *cancellable, GError **error); static AsComponent * extract_first_component_for_silo (XbSilo *silo, GError **error); static void bz_flatpak_instance_dispose (GObject *object) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (object); dex_clear (&self->scheduler); g_clear_object (&self->system); g_clear_object (&self->system_events); g_clear_object (&self->user); g_clear_object (&self->user_events); g_mutex_clear (&self->mute_mutex); g_clear_pointer (&self->notif_channels, g_ptr_array_unref); dex_clear (&self->notif_send); g_mutex_clear (&self->notif_mutex); G_OBJECT_CLASS (bz_flatpak_instance_parent_class)->dispose (object); } static void bz_flatpak_instance_class_init (BzFlatpakInstanceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_flatpak_instance_dispose; } static void bz_flatpak_instance_init (BzFlatpakInstance *self) { self->scheduler = dex_thread_pool_scheduler_new (); self->system_mute = 0; self->user_mute = 0; g_mutex_init (&self->mute_mutex); self->notif_channels = g_ptr_array_new_with_free_func (dex_unref); g_mutex_init (&self->notif_mutex); } static DexChannel * bz_flatpak_instance_create_notification_channel (BzBackend *backend) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (DexChannel) channel = NULL; channel = dex_channel_new (0); g_mutex_lock (&self->notif_mutex); g_ptr_array_add (self->notif_channels, dex_ref (channel)); g_mutex_unlock (&self->notif_mutex); return g_steal_pointer (&channel); } static DexFuture * bz_flatpak_instance_load_local_package (BzBackend *backend, GFile *file, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (LoadLocalRefData) data = NULL; data = load_local_ref_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); data->file = g_object_ref (file); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) load_local_ref_fiber, load_local_ref_data_ref (data), load_local_ref_data_unref); } static DexFuture * bz_flatpak_instance_retrieve_remote_refs (BzBackend *backend, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (GatherRefsData) data = NULL; data = gather_refs_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); data->total = 0; return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) retrieve_remote_refs_fiber, gather_refs_data_ref (data), gather_refs_data_unref); } static DexFuture * bz_flatpak_instance_retrieve_install_ids (BzBackend *backend, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (GatherRefsData) data = NULL; data = gather_refs_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) retrieve_installs_fiber, gather_refs_data_ref (data), gather_refs_data_unref); } static DexFuture * bz_flatpak_instance_retrieve_update_ids (BzBackend *backend, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (GatherRefsData) data = NULL; data = gather_refs_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) retrieve_updates_fiber, gather_refs_data_ref (data), gather_refs_data_unref); } static DexFuture * bz_flatpak_instance_list_repositories (BzBackend *backend, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); g_autoptr (ListReposData) data = NULL; data = list_repos_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) list_repositories_fiber, list_repos_data_ref (data), list_repos_data_unref); } static DexFuture * bz_flatpak_instance_schedule_transaction (BzBackend *backend, BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals, DexChannel *channel, GCancellable *cancellable) { BzFlatpakInstance *self = BZ_FLATPAK_INSTANCE (backend); BzFlatpakEntry **installs_dup = NULL; BzFlatpakEntry **updates_dup = NULL; BzFlatpakEntry **removals_dup = NULL; g_autoptr (TransactionData) data = NULL; for (guint i = 0; i < n_installs; i++) dex_return_error_if_fail (BZ_IS_FLATPAK_ENTRY (installs[i])); for (guint i = 0; i < n_updates; i++) dex_return_error_if_fail (BZ_IS_FLATPAK_ENTRY (updates[i])); for (guint i = 0; i < n_removals; i++) dex_return_error_if_fail (BZ_IS_FLATPAK_ENTRY (removals[i])); if (n_installs > 0) { installs_dup = g_malloc0_n (n_installs, sizeof (*installs_dup)); for (guint i = 0; i < n_installs; i++) installs_dup[i] = g_object_ref (BZ_FLATPAK_ENTRY (installs[i])); } if (n_updates > 0) { updates_dup = g_malloc0_n (n_updates, sizeof (*updates_dup)); for (guint i = 0; i < n_updates; i++) updates_dup[i] = g_object_ref (BZ_FLATPAK_ENTRY (updates[i])); } if (n_removals > 0) { removals_dup = g_malloc0_n (n_removals, sizeof (*removals_dup)); for (guint i = 0; i < n_removals; i++) removals_dup[i] = g_object_ref (BZ_FLATPAK_ENTRY (removals[i])); } data = transaction_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); data->installs = installs_dup != NULL ? g_ptr_array_new_take ((gpointer *) installs_dup, n_installs, g_object_unref) : NULL; data->updates = updates_dup != NULL ? g_ptr_array_new_take ((gpointer *) updates_dup, n_updates, g_object_unref) : NULL; data->removals = removals_dup != NULL ? g_ptr_array_new_take ((gpointer *) removals_dup, n_removals, g_object_unref) : NULL; data->channel = bz_dex_maybe_ref (channel); data->send_futures = g_ptr_array_new_with_free_func (dex_unref); data->ref_to_entry_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); data->op_to_progress_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); g_mutex_init (&data->mutex); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) transaction_fiber, transaction_data_ref (data), transaction_data_unref); } static void backend_iface_init (BzBackendInterface *iface) { iface->create_notification_channel = bz_flatpak_instance_create_notification_channel; iface->load_local_package = bz_flatpak_instance_load_local_package; iface->retrieve_remote_entries = bz_flatpak_instance_retrieve_remote_refs; iface->retrieve_install_ids = bz_flatpak_instance_retrieve_install_ids; iface->retrieve_update_ids = bz_flatpak_instance_retrieve_update_ids; iface->list_repositories = bz_flatpak_instance_list_repositories; iface->schedule_transaction = bz_flatpak_instance_schedule_transaction; } FlatpakInstallation * bz_flatpak_instance_get_system_installation (BzFlatpakInstance *self) { g_return_val_if_fail (BZ_IS_FLATPAK_INSTANCE (self), NULL); return self->system; } FlatpakInstallation * bz_flatpak_instance_get_user_installation (BzFlatpakInstance *self) { g_return_val_if_fail (BZ_IS_FLATPAK_INSTANCE (self), NULL); return self->user; } DexFuture * bz_flatpak_instance_new (void) { g_autoptr (InitData) data = NULL; data = init_data_new (); data->self = g_object_new (BZ_TYPE_FLATPAK_INSTANCE, NULL); return dex_scheduler_spawn ( data->self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) init_fiber, init_data_ref (data), init_data_unref); } DexFuture * bz_flatpak_instance_has_flathub (BzFlatpakInstance *self, GCancellable *cancellable) { g_autoptr (CheckHasFlathubData) data = NULL; dex_return_error_if_fail (BZ_IS_FLATPAK_INSTANCE (self)); dex_return_error_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); data = check_has_flathub_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) check_has_flathub_fiber, check_has_flathub_data_ref (data), check_has_flathub_data_unref); } DexFuture * bz_flatpak_instance_ensure_has_flathub (BzFlatpakInstance *self, GCancellable *cancellable) { g_autoptr (EnsureFlathubData) data = NULL; dex_return_error_if_fail (BZ_IS_FLATPAK_INSTANCE (self)); dex_return_error_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); data = ensure_flathub_data_new (); data->self = bz_track_weak (self); data->cancellable = bz_object_maybe_ref (cancellable); return dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) ensure_flathub_fiber, ensure_flathub_data_ref (data), ensure_flathub_data_unref); } static DexFuture * init_fiber (InitData *data) { BzFlatpakInstance *self = data->self; g_autoptr (GError) local_error = NULL; g_autofree char *main_cache = NULL; bz_discard_module_dir (); self->system = flatpak_installation_new_system (NULL, &local_error); if (self->system != NULL) { self->system_events = flatpak_installation_create_monitor ( self->system, NULL, &local_error); if (self->system_events != NULL) g_signal_connect_swapped ( self->system_events, "changed", G_CALLBACK (installation_event), self); else { g_warning ("Failed to initialize event watch for system installation: %s", local_error->message); g_clear_pointer (&local_error, g_error_free); } } else { g_warning ("Failed to initialize system installation: %s", local_error->message); g_clear_pointer (&local_error, g_error_free); } #ifdef SANDBOXED_LIBFLATPAK { g_autoptr (GFile) user_installation_path = NULL; const char *home = g_get_home_dir (); g_autofree char *user_flatpak_path = g_build_filename (home, ".local", "share", "flatpak", NULL); user_installation_path = g_file_new_for_path (user_flatpak_path); self->user = flatpak_installation_new_for_path ( user_installation_path, TRUE, NULL, &local_error); } #else self->user = flatpak_installation_new_user (NULL, &local_error); #endif if (self->user != NULL) { self->user_events = flatpak_installation_create_monitor ( self->user, NULL, &local_error); if (self->user_events != NULL) g_signal_connect_swapped ( self->user_events, "changed", G_CALLBACK (installation_event), self); else { g_warning ("Failed to initialize event watch for user installation: %s", local_error->message); g_clear_pointer (&local_error, g_error_free); } } else { g_warning ("Failed to initialize user installation: %s", local_error->message); g_clear_pointer (&local_error, g_error_free); } if (self->system == NULL && self->user == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to initialize any flatpak installations"); return dex_future_new_for_object (self); } static DexFuture * check_has_flathub_fiber (CheckHasFlathubData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) system_remotes = NULL; guint n_system_remotes = 0; g_autoptr (GPtrArray) user_remotes = NULL; guint n_user_remotes = 0; bz_weak_get_or_return_reject (self, data->self); if (self->system != NULL) { system_remotes = flatpak_installation_list_remotes ( self->system, cancellable, &local_error); if (system_remotes == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for system installation: %s", local_error->message); n_system_remotes = system_remotes->len; } if (self->user != NULL) { user_remotes = flatpak_installation_list_remotes ( self->user, cancellable, &local_error); if (user_remotes == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for user installation: %s", local_error->message); n_user_remotes = user_remotes->len; } for (guint i = 0; i < n_system_remotes + n_user_remotes; i++) { FlatpakRemote *remote = NULL; const char *name = NULL; if (i < n_system_remotes) remote = g_ptr_array_index (system_remotes, i); else remote = g_ptr_array_index (user_remotes, i - n_system_remotes); if (flatpak_remote_get_disabled (remote) || flatpak_remote_get_noenumerate (remote)) continue; name = flatpak_remote_get_name (remote); if (g_strcmp0 (name, "flathub") == 0) return dex_future_new_true (); } return dex_future_new_false (); } static DexFuture * ensure_flathub_fiber (EnsureFlathubData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (FlatpakRemote) sys_remote = NULL; g_autoptr (FlatpakRemote) usr_remote = NULL; gboolean result = FALSE; g_autoptr (FlatpakRemote) remote = NULL; bz_weak_get_or_return_reject (self, data->self); #define REPO_URL "https://dl.flathub.org/repo/flathub.flatpakrepo" if (self->system != NULL) sys_remote = flatpak_installation_get_remote_by_name ( self->system, "flathub", cancellable, NULL); if (self->user != NULL) usr_remote = flatpak_installation_get_remote_by_name ( self->user, "flathub", cancellable, NULL); if (sys_remote != NULL) remote = g_steal_pointer (&sys_remote); else if (usr_remote != NULL) remote = g_steal_pointer (&usr_remote); if (remote != NULL) { flatpak_remote_set_disabled (remote, FALSE); flatpak_remote_set_noenumerate (remote, FALSE); flatpak_remote_set_gpg_verify (remote, TRUE); } else { g_autoptr (SoupMessage) message = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (GBytes) bytes = NULL; message = soup_message_new (SOUP_METHOD_GET, REPO_URL); output = g_memory_output_stream_new_resizable (); result = dex_await ( bz_send_with_global_http_session_then_splice_into (message, output), &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to retrieve flatpakrepo file from %s: %s", REPO_URL, local_error->message); bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); remote = flatpak_remote_new_from_file ("flathub", bytes, &local_error); if (remote == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to construct flatpak remote from flatpakrepo file %s: %s", REPO_URL, local_error->message); flatpak_remote_set_gpg_verify (remote, TRUE); result = flatpak_installation_add_remote ( self->system != NULL ? self->system : self->user, remote, TRUE, cancellable, &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to add flathub to flatpak installation: %s", local_error->message); } return dex_future_new_true (); } static DexFuture * load_local_ref_fiber (LoadLocalRefData *data) { GFile *file = data->file; g_autoptr (GError) local_error = NULL; g_autofree char *uri = NULL; g_autofree char *path = NULL; g_autoptr (FlatpakBundleRef) bref = NULL; g_autoptr (BzFlatpakEntry) entry = NULL; g_autoptr (GBytes) appstream_gz = NULL; gboolean result = FALSE; g_autoptr (AsComponent) component = NULL; g_autoptr (GBytes) appstream = NULL; g_autoptr (GInputStream) stream_gz = NULL; g_autoptr (GInputStream) stream_data = NULL; g_autoptr (GZlibDecompressor) decompressor = NULL; uri = g_file_get_uri (file); path = g_file_get_path (file); if (uri == NULL) uri = g_strdup_printf ("file://%s", path); if (g_str_has_suffix (uri, ".flatpakref")) { const char *resolved_uri = NULL; g_autoptr (GKeyFile) key_file = g_key_file_new (); g_autofree char *name = NULL; if (g_str_has_prefix (uri, "flatpak+https")) resolved_uri = uri + strlen ("flatpak+"); else resolved_uri = uri; key_file = g_key_file_new (); if (g_str_has_prefix (resolved_uri, "http")) { g_autoptr (SoupMessage) message = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (GBytes) bytes = NULL; message = soup_message_new (SOUP_METHOD_GET, resolved_uri); output = g_memory_output_stream_new_resizable (); result = dex_await ( bz_send_with_global_http_session_then_splice_into (message, output), &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to retrieve flatpakref file from %s: %s", resolved_uri, local_error->message); bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); result = g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, &local_error); } else if (path != NULL) result = g_key_file_load_from_file ( key_file, path, G_KEY_FILE_NONE, &local_error); else local_error = g_error_new ( G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "Cannot handle URIs of this type"); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to load flatpakref '%s' into a key file: %s", uri, local_error->message); name = g_key_file_get_string (key_file, "Flatpak Ref", "Name", &local_error); if (name == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to load locate \"Name\" key in flatpakref '%s': %s", uri, local_error->message); return dex_future_new_take_string (g_steal_pointer (&name)); } bref = flatpak_bundle_ref_new (file, &local_error); if (bref == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to load local flatpak bundle '%s': %s", path, local_error->message); appstream_gz = flatpak_bundle_ref_get_appstream (bref); if (appstream_gz != NULL) { g_autoptr (XbBuilderSource) source = NULL; g_autoptr (XbSilo) silo = NULL; appstream = decompress_appstream_gz (appstream_gz, NULL, &local_error); if (appstream == NULL) { g_warning ("Failed to decompress AppStream data: %s", local_error->message); g_clear_error (&local_error); } else { source = xb_builder_source_new (); if (!xb_builder_source_load_bytes (source, appstream, XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT, &local_error)) { g_warning ("Failed to load AppStream bytes into xmlb: %s", local_error->message); g_clear_error (&local_error); } else { silo = build_silo (source, NULL, &local_error); if (silo == NULL) { g_warning ("Failed to compile xmlb silo: %s", local_error->message); g_clear_error (&local_error); } else { component = extract_first_component_for_silo (silo, &local_error); if (component == NULL && local_error != NULL) { g_warning ("Failed to parse component: %s", local_error->message); g_clear_error (&local_error); } } } } } entry = bz_flatpak_entry_new_for_ref ( FLATPAK_REF (bref), NULL, FALSE, component, NULL, &local_error); if (entry == NULL) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to parse information from flatpak bundle '%s': %s", path, local_error->message); return dex_future_new_for_object (entry); } static DexFuture * retrieve_remote_refs_fiber (GatherRefsData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) system_remotes = NULL; guint n_system_remotes = 0; g_autoptr (GPtrArray) user_remotes = NULL; guint n_user_remotes = 0; g_autoptr (GHashTable) blocked_names_hash = NULL; g_autoptr (GPtrArray) jobs = NULL; g_autoptr (GPtrArray) job_names = NULL; g_autoptr (DexFuture) future = NULL; gboolean result = FALSE; g_autoptr (GString) error_string = NULL; bz_weak_get_or_return_reject (self, data->self); if (self->system != NULL) { system_remotes = flatpak_installation_list_remotes ( self->system, cancellable, &local_error); if (system_remotes == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for system installation: %s", local_error->message); n_system_remotes = system_remotes->len; } if (self->user != NULL) { user_remotes = flatpak_installation_list_remotes ( self->user, cancellable, &local_error); if (user_remotes == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for user installation: %s", local_error->message); n_user_remotes = user_remotes->len; } if (n_user_remotes + n_system_remotes == 0) return dex_future_new_true (); jobs = g_ptr_array_new_with_free_func (dex_unref); job_names = g_ptr_array_new_with_free_func (g_free); for (guint i = 0; i < n_system_remotes + n_user_remotes; i++) { FlatpakInstallation *installation = NULL; FlatpakRemote *remote = NULL; const char *name = NULL; g_autoptr (RetrieveRefsForRemoteData) job_data = NULL; g_autoptr (DexFuture) job_future = NULL; if (i < n_system_remotes) { installation = self->system; remote = g_ptr_array_index (system_remotes, i); } else { installation = self->user; remote = g_ptr_array_index (user_remotes, i - n_system_remotes); } name = flatpak_remote_get_name (remote); if (strstr (name, "fedora") != NULL) { g_debug ("Skipping remote %s", name); /* the fedora flatpak repos cause too many issues */ continue; } job_data = retrieve_refs_for_remote_data_new (); job_data->parent = gather_refs_data_ref (data); job_data->installation = g_object_ref (installation); job_data->remote = g_object_ref (remote); job_future = dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) retrieve_refs_for_remote_fiber, retrieve_refs_for_remote_data_ref (job_data), retrieve_refs_for_remote_data_unref); g_ptr_array_add (jobs, g_steal_pointer (&job_future)); g_ptr_array_add (job_names, g_strdup (name)); } if (jobs->len == 0) return dex_future_new_true (); result = dex_await (dex_future_allv ( (DexFuture *const *) jobs->pdata, jobs->len), NULL); if (!result) error_string = g_string_new ("No remotes could be synchronized:\n\n"); for (guint i = 0; i < jobs->len; i++) { DexFuture *job_future = NULL; char *name = NULL; job_future = g_ptr_array_index (jobs, i); name = g_ptr_array_index (job_names, i); dex_future_get_value (job_future, &local_error); if (local_error != NULL) { if (error_string == NULL) error_string = g_string_new ("Some remotes couldn't be fully sychronized:\n"); g_string_append_printf (error_string, "\n%s failed because: %s\n", name, local_error->message); } g_clear_pointer (&local_error, g_error_free); } if (result) { if (error_string != NULL) return dex_future_new_take_string ( g_string_free_and_steal (g_steal_pointer (&error_string))); else return dex_future_new_true (); } else return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "%s", error_string->str); } static void gather_refs_update_progress (const char *status, guint progress, gboolean estimating, GatherRefsData *data) { } static DexFuture * retrieve_refs_for_enumerable_remote (RetrieveRefsForRemoteData *data, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->parent->cancellable; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autoptr (GFile) appstream_dir = NULL; g_autofree char *appstream_dir_path = NULL; g_autofree char *appstream_xml_path = NULL; g_autoptr (GFile) appstream_xml = NULL; g_autoptr (XbBuilderSource) source = NULL; g_autoptr (XbSilo) silo = NULL; g_autoptr (XbNode) root = NULL; g_autoptr (GPtrArray) children = NULL; g_autoptr (GHashTable) component_hash = NULL; g_autoptr (GPtrArray) refs = NULL; bz_weak_get_or_return_reject (self, data->parent->self); g_debug ("Remote '%s' is enumerable, listing all remote refs", remote_name); result = flatpak_installation_update_remote_sync ( installation, remote_name, cancellable, &local_error); if (!result) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to synchronize remote '%s': %s", remote_name, local_error->message); result = flatpak_installation_update_appstream_full_sync ( installation, remote_name, NULL, (FlatpakProgressCallback) gather_refs_update_progress, data, NULL, cancellable, &local_error); if (!result) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to synchronize appstream data for remote '%s': %s", remote_name, local_error->message); appstream_dir = flatpak_remote_get_appstream_dir (remote, NULL); if (appstream_dir == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to locate appstream directory for remote '%s': %s", remote_name, local_error->message); appstream_dir_path = g_file_get_path (appstream_dir); appstream_xml_path = g_build_filename (appstream_dir_path, "appstream.xml.gz", NULL); if (!g_file_test (appstream_xml_path, G_FILE_TEST_EXISTS)) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to verify existence of appstream " "bundle download at path %s for remote '%s'", appstream_xml_path, remote_name); appstream_xml = g_file_new_for_path (appstream_xml_path); source = xb_builder_source_new (); result = xb_builder_source_load_file ( source, appstream_xml, XB_BUILDER_SOURCE_FLAG_WATCH_FILE | XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT, cancellable, &local_error); if (!result) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to load binary xml from appstream bundle " "download at path %s for remote '%s': %s", appstream_xml_path, remote_name, local_error->message); silo = build_silo (source, cancellable, &local_error); #ifdef __GLIBC__ /* From gnome-software/plugins/core/gs-plugin-appstream.c * * https://gitlab.gnome.org/GNOME/gnome-software/-/issues/941 * libxmlb <= 0.3.22 makes lots of temporary heap allocations parsing large XMLs * trim the heap after parsing to control RSS growth. */ malloc_trim (0); #endif if (silo == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, "Failed to compile binary xml silo from appstream bundle " "download at path %s for remote '%s': %s", appstream_xml_path, remote_name, local_error->message); root = xb_silo_get_root (silo); children = xb_node_get_children (root); component_hash = g_hash_table_new (g_str_hash, g_str_equal); for (guint i = 0; i < children->len; i++) { XbNode *component_node = NULL; AsComponent *component = NULL; const char *id = NULL; component_node = g_ptr_array_index (children, i); component = parse_component_for_node (component_node, &local_error); if (component == NULL) { SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_APPSTREAM_FAILURE, "Failed to parse appstream component from appstream bundle silo " "originating from download at path %s for remote '%s': %s", appstream_xml_path, remote_name, local_error->message); } id = as_component_get_id (component); g_hash_table_replace (component_hash, (gpointer) id, component); } refs = flatpak_installation_list_remote_refs_sync ( installation, remote_name, cancellable, &local_error); if (refs == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to enumerate refs for remote '%s': %s", remote_name, local_error->message); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING); bz_backend_notification_set_n_incoming (notif, refs->len); send_notif_all (self, notif, TRUE); } /* Ensure the receiving side of the channel gets * runtimes first, then addons, then applications */ g_ptr_array_sort_values_with_data ( refs, (GCompareDataFunc) cmp_rref, component_hash); for (guint i = 0; i < refs->len; i++) { FlatpakRemoteRef *rref = NULL; const char *name = NULL; AsComponent *component = NULL; g_autoptr (BzFlatpakEntry) entry = NULL; rref = g_ptr_array_index (refs, i); name = flatpak_ref_get_name (FLATPAK_REF (rref)); component = g_hash_table_lookup (component_hash, name); if (component == NULL) { g_autofree char *desktop_id = NULL; desktop_id = g_strdup_printf ("%s.desktop", name); component = g_hash_table_lookup (component_hash, desktop_id); } entry = bz_flatpak_entry_new_for_ref ( FLATPAK_REF (rref), remote, installation == self->user, component, appstream_dir_path, NULL); if (entry != NULL) { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY); bz_backend_notification_set_entry (notif, BZ_ENTRY (entry)); send_notif_all (self, notif, TRUE); } else { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING); bz_backend_notification_set_n_incoming (notif, -1); send_notif_all (self, notif, TRUE); } } return dex_future_new_true (); } static DexFuture * retrieve_refs_for_noenumerable_remote (RetrieveRefsForRemoteData *data, const char *remote_name, FlatpakInstallation *installation, FlatpakRemote *remote) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->parent->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) installed_apps = NULL; guint matched = 0; bz_weak_get_or_return_reject (self, data->parent->self); installed_apps = flatpak_installation_list_installed_refs_by_kind ( installation, FLATPAK_REF_KIND_APP, cancellable, &local_error); if (installed_apps == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_LOCAL_SYNCHRONIZATION_FAILURE, "Failed to enumerate installed apps for non-enumerable remote '%s': %s", remote_name, local_error->message); g_debug ("Found %u total installed apps, filtering for remote '%s'", installed_apps->len, remote_name); for (guint i = 0; i < installed_apps->len; i++) { FlatpakInstalledRef *iref = NULL; const char *ref_origin = NULL; g_autoptr (AsComponent) component = NULL; g_autoptr (BzFlatpakEntry) entry = NULL; g_autoptr (GBytes) appstream_gz = NULL; iref = g_ptr_array_index (installed_apps, i); ref_origin = flatpak_installed_ref_get_origin (iref); if (g_strcmp0 (ref_origin, remote_name) != 0) continue; matched++; appstream_gz = flatpak_installed_ref_load_appdata (iref, cancellable, NULL); if (appstream_gz != NULL) { g_autoptr (GBytes) appstream = NULL; g_autoptr (XbBuilderSource) source = NULL; g_autoptr (XbSilo) silo = NULL; g_autoptr (GError) appstream_error = NULL; appstream = decompress_appstream_gz (appstream_gz, cancellable, &appstream_error); if (appstream == NULL) { g_info ("Could not decompress appstream for installed ref: %s", appstream_error ? appstream_error->message : "unknown error"); goto create_entry; } source = xb_builder_source_new (); if (!xb_builder_source_load_bytes (source, appstream, XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT, &appstream_error)) { g_info ("Could not load appstream bytes: %s", appstream_error ? appstream_error->message : "unknown error"); goto create_entry; } silo = build_silo (source, cancellable, &appstream_error); if (silo == NULL) { g_info ("Could not build silo from appstream: %s", appstream_error ? appstream_error->message : "unknown error"); goto create_entry; } component = extract_first_component_for_silo (silo, &appstream_error); if (component == NULL) { g_info ("Could not parse appstream component: %s", appstream_error ? appstream_error->message : "unknown error"); } } create_entry: entry = bz_flatpak_entry_new_for_ref ( FLATPAK_REF (iref), remote, installation == self->user, component, NULL, NULL); if (entry != NULL) { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_REPLACE_ENTRY); bz_backend_notification_set_entry (notif, BZ_ENTRY (entry)); send_notif_all (self, notif, TRUE); } } g_debug ("Found %u installed apps from non-enumerable remote '%s'", matched, remote_name); { g_autoptr (BzBackendNotification) notif = NULL; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_TELL_INCOMING); bz_backend_notification_set_n_incoming (notif, matched); send_notif_all (self, notif, TRUE); } return dex_future_new_true (); } static DexFuture * retrieve_refs_for_remote_fiber (RetrieveRefsForRemoteData *data) { FlatpakInstallation *installation = data->installation; FlatpakRemote *remote = data->remote; const char *remote_name = NULL; gboolean is_noenumerate = FALSE; g_autoptr (BzFlatpakInstance) self = NULL; bz_weak_get_or_return_reject (self, data->parent->self); remote_name = flatpak_remote_get_name (remote); is_noenumerate = flatpak_remote_get_noenumerate (remote); #ifdef SANDBOXED_LIBFLATPAK if (is_noenumerate || installation == self->user) #else if (is_noenumerate) #endif return retrieve_refs_for_noenumerable_remote (data, remote_name, installation, remote); else return retrieve_refs_for_enumerable_remote (data, remote_name, installation, remote); } static DexFuture * retrieve_installs_fiber (GatherRefsData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) system_refs = NULL; guint n_system_refs = 0; g_autoptr (GPtrArray) user_refs = NULL; guint n_user_refs = 0; g_autoptr (GHashTable) ids = NULL; bz_weak_get_or_return_reject (self, data->self); if (self->system != NULL) { flatpak_installation_drop_caches ( self->system, cancellable, NULL); system_refs = flatpak_installation_list_installed_refs ( self->system, cancellable, &local_error); if (system_refs == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_LOCAL_SYNCHRONIZATION_FAILURE, "Failed to discover installed refs for system installation: %s", local_error->message); n_system_refs = system_refs->len; } if (self->user != NULL) { flatpak_installation_drop_caches ( self->user, cancellable, NULL); user_refs = flatpak_installation_list_installed_refs ( self->user, cancellable, &local_error); if (user_refs == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_LOCAL_SYNCHRONIZATION_FAILURE, "Failed to discover installed refs for user installation: %s", local_error->message); n_user_refs = user_refs->len; } ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (guint i = 0; i < n_system_refs + n_user_refs; i++) { gboolean user = FALSE; FlatpakInstalledRef *iref = NULL; const char *version = NULL; g_autofree char *unique_id = NULL; if (i < n_system_refs) { user = FALSE; iref = g_ptr_array_index (system_refs, i); } else { user = TRUE; iref = g_ptr_array_index (user_refs, i - n_system_refs); } version = flatpak_installed_ref_get_appdata_version (iref); unique_id = bz_flatpak_ref_format_unique (FLATPAK_REF (iref), user); g_hash_table_replace (ids, g_steal_pointer (&unique_id), g_strdup (version != NULL ? version : "")); } return dex_future_new_take_boxed ( G_TYPE_HASH_TABLE, g_steal_pointer (&ids)); } static gboolean should_skip_extension_ref (FlatpakInstalledRef *iref) { const gchar *ref_name = flatpak_ref_get_name (FLATPAK_REF (iref)); /* These get updated with their parents and look really bad in the UI */ return g_str_has_suffix (ref_name, ".Locale") || g_str_has_suffix (ref_name, ".Debug") || g_str_has_suffix (ref_name, ".Sources"); } static DexFuture * retrieve_updates_fiber (GatherRefsData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) system_refs = NULL; guint n_sys_refs = 0; g_autoptr (GPtrArray) user_refs = NULL; guint n_user_refs = 0; g_autoptr (GPtrArray) ids = NULL; bz_weak_get_or_return_reject (self, data->self); if (self->system != NULL) { system_refs = flatpak_installation_list_installed_refs_for_update ( self->system, cancellable, &local_error); if (system_refs == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to discover update-elligible refs for system installation: %s", local_error->message); n_sys_refs = system_refs->len; } if (self->user != NULL) { user_refs = flatpak_installation_list_installed_refs_for_update ( self->user, cancellable, &local_error); if (user_refs == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, "Failed to discover update-elligible refs for user installation: %s", local_error->message); n_user_refs = user_refs->len; } ids = g_ptr_array_new_with_free_func (g_free); for (guint i = 0; i < n_sys_refs + n_user_refs; i++) { gboolean user = FALSE; FlatpakInstalledRef *iref = NULL; if (i < n_sys_refs) { user = FALSE; iref = g_ptr_array_index (system_refs, i); } else { user = TRUE; iref = g_ptr_array_index (user_refs, i - n_sys_refs); } if (should_skip_extension_ref (iref)) continue; g_ptr_array_add (ids, bz_flatpak_ref_format_unique (FLATPAK_REF (iref), user)); } return dex_future_new_take_boxed ( G_TYPE_PTR_ARRAY, g_steal_pointer (&ids)); } static DexFuture * list_repositories_fiber (ListReposData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GPtrArray) system_repos = NULL; g_autoptr (GPtrArray) user_repos = NULL; g_autoptr (GListStore) repos = NULL; cancellable = data->cancellable; bz_weak_get_or_return_reject (self, data->self); repos = g_list_store_new (BZ_TYPE_REPOSITORY); if (self->system != NULL) { system_repos = flatpak_installation_list_remotes ( self->system, cancellable, &local_error); if (system_repos == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for system installation: %s", local_error->message); for (guint i = 0; i < system_repos->len; i++) { FlatpakRemote *remote = NULL; g_autoptr (BzRepository) repo = NULL; remote = g_ptr_array_index (system_repos, i); repo = g_object_new (BZ_TYPE_REPOSITORY, "name", flatpak_remote_get_name (remote), "title", flatpak_remote_get_title (remote), "url", flatpak_remote_get_url (remote), "is-user", FALSE, NULL); g_list_store_append (repos, repo); } } if (self->user != NULL) { user_repos = flatpak_installation_list_remotes ( self->user, cancellable, &local_error); if (user_repos == NULL) SEND_AND_RETURN_ERROR ( self, TRUE, BZ_FLATPAK_ERROR_CANNOT_INITIALIZE, "Failed to enumerate remotes for user installation: %s", local_error->message); for (guint i = 0; i < user_repos->len; i++) { FlatpakRemote *remote = NULL; g_autoptr (BzRepository) repo = NULL; remote = g_ptr_array_index (user_repos, i); repo = g_object_new (BZ_TYPE_REPOSITORY, "name", flatpak_remote_get_name (remote), "title", flatpak_remote_get_title (remote), "url", flatpak_remote_get_url (remote), "is-user", TRUE, NULL); g_list_store_append (repos, repo); } } return dex_future_new_for_object (g_steal_pointer (&repos)); } static DexFuture * transaction_fiber (TransactionData *data) { g_autoptr (BzFlatpakInstance) self = NULL; GCancellable *cancellable = data->cancellable; GPtrArray *installations = data->installs; GPtrArray *updates = data->updates; GPtrArray *removals = data->removals; DexChannel *channel = data->channel; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autoptr (GPtrArray) transactions = NULL; g_autoptr (GPtrArray) entries = NULL; g_autoptr (GPtrArray) jobs = NULL; g_autoptr (GHashTable) errored = NULL; bz_weak_get_or_return_reject (self, data->self); transactions = g_ptr_array_new_with_free_func (g_object_unref); entries = g_ptr_array_new_with_free_func (g_object_unref); if (installations != NULL) { for (guint i = 0; i < installations->len; i++) { BzFlatpakEntry *entry = NULL; FlatpakRef *ref = NULL; gboolean is_user = FALSE; g_autofree char *ref_fmt = NULL; g_autoptr (FlatpakTransaction) transaction = NULL; entry = g_ptr_array_index (installations, i); ref = bz_flatpak_entry_get_ref (entry); is_user = bz_flatpak_entry_is_user (BZ_FLATPAK_ENTRY (entry)); ref_fmt = flatpak_ref_format_ref (ref); if ((is_user && self->user == NULL) || (!is_user && self->system == NULL)) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the update of %s to transaction " "because its installation couldn't be found", ref_fmt); } transaction = flatpak_transaction_new_for_installation ( is_user ? self->user : self->system, cancellable, &local_error); if (transaction == NULL) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to initialize potential transaction for installation: %s", local_error->message); } result = flatpak_transaction_add_install ( transaction, bz_entry_get_remote_repo_name (BZ_ENTRY (entry)), ref_fmt, NULL, &local_error); if (!result) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the installation of %s to transaction: %s", ref_fmt, local_error->message); } g_ptr_array_add (transactions, g_steal_pointer (&transaction)); g_ptr_array_add (entries, g_object_ref (entry)); g_hash_table_replace (data->ref_to_entry_hash, g_steal_pointer (&ref_fmt), g_object_ref (entry)); } } if (updates != NULL) { g_autoptr (FlatpakTransaction) user_transaction = NULL; g_autoptr (FlatpakTransaction) sys_transaction = NULL; for (guint i = 0; i < updates->len; i++) { BzFlatpakEntry *entry = NULL; FlatpakRef *ref = NULL; gboolean is_user = FALSE; g_autofree char *ref_fmt = NULL; entry = g_ptr_array_index (updates, i); ref = bz_flatpak_entry_get_ref (entry); is_user = bz_flatpak_entry_is_user (BZ_FLATPAK_ENTRY (entry)); ref_fmt = flatpak_ref_format_ref (ref); if ((is_user && self->user == NULL) || (!is_user && self->system == NULL)) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the update of %s to transaction " "because its installation couldn't be found", ref_fmt); } if (is_user && user_transaction == NULL) user_transaction = flatpak_transaction_new_for_installation ( self->user, cancellable, &local_error); else if (!is_user && sys_transaction == NULL) sys_transaction = flatpak_transaction_new_for_installation ( self->system, cancellable, &local_error); if ((is_user && user_transaction == NULL) || (!is_user && sys_transaction == NULL)) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to initialize potential transaction for installation: %s", local_error->message); } /* Put updates in one transaction to prevent dependency race-conditions, since the update list is most likely coming from this instance */ result = flatpak_transaction_add_update ( is_user ? user_transaction : sys_transaction, ref_fmt, NULL, NULL, &local_error); if (!result) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the update of %s to transaction: %s", ref_fmt, local_error->message); } g_ptr_array_add (entries, g_object_ref (entry)); g_hash_table_replace (data->ref_to_entry_hash, g_steal_pointer (&ref_fmt), g_object_ref (entry)); } if (user_transaction != NULL) g_ptr_array_add (transactions, g_steal_pointer (&user_transaction)); if (sys_transaction != NULL) g_ptr_array_add (transactions, g_steal_pointer (&sys_transaction)); } if (removals != NULL) { for (guint i = 0; i < removals->len; i++) { BzFlatpakEntry *entry = NULL; FlatpakRef *ref = NULL; gboolean is_user = FALSE; g_autofree char *ref_fmt = NULL; g_autoptr (FlatpakTransaction) transaction = NULL; entry = g_ptr_array_index (removals, i); ref = bz_flatpak_entry_get_ref (entry); is_user = bz_flatpak_entry_is_user (BZ_FLATPAK_ENTRY (entry)); ref_fmt = flatpak_ref_format_ref (ref); if ((is_user && self->user == NULL) || (!is_user && self->system == NULL)) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the removal of %s to transaction " "because its installation couldn't be found", ref_fmt); } transaction = flatpak_transaction_new_for_installation ( is_user ? self->user : self->system, cancellable, &local_error); if (transaction == NULL) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to initialize potential transaction for installation: %s", local_error->message); } result = flatpak_transaction_add_uninstall ( transaction, ref_fmt, &local_error); if (!result) { dex_channel_close_send (channel); return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to append the removal of %s to transaction: %s", ref_fmt, local_error->message); } g_ptr_array_add (transactions, g_steal_pointer (&transaction)); g_ptr_array_add (entries, g_object_ref (entry)); g_hash_table_replace (data->ref_to_entry_hash, g_steal_pointer (&ref_fmt), g_object_ref (entry)); } } jobs = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < transactions->len; i++) { FlatpakTransaction *transaction = NULL; g_autoptr (TransactionJobData) job_data = NULL; transaction = g_ptr_array_index (transactions, i); job_data = transaction_job_data_new (); job_data->parent = transaction_data_ref (data); job_data->transaction = g_object_ref (transaction); g_ptr_array_add ( jobs, dex_scheduler_spawn ( self->scheduler, bz_get_dex_stack_size (), (DexFiberFunc) transaction_job_fiber, transaction_job_data_ref (job_data), transaction_job_data_unref)); } dex_await (dex_future_all_racev ( (DexFuture *const *) jobs->pdata, jobs->len), NULL); if (data->send_futures->len > 0) dex_await (dex_future_allv ( (DexFuture *const *) data->send_futures->pdata, data->send_futures->len), NULL); errored = g_hash_table_new_full ( g_direct_hash, g_direct_equal, g_object_unref, (GDestroyNotify) g_error_free); for (guint i = 0; i < jobs->len; i++) { DexFuture *job = NULL; BzEntry *entry = NULL; job = g_ptr_array_index (jobs, i); entry = g_ptr_array_index (entries, i); dex_future_get_value (job, &local_error); if (local_error != NULL) g_hash_table_replace ( errored, g_object_ref (entry), g_steal_pointer (&local_error)); } dex_channel_close_send (channel); return dex_future_new_take_boxed (G_TYPE_HASH_TABLE, g_steal_pointer (&errored)); } static DexFuture * transaction_job_fiber (TransactionJobData *data) { TransactionData *parent = data->parent; FlatpakTransaction *transaction = data->transaction; GCancellable *cancellable = parent->cancellable; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_signal_connect (transaction, "new-operation", G_CALLBACK (transaction_new_operation), parent); g_signal_connect (transaction, "operation-done", G_CALLBACK (transaction_operation_done), parent); g_signal_connect (transaction, "operation-error", G_CALLBACK (transaction_operation_error), parent); g_signal_connect (transaction, "ready", G_CALLBACK (transaction_ready), parent); result = flatpak_transaction_run (transaction, cancellable, &local_error); if (!result) return dex_future_new_reject ( BZ_FLATPAK_ERROR, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, "Failed to run flatpak transaction on installation: %s", local_error->message); return dex_future_new_true (); } static void transaction_new_operation (FlatpakTransaction *transaction, FlatpakTransactionOperation *operation, FlatpakTransactionProgress *progress, TransactionData *data) { g_autoptr (BzFlatpakInstance) self = NULL; FlatpakTransactionOperationType kind = 0; BzFlatpakEntry *entry = NULL; g_autoptr (BzBackendTransactionOpPayload) payload = NULL; g_autoptr (TransactionOperationData) operation_data = NULL; bz_weak_get_or_return (self, data->self); kind = flatpak_transaction_operation_get_operation_type (operation); if (kind == FLATPAK_TRANSACTION_OPERATION_INSTALL || kind == FLATPAK_TRANSACTION_OPERATION_UPDATE || kind == FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE || kind == FLATPAK_TRANSACTION_OPERATION_UNINSTALL) { g_mutex_lock (&self->mute_mutex); if (self->user == flatpak_transaction_get_installation (transaction)) self->user_mute++; else self->system_mute++; g_mutex_unlock (&self->mute_mutex); } if (data->channel == NULL) return; flatpak_transaction_progress_set_update_frequency (progress, 100); entry = find_entry_from_operation (data, operation); payload = bz_backend_transaction_op_payload_new (); bz_backend_transaction_op_payload_set_entry ( payload, BZ_ENTRY (entry)); bz_backend_transaction_op_payload_set_name ( payload, flatpak_transaction_operation_get_ref (operation)); bz_backend_transaction_op_payload_set_download_size ( payload, flatpak_transaction_operation_get_download_size (operation)); bz_backend_transaction_op_payload_set_installed_size ( payload, flatpak_transaction_operation_get_installed_size (operation)); g_mutex_lock (&data->mutex); g_ptr_array_add ( data->send_futures, dex_channel_send ( data->channel, dex_future_new_for_object (payload))); data->unidentified_op_cnt--; g_mutex_unlock (&data->mutex); g_object_set_data_full ( G_OBJECT (operation), "payload", g_object_ref (payload), g_object_unref); operation_data = transaction_operation_data_new (); operation_data->parent = transaction_data_ref (data); operation_data->entry = bz_object_maybe_ref (entry); operation_data->op = g_object_ref (payload); g_signal_connect_data ( progress, "changed", G_CALLBACK (transaction_progress_changed), transaction_operation_data_ref (operation_data), transaction_operation_data_unref_closure, G_CONNECT_DEFAULT); } static void transaction_operation_done (FlatpakTransaction *transaction, FlatpakTransactionOperation *operation, gchar *commit, gint result, TransactionData *data) { g_autoptr (BzFlatpakInstance) self = NULL; g_autoptr (BzBackendTransactionOpPayload) payload = NULL; FlatpakTransactionOperationType op_type = 0; BzBackendNotificationKind notif_kind = 0; const char *origin = NULL; const char *ref = NULL; gboolean is_user = FALSE; g_autofree char *unique_id = NULL; g_autoptr (BzBackendNotification) notif = NULL; const char *version = NULL; FlatpakInstallation *installation = NULL; g_autoptr (FlatpakInstalledRef) iref = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (FlatpakRef) parsed_ref = NULL; bz_weak_get_or_return (self, data->self); g_mutex_lock (&data->mutex); g_hash_table_replace ( data->op_to_progress_hash, g_object_ref (operation), GINT_TO_POINTER (100)); payload = g_object_steal_data (G_OBJECT (operation), "payload"); if (payload != NULL) g_ptr_array_add ( data->send_futures, dex_channel_send ( data->channel, dex_future_new_for_object (payload))); g_mutex_unlock (&data->mutex); if (result == FLATPAK_TRANSACTION_RESULT_NO_CHANGE) return; op_type = flatpak_transaction_operation_get_operation_type (operation); switch (op_type) { case FLATPAK_TRANSACTION_OPERATION_INSTALL: case FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: notif_kind = BZ_BACKEND_NOTIFICATION_KIND_INSTALL_DONE; break; case FLATPAK_TRANSACTION_OPERATION_UPDATE: notif_kind = BZ_BACKEND_NOTIFICATION_KIND_UPDATE_DONE; break; case FLATPAK_TRANSACTION_OPERATION_UNINSTALL: notif_kind = BZ_BACKEND_NOTIFICATION_KIND_REMOVE_DONE; break; case FLATPAK_TRANSACTION_OPERATION_LAST_TYPE: default: g_assert_not_reached (); } origin = flatpak_transaction_operation_get_remote (operation); ref = flatpak_transaction_operation_get_ref (operation); is_user = flatpak_transaction_get_installation (transaction) == self->user; unique_id = bz_flatpak_ref_parts_format_unique (origin, ref, is_user); if (notif_kind == BZ_BACKEND_NOTIFICATION_KIND_INSTALL_DONE || notif_kind == BZ_BACKEND_NOTIFICATION_KIND_UPDATE_DONE) { installation = flatpak_transaction_get_installation (transaction); parsed_ref = flatpak_ref_parse (ref, &local_error); if (parsed_ref != NULL) { iref = flatpak_installation_get_installed_ref ( installation, flatpak_ref_get_kind (parsed_ref), flatpak_ref_get_name (parsed_ref), flatpak_ref_get_arch (parsed_ref), flatpak_ref_get_branch (parsed_ref), NULL, &local_error); if (iref != NULL) version = flatpak_installed_ref_get_appdata_version (iref); else if (local_error != NULL) { g_warning ("Failed to get installed ref for version: %s", local_error->message); g_clear_error (&local_error); } } else if (local_error != NULL) { g_warning ("Failed to parse ref for version: %s", local_error->message); g_clear_error (&local_error); } } notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, notif_kind); bz_backend_notification_set_unique_id (notif, unique_id); if (version != NULL && *version != '\0') bz_backend_notification_set_version (notif, version); send_notif_all (self, notif, TRUE); } static gboolean transaction_operation_error (FlatpakTransaction *object, FlatpakTransactionOperation *operation, GError *error, gint details, TransactionData *data) { g_autoptr (BzBackendTransactionOpPayload) payload = NULL; /* `FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL` is the only possible value of `details` */ g_warning ("Transaction failed to complete: %s", error->message); g_mutex_lock (&data->mutex); g_hash_table_replace ( data->op_to_progress_hash, g_object_ref (operation), GINT_TO_POINTER (100)); payload = g_object_steal_data (G_OBJECT (operation), "payload"); if (payload != NULL) { g_object_set_data_full ( G_OBJECT (payload), "error", g_strdup (error->message), g_free); g_ptr_array_add ( data->send_futures, dex_channel_send ( data->channel, dex_future_new_for_object (payload))); } g_mutex_unlock (&data->mutex); /* Don't recover for now */ return FALSE; } static gboolean transaction_ready (FlatpakTransaction *object, TransactionData *data) { g_autolist (GObject) operations = NULL; operations = flatpak_transaction_get_operations (object); g_mutex_lock (&data->mutex); data->unidentified_op_cnt += g_list_length (operations); g_mutex_unlock (&data->mutex); return TRUE; } static BzFlatpakEntry * find_entry_from_operation (TransactionData *data, FlatpakTransactionOperation *operation) { GPtrArray *related_to_ops = NULL; const char *ref_fmt = NULL; BzFlatpakEntry *entry = NULL; related_to_ops = flatpak_transaction_operation_get_related_to_ops (operation); ref_fmt = flatpak_transaction_operation_get_ref (operation); entry = g_hash_table_lookup (data->ref_to_entry_hash, ref_fmt); if (entry != NULL) return entry; if (related_to_ops != NULL) { for (guint i = 0; i < related_to_ops->len; i++) { FlatpakTransactionOperation *related_op = NULL; related_op = g_ptr_array_index (related_to_ops, i); entry = find_entry_from_operation (data, related_op); if (entry != NULL) break; } } return entry; } static void transaction_progress_changed (FlatpakTransactionProgress *progress, TransactionOperationData *data) { TransactionData *parent = data->parent; g_autoptr (BzBackendTransactionOpProgressPayload) payload = NULL; int int_progress = 0; double double_progress = 0.0; GHashTableIter iter = { 0 }; int progress_sum = 0; guint n_ops = 0; double total_progress = 0.0; g_mutex_lock (&parent->mutex); int_progress = flatpak_transaction_progress_get_progress (progress); double_progress = (double) flatpak_transaction_progress_get_progress (progress) / 100.0; g_hash_table_replace ( parent->op_to_progress_hash, g_object_ref (data->op), GINT_TO_POINTER (int_progress)); g_hash_table_iter_init (&iter, parent->op_to_progress_hash); for (;;) { gpointer key = NULL; gpointer val = NULL; if (!g_hash_table_iter_next (&iter, &key, &val)) break; progress_sum += GPOINTER_TO_INT (val); n_ops++; } total_progress = MIN ((double) progress_sum / (double) ((n_ops + parent->unidentified_op_cnt) * 100), 1.0); payload = bz_backend_transaction_op_progress_payload_new (); bz_backend_transaction_op_progress_payload_set_op ( payload, data->op); bz_backend_transaction_op_progress_payload_set_status ( payload, flatpak_transaction_progress_get_status (progress)); bz_backend_transaction_op_progress_payload_set_is_estimating ( payload, flatpak_transaction_progress_get_is_estimating (progress)); bz_backend_transaction_op_progress_payload_set_progress ( payload, double_progress); bz_backend_transaction_op_progress_payload_set_total_progress ( payload, total_progress); bz_backend_transaction_op_progress_payload_set_bytes_transferred ( payload, flatpak_transaction_progress_get_bytes_transferred (progress)); bz_backend_transaction_op_progress_payload_set_start_time ( payload, flatpak_transaction_progress_get_start_time (progress)); g_ptr_array_add ( data->parent->send_futures, dex_channel_send ( data->parent->channel, dex_future_new_for_object (payload))); g_mutex_unlock (&parent->mutex); } static void installation_event (BzFlatpakInstance *self, GFile *file, GFile *other_file, GFileMonitorEvent event_type, GFileMonitor *monitor) { gboolean emit = FALSE; g_autoptr (BzBackendNotification) notif = NULL; g_mutex_lock (&self->mute_mutex); if (monitor == self->user_events) { if (self->user_mute > 0) self->user_mute--; else emit = TRUE; } else { if (self->system_mute > 0) self->system_mute--; else emit = TRUE; } g_mutex_unlock (&self->mute_mutex); if (!emit) return; notif = bz_backend_notification_new (); bz_backend_notification_set_kind (notif, BZ_BACKEND_NOTIFICATION_KIND_EXTERNAL_CHANGE); send_notif_all (self, notif, TRUE); } static void send_notif (BzFlatpakInstance *self, DexChannel *channel, BzBackendNotification *notif, gboolean lock) { g_autoptr (GMutexLocker) locker = NULL; if (lock) locker = g_mutex_locker_new (&self->notif_mutex); if (self->notif_send == NULL || !dex_future_is_pending (self->notif_send)) { dex_clear (&self->notif_send); self->notif_send = dex_channel_send ( channel, dex_future_new_for_object (notif)); } else { g_autoptr (WaitNotifData) data = NULL; data = wait_notif_data_new (); g_weak_ref_init (&data->self, self); data->channel = dex_ref (channel); data->notif = g_object_ref (notif); self->notif_send = dex_future_finally ( g_steal_pointer (&self->notif_send), (DexFutureCallback) wait_notif_finally, wait_notif_data_ref (data), wait_notif_data_unref); } } static void send_notif_all (BzFlatpakInstance *self, BzBackendNotification *notif, gboolean lock) { g_autoptr (GMutexLocker) locker = NULL; if (lock) locker = g_mutex_locker_new (&self->notif_mutex); for (guint i = 0; i < self->notif_channels->len;) { DexChannel *channel = NULL; channel = g_ptr_array_index (self->notif_channels, i); if (dex_channel_can_send (channel)) { send_notif (self, channel, notif, FALSE); i++; } else g_ptr_array_remove_index_fast (self->notif_channels, i); } } static DexFuture * wait_notif_finally (DexFuture *future, WaitNotifData *data) { g_autoptr (BzFlatpakInstance) self = NULL; g_autoptr (GMutexLocker) locker = NULL; bz_weak_get_or_return_reject (self, &data->self); locker = g_mutex_locker_new (&self->notif_mutex); if (future == self->notif_send) dex_clear (&self->notif_send); send_notif (self, data->channel, data->notif, FALSE); return dex_future_new_true (); } static gint cmp_rref (FlatpakRemoteRef *a, FlatpakRemoteRef *b, GHashTable *hash) { FlatpakRefKind a_fkind = 0; FlatpakRefKind b_fkind = 0; AsComponent *a_comp = NULL; AsComponent *b_comp = NULL; AsComponentKind a_kind = AS_COMPONENT_KIND_UNKNOWN; AsComponentKind b_kind = AS_COMPONENT_KIND_UNKNOWN; a_fkind = flatpak_ref_get_kind (FLATPAK_REF (a)); b_fkind = flatpak_ref_get_kind (FLATPAK_REF (b)); a_comp = g_hash_table_lookup (hash, flatpak_ref_get_name (FLATPAK_REF (a))); b_comp = g_hash_table_lookup (hash, flatpak_ref_get_name (FLATPAK_REF (b))); if (a_comp == NULL) return a_fkind == FLATPAK_REF_KIND_RUNTIME ? -1 : 1; if (b_comp == NULL) return b_fkind == FLATPAK_REF_KIND_RUNTIME ? 1 : -1; a_kind = as_component_get_kind (a_comp); b_kind = as_component_get_kind (b_comp); if (a_kind == AS_COMPONENT_KIND_RUNTIME) return -1; if (b_kind == AS_COMPONENT_KIND_RUNTIME) return 1; if (a_kind == AS_COMPONENT_KIND_ADDON) return -1; if (b_kind == AS_COMPONENT_KIND_ADDON) return 1; if (a_kind == AS_COMPONENT_KIND_DESKTOP_APP || a_kind == AS_COMPONENT_KIND_CONSOLE_APP || a_kind == AS_COMPONENT_KIND_WEB_APP) return 1; if (b_kind == AS_COMPONENT_KIND_DESKTOP_APP || b_kind == AS_COMPONENT_KIND_CONSOLE_APP || b_kind == AS_COMPONENT_KIND_WEB_APP) return -1; return 0; } static AsComponent * parse_component_for_node (XbNode *node, GError **error) { g_autofree char *component_xml = NULL; g_autoptr (AsMetadata) metadata = NULL; AsComponent *component = NULL; gboolean result = FALSE; component_xml = xb_node_export (node, XB_NODE_EXPORT_FLAG_NONE, error); if (component_xml == NULL) return NULL; metadata = as_metadata_new (); result = as_metadata_parse_data ( metadata, component_xml, -1, AS_FORMAT_KIND_XML, error); if (!result) return NULL; component = as_metadata_get_component (metadata); return bz_object_maybe_ref (component); } static GBytes * decompress_appstream_gz (GBytes *appstream_gz, GCancellable *cancellable, GError **error) { g_autoptr (GZlibDecompressor) decompressor = NULL; g_autoptr (GInputStream) stream_gz = NULL; g_autoptr (GInputStream) stream_data = NULL; g_autoptr (GBytes) appstream = NULL; decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); stream_gz = g_memory_input_stream_new_from_bytes (appstream_gz); stream_data = g_converter_input_stream_new (stream_gz, G_CONVERTER (decompressor)); appstream = g_input_stream_read_bytes ( stream_data, 0x100000, /* 1MB */ cancellable, error); if (appstream == NULL) return NULL; return g_steal_pointer (&appstream); } static XbSilo * build_silo (XbBuilderSource *source, GCancellable *cancellable, GError **error) { g_autoptr (XbBuilder) builder = NULL; const gchar *const *locales = NULL; g_autoptr (XbSilo) silo = NULL; builder = xb_builder_new (); locales = g_get_language_names (); for (guint i = 0; locales[i] != NULL; i++) xb_builder_add_locale (builder, locales[i]); xb_builder_import_source (builder, source); silo = xb_builder_compile ( builder, XB_BUILDER_COMPILE_FLAG_NATIVE_LANGS, cancellable, error); return g_steal_pointer (&silo); } static AsComponent * extract_first_component_for_silo (XbSilo *silo, GError **error) { g_autoptr (XbNode) root = NULL; g_autoptr (GPtrArray) children = NULL; root = xb_silo_get_root (silo); children = xb_node_get_children (root); if (children == NULL || children->len == 0) return NULL; return parse_component_for_node ( g_ptr_array_index (children, 0), error); } kolunmi-bazaar-7b9c8e1/src/bz-flatpak-instance.h000066400000000000000000000033101514314607700216540ustar00rootroot00000000000000/* bz-flatpak-instance.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_FLATPAK_ERROR (bz_flatpak_error_quark ()) GQuark bz_flatpak_error_quark (void); typedef enum { BZ_FLATPAK_ERROR_CANNOT_INITIALIZE = 0, BZ_FLATPAK_ERROR_LOCAL_SYNCHRONIZATION_FAILURE, BZ_FLATPAK_ERROR_REMOTE_SYNCHRONIZATION_FAILURE, BZ_FLATPAK_ERROR_TRANSACTION_FAILURE, BZ_FLATPAK_ERROR_IO_MISBEHAVIOR, BZ_FLATPAK_ERROR_APPSTREAM_FAILURE, BZ_FLATPAK_ERROR_GLYCIN_FAILURE, } BzFlatpakError; #define BZ_TYPE_FLATPAK_INSTANCE (bz_flatpak_instance_get_type ()) G_DECLARE_FINAL_TYPE (BzFlatpakInstance, bz_flatpak_instance, BZ, FLATPAK_INSTANCE, GObject) DexFuture * bz_flatpak_instance_new (void); DexFuture * bz_flatpak_instance_has_flathub (BzFlatpakInstance *self, GCancellable *cancellable); DexFuture * bz_flatpak_instance_ensure_has_flathub (BzFlatpakInstance *self, GCancellable *cancellable); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-flatpak-private.h000066400000000000000000000034411514314607700215270ustar00rootroot00000000000000/* bz-flatpak-private.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include "bz-flatpak-entry.h" #include "bz-flatpak-instance.h" G_BEGIN_DECLS /* BzFlatpakInstance */ FlatpakInstallation * bz_flatpak_instance_get_system_installation (BzFlatpakInstance *self); FlatpakInstallation * bz_flatpak_instance_get_user_installation (BzFlatpakInstance *self); /* BzFlatpakEntry */ char * bz_flatpak_ref_parts_format_unique (const char *origin, const char *fmt, gboolean user); char * bz_flatpak_ref_format_unique (FlatpakRef *ref, gboolean user); BzFlatpakEntry * bz_flatpak_entry_new_for_ref (FlatpakRef *ref, FlatpakRemote *remote, gboolean user, AsComponent *component, const char *appstream_dir, GError **error); FlatpakRef * bz_flatpak_entry_get_ref (BzFlatpakEntry *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-full-view.blp000066400000000000000000001114111514314607700206720ustar00rootroot00000000000000using Gtk 4.0; using Gio 2.0; using Adw 1; template $BzFullView: Adw.Bin { child: Adw.ToolbarView { [top] Adw.HeaderBar header_bar { overflow: hidden; [title] Revealer { reveal-child: bind $is_scrolled_down(main_scroll.vadjustment as .value) as ; transition-type: slide_up; transition-duration: 500; overflow: visible; child: Label { label: bind template.entry-group as <$BzEntryGroup>.title; styles ["title"] }; } [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: bind template.main-menu; } [end] Button { styles [ "flat", "global-progress-button", ] can-target: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; action-name: "window.open-library"; has-tooltip: true; tooltip-text: _("Open App Library"); child: $BzGlobalProgress { expand-size: 125; active: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; pending: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.pending; fraction: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.current-progress; settings: bind template.state as <$BzStateInfo>.settings; }; } } content: Adw.ViewStack stack { enable-transitions: true; Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "sad-computer-symbolic"; title: _("No Results"); description: _("Try a different search query"); }; } Adw.ViewStackPage { name: "content"; title: _("Content"); child: Adw.BreakpointBin { width-request: 360; height-request: 450; Adw.Breakpoint { condition ("max-width: 700px") setters { context_bar.orientation: vertical; context_bar.spacing: 4; context_bar.homogeneous: false; header_box.spacing: 12; app_name_box.spacing: 0; formfactor_support_tile_wide.visible: false; formfactor_support_tile_narrow.visible: true; screenshots.compact: true; header_bar.show-title: false; } } child: Adw.BreakpointBin breakpoint_bin { width-request: 360; height-request: 450; Adw.Breakpoint breakpoint { condition ("max-width: 500px") setters { top_box.margin-start: 10; top_box.margin-end: 10; bottom_box.margin-start: 10; bottom_box.margin-end: 10; bottom_box.margin-top: 5; wide_install_controls.visible: false; narrow_install_controls.visible: true; app_icon.valign: start; app_icon.pixel-size: 96; } } child: Overlay { [overlay] Box shadow_overlay { valign: start; height-request: 3; can-target: false; } child: ScrolledWindow main_scroll { child: Box main_box { orientation: vertical; vexpand: false; margin-bottom: 15; spacing: 20; Adw.Banner { title: _("Installing .flatpak bundles is not yet supported"); revealed: bind template.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.is-bundle as ; } Adw.Clamp { maximum-size: 860; tightening-threshold: 1000; margin-top: 15; child: Box top_box { orientation: vertical; margin-start: 25; margin-end: 25; spacing: 20; Box header_box { orientation: horizontal; spacing: 20; Image app_icon { valign: center; halign: center; pixel-size: 128; paintable: bind template.entry-group as <$BzEntryGroup>.icon-paintable; visible: bind $invert_boolean($is_null(template.entry-group as <$BzEntryGroup>.icon-paintable) as ) as ; styles [ "icon-dropshadow", ] } Image fallback_icon { valign: center; halign: center; pixel-size: 128; icon-name: "application-x-executable"; visible: bind $is_null(template.entry-group as <$BzEntryGroup>.icon-paintable) as ; styles [ "icon-dropshadow", ] } Box not_icon { orientation: horizontal; baseline-position: center; halign: fill; hexpand: true; spacing: 15; Box app_name_box { orientation: vertical; valign: center; hexpand: true; spacing: 3; Label { styles [ "title-1", "app-title", ] xalign: 0.0; wrap: true; wrap-mode: word_char; natural-wrap-mode: word; label: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.title; } $BzDeveloperBadge { entry: bind template.ui-entry as <$BzResult>.object as <$BzEntry>; } Box { spacing: 8; Button { visible: bind $invert_boolean($is_null(template.ui-entry as <$BzResult>.object as <$BzEntry>.donation-url) as ) as ; styles [ "small-pill", "suggested-action", "support", ] margin-top: 8; valign: start; halign: start; has-tooltip: true; tooltip-text: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.donation-url; clicked => $support_cb(template); child: Adw.ButtonContent { label: _("Support"); icon-name: "heart-filled-symbolic"; }; } $BzFavoriteButton { state: bind template.state as <$BzStateInfo>; entry: bind template.ui-entry as <$BzResult>.object as <$BzEntry>; } } } Box wide_install_controls { orientation: horizontal; spacing: 10; valign: center; Button wide_open_button { styles [ "pill", ] has-tooltip: true; label: _("Open"); visible: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $run_cb(template); } Button wide_install_button { styles [ "suggested-action", "pill", ] has-tooltip: true; tooltip-text: _("Download & Install Application"); visible: bind $logical_and($invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable) as ) as , $is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable-and-available) as ) as ; label: _("Install"); clicked => $install_cb(template); } Button { styles [ "destructive-action", "circular", ] width-request: 45; has-tooltip: true; tooltip-text: _("Uninstall Application"); visible: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; icon-name: "user-trash-symbolic"; clicked => $remove_cb(template); } Button { styles [ "circular", ] width-request: 45; has-tooltip: true; icon-name: "download-plus-symbolic"; tooltip-text: _("Install Other Version"); visible: bind $logical_and($invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable) as ) as , $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable-and-available) as ) as ; clicked => $install_cb(template); } } } } Box context_bar { hexpand: false; homogeneous: true; spacing: 0; orientation: horizontal; halign: fill; styles [ "app-context-bar", ] Box { homogeneous: true; $BzContextTile download_size_tile { label: bind $get_size_label($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; has-tooltip: true; tooltip-text: bind $format_size_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>.size) as ; lozenge-style: "grey"; sensitive: bind $invert_boolean($is_zero($get_size_type(template.ui-entry as <$BzResult>.object as <$BzEntry>, $is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ) as ) as ; clicked => $size_cb(template); lozenge-child: Label { justify: center; label: bind $format_size($get_size_type(template.ui-entry as <$BzResult>.object as <$BzEntry>, $is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ) as ; lines: 3; ellipsize: end; halign: center; wrap: true; xalign: 0.5; use-markup: true; }; } $BzContextTile license_tile { label: bind $get_license_label(template.ui-entry as <$BzResult>.object as <$BzEntry>) as ; lozenge-style: bind $bool_to_string(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, "grey", "warning") as ; clicked => $license_cb(template); has-tooltip: true; tooltip-text: bind $format_license_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>) as ; lozenge-child: Box { spacing: 6; Image { icon-name: bind $get_license_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, 0) as ; } Image { icon-name: bind $get_license_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-floss, 1) as ; } }; } $BzContextTile { clicked => $safety_cb(template); label: bind $get_safety_rating_label(template.ui-entry as <$BzResult>.object as <$BzEntry>) as ; lozenge-style: bind $get_safety_rating_style(template.ui-entry as <$BzResult>.object as <$BzEntry>) as ; lozenge-child: Box { spacing: 4; Image { icon-name: bind $get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,0) as ; visible: bind $invert_boolean($is_empty_string($get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,0) as ) as ) as ; } Image { icon-name: bind $get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,1) as ; visible: bind $invert_boolean($is_empty_string($get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,1) as ) as ) as ; } Image { icon-name: bind $get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,2) as ; visible: bind $invert_boolean($is_empty_string($get_safety_rating_icon(template.ui-entry as <$BzResult>.object as <$BzEntry>,2) as ) as ) as ; } }; } } Box { homogeneous: true; $BzContextTile formfactor_support_tile_wide { label: bind $get_formfactor_label(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; has-tooltip: true; tooltip-text: bind $get_formfactor_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; clicked => $formfactor_cb(template); lozenge-style: "grey"; lozenge-child: Box { Image { visible: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly as ; icon-name: "device-support-adaptive-symbolic"; pixel-size: 56; styles [ "wide-image", ] } Image { visible: bind $invert_boolean(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; icon-name: "device-support-desktop-symbolic"; } }; } $BzContextTile formfactor_support_tile_narrow { visible: false; label: bind $get_formfactor_label(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; has-tooltip: true; tooltip-text: bind $get_formfactor_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; lozenge-style: bind $bool_to_string(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly, "grey", "error") as ; clicked => $formfactor_cb(template); lozenge-child: Box { Image { visible: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly as ; icon-name: "smartphone2-symbolic"; } Image { visible: bind $invert_boolean(template.ui-entry as <$BzResult>.object as <$BzEntry>.is-mobile-friendly) as ; icon-name: "device-support-desktop-symbolic"; } }; } $BzContextTile { clicked => $age_rating_cb(template); has-tooltip: true; tooltip-text: bind $get_age_rating_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>.content-rating) as ; label: bind $get_age_rating_label(template.ui-entry as <$BzResult>.object as <$BzEntry>.content-rating) as ; lozenge-style: bind $get_age_rating_style(template.ui-entry as <$BzResult>.object as <$BzEntry>.content-rating) as ; lozenge-child: Label { label: bind $format_age_rating(template.ui-entry as <$BzResult>.object as <$BzEntry>.content-rating) as ; hexpand: true; }; } $BzContextTile { can-target: bind $invert_boolean($is_null(template.ui-entry) as ) as ; sensitive: bind $invert_boolean($is_null(template.ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ) as ; clicked => $dl_stats_cb(template); label: _("Downloads/Month"); has-tooltip: bind $invert_boolean($is_null(template.ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ) as ; tooltip-text: bind $format_recent_downloads_tooltip(template.ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ; lozenge-style: "grey"; lozenge-child: Label { justify: center; label: bind $format_recent_downloads(template.ui-entry as <$BzResult>.object as <$BzEntry>.recent-downloads) as ; halign: center; use-markup: true; }; } } } Box narrow_install_controls { orientation: horizontal; spacing: 8; margin-start: 4; margin-end: 4; valign: center; visible: false; Box { homogeneous: true; spacing: 8; hexpand: true; Button narrow_install_button { styles [ "suggested-action", "pill", ] hexpand: true; has-tooltip: true; tooltip-text: _("Download & Install Application"); visible: bind $logical_and($invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable) as ) as , $is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable-and-available) as ) as ; label: _("Install"); clicked => $install_cb(template); } Button { styles [ "destructive-action", "circular", ] hexpand: true; visible: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; label: _("Remove"); clicked => $remove_cb(template); } Button narrow_open_button { styles [ "pill", ] hexpand: true; has-tooltip: true; label: _("Open"); visible: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $run_cb(template); } } Button { styles [ "circular", ] width-request: 45; has-tooltip: true; icon-name: "download-plus-symbolic"; tooltip-text: _("Install Other Version"); visible: bind $logical_and($invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable) as ) as , $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ) as ; sensitive: bind $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable-and-available) as ) as ; clicked => $install_cb(template); } } Box { visible: bind $invert_boolean($is_null(template.entry-group as <$BzEntryGroup>.eol) as ) as ; orientation: vertical; spacing: 8; styles [ "card", "colored", "warning", ] Label { label: _("Stopped Receiving Core Updates"); margin-top: 8; margin-start: 8; margin-end: 8; wrap: true; wrap-mode: word_char; justify: center; styles [ "title-4", ] } Label { label: _("This app uses a runtime that no longer receives updates or security fixes. It may become unsafe to use."); margin-bottom: 8; margin-start: 8; margin-end: 8; wrap: true; wrap-mode: word_char; justify: center; } } }; } Box screenshot_box { Adw.Spinner { vexpand: true; visible: bind $invert_boolean(template.ui-entry as <$BzResult>.resolved as ) as ; } $BzScreenshotsCarousel screenshots { vexpand: true; hexpand: true; visible: bind $logical_and( template.ui-entry as <$BzResult>.resolved as , $invert_boolean($is_empty(template.ui-entry as <$BzResult>.object as <$BzEntry>.screenshot-paintables) as ) as ) as ; clicked => $screenshot_clicked_cb() swapped; light-accent-color: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.light-accent-color; dark-accent-color: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.dark-accent-color; model: $BzLazyAsyncTextureModel { model: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.screenshot-paintables; }; } } Adw.Clamp { maximum-size: 860; tightening-threshold: 1000; child: Box { orientation: vertical; Box bottom_box { orientation: vertical; margin-start: 25; margin-end: 25; margin-bottom: 20; margin-top: 10; spacing: 15; Revealer { transition-type: slide_down; reveal-child: bind $logical_and( $logical_and($invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.user-data-size) as ) as ,$is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as , $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.installable-and-available) as ) as ) as ; visible: bind $invert_boolean($logical_and($is_zero(template.entry-group as <$BzEntryGroup>.removable) as , $is_zero(template.entry-group as <$BzEntryGroup>.installable) as ) as ) as ; child: Box { height-request: 50; margin-bottom: 10; spacing: 12; styles [ "card", "colored", "accent", ] Label { halign: start; valign: center; hexpand: true; margin-start: 12; margin-top: 8; margin-bottom: 8; label: bind $format_leftover_label(template.ui-entry as <$BzResult>.object as <$BzEntry>.title, template.entry-group as <$BzEntryGroup>.user-data-size) as ; use-markup: true; wrap: true; wrap-mode: word_char; justify: left; } Button { valign: center; margin-end: 8; clicked => $delete_user_data_cb(template); child: Adw.ButtonContent { icon-name: "user-trash-symbolic"; label: _("Trash Data"); }; } }; } Box { spacing: 10; orientation: vertical; Label { styles [ "title-2", ] valign: start; xalign: 0; wrap: true; wrap-mode: word_char; label: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.description; } $BzFadingClamp fading_clamp { max-height: bind $get_description_max_height(description_toggle.active) as ; min-max-height: 170; child: $BzAppstreamDescriptionRender { appstream-description: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.long-description; }; } } ToggleButton description_toggle { styles [ "circular", ] visible: bind fading_clamp.will-change; halign: center; child: Label { label: bind $get_description_toggle_text(description_toggle.active) as ; margin-start: 16; margin-end: 16; }; } Adw.PreferencesGroup { visible: bind $logical_and($invert_boolean($is_null(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.addons) as ) as , $invert_boolean($is_zero(template.entry-group as <$BzEntryGroup>.removable) as ) as ) as ; Adw.ActionRow { [prefix] Image { icon-name: "puzzle-piece-symbolic"; } [suffix] Image { icon-name: "go-next-symbolic"; styles [ "dimmed", ] } title: _("Manage Add-ons"); activatable: true; activated => $install_addons_cb(template); } } $BzReleasesList releases_list { version-history: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.version-history; installed-versions: bind template.entry-group as <$BzEntryGroup>.installed-versions; } $BzShareList { urls: bind template.ui-entry as <$BzResult>.object as <$BzEntry>.share-urls; } Box { orientation: vertical; visible: bind $has_other_apps(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer-apps, template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>) as ; Label { styles [ "heading", "h4", ] label: bind $format_other_apps_label(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer) as ; xalign: 0; wrap: true; wrap-mode: word_char; margin-bottom: 6; margin-start: 3; } $BzDynamicListView { hexpand: true; scroll: false; noscroll-kind: flow-box; child-type: "BzAppTile"; child-prop: "group"; max-children-per-line: 3; bind-widget => $bind_app_tile_cb(template); unbind-widget => $unbind_app_tile_cb(template); model: SliceListModel { offset: 0; size: 6; model: bind $get_developer_apps_entries(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer-apps, template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>) as ; }; } Button { visible: bind $is_longer(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer-apps, 6) as ; clicked => $more_apps_button_clicked_cb(template); halign: center; margin-top: 11; margin-bottom: 8; child: Label { label: bind $format_more_other_apps_label(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer) as ; justify: center; wrap: true; wrap-mode: word_char; }; styles [ "pill", ] } } $BzTagList { margin-top: 8; flathub-state: bind template.state as <$BzStateInfo>.flathub; select => $tag_list_select_cb(template); prefix: Label { label: _("Tags:"); styles [ "dimmed", ] }; model: SliceListModel { size: 5; model: bind template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.keywords; }; } } }; } }; }; }; }; }; } }; }; } kolunmi-bazaar-7b9c8e1/src/bz-full-view.c000066400000000000000000001123001514314607700203350ustar00rootroot00000000000000/* bz-full-view.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::FULL-VIEW-WIDGET" #include #include #include "bz-addons-dialog.h" #include "bz-age-rating-dialog.h" #include "bz-app-size-dialog.h" #include "bz-app-tile.h" #include "bz-apps-page.h" #include "bz-appstream-description-render.h" #include "bz-context-tile.h" #include "bz-developer-badge.h" #include "bz-dynamic-list-view.h" #include "bz-error.h" #include "bz-fading-clamp.h" #include "bz-favorite-button.h" #include "bz-flatpak-entry.h" #include "bz-full-view.h" #include "bz-hardware-support-dialog.h" #include "bz-lazy-async-texture-model.h" #include "bz-license-dialog.h" #include "bz-releases-list.h" #include "bz-safety-calculator.h" #include "bz-safety-dialog.h" #include "bz-screenshot-page.h" #include "bz-screenshots-carousel.h" #include "bz-section-view.h" #include "bz-share-list.h" #include "bz-spdx.h" #include "bz-state-info.h" #include "bz-stats-dialog.h" #include "bz-tag-list.h" #include "bz-template-callbacks.h" struct _BzFullView { AdwBin parent_instance; BzStateInfo *state; BzTransactionManager *transactions; BzEntryGroup *group; BzResult *ui_entry; BzResult *group_model; gboolean show_sidebar; GMenuModel *main_menu; /* Template widgets */ GtkScrolledWindow *main_scroll; AdwViewStack *stack; GtkWidget *shadow_overlay; GtkToggleButton *description_toggle; GtkWidget *wide_open_button; GtkWidget *wide_install_button; GtkWidget *narrow_install_button; GtkWidget *narrow_open_button; }; G_DEFINE_FINAL_TYPE (BzFullView, bz_full_view, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, PROP_ENTRY_GROUP, PROP_UI_ENTRY, PROP_MAIN_MENU, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_INSTALL, SIGNAL_REMOVE, SIGNAL_INSTALL_ADDON, SIGNAL_REMOVE_ADDON, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void addon_transact_cb (BzFullView *self, BzEntry *entry, BzAddonsDialog *dialog); static void grab_first_button (BzFullView *self); static void bz_full_view_dispose (GObject *object) { BzFullView *self = BZ_FULL_VIEW (object); g_clear_object (&self->state); g_clear_object (&self->transactions); g_clear_object (&self->group); g_clear_object (&self->ui_entry); g_clear_object (&self->group_model); g_clear_object (&self->main_menu); G_OBJECT_CLASS (bz_full_view_parent_class)->dispose (object); } static void bz_full_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzFullView *self = BZ_FULL_VIEW (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, self->state); break; case PROP_ENTRY_GROUP: g_value_set_object (value, bz_full_view_get_entry_group (self)); break; case PROP_UI_ENTRY: g_value_set_object (value, self->ui_entry); break; case PROP_MAIN_MENU: g_value_set_object (value, self->main_menu); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_full_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzFullView *self = BZ_FULL_VIEW (object); switch (prop_id) { case PROP_STATE: g_clear_object (&self->state); self->state = g_value_dup_object (value); break; case PROP_ENTRY_GROUP: bz_full_view_set_entry_group (self, g_value_get_object (value)); break; case PROP_UI_ENTRY: case PROP_MAIN_MENU: if (self->main_menu) g_object_unref (self->main_menu); self->main_menu = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * format_with_small_suffix (char *number, const char *suffix) { char *dot = g_strrstr (number, "."); if (dot != NULL) { char *end = dot + strlen (dot) - 1; while (end > dot && *end == '0') *end-- = '\0'; if (end == dot) *dot = '\0'; } return g_strdup_printf ("%s\xC2\xA0%s", number, suffix); } static gboolean is_scrolled_down (gpointer object, double value) { return value > 100.0; } static char * format_favorites_count (gpointer object, int favorites_count) { if (favorites_count < 0) return g_strdup (" "); return g_strdup_printf ("%d", favorites_count); } static char * format_recent_downloads (gpointer object, int value) { double result; int digits; if (value <= 0) return g_strdup (_ ("---")); if (value >= 1000000) { result = value / 1000000.0; digits = (int) log10 (result) + 1; /* Translators: M is the suffix for millions */ return g_strdup_printf (_ ("%.*fM"), 3 - digits, result); } else if (value >= 1000) { result = value / 1000.0; digits = (int) log10 (result) + 1; /* Translators: K is the suffix for thousands*/ return g_strdup_printf (_ ("%.*fK"), 3 - digits, result); } else return g_strdup_printf ("%'d", value); } static char * format_recent_downloads_tooltip (gpointer object, int value) { return g_strdup_printf (_ ("%d downloads in the last 30 days"), value); } static char * format_size (gpointer object, guint64 value) { g_autofree char *size_str = g_format_size (value); char *space = g_strrstr (size_str, "\xC2\xA0"); char *decimal = NULL; int digits = 0; if (value == 0) return g_strdup (_ ("N/A")); if (space != NULL) { *space = '\0'; for (char *p = size_str; *p != '\0' && *p != '.'; p++) if (g_ascii_isdigit (*p)) digits++; if (digits >= 3) { decimal = g_strrstr (size_str, "."); if (decimal != NULL) *decimal = '\0'; } return format_with_small_suffix (size_str, space + 2); } return g_strdup (size_str); } static char * get_size_label (gpointer object, gboolean is_installable) { // Translators: . return g_strdup (is_installable ? _ ("Download") : _ ("Installed")); } static guint64 get_size_type (gpointer object, BzEntry *entry, gboolean is_installable) { if (entry == NULL) return 0; return is_installable ? bz_entry_get_size (entry) : bz_entry_get_installed_size (entry); } static char * format_size_tooltip (gpointer object, guint64 value) { g_autofree char *size_str = NULL; if (value == 0) return g_strdup (_ ("Size information unavailable")); size_str = g_format_size (value); return g_strdup_printf (_ ("Download size of %s"), size_str); } static char * format_age_rating (gpointer object, AsContentRating *content_rating) { guint age; if (content_rating == NULL) return g_strdup ("?"); age = as_content_rating_get_minimum_age (content_rating); if (age < 3) age = 3; /* Translators: Age rating format, e.g. "12+" for ages 12 and up */ return g_strdup_printf (_ ("%d+"), age); } static char * get_age_rating_label (gpointer object, AsContentRating *content_rating) { guint age; if (content_rating == NULL) return g_strdup (_ ("Age Rating")); age = as_content_rating_get_minimum_age (content_rating); if (age == 0) return g_strdup (_ ("All Ages")); else return g_strdup (_ ("Age Rating")); } static char * get_age_rating_tooltip (gpointer object, AsContentRating *content_rating) { guint age; if (content_rating == NULL) return g_strdup (_ ("Age rating information unavailable")); age = as_content_rating_get_minimum_age (content_rating); if (age == 0) return g_strdup (_ ("Suitable for all ages")); return g_strdup_printf (_ ("Suitable for ages %d and up"), age); } static char * get_age_rating_style (gpointer object, AsContentRating *content_rating) { guint age; if (content_rating == NULL) return g_strdup ("grey"); age = as_content_rating_get_minimum_age (content_rating); if (age >= 18) return g_strdup ("error"); else if (age >= 15) return g_strdup ("orange"); else if (age >= 12) return g_strdup ("warning"); else return g_strdup ("grey"); } static char * format_license_tooltip (gpointer object, BzEntry *entry) { const char *license; gboolean is_floss = FALSE; g_autofree char *name = NULL; if (entry == NULL) return g_strdup (_ ("Unknown")); g_object_get (entry, "is-floss", &is_floss, "project-license", &license, NULL); if (license == NULL || *license == '\0') return g_strdup (_ ("Unknown")); if (is_floss && bz_spdx_is_valid (license)) { name = bz_spdx_get_name (license); return g_strdup_printf (_ ("Free software licensed under %s"), (name != NULL && *name != '\0') ? name : license); } if (is_floss) return g_strdup (_ ("Free software")); if (bz_spdx_is_proprietary (license)) return g_strdup (_ ("Proprietary Software")); name = bz_spdx_get_name (license); return g_strdup_printf (_ ("Special License: %s"), (name != NULL && *name != '\0') ? name : license); } static char * get_license_label (gpointer object, BzEntry *entry) { const char *license; gboolean is_floss = FALSE; if (entry == NULL) return g_strdup (_ ("Unknown")); g_object_get (entry, "is-floss", &is_floss, "project-license", &license, NULL); if (is_floss) return g_strdup (_ ("Free")); if (bz_spdx_is_proprietary (license)) return g_strdup (_ ("Proprietary")); if (license == NULL || *license == '\0') return g_strdup (_ ("Unknown")); return g_strdup (_ ("Special License")); } static char * get_license_icon (gpointer object, gboolean is_floss, int index) { const char *icons[][2] = { { "license-symbolic", "proprietary-code-symbolic" }, { "community-symbolic", "license-symbolic" } }; return g_strdup (icons[is_floss ? 1 : 0][index]); } static char * get_formfactor_label (gpointer object, gboolean is_mobile_friendly) { return g_strdup (is_mobile_friendly ? _ ("Adaptive") : _ ("Desktop Only")); } static char * get_formfactor_tooltip (gpointer object, gboolean is_mobile_friendly) { return g_strdup (is_mobile_friendly ? _ ("Works on desktop, tablets, and phones") : _ ("May not work on mobile devices")); } static char * format_as_link (gpointer object, const char *value) { if (value != NULL) return g_strdup_printf ("%s", value, value, value); else return g_strdup (_ ("No URL")); } static gboolean has_link (gpointer object, const char *license) { if (license == NULL || *license == '\0') return FALSE; return bz_spdx_is_valid (license); } static char * pick_license_warning (gpointer object, gboolean value) { return value ? g_strdup (_ ("This application has a FLOSS license, meaning the source code can be audited for safety.")) : g_strdup (_ ("This application has a proprietary license, meaning the source code is developed privately and cannot be audited by an independent third party.")); } static char * format_other_apps_label (gpointer object, const char *developer) { if (!developer || *developer == '\0') return g_strdup (_ ("More Apps")); return g_strdup_printf (_ ("More Apps by %s"), developer); } static char * format_more_other_apps_label (gpointer object, const char *developer) { if (!developer || *developer == '\0') return g_strdup (_ ("Other Apps by this Developer")); return g_strdup_printf (_ ("Other Apps by %s"), developer); } static char * format_leftover_label (gpointer object, const char *name, guint64 size) { g_autofree char *formatted_size = NULL; formatted_size = g_format_size (size); return g_strdup_printf (_ ("%s is not installed, but it still has %s of data present."), name, formatted_size); } static char * get_safety_rating_icon (gpointer object, BzEntry *entry, int index) { char *icon = NULL; BzImportance importance = 0; if (entry == NULL) return g_strdup ("app-safety-unknown-symbolic"); if (index < 0 || index > 2) return NULL; if (index == 0) { importance = bz_safety_calculator_calculate_rating (entry); switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: case BZ_IMPORTANCE_NEUTRAL: return g_strdup ("app-safety-ok-symbolic"); case BZ_IMPORTANCE_INFORMATION: case BZ_IMPORTANCE_WARNING: return NULL; case BZ_IMPORTANCE_IMPORTANT: return g_strdup ("dialog-warning-symbolic"); default: return NULL; } } icon = bz_safety_calculator_get_top_icon (entry, index - 1); return icon; } static char * get_safety_rating_style (gpointer object, BzEntry *entry) { BzImportance importance; if (entry == NULL) return g_strdup ("grey"); importance = bz_safety_calculator_calculate_rating (entry); switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: case BZ_IMPORTANCE_NEUTRAL: return g_strdup ("grey"); case BZ_IMPORTANCE_INFORMATION: return g_strdup ("warning"); case BZ_IMPORTANCE_WARNING: return g_strdup ("orange"); case BZ_IMPORTANCE_IMPORTANT: return g_strdup ("error"); default: return g_strdup ("grey"); } } static char * get_safety_rating_label (gpointer object, BzEntry *entry) { BzImportance importance; if (entry == NULL) return g_strdup (_ ("N/A")); importance = bz_safety_calculator_calculate_rating (entry); switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: return g_strdup (_ ("Safe")); case BZ_IMPORTANCE_NEUTRAL: return g_strdup (_ ("Low Risk")); case BZ_IMPORTANCE_INFORMATION: return g_strdup (_ ("Low Risk")); case BZ_IMPORTANCE_WARNING: return g_strdup (_ ("Medium Risk")); case BZ_IMPORTANCE_IMPORTANT: return g_strdup (_ ("High Risk")); default: return g_strdup (_ ("N/A")); } } static gpointer filter_own_app_id (BzEntry *entry, GtkStringList *app_ids) { const char *own_id; g_autoptr (GtkStringList) filtered = NULL; guint n_items = 0; if (!BZ_IS_ENTRY (entry) || !GTK_IS_STRING_LIST (app_ids)) return NULL; own_id = bz_entry_get_id (entry); if (!own_id) return NULL; filtered = gtk_string_list_new (NULL); n_items = g_list_model_get_n_items (G_LIST_MODEL (app_ids)); for (guint i = 0; i < n_items; i++) { const char *id = NULL; id = gtk_string_list_get_string (app_ids, i); if (g_strcmp0 (id, own_id) != 0) gtk_string_list_append (filtered, id); } if (g_list_model_get_n_items (G_LIST_MODEL (filtered)) > 0) return g_steal_pointer (&filtered); else return NULL; } static gboolean has_other_apps (gpointer object, GtkStringList *app_ids, BzEntry *entry) { g_autoptr (GtkStringList) filtered = filter_own_app_id (BZ_ENTRY (entry), app_ids); return filtered != NULL; } static GListModel * get_developer_apps_entries (gpointer object, GtkStringList *app_ids, BzEntry *entry) { BzFullView *self = BZ_FULL_VIEW (object); g_autoptr (GtkStringList) filtered = filter_own_app_id (BZ_ENTRY (entry), app_ids); BzApplicationMapFactory *factory; if (!filtered) return NULL; factory = bz_state_info_get_application_factory (self->state); if (!factory) return NULL; return bz_application_map_factory_generate (factory, G_LIST_MODEL (filtered)); } static void apps_page_select_cb (BzFullView *self, BzEntryGroup *group, AdwNavigationPage *page) { GtkWidget *nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); adw_navigation_view_pop (ADW_NAVIGATION_VIEW (nav_view)); bz_full_view_set_entry_group (self, group); } static void more_apps_button_clicked_cb (BzFullView *self, GtkButton *button) { g_autoptr (GListModel) model = NULL; guint n_items; g_autofree char *title = NULL; g_autofree char *subtitle = NULL; AdwNavigationPage *apps_page = NULL; GtkWidget *nav_view = NULL; g_autoptr (GListModel) app_ids = NULL; BzEntry *entry = NULL; const char *developer = NULL; g_return_if_fail (BZ_IS_FULL_VIEW (self)); g_return_if_fail (GTK_IS_BUTTON (button)); entry = bz_result_get_object (self->ui_entry); if (entry == NULL) return; g_object_get (entry, "developer-apps", &app_ids, NULL); model = bz_application_map_factory_generate ( bz_state_info_get_application_factory (self->state), app_ids); n_items = g_list_model_get_n_items (model); developer = bz_entry_get_developer (entry); if (developer != NULL && *developer != '\0') title = g_strdup_printf (_ ("Other Apps by %s"), developer); else title = g_strdup (_ ("Other Apps")); subtitle = g_strdup_printf (ngettext ("%d Application", "%d Applications", n_items), n_items); apps_page = bz_apps_page_new (title, model); bz_apps_page_set_subtitle (BZ_APPS_PAGE (apps_page), subtitle); g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb), self); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); if (nav_view != NULL) adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void app_tile_clicked_cb (BzFullView *self, BzAppTile *tile) { BzEntryGroup *group = bz_app_tile_get_group (tile); bz_full_view_set_entry_group (self, group); } static void bind_app_tile_cb (BzFullView *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (app_tile_clicked_cb), self); } static void unbind_app_tile_cb (BzFullView *self, BzAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (tile, G_CALLBACK (app_tile_clicked_cb), self); } static void tag_list_select_cb (BzFullView *self, BzEntryGroup *group) { bz_full_view_set_entry_group (self, group); } static void open_url_cb (BzFullView *self, AdwActionRow *row) { BzEntry *entry = NULL; const char *url = NULL; entry = BZ_ENTRY (bz_result_get_object (self->ui_entry)); url = bz_entry_get_url (entry); if (url != NULL && *url != '\0') g_app_info_launch_default_for_uri (url, NULL, NULL); else g_warning ("Invalid or empty URL provided for Flathub URL CB"); } static void license_cb (BzFullView *self, GtkButton *button) { AdwDialog *dialog = NULL; BzEntry *ui_entry = NULL; if (self->group == NULL) return; ui_entry = bz_result_get_object (self->ui_entry); if (ui_entry == NULL) return; dialog = bz_license_dialog_new (ui_entry); adw_dialog_present (dialog, GTK_WIDGET (self)); } static void age_rating_cb (BzFullView *self, GtkButton *button) { BzAgeRatingDialog *dialog = NULL; BzEntry *ui_entry = NULL; if (self->group == NULL) return; ui_entry = bz_result_get_object (self->ui_entry); if (ui_entry == NULL) return; dialog = bz_age_rating_dialog_new (ui_entry); adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (self)); } static void dl_stats_cb (BzFullView *self, GtkButton *button) { AdwDialog *dialog = NULL; BzEntry *ui_entry = NULL; if (self->group == NULL) return; ui_entry = bz_result_get_object (self->ui_entry); dialog = bz_stats_dialog_new (NULL, NULL, 0); g_object_bind_property (ui_entry, "download-stats", dialog, "model", G_BINDING_SYNC_CREATE); g_object_bind_property (ui_entry, "download-stats-per-country", dialog, "country-model", G_BINDING_SYNC_CREATE); g_object_bind_property (ui_entry, "total-downloads", dialog, "total-downloads", G_BINDING_SYNC_CREATE); adw_dialog_present (dialog, GTK_WIDGET (self)); bz_stats_dialog_animate_open (BZ_STATS_DIALOG (dialog)); } static void screenshot_clicked_cb (BzFullView *self, guint index, BzScreenshotsCarousel *carousel) { GListModel *screenshots = NULL; GListModel *captions = NULL; AdwNavigationPage *page = NULL; GtkWidget *nav_view = NULL; BzEntry *entry = NULL; screenshots = bz_screenshots_carousel_get_model (carousel); if (screenshots == NULL) return; if (self->ui_entry != NULL) { entry = bz_result_get_object (self->ui_entry); if (entry != NULL) g_object_get (entry, "screenshot-captions", &captions, NULL); } page = bz_screenshot_page_new (screenshots, captions, index); g_clear_object (&captions); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); if (nav_view != NULL) adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), page); } static void size_cb (BzFullView *self, GtkButton *button) { AdwDialog *size_dialog = NULL; if (self->group == NULL) return; size_dialog = bz_app_size_dialog_new (self->group); adw_dialog_present (size_dialog, GTK_WIDGET (self)); } static void formfactor_cb (BzFullView *self, GtkButton *button) { AdwDialog *dialog = NULL; BzEntry *ui_entry = NULL; if (self->group == NULL) return; ui_entry = bz_result_get_object (self->ui_entry); dialog = ADW_DIALOG (bz_hardware_support_dialog_new (ui_entry)); adw_dialog_present (dialog, GTK_WIDGET (self)); } static void safety_cb (BzFullView *self, GtkButton *button) { AdwDialog *dialog = NULL; if (self->group == NULL) return; dialog = ADW_DIALOG (bz_safety_dialog_new (self->group)); adw_dialog_present (dialog, GTK_WIDGET (self)); } static void run_cb (BzFullView *self, GtkButton *button) { GListModel *model = NULL; guint n_items = 0; if (self->group == NULL || !bz_result_get_resolved (self->group_model)) return; model = bz_result_get_object (self->group_model); n_items = g_list_model_get_n_items (model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = NULL; entry = g_list_model_get_item (model, i); if (BZ_IS_FLATPAK_ENTRY (entry) && bz_entry_is_installed (entry)) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; result = bz_flatpak_entry_launch ( BZ_FLATPAK_ENTRY (entry), BZ_FLATPAK_INSTANCE (bz_state_info_get_backend (self->state)), &local_error); if (!result) { GtkWidget *window = NULL; window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW); if (window != NULL) bz_show_error_for_widget (window, local_error->message); } break; } } } static void install_cb (BzFullView *self, GtkButton *button) { g_signal_emit (self, signals[SIGNAL_INSTALL], 0, button); } static void remove_cb (BzFullView *self, GtkButton *button) { g_signal_emit (self, signals[SIGNAL_REMOVE], 0, button); } static void delete_user_data_cb (BzFullView *self, GtkButton *button) { g_return_if_fail (BZ_IS_FULL_VIEW (self)); if (self->group == NULL) return; bz_entry_group_reap_user_data (self->group); } static void support_cb (BzFullView *self, GtkButton *button) { BzEntry *entry = NULL; entry = bz_result_get_object (self->ui_entry); if (entry != NULL) { const char *url = NULL; url = bz_entry_get_donation_url (entry); g_app_info_launch_default_for_uri (url, NULL, NULL); } } static void install_addons_cb (BzFullView *self, GtkButton *button) { BzEntry *entry = NULL; GListModel *model = NULL; g_autoptr (GListModel) mapped_model = NULL; AdwDialog *addons_dialog = NULL; if (self->group == NULL) return; entry = bz_result_get_object (self->ui_entry); if (entry == NULL) return; model = bz_entry_get_addons (entry); if (model == NULL || g_list_model_get_n_items (model) == 0) return; mapped_model = bz_application_map_factory_generate ( bz_state_info_get_entry_factory (self->state), model); addons_dialog = bz_addons_dialog_new (entry, mapped_model); g_signal_connect_swapped ( addons_dialog, "transact", G_CALLBACK (addon_transact_cb), self); adw_dialog_present (addons_dialog, GTK_WIDGET (self)); } static void addon_transact_cb (BzFullView *self, BzEntry *entry, BzAddonsDialog *dialog) { gboolean installed = FALSE; g_object_get (entry, "installed", &installed, NULL); if (installed) g_signal_emit (self, signals[SIGNAL_REMOVE_ADDON], 0, entry); else g_signal_emit (self, signals[SIGNAL_INSTALL_ADDON], 0, entry); } static int get_description_max_height (gpointer object, gboolean active) { return active ? 10000 : 170; } static char * get_description_toggle_text (gpointer object, gboolean active) { return g_strdup (active ? _ ("Show Less") : _ ("Show More")); } static void bz_full_view_class_init (BzFullViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_full_view_dispose; object_class->get_property = bz_full_view_get_property; object_class->set_property = bz_full_view_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_ENTRY_GROUP] = g_param_spec_object ( "entry-group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_UI_ENTRY] = g_param_spec_object ( "ui-entry", NULL, NULL, BZ_TYPE_RESULT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MAIN_MENU] = g_param_spec_object ( "main-menu", NULL, NULL, G_TYPE_MENU_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_INSTALL] = g_signal_new ( "install", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 0); g_signal_set_va_marshaller ( signals[SIGNAL_INSTALL], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_REMOVE] = g_signal_new ( "remove", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 0); g_signal_set_va_marshaller ( signals[SIGNAL_REMOVE], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_INSTALL_ADDON] = g_signal_new ( "install-addon", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_INSTALL_ADDON], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_REMOVE_ADDON] = g_signal_new ( "remove-addon", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_REMOVE_ADDON], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); g_type_ensure (BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER); g_type_ensure (BZ_TYPE_DEVELOPER_BADGE); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_ENTRY); g_type_ensure (BZ_TYPE_ENTRY_GROUP); g_type_ensure (BZ_TYPE_FADING_CLAMP); g_type_ensure (BZ_TYPE_FAVORITE_BUTTON); g_type_ensure (BZ_TYPE_FLATPAK_ENTRY); g_type_ensure (BZ_TYPE_HARDWARE_SUPPORT_DIALOG); g_type_ensure (BZ_TYPE_LAZY_ASYNC_TEXTURE_MODEL); g_type_ensure (BZ_TYPE_SECTION_VIEW); g_type_ensure (BZ_TYPE_RELEASES_LIST); g_type_ensure (BZ_TYPE_SCREENSHOTS_CAROUSEL); g_type_ensure (BZ_TYPE_SHARE_LIST); g_type_ensure (BZ_TYPE_TAG_LIST); g_type_ensure (BZ_TYPE_CONTEXT_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-full-view.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzFullView, stack); gtk_widget_class_bind_template_child (widget_class, BzFullView, main_scroll); gtk_widget_class_bind_template_child (widget_class, BzFullView, shadow_overlay); gtk_widget_class_bind_template_child (widget_class, BzFullView, description_toggle); gtk_widget_class_bind_template_child (widget_class, BzFullView, wide_open_button); gtk_widget_class_bind_template_child (widget_class, BzFullView, wide_install_button); gtk_widget_class_bind_template_child (widget_class, BzFullView, narrow_install_button); gtk_widget_class_bind_template_child (widget_class, BzFullView, narrow_open_button); gtk_widget_class_bind_template_callback (widget_class, is_scrolled_down); gtk_widget_class_bind_template_callback (widget_class, format_favorites_count); gtk_widget_class_bind_template_callback (widget_class, format_recent_downloads); gtk_widget_class_bind_template_callback (widget_class, format_recent_downloads_tooltip); gtk_widget_class_bind_template_callback (widget_class, format_size); gtk_widget_class_bind_template_callback (widget_class, get_size_label); gtk_widget_class_bind_template_callback (widget_class, format_size_tooltip); gtk_widget_class_bind_template_callback (widget_class, age_rating_cb); gtk_widget_class_bind_template_callback (widget_class, format_age_rating); gtk_widget_class_bind_template_callback (widget_class, get_age_rating_label); gtk_widget_class_bind_template_callback (widget_class, get_age_rating_tooltip); gtk_widget_class_bind_template_callback (widget_class, get_age_rating_style); gtk_widget_class_bind_template_callback (widget_class, format_as_link); gtk_widget_class_bind_template_callback (widget_class, format_license_tooltip); gtk_widget_class_bind_template_callback (widget_class, get_license_label); gtk_widget_class_bind_template_callback (widget_class, get_license_icon); gtk_widget_class_bind_template_callback (widget_class, get_formfactor_label); gtk_widget_class_bind_template_callback (widget_class, get_formfactor_tooltip); gtk_widget_class_bind_template_callback (widget_class, get_safety_rating_icon); gtk_widget_class_bind_template_callback (widget_class, get_safety_rating_style); gtk_widget_class_bind_template_callback (widget_class, get_safety_rating_label); gtk_widget_class_bind_template_callback (widget_class, has_link); gtk_widget_class_bind_template_callback (widget_class, format_leftover_label); gtk_widget_class_bind_template_callback (widget_class, format_other_apps_label); gtk_widget_class_bind_template_callback (widget_class, format_more_other_apps_label); gtk_widget_class_bind_template_callback (widget_class, get_developer_apps_entries); gtk_widget_class_bind_template_callback (widget_class, more_apps_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, has_other_apps); gtk_widget_class_bind_template_callback (widget_class, open_url_cb); gtk_widget_class_bind_template_callback (widget_class, license_cb); gtk_widget_class_bind_template_callback (widget_class, dl_stats_cb); gtk_widget_class_bind_template_callback (widget_class, screenshot_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, size_cb); gtk_widget_class_bind_template_callback (widget_class, get_size_type); gtk_widget_class_bind_template_callback (widget_class, formfactor_cb); gtk_widget_class_bind_template_callback (widget_class, safety_cb); gtk_widget_class_bind_template_callback (widget_class, run_cb); gtk_widget_class_bind_template_callback (widget_class, install_cb); gtk_widget_class_bind_template_callback (widget_class, remove_cb); gtk_widget_class_bind_template_callback (widget_class, delete_user_data_cb); gtk_widget_class_bind_template_callback (widget_class, support_cb); gtk_widget_class_bind_template_callback (widget_class, pick_license_warning); gtk_widget_class_bind_template_callback (widget_class, install_addons_cb); gtk_widget_class_bind_template_callback (widget_class, addon_transact_cb); gtk_widget_class_bind_template_callback (widget_class, bind_app_tile_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_app_tile_cb); gtk_widget_class_bind_template_callback (widget_class, get_description_max_height); gtk_widget_class_bind_template_callback (widget_class, get_description_toggle_text); gtk_widget_class_bind_template_callback (widget_class, tag_list_select_cb); } static void bz_full_view_init (BzFullView *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_full_view_new (void) { return g_object_new (BZ_TYPE_FULL_VIEW, NULL); } void bz_full_view_set_entry_group (BzFullView *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_FULL_VIEW (self)); g_return_if_fail (group == NULL || BZ_IS_ENTRY_GROUP (group)); if (group == self->group) return; g_clear_object (&self->group); g_clear_object (&self->ui_entry); g_clear_object (&self->group_model); gtk_toggle_button_set_active (self->description_toggle, FALSE); if (group != NULL) { self->group = g_object_ref (group); self->ui_entry = bz_entry_group_dup_ui_entry (group); if (self->ui_entry != NULL && bz_result_get_resolved (self->ui_entry)) { g_autoptr (GListStore) store = NULL; g_autoptr (DexFuture) future = NULL; BzEntry *entry = NULL; entry = bz_result_get_object (self->ui_entry); store = g_list_store_new (BZ_TYPE_ENTRY); g_list_store_append (store, entry); future = dex_future_new_for_object (store); self->group_model = bz_result_new (future); } else { g_autoptr (DexFuture) future = NULL; future = bz_entry_group_dup_all_into_store (group); self->group_model = bz_result_new (future); } adw_view_stack_set_visible_child_name (self->stack, "content"); } else adw_view_stack_set_visible_child_name (self->stack, "empty"); grab_first_button (self); gtk_adjustment_set_value (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->main_scroll)), 0.0); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY_GROUP]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_UI_ENTRY]); } BzEntryGroup * bz_full_view_get_entry_group (BzFullView *self) { g_return_val_if_fail (BZ_IS_FULL_VIEW (self), NULL); return self->group; } static void grab_first_button (BzFullView *self) { g_return_if_fail (BZ_IS_FULL_VIEW (self)); if (gtk_widget_get_visible (self->wide_open_button)) gtk_widget_grab_focus (self->wide_open_button); else if (gtk_widget_get_visible (self->wide_install_button)) gtk_widget_grab_focus (self->wide_install_button); else if (gtk_widget_get_visible (self->narrow_install_button)) gtk_widget_grab_focus (self->narrow_install_button); else if (gtk_widget_get_visible (self->narrow_open_button)) gtk_widget_grab_focus (self->narrow_open_button); } kolunmi-bazaar-7b9c8e1/src/bz-full-view.h000066400000000000000000000030761514314607700203530ustar00rootroot00000000000000/* bz-full-view.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry-group.h" #include "bz-transaction-manager.h" G_BEGIN_DECLS #define BZ_TYPE_FULL_VIEW (bz_full_view_get_type ()) G_DECLARE_FINAL_TYPE (BzFullView, bz_full_view, BZ, FULL_VIEW, AdwBin) GtkWidget * bz_full_view_new (void); void bz_full_view_set_transaction_manager (BzFullView *self, BzTransactionManager *group); BzTransactionManager * bz_full_view_get_transaction_manager (BzFullView *self); void bz_full_view_set_entry_group (BzFullView *self, BzEntryGroup *group); BzEntryGroup * bz_full_view_get_entry_group (BzFullView *self); void bz_full_view_set_debounce (BzFullView *self, gboolean debounce); gboolean bz_full_view_get_debounce (BzFullView *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-global-net.c000066400000000000000000000214211514314607700204520ustar00rootroot00000000000000/* bz-global-net.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::GLOBAL-NET" #include #include "bz-env.h" #include "bz-global-net.h" #include "bz-util.h" BZ_DEFINE_DATA ( http_request, HttpRequest, { SoupMessage *message; GOutputStream *splice_into; gboolean close_output; }, BZ_RELEASE_DATA (message, g_object_unref); BZ_RELEASE_DATA (splice_into, g_object_unref)); static DexFuture * http_send_fiber (HttpRequestData *data); static void http_send_and_splice_finish (GObject *object, GAsyncResult *result, gpointer user_data); static DexFuture * query_json_source_then (DexFuture *future, GOutputStream *output_stream); static DexFuture * send (SoupMessage *message, GOutputStream *splice_into, gboolean close_output); static DexFuture * query_flathub_v2_json_with_method (const char *request, const char *method, const char *token); DexFuture * bz_send_with_global_http_session (SoupMessage *message) { dex_return_error_if_fail (SOUP_IS_MESSAGE (message)); return send (message, NULL, FALSE); } DexFuture * bz_send_with_global_http_session_then_splice_into (SoupMessage *message, GOutputStream *output) { dex_return_error_if_fail (SOUP_IS_MESSAGE (message)); dex_return_error_if_fail (G_IS_OUTPUT_STREAM (output)); return send (message, output, TRUE); } DexFuture * bz_https_query_json (const char *uri) { g_autoptr (GError) local_error = NULL; g_autoptr (SoupMessage) message = NULL; SoupMessageHeaders *headers = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (DexFuture) future = NULL; dex_return_error_if_fail (uri != NULL); message = soup_message_new (SOUP_METHOD_GET, uri); headers = soup_message_get_request_headers (message); soup_message_headers_append (headers, "User-Agent", "Bazaar"); output = g_memory_output_stream_new_resizable (); future = send (message, output, TRUE); future = dex_future_then ( future, (DexFutureCallback) query_json_source_then, g_object_ref (output), g_object_unref); return g_steal_pointer (&future); } DexFuture * bz_query_flathub_v2_json (const char *request) { dex_return_error_if_fail (request != NULL); return query_flathub_v2_json_with_method (request, SOUP_METHOD_GET, NULL); } DexFuture * bz_query_flathub_v2_json_take (char *request) { DexFuture *future = NULL; dex_return_error_if_fail (request != NULL); future = bz_query_flathub_v2_json (request); g_free (request); return future; } DexFuture * bz_query_flathub_v2_json_authenticated (const char *request, const char *token) { dex_return_error_if_fail (request != NULL); return query_flathub_v2_json_with_method (request, SOUP_METHOD_GET, token); } DexFuture * bz_query_flathub_v2_json_authenticated_post (const char *request, const char *token) { dex_return_error_if_fail (request != NULL); return query_flathub_v2_json_with_method (request, SOUP_METHOD_POST, token); } DexFuture * bz_query_flathub_v2_json_authenticated_delete (const char *request, const char *token) { dex_return_error_if_fail (request != NULL); return query_flathub_v2_json_with_method (request, SOUP_METHOD_DELETE, token); } static DexFuture * query_flathub_v2_json_with_method (const char *request, const char *method, const char *token) { g_autofree char *uri = NULL; g_autoptr (SoupMessage) message = NULL; SoupMessageHeaders *headers = NULL; g_autoptr (GOutputStream) output = NULL; g_autoptr (DexFuture) future = NULL; uri = g_strdup_printf ("https://flathub.org/api/v2%s", request); message = soup_message_new (method, uri); headers = soup_message_get_request_headers (message); soup_message_headers_append (headers, "User-Agent", "Bazaar"); if (token != NULL && token[0] != '\0') { g_autofree char *cookie_value = NULL; cookie_value = g_strdup_printf ("session=%s", token); soup_message_headers_append (headers, "Cookie", cookie_value); } output = g_memory_output_stream_new_resizable (); future = send (message, output, TRUE); future = dex_future_then ( future, (DexFutureCallback) query_json_source_then, g_object_ref (output), g_object_unref); return g_steal_pointer (&future); } static DexFuture * http_send_fiber (HttpRequestData *data) { static SoupSession *session = NULL; SoupMessage *message = data->message; GOutputStream *splice_into = data->splice_into; gboolean close_output = data->close_output; GOutputStreamSpliceFlags splice_flags = G_OUTPUT_STREAM_SPLICE_NONE; g_autoptr (DexPromise) promise = NULL; if (g_once_init_enter_pointer (&session)) g_once_init_leave_pointer (&session, soup_session_new ()); splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE; if (close_output) splice_flags |= G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET; promise = dex_promise_new_cancellable (); soup_session_send_and_splice_async ( session, message, splice_into, splice_flags, G_PRIORITY_DEFAULT_IDLE, dex_promise_get_cancellable (promise), http_send_and_splice_finish, dex_ref (promise)); return DEX_FUTURE (g_steal_pointer (&promise)); } static void http_send_and_splice_finish (GObject *object, GAsyncResult *result, gpointer user_data) { DexPromise *promise = user_data; g_autoptr (GError) local_error = NULL; gssize bytes_written = 0; g_assert (SOUP_IS_SESSION (object)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (DEX_IS_PROMISE (promise)); bytes_written = soup_session_send_and_splice_finish (SOUP_SESSION (object), result, &local_error); if (bytes_written >= 0) { g_debug ("Spliced %zu bytes from http reply into output stream", bytes_written); dex_promise_resolve_uint64 (promise, bytes_written); } else { g_debug ("Could not splice http reply into output stream: %s", local_error->message); dex_promise_reject (promise, g_steal_pointer (&local_error)); } dex_unref (promise); } static DexFuture * query_json_source_then (DexFuture *future, GOutputStream *output_stream) { g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; gsize bytes_size = 0; gconstpointer bytes_data = NULL; g_autoptr (JsonParser) parser = NULL; gboolean result = FALSE; JsonNode *node = NULL; bytes = g_memory_output_stream_steal_as_bytes ( G_MEMORY_OUTPUT_STREAM (output_stream)); bytes_data = g_bytes_get_data (bytes, &bytes_size); if (bytes_size == 0) return dex_future_new_take_boxed (JSON_TYPE_NODE, json_node_new (JSON_NODE_NULL)); parser = json_parser_new_immutable (); result = json_parser_load_from_data (parser, bytes_data, bytes_size, &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); node = json_parser_get_root (parser); return dex_future_new_take_boxed (JSON_TYPE_NODE, json_node_ref (node)); } static DexFuture * send (SoupMessage *message, GOutputStream *splice_into, gboolean close_output) { g_autoptr (HttpRequestData) data = NULL; g_autoptr (DexFuture) future = NULL; data = http_request_data_new (); data->message = g_object_ref (message); data->splice_into = bz_object_maybe_ref (splice_into); data->close_output = close_output; future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) http_send_fiber, http_request_data_ref (data), http_request_data_unref); return g_steal_pointer (&future); } kolunmi-bazaar-7b9c8e1/src/bz-global-net.h000066400000000000000000000032141514314607700204570ustar00rootroot00000000000000/* bz-global-net.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS DexFuture * bz_send_with_global_http_session (SoupMessage *message); DexFuture * bz_send_with_global_http_session_then_splice_into (SoupMessage *message, GOutputStream *output); DexFuture * bz_https_query_json (const char *uri); DexFuture * bz_query_flathub_v2_json (const char *request); DexFuture * bz_query_flathub_v2_json_authenticated (const char *request, const char *token); DexFuture * bz_query_flathub_v2_json_authenticated_post (const char *request, const char *token); DexFuture * bz_query_flathub_v2_json_authenticated_delete (const char *request, const char *token); DexFuture * bz_query_flathub_v2_json_take (char *request); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-global-progress.c000066400000000000000000000611141514314607700215330ustar00rootroot00000000000000/* bz-global-progress.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-global-progress.h" #include "progress-bar-designs/common.h" struct _BzGlobalProgress { GtkWidget parent_instance; GtkWidget *draw_widget; char *draw_widget_class; GtkWidget *child; gboolean active; gboolean pending; double fraction; double actual_fraction; double pending_progress; double transition_progress; int expand_size; GSettings *settings; AdwAnimation *transition_animation; AdwAnimation *pending_animation; AdwAnimation *fraction_animation; AdwSpringParams *transition_spring_up; AdwSpringParams *transition_spring_down; AdwSpringParams *pending_spring; AdwSpringParams *fraction_spring; guint tick; double pending_time_mod; graphene_rect_t filled_rect; }; G_DEFINE_FINAL_TYPE (BzGlobalProgress, bz_global_progress, GTK_TYPE_WIDGET) enum { PROP_0, PROP_CHILD, PROP_ACTIVE, PROP_PENDING, PROP_FRACTION, PROP_ACTUAL_FRACTION, PROP_TRANSITION_PROGRESS, PROP_PENDING_PROGRESS, PROP_EXPAND_SIZE, PROP_SETTINGS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void global_progress_bar_flag_changed (BzGlobalProgress *self, const char *key, GSettings *settings); static void ensure_draw_css (BzGlobalProgress *self); static void bz_global_progress_dispose (GObject *object) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (object); gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick); self->tick = 0; if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, global_progress_bar_flag_changed, self); g_clear_pointer (&self->draw_widget, gtk_widget_unparent); g_clear_pointer (&self->draw_widget_class, g_free); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_object (&self->settings); g_clear_object (&self->transition_animation); g_clear_object (&self->pending_animation); g_clear_object (&self->fraction_animation); g_clear_pointer (&self->transition_spring_up, adw_spring_params_unref); g_clear_pointer (&self->transition_spring_down, adw_spring_params_unref); g_clear_pointer (&self->pending_spring, adw_spring_params_unref); g_clear_pointer (&self->fraction_spring, adw_spring_params_unref); G_OBJECT_CLASS (bz_global_progress_parent_class)->dispose (object); } static void bz_global_progress_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_global_progress_get_child (self)); break; case PROP_ACTIVE: g_value_set_boolean (value, bz_global_progress_get_active (self)); break; case PROP_PENDING: g_value_set_boolean (value, bz_global_progress_get_pending (self)); break; case PROP_FRACTION: g_value_set_double (value, bz_global_progress_get_fraction (self)); break; case PROP_ACTUAL_FRACTION: g_value_set_double (value, bz_global_progress_get_actual_fraction (self)); break; case PROP_TRANSITION_PROGRESS: g_value_set_double (value, bz_global_progress_get_transition_progress (self)); break; case PROP_PENDING_PROGRESS: g_value_set_double (value, bz_global_progress_get_pending_progress (self)); break; case PROP_EXPAND_SIZE: g_value_set_int (value, bz_global_progress_get_expand_size (self)); break; case PROP_SETTINGS: g_value_set_object (value, bz_global_progress_get_settings (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_global_progress_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (object); switch (prop_id) { case PROP_CHILD: bz_global_progress_set_child (self, g_value_get_object (value)); break; case PROP_ACTIVE: bz_global_progress_set_active (self, g_value_get_boolean (value)); break; case PROP_PENDING: bz_global_progress_set_pending (self, g_value_get_boolean (value)); break; case PROP_FRACTION: bz_global_progress_set_fraction (self, g_value_get_double (value)); break; case PROP_ACTUAL_FRACTION: bz_global_progress_set_actual_fraction (self, g_value_get_double (value)); break; case PROP_TRANSITION_PROGRESS: bz_global_progress_set_transition_progress (self, g_value_get_double (value)); break; case PROP_PENDING_PROGRESS: bz_global_progress_set_pending_progress (self, g_value_get_double (value)); break; case PROP_EXPAND_SIZE: bz_global_progress_set_expand_size (self, g_value_get_int (value)); break; case PROP_SETTINGS: bz_global_progress_set_settings (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_global_progress_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (widget); if (self->child != NULL) gtk_widget_measure ( self->child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); if (orientation == GTK_ORIENTATION_HORIZONTAL) { int add = 0; add = round (self->transition_progress * self->expand_size); (*minimum) += add; (*natural) += add; } } static void bz_global_progress_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (widget); graphene_rect_t pending_rect = { 0 }; graphene_rect_t fraction_rect = { 0 }; pending_rect = GRAPHENE_RECT_INIT ( ((double) height * 0.2) + MAX (((double) width - (double) height * 0.4) * 0.35, 0.0) * self->pending_time_mod, (double) height * 0.2, MAX (((double) width - (double) height * 0.4) * 0.65, 0.0), (double) height * 0.6); fraction_rect = GRAPHENE_RECT_INIT ( 0.0, 0.0, width * self->actual_fraction, height); graphene_rect_interpolate ( &fraction_rect, &pending_rect, self->pending_progress, &self->filled_rect); gtk_widget_allocate ( self->draw_widget, ceil (self->filled_rect.size.width), ceil (self->filled_rect.size.height), baseline, gsk_transform_translate ( NULL, &GRAPHENE_POINT_INIT ( floor (self->filled_rect.origin.x), floor (self->filled_rect.origin.y)))); if (self->child != NULL) gtk_widget_allocate (self->child, width, height, baseline, NULL); } static void bz_global_progress_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzGlobalProgress *self = BZ_GLOBAL_PROGRESS (widget); double width = 0; double height = 0; double corner_radius = 0.0; double inner_radius = 0.0; double gap = 0.0; GskRoundedRect total_clip = { 0 }; GskRoundedRect fraction_clip = { 0 }; g_autoptr (GdkRGBA) accent_color = NULL; accent_color = g_new0 (GdkRGBA, 1); gtk_widget_get_color (widget, accent_color); if (self->child != NULL) { gtk_snapshot_push_opacity (snapshot, CLAMP (1.0 - self->transition_progress, 0.0, 1.0)); gtk_widget_snapshot_child (widget, self->child, snapshot); gtk_snapshot_pop (snapshot); } width = gtk_widget_get_width (widget); height = gtk_widget_get_height (widget); corner_radius = height * 0.5 * (0.3 * self->transition_progress + 0.2); gap = height * 0.1; inner_radius = MAX (corner_radius - gap, 0.0); total_clip.bounds = GRAPHENE_RECT_INIT (0.0, 0.0, width, height); total_clip.corner[0].width = corner_radius; total_clip.corner[0].height = corner_radius; total_clip.corner[1].width = corner_radius; total_clip.corner[1].height = corner_radius; total_clip.corner[2].width = corner_radius; total_clip.corner[2].height = corner_radius; total_clip.corner[3].width = corner_radius; total_clip.corner[3].height = corner_radius; fraction_clip.bounds = self->filled_rect; fraction_clip.corner[0].width = inner_radius; fraction_clip.corner[0].height = inner_radius; fraction_clip.corner[1].width = inner_radius; fraction_clip.corner[1].height = inner_radius; fraction_clip.corner[2].width = inner_radius; fraction_clip.corner[2].height = inner_radius; fraction_clip.corner[3].width = inner_radius; fraction_clip.corner[3].height = inner_radius; gtk_snapshot_push_rounded_clip (snapshot, &total_clip); gtk_snapshot_push_opacity (snapshot, CLAMP (self->transition_progress, 0.0, 1.0)); accent_color->alpha = 0.2; gtk_snapshot_append_color (snapshot, accent_color, &total_clip.bounds); accent_color->alpha = 1.0; gtk_snapshot_push_rounded_clip (snapshot, &fraction_clip); gtk_widget_snapshot_child (widget, self->draw_widget, snapshot); gtk_snapshot_pop (snapshot); gtk_snapshot_pop (snapshot); gtk_snapshot_pop (snapshot); } static void bz_global_progress_class_init (BzGlobalProgressClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_global_progress_dispose; object_class->get_property = bz_global_progress_get_property; object_class->set_property = bz_global_progress_set_property; props[PROP_CHILD] = g_param_spec_object ( "child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ACTIVE] = g_param_spec_boolean ( "active", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PENDING] = g_param_spec_boolean ( "pending", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FRACTION] = g_param_spec_double ( "fraction", NULL, NULL, 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ACTUAL_FRACTION] = g_param_spec_double ( "actual-fraction", NULL, NULL, 0.0, 2.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TRANSITION_PROGRESS] = g_param_spec_double ( "transition-progress", NULL, NULL, 0.0, 2.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PENDING_PROGRESS] = g_param_spec_double ( "pending-progress", NULL, NULL, 0.0, 2.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_EXPAND_SIZE] = g_param_spec_int ( "expand-size", NULL, NULL, 0, G_MAXINT, 100, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SETTINGS] = g_param_spec_object ( "settings", NULL, NULL, G_TYPE_SETTINGS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->measure = bz_global_progress_measure; widget_class->size_allocate = bz_global_progress_size_allocate; widget_class->snapshot = bz_global_progress_snapshot; gtk_widget_class_set_css_name (widget_class, "global-progress"); } static gboolean tick_cb (BzGlobalProgress *self, GdkFrameClock *frame_clock, gpointer user_data) { gint64 frame_time = 0; double linear_value = 0.0; frame_time = gdk_frame_clock_get_frame_time (frame_clock); linear_value = fmod ((double) (frame_time % (gint64) G_MAXDOUBLE) * 0.000001, 2.0); if (linear_value > 1.0) linear_value = 2.0 - linear_value; self->pending_time_mod = adw_easing_ease (ADW_EASE_IN_OUT_CUBIC, linear_value); if (self->pending_progress > 0.0 && self->transition_progress > 0.0) gtk_widget_queue_allocate (GTK_WIDGET (self)); return G_SOURCE_CONTINUE; } static void bz_global_progress_init (BzGlobalProgress *self) { AdwAnimationTarget *transition_target = NULL; AdwSpringParams *transition_spring = NULL; AdwAnimationTarget *pending_target = NULL; AdwSpringParams *pending_spring = NULL; AdwAnimationTarget *fraction_target = NULL; AdwSpringParams *fraction_spring = NULL; self->draw_widget = gtk_fixed_new (); gtk_widget_set_halign (self->draw_widget, GTK_ALIGN_FILL); gtk_widget_set_valign (self->draw_widget, GTK_ALIGN_FILL); gtk_widget_set_parent (self->draw_widget, GTK_WIDGET (self)); self->expand_size = 100; self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), (GtkTickCallback) tick_cb, NULL, NULL); transition_target = adw_property_animation_target_new (G_OBJECT (self), "transition-progress"); transition_spring = adw_spring_params_new (0.75, 0.8, 200.0); self->transition_animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, transition_spring, transition_target); adw_spring_animation_set_epsilon ( ADW_SPRING_ANIMATION (self->transition_animation), 0.00005); pending_target = adw_property_animation_target_new (G_OBJECT (self), "pending-progress"); pending_spring = adw_spring_params_new (1.0, 0.75, 200.0); self->pending_animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, pending_spring, pending_target); fraction_target = adw_property_animation_target_new (G_OBJECT (self), "actual-fraction"); fraction_spring = adw_spring_params_new (1.0, 0.75, 200.0); self->fraction_animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, fraction_spring, fraction_target); self->transition_spring_up = adw_spring_params_ref (transition_spring); self->transition_spring_down = adw_spring_params_new (1.5, 0.1, 100.0); self->pending_spring = adw_spring_params_ref (pending_spring); self->fraction_spring = adw_spring_params_ref (fraction_spring); } GtkWidget * bz_global_progress_new (void) { return g_object_new (BZ_TYPE_GLOBAL_PROGRESS, NULL); } void bz_global_progress_set_child (BzGlobalProgress *self, GtkWidget *child) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (self->child == child) return; if (child != NULL) g_return_if_fail (gtk_widget_get_parent (child) == NULL); g_clear_pointer (&self->child, gtk_widget_unparent); self->child = child; if (child != NULL) gtk_widget_set_parent (child, GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]); } GtkWidget * bz_global_progress_get_child (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), NULL); return self->child; } void bz_global_progress_set_active (BzGlobalProgress *self, gboolean active) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); if ((active && self->active) || (!active && !self->active)) return; self->active = active; adw_spring_animation_set_value_from ( ADW_SPRING_ANIMATION (self->transition_animation), self->transition_progress); adw_spring_animation_set_value_to ( ADW_SPRING_ANIMATION (self->transition_animation), active ? 1.0 : 0.0); adw_spring_animation_set_initial_velocity ( ADW_SPRING_ANIMATION (self->transition_animation), adw_spring_animation_get_velocity (ADW_SPRING_ANIMATION (self->transition_animation))); adw_spring_animation_set_spring_params ( ADW_SPRING_ANIMATION (self->transition_animation), active ? self->transition_spring_up : self->transition_spring_down); adw_animation_play (self->transition_animation); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVE]); } gboolean bz_global_progress_get_active (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->active; } void bz_global_progress_set_pending (BzGlobalProgress *self, gboolean pending) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); if ((pending && self->pending) || (!pending && !self->pending)) return; self->pending = pending; adw_spring_animation_set_value_from ( ADW_SPRING_ANIMATION (self->pending_animation), self->pending_progress); adw_spring_animation_set_value_to ( ADW_SPRING_ANIMATION (self->pending_animation), pending ? 1.0 : 0.0); adw_spring_animation_set_initial_velocity ( ADW_SPRING_ANIMATION (self->pending_animation), adw_spring_animation_get_velocity ( ADW_SPRING_ANIMATION (self->pending_animation))); adw_animation_play (self->pending_animation); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); } gboolean bz_global_progress_get_pending (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->pending; } void bz_global_progress_set_fraction (BzGlobalProgress *self, double fraction) { double last = 0.0; g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); last = self->actual_fraction; self->fraction = CLAMP (fraction, 0.0, 1.0); if (self->fraction < last || G_APPROX_VALUE (last, self->fraction, 0.001)) { adw_animation_reset (self->fraction_animation); bz_global_progress_set_actual_fraction (self, self->fraction); } else { adw_spring_animation_set_value_from ( ADW_SPRING_ANIMATION (self->fraction_animation), self->actual_fraction); adw_spring_animation_set_value_to ( ADW_SPRING_ANIMATION (self->fraction_animation), self->fraction); adw_spring_animation_set_initial_velocity ( ADW_SPRING_ANIMATION (self->fraction_animation), adw_spring_animation_get_velocity ( ADW_SPRING_ANIMATION (self->fraction_animation))); adw_animation_play (self->fraction_animation); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FRACTION]); } double bz_global_progress_get_fraction (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->fraction; } void bz_global_progress_set_actual_fraction (BzGlobalProgress *self, double fraction) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); self->actual_fraction = CLAMP (fraction, 0.0, 1.0); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FRACTION]); } double bz_global_progress_get_actual_fraction (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->actual_fraction; } void bz_global_progress_set_transition_progress (BzGlobalProgress *self, double progress) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); self->transition_progress = MAX (progress, 0.0); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_PROGRESS]); } double bz_global_progress_get_transition_progress (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), 0.0); return self->transition_progress; } void bz_global_progress_set_pending_progress (BzGlobalProgress *self, double progress) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); self->pending_progress = MAX (progress, 0.0); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING_PROGRESS]); } double bz_global_progress_get_pending_progress (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), 0.0); return self->pending_progress; } void bz_global_progress_set_expand_size (BzGlobalProgress *self, int expand_size) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); self->expand_size = MAX (expand_size, 0); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_EXPAND_SIZE]); } int bz_global_progress_get_expand_size (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->expand_size; } void bz_global_progress_set_settings (BzGlobalProgress *self, GSettings *settings) { g_return_if_fail (BZ_IS_GLOBAL_PROGRESS (self)); if (self->settings != NULL) g_signal_handlers_disconnect_by_func ( self->settings, global_progress_bar_flag_changed, self); g_clear_object (&self->settings); if (settings != NULL) { self->settings = g_object_ref (settings); g_signal_connect_swapped ( self->settings, "changed::global-progress-bar-theme", G_CALLBACK (global_progress_bar_flag_changed), self); g_signal_connect_swapped ( self->settings, "changed::rotate-flag", G_CALLBACK (global_progress_bar_flag_changed), self); } ensure_draw_css (self); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SETTINGS]); } GSettings * bz_global_progress_get_settings (BzGlobalProgress *self) { g_return_val_if_fail (BZ_IS_GLOBAL_PROGRESS (self), FALSE); return self->settings; } static void global_progress_bar_flag_changed (BzGlobalProgress *self, const char *key, GSettings *settings) { ensure_draw_css (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void ensure_draw_css (BzGlobalProgress *self) { if (self->settings != NULL) { g_autofree char *id = NULL; g_autofree char *final_id = NULL; g_autofree char *class = NULL; gboolean rotate = FALSE; id = g_settings_get_string (self->settings, "global-progress-bar-theme"); rotate = g_settings_get_boolean (self->settings, "rotate-flag"); if (rotate && g_strcmp0 (id, "accent-color") != 0) final_id = g_strdup_printf ("%s-horizontal", id); else final_id = g_strdup (id); class = bz_dup_css_class_for_pride_id (final_id); if (self->draw_widget_class != NULL && g_strcmp0 (self->draw_widget_class, class) == 0) return; if (self->draw_widget_class != NULL) gtk_widget_remove_css_class (self->draw_widget, self->draw_widget_class); g_clear_pointer (&self->draw_widget_class, g_free); gtk_widget_add_css_class (self->draw_widget, class); self->draw_widget_class = g_steal_pointer (&class); } else { if (self->draw_widget_class != NULL) gtk_widget_remove_css_class (self->draw_widget, self->draw_widget_class); g_clear_pointer (&self->draw_widget_class, g_free); } } kolunmi-bazaar-7b9c8e1/src/bz-global-progress.h000066400000000000000000000054071514314607700215430ustar00rootroot00000000000000/* bz-global-progress.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_GLOBAL_PROGRESS (bz_global_progress_get_type ()) G_DECLARE_FINAL_TYPE (BzGlobalProgress, bz_global_progress, BZ, GLOBAL_PROGRESS, GtkWidget) GtkWidget * bz_global_progress_new (void); GtkWidget * bz_global_progress_get_child (BzGlobalProgress *self); void bz_global_progress_set_child (BzGlobalProgress *self, GtkWidget *child); void bz_global_progress_set_active (BzGlobalProgress *self, gboolean active); gboolean bz_global_progress_get_active (BzGlobalProgress *self); void bz_global_progress_set_pending (BzGlobalProgress *self, gboolean pending); gboolean bz_global_progress_get_pending (BzGlobalProgress *self); void bz_global_progress_set_fraction (BzGlobalProgress *self, double fraction); double bz_global_progress_get_fraction (BzGlobalProgress *self); void bz_global_progress_set_actual_fraction (BzGlobalProgress *self, double fraction); double bz_global_progress_get_actual_fraction (BzGlobalProgress *self); void bz_global_progress_set_transition_progress (BzGlobalProgress *self, double progress); double bz_global_progress_get_transition_progress (BzGlobalProgress *self); void bz_global_progress_set_pending_progress (BzGlobalProgress *self, double progress); double bz_global_progress_get_pending_progress (BzGlobalProgress *self); void bz_global_progress_set_expand_size (BzGlobalProgress *self, int expand_size); int bz_global_progress_get_expand_size (BzGlobalProgress *self); void bz_global_progress_set_settings (BzGlobalProgress *self, GSettings *settings); GSettings * bz_global_progress_get_settings (BzGlobalProgress *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-gnome-shell-search-provider.c000066400000000000000000000352411514314607700237400ustar00rootroot00000000000000/* bz-gnome-shell-search-provider.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-gnome-shell-search-provider.h" #include "bz-entry-group.h" #include "bz-search-result.h" #include "bz-util.h" #include "gs-shell-search-provider-generated.h" struct _BzGnomeShellSearchProvider { GObject parent_instance; BzSearchEngine *engine; GDBusConnection *connection; BzShellSearchProvider2 *skeleton; DexFuture *task; GHashTable *last_results; }; G_DEFINE_FINAL_TYPE (BzGnomeShellSearchProvider, bz_gnome_shell_search_provider, G_TYPE_OBJECT); enum { PROP_0, PROP_ENGINE, PROP_CONNECTION, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; BZ_DEFINE_DATA ( request, Request, { BzGnomeShellSearchProvider *self; GDBusMethodInvocation *invocation; GApplication *application; }, BZ_RELEASE_DATA (invocation, g_object_unref); BZ_RELEASE_DATA (application, g_application_release);) static DexFuture * request_finally (DexFuture *future, RequestData *data); static void start_request (BzGnomeShellSearchProvider *self, GDBusMethodInvocation *invocation, const char *const *terms); static void bz_gnome_shell_search_provider_dispose (GObject *object) { BzGnomeShellSearchProvider *self = BZ_GNOME_SHELL_SEARCH_PROVIDER (object); dex_clear (&self->task); g_clear_object (&self->engine); g_clear_object (&self->connection); g_clear_object (&self->skeleton); g_clear_pointer (&self->last_results, g_hash_table_unref); G_OBJECT_CLASS (bz_gnome_shell_search_provider_parent_class)->dispose (object); } static void bz_gnome_shell_search_provider_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzGnomeShellSearchProvider *self = BZ_GNOME_SHELL_SEARCH_PROVIDER (object); switch (prop_id) { case PROP_ENGINE: g_value_set_object (value, bz_gnome_shell_search_provider_get_engine (self)); break; case PROP_CONNECTION: g_value_set_object (value, bz_gnome_shell_search_provider_get_connection (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_gnome_shell_search_provider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzGnomeShellSearchProvider *self = BZ_GNOME_SHELL_SEARCH_PROVIDER (object); switch (prop_id) { case PROP_ENGINE: bz_gnome_shell_search_provider_set_engine (self, g_value_get_object (value)); break; case PROP_CONNECTION: bz_gnome_shell_search_provider_set_connection (self, g_value_get_object (value), NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_gnome_shell_search_provider_class_init (BzGnomeShellSearchProviderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_gnome_shell_search_provider_set_property; object_class->get_property = bz_gnome_shell_search_provider_get_property; object_class->dispose = bz_gnome_shell_search_provider_dispose; props[PROP_ENGINE] = g_param_spec_object ( "engine", NULL, NULL, BZ_TYPE_SEARCH_ENGINE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_CONNECTION] = g_param_spec_object ( "connection", NULL, NULL, G_TYPE_DBUS_CONNECTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static gboolean get_initial_result_set (BzShellSearchProvider2 *skeleton, GDBusMethodInvocation *invocation, gchar **terms, BzGnomeShellSearchProvider *self) { start_request (self, invocation, (const char *const *) terms); return TRUE; } static gboolean get_subsearch_result_set (BzShellSearchProvider2 *skeleton, GDBusMethodInvocation *invocation, gchar **previous_results, gchar **terms, BzGnomeShellSearchProvider *self) { start_request (self, invocation, (const char *const *) terms); return TRUE; } static gboolean get_result_metas (BzShellSearchProvider2 *skeleton, GDBusMethodInvocation *invocation, gchar **results, BzGnomeShellSearchProvider *self) { g_autoptr (GVariantBuilder) builder = NULL; builder = g_variant_builder_new (G_VARIANT_TYPE ("aa{sv}")); for (char **result = results; *result != NULL; result++) { BzEntryGroup *group = NULL; g_autoptr (GVariantBuilder) meta_builder = NULL; const char *title = NULL; const char *description = NULL; GIcon *icon = NULL; group = g_hash_table_lookup (self->last_results, *result); if (group == NULL) { g_warning ("failed to find '%s' in gnome-shell search result cache", *result); continue; } meta_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (meta_builder, "{sv}", "id", g_variant_new_string (*result)); title = bz_entry_group_get_title (group); g_variant_builder_add (meta_builder, "{sv}", "name", g_variant_new_string (title)); description = bz_entry_group_get_description (group); if (description != NULL) g_variant_builder_add (meta_builder, "{sv}", "description", g_variant_new_string (description)); icon = bz_entry_group_get_mini_icon (group); if (icon != NULL) { g_autofree gchar *icon_str = g_icon_to_string (icon); if (icon_str != NULL) g_variant_builder_add (meta_builder, "{sv}", "gicon", g_variant_new_string (icon_str)); else { g_autoptr (GVariant) icon_serialized = NULL; icon_serialized = g_icon_serialize (icon); if (icon_serialized != NULL) g_variant_builder_add (meta_builder, "{sv}", "icon", icon_serialized); } } g_variant_builder_add_value (builder, g_variant_builder_end (meta_builder)); } g_dbus_method_invocation_return_value (invocation, g_variant_new ("(aa{sv})", builder)); return TRUE; } static gboolean activate_result (BzShellSearchProvider2 *skeleton, GDBusMethodInvocation *invocation, gchar *result, gchar **terms, guint32 timestamp, BzGnomeShellSearchProvider *self) { g_action_group_activate_action ( G_ACTION_GROUP (g_application_get_default ()), "show-app-id", g_variant_new ("s", result)); bz_shell_search_provider2_complete_activate_result (skeleton, invocation); return TRUE; } static gboolean launch_search (BzShellSearchProvider2 *skeleton, GDBusMethodInvocation *invocation, gchar **terms, guint32 timestamp, BzGnomeShellSearchProvider *self) { g_autofree gchar *string = NULL; string = g_strjoinv (" ", terms); g_action_group_activate_action ( G_ACTION_GROUP (g_application_get_default ()), "show-app-id", g_variant_new ("s", string)); bz_shell_search_provider2_complete_launch_search (skeleton, invocation); return TRUE; } static void bz_gnome_shell_search_provider_init (BzGnomeShellSearchProvider *self) { self->skeleton = bz_shell_search_provider2_skeleton_new (); self->last_results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); g_signal_connect ( self->skeleton, "handle-get-initial-result-set", G_CALLBACK (get_initial_result_set), self); g_signal_connect ( self->skeleton, "handle-get-subsearch-result-set", G_CALLBACK (get_subsearch_result_set), self); g_signal_connect ( self->skeleton, "handle-get-result-metas", G_CALLBACK (get_result_metas), self); g_signal_connect ( self->skeleton, "handle-activate-result", G_CALLBACK (activate_result), self); g_signal_connect ( self->skeleton, "handle-launch-search", G_CALLBACK (launch_search), self); } BzGnomeShellSearchProvider * bz_gnome_shell_search_provider_new (void) { return g_object_new (BZ_TYPE_GNOME_SHELL_SEARCH_PROVIDER, NULL); } BzSearchEngine * bz_gnome_shell_search_provider_get_engine (BzGnomeShellSearchProvider *self) { g_return_val_if_fail (BZ_IS_GNOME_SHELL_SEARCH_PROVIDER (self), NULL); return self->engine; } void bz_gnome_shell_search_provider_set_engine (BzGnomeShellSearchProvider *self, BzSearchEngine *engine) { g_return_if_fail (BZ_IS_GNOME_SHELL_SEARCH_PROVIDER (self)); g_return_if_fail (engine == NULL || BZ_IS_SEARCH_ENGINE (engine)); g_clear_pointer (&self->engine, g_object_unref); if (engine != NULL) self->engine = g_object_ref (engine); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENGINE]); } GDBusConnection * bz_gnome_shell_search_provider_get_connection (BzGnomeShellSearchProvider *self) { g_return_val_if_fail (BZ_IS_GNOME_SHELL_SEARCH_PROVIDER (self), NULL); return self->connection; } gboolean bz_gnome_shell_search_provider_set_connection (BzGnomeShellSearchProvider *self, GDBusConnection *connection, GError **error) { gboolean success = TRUE; g_return_val_if_fail (BZ_IS_GNOME_SHELL_SEARCH_PROVIDER (self), FALSE); g_return_val_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection), FALSE); if (self->connection != NULL) g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton)); g_clear_pointer (&self->connection, g_object_unref); if (connection != NULL) { g_autoptr (GError) local_error = NULL; self->connection = g_object_ref (connection); success = g_dbus_interface_skeleton_export ( G_DBUS_INTERFACE_SKELETON (self->skeleton), connection, "/io/github/kolunmi/Bazaar/SearchProvider", &local_error); if (!success) { if (error != NULL) g_propagate_error (error, g_steal_pointer (&local_error)); else g_warning ("Could not register gnome shell search provider: %s", local_error->message); } } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONNECTION]); return success; } static DexFuture * request_finally (DexFuture *future, RequestData *data) { BzGnomeShellSearchProvider *self = data->self; GDBusMethodInvocation *invocation = data->invocation; g_autoptr (GError) local_error = NULL; const GValue *value = NULL; GPtrArray *results = NULL; g_autoptr (GVariantBuilder) builder = NULL; value = dex_future_get_value (future, &local_error); if (value != NULL) { results = g_value_get_boxed (value); builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); for (guint i = 0; i < results->len; i++) { BzSearchResult *result = NULL; BzEntryGroup *group = NULL; const char *id = NULL; result = g_ptr_array_index (results, i); group = bz_search_result_get_group (result); if (bz_entry_group_get_removable (group) > 0) /* Skip already installed groups */ continue; id = bz_entry_group_get_id (group); g_variant_builder_add (builder, "s", id); g_hash_table_replace ( self->last_results, g_strdup (id), g_object_ref (group)); } g_dbus_method_invocation_return_value ( invocation, g_variant_new ("(as)", builder)); } else { g_warning ("search engine reported an error to the search provider, " "returning an empty response to invocation: %s", local_error->message); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(as)", NULL)); } return NULL; } static void start_request (BzGnomeShellSearchProvider *self, GDBusMethodInvocation *invocation, const char *const *terms) { g_autoptr (RequestData) data = NULL; g_autoptr (DexFuture) future = NULL; dex_clear (&self->task); g_hash_table_remove_all (self->last_results); if (g_strv_length ((gchar **) terms) == 1 && g_utf8_strlen (terms[0], -1) == 1) { g_dbus_method_invocation_return_value ( invocation, g_variant_new ("(as)", NULL)); return; } if (self->engine == NULL) { g_warning ("search provider does not have an engine, " "returning empty response to invocation"); g_dbus_method_invocation_return_value ( invocation, g_variant_new ("(as)", NULL)); return; } data = request_data_new (); data->self = self; data->invocation = g_object_ref (invocation); data->application = g_application_get_default (); g_application_hold (data->application); future = bz_search_engine_query (self->engine, terms); future = dex_future_finally ( future, (DexFutureCallback) request_finally, request_data_ref (data), request_data_unref); self->task = g_steal_pointer (&future); } /* End of bz-gnome-shell-search-provider.c */ kolunmi-bazaar-7b9c8e1/src/bz-gnome-shell-search-provider.h000066400000000000000000000034111514314607700237370ustar00rootroot00000000000000/* bz-gnome-shell-search-provider.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-search-engine.h" G_BEGIN_DECLS #define BZ_TYPE_GNOME_SHELL_SEARCH_PROVIDER (bz_gnome_shell_search_provider_get_type ()) G_DECLARE_FINAL_TYPE (BzGnomeShellSearchProvider, bz_gnome_shell_search_provider, BZ, GNOME_SHELL_SEARCH_PROVIDER, GObject) BzGnomeShellSearchProvider * bz_gnome_shell_search_provider_new (void); BzSearchEngine * bz_gnome_shell_search_provider_get_engine (BzGnomeShellSearchProvider *self); void bz_gnome_shell_search_provider_set_engine (BzGnomeShellSearchProvider *self, BzSearchEngine *engine); GDBusConnection * bz_gnome_shell_search_provider_get_connection (BzGnomeShellSearchProvider *self); gboolean bz_gnome_shell_search_provider_set_connection (BzGnomeShellSearchProvider *self, GDBusConnection *connection, GError **error); G_END_DECLS /* End of bz-gnome-shell-search-provider.h */ kolunmi-bazaar-7b9c8e1/src/bz-group-tile-css-watcher.c000066400000000000000000000235321514314607700227430ustar00rootroot00000000000000/* bz-group-tile-css-watcher.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-group-tile-css-watcher.h" #define LUMINANCE_THRESHOLD 130.0 struct _BzGroupTileCssWatcher { GObject parent_instance; GWeakRef widget; BzEntryGroup *group; GtkCssProvider *css; char *light_class; char *dark_class; char *light_text_class; char *dark_text_class; }; G_DEFINE_FINAL_TYPE (BzGroupTileCssWatcher, bz_group_tile_css_watcher, G_TYPE_OBJECT); enum { PROP_0, PROP_WIDGET, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void refresh (BzGroupTileCssWatcher *self); static void clear (BzGroupTileCssWatcher *self); static void bz_group_tile_css_watcher_dispose (GObject *object) { BzGroupTileCssWatcher *self = BZ_GROUP_TILE_CSS_WATCHER (object); clear (self); g_weak_ref_clear (&self->widget); g_clear_pointer (&self->group, g_object_unref); G_OBJECT_CLASS (bz_group_tile_css_watcher_parent_class)->dispose (object); } static void bz_group_tile_css_watcher_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzGroupTileCssWatcher *self = BZ_GROUP_TILE_CSS_WATCHER (object); switch (prop_id) { case PROP_WIDGET: g_value_take_object (value, bz_group_tile_css_watcher_dup_widget (self)); break; case PROP_GROUP: g_value_set_object (value, bz_group_tile_css_watcher_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_group_tile_css_watcher_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzGroupTileCssWatcher *self = BZ_GROUP_TILE_CSS_WATCHER (object); switch (prop_id) { case PROP_WIDGET: bz_group_tile_css_watcher_set_widget (self, g_value_get_object (value)); break; case PROP_GROUP: bz_group_tile_css_watcher_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_group_tile_css_watcher_class_init (BzGroupTileCssWatcherClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_group_tile_css_watcher_set_property; object_class->get_property = bz_group_tile_css_watcher_get_property; object_class->dispose = bz_group_tile_css_watcher_dispose; props[PROP_WIDGET] = g_param_spec_object ( "widget", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void dark_changed (BzGroupTileCssWatcher *self, GParamSpec *pspec, AdwStyleManager *mgr) { g_autoptr (GtkWidget) widget = NULL; gboolean is_dark; if (self->css == NULL) return; widget = g_weak_ref_get (&self->widget); if (widget == NULL) return; is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_widget_remove_css_class (widget, self->light_class); gtk_widget_remove_css_class (widget, self->dark_class); gtk_widget_remove_css_class (widget, self->light_text_class); gtk_widget_remove_css_class (widget, self->dark_text_class); gtk_widget_add_css_class (widget, is_dark ? self->dark_class : self->light_class); gtk_widget_add_css_class (widget, is_dark ? self->dark_text_class : self->light_text_class); } static void bz_group_tile_css_watcher_init (BzGroupTileCssWatcher *self) { g_weak_ref_init (&self->widget, NULL); g_signal_connect_object ( adw_style_manager_get_default (), "notify::dark", G_CALLBACK (dark_changed), self, G_CONNECT_SWAPPED); } BzGroupTileCssWatcher * bz_group_tile_css_watcher_new (void) { return g_object_new (BZ_TYPE_GROUP_TILE_CSS_WATCHER, NULL); } GtkWidget * bz_group_tile_css_watcher_dup_widget (BzGroupTileCssWatcher *self) { g_return_val_if_fail (BZ_IS_GROUP_TILE_CSS_WATCHER (self), NULL); return g_weak_ref_get (&self->widget); } BzEntryGroup * bz_group_tile_css_watcher_get_group (BzGroupTileCssWatcher *self) { g_return_val_if_fail (BZ_IS_GROUP_TILE_CSS_WATCHER (self), NULL); return self->group; } void bz_group_tile_css_watcher_set_widget (BzGroupTileCssWatcher *self, GtkWidget *widget) { g_return_if_fail (BZ_IS_GROUP_TILE_CSS_WATCHER (self)); g_weak_ref_clear (&self->widget); if (widget != NULL) g_weak_ref_init (&self->widget, widget); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_WIDGET]); } void bz_group_tile_css_watcher_set_group (BzGroupTileCssWatcher *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_GROUP_TILE_CSS_WATCHER (self)); g_clear_pointer (&self->group, g_object_unref); if (group != NULL) self->group = g_object_ref (group); refresh (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } static gdouble get_luminance (GdkRGBA *rgba) { return (0.299 * rgba->red * 255.0) + (0.587 * rgba->green * 255.0) + (0.114 * rgba->blue * 255.0); } static gboolean color_is_light (const char *hex_color) { GdkRGBA rgba; gdouble luminance; if (hex_color == NULL || !gdk_rgba_parse (&rgba, hex_color)) return FALSE; luminance = get_luminance (&rgba); return luminance > LUMINANCE_THRESHOLD; } static void refresh (BzGroupTileCssWatcher *self) { g_autoptr (GtkWidget) widget = NULL; const char *id = NULL; const char *light_accent_color = NULL; const char *dark_accent_color = NULL; clear (self); widget = g_weak_ref_get (&self->widget); if (self->group == NULL || widget == NULL) return; id = bz_entry_group_get_id (self->group); light_accent_color = bz_entry_group_get_light_accent_color (self->group); dark_accent_color = bz_entry_group_get_dark_accent_color (self->group); if (light_accent_color != NULL || dark_accent_color != NULL) { g_autoptr (GString) fixed_id = NULL; g_autofree char *css_string = NULL; gboolean is_dark; fixed_id = g_string_new (id); g_string_replace (fixed_id, ".", "--", 0); self->light_class = g_strdup_printf ("%s-light", fixed_id->str); self->dark_class = g_strdup_printf ("%s-dark", fixed_id->str); self->light_text_class = g_strdup ( color_is_light (light_accent_color != NULL ? light_accent_color : dark_accent_color) ? "flathub-gunmetal" : "flathub-lotion"); self->dark_text_class = g_strdup ( color_is_light (dark_accent_color != NULL ? dark_accent_color : light_accent_color) ? "flathub-gunmetal" : "flathub-lotion"); css_string = g_strdup_printf ( ".%s{background-color:%s;}\n" ".%s{background-color:%s;}", self->light_class, light_accent_color != NULL ? light_accent_color : dark_accent_color, self->dark_class, dark_accent_color != NULL ? dark_accent_color : light_accent_color); self->css = gtk_css_provider_new (); gtk_css_provider_load_from_string ( self->css, css_string); gtk_style_context_add_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (self->css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_widget_add_css_class (widget, is_dark ? self->dark_class : self->light_class); gtk_widget_add_css_class (widget, is_dark ? self->dark_text_class : self->light_text_class); } } static void clear (BzGroupTileCssWatcher *self) { g_autoptr (GtkWidget) widget = NULL; widget = g_weak_ref_get (&self->widget); if (widget != NULL) { if (self->light_class != NULL) gtk_widget_remove_css_class (widget, self->light_class); if (self->dark_class != NULL) gtk_widget_remove_css_class (widget, self->dark_class); if (self->light_text_class != NULL) gtk_widget_remove_css_class (widget, self->light_text_class); if (self->dark_text_class != NULL) gtk_widget_remove_css_class (widget, self->dark_text_class); } g_clear_pointer (&self->light_class, g_free); g_clear_pointer (&self->dark_class, g_free); g_clear_pointer (&self->light_text_class, g_free); g_clear_pointer (&self->dark_text_class, g_free); if (self->css != NULL) gtk_style_context_remove_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (self->css)); g_clear_pointer (&self->css, g_object_unref); } /* End of bz-group-tile-css-watcher.c */ kolunmi-bazaar-7b9c8e1/src/bz-group-tile-css-watcher.h000066400000000000000000000031021514314607700227370ustar00rootroot00000000000000/* bz-group-tile-css-watcher.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry-group.h" G_BEGIN_DECLS #define BZ_TYPE_GROUP_TILE_CSS_WATCHER (bz_group_tile_css_watcher_get_type ()) G_DECLARE_FINAL_TYPE (BzGroupTileCssWatcher, bz_group_tile_css_watcher, BZ, GROUP_TILE_CSS_WATCHER, GObject) BzGroupTileCssWatcher * bz_group_tile_css_watcher_new (void); GtkWidget * bz_group_tile_css_watcher_dup_widget (BzGroupTileCssWatcher *self); BzEntryGroup * bz_group_tile_css_watcher_get_group (BzGroupTileCssWatcher *self); void bz_group_tile_css_watcher_set_widget (BzGroupTileCssWatcher *self, GtkWidget *widget); void bz_group_tile_css_watcher_set_group (BzGroupTileCssWatcher *self, BzEntryGroup *group); G_END_DECLS /* End of bz-group-tile-css-watcher.h */ kolunmi-bazaar-7b9c8e1/src/bz-hardware-support-dialog.blp000066400000000000000000000016501514314607700235270ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzHardwareSupportDialog: Adw.Dialog { content-height: 530; content-width: 640; title: _("Hardware Support"); Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { hscrollbar-policy: never; Adw.Clamp { maximum-size: 600; tightening-threshold: 400; Box { orientation: vertical; spacing: 24; margin-start: 24; margin-end: 24; margin-top: 24; margin-bottom: 24; $BzLozenge lozenge { title: _("Hardware Support"); icon-names: [ "device-supported-symbolic", ]; importance: unimportant; } ListBox list { selection-mode: none; styles [ "boxed-list", ] } } } }; } } kolunmi-bazaar-7b9c8e1/src/bz-hardware-support-dialog.c000066400000000000000000000235151514314607700232000ustar00rootroot00000000000000/* bz-hardware-support-dialog.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-hardware-support-dialog.h" #include "bz-context-row.h" #include "bz-lozenge.h" #include struct _BzHardwareSupportDialog { AdwDialog parent_instance; BzEntry *entry; gulong entry_notify_handler; /* Template widgets */ BzLozenge *lozenge; GtkListBox *list; }; G_DEFINE_FINAL_TYPE (BzHardwareSupportDialog, bz_hardware_support_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; typedef struct { const gchar *icon_name; const gchar *title; BzControlType control_flag; const gchar *required_subtitle; const gchar *recommended_subtitle; const gchar *supported_subtitle; const gchar *unsupported_subtitle; } ControlInfo; static const ControlInfo control_infos[] = { { "input-keyboard-symbolic", N_ ("Keyboard support"), BZ_CONTROL_KEYBOARD, N_ ("Requires keyboards"), N_ ("Recommends keyboards"), N_ ("Supports keyboards"), N_ ("Unknown support for keyboards") }, { "input-mouse-symbolic", N_ ("Mouse support"), BZ_CONTROL_POINTING, N_ ("Requires mice or pointing devices"), N_ ("Recommends mice or pointing devices"), N_ ("Supports mice or pointing devices"), N_ ("Unknown support for mice or pointing devices") }, { "device-support-touch-symbolic", N_ ("Touchscreen support"), BZ_CONTROL_TOUCH, N_ ("Requires touchscreens"), N_ ("Recommends touchscreens"), N_ ("Supports touchscreens"), N_ ("Unknown support for touchscreens") } }; static BzImportance get_control_importance (guint required_controls, guint recommended_controls, guint supported_controls, BzControlType control_flag) { if (required_controls & control_flag) return BZ_IMPORTANCE_IMPORTANT; else if (recommended_controls & control_flag) return BZ_IMPORTANCE_INFORMATION; else if (supported_controls & control_flag) return BZ_IMPORTANCE_UNIMPORTANT; else return BZ_IMPORTANCE_NEUTRAL; } static const gchar * get_subtitle_for_importance (const ControlInfo *info, BzImportance importance) { switch (importance) { case BZ_IMPORTANCE_IMPORTANT: return _ (info->required_subtitle); case BZ_IMPORTANCE_INFORMATION: return _ (info->recommended_subtitle); case BZ_IMPORTANCE_UNIMPORTANT: return _ (info->supported_subtitle); case BZ_IMPORTANCE_NEUTRAL: return _ (info->unsupported_subtitle); case BZ_IMPORTANCE_WARNING: default: g_assert_not_reached (); } } static void add_control_row (BzHardwareSupportDialog *self, const ControlInfo *info, BzImportance importance) { AdwActionRow *row; const gchar *subtitle; subtitle = get_subtitle_for_importance (info, importance); row = bz_context_row_new (info->icon_name, importance, _ (info->title), subtitle); gtk_list_box_append (self->list, GTK_WIDGET (row)); } static void update_list (BzHardwareSupportDialog *self) { GtkWidget *child; AdwActionRow *row; guint required_controls; guint recommended_controls; guint supported_controls; gboolean is_mobile_friendly; while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->list))) != NULL) gtk_list_box_remove (self->list, child); if (self->entry == NULL) return; required_controls = bz_entry_get_required_controls (self->entry); recommended_controls = bz_entry_get_recommended_controls (self->entry); supported_controls = bz_entry_get_supported_controls (self->entry); is_mobile_friendly = bz_entry_get_is_mobile_friendly (self->entry); row = bz_context_row_new ("phone-symbolic", is_mobile_friendly ? BZ_IMPORTANCE_UNIMPORTANT : BZ_IMPORTANCE_NEUTRAL, _ ("Mobile support"), is_mobile_friendly ? _ ("Works on mobile devices") : _ ("May not work well on mobile devices")); gtk_list_box_append (self->list, GTK_WIDGET (row)); row = bz_context_row_new ("device-support-desktop-symbolic", BZ_IMPORTANCE_UNIMPORTANT, _ ("Desktop support"), _ ("Works well on large screens")); gtk_list_box_append (self->list, GTK_WIDGET (row)); for (gsize i = 0; i < G_N_ELEMENTS (control_infos); i++) { BzImportance importance; importance = get_control_importance (required_controls, recommended_controls, supported_controls, control_infos[i].control_flag); add_control_row (self, &control_infos[i], importance); } } static void update_header (BzHardwareSupportDialog *self) { const gchar *icon_names[2]; g_autofree gchar *title_text = NULL; BzImportance importance; guint required_controls; gboolean is_mobile_friendly; if (self->entry == NULL) return; required_controls = bz_entry_get_required_controls (self->entry); is_mobile_friendly = bz_entry_get_is_mobile_friendly (self->entry); if (required_controls != BZ_CONTROL_NONE || !is_mobile_friendly) { icon_names[0] = "dialog-warning-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s works best on specific hardware"), bz_entry_get_title (self->entry)); importance = BZ_IMPORTANCE_NEUTRAL; } else { icon_names[0] = "device-supported-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s works on most devices"), bz_entry_get_title (self->entry)); importance = BZ_IMPORTANCE_UNIMPORTANT; } bz_lozenge_set_icon_names (self->lozenge, icon_names); bz_lozenge_set_title (self->lozenge, title_text); bz_lozenge_set_importance (self->lozenge, importance); } static void update_ui (BzHardwareSupportDialog *self) { update_list (self); update_header (self); } static void entry_notify_cb (GObject *obj, GParamSpec *pspec, gpointer user_data) { BzHardwareSupportDialog *self = BZ_HARDWARE_SUPPORT_DIALOG (user_data); update_ui (self); } static void bz_hardware_support_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzHardwareSupportDialog *self = BZ_HARDWARE_SUPPORT_DIALOG (object); switch (prop_id) { case PROP_ENTRY: self->entry = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_hardware_support_dialog_constructed (GObject *object) { BzHardwareSupportDialog *self = BZ_HARDWARE_SUPPORT_DIALOG (object); G_OBJECT_CLASS (bz_hardware_support_dialog_parent_class)->constructed (object); if (self->entry != NULL) { self->entry_notify_handler = g_signal_connect (self->entry, "notify", G_CALLBACK (entry_notify_cb), self); update_ui (self); } } static void bz_hardware_support_dialog_dispose (GObject *object) { BzHardwareSupportDialog *self = BZ_HARDWARE_SUPPORT_DIALOG (object); g_clear_signal_handler (&self->entry_notify_handler, self->entry); g_clear_object (&self->entry); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_HARDWARE_SUPPORT_DIALOG); G_OBJECT_CLASS (bz_hardware_support_dialog_parent_class)->dispose (object); } static void bz_hardware_support_dialog_class_init (BzHardwareSupportDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_hardware_support_dialog_set_property; object_class->constructed = bz_hardware_support_dialog_constructed; object_class->dispose = bz_hardware_support_dialog_dispose; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LOZENGE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-hardware-support-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzHardwareSupportDialog, lozenge); gtk_widget_class_bind_template_child (widget_class, BzHardwareSupportDialog, list); } static void bz_hardware_support_dialog_init (BzHardwareSupportDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzHardwareSupportDialog * bz_hardware_support_dialog_new (BzEntry *entry) { return g_object_new (BZ_TYPE_HARDWARE_SUPPORT_DIALOG, "entry", entry, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-hardware-support-dialog.h000066400000000000000000000021771514314607700232060ustar00rootroot00000000000000/* bz-hardware-support-dialog.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include #include G_BEGIN_DECLS #define BZ_TYPE_HARDWARE_SUPPORT_DIALOG (bz_hardware_support_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzHardwareSupportDialog, bz_hardware_support_dialog, BZ, HARDWARE_SUPPORT_DIALOG, AdwDialog) BzHardwareSupportDialog *bz_hardware_support_dialog_new (BzEntry *entry); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-hash-table-object.txt000066400000000000000000000002571514314607700223030ustar00rootroot00000000000000prefix=bz name=hash_table_object parent-prefix=g parent-name=object author=AUTOGEN property=hash_table GHashTable G_TYPE_HASH_TABLE boxed g_hash_table_unref g_hash_table_ref kolunmi-bazaar-7b9c8e1/src/bz-hook-dialog-option.txt000066400000000000000000000003431514314607700225260ustar00rootroot00000000000000prefix=bz name=hook_dialog_option parent-prefix=g parent-name=object author=AUTOGEN include= property=id char G_TYPE_STRING string property=string char G_TYPE_STRING string property=style char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-hook-dialog.txt000066400000000000000000000007041514314607700212210ustar00rootroot00000000000000prefix=bz name=hook_dialog parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-hook-dialog-option.h" ensure=BZ_TYPE_HOOK_DIALOG_OPTION property=id char G_TYPE_STRING string property=title char G_TYPE_STRING string property=body char G_TYPE_STRING string property=body_use_markup gboolean G_TYPE_BOOLEAN boolean property=options GListModel G_TYPE_LIST_MODEL object property=default_response_id char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-hook.txt000066400000000000000000000006471514314607700177720ustar00rootroot00000000000000prefix=bz name=hook parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-hook-dialog.h" ensure=BZ_TYPE_HOOK_DIALOG ensure=BZ_TYPE_HOOK_DIALOG_OPTION enum=bz hook_signal before_transaction after_transaction property=id char G_TYPE_STRING string property=when BzHookSignal BZ_TYPE_HOOK_SIGNAL enum property=dialogs GListModel G_TYPE_LIST_MODEL object property=shell char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-inhibited-scrollable.c000066400000000000000000000347001514314607700225110ustar00rootroot00000000000000/* bz-inhibited-scrollable.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ /* This is a complete hack but I * don't see any other way to prevent * the annoying jumping in GtkListView etc */ #include "config.h" #include "bz-inhibited-scrollable.h" struct _BzInhibitedScrollable { GtkWidget parent_instance; GtkScrollable *child; GtkScrollablePolicy hscroll_policy; GtkScrollablePolicy vscroll_policy; GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; GtkAdjustment *child_hadjustment; GtkAdjustment *child_vadjustment; GBinding *hscroll_policy_bind; GBinding *vscroll_policy_bind; struct { GBinding *lower; GBinding *upper; GBinding *page_increment; GBinding *step_increment; GBinding *page_size; GBinding *value; } vadjustment_binds; struct { GBinding *lower; GBinding *upper; GBinding *page_increment; GBinding *step_increment; GBinding *page_size; GBinding *value; } hadjustment_binds; }; static void scrollable_iface_init (GtkScrollableInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzInhibitedScrollable, bz_inhibited_scrollable, GTK_TYPE_WIDGET, G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, scrollable_iface_init)) enum { PROP_0, PROP_SCROLLABLE, LAST_PROP, PROP_HADJUSTMENT, PROP_VADJUSTMENT, PROP_HSCROLL_POLICY, PROP_VSCROLL_POLICY, }; static GParamSpec *props[LAST_PROP] = { 0 }; static void child_adjustment_value_changed (BzInhibitedScrollable *self, GtkAdjustment *adjustment); static void setup_hadjustments (BzInhibitedScrollable *self); static void setup_vadjustments (BzInhibitedScrollable *self); static void clear_bindings (BzInhibitedScrollable *self); static void bz_inhibited_scrollable_dispose (GObject *object) { BzInhibitedScrollable *self = BZ_INHIBITED_SCROLLABLE (object); clear_bindings (self); g_clear_object (&self->hadjustment); g_clear_object (&self->vadjustment); g_clear_pointer ((GtkWidget **) &self->child, gtk_widget_unparent); G_OBJECT_CLASS (bz_inhibited_scrollable_parent_class)->dispose (object); } static void bz_inhibited_scrollable_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzInhibitedScrollable *self = BZ_INHIBITED_SCROLLABLE (object); switch (prop_id) { case PROP_SCROLLABLE: g_value_set_object (value, bz_inhibited_scrollable_get_scrollable (self)); break; case PROP_HADJUSTMENT: g_value_set_object (value, self->hadjustment); break; case PROP_VADJUSTMENT: g_value_set_object (value, self->vadjustment); break; case PROP_HSCROLL_POLICY: g_value_set_enum (value, self->hscroll_policy); break; case PROP_VSCROLL_POLICY: g_value_set_enum (value, self->vscroll_policy); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_inhibited_scrollable_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzInhibitedScrollable *self = BZ_INHIBITED_SCROLLABLE (object); switch (prop_id) { case PROP_SCROLLABLE: bz_inhibited_scrollable_set_scrollable (self, g_value_get_object (value)); break; case PROP_HADJUSTMENT: g_clear_object (&self->hadjustment); self->hadjustment = g_value_dup_object (value); setup_hadjustments (self); break; case PROP_VADJUSTMENT: g_clear_object (&self->vadjustment); self->vadjustment = g_value_dup_object (value); setup_vadjustments (self); break; case PROP_HSCROLL_POLICY: self->hscroll_policy = g_value_get_enum (value); break; case PROP_VSCROLL_POLICY: self->vscroll_policy = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_inhibited_scrollable_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzInhibitedScrollable *self = BZ_INHIBITED_SCROLLABLE (widget); if (self->child != NULL && gtk_widget_should_layout (GTK_WIDGET (self->child))) gtk_widget_allocate (GTK_WIDGET (self->child), width, height, baseline, NULL); } static void bz_inhibited_scrollable_class_init (BzInhibitedScrollableClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_inhibited_scrollable_dispose; object_class->get_property = bz_inhibited_scrollable_get_property; object_class->set_property = bz_inhibited_scrollable_set_property; props[PROP_SCROLLABLE] = g_param_spec_object ( "scrollable", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment"); g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment"); g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy"); g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy"); widget_class->size_allocate = bz_inhibited_scrollable_size_allocate; } static void bz_inhibited_scrollable_init (BzInhibitedScrollable *self) { } static gboolean scrollable_get_border (GtkScrollable *scrollable, GtkBorder *border) { BzInhibitedScrollable *self = BZ_INHIBITED_SCROLLABLE (scrollable); if (self->child != NULL) return gtk_scrollable_get_border (self->child, border); else return FALSE; } static void scrollable_iface_init (GtkScrollableInterface *iface) { iface->get_border = scrollable_get_border; } GtkWidget * bz_inhibited_scrollable_new (void) { return g_object_new (BZ_TYPE_INHIBITED_SCROLLABLE, NULL); } void bz_inhibited_scrollable_set_scrollable (BzInhibitedScrollable *self, GtkScrollable *child) { g_return_if_fail (BZ_IS_INHIBITED_SCROLLABLE (self)); g_return_if_fail (child == NULL || GTK_IS_SCROLLABLE (child)); if (self->child == child) return; if (child != NULL) g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (child)) == NULL); clear_bindings (self); g_clear_pointer ((GtkWidget **) &self->child, gtk_widget_unparent); self->child = child; if (child != NULL) { gtk_widget_set_parent (GTK_WIDGET (child), GTK_WIDGET (self)); self->hscroll_policy_bind = g_object_bind_property ( self, "hscroll-policy", self->child, "hscroll-policy", G_BINDING_SYNC_CREATE); self->vscroll_policy_bind = g_object_bind_property ( self, "vscroll-policy", self->child, "vscroll-policy", G_BINDING_SYNC_CREATE); setup_hadjustments (self); setup_vadjustments (self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SCROLLABLE]); } GtkScrollable * bz_inhibited_scrollable_get_scrollable (BzInhibitedScrollable *self) { g_return_val_if_fail (BZ_IS_INHIBITED_SCROLLABLE (self), NULL); return self->child; } static void child_adjustment_value_changed (BzInhibitedScrollable *self, GtkAdjustment *adjustment) { GtkAdjustment *parent_adjustment = NULL; double child_value = 0.0; double forced_value = 0.0; if (adjustment == self->child_vadjustment) parent_adjustment = self->vadjustment; else parent_adjustment = self->hadjustment; child_value = gtk_adjustment_get_value (adjustment); forced_value = gtk_adjustment_get_value (parent_adjustment); if (child_value != forced_value) gtk_adjustment_set_value (adjustment, forced_value); } static void setup_hadjustments (BzInhibitedScrollable *self) { g_clear_object (&self->hadjustment_binds.lower); g_clear_object (&self->hadjustment_binds.upper); g_clear_object (&self->hadjustment_binds.page_increment); g_clear_object (&self->hadjustment_binds.step_increment); g_clear_object (&self->hadjustment_binds.page_size); g_clear_object (&self->hadjustment_binds.value); if (self->child_hadjustment != NULL) g_signal_handlers_disconnect_by_func ( self->child_hadjustment, child_adjustment_value_changed, self); g_clear_object (&self->child_hadjustment); if (self->child != NULL && self->hadjustment != NULL) { self->child_hadjustment = g_object_ref_sink (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); g_signal_connect_swapped (self->child_hadjustment, "value-changed", G_CALLBACK (child_adjustment_value_changed), self); self->hadjustment_binds.lower = g_object_bind_property ( self->hadjustment, "lower", self->child_hadjustment, "lower", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->hadjustment_binds.upper = g_object_bind_property ( self->hadjustment, "upper", self->child_hadjustment, "upper", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->hadjustment_binds.page_increment = g_object_bind_property ( self->hadjustment, "page-increment", self->child_hadjustment, "page-increment", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->hadjustment_binds.step_increment = g_object_bind_property ( self->hadjustment, "step-increment", self->child_hadjustment, "step-increment", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->hadjustment_binds.page_size = g_object_bind_property ( self->hadjustment, "page-size", self->child_hadjustment, "page-size", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->hadjustment_binds.value = g_object_bind_property ( self->hadjustment, "value", self->child_hadjustment, "value", G_BINDING_SYNC_CREATE); gtk_scrollable_set_hadjustment (self->child, self->child_hadjustment); } } static void setup_vadjustments (BzInhibitedScrollable *self) { g_clear_object (&self->vadjustment_binds.lower); g_clear_object (&self->vadjustment_binds.upper); g_clear_object (&self->vadjustment_binds.page_increment); g_clear_object (&self->vadjustment_binds.step_increment); g_clear_object (&self->vadjustment_binds.page_size); g_clear_object (&self->vadjustment_binds.value); if (self->child_vadjustment != NULL) g_signal_handlers_disconnect_by_func ( self->child_vadjustment, child_adjustment_value_changed, self); g_clear_object (&self->child_vadjustment); if (self->child != NULL && self->vadjustment != NULL) { self->child_vadjustment = g_object_ref_sink (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); g_signal_connect_swapped (self->child_vadjustment, "value-changed", G_CALLBACK (child_adjustment_value_changed), self); self->vadjustment_binds.lower = g_object_bind_property ( self->vadjustment, "lower", self->child_vadjustment, "lower", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->vadjustment_binds.upper = g_object_bind_property ( self->vadjustment, "upper", self->child_vadjustment, "upper", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->vadjustment_binds.page_increment = g_object_bind_property ( self->vadjustment, "page-increment", self->child_vadjustment, "page-increment", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->vadjustment_binds.step_increment = g_object_bind_property ( self->vadjustment, "step-increment", self->child_vadjustment, "step-increment", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->vadjustment_binds.page_size = g_object_bind_property ( self->vadjustment, "page-size", self->child_vadjustment, "page-size", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->vadjustment_binds.value = g_object_bind_property ( self->vadjustment, "value", self->child_vadjustment, "value", G_BINDING_SYNC_CREATE); gtk_scrollable_set_vadjustment (self->child, self->child_vadjustment); } } static void clear_bindings (BzInhibitedScrollable *self) { g_clear_object (&self->hscroll_policy_bind); g_clear_object (&self->vscroll_policy_bind); g_clear_object (&self->hadjustment_binds.lower); g_clear_object (&self->hadjustment_binds.upper); g_clear_object (&self->hadjustment_binds.page_increment); g_clear_object (&self->hadjustment_binds.step_increment); g_clear_object (&self->hadjustment_binds.page_size); g_clear_object (&self->hadjustment_binds.value); g_clear_object (&self->vadjustment_binds.lower); g_clear_object (&self->vadjustment_binds.upper); g_clear_object (&self->vadjustment_binds.page_increment); g_clear_object (&self->vadjustment_binds.step_increment); g_clear_object (&self->vadjustment_binds.page_size); g_clear_object (&self->vadjustment_binds.value); if (self->child_hadjustment != NULL) g_signal_handlers_disconnect_by_func ( self->child_hadjustment, child_adjustment_value_changed, self); g_clear_object (&self->child_hadjustment); if (self->child_vadjustment != NULL) g_signal_handlers_disconnect_by_func ( self->child_vadjustment, child_adjustment_value_changed, self); g_clear_object (&self->child_vadjustment); } kolunmi-bazaar-7b9c8e1/src/bz-inhibited-scrollable.h000066400000000000000000000024241514314607700225140ustar00rootroot00000000000000/* bz-inhibited-scrollable.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_INHIBITED_SCROLLABLE (bz_inhibited_scrollable_get_type ()) G_DECLARE_FINAL_TYPE (BzInhibitedScrollable, bz_inhibited_scrollable, BZ, INHIBITED_SCROLLABLE, GtkWidget) GtkWidget * bz_inhibited_scrollable_new (void); void bz_inhibited_scrollable_set_scrollable (BzInhibitedScrollable *self, GtkScrollable *scrollable); GtkScrollable * bz_inhibited_scrollable_get_scrollable (BzInhibitedScrollable *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-inspector.blp000066400000000000000000000135401514314607700207720ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzInspector: Adw.Window { title: "Bazaar Inspector"; default-width: 800; default-height: 1000; width-request: 300; height-request: 600; Adw.ToolbarView { top-bar-style: raised_border; bottom-bar-style: raised_border; reveal-bottom-bars: false; content: Box { orientation: vertical; width-request: 100; spacing: 10; Box { styles [ "bz-debug" ] orientation: horizontal; spacing: 10; Label { styles [ "heading" ] label: "Background Task Info:"; xalign: 0.0; } Label { label: bind template.state as <$BzStateInfo>.background-task-label as ; xalign: 0.0; } } Box { orientation: vertical; spacing: 3; CheckButton debug_mode_check { label: "Enable Global Debug Mode"; } CheckButton disable_blocklists_check { label: "Disable All Blocklists"; } } Box { orientation: vertical; spacing: 3; Label { styles [ "heading" ] label: "Active Blocklists (YAML)"; xalign: 0.0; } ScrolledWindow { propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.state as <$BzStateInfo>.blocklists; }; factory: string_list_factory; }; } } Box { orientation: vertical; spacing: 3; Label { styles [ "heading" ] label: "Active Blocklists (TXT)"; xalign: 0.0; } ScrolledWindow { propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.state as <$BzStateInfo>.txt-blocklists; }; factory: string_list_factory; }; } } Box { orientation: vertical; spacing: 3; Label { styles [ "heading" ] label: "Active Curated-Configs"; xalign: 0.0; } ScrolledWindow { propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.state as <$BzStateInfo>.curated-configs; }; factory: string_list_factory; }; } } Label { styles [ "heading" ] margin-top: 10; label: "All Entry Groups"; xalign: 0.0; } Box { orientation: horizontal; spacing: 5; CheckButton { label: "Preview"; notify::active => $preview_changed(template); } Entry search_entry { hexpand: true; margin-start: 5; margin-end: 5; margin-top: 5; margin-bottom: 5; placeholder-text: "Filter..."; changed => $entry_changed(template); } } ScrolledWindow { vscrollbar-policy: always; propagate-natural-height: true; child: ListView { model: SingleSelection groups_selection { model: FilterListModel filter_model { model: bind template.state as <$BzStateInfo>.all-entry-groups; }; notify::selected-item => $selected_group_changed(template); }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Expander { label: bind template.item as <$BzEntryGroup>.id as ; child: Box { orientation: vertical; Separator {} ScrolledWindow { propagate-natural-height: true; child: ListView { model: NoSelection { model: bind template.item as <$BzEntryGroup>.model; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { orientation: horizontal; Label { hexpand: true; ellipsize: end; xalign: 0.0; label: bind template.item as <$GtkStringObject>.string as ; } Button { label: "Decache and Inspect"; clicked => $decache_and_inspect_cb(template); } }; } }; }; } Separator {} }; }; } }; }; } }; [top] Adw.HeaderBar top_header_bar {} } } BuilderListItemFactory string_list_factory { template ListItem { selectable: false; activatable: false; child: Box { orientation: horizontal; spacing: 10; Label { styles [ "dimmed", "bz-monospace", ] width-request: 30; label: bind $format_uint(template.position) as ; xalign: 1.0; } Label { styles [ "bz-monospace", ] hexpand: true; margin-top: 2; margin-bottom: 2; xalign: 0.0; selectable: true; label: bind template.item as <$GtkStringObject>.string as ; } Button { label: "Open"; clicked => $open_file_externally_cb(template); } }; } } kolunmi-bazaar-7b9c8e1/src/bz-inspector.c000066400000000000000000000221051514314607700204340ustar00rootroot00000000000000/* bz-inspector.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-inspector.h" #include "bz-entry-inspector.h" #include "bz-window.h" struct _BzInspector { AdwWindow parent_instance; BzStateInfo *state; GBinding *debug_mode_binding; GBinding *disable_blocklists_binding; GtkWindow *preview_window; GtkCheckButton *debug_mode_check; GtkCheckButton *disable_blocklists_check; GtkEditable *search_entry; GtkFilterListModel *filter_model; GtkSingleSelection *groups_selection; }; G_DEFINE_FINAL_TYPE (BzInspector, bz_inspector, ADW_TYPE_WINDOW); enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static gboolean filter_func (BzEntryGroup *group, BzInspector *self); static void bz_inspector_dispose (GObject *object) { BzInspector *self = BZ_INSPECTOR (object); g_clear_pointer (&self->state, g_object_unref); g_clear_object (&self->debug_mode_binding); g_clear_object (&self->disable_blocklists_binding); if (self->preview_window != NULL) gtk_window_close (self->preview_window); g_clear_object (&self->preview_window); G_OBJECT_CLASS (bz_inspector_parent_class)->dispose (object); } static void bz_inspector_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzInspector *self = BZ_INSPECTOR (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_inspector_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_inspector_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzInspector *self = BZ_INSPECTOR (object); switch (prop_id) { case PROP_STATE: bz_inspector_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void preview_changed (BzInspector *self, GParamSpec *pspec, GtkCheckButton *button) { if (gtk_check_button_get_active (button)) { BzWindow *window = NULL; BzEntryGroup *selected = NULL; g_assert (self->preview_window == NULL); window = bz_window_new (self->state); gtk_window_set_default_size (GTK_WINDOW (window), 750, 750); gtk_window_present (GTK_WINDOW (window)); selected = gtk_single_selection_get_selected_item (self->groups_selection); if (selected != NULL) bz_window_show_group (window, selected); self->preview_window = (GtkWindow *) g_object_ref_sink (window); } else { if (self->preview_window != NULL) gtk_window_close (self->preview_window); g_clear_object (&self->preview_window); } } static void selected_group_changed (BzInspector *self, GParamSpec *pspec, GtkSingleSelection *selection) { BzEntryGroup *group = NULL; if (self->preview_window == NULL || !gtk_widget_get_mapped (GTK_WIDGET (self->preview_window))) return; group = gtk_single_selection_get_selected_item (self->groups_selection); if (group != NULL) bz_window_show_group (BZ_WINDOW (self->preview_window), group); } static void entry_changed (BzInspector *self, GtkEditable *editable) { GtkFilter *filter = NULL; filter = gtk_filter_list_model_get_filter (self->filter_model); gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT); } static void decache_and_inspect_cb (GtkListItem *list_item, GtkButton *button) { GtkStringObject *item = NULL; BzInspector *self = NULL; g_autoptr (BzResult) result = NULL; item = gtk_list_item_get_item (list_item); self = BZ_INSPECTOR (gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_INSPECTOR)); g_assert (self != NULL); result = bz_application_map_factory_convert_one ( bz_state_info_get_entry_factory (self->state), g_object_ref (item)); if (result != NULL) { BzEntryInspector *inspector = NULL; inspector = bz_entry_inspector_new (); bz_entry_inspector_set_result (inspector, result); gtk_window_present (GTK_WINDOW (inspector)); } } static void open_file_externally_cb (GtkListItem *list_item, GtkButton *button) { GtkStringObject *string = NULL; const char *path = NULL; g_autofree char *uri = NULL; string = gtk_list_item_get_item (list_item); path = gtk_string_object_get_string (string); uri = g_strdup_printf ("file://%s", path); g_app_info_launch_default_for_uri (uri, NULL, NULL); } static char * format_uint (gpointer object, guint value) { return g_strdup_printf ("%d", value); } static void bz_inspector_class_init (BzInspectorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_inspector_set_property; object_class->get_property = bz_inspector_get_property; object_class->dispose = bz_inspector_dispose; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-inspector.ui"); gtk_widget_class_bind_template_child (widget_class, BzInspector, debug_mode_check); gtk_widget_class_bind_template_child (widget_class, BzInspector, disable_blocklists_check); gtk_widget_class_bind_template_child (widget_class, BzInspector, search_entry); gtk_widget_class_bind_template_child (widget_class, BzInspector, filter_model); gtk_widget_class_bind_template_child (widget_class, BzInspector, groups_selection); gtk_widget_class_bind_template_callback (widget_class, preview_changed); gtk_widget_class_bind_template_callback (widget_class, selected_group_changed); gtk_widget_class_bind_template_callback (widget_class, decache_and_inspect_cb); gtk_widget_class_bind_template_callback (widget_class, open_file_externally_cb); gtk_widget_class_bind_template_callback (widget_class, entry_changed); gtk_widget_class_bind_template_callback (widget_class, format_uint); } static void bz_inspector_init (BzInspector *self) { GtkCustomFilter *filter = NULL; gtk_widget_init_template (GTK_WIDGET (self)); filter = gtk_custom_filter_new ((GtkCustomFilterFunc) filter_func, self, NULL); gtk_filter_list_model_set_filter (self->filter_model, GTK_FILTER (filter)); } BzInspector * bz_inspector_new (void) { return g_object_new (BZ_TYPE_INSPECTOR, NULL); } BzStateInfo * bz_inspector_get_state (BzInspector *self) { g_return_val_if_fail (BZ_IS_INSPECTOR (self), NULL); return self->state; } void bz_inspector_set_state (BzInspector *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_INSPECTOR (self)); g_clear_pointer (&self->state, g_object_unref); g_clear_pointer (&self->debug_mode_binding, g_object_unref); g_clear_pointer (&self->disable_blocklists_binding, g_object_unref); if (state != NULL) { self->state = g_object_ref (state); self->debug_mode_binding = g_object_bind_property ( state, "debug-mode", self->debug_mode_check, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); self->disable_blocklists_binding = g_object_bind_property ( state, "disable-blocklists", self->disable_blocklists_check, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } static gboolean filter_func (BzEntryGroup *group, BzInspector *self) { const char *text = NULL; const char *id = NULL; const char *title = NULL; text = gtk_editable_get_text (self->search_entry); id = bz_entry_group_get_id (group); title = bz_entry_group_get_title (group); if (text == NULL || *text == '\0') return TRUE; if (strcasestr (id, text) != NULL) return TRUE; if (strcasestr (title, text) != NULL) return TRUE; return FALSE; } /* End of bz-inspector.c */ kolunmi-bazaar-7b9c8e1/src/bz-inspector.h000066400000000000000000000022561514314607700204460ustar00rootroot00000000000000/* bz-inspector.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_INSPECTOR (bz_inspector_get_type ()) G_DECLARE_FINAL_TYPE (BzInspector, bz_inspector, BZ, INSPECTOR, AdwWindow) BzInspector * bz_inspector_new (void); BzStateInfo * bz_inspector_get_state (BzInspector *self); void bz_inspector_set_state (BzInspector *self, BzStateInfo *state); G_END_DECLS /* End of bz-inspector.h */ kolunmi-bazaar-7b9c8e1/src/bz-installed-tile.blp000066400000000000000000000073261514314607700217030ustar00rootroot00000000000000using Gtk 4.0; template $BzInstalledTile: $BzListTile { accessibility { labelled-by: title_label; described-by: description_label; } child: Box { orientation: horizontal; spacing: 10; Picture icon_picture { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 64; width-request: 64; paintable: bind template.group as <$BzEntryGroup>.icon-paintable; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.icon-paintable) as ) as ; styles ["icon-dropshadow"] } Image fallback_icon { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 64; width-request: 64; pixel-size: 64; icon-name: "application-x-executable"; visible: bind $is_null(template.group as <$BzEntryGroup>.icon-paintable) as ; styles ["icon-dropshadow"] } Box { orientation: vertical; valign: center; spacing: 4; Label title_label { xalign: 0.0; ellipsize: end; single-line-mode: true; has-tooltip: true; tooltip-text: bind template.group as <$BzEntryGroup>.id; label: bind template.group as <$BzEntryGroup>.title; } Label description_label { halign: start; ellipsize: end; single-line-mode: true; label: bind $format_description(template.group as <$BzEntryGroup>.installed-size, template.group as <$BzEntryGroup>.installed-versions) as ; styles ["dimmed", "caption", "installed-size"] } Label { xalign: 0.0; ellipsize: end; single-line-mode: true; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.eol) as ) as ; label: _("Stopped Receiving Updates"); styles ["warning", "caption"] } } Button support_button { styles [ "circular", "flat", "suggested-action", "support" ] has-tooltip: true; tooltip-text: _("Support this application"); width-request: 32; height-request: 32; valign: center; icon-name: "heart-filled-symbolic"; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.donation-url) as ) as ; clicked => $support_cb() swapped; } Box { orientation: horizontal; spacing: 8; margin-end: 8; hexpand: true; halign: end; Button addons_button { styles [ "flat" ] has-tooltip: true; tooltip-text: _("Manage Add-ons"); width-request: 32; height-request: 32; valign: center; icon-name: "puzzle-piece-symbolic"; sensitive: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as ; visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.n-addons as ) as ) as ; clicked => $install_addons_cb() swapped; } Button remove_button { styles [ "flat", ] has-tooltip: true; tooltip-text: _("Remove"); width-request: 32; height-request: 32; valign: center; icon-name: "user-trash-symbolic"; visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as ; clicked => $remove_cb() swapped; } Image { pixel-size: 14; icon-name: "go-next-symbolic"; margin-end: 4; styles ["dimmed"] } } }; } kolunmi-bazaar-7b9c8e1/src/bz-installed-tile.c000066400000000000000000000264531514314607700213520ustar00rootroot00000000000000/* bz-installed-tile.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-addons-dialog.h" #include "bz-entry-group-util.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-error.h" #include "bz-installed-tile.h" #include "bz-library-page.h" #include "bz-state-info.h" struct _BzInstalledTile { BzListTile parent_instance; BzEntryGroup *group; GtkPicture *icon_picture; GtkImage *fallback_icon; GtkLabel *title_label; GtkButton *support_button; GtkButton *addons_button; GtkButton *remove_button; }; G_DEFINE_FINAL_TYPE (BzInstalledTile, bz_installed_tile, BZ_TYPE_LIST_TILE) enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static gboolean test_is_support (BzEntry *entry); static gboolean test_has_addons (BzEntry *entry); static void bz_installed_tile_dispose (GObject *object) { BzInstalledTile *self = BZ_INSTALLED_TILE (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_installed_tile_parent_class)->dispose (object); } static void bz_installed_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzInstalledTile *self = BZ_INSTALLED_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_installed_tile_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_installed_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzInstalledTile *self = BZ_INSTALLED_TILE (object); switch (prop_id) { case PROP_GROUP: bz_installed_tile_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static char * format_description (gpointer object, guint64 size, GListModel *versions) { g_autoptr (GString) result = NULL; g_autoptr (GString) versions_str = NULL; g_autofree char *size_str = NULL; guint n_versions = 0; result = g_string_new (NULL); if (versions != NULL) n_versions = g_list_model_get_n_items (versions); if (n_versions > 0) { versions_str = g_string_new (NULL); for (guint i = 0; i < n_versions; i++) { g_autoptr (GtkStringObject) string = NULL; const char *version = NULL; string = g_list_model_get_item (versions, i); version = gtk_string_object_get_string (string); if (version != NULL && *version != '\0') { if (versions_str->len > 0) g_string_append_c (versions_str, ' '); g_string_append (versions_str, version); } } if (versions_str->len > 0) { g_string_append (result, versions_str->str); g_string_append (result, " • "); } } size_str = g_format_size (size); g_string_append (result, size_str); return g_string_free (g_steal_pointer (&result), FALSE); } static void addon_transact_cb (BzInstalledTile *self, BzEntry *entry, BzAddonsDialog *dialog) { BzLibraryPage *page = NULL; gboolean installed = FALSE; page = BZ_LIBRARY_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (self), BZ_TYPE_LIBRARY_PAGE)); g_assert (page != NULL); g_object_get (entry, "installed", &installed, NULL); if (installed) g_signal_emit_by_name (page, "remove-addon", entry); else g_signal_emit_by_name (page, "install-addon", entry); } static DexFuture * support_fiber (BzInstalledTile *tile) { g_autoptr (GError) local_error = NULL; GtkWidget *window = NULL; g_autoptr (BzEntry) entry = NULL; const char *url = NULL; window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); g_assert (window != NULL); entry = bz_entry_group_find_entry (tile->group, test_is_support, window, &local_error); if (entry == NULL) goto err; url = bz_entry_get_donation_url (entry); g_app_info_launch_default_for_uri (url, NULL, NULL); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return NULL; } static void support_cb (BzInstalledTile *self, GtkButton *button) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) support_fiber, g_object_ref (self), g_object_unref)); } static DexFuture * install_addons_fiber (BzInstalledTile *tile) { g_autoptr (GError) local_error = NULL; BzLibraryPage *page = NULL; BzStateInfo *state = NULL; GtkWidget *window = NULL; g_autoptr (BzEntry) entry = NULL; g_autoptr (GListModel) model = NULL; AdwDialog *addons_dialog = NULL; page = BZ_LIBRARY_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_LIBRARY_PAGE)); g_assert (page != NULL); window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); g_assert (window != NULL); g_object_get (page, "state", &state, NULL); g_assert (state != NULL); entry = bz_entry_group_find_entry (tile->group, test_has_addons, window, &local_error); if (entry == NULL) goto err; model = bz_application_map_factory_generate ( bz_state_info_get_entry_factory (state), bz_entry_get_addons (entry)); addons_dialog = bz_addons_dialog_new (entry, model); gtk_widget_set_size_request (GTK_WIDGET (addons_dialog), 350, -1); g_signal_connect_swapped (addons_dialog, "transact", G_CALLBACK (addon_transact_cb), tile); adw_dialog_present (addons_dialog, GTK_WIDGET (tile)); g_clear_object (&state); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); g_clear_object (&state); return NULL; } static void install_addons_cb (BzInstalledTile *self, GtkButton *button) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) install_addons_fiber, g_object_ref (self), g_object_unref)); } static DexFuture * remove_fiber (BzInstalledTile *tile) { g_autoptr (GError) local_error = NULL; BzLibraryPage *page = NULL; GtkWidget *window = NULL; g_autoptr (BzEntry) entry = NULL; page = BZ_LIBRARY_PAGE (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_LIBRARY_PAGE)); g_assert (page != NULL); window = gtk_widget_get_ancestor (GTK_WIDGET (tile), GTK_TYPE_WINDOW); g_assert (window != NULL); entry = bz_entry_group_find_entry (tile->group, NULL, window, &local_error); if (entry == NULL) goto err; g_signal_emit_by_name (page, "remove", entry); return NULL; err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return NULL; } static void remove_cb (BzInstalledTile *self, GtkButton *button) { dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) remove_fiber, g_object_ref (self), g_object_unref)); } static void bz_installed_tile_class_init (BzInstalledTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_installed_tile_dispose; object_class->get_property = bz_installed_tile_get_property; object_class->set_property = bz_installed_tile_set_property; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LIST_TILE); g_type_ensure (BZ_TYPE_ENTRY_GROUP); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-installed-tile.ui"); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, icon_picture); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, fallback_icon); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, title_label); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, support_button); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, addons_button); gtk_widget_class_bind_template_child (widget_class, BzInstalledTile, remove_button); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, format_description); gtk_widget_class_bind_template_callback (widget_class, support_cb); gtk_widget_class_bind_template_callback (widget_class, install_addons_cb); gtk_widget_class_bind_template_callback (widget_class, remove_cb); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_installed_tile_init (BzInstalledTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_installed_tile_new (void) { return g_object_new (BZ_TYPE_INSTALLED_TILE, NULL); } void bz_installed_tile_set_group (BzInstalledTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_INSTALLED_TILE (self)); g_return_if_fail (group == NULL || BZ_IS_ENTRY_GROUP (group)); g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } BzEntryGroup * bz_installed_tile_get_group (BzInstalledTile *self) { g_return_val_if_fail (BZ_IS_INSTALLED_TILE (self), NULL); return self->group; } static gboolean test_is_support (BzEntry *entry) { return bz_entry_get_donation_url (entry) != NULL; } static gboolean test_has_addons (BzEntry *entry) { GListModel *model = NULL; model = bz_entry_get_addons (entry); return model != NULL && g_list_model_get_n_items (model) > 0; } kolunmi-bazaar-7b9c8e1/src/bz-installed-tile.h000066400000000000000000000023731514314607700213520ustar00rootroot00000000000000/* bz-installed-tile.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include "bz-list-tile.h" #include G_BEGIN_DECLS #define BZ_TYPE_INSTALLED_TILE (bz_installed_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzInstalledTile, bz_installed_tile, BZ, INSTALLED_TILE, BzListTile) GtkWidget * bz_installed_tile_new (void); void bz_installed_tile_set_group (BzInstalledTile *self, BzEntryGroup *group); BzEntryGroup * bz_installed_tile_get_group (BzInstalledTile *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-io.c000066400000000000000000000273331514314607700170450ustar00rootroot00000000000000/* bz-io.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-io.h" #include "bz-env.h" static DexFuture * reap_file_fiber (GFile *file); static DexFuture * reap_path_fiber (char *path); static DexFuture * get_directory_size_fiber (GFile *file); static DexFuture * get_user_data_size_fiber (char *app_id); static DexFuture * get_all_user_data_ids_fiber (void); DexScheduler * bz_get_io_scheduler (void) { static DexScheduler *scheduler = NULL; if (g_once_init_enter_pointer (&scheduler)) g_once_init_leave_pointer (&scheduler, dex_thread_pool_scheduler_new ()); return scheduler; } void bz_reap_file (GFile *file) { g_autoptr (GError) local_error = NULL; g_autofree gchar *uri = NULL; g_autoptr (GFileEnumerator) enumerator = NULL; gboolean result = FALSE; g_return_if_fail (G_IS_FILE (file)); uri = g_file_get_uri (file); if (uri == NULL) uri = g_file_get_path (file); enumerator = g_file_enumerate_children ( file, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); if (enumerator == NULL) { if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_warning ("failed to reap cache directory '%s': %s", uri, local_error->message); g_clear_pointer (&local_error, g_error_free); return; } for (;;) { g_autoptr (GFileInfo) info = NULL; g_autoptr (GFile) child = NULL; GFileType file_type = G_FILE_TYPE_UNKNOWN; info = g_file_enumerator_next_file (enumerator, NULL, &local_error); if (info == NULL) { if (local_error != NULL) g_warning ("failed to enumerate cache directory '%s': %s", uri, local_error->message); g_clear_pointer (&local_error, g_error_free); break; } child = g_file_enumerator_get_child (enumerator, info); file_type = g_file_info_get_file_type (info); if (!g_file_info_get_is_symlink (info) && file_type == G_FILE_TYPE_DIRECTORY) bz_reap_file (child); else { result = g_file_delete (child, NULL, &local_error); if (!result) { g_warning ("failed to reap cache directory '%s': %s", uri, local_error->message); g_clear_pointer (&local_error, g_error_free); } } } result = g_file_enumerator_close (enumerator, NULL, &local_error); if (!result) { g_warning ("failed to reap cache directory '%s': %s", uri, local_error->message); g_clear_pointer (&local_error, g_error_free); } result = g_file_delete (file, NULL, &local_error); if (!result) { g_warning ("failed to reap cache directory '%s': %s", uri, local_error->message); g_clear_pointer (&local_error, g_error_free); } } static void trash_file_callback (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr (DexPromise) promise = user_data; g_autoptr (GError) error = NULL; if (g_file_trash_finish (G_FILE (object), result, &error)) dex_promise_resolve_boolean (promise, TRUE); else dex_promise_reject (promise, g_steal_pointer (&error)); } static DexFuture * trash_file_dex (GFile *file) { DexPromise *promise = dex_promise_new_cancellable (); g_file_trash_async (file, G_PRIORITY_DEFAULT, dex_promise_get_cancellable (promise), trash_file_callback, dex_ref (promise)); return DEX_FUTURE (promise); } static DexFuture * reap_user_data_fiber (char *app_id) { g_autofree char *user_data_path = NULL; g_autoptr (GFile) file = NULL; g_autoptr (DexFuture) trash_future = NULL; g_autoptr (GError) error = NULL; gboolean result = FALSE; user_data_path = g_build_filename (g_get_home_dir (), ".var", "app", app_id, NULL); file = g_file_new_for_path (user_data_path); trash_future = trash_file_dex (file); result = dex_await_boolean (dex_ref (trash_future), &error); if (!result) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_warning ("failed to trash user data '%s': %s", user_data_path, error->message); } return dex_future_new_true (); } DexFuture * bz_reap_user_data_dex (const char *app_id) { dex_return_error_if_fail (app_id != NULL); return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) reap_user_data_fiber, g_strdup (app_id), g_free); } void bz_reap_path (const char *path) { g_autoptr (GFile) file = NULL; g_return_if_fail (path != NULL); file = g_file_new_for_path (path); bz_reap_file (file); } DexFuture * bz_reap_file_dex (GFile *file) { dex_return_error_if_fail (G_IS_FILE (file)); return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) reap_file_fiber, g_object_ref (file), g_object_unref); } DexFuture * bz_reap_path_dex (const char *path) { dex_return_error_if_fail (path != NULL); return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) reap_path_fiber, g_strdup (path), g_free); } DexFuture * bz_get_user_data_size_dex (const char *app_id) { dex_return_error_if_fail (app_id != NULL); return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) get_user_data_size_fiber, g_strdup (app_id), g_free); } DexFuture * bz_get_user_data_ids_dex (void) { return dex_scheduler_spawn ( bz_get_io_scheduler (), bz_get_dex_stack_size (), (DexFiberFunc) get_all_user_data_ids_fiber, NULL, NULL); } static DexFuture * get_user_data_size_fiber (char *app_id) { g_autofree char *user_data_path = NULL; g_autoptr (GFile) file = NULL; user_data_path = g_build_filename (g_get_home_dir (), ".var", "app", app_id, NULL); file = g_file_new_for_path (user_data_path); return get_directory_size_fiber (file); } static DexFuture * get_directory_size_fiber (GFile *file) { g_autoptr (DexFuture) enumerator_future = NULL; g_autoptr (GFileEnumerator) enumerator = NULL; g_autoptr (GError) error = NULL; guint64 total_size = 0; enumerator_future = dex_file_enumerate_children ( file, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_PRIORITY_DEFAULT); enumerator = dex_await_object (dex_ref (enumerator_future), &error); if (enumerator == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) return dex_future_new_for_uint64 (0); return dex_future_new_for_error (g_steal_pointer (&error)); } for (;;) { g_autoptr (DexFuture) next_future = NULL; g_autolist (GFileInfo) infos = NULL; next_future = dex_file_enumerator_next_files (enumerator, 10, G_PRIORITY_DEFAULT); infos = dex_await_boxed (dex_ref (next_future), &error); if (infos == NULL) { if (error != NULL) return dex_future_new_for_error (g_steal_pointer (&error)); break; } for (GList *l = infos; l != NULL; l = l->next) { GFileInfo *info = l->data; GFileType file_type = g_file_info_get_file_type (info); if (file_type == G_FILE_TYPE_DIRECTORY) { g_autoptr (GFile) child = g_file_enumerator_get_child (enumerator, info); g_autoptr (DexFuture) size_future = get_directory_size_fiber (child); guint64 child_size = dex_await_uint64 (dex_ref (size_future), &error); if (error != NULL) return dex_future_new_for_error (g_steal_pointer (&error)); total_size += child_size; } else { total_size += g_file_info_get_size (info); } } } return dex_future_new_for_uint64 (total_size); } static DexFuture * get_all_user_data_ids_fiber (void) { g_autofree char *var_app_path = NULL; g_autoptr (GFile) var_app_dir = NULL; g_autoptr (DexFuture) enumerator_future = NULL; g_autoptr (GFileEnumerator) enumerator = NULL; g_autoptr (GError) error = NULL; GHashTable *ids = NULL; var_app_path = g_build_filename (g_get_home_dir (), ".var", "app", NULL); var_app_dir = g_file_new_for_path (var_app_path); ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); enumerator_future = dex_file_enumerate_children ( var_app_dir, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_PRIORITY_DEFAULT); enumerator = dex_await_object (dex_ref (enumerator_future), &error); if (enumerator == NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) return dex_future_new_take_boxed (G_TYPE_HASH_TABLE, ids); g_hash_table_unref (ids); return dex_future_new_for_error (g_steal_pointer (&error)); } for (;;) { g_autoptr (DexFuture) next_future = NULL; g_autolist (GFileInfo) infos = NULL; next_future = dex_file_enumerator_next_files (enumerator, 10, G_PRIORITY_DEFAULT); infos = dex_await_boxed (dex_ref (next_future), &error); if (infos == NULL) { if (error != NULL) { g_hash_table_unref (ids); return dex_future_new_for_error (g_steal_pointer (&error)); } break; } for (GList *l = infos; l != NULL; l = l->next) { GFileInfo *info = l->data; GFileType file_type = g_file_info_get_file_type (info); if (file_type == G_FILE_TYPE_DIRECTORY) { const char *app_id = g_file_info_get_name (info); g_hash_table_insert (ids, g_strdup (app_id), NULL); } } } return dex_future_new_take_boxed (G_TYPE_HASH_TABLE, ids); } char * bz_dup_root_cache_dir (void) { const char *user_cache = NULL; const char *id = NULL; user_cache = g_get_user_cache_dir (); id = g_application_get_application_id (g_application_get_default ()); if (id == NULL) id = "Bazaar"; return g_build_filename (user_cache, id, NULL); } char * bz_dup_cache_dir (const char *submodule) { g_autofree char *root_cache_dir = NULL; g_return_val_if_fail (submodule != NULL, NULL); root_cache_dir = bz_dup_root_cache_dir (); return g_build_filename (root_cache_dir, submodule, NULL); } static DexFuture * reap_file_fiber (GFile *file) { bz_reap_file (file); return dex_future_new_true (); } static DexFuture * reap_path_fiber (char *path) { bz_reap_path (path); return dex_future_new_true (); } kolunmi-bazaar-7b9c8e1/src/bz-io.h000066400000000000000000000046041514314607700170460ustar00rootroot00000000000000/* bz-io.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS DexScheduler * bz_get_io_scheduler (void); void bz_reap_file (GFile *file); void bz_reap_path (const char *path); DexFuture * bz_reap_file_dex (GFile *file); DexFuture * bz_reap_path_dex (const char *path); DexFuture * bz_reap_user_data_dex (const char *app_id); DexFuture * bz_get_user_data_size_dex (const char *app_id); DexFuture * bz_get_user_data_ids_dex (void); char * bz_dup_root_cache_dir (void); char * bz_dup_cache_dir (const char *submodule); #define bz_dup_module_dir() bz_dup_cache_dir (BAZAAR_MODULE) #define bz_discard_path(_path) \ G_STMT_START \ { \ if (g_file_test ((_path), G_FILE_TEST_IS_DIR)) \ bz_reap_path ((_path)); \ else if (g_file_test ((_path), G_FILE_TEST_EXISTS)) \ { \ g_autoptr (GFile) file = NULL; \ \ file = g_file_new_for_path ((_path)); \ g_file_delete (file, NULL, NULL); \ } \ } \ G_STMT_END #define bz_discard_module_dir() \ G_STMT_START \ { \ g_autofree char *_path = NULL; \ \ _path = bz_dup_module_dir (); \ bz_discard_path (_path); \ } \ G_STMT_END G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-lazy-async-texture-model.c000066400000000000000000000142361514314607700233220ustar00rootroot00000000000000/* bz-lazy-async-texture-model.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-lazy-async-texture-model.h" #include "bz-async-texture.h" struct _BzLazyAsyncTextureModel { GObject parent_instance; GListModel *model; }; static void list_model_iface_init (GListModelInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzLazyAsyncTextureModel, bz_lazy_async_texture_model, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init)); enum { PROP_0, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void items_changed (BzLazyAsyncTextureModel *self, guint position, guint removed, guint added, GListModel *model); static void bz_lazy_async_texture_model_dispose (GObject *object) { BzLazyAsyncTextureModel *self = BZ_LAZY_ASYNC_TEXTURE_MODEL (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_pointer (&self->model, g_object_unref); G_OBJECT_CLASS (bz_lazy_async_texture_model_parent_class)->dispose (object); } static void bz_lazy_async_texture_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzLazyAsyncTextureModel *self = BZ_LAZY_ASYNC_TEXTURE_MODEL (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_lazy_async_texture_model_get_model (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_lazy_async_texture_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzLazyAsyncTextureModel *self = BZ_LAZY_ASYNC_TEXTURE_MODEL (object); switch (prop_id) { case PROP_MODEL: bz_lazy_async_texture_model_set_model (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_lazy_async_texture_model_class_init (BzLazyAsyncTextureModelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_lazy_async_texture_model_set_property; object_class->get_property = bz_lazy_async_texture_model_get_property; object_class->dispose = bz_lazy_async_texture_model_dispose; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static GType list_model_get_item_type (GListModel *list) { return BZ_TYPE_ASYNC_TEXTURE; } static guint list_model_get_n_items (GListModel *list) { BzLazyAsyncTextureModel *self = BZ_LAZY_ASYNC_TEXTURE_MODEL (list); guint ret = 0; if (self->model != NULL) ret = g_list_model_get_n_items (self->model); return ret; } static gpointer list_model_get_item (GListModel *list, guint position) { BzLazyAsyncTextureModel *self = BZ_LAZY_ASYNC_TEXTURE_MODEL (list); g_autoptr (BzAsyncTexture) ret = NULL; if (self->model != NULL) { ret = g_list_model_get_item (self->model, position); bz_async_texture_ensure (ret); } return g_steal_pointer (&ret); } static void list_model_iface_init (GListModelInterface *iface) { iface->get_item_type = list_model_get_item_type; iface->get_n_items = list_model_get_n_items; iface->get_item = list_model_get_item; } static void bz_lazy_async_texture_model_init (BzLazyAsyncTextureModel *self) { } BzLazyAsyncTextureModel * bz_lazy_async_texture_model_new (void) { return g_object_new (BZ_TYPE_LAZY_ASYNC_TEXTURE_MODEL, NULL); } GListModel * bz_lazy_async_texture_model_get_model (BzLazyAsyncTextureModel *self) { g_return_val_if_fail (BZ_IS_LAZY_ASYNC_TEXTURE_MODEL (self), NULL); return self->model; } void bz_lazy_async_texture_model_set_model (BzLazyAsyncTextureModel *self, GListModel *model) { guint had_n_items = 0; guint have_n_items = 0; g_return_if_fail (BZ_IS_LAZY_ASYNC_TEXTURE_MODEL (self)); if (model == self->model) return; if (self->model != NULL) { had_n_items = g_list_model_get_n_items (self->model); g_signal_handlers_disconnect_by_func (self->model, items_changed, self); } g_clear_pointer (&self->model, g_object_unref); if (model != NULL) { self->model = g_object_ref (model); have_n_items = g_list_model_get_n_items (model); g_signal_connect_swapped (model, "items-changed", G_CALLBACK (items_changed), self); } g_list_model_items_changed (G_LIST_MODEL (self), 0, had_n_items, have_n_items); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } static void items_changed (BzLazyAsyncTextureModel *self, guint position, guint removed, guint added, GListModel *model) { g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added); } /* End of bz-lazy-async-texture-model.c */ kolunmi-bazaar-7b9c8e1/src/bz-lazy-async-texture-model.h000066400000000000000000000025411514314607700233230ustar00rootroot00000000000000/* bz-lazy-async-texture-model.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_LAZY_ASYNC_TEXTURE_MODEL (bz_lazy_async_texture_model_get_type ()) G_DECLARE_FINAL_TYPE (BzLazyAsyncTextureModel, bz_lazy_async_texture_model, BZ, LAZY_ASYNC_TEXTURE_MODEL, GObject) BzLazyAsyncTextureModel * bz_lazy_async_texture_model_new (void); GListModel * bz_lazy_async_texture_model_get_model (BzLazyAsyncTextureModel *self); void bz_lazy_async_texture_model_set_model (BzLazyAsyncTextureModel *self, GListModel *model); G_END_DECLS /* End of bz-lazy-async-texture-model.h */ kolunmi-bazaar-7b9c8e1/src/bz-library-page.blp000066400000000000000000000213051514314607700213400ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzLibraryPage: Adw.Bin { child: Box { orientation: vertical; Adw.Clamp search_box_clamp { margin-start: 12; margin-end: 12; maximum-size: 375; child: Adw.Bin { halign: fill; margin-top: 10; margin-bottom: 10; child: Box { orientation: horizontal; spacing: 8; height-request: 40; Image { icon-name: "system-search-symbolic"; } Text search_bar { hexpand: true; placeholder-text: _("Search installed apps"); notify::text => $search_text_changed(template); } Button clear_button { icon-name: "edit-clear-symbolic"; visible: bind $not($is_empty_string(search_bar.text) as ) as ; styles [ "flat", "circular", "clear-button", ] clicked => $reset_search_cb(template); } styles [ "search-box", ] }; }; } Adw.ViewStack stack { enable-transitions: true; transition-duration: 400; Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "library-symbolic"; title: _("No Apps Found"); description: ""; }; } Adw.ViewStackPage { name: "no-results"; title: _("No Results"); child: Adw.StatusPage { icon-name: "library-symbolic"; title: _("No Results"); description: bind $no_results_found_subtitle(search_bar.text) as ; }; } Adw.ViewStackPage { name: "content"; // Translators: . title: _("Library"); child: ScrolledWindow scroll{ hscrollbar-policy: never; child: Adw.Clamp { vexpand: true; maximum-size: 650; child: Box margin_box { orientation: vertical; margin-start: 9; margin-end: 9; Box non_search_content { orientation: vertical; visible: bind $is_empty_string(search_bar.text) as ; Revealer { reveal-child: bind $invert_boolean($is_empty(template.state as <$BzStateInfo>.available-updates) as ) as ; transition-type: slide_down; child: Box { orientation: vertical; spacing: 8; margin-top: 15; Label { label: _("Pending Updates"); xalign: 0; margin-start: 12; margin-top: 15; styles [ "heading", "h4", ] } $BzUpdatesCard { state: bind template.state; update => $updates_card_update_cb(template); } }; } Revealer { reveal-child: bind $invert_boolean($is_zero(template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.install-trackers as .n-items) as ) as ; transition-type: slide_down; child: Box { margin-top: 15; orientation: vertical; Label install_label { label: _("Downloads"); xalign: 0; margin-start: 12; styles [ "heading", "h4", ] } ListView install_list_view { styles [ "navigation-sidebar", "installed-list-view", ] model: NoSelection { model: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.install-trackers; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: $BzTransactionTile { tracker: bind template.item; activated => $tile_activated_cb(); }; } }; } }; } Revealer { reveal-child: bind $invert_boolean($is_zero(template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.removal-trackers as .n-items) as ) as ; transition-type: slide_down; child: Box { margin-top: 15; orientation: vertical; Label removal_label { label: _("Recently Uninstalled"); xalign: 0; margin-start: 12; styles [ "heading", "h4", ] } ListView removal_list_view { styles [ "navigation-sidebar", "installed-list-view", ] model: NoSelection { model: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.removal-trackers; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: $BzTransactionTile { tracker: bind template.item; activated => $tile_activated_cb(); }; } }; } }; } Revealer { reveal-child: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.has-transactions; margin-bottom: 15; transition-type: slide_down; child: ListBox { margin-bottom: 16; margin-top: 4; margin-start: 4; margin-end: 4; selection-mode: none; styles [ "boxed-list", ] Adw.ButtonRow { title: _("Clear Finished Tasks"); activated => $clear_tasks_cb(template); styles [ "error", ] } }; } Label { label: _("Installed Apps"); xalign: 0; margin-start: 12; visible: bind $logical_or($logical_or($invert_boolean($is_zero(template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.removal-trackers as .n-items) as ) as , $invert_boolean($is_zero(template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.install-trackers as .n-items) as ) as ) as , $invert_boolean($is_null(template.state as <$BzStateInfo>.available-updates) as ) as ) as ; styles [ "heading", "h4", ] } } ListView list_view { styles [ "navigation-sidebar", "installed-list-view", ] model: NoSelection { model: FilterListModel { filter: CustomFilter filter {}; model: bind template.model; }; }; factory: BuilderListItemFactory { template ListItem { activatable: false; selectable: false; focusable: false; child: $BzInstalledTile { group: bind template.item as <$BzEntryGroup>; activated => $tile_activated_cb(); }; } }; } }; }; }; } } }; } kolunmi-bazaar-7b9c8e1/src/bz-library-page.c000066400000000000000000000357561514314607700210240ustar00rootroot00000000000000/* bz-library-page.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-entry-group-util.h" #include "bz-env.h" #include "bz-error.h" #include "bz-installed-tile.h" #include "bz-library-page.h" #include "bz-section-view.h" #include "bz-template-callbacks.h" #include "bz-transaction-tile.h" #include "bz-updates-card.h" #include "bz-util.h" struct _BzLibraryPage { AdwBin parent_instance; GListModel *model; BzStateInfo *state; /* Template widgets */ AdwViewStack *stack; GtkText *search_bar; GtkScrolledWindow *scroll; GtkCustomFilter *filter; GtkListView *list_view; }; G_DEFINE_FINAL_TYPE (BzLibraryPage, bz_library_page, ADW_TYPE_BIN) enum { PROP_0, PROP_MODEL, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_REMOVE, SIGNAL_REMOVE_ADDON, SIGNAL_INSTALL_ADDON, SIGNAL_SHOW, SIGNAL_UPDATE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void items_changed (BzLibraryPage *self, guint position, guint removed, guint added, GListModel *model); static void set_page (BzLibraryPage *self); static gboolean set_page_idle_cb (BzLibraryPage *self); static gboolean filter (BzEntryGroup *group, BzLibraryPage *self); static void bz_library_page_dispose (GObject *object) { BzLibraryPage *self = BZ_LIBRARY_PAGE (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); g_clear_object (&self->state); G_OBJECT_CLASS (bz_library_page_parent_class)->dispose (object); } static void bz_library_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzLibraryPage *self = BZ_LIBRARY_PAGE (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_library_page_get_model (self)); break; case PROP_STATE: g_value_set_object (value, bz_library_page_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_library_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzLibraryPage *self = BZ_LIBRARY_PAGE (object); switch (prop_id) { case PROP_MODEL: bz_library_page_set_model (self, g_value_get_object (value)); break; case PROP_STATE: bz_library_page_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * no_results_found_subtitle (gpointer object, const char *search_text) { if (search_text == NULL || *search_text == '\0') return g_strdup (""); return g_strdup_printf (_ ("No matches found for \"%s\" in the list of installed apps"), search_text); } static char * format_update_count (gpointer object, GListModel *updates) { guint n_updates = 0; if (updates == NULL) return g_strdup (""); n_updates = g_list_model_get_n_items (updates); return g_strdup_printf (ngettext ("%u Available Update", "%u Available Updates", n_updates), n_updates); } static DexFuture * row_activated_fiber (GWeakRef *wr) { g_autoptr (GError) local_error = NULL; g_autoptr (BzListTile) tile = NULL; BzLibraryPage *self = NULL; GtkWidget *window = NULL; BzEntryGroup *group = NULL; g_autoptr (BzEntry) entry = NULL; bz_weak_get_or_return_reject (tile, wr); self = (BzLibraryPage *) gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_LIBRARY_PAGE); if (self == NULL) return NULL; if (self->model == NULL) goto err; window = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_WINDOW); if (window == NULL) goto err; if (BZ_IS_INSTALLED_TILE (tile)) { group = bz_installed_tile_get_group (BZ_INSTALLED_TILE (tile)); if (group == NULL) goto err; entry = bz_entry_group_find_entry (group, NULL, window, &local_error); if (entry == NULL) goto err; } else if (BZ_IS_TRANSACTION_TILE (tile)) { BzTransactionEntryTracker *tracker = NULL; tracker = bz_transaction_tile_get_tracker (BZ_TRANSACTION_TILE (tile)); if (tracker == NULL) goto err; entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL) goto err; entry = g_object_ref (entry); } else goto err; g_signal_emit (self, signals[SIGNAL_SHOW], 0, entry); return dex_future_new_true (); err: if (local_error != NULL) bz_show_error_for_widget (window, local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } static void tile_activated_cb (BzListTile *tile) { g_assert (BZ_IS_LIST_TILE (tile)); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) row_activated_fiber, bz_track_weak (tile), bz_weak_release)); } static void search_text_changed (BzLibraryPage *self, GParamSpec *pspec, GtkEntry *entry) { gtk_filter_changed (GTK_FILTER (self->filter), GTK_FILTER_CHANGE_DIFFERENT); set_page (self); } static void reset_search_cb (BzLibraryPage *self, GtkButton *button) { gtk_text_set_buffer (self->search_bar, NULL); } static void clear_tasks_cb (BzLibraryPage *self) { BzTransactionManager *manager = NULL; manager = bz_state_info_get_transaction_manager (self->state); bz_transaction_manager_clear_finished (manager); } static void updates_card_update_cb (BzLibraryPage *self, GListModel *entries, BzUpdatesCard *card) { g_signal_emit (self, signals[SIGNAL_UPDATE], 0, entries); } static void bz_library_page_class_init (BzLibraryPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_library_page_dispose; object_class->get_property = bz_library_page_get_property; object_class->set_property = bz_library_page_set_property; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_REMOVE] = g_signal_new ( "remove", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_REMOVE], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_INSTALL_ADDON] = g_signal_new ( "install-addon", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_INSTALL_ADDON], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_REMOVE_ADDON] = g_signal_new ( "remove-addon", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_REMOVE_ADDON], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_SHOW] = g_signal_new ( "show-entry", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY); g_signal_set_va_marshaller ( signals[SIGNAL_SHOW], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); signals[SIGNAL_UPDATE] = g_signal_new ( "update", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_LIST_MODEL); g_signal_set_va_marshaller ( signals[SIGNAL_UPDATE], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); g_type_ensure (BZ_TYPE_SECTION_VIEW); g_type_ensure (BZ_TYPE_ENTRY_GROUP); g_type_ensure (BZ_TYPE_INSTALLED_TILE); g_type_ensure (BZ_TYPE_TRANSACTION_TILE); g_type_ensure (BZ_TYPE_UPDATES_CARD); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-library-page.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, stack); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, search_bar); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, scroll); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, filter); gtk_widget_class_bind_template_child (widget_class, BzLibraryPage, list_view); gtk_widget_class_bind_template_callback (widget_class, no_results_found_subtitle); gtk_widget_class_bind_template_callback (widget_class, format_update_count); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); gtk_widget_class_bind_template_callback (widget_class, reset_search_cb); gtk_widget_class_bind_template_callback (widget_class, search_text_changed); gtk_widget_class_bind_template_callback (widget_class, clear_tasks_cb); gtk_widget_class_bind_template_callback (widget_class, updates_card_update_cb); } static void bz_library_page_init (BzLibraryPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); gtk_custom_filter_set_filter_func ( self->filter, (GtkCustomFilterFunc) filter, self, NULL); } GtkWidget * bz_library_page_new (void) { return g_object_new (BZ_TYPE_LIBRARY_PAGE, NULL); } void bz_library_page_set_model (BzLibraryPage *self, GListModel *model) { g_return_if_fail (BZ_IS_LIBRARY_PAGE (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); if (model != NULL) { self->model = g_object_ref (model); g_signal_connect_swapped (model, "items-changed", G_CALLBACK (items_changed), self); } g_idle_add_full ( G_PRIORITY_DEFAULT, (GSourceFunc) set_page_idle_cb, g_object_ref (self), g_object_unref); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } GListModel * bz_library_page_get_model (BzLibraryPage *self) { g_return_val_if_fail (BZ_IS_LIBRARY_PAGE (self), NULL); return self->model; } void bz_library_page_set_state (BzLibraryPage *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_LIBRARY_PAGE (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); g_clear_object (&self->state); if (state != NULL) self->state = g_object_ref (state); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } BzStateInfo * bz_library_page_get_state (BzLibraryPage *self) { g_return_val_if_fail (BZ_IS_LIBRARY_PAGE (self), NULL); return self->state; } gboolean bz_library_page_ensure_active (BzLibraryPage *self, const char *initial) { const char *text = NULL; g_return_val_if_fail (BZ_IS_LIBRARY_PAGE (self), FALSE); text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (text != NULL && *text != '\0' && gtk_widget_has_focus (GTK_WIDGET (self->search_bar))) return FALSE; gtk_widget_grab_focus (GTK_WIDGET (self->search_bar)); gtk_editable_set_text (GTK_EDITABLE (self->search_bar), initial); if (initial != NULL) gtk_editable_set_position (GTK_EDITABLE (self->search_bar), g_utf8_strlen (initial, -1)); return TRUE; } void bz_library_page_reset_search (BzLibraryPage *self) { GtkAdjustment *vadjustment = NULL; g_return_if_fail (BZ_IS_LIBRARY_PAGE (self)); vadjustment = gtk_scrolled_window_get_vadjustment (self->scroll); gtk_adjustment_set_value (vadjustment, 0.0); gtk_text_set_buffer (self->search_bar, NULL); } static void items_changed (BzLibraryPage *self, guint position, guint removed, guint added, GListModel *model) { set_page (self); } static void set_page (BzLibraryPage *self) { GtkSelectionModel *selection_model; GListModel *filter_model; if (self->model == NULL || g_list_model_get_n_items (self->model) == 0) { adw_view_stack_set_visible_child_name (self->stack, "empty"); return; } selection_model = gtk_list_view_get_model (self->list_view); filter_model = gtk_no_selection_get_model (GTK_NO_SELECTION (selection_model)); if (g_list_model_get_n_items (filter_model) == 0) adw_view_stack_set_visible_child_name (self->stack, "no-results"); else adw_view_stack_set_visible_child_name (self->stack, "content"); } static gboolean set_page_idle_cb (BzLibraryPage *self) { set_page (self); return G_SOURCE_REMOVE; } static gboolean filter (BzEntryGroup *group, BzLibraryPage *self) { const char *id = NULL; const char *title = NULL; const char *text = NULL; id = bz_entry_group_get_id (group); title = bz_entry_group_get_title (group); text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (text != NULL && *text != '\0') return strcasestr (id, text) != NULL || strcasestr (title, text) != NULL; else return TRUE; } kolunmi-bazaar-7b9c8e1/src/bz-library-page.h000066400000000000000000000030061514314607700210100ustar00rootroot00000000000000/* bz-library-page.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_LIBRARY_PAGE (bz_library_page_get_type ()) G_DECLARE_FINAL_TYPE (BzLibraryPage, bz_library_page, BZ, LIBRARY_PAGE, AdwBin) GtkWidget * bz_library_page_new (void); void bz_library_page_set_model (BzLibraryPage *self, GListModel *model); GListModel * bz_library_page_get_model (BzLibraryPage *self); void bz_library_page_set_state (BzLibraryPage *self, BzStateInfo *state); BzStateInfo * bz_library_page_get_state (BzLibraryPage *self); gboolean bz_library_page_ensure_active (BzLibraryPage *self, const char *initial); void bz_library_page_reset_search (BzLibraryPage *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-license-dialog.blp000066400000000000000000000050741514314607700216460ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzLicenseDialog: Adw.Dialog { content-width: 400; child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: Adw.Clamp { maximum-size: 600; child: Box { orientation: vertical; margin-top: 6; margin-bottom: 18; margin-start: 18; margin-end: 18; Box { orientation: vertical; margin-bottom: 24; valign: center; vexpand: true; $BzLozenge { visible: bind template.entry as <$BzEntry>.is-floss as ; title: bind $get_label_cb(template.entry as <$BzEntry>) as ; icon-names: [ "heart-outline-thick-symbolic", "community-symbolic", "thumbs-up-outline-symbolic", ]; importance: unimportant; } $BzLozenge { visible: bind $invert_boolean(template.entry as <$BzEntry>.is-floss as ) as ; title: bind $get_label_cb(template.entry as <$BzEntry>) as ; icon-names: [ "hand-openyay-symbolic", "proprietary-code-symbolic", "license-symbolic", ]; importance: information; } } Box { orientation: vertical; spacing: 12; ListBox { selection-mode: none; styles [ "boxed-list", ] ListBoxRow { vexpand: true; activatable: false; Label { label: bind $get_license_info(template.entry as <$BzEntry>) as ; valign: start; margin-top: 12; margin-bottom: 12; margin-start: 12; margin-end: 12; use-markup: true; xalign: 0; wrap: true; wrap-mode: word_char; } } } ListBox { visible: bind template.entry as <$BzEntry>.is-floss as ; selection-mode: none; styles [ "boxed-list", ] Adw.ButtonRow show_all_button { title: _("Get Involved"); end-icon-name: "external-link-symbolic"; activated => $contribute_cb(template); has-tooltip: true; tooltip-text: bind $get_involved_tooltip(template.entry) as ; } } } }; }; }; } kolunmi-bazaar-7b9c8e1/src/bz-license-dialog.c000066400000000000000000000173741514314607700213210ustar00rootroot00000000000000/* bz-license-dialog.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-entry.h" #include "bz-license-dialog.h" #include "bz-lozenge.h" #include "bz-spdx.h" #include "bz-url.h" struct _BzLicenseDialog { AdwDialog parent_instance; BzEntry *entry; }; G_DEFINE_FINAL_TYPE (BzLicenseDialog, bz_license_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL }; static void bz_license_dialog_dispose (GObject *object) { BzLicenseDialog *self = NULL; self = BZ_LICENSE_DIALOG (object); g_clear_object (&self->entry); G_OBJECT_CLASS (bz_license_dialog_parent_class)->dispose (object); } static void bz_license_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzLicenseDialog *self = NULL; self = BZ_LICENSE_DIALOG (object); switch (prop_id) { case PROP_ENTRY: g_value_set_object (value, self->entry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_license_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzLicenseDialog *self = NULL; self = BZ_LICENSE_DIALOG (object); switch (prop_id) { case PROP_ENTRY: g_clear_object (&self->entry); self->entry = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static char * get_label_cb (gpointer object, BzEntry *entry) { g_autofree char *license = NULL; gboolean is_floss = FALSE; if (entry == NULL) return g_strdup (""); g_object_get ( entry, "is-floss", &is_floss, "project-license", &license, NULL); if (license == NULL || *license == '\0') return g_strdup (_ ("Unknown License")); if (is_floss) return g_strdup (_ ("Community Built")); if (bz_spdx_is_proprietary (license)) return g_strdup (_ ("Proprietary")); return g_strdup (_ ("Special License")); } static char * get_involved_tooltip (gpointer object, BzEntry *entry) { g_autoptr (GListModel) share_urls = NULL; g_autoptr (BzUrl) first_url = NULL; const char *url = NULL; if (entry == NULL) return NULL; g_object_get (entry, "share-urls", &share_urls, NULL); if (share_urls == NULL || g_list_model_get_n_items (share_urls) < 1) return NULL; first_url = g_list_model_get_item (share_urls, 1); url = bz_url_get_url (first_url); if (url != NULL && *url != '\0') return g_strdup (url); return NULL; } static char * format_license_link (const char *license) { g_autofree char *license_name = NULL; g_autofree char *license_url = NULL; if (!bz_spdx_is_valid (license)) return g_strdup (license); license_name = bz_spdx_get_name (license); if (license_name == NULL || *license_name == '\0') { g_clear_pointer (&license_name, g_free); license_name = g_strdup (license); } license_url = bz_spdx_get_url (license); return g_strdup_printf ("%s", license_url, license_name); } static char * get_license_info (gpointer object, BzEntry *entry) { g_autofree char *license = NULL; gboolean is_floss = FALSE; g_autofree char *link = NULL; if (entry == NULL) return g_strdup (""); g_object_get ( entry, "is-floss", &is_floss, "project-license", &license, NULL); if (license == NULL || *license == '\0') { if (is_floss) return g_strdup (_ ("This app is developed in the open by an international community.\n\n" "You can participate and help make it even better.")); else return g_strdup (_ ("The license of this app is not known")); } if (is_floss) { link = format_license_link (license); return g_strdup_printf (_ ("This app is developed in the open by an international community, " "and released under the %s license.\n\n" "You can participate and help make it even better."), link); } if (bz_spdx_is_proprietary (license)) { return g_strdup (_ ("This app is not developed in the open, so only its developers know how it works. " "It may be insecure in ways that are hard to detect, and it may change without oversight.\n\n" "You may or may not be able to contribute to this app.")); } link = format_license_link (license); return g_strdup_printf (_ ("This app is developed under the special license %s.\n\n" "You may or may not be able to contribute to this app."), link); } static void contribute_cb (BzLicenseDialog *self) { g_autoptr (GListModel) share_urls = NULL; g_autoptr (BzUrl) first_url = NULL; const char *url = NULL; g_object_get (self->entry, "share-urls", &share_urls, NULL); if (share_urls == NULL || g_list_model_get_n_items (share_urls) < 1) return; first_url = g_list_model_get_item (share_urls, 1); url = bz_url_get_url (first_url); if (url != NULL && *url != '\0') g_app_info_launch_default_for_uri (url, NULL, NULL); } static void bz_license_dialog_class_init (BzLicenseDialogClass *klass) { GObjectClass *object_class = NULL; GtkWidgetClass *widget_class = NULL; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_license_dialog_dispose; object_class->get_property = bz_license_dialog_get_property; object_class->set_property = bz_license_dialog_set_property; props[PROP_ENTRY] = g_param_spec_object ( "entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LOZENGE); gtk_widget_class_set_template_from_resource ( widget_class, "/io/github/kolunmi/Bazaar/bz-license-dialog.ui"); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, get_label_cb); gtk_widget_class_bind_template_callback (widget_class, get_license_info); gtk_widget_class_bind_template_callback (widget_class, get_involved_tooltip); gtk_widget_class_bind_template_callback (widget_class, contribute_cb); } static void bz_license_dialog_init (BzLicenseDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_license_dialog_new (BzEntry *entry) { return g_object_new (BZ_TYPE_LICENSE_DIALOG, "entry", entry, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-license-dialog.h000066400000000000000000000020401514314607700213060ustar00rootroot00000000000000/* bz-license-dialog.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include G_BEGIN_DECLS #define BZ_TYPE_LICENSE_DIALOG (bz_license_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzLicenseDialog, bz_license_dialog, BZ, LICENSE_DIALOG, AdwDialog) AdwDialog * bz_license_dialog_new (BzEntry *entry); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-list-tile.c000066400000000000000000000150471514314607700203430ustar00rootroot00000000000000/* bz-list-tile.c * * Copyright 2025 Hari Rana * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-list-tile.h" typedef struct { GtkWidget *child; } BzListTilePrivate; G_DEFINE_TYPE_WITH_PRIVATE (BzListTile, bz_list_tile, GTK_TYPE_WIDGET) enum { PROP_0, PROP_CHILD, LAST_PROP }; static GParamSpec *props[LAST_PROP]; enum { ACTIVATED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0, }; static void on_gesture_click_released (BzListTile *self, gint n_press, gdouble x, gdouble y, GtkGestureClick *gesture); static void bz_list_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzListTile *self = BZ_LIST_TILE (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_list_tile_get_child (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_list_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzListTile *self = BZ_LIST_TILE (object); switch (prop_id) { case PROP_CHILD: bz_list_tile_set_child (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_list_tile_dispose (GObject *object) { BzListTile *self = BZ_LIST_TILE (object); BzListTilePrivate *priv = bz_list_tile_get_instance_private (self); g_clear_pointer (&priv->child, gtk_widget_unparent); G_OBJECT_CLASS (bz_list_tile_parent_class)->dispose (object); } static void bz_list_tile_class_init (BzListTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->get_property = bz_list_tile_get_property; object_class->set_property = bz_list_tile_set_property; object_class->dispose = bz_list_tile_dispose; /** * BzListTile:child: * * The child widget. */ props[PROP_CHILD] = g_param_spec_object ("child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); /** * BzListTile::activated: * * This signal is emitted after the tile has been activated. */ signals[ACTIVATED] = g_signal_new ("activated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); { g_autoptr (GtkShortcutAction) activate_action = NULL; const guint activate_keyvals[] = { GDK_KEY_space, GDK_KEY_KP_Space, GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter, }; activate_action = gtk_signal_action_new ("activated"); for (size_t i = 0; i < G_N_ELEMENTS (activate_keyvals); i++) { g_autoptr (GtkShortcut) activate_shortcut = NULL; activate_shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (activate_keyvals[i], 0), g_object_ref (activate_action)); gtk_widget_class_add_shortcut (widget_class, activate_shortcut); } } gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); } static void bz_list_tile_init (BzListTile *self) { GtkGesture *gesture_click; gtk_widget_add_css_class (GTK_WIDGET (self), "card"); gtk_widget_add_css_class (GTK_WIDGET (self), "activatable"); gesture_click = gtk_gesture_click_new (); g_signal_connect_swapped (gesture_click, "released", G_CALLBACK (on_gesture_click_released), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture_click)); gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); gtk_widget_set_receives_default (GTK_WIDGET (self), TRUE); } /** * bz_list_tile_new: * * Create a new #BzListTile. * * Returns: (transfer full): a newly created #BzListTile */ BzListTile * bz_list_tile_new (void) { return g_object_new (BZ_TYPE_LIST_TILE, NULL); } /** * bz_list_tile_get_child: * @self: a #BzListTile * * Get the child associated with @self. * * Returns: (transfer none) (nullable): the child */ GtkWidget * bz_list_tile_get_child (BzListTile *self) { BzListTilePrivate *priv; g_assert (BZ_IS_LIST_TILE (self)); priv = bz_list_tile_get_instance_private (self); return priv->child; } /** * bz_list_tile_set_child: * @self: a #BzListTile * @child: (transfer none): the child * * Set the child to associate with @self. */ void bz_list_tile_set_child (BzListTile *self, GtkWidget *child) { BzListTilePrivate *priv; g_assert (BZ_IS_LIST_TILE (self)); priv = bz_list_tile_get_instance_private (self); /* Since this is not a library, there is no point in safeguarding it */ priv->child = child; gtk_widget_set_parent (child, GTK_WIDGET (self)); } static void on_gesture_click_released (BzListTile *self, gint n_press, gdouble x, gdouble y, GtkGestureClick *gesture) { if (gtk_widget_contains (GTK_WIDGET (self), x, y)) { gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); if (!gtk_widget_grab_focus (GTK_WIDGET (self))) g_assert_not_reached (); g_signal_emit (self, signals[ACTIVATED], 0); } else { gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED); } } kolunmi-bazaar-7b9c8e1/src/bz-list-tile.h000066400000000000000000000023361514314607700203450ustar00rootroot00000000000000/* bz-list-tile.h * * Copyright 2025 Hari Rana * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_LIST_TILE (bz_list_tile_get_type()) G_DECLARE_DERIVABLE_TYPE (BzListTile, bz_list_tile, BZ, LIST_TILE, GtkWidget) struct _BzListTileClass { GtkWidgetClass parent_class; }; BzListTile *bz_list_tile_new (void); GtkWidget *bz_list_tile_get_child (BzListTile *self); void bz_list_tile_set_child (BzListTile *self, GtkWidget *child); G_END_DECLSkolunmi-bazaar-7b9c8e1/src/bz-login-page.blp000066400000000000000000000054211514314607700210050ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzLoginPage: Adw.NavigationPage { title: _("Connect to Flathub"); child: Adw.ToolbarView { [top] Adw.HeaderBar {} content: Stack main_stack { transition-type: crossfade; StackPage { name: "loading"; child: Adw.Spinner { hexpand: true; vexpand: true; halign: center; valign: center; width-request: 64; height-request: 64; }; } StackPage { name: "error"; child: Adw.StatusPage error_status_page { icon-name: "computer-fail-symbolic"; title: _("Something Went Wrong"); }; } StackPage { name: "start"; child: Adw.Clamp { child: Adw.StatusPage { icon-name: "flathub-symbolic"; title: _("Connect to Flathub"); description: _("Connect your Flathub account to Bazaar to manage your favorited apps."); child: Adw.PreferencesGroup provider_preferences_group { margin-start: 10; margin-end: 10; hexpand: true; halign: fill; }; }; }; } StackPage { name: "browser"; child: ScrolledWindow browser_scroll { vexpand: true; }; } StackPage { name: "finish"; child: ScrolledWindow { hscrollbar-policy: never; child: Adw.Clamp { maximum-size: 600; child: Box { orientation: vertical; vexpand: true; halign: center; valign: center; Box { orientation: vertical; spacing: 15; halign: center; valign: center; Adw.Avatar { size: 96; show-initials: true; text: bind template.auth-state as <$BzAuthState>.name; custom-image: bind template.auth-state as <$BzAuthState>.paintable; } Label { halign: center; label: bind $format_greeting(template.auth-state as <$BzAuthState>.name as ) as ; styles [ "title-1", ] } } Box { orientation: horizontal; spacing: 10; halign: center; margin-top: 20; Button { label: _("Finish"); clicked => $on_close_clicked(); styles [ "pill", ] } } }; }; }; } }; }; }kolunmi-bazaar-7b9c8e1/src/bz-login-page.c000066400000000000000000000536221514314607700204600ustar00rootroot00000000000000/* bz-login-page.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include #include #include "bz-auth-state.h" #include "bz-flathub-auth-provider.h" #include "bz-login-page.h" #include "bz-util.h" struct _BzLoginPage { AdwNavigationPage parent_instance; BzAuthState *auth_state; WebKitWebView *webview; gboolean webkit_loaded; SoupSession *session; SoupCookieJar *cookie_jar; GList *providers; BzFlathubAuthProvider *current_provider; char *auth_redirect_url; char *session_cookie; GDateTime *session_cookie_expires; gboolean oauth_completed; GtkStack *main_stack; AdwStatusPage *error_status_page; AdwPreferencesGroup *provider_preferences_group; GtkScrolledWindow *browser_scroll; }; G_DEFINE_FINAL_TYPE (BzLoginPage, bz_login_page, ADW_TYPE_NAVIGATION_PAGE) enum { PROP_0, PROP_AUTH_STATE, N_PROPS }; static GParamSpec *properties[N_PROPS]; static WebKitNetworkSession * get_shared_network_session (void) { static WebKitNetworkSession *shared_session = NULL; if (g_once_init_enter (&shared_session)) { g_autofree char *data_dir = NULL; g_autoptr (WebKitNetworkSession) session = NULL; data_dir = g_build_filename (g_get_user_data_dir (), "io.github.kolunmi.Bazaar", "webkit-data", NULL); session = webkit_network_session_new (data_dir, NULL); g_once_init_leave (&shared_session, g_steal_pointer (&session)); } return shared_session; } static void show_error_take (BzLoginPage *self, char *message) { g_autofree char *escaped_message = NULL; gtk_stack_set_visible_child_name (self->main_stack, "error"); escaped_message = g_markup_escape_text (message, -1); adw_status_page_set_description (self->error_status_page, escaped_message); g_free (message); } static JsonObject * parse_json_response (GBytes *bytes, GError **error) { gboolean result = FALSE; g_autoptr (JsonParser) parser = NULL; JsonNode *root = NULL; parser = json_parser_new (); result = json_parser_load_from_data ( parser, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), error); if (!result) return NULL; root = json_parser_get_root (parser); return json_node_dup_object (root); } static SoupMessage * create_flathub_request (const char *method, const char *route) { g_autofree char *url = NULL; g_autoptr (SoupMessage) msg = NULL; url = g_strdup_printf ("https://flathub.org/api/v2%s", route); msg = soup_message_new (method, url); soup_message_headers_append (soup_message_get_request_headers (msg), "accept", "application/json"); return g_steal_pointer (&msg); } static void load_webkit_library (BzLoginPage *self) { WebKitNetworkSession *network_session = NULL; if (self->webkit_loaded) return; network_session = get_shared_network_session (); self->webview = g_object_new ( WEBKIT_TYPE_WEB_VIEW, "network-session", network_session, NULL); gtk_scrolled_window_set_child ( self->browser_scroll, GTK_WIDGET (self->webview)); self->webkit_loaded = TRUE; } static void on_user_info_loaded (GObject *source_object, GAsyncResult *res, GWeakRef *wr); static void on_oauth_complete (GObject *source_object, GAsyncResult *res, GWeakRef *wr); static void complete_oauth (BzLoginPage *self, const char *code, const char *state, const char *error) { g_autoptr (JsonBuilder) builder = NULL; g_autoptr (JsonGenerator) generator = NULL; g_autofree char *route = NULL; g_autofree char *json_data = NULL; g_autoptr (SoupMessage) msg = NULL; gtk_stack_set_visible_child_name (self->main_stack, "loading"); builder = json_builder_new (); json_builder_begin_object (builder); if (error != NULL) { json_builder_set_member_name (builder, "state"); json_builder_add_string_value (builder, state); json_builder_set_member_name (builder, "error"); json_builder_add_string_value (builder, error); } else { json_builder_set_member_name (builder, "code"); json_builder_add_string_value (builder, code); json_builder_set_member_name (builder, "state"); json_builder_add_string_value (builder, state); } json_builder_end_object (builder); generator = json_generator_new (); json_generator_set_root (generator, json_builder_get_root (builder)); json_data = json_generator_to_data (generator, NULL); route = g_strdup_printf ("/auth/login/%s", bz_flathub_auth_provider_get_method (self->current_provider)); msg = soup_message_new ("POST", g_strdup_printf ("https://flathub.org/api/v2%s", route)); soup_message_headers_append (soup_message_get_request_headers (msg), "accept", "application/json"); soup_message_headers_append (soup_message_get_request_headers (msg), "Content-Type", "application/json"); soup_message_set_request_body_from_bytes (msg, "application/json", g_bytes_new (json_data, strlen (json_data))); soup_session_send_and_read_async ( self->session, msg, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback) on_oauth_complete, bz_track_weak (self)); } static gboolean on_decide_policy (BzLoginPage *self, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decision_type, WebKitWebView *webview) { WebKitNavigationAction *nav_action = NULL; WebKitURIRequest *request = NULL; const char *uri = NULL; g_autoptr (GUri) parsed_uri = NULL; g_autoptr (GHashTable) params = NULL; const char *code = NULL; const char *state = NULL; const char *error = NULL; if (decision_type != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION) return FALSE; nav_action = webkit_navigation_policy_decision_get_navigation_action ( WEBKIT_NAVIGATION_POLICY_DECISION (decision)); request = webkit_navigation_action_get_request (nav_action); uri = webkit_uri_request_get_uri (request); if (uri == NULL || strstr (uri, "flathub.org") == NULL || strstr (uri, "/login/") == NULL) return FALSE; parsed_uri = g_uri_parse (uri, G_URI_FLAGS_NONE, NULL); if (parsed_uri == NULL) return FALSE; params = g_uri_parse_params (g_uri_get_query (parsed_uri), -1, "&", G_URI_PARAMS_NONE, NULL); if (params == NULL) return FALSE; code = g_hash_table_lookup (params, "code"); state = g_hash_table_lookup (params, "state"); error = g_hash_table_lookup (params, "error"); if ((code != NULL && state != NULL && !self->oauth_completed) || (error != NULL && state != NULL && !self->oauth_completed)) { self->oauth_completed = TRUE; webkit_policy_decision_ignore (decision); complete_oauth (self, code, state, error); return TRUE; } return FALSE; } static void get_user_info (BzLoginPage *self) { g_autoptr (SoupMessage) msg = NULL; msg = create_flathub_request ("GET", "/auth/userinfo"); soup_session_send_and_read_async ( self->session, msg, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback) on_user_info_loaded, bz_track_weak (self)); } static void on_oauth_complete (GObject *source_object, GAsyncResult *res, GWeakRef *wr) { g_autoptr (BzLoginPage) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (JsonObject) obj = NULL; const char *status = NULL; g_autoslist (SoupCookie) cookies = NULL; self = g_weak_ref_get (wr); if (self == NULL) goto done; bytes = soup_session_send_and_read_finish ( SOUP_SESSION (source_object), res, &local_error); if (bytes == NULL) { g_warning ("OAuth complete error: %s", local_error->message); show_error_take (self, g_strdup_printf ("Error: %s", local_error->message)); goto done; } obj = parse_json_response (bytes, &local_error); if (obj == NULL) { g_warning ("Failed to parse OAuth response: %s", local_error->message); show_error_take (self, g_strdup_printf ("Error: %s", local_error->message)); goto done; } status = json_object_get_string_member (obj, "status"); cookies = soup_cookie_jar_all_cookies (self->cookie_jar); for (GSList *l = cookies; l != NULL; l = l->next) { SoupCookie *cookie = l->data; if (g_strcmp0 (soup_cookie_get_name (cookie), "session") == 0) { g_clear_pointer (&self->session_cookie, g_free); self->session_cookie = g_strdup (soup_cookie_get_value (cookie)); g_clear_pointer (&self->session_cookie_expires, g_date_time_unref); self->session_cookie_expires = g_date_time_ref (soup_cookie_get_expires (cookie)); } } if (g_strcmp0 (status, "ok") == 0 || g_strcmp0 (status, "success") == 0) get_user_info (self); else show_error_take (self, g_strdup ("Authentication failed")); done: bz_weak_release (wr); } static void on_user_info_loaded (GObject *source_object, GAsyncResult *res, GWeakRef *wr) { g_autoptr (BzLoginPage) self = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (GError) error = NULL; g_autoptr (JsonObject) obj = NULL; JsonObject *default_account = NULL; const char *displayname = NULL; const char *avatar_url = NULL; self = g_weak_ref_get (wr); if (self == NULL) goto done; if (self->webview != NULL) webkit_web_view_load_uri (self->webview, "about:blank"); bytes = soup_session_send_and_read_finish (SOUP_SESSION (source_object), res, &error); if (error != NULL) { g_warning ("User info load error: %s", error->message); show_error_take (self, g_strdup_printf ("Error: %s", error->message)); goto done; } obj = parse_json_response (bytes, &error); if (obj == NULL) { g_warning ("Failed to parse user info: %s", error->message); show_error_take (self, g_strdup_printf ("Error: %s", error->message)); goto done; } displayname = json_object_get_string_member (obj, "displayname"); if (json_object_has_member (obj, "default_account")) { default_account = json_object_get_object_member (obj, "default_account"); if (displayname == NULL && json_object_has_member (default_account, "login")) displayname = json_object_get_string_member (default_account, "login"); if (json_object_has_member (default_account, "avatar")) avatar_url = json_object_get_string_member (default_account, "avatar"); } if (displayname == NULL) displayname = "N/A"; if (self->auth_state != NULL) bz_auth_state_set_authenticated (self->auth_state, displayname, self->session_cookie, self->session_cookie_expires, avatar_url); gtk_stack_set_visible_child_name (self->main_stack, "finish"); done: bz_weak_release (wr); } static void on_login_response (GObject *source_object, GAsyncResult *res, GWeakRef *wr) { g_autoptr (BzLoginPage) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (JsonObject) obj = NULL; const char *redirect = NULL; self = g_weak_ref_get (wr); if (self == NULL) goto done; bytes = soup_session_send_and_read_finish ( SOUP_SESSION (source_object), res, &local_error); if (bytes == NULL) { show_error_take (self, g_strdup_printf ("Error: %s", local_error->message)); goto done; } obj = parse_json_response (bytes, &local_error); if (obj == NULL) { show_error_take (self, g_strdup_printf ("Error: %s", local_error->message)); goto done; } redirect = json_object_get_string_member (obj, "redirect"); if (redirect == NULL) { show_error_take (self, g_strdup ("Error: No redirect URL received")); goto done; } g_clear_pointer (&self->auth_redirect_url, g_free); self->auth_redirect_url = g_strdup (redirect); load_webkit_library (self); g_signal_connect_swapped ( self->webview, "decide-policy", G_CALLBACK (on_decide_policy), self); gtk_stack_set_visible_child_name (self->main_stack, "browser"); webkit_web_view_load_uri (self->webview, self->auth_redirect_url); done: bz_weak_release (wr); } static void on_provider_row_activated (BzLoginPage *self, GtkButton *button) { BzFlathubAuthProvider *provider = NULL; g_autoptr (SoupMessage) msg = NULL; g_autofree char *route = NULL; provider = g_object_get_data (G_OBJECT (button), "provider"); if (provider == NULL) return; self->current_provider = provider; self->oauth_completed = FALSE; gtk_stack_set_visible_child_name (self->main_stack, "loading"); route = g_strdup_printf ("/auth/login/%s", bz_flathub_auth_provider_get_method (provider)); msg = create_flathub_request ("GET", route); soup_session_send_and_read_async ( self->session, msg, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback) on_login_response, bz_track_weak (self)); } static void on_providers_loaded (GObject *source_object, GAsyncResult *res, GWeakRef *wr) { g_autoptr (BzLoginPage) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; g_autoptr (JsonParser) parser = NULL; JsonNode *root; JsonArray *array; self = g_weak_ref_get (wr); if (self == NULL) goto done; bytes = soup_session_send_and_read_finish (SOUP_SESSION (source_object), res, &local_error); if (bytes == NULL) { show_error_take (self, g_strdup_printf ("Error loading providers: %s", local_error->message)); goto done; } parser = json_parser_new (); if (!json_parser_load_from_data (parser, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &local_error)) { show_error_take (self, g_strdup_printf ("Error parsing providers: %s", local_error->message)); goto done; } root = json_parser_get_root (parser); array = json_node_get_array (root); for (guint i = 0; i < json_array_get_length (array); i++) { JsonObject *provider_obj = NULL; g_autoptr (BzFlathubAuthProvider) provider = NULL; const char *method = NULL; const char *name = NULL; GtkWidget *row = NULL; GtkWidget *prefix_icon = NULL; GtkWidget *suffix_icon = NULL; g_autofree char *icon_name = NULL; provider_obj = json_array_get_object_element (array, i); provider = bz_flathub_auth_provider_new (); method = json_object_get_string_member (provider_obj, "method"); name = json_object_get_string_member (provider_obj, "name"); row = adw_action_row_new (); icon_name = g_strdup_printf ("io.github.kolunmi.Bazaar.%s", method); bz_flathub_auth_provider_set_name (provider, name); bz_flathub_auth_provider_set_method (provider, method); self->providers = g_list_append (self->providers, g_object_ref (provider)); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), name); prefix_icon = gtk_image_new_from_icon_name (icon_name); gtk_image_set_icon_size (GTK_IMAGE (prefix_icon), GTK_ICON_SIZE_LARGE); gtk_widget_add_css_class (prefix_icon, "lowres-icon"); adw_action_row_add_prefix (ADW_ACTION_ROW (row), prefix_icon); suffix_icon = gtk_image_new_from_icon_name ("go-next-symbolic"); adw_action_row_add_suffix (ADW_ACTION_ROW (row), suffix_icon); g_object_set_data_full (G_OBJECT (row), "provider", g_object_ref (provider), g_object_unref); gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), true); g_signal_connect_swapped (row, "activated", G_CALLBACK (on_provider_row_activated), self); adw_preferences_group_add (self->provider_preferences_group, row); } gtk_stack_set_visible_child_name (self->main_stack, "start"); done: bz_weak_release (wr); } static void load_providers (BzLoginPage *self) { g_autoptr (SoupMessage) msg = NULL; gtk_stack_set_visible_child_name (self->main_stack, "loading"); msg = create_flathub_request ("GET", "/auth/login"); soup_session_send_and_read_async ( self->session, msg, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback) on_providers_loaded, bz_track_weak (self)); } static void on_close_clicked (GtkButton *button, BzLoginPage *self) { GtkWidget *navigation_view = NULL; navigation_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); if (navigation_view != NULL) adw_navigation_view_pop (ADW_NAVIGATION_VIEW (navigation_view)); } static void bz_login_page_dispose (GObject *object) { BzLoginPage *self = BZ_LOGIN_PAGE (object); g_clear_object (&self->auth_state); g_clear_object (&self->session); g_clear_object (&self->cookie_jar); g_clear_pointer (&self->session_cookie_expires, g_date_time_unref); g_clear_pointer (&self->auth_redirect_url, g_free); g_clear_pointer (&self->session_cookie, g_free); if (self->providers != NULL) { g_list_free_full (self->providers, (GDestroyNotify) g_object_unref); self->providers = NULL; } G_OBJECT_CLASS (bz_login_page_parent_class)->dispose (object); } static void bz_login_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzLoginPage *self = BZ_LOGIN_PAGE (object); switch (prop_id) { case PROP_AUTH_STATE: g_value_set_object (value, self->auth_state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_login_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzLoginPage *self = BZ_LOGIN_PAGE (object); switch (prop_id) { case PROP_AUTH_STATE: g_set_object (&self->auth_state, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * format_greeting (gpointer object, const char *name) { if (name == NULL || name[0] == '\0') return g_strdup (" "); return g_strdup_printf (_ ("Hello, %s!"), name); } static void bz_login_page_class_init (BzLoginPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_login_page_dispose; object_class->get_property = bz_login_page_get_property; object_class->set_property = bz_login_page_set_property; properties[PROP_AUTH_STATE] = g_param_spec_object ( "auth-state", NULL, NULL, BZ_TYPE_AUTH_STATE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-login-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzLoginPage, main_stack); gtk_widget_class_bind_template_child (widget_class, BzLoginPage, error_status_page); gtk_widget_class_bind_template_child (widget_class, BzLoginPage, provider_preferences_group); gtk_widget_class_bind_template_child (widget_class, BzLoginPage, browser_scroll); gtk_widget_class_bind_template_callback (widget_class, on_close_clicked); gtk_widget_class_bind_template_callback (widget_class, format_greeting); } static void bz_login_page_init (BzLoginPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->session = soup_session_new (); self->cookie_jar = soup_cookie_jar_new (); soup_cookie_jar_set_accept_policy (self->cookie_jar, SOUP_COOKIE_JAR_ACCEPT_ALWAYS); soup_session_add_feature (self->session, SOUP_SESSION_FEATURE (self->cookie_jar)); self->webkit_loaded = FALSE; self->oauth_completed = FALSE; load_providers (self); } AdwNavigationPage * bz_login_page_new (BzAuthState *auth_state) { return g_object_new (BZ_TYPE_LOGIN_PAGE, "auth-state", auth_state, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-login-page.h000066400000000000000000000020411514314607700204520ustar00rootroot00000000000000/* bz-login-page.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-auth-state.h" #include G_BEGIN_DECLS #define BZ_TYPE_LOGIN_PAGE (bz_login_page_get_type ()) G_DECLARE_FINAL_TYPE (BzLoginPage, bz_login_page, BZ, LOGIN_PAGE, AdwNavigationPage) AdwNavigationPage *bz_login_page_new (BzAuthState *auth_state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-lozenge.c000066400000000000000000000240041514314607700200710ustar00rootroot00000000000000/* bz-lozenge.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-context-row.h" #include "bz-lozenge.h" struct _BzLozenge { GtkBox parent_instance; gchar *title; gchar *label; gchar **icon_names; BzImportance importance; GtkWidget *icon_box; GtkWidget *label_widget; GtkWidget *title_label; }; G_DEFINE_FINAL_TYPE (BzLozenge, bz_lozenge, GTK_TYPE_BOX) enum { PROP_0, PROP_TITLE, PROP_LABEL, PROP_ICON_NAMES, PROP_IMPORTANCE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL }; static void bz_lozenge_rebuild (BzLozenge *self); static void bz_lozenge_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzLozenge *self = NULL; self = BZ_LOZENGE (object); switch (prop_id) { case PROP_TITLE: g_value_set_string (value, self->title); break; case PROP_LABEL: g_value_set_string (value, self->label); break; case PROP_ICON_NAMES: g_value_set_boxed (value, self->icon_names); break; case PROP_IMPORTANCE: g_value_set_enum (value, self->importance); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_lozenge_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzLozenge *self = NULL; self = BZ_LOZENGE (object); switch (prop_id) { case PROP_TITLE: bz_lozenge_set_title (self, g_value_get_string (value)); break; case PROP_LABEL: bz_lozenge_set_label (self, g_value_get_string (value)); break; case PROP_ICON_NAMES: bz_lozenge_set_icon_names (self, g_value_get_boxed (value)); break; case PROP_IMPORTANCE: bz_lozenge_set_importance (self, g_value_get_enum (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_lozenge_dispose (GObject *object) { BzLozenge *self = NULL; self = BZ_LOZENGE (object); g_clear_pointer (&self->title, g_free); g_clear_pointer (&self->label, g_free); g_clear_pointer (&self->icon_names, g_strfreev); g_clear_pointer (&self->icon_box, gtk_widget_unparent); g_clear_pointer (&self->label_widget, gtk_widget_unparent); g_clear_pointer (&self->title_label, gtk_widget_unparent); G_OBJECT_CLASS (bz_lozenge_parent_class)->dispose (object); } static void bz_lozenge_class_init (BzLozengeClass *klass) { GObjectClass *object_class = NULL; object_class = G_OBJECT_CLASS (klass); object_class->get_property = bz_lozenge_get_property; object_class->set_property = bz_lozenge_set_property; object_class->dispose = bz_lozenge_dispose; props[PROP_TITLE] = g_param_spec_string ("title", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_LABEL] = g_param_spec_string ("label", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ICON_NAMES] = g_param_spec_boxed ("icon-names", NULL, NULL, G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_IMPORTANCE] = g_param_spec_enum ("importance", NULL, NULL, BZ_TYPE_IMPORTANCE, BZ_IMPORTANCE_NEUTRAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_lozenge_init (BzLozenge *self) { GtkWidget *container = NULL; self->importance = BZ_IMPORTANCE_NEUTRAL; gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL); gtk_box_set_spacing (GTK_BOX (self), 12); gtk_widget_set_halign (GTK_WIDGET (self), GTK_ALIGN_CENTER); container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_widget_set_halign (container, GTK_ALIGN_CENTER); gtk_box_append (GTK_BOX (self), container); self->icon_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_widget_set_halign (self->icon_box, GTK_ALIGN_CENTER); gtk_box_append (GTK_BOX (container), self->icon_box); self->label_widget = gtk_label_new (NULL); gtk_widget_set_halign (self->label_widget, GTK_ALIGN_CENTER); gtk_widget_add_css_class (self->label_widget, "circular-lozenge"); gtk_widget_add_css_class (self->label_widget, "large"); gtk_box_append (GTK_BOX (container), self->label_widget); self->title_label = gtk_label_new (NULL); gtk_label_set_justify (GTK_LABEL (self->title_label), GTK_JUSTIFY_CENTER); gtk_label_set_wrap (GTK_LABEL (self->title_label), TRUE); gtk_label_set_wrap_mode (GTK_LABEL (self->title_label), PANGO_WRAP_WORD_CHAR); gtk_label_set_xalign (GTK_LABEL (self->title_label), 0.5); gtk_widget_add_css_class (self->title_label, "title-2"); gtk_box_append (GTK_BOX (self), self->title_label); bz_lozenge_rebuild (self); } GtkWidget * bz_lozenge_new (void) { return g_object_new (BZ_TYPE_LOZENGE, NULL); } void bz_lozenge_set_title (BzLozenge *self, const gchar *title) { g_return_if_fail (BZ_IS_LOZENGE (self)); if (g_strcmp0 (self->title, title) == 0) return; g_clear_pointer (&self->title, g_free); self->title = g_strdup (title); bz_lozenge_rebuild (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE]); } const gchar * bz_lozenge_get_title (BzLozenge *self) { g_return_val_if_fail (BZ_IS_LOZENGE (self), NULL); return self->title; } void bz_lozenge_set_label (BzLozenge *self, const gchar *label) { g_return_if_fail (BZ_IS_LOZENGE (self)); if (g_strcmp0 (self->label, label) == 0) return; g_clear_pointer (&self->label, g_free); self->label = g_strdup (label); bz_lozenge_rebuild (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LABEL]); } const gchar * bz_lozenge_get_label (BzLozenge *self) { g_return_val_if_fail (BZ_IS_LOZENGE (self), NULL); return self->label; } void bz_lozenge_set_icon_names (BzLozenge *self, const gchar *const *icon_names) { g_return_if_fail (BZ_IS_LOZENGE (self)); g_clear_pointer (&self->icon_names, g_strfreev); self->icon_names = g_strdupv ((gchar **) icon_names); bz_lozenge_rebuild (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAMES]); } gchar ** bz_lozenge_get_icon_names (BzLozenge *self) { g_return_val_if_fail (BZ_IS_LOZENGE (self), NULL); return g_strdupv (self->icon_names); } void bz_lozenge_set_importance (BzLozenge *self, BzImportance importance) { g_return_if_fail (BZ_IS_LOZENGE (self)); if (self->importance == importance) return; self->importance = importance; bz_lozenge_rebuild (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IMPORTANCE]); } BzImportance bz_lozenge_get_importance (BzLozenge *self) { g_return_val_if_fail (BZ_IS_LOZENGE (self), BZ_IMPORTANCE_NEUTRAL); return self->importance; } static void bz_lozenge_rebuild (BzLozenge *self) { GtkWidget *child = NULL; const gchar *css_class = NULL; g_return_if_fail (BZ_IS_LOZENGE (self)); while ((child = gtk_widget_get_first_child (self->icon_box)) != NULL) gtk_box_remove (GTK_BOX (self->icon_box), child); if (self->icon_names != NULL && self->icon_names[0] != NULL) { gtk_widget_set_visible (self->icon_box, TRUE); gtk_widget_set_visible (self->label_widget, FALSE); css_class = bz_context_row_importance_to_css_class (self->importance); for (gsize i = 0; self->icon_names[i] != NULL; i++) { GtkWidget *icon = NULL; icon = gtk_image_new_from_icon_name (self->icon_names[i]); gtk_image_set_pixel_size (GTK_IMAGE (icon), 24); gtk_widget_set_halign (icon, GTK_ALIGN_CENTER); gtk_widget_add_css_class (icon, "circular-lozenge"); gtk_widget_add_css_class (icon, css_class); gtk_widget_add_css_class (icon, "large"); gtk_box_append (GTK_BOX (self->icon_box), icon); } } else if (self->label != NULL && *self->label != '\0') { const gchar *new_classes[3] = { "circular-lozenge", "large", NULL }; gtk_widget_set_visible (self->icon_box, FALSE); gtk_widget_set_visible (self->label_widget, TRUE); gtk_label_set_markup (GTK_LABEL (self->label_widget), self->label); gtk_widget_set_css_classes (self->label_widget, new_classes); css_class = bz_context_row_importance_to_css_class (self->importance); gtk_widget_add_css_class (self->label_widget, css_class); } else { gtk_widget_set_visible (self->icon_box, FALSE); gtk_widget_set_visible (self->label_widget, FALSE); } if (self->title != NULL && *self->title != '\0') { gtk_label_set_text (GTK_LABEL (self->title_label), self->title); gtk_widget_set_visible (self->title_label, TRUE); } else { gtk_widget_set_visible (self->title_label, FALSE); } } kolunmi-bazaar-7b9c8e1/src/bz-lozenge.h000066400000000000000000000031301514314607700200730ustar00rootroot00000000000000/* bz-lozenge.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-context-row.h" #include G_BEGIN_DECLS #define BZ_TYPE_LOZENGE (bz_lozenge_get_type ()) G_DECLARE_FINAL_TYPE (BzLozenge, bz_lozenge, BZ, LOZENGE, GtkBox) GtkWidget *bz_lozenge_new (void); void bz_lozenge_set_title (BzLozenge *self, const gchar *title); const gchar * bz_lozenge_get_title (BzLozenge *self); void bz_lozenge_set_label (BzLozenge *self, const gchar *label); const gchar * bz_lozenge_get_label (BzLozenge *self); void bz_lozenge_set_icon_names (BzLozenge *self, const gchar *const *icon_names); gchar ** bz_lozenge_get_icon_names (BzLozenge *self); void bz_lozenge_set_importance (BzLozenge *self, BzImportance importance); BzImportance bz_lozenge_get_importance (BzLozenge *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-main-config.txt000066400000000000000000000011501514314607700212070ustar00rootroot00000000000000prefix=bz name=main_config parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-hook.h" ensure=BZ_TYPE_HOOK ensure=BZ_TYPE_HOOK_DIALOG ensure=BZ_TYPE_HOOK_DIALOG_OPTION property=txt_blocklist_paths GListModel G_TYPE_LIST_MODEL object property=blocklist_version int G_TYPE_INT int property=yaml_blocklist_paths GListModel G_TYPE_LIST_MODEL object property=curated_config_version int G_TYPE_INT int property=curated_config_paths GListModel G_TYPE_LIST_MODEL object property=override_eol_markings GListModel G_TYPE_LIST_MODEL object property=hooks GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-markdown-render.blp000066400000000000000000000002111514314607700220520ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzMarkdownRender: Adw.Bin { child: Box box { orientation: vertical; spacing: 10; }; } kolunmi-bazaar-7b9c8e1/src/bz-markdown-render.c000066400000000000000000000420321514314607700215260ustar00rootroot00000000000000/* bz-markdown-render.c * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::MARKDOWN-RENDER" #include #include "bz-markdown-render.h" struct _BzMarkdownRender { AdwBin parent_instance; char *markdown; gboolean selectable; GPtrArray *box_children; /* Template widgets */ GtkBox *box; }; G_DEFINE_FINAL_TYPE (BzMarkdownRender, bz_markdown_render, ADW_TYPE_BIN); enum { PROP_0, PROP_MARKDOWN, PROP_SELECTABLE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void regenerate (BzMarkdownRender *self); typedef struct { GtkBox *box; GPtrArray *box_children; char *beginning; GString *markup; GArray *block_stack; int indent; int list_index; MD_CHAR list_prefix; } ParseCtx; static int enter_block (MD_BLOCKTYPE type, void *detail, void *user_data); static int leave_block (MD_BLOCKTYPE type, void *detail, void *user_data); static int enter_span (MD_SPANTYPE type, void *detail, void *user_data); static int leave_span (MD_SPANTYPE type, void *detail, void *user_data); static int text (MD_TEXTTYPE type, const MD_CHAR *buf, MD_SIZE size, void *user_data); static const MD_PARSER parser = { .flags = MD_FLAG_COLLAPSEWHITESPACE | MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS, .enter_block = enter_block, .leave_block = leave_block, .enter_span = enter_span, .leave_span = leave_span, .text = text, }; static int terminate_block (MD_BLOCKTYPE type, void *detail, void *user_data); static void bz_markdown_render_dispose (GObject *object) { BzMarkdownRender *self = BZ_MARKDOWN_RENDER (object); g_clear_pointer (&self->markdown, g_free); g_clear_pointer (&self->box_children, g_ptr_array_unref); G_OBJECT_CLASS (bz_markdown_render_parent_class)->dispose (object); } static void bz_markdown_render_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzMarkdownRender *self = BZ_MARKDOWN_RENDER (object); switch (prop_id) { case PROP_MARKDOWN: g_value_set_string (value, bz_markdown_render_get_markdown (self)); break; case PROP_SELECTABLE: g_value_set_boolean (value, bz_markdown_render_get_selectable (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_markdown_render_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzMarkdownRender *self = BZ_MARKDOWN_RENDER (object); switch (prop_id) { case PROP_MARKDOWN: bz_markdown_render_set_markdown (self, g_value_get_string (value)); break; case PROP_SELECTABLE: bz_markdown_render_set_selectable (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_markdown_render_class_init (BzMarkdownRenderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_markdown_render_set_property; object_class->get_property = bz_markdown_render_get_property; object_class->dispose = bz_markdown_render_dispose; props[PROP_MARKDOWN] = g_param_spec_string ( "markdown", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_SELECTABLE] = g_param_spec_boolean ( "selectable", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-markdown-render.ui"); gtk_widget_class_bind_template_child (widget_class, BzMarkdownRender, box); } static void bz_markdown_render_init (BzMarkdownRender *self) { gtk_widget_init_template (GTK_WIDGET (self)); self->box_children = g_ptr_array_new (); } GtkWidget * bz_markdown_render_new (void) { return g_object_new (BZ_TYPE_MARKDOWN_RENDER, NULL); } const char * bz_markdown_render_get_markdown (BzMarkdownRender *self) { g_return_val_if_fail (BZ_IS_MARKDOWN_RENDER (self), NULL); return self->markdown; } gboolean bz_markdown_render_get_selectable (BzMarkdownRender *self) { g_return_val_if_fail (BZ_IS_MARKDOWN_RENDER (self), FALSE); return self->selectable; } void bz_markdown_render_set_markdown (BzMarkdownRender *self, const char *markdown) { g_return_if_fail (BZ_IS_MARKDOWN_RENDER (self)); g_clear_pointer (&self->markdown, g_free); if (markdown != NULL) self->markdown = g_strdup (markdown); regenerate (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MARKDOWN]); } void bz_markdown_render_set_selectable (BzMarkdownRender *self, gboolean selectable) { g_return_if_fail (BZ_IS_MARKDOWN_RENDER (self)); self->selectable = selectable; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTABLE]); } static void regenerate (BzMarkdownRender *self) { int iresult = 0; ParseCtx ctx = { 0 }; for (guint i = 0; i < self->box_children->len; i++) { GtkWidget *child = NULL; child = g_ptr_array_index (self->box_children, i); gtk_box_remove (self->box, child); } g_ptr_array_set_size (self->box_children, 0); if (self->markdown == NULL) return; ctx.box = self->box; ctx.box_children = self->box_children; ctx.beginning = self->markdown; ctx.markup = NULL; ctx.block_stack = g_array_new (FALSE, TRUE, sizeof (int)); ctx.indent = 0; ctx.list_index = 0; ctx.list_prefix = '\0'; iresult = md_parse ( self->markdown, strlen (self->markdown), &parser, &ctx); if (ctx.markup != NULL) g_string_free (ctx.markup, TRUE); g_array_unref (ctx.block_stack); if (iresult != 0) { g_warning ("Failed to parse markdown text"); return; } } static int enter_block (MD_BLOCKTYPE type, void *detail, void *user_data) { ParseCtx *ctx = user_data; if (ctx->markup != NULL) { terminate_block (type, detail, user_data); g_array_index (ctx->block_stack, int, ctx->block_stack->len - 1) = -1; } if (type == MD_BLOCK_UL) { MD_BLOCK_UL_DETAIL *ul_detail = detail; ctx->indent++; ctx->list_index = 0; ctx->list_prefix = ul_detail->mark; } else if (type == MD_BLOCK_OL) { MD_BLOCK_OL_DETAIL *ol_detail = detail; ctx->indent++; ctx->list_index = 0; ctx->list_prefix = ol_detail->mark_delimiter; } else ctx->markup = g_string_new (NULL); g_array_append_val (ctx->block_stack, type); return 0; } static int leave_block (MD_BLOCKTYPE type, void *detail, void *user_data) { ParseCtx *ctx = user_data; g_assert (ctx->block_stack->len > 0); if (g_array_index (ctx->block_stack, int, ctx->block_stack->len - 1) >= 0) terminate_block (type, detail, user_data); g_array_set_size (ctx->block_stack, ctx->block_stack->len - 1); return 0; } static int enter_span (MD_SPANTYPE type, void *detail, void *user_data) { ParseCtx *ctx = user_data; g_assert (ctx->markup != NULL); switch (type) { case MD_SPAN_EM: g_string_append (ctx->markup, ""); break; case MD_SPAN_STRONG: g_string_append (ctx->markup, ""); break; case MD_SPAN_A: { MD_SPAN_A_DETAIL *a_detail = detail; g_autofree char *href = NULL; g_autofree char *title = NULL; href = g_strndup (a_detail->href.text, a_detail->href.size); if (a_detail->title.text != NULL) title = g_strndup (a_detail->title.text, a_detail->title.size); g_string_append_printf ( ctx->markup, "", href, title != NULL ? title : href); } break; case MD_SPAN_IMG: g_warning ("Images aren't implemented yet!"); break; case MD_SPAN_CODE: g_string_append (ctx->markup, ""); break; case MD_SPAN_DEL: g_string_append (ctx->markup, ""); break; case MD_SPAN_U: g_string_append (ctx->markup, ""); break; case MD_SPAN_LATEXMATH: case MD_SPAN_LATEXMATH_DISPLAY: case MD_SPAN_WIKILINK: default: g_warning ("Unsupported markdown event (Did you use latex/wikilinks?)"); return 1; break; } return 0; } static int leave_span (MD_SPANTYPE type, void *detail, void *user_data) { ParseCtx *ctx = user_data; g_assert (ctx->markup != NULL); switch (type) { case MD_SPAN_EM: g_string_append (ctx->markup, ""); break; case MD_SPAN_STRONG: g_string_append (ctx->markup, ""); break; case MD_SPAN_A: g_string_append (ctx->markup, ""); break; case MD_SPAN_IMG: // g_warning ("Images aren't implemented yet!"); break; case MD_SPAN_CODE: g_string_append (ctx->markup, ""); break; case MD_SPAN_DEL: g_string_append (ctx->markup, ""); break; case MD_SPAN_U: g_string_append (ctx->markup, ""); break; case MD_SPAN_LATEXMATH: case MD_SPAN_LATEXMATH_DISPLAY: case MD_SPAN_WIKILINK: default: g_warning ("Unsupported markdown event (Did you use latex/wikilinks?)"); return 1; break; } return 0; } static int text (MD_TEXTTYPE type, const MD_CHAR *buf, MD_SIZE size, void *user_data) { ParseCtx *ctx = user_data; g_autofree char *escaped = NULL; g_assert (ctx->markup != NULL); if (type == MD_TEXT_SOFTBR && ctx->markup->len > 0) g_string_append_c (ctx->markup, ' '); else if (type == MD_TEXT_BR && ctx->markup->len > 0) g_string_append_c (ctx->markup, '\n'); else { escaped = g_markup_escape_text (buf, size); g_string_append (ctx->markup, escaped); } return 0; } static int terminate_block (MD_BLOCKTYPE type, void *detail, void *user_data) { ParseCtx *ctx = user_data; int parent = 0; GtkWidget *child = NULL; g_assert (ctx->block_stack->len > 0); if (ctx->block_stack->len > 1) parent = g_array_index (ctx->block_stack, int, ctx->block_stack->len - 2); if (ctx->markup != NULL) { if (ctx->markup->len > 0 && !g_unichar_isgraph (ctx->markup->str[ctx->markup->len - 1])) g_string_truncate (ctx->markup, ctx->markup->len - 1); } #define SET_DEFAULTS(_label_widget) \ G_STMT_START \ { \ gtk_label_set_use_markup (GTK_LABEL (_label_widget), TRUE); \ gtk_label_set_wrap (GTK_LABEL (_label_widget), TRUE); \ gtk_label_set_wrap_mode (GTK_LABEL (_label_widget), PANGO_WRAP_WORD_CHAR); \ gtk_label_set_xalign (GTK_LABEL (_label_widget), 0.0); \ gtk_label_set_selectable (GTK_LABEL (_label_widget), TRUE); \ } \ G_STMT_END switch (type) { case MD_BLOCK_DOC: { g_assert (ctx->markup != NULL); child = gtk_label_new (ctx->markup->str); SET_DEFAULTS (child); } break; case MD_BLOCK_QUOTE: { GtkWidget *bar = NULL; GtkWidget *label = NULL; g_assert (ctx->markup != NULL); bar = gtk_separator_new (GTK_ORIENTATION_VERTICAL); gtk_widget_set_size_request (bar, 10, -1); gtk_widget_set_margin_end (bar, 20); label = gtk_label_new (ctx->markup->str); SET_DEFAULTS (label); child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_append (GTK_BOX (child), bar); gtk_box_append (GTK_BOX (child), label); } break; case MD_BLOCK_UL: { // MD_BLOCK_UL_DETAIL *ul_detail = detail; if (ctx->markup == NULL) ctx->indent--; } break; case MD_BLOCK_OL: { // MD_BLOCK_OL_DETAIL *ol_detail = detail; if (ctx->markup == NULL) ctx->indent--; } break; case MD_BLOCK_LI: { // MD_BLOCK_LI_DETAIL *li_detail = detail; GtkWidget *prefix = NULL; GtkWidget *label = NULL; g_assert (ctx->markup != NULL); g_assert (parent == MD_BLOCK_UL || parent == MD_BLOCK_OL); if (parent == MD_BLOCK_OL) { g_autofree char *prefix_text = NULL; prefix_text = g_strdup_printf ("%d%c", ctx->list_index, ctx->list_prefix); prefix = gtk_label_new (prefix_text); gtk_widget_add_css_class (prefix, "caption"); } else { /* TODO: `ctx->list_prefix` is '-', '+', '*' maybe handle these? */ prefix = gtk_image_new_from_icon_name ("circle-filled-symbolic"); gtk_image_set_pixel_size (GTK_IMAGE (prefix), 6); gtk_widget_set_margin_top (prefix, 6); } gtk_widget_add_css_class (prefix, "dimmed"); gtk_widget_set_valign (prefix, GTK_ALIGN_START); label = gtk_label_new (ctx->markup->str); SET_DEFAULTS (label); child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_append (GTK_BOX (child), prefix); gtk_box_append (GTK_BOX (child), label); ctx->list_index++; } break; case MD_BLOCK_HR: child = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); break; case MD_BLOCK_H: { MD_BLOCK_H_DETAIL *h_detail = detail; const char *css_class = NULL; child = gtk_label_new (ctx->markup->str); SET_DEFAULTS (child); switch (h_detail->level) { case 1: css_class = "title-1"; break; case 2: css_class = "title-2"; break; case 3: css_class = "title-3"; break; case 4: css_class = "title-4"; break; case 5: css_class = "heading"; break; case 6: default: css_class = "caption-heading"; break; } gtk_widget_add_css_class (child, css_class); } break; case MD_BLOCK_CODE: { GtkWidget *label = NULL; label = gtk_label_new (ctx->markup->str); SET_DEFAULTS (label); gtk_widget_add_css_class (label, "monospace"); gtk_widget_set_margin_start (label, 5); gtk_widget_set_margin_end (label, 5); gtk_widget_set_margin_top (label, 5); gtk_widget_set_margin_bottom (label, 5); child = gtk_frame_new (NULL); gtk_frame_set_child (GTK_FRAME (child), label); } break; case MD_BLOCK_P: { child = gtk_label_new (ctx->markup->str); SET_DEFAULTS (child); gtk_widget_add_css_class (child, "body"); } break; case MD_BLOCK_HTML: case MD_BLOCK_TABLE: case MD_BLOCK_THEAD: case MD_BLOCK_TBODY: case MD_BLOCK_TR: case MD_BLOCK_TH: case MD_BLOCK_TD: default: g_warning ("Unsupported markdown event (Did you use html/tables?)"); return 1; } #undef SET_DEFAULTS if (child != NULL) { gtk_widget_set_margin_start (child, 10 * ctx->indent); gtk_box_append (ctx->box, child); g_ptr_array_add (ctx->box_children, child); } if (ctx->markup != NULL) { g_string_free (ctx->markup, TRUE); ctx->markup = NULL; } return 0; } /* End of bz-markdown-render.c */ kolunmi-bazaar-7b9c8e1/src/bz-markdown-render.h000066400000000000000000000026511514314607700215360ustar00rootroot00000000000000/* bz-markdown-render.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_MARKDOWN_RENDER (bz_markdown_render_get_type ()) G_DECLARE_FINAL_TYPE (BzMarkdownRender, bz_markdown_render, BZ, MARKDOWN_RENDER, AdwBin) GtkWidget * bz_markdown_render_new (void); const char * bz_markdown_render_get_markdown (BzMarkdownRender *self); gboolean bz_markdown_render_get_selectable (BzMarkdownRender *self); void bz_markdown_render_set_markdown (BzMarkdownRender *self, const char *markdown); void bz_markdown_render_set_selectable (BzMarkdownRender *self, gboolean selectable); G_END_DECLS /* End of bz-markdown-render.h */ kolunmi-bazaar-7b9c8e1/src/bz-marshalers.list000066400000000000000000000026251514314607700213250ustar00rootroot00000000000000# see glib-genmarshal(1) for a detailed description of the file format, # possible parameter types are: # VOID indicates no return type, or no extra # parameters. if VOID is used as the parameter # list, no additional parameters may be present. # BOOLEAN for boolean types (gboolean) # CHAR for signed char types (char) # UCHAR for unsigned char types (guchar) # INT for signed integer types (int) # UINT for unsigned integer types (guint) # LONG for signed long integer types (glong) # ULONG for unsigned long integer types (gulong) # INT64 for signed 64bit integer types (gint64) # UINT64 for unsigned 64bit integer types (guint64) # ENUM for enumeration types (int) # FLAGS for flag enumeration types (guint) # FLOAT for single-precision float types (float) # DOUBLE for double-precision float types (double) # STRING for string types (char *) # BOXED for boxed (anonymous but reference counted) types (GBoxed*) # PARAM for GParamSpec or derived types (GParamSpec*) # POINTER for anonymous pointer types (gpointer) # OBJECT for GObject or derived types (GObject*) # VARIANT for GVariant types (GVariant*) # NONE deprecated alias for VOID # BOOL deprecated alias for BOOLEAN VOID:OBJECT,OBJECT VOID:OBJECT,BOXED kolunmi-bazaar-7b9c8e1/src/bz-newline-parser.c000066400000000000000000000112501514314607700213600ustar00rootroot00000000000000/* bz-newline-parser.c * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::NEWLINE-TXT-PARSER" #include "config.h" #include "bz-hash-table-object.h" #include "bz-newline-parser.h" #include "bz-parser.h" struct _BzNewlineParser { GObject parent_instance; gboolean comments; guint max_lines; }; static void parser_iface_init (BzParserInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzNewlineParser, bz_newline_parser, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (BZ_TYPE_PARSER, parser_iface_init)) static void destroy_gvalue (GValue *value); static void bz_newline_parser_dispose (GObject *object) { BzNewlineParser *self = BZ_NEWLINE_PARSER (object); (void) self; G_OBJECT_CLASS (bz_newline_parser_parent_class)->dispose (object); } static void bz_newline_parser_class_init (BzNewlineParserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_newline_parser_dispose; } static void bz_newline_parser_init (BzNewlineParser *self) { } static GHashTable * bz_newline_parser_real_process_bytes (BzParser *iface_self, GBytes *bytes, GError **error) { BzNewlineParser *self = BZ_NEWLINE_PARSER (iface_self); gsize size = 0; const guchar *data = NULL; g_autofree char *contents = NULL; g_autoptr (GHashTable) set = NULL; guint n_ids = 0; char *beg = NULL; char *end = NULL; g_autoptr (BzHashTableObject) obj = NULL; GValue *value = NULL; g_autoptr (GHashTable) ret = NULL; g_return_val_if_fail (BZ_IS_NEWLINE_PARSER (self), NULL); g_return_val_if_fail (bytes != NULL, NULL); data = g_bytes_get_data (bytes, &size); contents = g_memdup2 (data, size + 1); contents[size] = '\0'; set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (beg = contents, end = g_utf8_strchr (beg, -1, '\n'); beg != NULL && *beg != '\0'; beg = end + 1, end = g_utf8_strchr (beg, -1, '\n')) { g_autofree char *line = NULL; if (end == NULL) g_warning ("Data has no terminating newline"); if ((self->comments && g_str_has_prefix (beg, "#")) || (end != NULL && end - beg <= 1) || (end == NULL && *beg == '\0')) { if (end != NULL) continue; else break; } if (end != NULL) line = g_strndup (beg, end - beg); else line = g_strdup (beg); if (g_hash_table_contains (set, line)) g_warning ("Duplicate line %s detected in data", line); else g_hash_table_replace (set, g_steal_pointer (&line), NULL); if (end == NULL) break; if (self->max_lines > 0 && ++n_ids > self->max_lines) { g_warning ("Data has a lot of lines, automatically " "truncating to %d", self->max_lines); break; } } obj = bz_hash_table_object_new (); bz_hash_table_object_set_hash_table (obj, set); value = g_new0 (typeof (*value), 1); g_value_init (value, G_TYPE_OBJECT); g_value_set_object (value, obj); ret = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_gvalue); g_hash_table_replace (ret, g_strdup ("/"), g_steal_pointer (&value)); return g_steal_pointer (&ret); } static void parser_iface_init (BzParserInterface *iface) { iface->process_bytes = bz_newline_parser_real_process_bytes; } BzNewlineParser * bz_newline_parser_new (gboolean comments, guint max_lines) { BzNewlineParser *parser = NULL; parser = g_object_new (BZ_TYPE_NEWLINE_PARSER, NULL); parser->comments = comments; parser->max_lines = max_lines; return parser; } static void destroy_gvalue (GValue *value) { g_value_unset (value); g_free (value); } kolunmi-bazaar-7b9c8e1/src/bz-newline-parser.h000066400000000000000000000020601514314607700213640ustar00rootroot00000000000000/* bz-newline-parser.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_NEWLINE_PARSER (bz_newline_parser_get_type ()) G_DECLARE_FINAL_TYPE (BzNewlineParser, bz_newline_parser, BZ, NEWLINE_PARSER, GObject) BzNewlineParser * bz_newline_parser_new (gboolean comments, guint max_lines); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-parser.c000066400000000000000000000026651514314607700177330ustar00rootroot00000000000000/* bz-parser.c * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-parser.h" G_DEFINE_INTERFACE (BzParser, bz_parser, G_TYPE_OBJECT) static GHashTable * bz_parser_real_process_bytes (BzParser *self, GBytes *bytes, GError **error) { return NULL; } static void bz_parser_default_init (BzParserInterface *iface) { iface->process_bytes = bz_parser_real_process_bytes; } GHashTable * bz_parser_process_bytes (BzParser *self, GBytes *bytes, GError **error) { g_return_val_if_fail (BZ_IS_PARSER (self), NULL); g_return_val_if_fail (bytes != NULL, NULL); return BZ_PARSER_GET_IFACE (self)->process_bytes ( self, bytes, error); } kolunmi-bazaar-7b9c8e1/src/bz-parser.h000066400000000000000000000023721514314607700177330ustar00rootroot00000000000000/* bz-parser.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_PARSER (bz_parser_get_type ()) G_DECLARE_INTERFACE (BzParser, bz_parser, BZ, PARSER, GObject) struct _BzParserInterface { GTypeInterface parent_iface; GHashTable *(*process_bytes) (BzParser *self, GBytes *bytes, GError **error); }; GHashTable * bz_parser_process_bytes (BzParser *self, GBytes *bytes, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-popup-overlay.c000066400000000000000000000335111514314607700212530ustar00rootroot00000000000000/* bz-popup-overlay.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::POPUP-OVERLAY" #include "bz-popup-overlay.h" #include "bz-animation.h" #include "bz-util.h" struct _BzPopupOverlay { GtkWidget parent_instance; GtkWidget *child; GPtrArray *stack; BzAnimation *animation; int width; int height; }; G_DEFINE_FINAL_TYPE (BzPopupOverlay, bz_popup_overlay, GTK_TYPE_WIDGET); BZ_DEFINE_DATA ( popup, Popup, { GtkWidget *child; GtkWidget *source; graphene_rect_t allocation; gboolean initialized; graphene_point_t offset; graphene_size_t scale; double opacity; }, BZ_RELEASE_DATA (child, gtk_widget_unparent); BZ_RELEASE_DATA (source, g_object_unref)) static void animate (BzPopupOverlay *self, const char *key, double value, PopupData *data); static gboolean close_request_cb (BzPopupOverlay *self, GtkRoot *root); enum { PROP_0, PROP_CHILD, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_popup_overlay_dispose (GObject *object) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (object); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_pointer (&self->stack, g_ptr_array_unref); g_clear_object (&self->animation); G_OBJECT_CLASS (bz_popup_overlay_parent_class)->dispose (object); } static void bz_popup_overlay_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_popup_overlay_get_child (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_popup_overlay_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (object); switch (prop_id) { case PROP_CHILD: bz_popup_overlay_set_child (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_popup_overlay_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (widget); if (self->child != NULL) gtk_widget_measure ( self->child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); } static void bz_popup_overlay_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (widget); if (self->child != NULL && gtk_widget_should_layout (self->child)) gtk_widget_allocate (self->child, width, height, baseline, NULL); for (guint i = 0; i < self->stack->len;) { gboolean result = FALSE; PopupData *data = NULL; graphene_rect_t source_bounds = { 0 }; graphene_point_t source_center = { 0 }; int minimum_width = 0; int natural_width = 0; int minimum_height = 0; int natural_height = 0; graphene_size_t popup_size = { 0 }; graphene_rect_t popup_bounds = { 0 }; int unused = 0; g_autoptr (GskTransform) transform = NULL; data = g_ptr_array_index (self->stack, i); result = gtk_widget_compute_bounds (data->source, GTK_WIDGET (self), &source_bounds); if (!result) { g_critical ("popup lost track of its source widget!"); g_ptr_array_remove_index (self->stack, i); continue; } graphene_rect_get_center (&source_bounds, &source_center); gtk_widget_measure ( data->child, GTK_ORIENTATION_HORIZONTAL, width, &minimum_width, &natural_width, &unused, &unused); gtk_widget_measure ( data->child, GTK_ORIENTATION_VERTICAL, height, &minimum_height, &natural_height, &unused, &unused); popup_size = GRAPHENE_SIZE_INIT ( CLAMP ((double) natural_width, (double) minimum_width, (double) width), CLAMP ((double) natural_height, (double) minimum_height, (double) height)); popup_bounds = GRAPHENE_RECT_INIT ( CLAMP (source_center.x / 2.0 < (double) width / 2.0 ? source_bounds.origin.x + source_bounds.size.width : source_bounds.origin.x - popup_size.width, 0.0, (double) width - popup_size.width), CLAMP (source_center.y / 2.0 < (double) height / 2.0 ? source_bounds.origin.y + source_bounds.size.height : source_bounds.origin.y - popup_size.height, 0.0, (double) height - popup_size.height), popup_size.width, popup_size.height); if (!data->initialized) { char buf[64] = { 0 }; g_snprintf (buf, sizeof (buf), "x-%p", data); bz_animation_add_spring ( self->animation, buf, popup_bounds.origin.x - source_bounds.origin.x, 0.0, 0.9, 1.0, 0.1, (BzAnimationCallback) animate, popup_data_ref (data), popup_data_unref); buf[0] = 'y'; bz_animation_add_spring ( self->animation, buf, popup_bounds.origin.y - source_bounds.origin.y, 0.0, 0.9, 1.0, 0.1, (BzAnimationCallback) animate, popup_data_ref (data), popup_data_unref); buf[0] = 'w'; bz_animation_add_spring ( self->animation, buf, 0.0, 1.0, 0.9, 1.0, 0.1, (BzAnimationCallback) animate, popup_data_ref (data), popup_data_unref); buf[0] = 'h'; bz_animation_add_spring ( self->animation, buf, 0.0, 1.0, 0.9, 1.0, 0.1, (BzAnimationCallback) animate, popup_data_ref (data), popup_data_unref); buf[0] = 'o'; bz_animation_add_spring ( self->animation, buf, 0.0, 1.0, 1.0, 1.0, 0.2, (BzAnimationCallback) animate, popup_data_ref (data), popup_data_unref); data->initialized = TRUE; } popup_bounds.origin.x -= data->offset.x; popup_bounds.origin.y -= data->offset.y; transform = gsk_transform_translate (transform, &popup_bounds.origin); transform = gsk_transform_scale (transform, data->scale.width, data->scale.height); gtk_widget_allocate ( data->child, popup_bounds.size.width, popup_bounds.size.height, baseline, g_steal_pointer (&transform)); i++; } } static void bz_popup_overlay_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (widget); double width = 0.0; double height = 0.0; if (self->child != NULL) gtk_widget_snapshot_child (widget, self->child, snapshot); width = gtk_widget_get_width (widget); height = gtk_widget_get_height (widget); for (guint i = 0; i < self->stack->len; i++) { PopupData *data = NULL; data = g_ptr_array_index (self->stack, i); gtk_snapshot_push_opacity (snapshot, data->opacity); gtk_snapshot_append_color ( snapshot, &(const GdkRGBA) { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 0.25, }, &GRAPHENE_RECT_INIT (0.0, 0.0, width, height)); gtk_widget_snapshot_child (widget, data->child, snapshot); gtk_snapshot_pop (snapshot); } } static void bz_popup_overlay_root (GtkWidget *widget) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (widget); GtkRoot *root = NULL; GTK_WIDGET_CLASS (bz_popup_overlay_parent_class)->root (widget); root = gtk_widget_get_root (GTK_WIDGET (self)); g_signal_connect_swapped ( root, "close-request", G_CALLBACK (close_request_cb), self); } static void bz_popup_overlay_unroot (GtkWidget *widget) { BzPopupOverlay *self = BZ_POPUP_OVERLAY (widget); GtkRoot *root = NULL; root = gtk_widget_get_root (GTK_WIDGET (self)); g_signal_handlers_disconnect_by_func (root, close_request_cb, self); GTK_WIDGET_CLASS (bz_popup_overlay_parent_class)->unroot (widget); } static void bz_popup_overlay_class_init (BzPopupOverlayClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_popup_overlay_set_property; object_class->get_property = bz_popup_overlay_get_property; object_class->dispose = bz_popup_overlay_dispose; props[PROP_CHILD] = g_param_spec_object ( "child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->measure = bz_popup_overlay_measure; widget_class->size_allocate = bz_popup_overlay_size_allocate; widget_class->snapshot = bz_popup_overlay_snapshot; widget_class->root = bz_popup_overlay_root; widget_class->unroot = bz_popup_overlay_unroot; } static void bz_popup_overlay_init (BzPopupOverlay *self) { self->stack = g_ptr_array_new_with_free_func (popup_data_unref); self->animation = bz_animation_new (GTK_WIDGET (self)); self->width = -1; self->height = -1; } BzPopupOverlay * bz_popup_overlay_new (void) { return g_object_new (BZ_TYPE_POPUP_OVERLAY, NULL); } GtkWidget * bz_popup_overlay_get_child (BzPopupOverlay *self) { g_return_val_if_fail (BZ_IS_POPUP_OVERLAY (self), NULL); return self->child; } void bz_popup_overlay_set_child (BzPopupOverlay *self, GtkWidget *child) { g_return_if_fail (BZ_IS_POPUP_OVERLAY (self)); if (child == self->child) return; if (child != NULL) g_return_if_fail (gtk_widget_get_parent (child) == NULL); g_clear_pointer (&self->child, gtk_widget_unparent); self->child = child; if (child != NULL) gtk_widget_set_parent (child, GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]); } void bz_popup_overlay_push (BzPopupOverlay *self, GtkWidget *widget, GtkWidget *source) { g_autoptr (PopupData) data = NULL; g_return_if_fail (BZ_IS_POPUP_OVERLAY (self)); g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_IS_WIDGET (source)); g_return_if_fail (gtk_widget_is_ancestor (source, GTK_WIDGET (self))); data = popup_data_new (); data->child = widget; data->source = g_object_ref (source); data->allocation = (graphene_rect_t) { 0 }; data->initialized = FALSE; data->offset = (graphene_point_t) { 0 }; data->scale = (graphene_size_t) { 0 }; data->opacity = 0.0; g_ptr_array_add (self->stack, popup_data_ref (data)); gtk_widget_set_parent (widget, GTK_WIDGET (self)); gtk_widget_queue_allocate (GTK_WIDGET (self)); } void bz_popup_present (GtkWidget *popup, GtkWidget *source) { GtkWidget *overlay = NULL; g_return_if_fail (GTK_IS_WIDGET (popup)); g_return_if_fail (GTK_IS_WIDGET (source)); overlay = gtk_widget_get_ancestor (source, BZ_TYPE_POPUP_OVERLAY); if (overlay == NULL) { g_critical ("source widget does not have an ancestor of type %s!", g_type_name (BZ_TYPE_POPUP_OVERLAY)); return; } bz_popup_overlay_push (BZ_POPUP_OVERLAY (overlay), popup, source); } static void animate (BzPopupOverlay *self, const char *key, double value, PopupData *data) { switch (*key) { case 'x': data->offset.x = value; break; case 'y': data->offset.y = value; break; case 'w': data->scale.width = value; break; case 'h': data->scale.height = value; break; case 'o': data->opacity = value; break; default: g_assert_not_reached (); } gtk_widget_queue_allocate (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); } static gboolean close_request_cb (BzPopupOverlay *self, GtkRoot *root) { if (self->stack->len > 0) { g_ptr_array_remove_index (self->stack, self->stack->len - 1); return GDK_EVENT_STOP; } return GDK_EVENT_PROPAGATE; } /* End of bz-popup-overlay.c */ kolunmi-bazaar-7b9c8e1/src/bz-popup-overlay.h000066400000000000000000000026411514314607700212600ustar00rootroot00000000000000/* bz-popup-overlay.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_POPUP_OVERLAY (bz_popup_overlay_get_type ()) G_DECLARE_FINAL_TYPE (BzPopupOverlay, bz_popup_overlay, BZ, POPUP_OVERLAY, GtkWidget) BzPopupOverlay * bz_popup_overlay_new (void); GtkWidget * bz_popup_overlay_get_child (BzPopupOverlay *self); void bz_popup_overlay_set_child (BzPopupOverlay *self, GtkWidget *child); void bz_popup_overlay_push (BzPopupOverlay *self, GtkWidget *widget, GtkWidget *source); void bz_popup_present (GtkWidget *popup, GtkWidget *source); G_END_DECLS /* End of bz-popup-overlay.h */ kolunmi-bazaar-7b9c8e1/src/bz-preferences-dialog.blp000066400000000000000000000050371514314607700225240ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzPreferencesDialog: Adw.PreferencesDialog { content-height: 500; search-enabled: true; width-request: 350; height-request: 500; Adw.Breakpoint { condition ("max-width: 625sp") setters { flag_buttons_box.max-children-per-line: 6; } } Adw.PreferencesPage { title: _("Preferences"); use-underline: true; banner: Adw.Banner { sensitive: bind $invert_boolean(template.state as <$BzStateInfo>.syncing as ) as ; revealed: bind template.state as <$BzStateInfo>.metered_connection as ; title: _("Network connection is metered — automatic store data sync is paused"); button-label: _("Sync Manually"); action-name: "app.sync-remotes"; }; Adw.PreferencesGroup { title: _("Content Filters"); Adw.SwitchRow only_foss_switch { title: _("Free Software Only"); subtitle: _("Hide proprietary applications when browsing and searching"); } Adw.SwitchRow only_flathub_switch { title: _("Flathub Results Only"); subtitle: _("Limit search and browse results to applications only available on Flathub"); } Adw.SwitchRow only_verified_switch { title: _("Verified Results Only"); subtitle: _("Hide results that are not verified on Flathub"); } Adw.SwitchRow hide_eol_switch { title: _("Hide EOL Apps"); subtitle: _("Hide apps which are no longer supported by their developers"); } } Adw.PreferencesGroup { title: _("Search"); Adw.SwitchRow search_debounce_switch { title: _("Delay Search Results"); subtitle: _("Improve results performance by debouncing search terms"); } } Adw.PreferencesGroup { title: _("Progress Bar"); description: _("Choose a theme for the progress bar!"); Adw.ActionRow { child: Box { margin-top: 6; margin-bottom: 6; halign: center; FlowBox flag_buttons_box { styles [ "accent-button-box", ] orientation: horizontal; column-spacing: 4; row-spacing: 4; halign: center; homogeneous: true; max-children-per-line: 12; selection-mode: none; } }; } Adw.SwitchRow rotate_switch { title: _("Vertical Stripes"); subtitle: _("Display flag colors from left to right"); notify::active => $on_rotate_switch_changed(); } } } } kolunmi-bazaar-7b9c8e1/src/bz-preferences-dialog.c000066400000000000000000000274351514314607700221770ustar00rootroot00000000000000/* bz-preferences-dialog.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-preferences-dialog.h" #include typedef struct { const char *id; const char *style_class; const char *tooltip; } BarTheme; static const BarTheme bar_themes[] = { { "accent-color", "accent-color-theme", N_ ("Accent Color") }, { "pride-rainbow-flag", "pride-rainbow-flag-theme", N_ ("Pride Colors") }, { "lesbian-pride-flag", "lesbian-pride-flag-theme", N_ ("Lesbian Pride Colors") }, { "gay-pride-flag", "gay-pride-flag-theme", N_ ("Male Homosexual Pride Colors") }, { "transgender-flag", "transgender-flag-theme", N_ ("Transgender Pride Colors") }, { "nonbinary-flag", "nonbinary-flag-theme", N_ ("Nonbinary Pride Colors") }, { "bisexual-flag", "bisexual-flag-theme", N_ ("Bisexual Pride Colors") }, { "asexual-flag", "asexual-flag-theme", N_ ("Asexual Pride Colors") }, { "pansexual-flag", "pansexual-flag-theme", N_ ("Pansexual Pride Colors") }, { "aromantic-flag", "aromantic-flag-theme", N_ ("Aromantic Pride Colors") }, { "genderfluid-flag", "genderfluid-flag-theme", N_ ("Genderfluid Pride Colors") }, { "polysexual-flag", "polysexual-flag-theme", N_ ("Polysexual Pride Colors") }, { "omnisexual-flag", "omnisexual-flag-theme", N_ ("Omnisexual Pride Colors") }, { "aroace-flag", "aroace-flag-theme", N_ ("Aroace Pride Colors") }, { "agender-flag", "agender-flag-theme", N_ ("Agender Pride Colors") }, { "genderqueer-flag", "genderqueer-flag-theme", N_ ("Genderqueer Pride Colors") }, { "intersex-flag", "intersex-flag-theme", N_ ("Intersex Pride Colors") }, { "demigender-flag", "demigender-flag-theme", N_ ("Demigender Pride Colors") }, { "biromantic-flag", "biromantic-flag-theme", N_ ("Biromantic Pride Colors") }, { "disability-flag", "disability-flag-theme", N_ ("Disability Pride Colors") }, { "femboy-flag", "femboy-flag-theme", N_ ("Femboy Pride Colors") }, { "neutrois-flag", "neutrois-flag-theme", N_ ("Neutrois Pride Colors") }, }; struct _BzPreferencesDialog { AdwPreferencesDialog parent_instance; BzStateInfo *state; GSettings *settings; /* Template widgets */ AdwSwitchRow *only_foss_switch; AdwSwitchRow *only_flathub_switch; AdwSwitchRow *only_verified_switch; AdwSwitchRow *search_debounce_switch; GtkFlowBox *flag_buttons_box; AdwSwitchRow *hide_eol_switch; AdwSwitchRow *rotate_switch; GtkToggleButton *flag_buttons[G_N_ELEMENTS (bar_themes)]; }; G_DEFINE_FINAL_TYPE (BzPreferencesDialog, bz_preferences_dialog, ADW_TYPE_PREFERENCES_DIALOG) enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bind_settings (BzPreferencesDialog *self); static void create_flag_buttons (BzPreferencesDialog *self); static void bz_preferences_dialog_dispose (GObject *object) { BzPreferencesDialog *self = BZ_PREFERENCES_DIALOG (object); g_clear_object (&self->state); g_clear_object (&self->settings); G_OBJECT_CLASS (bz_preferences_dialog_parent_class)->dispose (object); } static void flag_button_toggled (GtkToggleButton *button, BzPreferencesDialog *self) { const char *theme_id = NULL; if (!gtk_toggle_button_get_active (button)) return; theme_id = g_object_get_data (G_OBJECT (button), "theme-id"); if (theme_id != NULL) { g_settings_set_string (self->settings, "global-progress-bar-theme", theme_id); } } static void global_progress_theme_settings_changed (BzPreferencesDialog *self, const char *key, GSettings *settings) { const char *theme = NULL; theme = g_settings_get_string (self->settings, "global-progress-bar-theme"); for (guint i = 0; i < G_N_ELEMENTS (bar_themes); i++) { if (g_strcmp0 (theme, bar_themes[i].id) == 0) { gtk_toggle_button_set_active (self->flag_buttons[i], TRUE); break; } } } static void on_rotate_switch_changed (AdwSwitchRow *row, GParamSpec *pspec, BzPreferencesDialog *self) { gboolean active = FALSE; active = adw_switch_row_get_active (row); for (guint i = 0; i < G_N_ELEMENTS (bar_themes); i++) { if (active) gtk_widget_add_css_class (GTK_WIDGET (self->flag_buttons[i]), "horizontal"); else gtk_widget_remove_css_class (GTK_WIDGET (self->flag_buttons[i]), "horizontal"); } } static void create_flag_buttons (BzPreferencesDialog *self) { GtkToggleButton *first_button = NULL; for (guint i = 0; i < G_N_ELEMENTS (bar_themes); i++) { GtkToggleButton *button = NULL; button = GTK_TOGGLE_BUTTON (gtk_toggle_button_new ()); gtk_widget_set_tooltip_text (GTK_WIDGET (button), Q_ (bar_themes[i].tooltip)); gtk_widget_add_css_class (GTK_WIDGET (button), "accent-button"); gtk_widget_add_css_class (GTK_WIDGET (button), bar_themes[i].style_class); g_object_set_data_full (G_OBJECT (button), "theme-id", g_strdup (bar_themes[i].id), g_free); if (i == 0) { first_button = button; } else { gtk_toggle_button_set_group (button, first_button); } g_signal_connect (button, "toggled", G_CALLBACK (flag_button_toggled), self); self->flag_buttons[i] = button; gtk_flow_box_append (self->flag_buttons_box, GTK_WIDGET (button)); } } static void bind_settings (BzPreferencesDialog *self) { if (self->settings == NULL) return; /* Bind all boolean settings to their respective switches */ g_settings_bind (self->settings, "show-only-foss", self->only_foss_switch, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (self->settings, "show-only-flathub", self->only_flathub_switch, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (self->settings, "show-only-verified", self->only_verified_switch, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (self->settings, "search-debounce", self->search_debounce_switch, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (self->settings, "hide-eol", self->hide_eol_switch, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind (self->settings, "rotate-flag", self->rotate_switch, "active", G_SETTINGS_BIND_DEFAULT); if (adw_switch_row_get_active (self->rotate_switch)) { for (guint i = 0; i < G_N_ELEMENTS (bar_themes); i++) { gtk_widget_add_css_class (GTK_WIDGET (self->flag_buttons[i]), "horizontal"); } } g_signal_connect_object ( self->settings, "changed::global-progress-bar-theme", G_CALLBACK (global_progress_theme_settings_changed), self, G_CONNECT_SWAPPED); global_progress_theme_settings_changed (self, "global-progress-bar-theme", self->settings); } static void bz_preferences_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzPreferencesDialog *self = BZ_PREFERENCES_DIALOG (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, self->state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_preferences_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_STATE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static void bz_preferences_dialog_class_init (BzPreferencesDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_preferences_dialog_set_property; object_class->get_property = bz_preferences_dialog_get_property; object_class->dispose = bz_preferences_dialog_dispose; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-preferences-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, only_foss_switch); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, only_flathub_switch); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, only_verified_switch); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, search_debounce_switch); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, flag_buttons_box); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, hide_eol_switch); gtk_widget_class_bind_template_child (widget_class, BzPreferencesDialog, rotate_switch); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, on_rotate_switch_changed); } static void bz_preferences_dialog_init (BzPreferencesDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); create_flag_buttons (self); } AdwDialog * bz_preferences_dialog_new (BzStateInfo *state) { BzPreferencesDialog *dialog = NULL; g_return_val_if_fail (BZ_IS_STATE_INFO (state), NULL); dialog = g_object_new (BZ_TYPE_PREFERENCES_DIALOG, NULL); dialog->state = g_object_ref (state); g_object_get (state, "settings", &dialog->settings, NULL); bind_settings (dialog); return ADW_DIALOG (dialog); } kolunmi-bazaar-7b9c8e1/src/bz-preferences-dialog.h000066400000000000000000000021151514314607700221700ustar00rootroot00000000000000/* bz-preferences-dialog.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_PREFERENCES_DIALOG (bz_preferences_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzPreferencesDialog, bz_preferences_dialog, BZ, PREFERENCES_DIALOG, AdwPreferencesDialog) AdwDialog * bz_preferences_dialog_new (BzStateInfo *state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-pride-flag-config.txt000066400000000000000000000003401514314607700222750ustar00rootroot00000000000000prefix=bz name=pride_flag_config parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-pride-flag-spec.h" ensure=BZ_TYPE_PRIDE_FLAG_SPEC property=flag_specs GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-pride-flag-spec.txt000066400000000000000000000006311514314607700217650ustar00rootroot00000000000000prefix=bz name=pride_flag_spec parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-pride-flag-stripe-spec.h" ensure=BZ_TYPE_PRIDE_FLAG_STRIPE_SPEC property=id char G_TYPE_STRING string property=name char G_TYPE_STRING string property=homogeneous gboolean G_TYPE_BOOLEAN boolean property=direction char G_TYPE_STRING string property=stripes GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-pride-flag-stripe-spec.txt000066400000000000000000000003001514314607700232620ustar00rootroot00000000000000prefix=bz name=pride_flag_stripe_spec parent-prefix=g parent-name=object author=AUTOGEN include= property=rgba char G_TYPE_STRING string property=size double G_TYPE_DOUBLE double kolunmi-bazaar-7b9c8e1/src/bz-progress-bar.blp000066400000000000000000000001371514314607700213700ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzProgressBar: Adw.Bin { child: ProgressBar bar {}; } kolunmi-bazaar-7b9c8e1/src/bz-progress-bar.c000066400000000000000000000116541514314607700210430ustar00rootroot00000000000000/* bz-progress-bar.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-progress-bar.h" struct _BzProgressBar { AdwBin parent_instance; double fraction; AdwAnimation *animation; /* Template widgets */ GtkProgressBar *bar; }; G_DEFINE_FINAL_TYPE (BzProgressBar, bz_progress_bar, ADW_TYPE_BIN) enum { PROP_0, PROP_FRACTION, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_progress_bar_dispose (GObject *object) { BzProgressBar *self = BZ_PROGRESS_BAR (object); g_clear_object (&self->animation); G_OBJECT_CLASS (bz_progress_bar_parent_class)->dispose (object); } static void bz_progress_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzProgressBar *self = BZ_PROGRESS_BAR (object); switch (prop_id) { case PROP_FRACTION: g_value_set_double (value, bz_progress_bar_get_fraction (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_progress_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzProgressBar *self = BZ_PROGRESS_BAR (object); switch (prop_id) { case PROP_FRACTION: bz_progress_bar_set_fraction (self, g_value_get_double (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_progress_bar_class_init (BzProgressBarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_progress_bar_dispose; object_class->get_property = bz_progress_bar_get_property; object_class->set_property = bz_progress_bar_set_property; props[PROP_FRACTION] = g_param_spec_double ( "fraction", NULL, NULL, 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-progress-bar.ui"); gtk_widget_class_bind_template_child (widget_class, BzProgressBar, bar); } static void bz_progress_bar_init (BzProgressBar *self) { AdwAnimationTarget *target = NULL; AdwSpringParams *spring = NULL; gtk_widget_init_template (GTK_WIDGET (self)); target = adw_property_animation_target_new (G_OBJECT (self->bar), "fraction"); spring = adw_spring_params_new (1.0, 0.5, 200.0); self->animation = adw_spring_animation_new ( GTK_WIDGET (self), 0.0, 0.0, spring, target); adw_spring_animation_set_epsilon ( ADW_SPRING_ANIMATION (self->animation), 0.00025); } GtkWidget * bz_progress_bar_new (void) { return g_object_new (BZ_TYPE_PROGRESS_BAR, NULL); } void bz_progress_bar_set_fraction (BzProgressBar *self, double fraction) { double last = 0.0; double current = 0.0; g_return_if_fail (BZ_IS_PROGRESS_BAR (self)); last = self->fraction; self->fraction = CLAMP (fraction, 0.0, 1.0); current = gtk_progress_bar_get_fraction (self->bar); if (self->fraction < last || G_APPROX_VALUE (last, self->fraction, 0.001)) { adw_animation_reset (self->animation); gtk_progress_bar_set_fraction (self->bar, self->fraction); } else { adw_spring_animation_set_value_from ( ADW_SPRING_ANIMATION (self->animation), current); adw_spring_animation_set_value_to ( ADW_SPRING_ANIMATION (self->animation), self->fraction); adw_spring_animation_set_initial_velocity ( ADW_SPRING_ANIMATION (self->animation), adw_spring_animation_get_velocity ( ADW_SPRING_ANIMATION (self->animation))); adw_animation_play (self->animation); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FRACTION]); } double bz_progress_bar_get_fraction (BzProgressBar *self) { g_return_val_if_fail (BZ_IS_PROGRESS_BAR (self), 0.0); return self->fraction; } kolunmi-bazaar-7b9c8e1/src/bz-progress-bar.h000066400000000000000000000022301514314607700210360ustar00rootroot00000000000000/* bz-progress-bar.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_PROGRESS_BAR (bz_progress_bar_get_type ()) G_DECLARE_FINAL_TYPE (BzProgressBar, bz_progress_bar, BZ, PROGRESS_BAR, AdwBin) GtkWidget * bz_progress_bar_new (void); void bz_progress_bar_set_fraction (BzProgressBar *self, double fraction); double bz_progress_bar_get_fraction (BzProgressBar *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-release.txt000066400000000000000000000004201514314607700204370ustar00rootroot00000000000000prefix=bz name=release parent-prefix=g parent-name=object author=AUTOGEN include= property=description char G_TYPE_STRING string property=timestamp guint64 G_TYPE_UINT64 uint64 property=url char G_TYPE_STRING string property=version char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-releases-dialog.blp000066400000000000000000000013031514314607700220160ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzReleasesDialog: Adw.Dialog { title: _("Version History"); content-width: 550; content-height: 600; child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: true; } content: ScrolledWindow { propagate-natural-height: true; vexpand: true; hscrollbar-policy: never; child: Adw.Clamp { maximum-size: 500; tightening-threshold: 600; margin-top: 24; margin-bottom: 24; margin-start: 12; margin-end: 12; child: ListBox releases_box { styles ["boxed-list"] valign: start; selection-mode: none; }; }; }; }; }kolunmi-bazaar-7b9c8e1/src/bz-releases-list.blp000066400000000000000000000012441514314607700215360ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; using Gio 2.0; template $BzReleasesList: Adw.Bin { visible: bind $invert_boolean($is_zero(template.version-history as .n-items) as ) as ; child: Box { orientation: vertical; spacing: 12; ListBox preview_box { styles [ "boxed-list", ] selection-mode: none; valign: start; } ListBox show_all_box { visible: false; styles [ "boxed-list", ] selection-mode: none; Adw.ButtonRow { title: _("Version History"); activated => $show_all_releases_cb(); end-icon-name: "go-next-symbolic"; } } }; } kolunmi-bazaar-7b9c8e1/src/bz-releases-list.c000066400000000000000000000445061514314607700212130ustar00rootroot00000000000000/* bz-releases-list.c * * Copyright 2025 Alexander Vanhee, Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-appstream-description-render.h" #include "bz-fading-clamp.h" #include "bz-release.h" #include "bz-releases-list.h" #include "bz-template-callbacks.h" /* Dialog structure */ typedef struct { /* Template widgets */ AdwDialog parent_instance; GtkListBox *releases_box; GListModel *installed_versions; } BzReleasesDialog; typedef struct { AdwDialogClass parent_class; } BzReleasesDialogClass; static GType bz_releases_dialog_get_type (void) G_GNUC_CONST; G_DEFINE_TYPE (BzReleasesDialog, bz_releases_dialog, ADW_TYPE_DIALOG) /* Main widget structure */ struct _BzReleasesList { AdwBin parent_instance; GListModel *version_history; GListModel *installed_versions; /* Template widgets */ GtkListBox *preview_box; GtkBox *show_all_box; }; G_DEFINE_FINAL_TYPE (BzReleasesList, bz_releases_list, ADW_TYPE_BIN) enum { PROP_0, PROP_VERSION_HISTORY, PROP_INSTALLED_VERSIONS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static gboolean is_version_installed (GListModel *installed_versions, const char *version) { guint n_items = 0; if (!installed_versions || !version) return FALSE; n_items = g_list_model_get_n_items (installed_versions); for (guint i = 0; i < n_items; i++) { g_autoptr (GObject) item = NULL; item = g_list_model_get_item (installed_versions, i); if (GTK_IS_STRING_OBJECT (item)) { const char *installed_version = NULL; installed_version = gtk_string_object_get_string (GTK_STRING_OBJECT (item)); if (installed_version != NULL && g_strcmp0 (installed_version, version) == 0) return TRUE; } } return FALSE; } static char * format_timestamp (gpointer object, guint64 value) { g_autoptr (GDateTime) date = NULL; g_autoptr (GDateTime) now = NULL; if (value == 0) return NULL; date = g_date_time_new_from_unix_utc (value); now = g_date_time_new_now_local (); if (date == NULL || now == NULL) return NULL; if (g_date_time_get_year (date) == g_date_time_get_year (now)) /* Translators: This is a date format for timestamps from previous years. Used in the app releases section. * %B is the full month name, %e is the day, %Y is the year. * Example: "October 1, 2025" * See https://docs.gtk.org/glib/method.DateTime.format.html for format options * Please modify to make it sound natural in your locale. * */ return g_date_time_format (date, "%e %B"); else /* Translators: This is a date format for timestamps from the current year. Used in the app releases section. * %B is the full month name, %e is the day. * Example: "October 1" * See https://docs.gtk.org/glib/method.DateTime.format.html for format options * Please modify to make it sound natural in your locale. * */ return g_date_time_format (date, "%e %B %Y"); } static GtkWidget * create_release_row (const char *version, const char *description, guint64 timestamp, const char *url, gboolean use_clamp, GListModel *installed_versions) { AdwActionRow *row = NULL; GtkBox *content_box = NULL; GtkBox *header_box = NULL; GtkLabel *version_label = NULL; GtkLabel *date_label = NULL; GtkLabel *installed_label = NULL; BzAppstreamDescriptionRender *description_widget = NULL; BzFadingClamp *fading_clamp = NULL; GtkBox *more_info_box = NULL; GtkLabel *more_info_label = NULL; GtkImage *more_info_icon = NULL; g_autofree char *date_str = NULL; g_autofree char *version_text = NULL; g_autofree char *markup = NULL; date_str = format_timestamp (NULL, timestamp); row = ADW_ACTION_ROW (adw_action_row_new ()); gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); content_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 3)); gtk_widget_set_margin_top (GTK_WIDGET (content_box), 15); gtk_widget_set_margin_bottom (GTK_WIDGET (content_box), 15); gtk_widget_set_margin_start (GTK_WIDGET (content_box), 15); gtk_widget_set_margin_end (GTK_WIDGET (content_box), 15); header_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8)); version_text = g_strdup_printf (_ ("Version %s"), version); version_label = GTK_LABEL (gtk_label_new (version_text)); gtk_widget_add_css_class (GTK_WIDGET (version_label), "accent"); gtk_widget_add_css_class (GTK_WIDGET (version_label), "heading"); gtk_label_set_ellipsize (version_label, PANGO_ELLIPSIZE_END); gtk_widget_set_halign (GTK_WIDGET (version_label), GTK_ALIGN_START); gtk_box_append (header_box, GTK_WIDGET (version_label)); if (is_version_installed (installed_versions, version)) { installed_label = GTK_LABEL (gtk_label_new (_ ("Installed"))); gtk_widget_add_css_class (GTK_WIDGET (installed_label), "lozenge"); gtk_widget_add_css_class (GTK_WIDGET (installed_label), "small"); gtk_widget_set_halign (GTK_WIDGET (installed_label), GTK_ALIGN_START); gtk_widget_set_hexpand (GTK_WIDGET (installed_label), TRUE); gtk_box_append (header_box, GTK_WIDGET (installed_label)); } else { gtk_widget_set_hexpand (GTK_WIDGET (version_label), TRUE); } date_label = GTK_LABEL (gtk_label_new (date_str ? date_str : "")); gtk_widget_add_css_class (GTK_WIDGET (date_label), "dim-label"); gtk_widget_set_halign (GTK_WIDGET (date_label), GTK_ALIGN_END); gtk_box_append (header_box, GTK_WIDGET (date_label)); gtk_box_append (content_box, GTK_WIDGET (header_box)); if (description != NULL && *description) { description_widget = bz_appstream_description_render_new (); bz_appstream_description_render_set_appstream_description (description_widget, description); if (use_clamp) { fading_clamp = BZ_FADING_CLAMP (bz_fading_clamp_new ()); bz_fading_clamp_set_max_height (fading_clamp, 270); bz_fading_clamp_set_child (fading_clamp, GTK_WIDGET (description_widget)); gtk_widget_set_margin_top (GTK_WIDGET (fading_clamp), 10); gtk_box_append (content_box, GTK_WIDGET (fading_clamp)); } else { gtk_widget_set_margin_top (GTK_WIDGET (description_widget), 10); gtk_box_append (content_box, GTK_WIDGET (description_widget)); } } else { GtkLabel *fallback_label = NULL; fallback_label = GTK_LABEL (gtk_label_new (_ ("No details for this release"))); gtk_widget_set_margin_top (GTK_WIDGET (fallback_label), 5); gtk_widget_add_css_class (GTK_WIDGET (fallback_label), "dim-label"); gtk_label_set_xalign (fallback_label, 0.0); gtk_label_set_wrap (fallback_label, TRUE); gtk_box_append (content_box, GTK_WIDGET (fallback_label)); } if (!use_clamp && url && *url) { more_info_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4)); markup = g_markup_printf_escaped ("%s", url, _ ("Get More Information")); more_info_label = GTK_LABEL (gtk_label_new (NULL)); gtk_label_set_markup (more_info_label, markup); gtk_box_append (more_info_box, GTK_WIDGET (more_info_label)); more_info_icon = GTK_IMAGE (gtk_image_new_from_icon_name ("external-link-symbolic")); gtk_image_set_pixel_size (more_info_icon, 12); gtk_widget_add_css_class (GTK_WIDGET (more_info_icon), "accent"); gtk_box_append (more_info_box, GTK_WIDGET (more_info_icon)); gtk_box_append (content_box, GTK_WIDGET (more_info_box)); } gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), GTK_WIDGET (content_box)); return GTK_WIDGET (row); } static void bz_releases_dialog_dispose (GObject *object) { BzReleasesDialog *self = (BzReleasesDialog *) object; g_clear_object (&self->installed_versions); G_OBJECT_CLASS (bz_releases_dialog_parent_class)->dispose (object); } static void bz_releases_dialog_class_init (BzReleasesDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_releases_dialog_dispose; gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-releases-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzReleasesDialog, releases_box); } static void bz_releases_dialog_init (BzReleasesDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_releases_dialog_new (GListModel *version_history, GListModel *installed_versions) { BzReleasesDialog *dialog = NULL; guint n_items = 0; dialog = g_object_new (bz_releases_dialog_get_type (), NULL); if (installed_versions) dialog->installed_versions = g_object_ref (installed_versions); if (version_history == NULL) return GTK_WIDGET (dialog); n_items = g_list_model_get_n_items (version_history); for (guint i = 0; i < n_items; i++) { g_autoptr (BzRelease) release = NULL; const char *version = NULL; const char *description = NULL; const char *url = NULL; guint64 timestamp = 0; GtkWidget *row = NULL; release = g_list_model_get_item (version_history, i); if (release == NULL) continue; version = bz_release_get_version (release); description = bz_release_get_description (release); url = bz_release_get_url (release); timestamp = bz_release_get_timestamp (release); row = create_release_row (version, description, timestamp, url, FALSE, dialog->installed_versions); gtk_list_box_append (dialog->releases_box, row); } return GTK_WIDGET (dialog); } static void bz_releases_dialog_set_version_history (BzReleasesDialog *self, GListModel *version_history, GListModel *installed_versions) { guint n_items = 0; GtkWidget *child = NULL; g_return_if_fail (self != NULL); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->releases_box))) != NULL) gtk_list_box_remove (self->releases_box, child); g_clear_object (&self->installed_versions); if (installed_versions) self->installed_versions = g_object_ref (installed_versions); if (version_history == NULL) return; n_items = g_list_model_get_n_items (version_history); for (guint i = 0; i < n_items; i++) { g_autoptr (BzRelease) release = NULL; const char *version = NULL; const char *description = NULL; const char *url = NULL; guint64 timestamp = 0; GtkWidget *row = NULL; release = g_list_model_get_item (version_history, i); if (release == NULL) continue; version = bz_release_get_version (release); description = bz_release_get_description (release); url = bz_release_get_url (release); timestamp = bz_release_get_timestamp (release); row = create_release_row (version, description, timestamp, url, FALSE, self->installed_versions); gtk_list_box_append (self->releases_box, row); } } static void clear_preview_box (BzReleasesList *self) { GtkWidget *child = NULL; g_return_if_fail (BZ_IS_RELEASES_LIST (self)); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->preview_box))) != NULL) { if (child == GTK_WIDGET (self->show_all_box)) break; gtk_list_box_remove (self->preview_box, child); } } static void populate_preview_box (BzReleasesList *self) { guint n_items = 0; g_return_if_fail (BZ_IS_RELEASES_LIST (self)); clear_preview_box (self); if (self->version_history == NULL) { gtk_widget_set_visible (GTK_WIDGET (self->show_all_box), FALSE); return; } n_items = g_list_model_get_n_items (self->version_history); if (n_items == 0) { gtk_widget_set_visible (GTK_WIDGET (self->show_all_box), FALSE); return; } if (n_items > 0) { g_autoptr (BzRelease) release = NULL; const char *version = NULL; const char *description = NULL; guint64 timestamp = 0; GtkWidget *row = NULL; release = g_list_model_get_item (self->version_history, 0); if (release != NULL) { version = bz_release_get_version (release); description = bz_release_get_description (release); timestamp = bz_release_get_timestamp (release); row = create_release_row (version, description, timestamp, NULL, TRUE, self->installed_versions); gtk_list_box_insert (self->preview_box, row, 0); } } gtk_widget_set_visible (GTK_WIDGET (self->show_all_box), n_items > 0); } static void show_all_releases_cb (AdwButtonRow *button, BzReleasesList *self) { GtkWidget *dialog = NULL; GtkRoot *root = NULL; g_return_if_fail (BZ_IS_RELEASES_LIST (self)); root = gtk_widget_get_root (GTK_WIDGET (self)); if (root == NULL) return; dialog = bz_releases_dialog_new (self->version_history, self->installed_versions); adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (root)); } static void bz_releases_list_dispose (GObject *object) { BzReleasesList *self = BZ_RELEASES_LIST (object); g_clear_object (&self->version_history); g_clear_object (&self->installed_versions); G_OBJECT_CLASS (bz_releases_list_parent_class)->dispose (object); } static void bz_releases_list_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzReleasesList *self = BZ_RELEASES_LIST (object); switch (prop_id) { case PROP_VERSION_HISTORY: g_value_set_object (value, self->version_history); break; case PROP_INSTALLED_VERSIONS: g_value_set_object (value, self->installed_versions); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_releases_list_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzReleasesList *self = BZ_RELEASES_LIST (object); switch (prop_id) { case PROP_VERSION_HISTORY: bz_releases_list_set_version_history (self, g_value_get_object (value)); break; case PROP_INSTALLED_VERSIONS: g_clear_object (&self->installed_versions); self->installed_versions = g_value_dup_object (value); populate_preview_box (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_releases_list_class_init (BzReleasesListClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_releases_list_dispose; object_class->get_property = bz_releases_list_get_property; object_class->set_property = bz_releases_list_set_property; props[PROP_VERSION_HISTORY] = g_param_spec_object ("version-history", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_INSTALLED_VERSIONS] = g_param_spec_object ("installed-versions", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_RELEASE); g_type_ensure (BZ_TYPE_APPSTREAM_DESCRIPTION_RENDER); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-releases-list.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzReleasesList, preview_box); gtk_widget_class_bind_template_child (widget_class, BzReleasesList, show_all_box); gtk_widget_class_bind_template_callback (widget_class, show_all_releases_cb); } static void bz_releases_list_init (BzReleasesList *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_releases_list_new (void) { return g_object_new (BZ_TYPE_RELEASES_LIST, NULL); } void bz_releases_list_set_version_history (BzReleasesList *self, GListModel *version_history) { g_return_if_fail (BZ_IS_RELEASES_LIST (self)); g_return_if_fail (version_history == NULL || G_IS_LIST_MODEL (version_history)); if (self->version_history == version_history) return; g_clear_object (&self->version_history); if (version_history != NULL) { self->version_history = g_object_ref (version_history); populate_preview_box (self); } else { clear_preview_box (self); gtk_widget_set_visible (GTK_WIDGET (self->show_all_box), FALSE); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VERSION_HISTORY]); } GListModel * bz_releases_list_get_version_history (BzReleasesList *self) { g_return_val_if_fail (BZ_IS_RELEASES_LIST (self), NULL); return self->version_history; } kolunmi-bazaar-7b9c8e1/src/bz-releases-list.h000066400000000000000000000025251514314607700212130ustar00rootroot00000000000000/* bz-releases-list.h * * Copyright 2025 Alexander Vanhee, Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_RELEASES_LIST (bz_releases_list_get_type ()) G_DECLARE_FINAL_TYPE (BzReleasesList, bz_releases_list, BZ, RELEASES_LIST, AdwBin) GtkWidget * bz_releases_list_new (void); GtkWidget * bz_releases_dialog_new (GListModel *version_history, GListModel *installed_versions); void bz_releases_list_set_version_history (BzReleasesList *self, GListModel *version_history); GListModel * bz_releases_list_get_version_history (BzReleasesList *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-repository.txt000066400000000000000000000003661514314607700212470ustar00rootroot00000000000000prefix=bz name=repository parent-prefix=g parent-name=object author=AUTOGEN property=is_user gboolean G_TYPE_BOOLEAN boolean property=title char G_TYPE_STRING string property=url char G_TYPE_STRING string property=name char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-result.c000066400000000000000000000166661514314607700177630ustar00rootroot00000000000000/* bz-result.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-result.h" struct _BzResult { GObject parent_instance; DexFuture *finally; GObject *object; GError *error; GTimer *timer; char *non_error_msg; }; G_DEFINE_FINAL_TYPE (BzResult, bz_result, G_TYPE_OBJECT); enum { PROP_0, PROP_PENDING, PROP_RESOLVED, PROP_REJECTED, PROP_OBJECT, PROP_MESSAGE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * future_finally (DexFuture *future, BzResult *self); static void bz_result_dispose (GObject *object) { BzResult *self = BZ_RESULT (object); dex_clear (&self->finally); g_clear_object (&self->object); g_clear_pointer (&self->error, g_error_free); g_clear_pointer (&self->timer, g_timer_destroy); g_clear_pointer (&self->non_error_msg, g_free); G_OBJECT_CLASS (bz_result_parent_class)->dispose (object); } static void bz_result_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzResult *self = BZ_RESULT (object); switch (prop_id) { case PROP_PENDING: g_value_set_boolean (value, bz_result_get_pending (self)); break; case PROP_RESOLVED: g_value_set_boolean (value, bz_result_get_resolved (self)); break; case PROP_REJECTED: g_value_set_boolean (value, bz_result_get_rejected (self)); break; case PROP_OBJECT: g_value_set_object (value, bz_result_get_object (self)); break; case PROP_MESSAGE: g_value_set_string (value, bz_result_get_message (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_result_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { // BzResult *self = BZ_RESULT (object); switch (prop_id) { case PROP_PENDING: case PROP_RESOLVED: case PROP_REJECTED: case PROP_OBJECT: case PROP_MESSAGE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_result_class_init (BzResultClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_result_set_property; object_class->get_property = bz_result_get_property; object_class->dispose = bz_result_dispose; props[PROP_PENDING] = g_param_spec_boolean ( "pending", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_RESOLVED] = g_param_spec_boolean ( "resolved", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_REJECTED] = g_param_spec_boolean ( "rejected", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_OBJECT] = g_param_spec_object ( "object", NULL, NULL, G_TYPE_OBJECT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MESSAGE] = g_param_spec_string ( "message", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_result_init (BzResult *self) { } BzResult * bz_result_new (DexFuture *future) { BzResult *self = NULL; DexFutureStatus status = DEX_FUTURE_STATUS_PENDING; g_return_val_if_fail (DEX_IS_FUTURE (future), NULL); self = g_object_new (BZ_TYPE_RESULT, NULL); status = dex_future_get_status (future); switch (status) { case DEX_FUTURE_STATUS_PENDING: self->timer = g_timer_new (); self->finally = dex_future_finally ( dex_ref (future), (DexFutureCallback) future_finally, g_object_ref (self), g_object_unref); break; case DEX_FUTURE_STATUS_RESOLVED: self->object = g_value_dup_object (dex_future_get_value (future, NULL)); self->non_error_msg = g_strdup ("Object was already successfully resolved"); break; case DEX_FUTURE_STATUS_REJECTED: { g_autoptr (GError) local_error = NULL; dex_future_get_value (future, &local_error); self->error = g_error_copy (local_error); } break; default: g_assert_not_reached (); } return self; } gboolean bz_result_get_pending (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), FALSE); return self->finally != NULL; } gboolean bz_result_get_resolved (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), FALSE); return self->object != NULL; } gboolean bz_result_get_rejected (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), FALSE); return self->error != NULL; } gpointer bz_result_get_object (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), NULL); return self->object; } const char * bz_result_get_message (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), NULL); if (self->error != NULL) return self->error->message; else return self->non_error_msg; } DexFuture * bz_result_dup_future (BzResult *self) { g_return_val_if_fail (BZ_IS_RESULT (self), NULL); if (self->finally != NULL) return dex_ref (self->finally); else if (self->object != NULL) return dex_future_new_for_object (self->object); else if (self->error != NULL) return dex_future_new_for_error (g_error_copy (self->error)); else return NULL; } static DexFuture * future_finally (DexFuture *future, BzResult *self) { g_autoptr (GError) local_error = NULL; const GValue *value = NULL; dex_clear (&self->finally); g_timer_stop (self->timer); value = dex_future_get_value (future, &local_error); if (value != NULL) { self->object = g_value_dup_object (value); self->non_error_msg = g_strdup_printf ( "Successfully resolved object in %f seconds", g_timer_elapsed (self->timer, NULL)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_OBJECT]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MESSAGE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESOLVED]); } else { self->error = g_error_copy (local_error); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MESSAGE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REJECTED]); } return dex_ref (future); } /* End of bz-result.c */ kolunmi-bazaar-7b9c8e1/src/bz-result.h000066400000000000000000000024331514314607700177530ustar00rootroot00000000000000/* bz-result.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_RESULT (bz_result_get_type ()) G_DECLARE_FINAL_TYPE (BzResult, bz_result, BZ, RESULT, GObject) BzResult * bz_result_new (DexFuture *future); gboolean bz_result_get_pending (BzResult *self); gboolean bz_result_get_resolved (BzResult *self); gboolean bz_result_get_rejected (BzResult *self); gpointer bz_result_get_object (BzResult *self); const char * bz_result_get_message (BzResult *self); DexFuture * bz_result_dup_future (BzResult *self); G_END_DECLS /* End of bz-result.h */ kolunmi-bazaar-7b9c8e1/src/bz-rich-app-tile.blp000066400000000000000000000104711514314607700214220ustar00rootroot00000000000000using Gtk 4.0; template $BzRichAppTile: $BzListTile { overflow: hidden; accessibility { labelled-by: title; described-by: description; } child: Box { orientation: vertical; styles [ "rich-tile-card", ] $BzThemedEntryGroupRect picture_box { height-request: 200; styles [ "rich-screenshot-box", ] group: bind template.group as <$BzEntryGroup>; child: Box { margin-start: 12; margin-end: 12; margin-top: 12; margin-bottom: 12; Image { icon-name: "image-missing-symbolic"; pixel-size: 96; halign: center; valign: center; hexpand: true; visible: bind $is_null(template.ui-entry as <$BzEntry>.thumbnail-paintable) as ; } $BzRoundedPicture { halign: center; hexpand: true; valign: center; paintable: bind template.ui-entry as <$BzEntry>.thumbnail-paintable; radius: 6; visible: bind $invert_boolean($is_null(template.ui-entry as <$BzEntry>.thumbnail-paintable) as ) as ; } }; } Box { margin-start: 12; margin-end: 12; margin-top: 12; margin-bottom: 12; orientation: horizontal; spacing: 15; Image { pixel-size: 64; paintable: bind template.group as <$BzEntryGroup>.icon-paintable; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.icon-paintable) as ) as ; styles [ "icon-dropshadow", ] } Box { valign: center; hexpand: true; orientation: vertical; spacing: 5; Box { spacing: 6; Label title { css-name: "app-tile-title"; styles [ "heading", ] xalign: 0.0; ellipsize: end; label: bind template.group as <$BzEntryGroup>.title; max-width-chars: 18; } Image { styles [ "verified", ] visible: bind template.group as <$BzEntryGroup>.is-verified; icon-name: "verified-checkmark-symbolic"; pixel-size: 14; } } Label description { visible: bind $is_null(template.group as <$BzEntryGroup>.eol) as ; css-name: "app-tile-description"; xalign: 0.0; yalign: 0.0; wrap: true; wrap-mode: word_char; ellipsize: end; vexpand: true; lines: 2; max-width-chars: 15; single-line-mode: true; label: bind template.group as <$BzEntryGroup>.description; styles [ "dimmed", ] } Label { visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.eol) as ) as ; css-name: "app-tile-description"; xalign: 0.0; yalign: 0.0; wrap: true; wrap-mode: word_char; ellipsize: end; vexpand: true; lines: 2; max-width-chars: 15; single-line-mode: true; label: _("Stopped Receiving Updates"); styles [ "warning", ] } } Box { Button { visible: bind $logical_and($invert_boolean($is_zero(template.group as <$BzEntryGroup>.installable) as ) as , $is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.installable-and-available) as ) as ; styles [ "medium-pill", ] label: _("Get"); valign: center; clicked => $install_button_clicked_cb(template); } Button { visible: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable) as ) as ; sensitive: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.removable-and-available) as ) as ; styles [ "circular" ] icon-name: "user-trash-symbolic"; valign: center; clicked => $install_button_clicked_cb(template); } } } }; } kolunmi-bazaar-7b9c8e1/src/bz-rich-app-tile.c000066400000000000000000000156711514314607700210760ustar00rootroot00000000000000/* bz-rich-app-tile.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-rich-app-tile.h" #include "bz-entry.h" #include "bz-rounded-picture.h" #include "bz-themed-entry-group-rect.h" #include "bz-util.h" struct _BzRichAppTile { BzListTile parent_instance; BzEntryGroup *group; BzEntry *ui_entry; DexFuture *ui_entry_resolve; GtkWidget *picture_box; }; G_DEFINE_FINAL_TYPE (BzRichAppTile, bz_rich_app_tile, BZ_TYPE_LIST_TILE); enum { PROP_0, PROP_GROUP, PROP_UI_ENTRY, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_INSTALL_CLICKED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL]; static void update_ui_entry (BzRichAppTile *self); static DexFuture * ui_entry_resolved_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzRichAppTile) self = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, wr); value = dex_future_get_value (future, NULL); if (value != NULL) { BzEntry *ui_entry = g_value_get_object (value); g_set_object (&self->ui_entry, ui_entry); } else { g_clear_object (&self->ui_entry); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_UI_ENTRY]); return NULL; } static void update_ui_entry (BzRichAppTile *self) { g_autoptr (BzResult) ui_entry_result = NULL; dex_clear (&self->ui_entry_resolve); if (self->ui_entry != NULL) { g_clear_object (&self->ui_entry); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_UI_ENTRY]); } ui_entry_result = bz_entry_group_dup_ui_entry (self->group); self->ui_entry_resolve = dex_future_finally ( bz_result_dup_future (ui_entry_result), (DexFutureCallback) ui_entry_resolved_finally, bz_track_weak (self), bz_weak_release); } static void bz_rich_app_tile_dispose (GObject *object) { BzRichAppTile *self = BZ_RICH_APP_TILE (object); g_clear_object (&self->group); g_clear_object (&self->ui_entry); dex_clear (&self->ui_entry_resolve); G_OBJECT_CLASS (bz_rich_app_tile_parent_class)->dispose (object); } static void bz_rich_app_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzRichAppTile *self = BZ_RICH_APP_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_rich_app_tile_get_group (self)); break; case PROP_UI_ENTRY: g_value_set_object (value, self->ui_entry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_rich_app_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzRichAppTile *self = BZ_RICH_APP_TILE (object); switch (prop_id) { case PROP_GROUP: bz_rich_app_tile_set_group (self, g_value_get_object (value)); break; case PROP_UI_ENTRY: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean logical_and (gpointer object, gboolean value1, gboolean value2) { return value1 && value2; } static void install_button_clicked_cb (BzRichAppTile *self, GtkButton *button) { g_signal_emit (self, signals[SIGNAL_INSTALL_CLICKED], 0); } static void bz_rich_app_tile_class_init (BzRichAppTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_rich_app_tile_set_property; object_class->get_property = bz_rich_app_tile_get_property; object_class->dispose = bz_rich_app_tile_dispose; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_UI_ENTRY] = g_param_spec_object ( "ui-entry", NULL, NULL, BZ_TYPE_ENTRY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_INSTALL_CLICKED] = g_signal_new ( "install-clicked", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); g_type_ensure (BZ_TYPE_LIST_TILE); g_type_ensure (BZ_TYPE_ROUNDED_PICTURE); g_type_ensure (BZ_TYPE_THEMED_ENTRY_GROUP_RECT); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-rich-app-tile.ui"); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, logical_and); gtk_widget_class_bind_template_callback (widget_class, install_button_clicked_cb); gtk_widget_class_bind_template_child (widget_class, BzRichAppTile, picture_box); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_rich_app_tile_init (BzRichAppTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_rich_app_tile_new (void) { return g_object_new (BZ_TYPE_RICH_APP_TILE, NULL); } BzEntryGroup * bz_rich_app_tile_get_group (BzRichAppTile *self) { g_return_val_if_fail (BZ_IS_RICH_APP_TILE (self), NULL); return self->group; } void bz_rich_app_tile_set_group (BzRichAppTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_RICH_APP_TILE (self)); g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); update_ui_entry (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } /* End of bz-rich-app-tile.c */ kolunmi-bazaar-7b9c8e1/src/bz-rich-app-tile.h000066400000000000000000000024401514314607700210710ustar00rootroot00000000000000/* bz-rich-app-tile.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "adwaita.h" #include #include "bz-entry-group.h" #include "bz-list-tile.h" G_BEGIN_DECLS #define BZ_TYPE_RICH_APP_TILE (bz_rich_app_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzRichAppTile, bz_rich_app_tile, BZ, RICH_APP_TILE, BzListTile) GtkWidget * bz_rich_app_tile_new (void); BzEntryGroup * bz_rich_app_tile_get_group (BzRichAppTile *self); void bz_rich_app_tile_set_group (BzRichAppTile *self, BzEntryGroup *group); G_END_DECLS /* End of bz-rich-app-tile.h */ kolunmi-bazaar-7b9c8e1/src/bz-root-blocklist.txt000066400000000000000000000003211514314607700217660ustar00rootroot00000000000000prefix=bz name=root_blocklist parent-prefix=g parent-name=object author=AUTOGEN include= include="bz-blocklist.h" ensure=BZ_TYPE_BLOCKLIST property=blocklists GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-root-curated-config.txt000066400000000000000000000004021514314607700226720ustar00rootroot00000000000000prefix=bz name=root_curated_config parent-prefix=g parent-name=object author=AUTOGEN include="bz-curated-row.h" property=css char G_TYPE_STRING string property=templates GListModel G_TYPE_LIST_MODEL object property=rows GListModel G_TYPE_LIST_MODEL object kolunmi-bazaar-7b9c8e1/src/bz-rounded-picture.c000066400000000000000000000216441514314607700215460ustar00rootroot00000000000000/* bz-rounded-picture.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-rounded-picture.h" struct _BzRoundedPicture { GtkWidget parent_instance; GdkPaintable *paintable; double radius; }; G_DEFINE_FINAL_TYPE (BzRoundedPicture, bz_rounded_picture, GTK_TYPE_WIDGET) enum { PROP_0, PROP_PAINTABLE, PROP_RADIUS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { NULL }; static void invalidate_contents (BzRoundedPicture *self, GdkPaintable *paintable) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void invalidate_size (BzRoundedPicture *self, GdkPaintable *paintable) { gtk_widget_queue_resize (GTK_WIDGET (self)); } static void bz_rounded_picture_dispose (GObject *object) { BzRoundedPicture *self = BZ_ROUNDED_PICTURE (object); if (self->paintable != NULL) { g_signal_handlers_disconnect_by_func (self->paintable, invalidate_contents, self); g_signal_handlers_disconnect_by_func (self->paintable, invalidate_size, self); } g_clear_object (&self->paintable); G_OBJECT_CLASS (bz_rounded_picture_parent_class)->dispose (object); } static void bz_rounded_picture_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzRoundedPicture *self = BZ_ROUNDED_PICTURE (object); switch (prop_id) { case PROP_PAINTABLE: g_value_set_object (value, self->paintable); break; case PROP_RADIUS: g_value_set_double (value, self->radius); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_rounded_picture_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzRoundedPicture *self = BZ_ROUNDED_PICTURE (object); switch (prop_id) { case PROP_PAINTABLE: bz_rounded_picture_set_paintable (self, g_value_get_object (value)); break; case PROP_RADIUS: bz_rounded_picture_set_radius (self, g_value_get_double (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_rounded_picture_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzRoundedPicture *self = BZ_ROUNDED_PICTURE (widget); *minimum = 0; *natural = 0; if (self->paintable == NULL) return; if (orientation == GTK_ORIENTATION_HORIZONTAL) { *natural = gdk_paintable_get_intrinsic_width (self->paintable); } else { *natural = gdk_paintable_get_intrinsic_height (self->paintable); } } static void bz_rounded_picture_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzRoundedPicture *self = BZ_ROUNDED_PICTURE (widget); int widget_width; int widget_height; double paintable_width; double paintable_height; double paintable_aspect; double widget_aspect; double scale; double draw_width, draw_height; double x, y; GskRoundedRect rect; GskShadow shadow; if (self->paintable == NULL) return; widget_width = gtk_widget_get_width (widget); widget_height = gtk_widget_get_height (widget); if (widget_width <= 0 || widget_height <= 0) return; paintable_width = gdk_paintable_get_intrinsic_width (self->paintable); paintable_height = gdk_paintable_get_intrinsic_height (self->paintable); if (paintable_width <= 0 || paintable_height <= 0) { paintable_width = widget_width; paintable_height = widget_height; } paintable_aspect = paintable_width / paintable_height; widget_aspect = (double) widget_width / (double) widget_height; if (widget_aspect > paintable_aspect) { scale = (double) widget_height / paintable_height; draw_height = widget_height; draw_width = paintable_width * scale; } else { scale = (double) widget_width / paintable_width; draw_width = widget_width; draw_height = paintable_height * scale; } x = (widget_width - draw_width) / 2.0; y = (widget_height - draw_height) / 2.0; shadow.color.red = 0.0; shadow.color.green = 0.0; shadow.color.blue = 0.0; shadow.color.alpha = 0.35; shadow.dx = 0.0; shadow.dy = 2.0; shadow.radius = 16.0; gtk_snapshot_push_shadow (snapshot, &shadow, 1); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); gsk_rounded_rect_init_from_rect (&rect, &GRAPHENE_RECT_INIT (0, 0, draw_width, draw_height), self->radius); gtk_snapshot_push_rounded_clip (snapshot, &rect); gdk_paintable_snapshot (self->paintable, snapshot, draw_width, draw_height); gtk_snapshot_pop (snapshot); gtk_snapshot_pop (snapshot); } static void bz_rounded_picture_class_init (BzRoundedPictureClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_rounded_picture_dispose; object_class->get_property = bz_rounded_picture_get_property; object_class->set_property = bz_rounded_picture_set_property; widget_class->measure = bz_rounded_picture_measure; widget_class->snapshot = bz_rounded_picture_snapshot; props[PROP_PAINTABLE] = g_param_spec_object ("paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_RADIUS] = g_param_spec_double ("radius", NULL, NULL, 0.0, G_MAXDOUBLE, 12.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_rounded_picture_init (BzRoundedPicture *self) { self->radius = 12.0; } GtkWidget * bz_rounded_picture_new (void) { return g_object_new (BZ_TYPE_ROUNDED_PICTURE, NULL); } void bz_rounded_picture_set_paintable (BzRoundedPicture *self, GdkPaintable *paintable) { g_return_if_fail (BZ_IS_ROUNDED_PICTURE (self)); g_return_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable)); if (self->paintable == paintable) return; if (self->paintable != NULL) { g_signal_handlers_disconnect_by_func (self->paintable, invalidate_contents, self); g_signal_handlers_disconnect_by_func (self->paintable, invalidate_size, self); } g_clear_object (&self->paintable); if (paintable != NULL) { self->paintable = g_object_ref (paintable); g_signal_connect_swapped (self->paintable, "invalidate-contents", G_CALLBACK (invalidate_contents), self); g_signal_connect_swapped (self->paintable, "invalidate-size", G_CALLBACK (invalidate_size), self); } gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PAINTABLE]); } GdkPaintable * bz_rounded_picture_get_paintable (BzRoundedPicture *self) { g_return_val_if_fail (BZ_IS_ROUNDED_PICTURE (self), NULL); return self->paintable; } void bz_rounded_picture_set_radius (BzRoundedPicture *self, double radius) { g_return_if_fail (BZ_IS_ROUNDED_PICTURE (self)); if (self->radius == radius) return; self->radius = radius; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RADIUS]); } double bz_rounded_picture_get_radius (BzRoundedPicture *self) { g_return_val_if_fail (BZ_IS_ROUNDED_PICTURE (self), 0.0); return self->radius; } kolunmi-bazaar-7b9c8e1/src/bz-rounded-picture.h000066400000000000000000000026111514314607700215440ustar00rootroot00000000000000/* bz-rounded-picture.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_ROUNDED_PICTURE (bz_rounded_picture_get_type ()) G_DECLARE_FINAL_TYPE (BzRoundedPicture, bz_rounded_picture, BZ, ROUNDED_PICTURE, GtkWidget) GtkWidget * bz_rounded_picture_new (void); void bz_rounded_picture_set_paintable (BzRoundedPicture *self, GdkPaintable *paintable); GdkPaintable * bz_rounded_picture_get_paintable (BzRoundedPicture *self); void bz_rounded_picture_set_radius (BzRoundedPicture *self, double radius); double bz_rounded_picture_get_radius (BzRoundedPicture *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-row-view.blp000066400000000000000000000006051514314607700205410ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzRowView: Adw.Bin { child: $BzDynamicListView { hexpand: true; scroll: false; noscroll-kind: h-box; child-type: "BzSectionView"; child-prop: "section"; bind-widget => $bind_section_view_cb(template); unbind-widget => $unbind_section_view_cb(template); model: bind template.row as <$BzCuratedRow>.sections; }; } kolunmi-bazaar-7b9c8e1/src/bz-row-view.c000066400000000000000000000122261514314607700202100ustar00rootroot00000000000000/* bz-row-view.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-row-view.h" #include "bz-curated-view.h" #include "bz-dynamic-list-view.h" #include "bz-section-view.h" struct _BzRowView { AdwBin parent_instance; BzCuratedRow *row; /* Template widgets */ }; G_DEFINE_FINAL_TYPE (BzRowView, bz_row_view, ADW_TYPE_BIN) enum { PROP_0, PROP_ROW, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_row_view_dispose (GObject *object) { BzRowView *self = BZ_ROW_VIEW (object); g_clear_object (&self->row); G_OBJECT_CLASS (bz_row_view_parent_class)->dispose (object); } static void bz_row_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzRowView *self = BZ_ROW_VIEW (object); switch (prop_id) { case PROP_ROW: g_value_set_object (value, bz_row_view_get_row (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_row_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzRowView *self = BZ_ROW_VIEW (object); switch (prop_id) { case PROP_ROW: bz_row_view_set_row (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static void group_activated_cb (GtkListItem *list_item, BzEntryGroup *group, BzRowView *view) { GtkWidget *self = NULL; self = gtk_widget_get_ancestor (GTK_WIDGET (view), BZ_TYPE_CURATED_VIEW); g_assert (self != NULL); g_signal_emit_by_name (self, "group-selected", group); } static void bind_section_view_cb (GtkListItem *list_item, BzSectionView *section_view, BzCuratedSection *section, BzDynamicListView *view) { g_signal_connect_swapped (section_view, "group-activated", G_CALLBACK (group_activated_cb), list_item); } static void unbind_section_view_cb (GtkListItem *list_item, BzSectionView *section_view, BzCuratedSection *section, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (section_view, group_activated_cb, list_item); } static void bz_row_view_class_init (BzRowViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_row_view_dispose; object_class->get_property = bz_row_view_get_property; object_class->set_property = bz_row_view_set_property; props[PROP_ROW] = g_param_spec_object ( "row", NULL, NULL, BZ_TYPE_CURATED_ROW, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_SECTION_VIEW); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-row-view.ui"); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, bind_section_view_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_section_view_cb); } static void bz_row_view_init (BzRowView *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_row_view_new (BzCuratedRow *row) { return g_object_new ( BZ_TYPE_ROW_VIEW, "row", row, NULL); } void bz_row_view_set_row (BzRowView *self, BzCuratedRow *row) { g_return_if_fail (BZ_IS_ROW_VIEW (self)); g_return_if_fail (row == NULL || BZ_IS_CURATED_ROW (row)); g_clear_object (&self->row); if (row != NULL) self->row = g_object_ref (row); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ROW]); } BzCuratedRow * bz_row_view_get_row (BzRowView *self) { g_return_val_if_fail (BZ_IS_ROW_VIEW (self), NULL); return self->row; } kolunmi-bazaar-7b9c8e1/src/bz-row-view.h000066400000000000000000000022201514314607700202060ustar00rootroot00000000000000/* bz-row-view.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-curated-row.h" G_BEGIN_DECLS #define BZ_TYPE_ROW_VIEW (bz_row_view_get_type ()) G_DECLARE_FINAL_TYPE (BzRowView, bz_row_view, BZ, ROW_VIEW, AdwBin) GtkWidget * bz_row_view_new (BzCuratedRow *row); void bz_row_view_set_row (BzRowView *self, BzCuratedRow *row); BzCuratedRow * bz_row_view_get_row (BzRowView *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-safety-calculator.c000066400000000000000000000627711514314607700220650ustar00rootroot00000000000000/* bz-safety-calculator.c * * Copyright 2026 Alexander Vanhee * Copyright (C) 2022 Red Hat * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-app-permissions.h" #include "bz-context-row.h" #include "bz-safety-calculator.h" #include "bz-safety-row.h" static char * format_bus_policy_title (const BzBusPolicy *bus_policy); static const char * format_bus_policy_subtitle (const BzBusPolicy *bus_policy); static void add_row_if_permission (GListStore *store, gboolean has_permission, BzImportance item_rating, const char *icon_name_with_permission, const char *title_with_permission, const char *description_with_permission, const char *icon_name_without_permission, const char *title_without_permission, const char *description_without_permission); static gboolean lookup_well_known_bus_policy (const char *bus_name, const char **out_title, const char **out_description); GListModel * bz_safety_calculator_analyze_entry (BzEntry *entry) { GListStore *store = NULL; BzAppPermissions *permissions = NULL; BzAppPermissionsFlags perm_flags = BZ_APP_PERMISSIONS_FLAGS_NONE; gboolean is_verified = FALSE; gboolean is_foss = FALSE; const GPtrArray *filesystem_read = NULL; const GPtrArray *filesystem_full = NULL; const BzBusPolicy *const *bus_policies = NULL; size_t n_bus_policies = 0; gboolean has_system_tray = FALSE; guint i = 0; g_return_val_if_fail (BZ_IS_ENTRY (entry), NULL); store = g_list_store_new (BZ_TYPE_SAFETY_ROW); is_verified = bz_entry_is_verified (entry); is_foss = bz_entry_get_is_foss (entry); g_object_get (entry, "permissions", &permissions, NULL); if (permissions != NULL) perm_flags = bz_app_permissions_get_flags (permissions); if (permissions == NULL) { add_row_if_permission (store, TRUE, BZ_IMPORTANCE_WARNING, "channel-insecure-symbolic", _ ("Unknown Permissions"), _ ("Permissions are missing for this app."), NULL, NULL, NULL); } else { filesystem_read = bz_app_permissions_get_filesystem_read (permissions); filesystem_full = bz_app_permissions_get_filesystem_full (permissions); bus_policies = bz_app_permissions_get_bus_policies (permissions, &n_bus_policies); add_row_if_permission (store, bz_app_permissions_is_empty (permissions), BZ_IMPORTANCE_UNIMPORTANT, "permissions-sandboxed-symbolic", _ ("No Permissions"), _ ("App is fully sandboxed"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_NETWORK) != 0, BZ_IMPORTANCE_INFORMATION, "network-wireless-symbolic", _ ("Network Access"), _ ("Can access the internet"), "network-wireless-disabled-symbolic", _ ("No Network Access"), _ ("Cannot access the internet")); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_DEVICES) != 0, BZ_IMPORTANCE_WARNING, "camera-photo-symbolic", _ ("User Device Access"), _ ("Can access devices such as webcams or gaming controllers"), "camera-disabled-symbolic", _ ("No User Device Access"), _ ("Cannot access devices such as webcams or gaming controllers")); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_INPUT_DEVICES) != 0, BZ_IMPORTANCE_INFORMATION, "input-keyboard-symbolic", _ ("Input Device Access"), _ ("Can access input devices"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_AUDIO_DEVICES) != 0, BZ_IMPORTANCE_INFORMATION, "permissions-microphone-symbolic", _ ("Microphone Access and Audio Playback"), _ ("Can listen using microphones and play audio without asking permission"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_SYSTEM_DEVICES) != 0, BZ_IMPORTANCE_WARNING, "permissions-system-devices-symbolic", _ ("System Device Access"), _ ("Can access system devices which require elevated permissions"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_SCREEN) != 0, BZ_IMPORTANCE_WARNING, "permissions-screen-contents-symbolic", _ ("Screen Contents Access"), _ ("Can access the contents of the screen or other windows"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_X11) != 0, BZ_IMPORTANCE_IMPORTANT, "permissions-legacy-windowing-system-symbolic", _ ("Legacy Windowing System"), _ ("Always uses a legacy windowing system (X11)"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX) != 0, BZ_IMPORTANCE_IMPORTANT, "earth-symbolic", _ ("Arbitrary Permissions"), _ ("Can acquire arbitrary permissions"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_SETTINGS) != 0, BZ_IMPORTANCE_WARNING, "emblem-system-symbolic", _ ("User Settings"), _ ("Can access and change user settings"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL) != 0, BZ_IMPORTANCE_IMPORTANT, "drive-harddisk-symbolic", _ ("Full File System Read/Write Access"), _ ("Can read and write all data on the file system"), NULL, NULL, NULL); add_row_if_permission (store, ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_HOME_FULL) != 0 && !(perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL)), BZ_IMPORTANCE_IMPORTANT, "user-home-symbolic", _ ("Home Folder Read/Write Access"), _ ("Can read and write all data in your home directory"), NULL, NULL, NULL); add_row_if_permission (store, ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ) != 0 && !(perm_flags & BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL)), BZ_IMPORTANCE_IMPORTANT, "folder-symbolic", _ ("Full File System Read Access"), _ ("Can read all data on the file system"), NULL, NULL, NULL); add_row_if_permission (store, ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_HOME_READ) != 0 && !(perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL | BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ))), BZ_IMPORTANCE_IMPORTANT, "user-home-symbolic", _ ("Home Folder Read Access"), _ ("Can read all data in your home directory"), NULL, NULL, NULL); add_row_if_permission (store, ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL) != 0 && !(perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL | BZ_APP_PERMISSIONS_FLAGS_HOME_FULL))), BZ_IMPORTANCE_WARNING, "folder-download-symbolic", _ ("Download Folder Read/Write Access"), _ ("Can read and write all data in your downloads directory"), NULL, NULL, NULL); add_row_if_permission (store, ((perm_flags & BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ) != 0 && !(perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL | BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ | BZ_APP_PERMISSIONS_FLAGS_HOME_FULL | BZ_APP_PERMISSIONS_FLAGS_HOME_READ))), BZ_IMPORTANCE_WARNING, "folder-download-symbolic", _ ("Download Folder Read Access"), _ ("Can read all data in your downloads directory"), NULL, NULL, NULL); for (i = 0; filesystem_full != NULL && i < filesystem_full->len; i++) { const BzFilesystemPath *path = g_ptr_array_index (filesystem_full, i); g_autofree char *fs_title = bz_filesystem_path_to_display_string (path); const char *fs_icon = bz_filesystem_path_to_icon_name (path); add_row_if_permission (store, TRUE, BZ_IMPORTANCE_WARNING, fs_icon, fs_title, _ ("Can read and write all data in the directory"), NULL, NULL, NULL); } for (i = 0; filesystem_read != NULL && i < filesystem_read->len; i++) { const BzFilesystemPath *path = g_ptr_array_index (filesystem_read, i); g_autofree char *fs_title = bz_filesystem_path_to_display_string (path); const char *fs_icon = bz_filesystem_path_to_icon_name (path); add_row_if_permission (store, TRUE, BZ_IMPORTANCE_WARNING, fs_icon, fs_title, _ ("Can read all data in the directory"), NULL, NULL, NULL); } add_row_if_permission (store, !(perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL | BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ | BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_OTHER | BZ_APP_PERMISSIONS_FLAGS_HOME_FULL | BZ_APP_PERMISSIONS_FLAGS_HOME_READ | BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_FULL | BZ_APP_PERMISSIONS_FLAGS_DOWNLOADS_READ)) && filesystem_read == NULL && filesystem_full == NULL, BZ_IMPORTANCE_UNIMPORTANT, "folder-symbolic", _ ("No File System Access"), _ ("Cannot access the file system at all"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS) != 0, BZ_IMPORTANCE_WARNING, "emblem-system-symbolic", _ ("Uses System Services"), _ ("Can request data from non-portal system services"), NULL, NULL, NULL); add_row_if_permission (store, (perm_flags & BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS) != 0, BZ_IMPORTANCE_WARNING, "emblem-system-symbolic", _ ("Uses Session Services"), _ ("Can request data from non-portal session services"), NULL, NULL, NULL); for (i = 0; i < n_bus_policies; i++) { const BzBusPolicy *policy = bus_policies[i]; const char *well_known_title = NULL; const char *well_known_desc = NULL; g_autofree char *bus_title = NULL; const char *bus_description = NULL; gboolean is_system_tray = FALSE; is_system_tray = g_str_equal (policy->bus_name, "org.kde.StatusNotifierWatcher") || g_str_equal (policy->bus_name, "com.canonical.indicator.application"); if (is_system_tray && has_system_tray) // if not filtered, then there would be 2 entries for tray icon continue; if (is_system_tray) has_system_tray = TRUE; if (lookup_well_known_bus_policy (policy->bus_name, &well_known_title, &well_known_desc)) { bus_title = g_strdup (well_known_title); bus_description = well_known_desc; } else { bus_title = format_bus_policy_title (policy); bus_description = format_bus_policy_subtitle (policy); } add_row_if_permission (store, TRUE, BZ_IMPORTANCE_WARNING, "emblem-system-symbolic", bus_title, bus_description, NULL, NULL, NULL); } add_row_if_permission (store, !(perm_flags & (BZ_APP_PERMISSIONS_FLAGS_SYSTEM_BUS | BZ_APP_PERMISSIONS_FLAGS_SESSION_BUS | BZ_APP_PERMISSIONS_FLAGS_BUS_POLICY_OTHER)) && n_bus_policies == 0, BZ_IMPORTANCE_UNIMPORTANT, "emblem-system-symbolic", _ ("No Service Access"), _ ("Cannot access non-portal session or system services at all"), NULL, NULL, NULL); } add_row_if_permission (store, is_verified, BZ_IMPORTANCE_UNIMPORTANT, "verified-checkmark-symbolic", _ ("Verified App Developer"), _ ("The developer of this app has been verified to be who they say they are"), NULL, NULL, NULL); if (!is_foss) { add_row_if_permission (store, TRUE, BZ_IMPORTANCE_INFORMATION, "proprietary-code-symbolic", _ ("Proprietary Code"), _ ("The source code is not public, so it cannot be independently audited and might be unsafe"), NULL, NULL, NULL); } else { add_row_if_permission (store, FALSE, BZ_IMPORTANCE_NEUTRAL, NULL, NULL, NULL, "auditable-code-symbolic", _ ("Auditable Code"), _ ("The source code is public and can be independently audited, which makes the app more likely to be safe")); } g_clear_object (&permissions); return G_LIST_MODEL (store); } char * bz_safety_calculator_get_top_icon (BzEntry *entry, int index) { g_autoptr (GListModel) model = NULL; const char *icons[2] = { NULL, NULL }; guint icon_count = 0; guint n_items = 0; BzImportance priorities[] = { BZ_IMPORTANCE_IMPORTANT, BZ_IMPORTANCE_WARNING, BZ_IMPORTANCE_INFORMATION }; g_return_val_if_fail (BZ_IS_ENTRY (entry), NULL); if (index < 0 || index > 1) return NULL; model = bz_safety_calculator_analyze_entry (entry); n_items = g_list_model_get_n_items (model); for (guint priority_idx = 0; priority_idx < 3 && icon_count < 2; priority_idx++) { BzImportance current_priority = priorities[priority_idx]; for (guint i = 0; i < n_items && icon_count < 2; i++) { g_autoptr (BzSafetyRow) row = g_list_model_get_item (model, i); BzImportance importance = BZ_IMPORTANCE_UNIMPORTANT; const char *icon_name = NULL; gboolean duplicate = FALSE; g_object_get (row, "importance", &importance, "icon-name", &icon_name, NULL); if (importance != current_priority) continue; if (icon_name == NULL || *icon_name == '\0') continue; for (guint j = 0; j < icon_count; j++) { if (g_strcmp0 (icons[j], icon_name) == 0) { duplicate = TRUE; break; } } if (!duplicate) { icons[icon_count] = icon_name; icon_count++; } } } if (icon_count == 0 || icons[index] == NULL) return NULL; return g_strdup (icons[index]); } BzImportance bz_safety_calculator_calculate_rating (BzEntry *entry) { g_autoptr (GListModel) model = NULL; BzImportance max_rating = BZ_IMPORTANCE_UNIMPORTANT; guint n_items = 0; guint i = 0; gboolean is_foss = FALSE; g_return_val_if_fail (BZ_IS_ENTRY (entry), BZ_IMPORTANCE_UNIMPORTANT); model = bz_safety_calculator_analyze_entry (entry); n_items = g_list_model_get_n_items (model); is_foss = bz_entry_get_is_foss (entry); for (i = 0; i < n_items; i++) { g_autoptr (BzSafetyRow) row = g_list_model_get_item (model, i); BzImportance rating = BZ_IMPORTANCE_UNIMPORTANT; g_object_get (row, "importance", &rating, NULL); max_rating = MAX (max_rating, rating); } if (is_foss && max_rating == BZ_IMPORTANCE_WARNING) { max_rating = BZ_IMPORTANCE_INFORMATION; } if (is_foss && max_rating == BZ_IMPORTANCE_IMPORTANT) { max_rating = BZ_IMPORTANCE_WARNING; } return max_rating; } BzHighRiskGroup bz_safety_calculator_get_high_risk_groups (BzEntry *entry) { BzAppPermissions *permissions = NULL; BzAppPermissionsFlags perm_flags = BZ_APP_PERMISSIONS_FLAGS_NONE; BzHighRiskGroup result = BZ_HIGH_RISK_GROUP_NONE; g_return_val_if_fail (BZ_IS_ENTRY (entry), BZ_HIGH_RISK_GROUP_NONE); g_object_get (entry, "permissions", &permissions, NULL); if (permissions == NULL) return BZ_HIGH_RISK_GROUP_NONE; perm_flags = bz_app_permissions_get_flags (permissions); if (perm_flags & BZ_APP_PERMISSIONS_FLAGS_X11) result |= BZ_HIGH_RISK_GROUP_X11; if (perm_flags & (BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_FULL | BZ_APP_PERMISSIONS_FLAGS_FILESYSTEM_READ | BZ_APP_PERMISSIONS_FLAGS_HOME_FULL | BZ_APP_PERMISSIONS_FLAGS_HOME_READ | BZ_APP_PERMISSIONS_FLAGS_ESCAPE_SANDBOX)) result |= BZ_HIGH_RISK_GROUP_DISK; g_clear_object (&permissions); return result; } static char * format_bus_policy_title (const BzBusPolicy *bus_policy) { if (bus_policy->bus_type == G_BUS_TYPE_SYSTEM) { return g_strdup_printf (_ ("Use the %s System Service"), bus_policy->bus_name); } else if (bus_policy->bus_type == G_BUS_TYPE_SESSION) { return g_strdup_printf (_ ("Use the %s Session Service"), bus_policy->bus_name); } else { return g_strdup_printf (_ ("Use the %s Service"), bus_policy->bus_name); } } static const char * format_bus_policy_subtitle (const BzBusPolicy *bus_policy) { switch (bus_policy->permission) { case BZ_BUS_POLICY_PERMISSION_SEE: return _ ("Can see the non-portal service"); case BZ_BUS_POLICY_PERMISSION_TALK: return _ ("Can talk to the non-portal service"); case BZ_BUS_POLICY_PERMISSION_OWN: return _ ("Can own the non-portal service"); case BZ_BUS_POLICY_PERMISSION_NONE: case BZ_BUS_POLICY_PERMISSION_UNKNOWN: default: g_assert_not_reached (); } } static gboolean lookup_well_known_bus_policy (const char *bus_name, const char **out_title, const char **out_description) { if (g_str_equal (bus_name, "com.canonical.AppMenu.Registrar")) { *out_title = _ ("Global Menu Integration"); *out_description = _ ("Can display its menus in a global menu bar"); return TRUE; } if (g_str_equal (bus_name, "org.kde.kconfig.notify")) { *out_title = _ ("KDE Settings Integration"); *out_description = _ ("Can detect when KDE desktop settings change"); return TRUE; } if (g_str_equal (bus_name, "org.kde.KGlobalSettings")) { *out_title = _ ("KDE Global Settings"); *out_description = _ ("Can read KDE desktop preferences like fonts and colors"); return TRUE; } if (g_str_equal (bus_name, "org.freedesktop.secrets")) { *out_title = _ ("Secret Storage Service"); *out_description = _ ("Can store and retrieve its own passwords using the system keyring"); return TRUE; } if (g_str_equal (bus_name, "org.freedesktop.Notifications")) { *out_title = _ ("Desktop Notifications Service"); *out_description = _ ("Can send desktop notifications"); return TRUE; } if (g_str_equal (bus_name, "org.kde.StatusNotifierWatcher") || g_str_equal (bus_name, "com.canonical.indicator.application")) { *out_title = _ ("System Tray Integration"); *out_description = _ ("Can display an icon in the system tray"); return TRUE; } if (g_str_equal (bus_name, "org.kde.kdeconnect")) { *out_title = _ ("KDE Connect Integration"); *out_description = _ ("Can interact with devices paired via KDE Connect"); return TRUE; } return FALSE; } static void add_row_if_permission (GListStore *store, gboolean has_permission, BzImportance item_rating, const char *icon_name_with_permission, const char *title_with_permission, const char *description_with_permission, const char *icon_name_without_permission, const char *title_without_permission, const char *description_without_permission) { BzSafetyRow *row = NULL; if (!has_permission && title_without_permission == NULL) return; row = bz_safety_row_new (); g_object_set (row, "importance", has_permission ? item_rating : BZ_IMPORTANCE_UNIMPORTANT, "icon-name", has_permission ? icon_name_with_permission : icon_name_without_permission, "title", has_permission ? title_with_permission : title_without_permission, "subtitle", has_permission ? description_with_permission : description_without_permission, NULL); g_list_store_append (store, row); g_object_unref (row); } kolunmi-bazaar-7b9c8e1/src/bz-safety-calculator.h000066400000000000000000000026351514314607700220630ustar00rootroot00000000000000/* bz-safety-calculator.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-context-row.h" #include "bz-entry.h" #include "bz-safety-row.h" #include G_BEGIN_DECLS typedef enum { BZ_HIGH_RISK_GROUP_NONE = 0, BZ_HIGH_RISK_GROUP_X11 = 1 << 0, BZ_HIGH_RISK_GROUP_DISK = 1 << 1, } BzHighRiskGroup; #define BZ_TYPE_HIGH_RISK_GROUP (bz_high_risk_group_get_type ()) GListModel * bz_safety_calculator_analyze_entry (BzEntry *entry); BzImportance bz_safety_calculator_calculate_rating (BzEntry *entry); char * bz_safety_calculator_get_top_icon (BzEntry *entry, int index); BzHighRiskGroup bz_safety_calculator_get_high_risk_groups (BzEntry *entry); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-safety-dialog.blp000066400000000000000000000056771514314607700215300ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzSafetyDialog: Adw.Dialog { content-height: 576; content-width: 640; title: _("Safety"); child: Adw.ToolbarView { [top] Adw.HeaderBar { show-title: false; } content: ScrolledWindow { hscrollbar-policy: never; Adw.Clamp { maximum-size: 640; tightening-threshold: 400; Box { orientation: vertical; spacing: 24; margin-start: 24; margin-end: 24; margin-top: 24; margin-bottom: 24; $BzLozenge lozenge { title: _("Safe"); icon-names: [ "app-safety-ok-symbolic", ]; importance: unimportant; } ListBox permissions_list { selection-mode: none; styles [ "boxed-list", ] } Adw.PreferencesGroup { margin-top: 10; title: _("Details"); Adw.ActionRow { title: _("License"); subtitle: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.project-license; subtitle-selectable: true; styles [ "property", ] } Adw.ActionRow { title: _("App ID"); subtitle: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.id; subtitle-selectable: true; styles [ "property", ] } Adw.ActionRow { title: _("SDK"); visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.application-runtime) as ) as ; subtitle: bind template.group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzFlatpakEntry>.application-runtime; subtitle-selectable: true; styles [ "property", ] [suffix] MenuButton { visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.eol) as ) as ; styles [ "error", "flat", ] valign: center; icon-name: "dialog-warning-symbolic"; popover: Popover { child: Label { margin-top: 8; margin-bottom: 8; margin-start: 8; margin-end: 8; max-width-chars: 35; wrap: true; label: _("This app uses an outdated version of the software platform (SDK) and might contain bugs or security vulnerabilities which will not be fixed."); }; }; } } } } } }; }; } kolunmi-bazaar-7b9c8e1/src/bz-safety-dialog.c000066400000000000000000000171521514314607700211640ustar00rootroot00000000000000/* bz-safety-dialog.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-app-permissions.h" #include "bz-context-row.h" #include "bz-entry-group.h" #include "bz-entry.h" #include "bz-lozenge.h" #include "bz-result.h" #include "bz-safety-calculator.h" #include "bz-safety-dialog.h" #include "bz-safety-row.h" struct _BzSafetyDialog { AdwDialog parent_instance; BzEntryGroup *group; BzLozenge *lozenge; GtkListBox *permissions_list; }; G_DEFINE_FINAL_TYPE (BzSafetyDialog, bz_safety_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static AdwActionRow *create_permission_row (BzSafetyRow *row_data); static void update_permissions_list (BzSafetyDialog *self); static gboolean invert_boolean (gpointer object, gboolean value); static gboolean is_null (gpointer object, GObject *value); static void bz_safety_dialog_dispose (GObject *object) { BzSafetyDialog *self; self = BZ_SAFETY_DIALOG (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_safety_dialog_parent_class)->dispose (object); } static void bz_safety_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSafetyDialog *self; self = BZ_SAFETY_DIALOG (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, self->group); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_safety_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSafetyDialog *self; self = BZ_SAFETY_DIALOG (object); switch (prop_id) { case PROP_GROUP: g_clear_object (&self->group); self->group = g_value_dup_object (value); update_permissions_list (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_safety_dialog_class_init (BzSafetyDialogClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_safety_dialog_dispose; object_class->get_property = bz_safety_dialog_get_property; object_class->set_property = bz_safety_dialog_set_property; props[PROP_GROUP] = g_param_spec_object ("group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LOZENGE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-safety-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzSafetyDialog, lozenge); gtk_widget_class_bind_template_child (widget_class, BzSafetyDialog, permissions_list); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); } static void bz_safety_dialog_init (BzSafetyDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_safety_dialog_new (BzEntryGroup *group) { return g_object_new (BZ_TYPE_SAFETY_DIALOG, "group", group, NULL); } static AdwActionRow * create_permission_row (BzSafetyRow *row_data) { return bz_context_row_new (bz_safety_row_get_icon_name (row_data), bz_safety_row_get_importance (row_data), bz_safety_row_get_title (row_data), bz_safety_row_get_subtitle (row_data)); } static void update_permissions_list (BzSafetyDialog *self) { const char *icon_names[2]; const char *app_name = NULL; g_autofree char *title_text = NULL; BzImportance importance = BZ_IMPORTANCE_UNIMPORTANT; BzEntry *entry = NULL; BzResult *result = NULL; GtkWidget *child; g_autoptr (GListModel) model = NULL; guint n_items = 0; while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->permissions_list))) != NULL) gtk_list_box_remove (self->permissions_list, child); if (self->group == NULL) return; g_object_get (self->group, "ui-entry", &result, NULL); if (result == NULL) return; entry = bz_result_get_object (result); if (entry == NULL) { g_clear_object (&result); return; } app_name = bz_entry_get_title (entry); model = bz_safety_calculator_analyze_entry (entry); importance = bz_safety_calculator_calculate_rating (entry); n_items = g_list_model_get_n_items (model); for (gint level = BZ_IMPORTANCE_IMPORTANT; level >= BZ_IMPORTANCE_UNIMPORTANT; level--) { for (gint j = 0; j < n_items; j++) { g_autoptr (BzSafetyRow) row_data; AdwActionRow *row; BzImportance row_importance; row_data = g_list_model_get_item (model, j); row_importance = bz_safety_row_get_importance (row_data); if (row_importance != level) continue; row = create_permission_row (row_data); gtk_list_box_append (self->permissions_list, GTK_WIDGET (row)); } } switch (importance) { case BZ_IMPORTANCE_UNIMPORTANT: icon_names[0] = "app-safety-ok-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s is Safe"), app_name); break; case BZ_IMPORTANCE_NEUTRAL: icon_names[0] = "app-safety-ok-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s has no Unsafe Permissions"), app_name); break; case BZ_IMPORTANCE_INFORMATION: icon_names[0] = "app-safety-ok-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s is Probably Safe"), app_name); break; case BZ_IMPORTANCE_WARNING: icon_names[0] = "app-safety-unknown-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s is Possibly Unsafe"), app_name); break; case BZ_IMPORTANCE_IMPORTANT: icon_names[0] = "app-safety-unsafe-symbolic"; icon_names[1] = NULL; title_text = g_strdup_printf (_ ("%s is Unsafe"), app_name); break; default: g_assert_not_reached (); } bz_lozenge_set_icon_names (self->lozenge, icon_names); bz_lozenge_set_title (self->lozenge, title_text); bz_lozenge_set_importance (self->lozenge, importance); g_clear_object (&result); } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } kolunmi-bazaar-7b9c8e1/src/bz-safety-dialog.h000066400000000000000000000020431514314607700211620ustar00rootroot00000000000000/* bz-safety-dialog.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include G_BEGIN_DECLS #define BZ_TYPE_SAFETY_DIALOG (bz_safety_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzSafetyDialog, bz_safety_dialog, BZ, SAFETY_DIALOG, AdwDialog) AdwDialog *bz_safety_dialog_new (BzEntryGroup *group); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-safety-row.txt000066400000000000000000000004441514314607700211250ustar00rootroot00000000000000prefix=bz name=safety_row parent-prefix=g parent-name=object author=AUTOGEN include="bz-context-row.h" property=importance BzImportance BZ_TYPE_IMPORTANCE enum property=title char G_TYPE_STRING string property=subtitle char G_TYPE_STRING string property=icon_name char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-screenshot-page.blp000066400000000000000000000113301514314607700220460ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzScreenshotPage: Adw.NavigationPage { title: _("Screenshots"); child: Adw.BreakpointBin { width-request: 360; height-request: 450; Adw.Breakpoint { condition ("max-width: 700px") setters { mobile_caption_box.margin-bottom: 70; } } child: Adw.ToastOverlay toast_overlay { child: Adw.ToolbarView { top-bar-style: flat; extend-content-to-top-edge: true; styles [ "view-dark", ] [top] Adw.HeaderBar header_bar { styles [ "flat", "header-osd", ] show-end-title-buttons: false; show-start-title-buttons: false; show-title: false; } content: Overlay { [overlay] Box { orientation: horizontal; halign: start; valign: end; margin-bottom: 12; margin-start: 12; spacing: 6; Box navigation_controls { orientation: horizontal; spacing: 6; visible: bind $has_multiple_screenshots(template.screenshots) as ; styles [ "osd-box", ] Button previous_button { icon-name: "go-previous-symbolic"; tooltip-text: _("Previous Screenshot"); clicked => $previous_clicked() swapped; styles [ "flat", ] } Button next_button { icon-name: "go-next-symbolic"; tooltip-text: _("Next Screenshot"); clicked => $next_clicked() swapped; styles [ "flat", ] } } Box { styles [ "osd-box", ] Button copy_button { icon-name: "edit-copy-symbolic"; tooltip-text: _("Copy Image"); clicked => $copy_clicked() swapped; styles [ "flat", ] } } } [overlay] Revealer { halign: center; valign: end; reveal-child: bind $is_valid_string(template.current-caption) as ; transition-type: crossfade; can-target: false; child: Box mobile_caption_box { margin-bottom: 20; styles [ "osd-box", ] Label { halign: center; hexpand: true; label: bind template.current-caption; justify: center; max-width-chars: 30; wrap: true; wrap-mode: word_char; styles [ "heading" ] } }; } [overlay] Box { orientation: horizontal; halign: end; valign: end; margin-bottom: 12; margin-end: 12; Box zoom_controls { orientation: horizontal; styles [ "osd-box", ] Revealer { reveal-child: bind template.is-zoomed as ; transition-type: slide_right; Button reset_zoom_button { icon-name: "zoom-original-symbolic"; tooltip-text: _("Reset View"); clicked => $reset_zoom_clicked() swapped; styles [ "flat", ] } } Button zoom_out_button { icon-name: "zoom-minus-symbolic"; tooltip-text: _("Zoom Out"); clicked => $zoom_out_clicked() swapped; styles [ "flat", ] } Button zoom_in_button { icon-name: "zoom-plus-symbolic"; tooltip-text: _("Zoom In"); clicked => $zoom_in_clicked() swapped; styles [ "flat", ] } } } child: Adw.Carousel carousel { can-focus: false; interactive: bind $invert_boolean(template.is-zoomed) as ; allow-scroll-wheel: bind $invert_boolean(template.is-zoomed) as ; allow-mouse-drag: bind $invert_boolean(template.is-zoomed) as ; allow-long-swipes: false; notify::position => $on_carousel_position_changed(); }; }; }; }; }; }kolunmi-bazaar-7b9c8e1/src/bz-screenshot-page.c000066400000000000000000000375651514314607700215350ustar00rootroot00000000000000/* bz-screenshot-page.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-screenshot-page.h" #include "bz-screenshot.h" #include "bz-zoom.h" #include struct _BzScreenshotPage { AdwNavigationPage parent_instance; AdwCarousel *carousel; AdwToastOverlay *toast_overlay; GListModel *screenshots; GListModel *captions; guint current_index; guint initial_index; gboolean is_zoomed; }; G_DEFINE_FINAL_TYPE (BzScreenshotPage, bz_screenshot_page, ADW_TYPE_NAVIGATION_PAGE) static void on_zoom_level_changed (BzZoom *zoom, GParamSpec *pspec, BzScreenshotPage *self); enum { PROP_0, PROP_SCREENSHOTS, PROP_CURRENT_INDEX, PROP_CURRENT_CAPTION, PROP_IS_ZOOMED, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_screenshot_page_dispose (GObject *object) { BzScreenshotPage *self = BZ_SCREENSHOT_PAGE (object); g_clear_object (&self->screenshots); g_clear_object (&self->captions); G_OBJECT_CLASS (bz_screenshot_page_parent_class)->dispose (object); } static void bz_screenshot_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzScreenshotPage *self = BZ_SCREENSHOT_PAGE (object); switch (prop_id) { case PROP_SCREENSHOTS: g_value_set_object (value, self->screenshots); break; case PROP_CURRENT_INDEX: g_value_set_uint (value, self->current_index); break; case PROP_CURRENT_CAPTION: { const char *caption = bz_screenshot_page_get_current_caption (self); g_value_set_string (value, caption); } break; case PROP_IS_ZOOMED: g_value_set_boolean (value, self->is_zoomed); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void populate_carousel (BzScreenshotPage *self) { guint n_items = 0; guint i = 0; if (self->screenshots == NULL) return; n_items = g_list_model_get_n_items (self->screenshots); if (n_items == 0) return; for (guint offset = 0; offset < n_items; offset++) { g_autoptr (BzAsyncTexture) async_texture = NULL; GtkWidget *zoom_widget = NULL; GtkWidget *screenshot = NULL; i = (self->initial_index + offset) % n_items; async_texture = g_list_model_get_item (self->screenshots, i); if (async_texture == NULL) continue; screenshot = bz_screenshot_new (); bz_screenshot_set_paintable (BZ_SCREENSHOT (screenshot), GDK_PAINTABLE (async_texture)); bz_screenshot_set_rounded_corners (BZ_SCREENSHOT (screenshot), FALSE); gtk_widget_set_margin_top (screenshot, 25); gtk_widget_set_margin_bottom (screenshot, 25); gtk_widget_set_margin_start (screenshot, 25); gtk_widget_set_margin_end (screenshot, 25); zoom_widget = bz_zoom_new (); gtk_widget_set_hexpand (zoom_widget, TRUE); gtk_widget_set_vexpand (zoom_widget, TRUE); bz_zoom_set_child (BZ_ZOOM (zoom_widget), screenshot); adw_carousel_append (self->carousel, zoom_widget); } } static void update_is_zoomed (BzScreenshotPage *self) { GtkWidget *page = NULL; BzZoom *zoom = NULL; double zoom_level = 1.0; gboolean was_zoomed = self->is_zoomed; guint n_pages = 0; n_pages = adw_carousel_get_n_pages (self->carousel); if (self->current_index >= n_pages) return; page = adw_carousel_get_nth_page (self->carousel, self->current_index); if (page != NULL && BZ_IS_ZOOM (page)) { GtkWidget *screenshot = NULL; zoom = BZ_ZOOM (page); g_object_get (zoom, "zoom-level", &zoom_level, NULL); screenshot = bz_zoom_get_child (zoom); if (screenshot != NULL) bz_screenshot_set_filter ( BZ_SCREENSHOT (screenshot), zoom_level <= 4.5 ? GSK_SCALING_FILTER_TRILINEAR : GSK_SCALING_FILTER_NEAREST); } self->is_zoomed = (zoom_level != 1.0); if (was_zoomed != self->is_zoomed) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_ZOOMED]); } static void on_zoom_level_changed (BzZoom *zoom, GParamSpec *pspec, BzScreenshotPage *self) { update_is_zoomed (self); } static void connect_zoom_signal (BzScreenshotPage *self, GtkWidget *page) { BzZoom *zoom = NULL; if (page != NULL && BZ_IS_ZOOM (page)) { zoom = BZ_ZOOM (page); g_signal_connect (zoom, "notify::zoom-level", G_CALLBACK (on_zoom_level_changed), self); } } static void bz_screenshot_page_constructed (GObject *object) { BzScreenshotPage *self = BZ_SCREENSHOT_PAGE (object); GtkWidget *page = NULL; G_OBJECT_CLASS (bz_screenshot_page_parent_class)->constructed (object); populate_carousel (self); self->current_index = 0; page = adw_carousel_get_nth_page (self->carousel, 0); if (page != NULL) connect_zoom_signal (self, page); update_is_zoomed (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_CAPTION]); } static void bz_screenshot_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzScreenshotPage *self = BZ_SCREENSHOT_PAGE (object); switch (prop_id) { case PROP_SCREENSHOTS: g_set_object (&self->screenshots, g_value_get_object (value)); break; case PROP_CURRENT_INDEX: self->initial_index = g_value_get_uint (value); break; case PROP_CURRENT_CAPTION: case PROP_IS_ZOOMED: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void zoom_in_clicked (BzScreenshotPage *self) { GtkWidget *page = NULL; BzZoom *zoom = NULL; guint n_pages = 0; n_pages = adw_carousel_get_n_pages (self->carousel); if (self->current_index >= n_pages) return; page = adw_carousel_get_nth_page (self->carousel, self->current_index); if (page == NULL || !BZ_IS_ZOOM (page)) return; zoom = BZ_ZOOM (page); bz_zoom_zoom_in (zoom); } static void zoom_out_clicked (BzScreenshotPage *self) { GtkWidget *page = NULL; BzZoom *zoom = NULL; guint n_pages = 0; n_pages = adw_carousel_get_n_pages (self->carousel); if (self->current_index >= n_pages) return; page = adw_carousel_get_nth_page (self->carousel, self->current_index); if (page == NULL || !BZ_IS_ZOOM (page)) return; zoom = BZ_ZOOM (page); bz_zoom_zoom_out (zoom); } static void reset_zoom_clicked (BzScreenshotPage *self) { GtkWidget *page = NULL; BzZoom *zoom = NULL; guint n_pages = 0; n_pages = adw_carousel_get_n_pages (self->carousel); if (self->current_index >= n_pages) return; page = adw_carousel_get_nth_page (self->carousel, self->current_index); if (page == NULL || !BZ_IS_ZOOM (page)) return; zoom = BZ_ZOOM (page); bz_zoom_reset (zoom); } static void previous_clicked (BzScreenshotPage *self) { guint n_pages = 0; GtkWidget *page = NULL; n_pages = adw_carousel_get_n_pages (self->carousel); if (n_pages == 0) return; if (self->current_index > 0) page = adw_carousel_get_nth_page (self->carousel, self->current_index - 1); else page = adw_carousel_get_nth_page (self->carousel, n_pages - 1); if (page != NULL) adw_carousel_scroll_to (self->carousel, page, TRUE); } static void next_clicked (BzScreenshotPage *self) { guint n_pages = 0; GtkWidget *page = NULL; n_pages = adw_carousel_get_n_pages (self->carousel); if (n_pages == 0) return; if (self->current_index < n_pages - 1) page = adw_carousel_get_nth_page (self->carousel, self->current_index + 1); else page = adw_carousel_get_nth_page (self->carousel, 0); if (page != NULL) adw_carousel_scroll_to (self->carousel, page, TRUE); } static void on_carousel_position_changed (AdwCarousel *carousel, GParamSpec *pspec, BzScreenshotPage *self) { GtkWidget *old_page = NULL; GtkWidget *new_page = NULL; BzZoom *old_zoom = NULL; guint new_index = (guint) round (adw_carousel_get_position (carousel)); guint n_pages = adw_carousel_get_n_pages (carousel); if (new_index == self->current_index || new_index >= n_pages) return; if (self->current_index < n_pages) { old_page = adw_carousel_get_nth_page (carousel, self->current_index); if (old_page != NULL && BZ_IS_ZOOM (old_page)) { old_zoom = BZ_ZOOM (old_page); g_signal_handlers_disconnect_by_func (old_zoom, on_zoom_level_changed, self); bz_zoom_reset (old_zoom); } } self->current_index = new_index; if (new_index < n_pages) { new_page = adw_carousel_get_nth_page (carousel, new_index); connect_zoom_signal (self, new_page); } update_is_zoomed (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_INDEX]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_CAPTION]); } static void copy_clicked (BzScreenshotPage *self) { g_autoptr (BzAsyncTexture) async_texture = NULL; g_autoptr (GdkTexture) texture = NULL; GdkClipboard *clipboard; AdwToast *toast = NULL; guint n_items = 0; guint actual_index = 0; if (self->screenshots == NULL) return; n_items = g_list_model_get_n_items (self->screenshots); if (n_items == 0) return; actual_index = (self->initial_index + self->current_index) % n_items; async_texture = g_list_model_get_item (self->screenshots, actual_index); if (async_texture == NULL) return; texture = bz_async_texture_dup_texture (async_texture); if (texture == NULL) return; clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_texture (clipboard, texture); toast = adw_toast_new (_ ("Copied!")); adw_toast_set_timeout (toast, 1); adw_toast_overlay_add_toast (self->toast_overlay, toast); } static gboolean on_key_pressed (GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, BzScreenshotPage *self) { if (keyval == GDK_KEY_Left) { previous_clicked (self); return TRUE; } else if (keyval == GDK_KEY_Right) { next_clicked (self); return TRUE; } return FALSE; } static gboolean has_multiple_screenshots (GObject *object, GListModel *screenshots, gpointer user_data) { if (screenshots == NULL) return FALSE; return g_list_model_get_n_items (screenshots) > 1; } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_valid_string (gpointer object, const char *value) { return value != NULL && *value != '\0'; } static void bz_screenshot_page_class_init (BzScreenshotPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_screenshot_page_dispose; object_class->constructed = bz_screenshot_page_constructed; object_class->get_property = bz_screenshot_page_get_property; object_class->set_property = bz_screenshot_page_set_property; props[PROP_SCREENSHOTS] = g_param_spec_object ( "screenshots", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_CURRENT_INDEX] = g_param_spec_uint ( "current-index", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); props[PROP_CURRENT_CAPTION] = g_param_spec_string ( "current-caption", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_IS_ZOOMED] = g_param_spec_boolean ( "is-zoomed", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_ZOOM); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-screenshot-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzScreenshotPage, carousel); gtk_widget_class_bind_template_child (widget_class, BzScreenshotPage, toast_overlay); gtk_widget_class_bind_template_callback (widget_class, zoom_in_clicked); gtk_widget_class_bind_template_callback (widget_class, zoom_out_clicked); gtk_widget_class_bind_template_callback (widget_class, on_carousel_position_changed); gtk_widget_class_bind_template_callback (widget_class, reset_zoom_clicked); gtk_widget_class_bind_template_callback (widget_class, copy_clicked); gtk_widget_class_bind_template_callback (widget_class, previous_clicked); gtk_widget_class_bind_template_callback (widget_class, next_clicked); gtk_widget_class_bind_template_callback (widget_class, has_multiple_screenshots); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_valid_string); } static void bz_screenshot_page_init (BzScreenshotPage *self) { GtkEventController *key_controller = NULL; gtk_widget_init_template (GTK_WIDGET (self)); key_controller = gtk_event_controller_key_new (); g_signal_connect (key_controller, "key-pressed", G_CALLBACK (on_key_pressed), self); gtk_widget_add_controller (GTK_WIDGET (self), key_controller); } const char * bz_screenshot_page_get_current_caption (BzScreenshotPage *self) { g_autoptr (GtkStringObject) caption_obj = NULL; guint n_items = 0; guint actual_index = 0; g_return_val_if_fail (BZ_IS_SCREENSHOT_PAGE (self), NULL); if (self->captions == NULL) return ""; n_items = g_list_model_get_n_items (self->captions); if (n_items == 0) return ""; actual_index = (self->initial_index + self->current_index) % n_items; caption_obj = g_list_model_get_item (self->captions, actual_index); if (caption_obj == NULL) return ""; return gtk_string_object_get_string (caption_obj); } void bz_screenshot_page_set_captions (BzScreenshotPage *self, GListModel *captions) { g_return_if_fail (BZ_IS_SCREENSHOT_PAGE (self)); g_set_object (&self->captions, captions); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_CAPTION]); } AdwNavigationPage * bz_screenshot_page_new (GListModel *screenshots, GListModel *captions, guint initial_index) { BzScreenshotPage *page = g_object_new ( BZ_TYPE_SCREENSHOT_PAGE, "screenshots", screenshots, "current-index", initial_index, NULL); if (captions != NULL) bz_screenshot_page_set_captions (page, captions); return ADW_NAVIGATION_PAGE (page); } kolunmi-bazaar-7b9c8e1/src/bz-screenshot-page.h000066400000000000000000000026321514314607700215250ustar00rootroot00000000000000/* bz-screenshot-page.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-async-texture.h" #include G_BEGIN_DECLS #define BZ_TYPE_SCREENSHOT_PAGE (bz_screenshot_page_get_type ()) G_DECLARE_FINAL_TYPE (BzScreenshotPage, bz_screenshot_page, BZ, SCREENSHOT_PAGE, AdwNavigationPage) AdwNavigationPage *bz_screenshot_page_new (GListModel *screenshots, GListModel *captions, guint initial_index); void bz_screenshot_page_set_captions (BzScreenshotPage *self, GListModel *captions); const char * bz_screenshot_page_get_current_caption (BzScreenshotPage *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-screenshot.c000066400000000000000000000374741514314607700206220ustar00rootroot00000000000000/* bz-screenshot.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-screenshot.h" #include "bz-async-texture.h" #define TOP_HALF_FIXED_WIDTH 650 #define TOP_HALF_FIXED_HEIGHT 265 struct _BzScreenshot { GtkWidget parent_instance; GdkPaintable *paintable; double focus_x; double focus_y; gboolean rounded_corners; gboolean top_half; GskScalingFilter filter; }; G_DEFINE_FINAL_TYPE (BzScreenshot, bz_screenshot, GTK_TYPE_WIDGET) enum { PROP_0, PROP_PAINTABLE, PROP_FOCUS_X, PROP_FOCUS_Y, PROP_ROUNDED_CORNERS, PROP_TOP_HALF, PROP_FILTER, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void invalidate_contents (BzScreenshot *self, GdkPaintable *paintable); static void invalidate_size (BzScreenshot *self, GdkPaintable *paintable); static void async_loaded (BzScreenshot *self, GParamSpec *pspec, BzAsyncTexture *texture); static void bz_screenshot_dispose (GObject *object) { BzScreenshot *self = BZ_SCREENSHOT (object); if (self->paintable != NULL) { g_signal_handlers_disconnect_by_func (self->paintable, invalidate_contents, self); g_signal_handlers_disconnect_by_func (self->paintable, invalidate_size, self); g_signal_handlers_disconnect_by_func (self->paintable, async_loaded, self); } g_clear_object (&self->paintable); G_OBJECT_CLASS (bz_screenshot_parent_class)->dispose (object); } static void bz_screenshot_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzScreenshot *self = BZ_SCREENSHOT (object); switch (prop_id) { case PROP_PAINTABLE: g_value_set_object (value, bz_screenshot_get_paintable (self)); break; case PROP_FOCUS_X: g_value_set_double (value, bz_screenshot_get_focus_x (self)); break; case PROP_FOCUS_Y: g_value_set_double (value, bz_screenshot_get_focus_y (self)); break; case PROP_ROUNDED_CORNERS: g_value_set_boolean (value, bz_screenshot_get_rounded_corners (self)); break; case PROP_TOP_HALF: g_value_set_boolean (value, bz_screenshot_get_top_half (self)); break; case PROP_FILTER: g_value_set_enum (value, bz_screenshot_get_filter (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_screenshot_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzScreenshot *self = BZ_SCREENSHOT (object); switch (prop_id) { case PROP_PAINTABLE: bz_screenshot_set_paintable (self, g_value_get_object (value)); break; case PROP_FOCUS_X: bz_screenshot_set_focus_x (self, g_value_get_double (value)); break; case PROP_FOCUS_Y: bz_screenshot_set_focus_y (self, g_value_get_double (value)); break; case PROP_ROUNDED_CORNERS: bz_screenshot_set_rounded_corners (self, g_value_get_boolean (value)); break; case PROP_TOP_HALF: bz_screenshot_set_top_half (self, g_value_get_boolean (value)); break; case PROP_FILTER: bz_screenshot_set_filter (self, g_value_get_enum (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static GtkSizeRequestMode bz_screenshot_get_request_mode (GtkWidget *widget) { BzScreenshot *self = BZ_SCREENSHOT (widget); if (self->top_half) return GTK_SIZE_REQUEST_CONSTANT_SIZE; return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; } static void bz_screenshot_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzScreenshot *self = BZ_SCREENSHOT (widget); if (self->paintable == NULL) return; if (self->top_half) { if (orientation == GTK_ORIENTATION_HORIZONTAL) { *minimum = TOP_HALF_FIXED_WIDTH; *natural = TOP_HALF_FIXED_WIDTH; } else { *minimum = TOP_HALF_FIXED_HEIGHT; *natural = TOP_HALF_FIXED_HEIGHT; } } else { if (orientation == GTK_ORIENTATION_VERTICAL) { int intrinsic_height; double intrinsic_aspect_ratio; intrinsic_height = gdk_paintable_get_intrinsic_height (self->paintable); intrinsic_aspect_ratio = gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); if (for_size >= 0 && intrinsic_aspect_ratio > 0.0) { double result; result = ceil ((double) for_size / intrinsic_aspect_ratio); *minimum = (int) MIN (intrinsic_height, result); *natural = (int) MIN (intrinsic_height, result); } else { *minimum = 0; *natural = intrinsic_height; } } else { *minimum = 0; *natural = gdk_paintable_get_intrinsic_width (self->paintable); } } } static void bz_screenshot_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzScreenshot *self; int widget_width; int widget_height; double paintable_aspect; double scaled_w, scaled_h; double x, y; GskRoundedRect rect; self = BZ_SCREENSHOT (widget); if (self->paintable == NULL) return; widget_width = gtk_widget_get_width (widget); widget_height = gtk_widget_get_height (widget); paintable_aspect = gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); if (self->top_half) { int paintable_width = gdk_paintable_get_intrinsic_width (self->paintable); if (paintable_width > TOP_HALF_FIXED_WIDTH) scaled_w = TOP_HALF_FIXED_WIDTH; else scaled_w = paintable_width > 0 ? paintable_width : TOP_HALF_FIXED_WIDTH; if (paintable_aspect > 0.0) scaled_h = scaled_w / paintable_aspect; else scaled_h = widget_height * 2.0; x = (widget_width - scaled_w) / 2.0; y = 0; } else { if (paintable_aspect > 0.0) { scaled_w = widget_width; scaled_h = scaled_w / paintable_aspect; if (scaled_h > widget_height) { scaled_h = widget_height; scaled_w = scaled_h * paintable_aspect; } } else { scaled_w = widget_width; scaled_h = widget_height; } x = (widget_width - scaled_w) / 2.0; y = (widget_height - scaled_h) / 2.0; } if (self->rounded_corners) { rect.corner[0].width = 10.0; rect.corner[0].height = 10.0; rect.corner[1].width = 10.0; rect.corner[1].height = 10.0; rect.corner[2].width = 10.0; rect.corner[2].height = 10.0; rect.corner[3].width = 10.0; rect.corner[3].height = 10.0; if (self->top_half) { rect.bounds = GRAPHENE_RECT_INIT (x, y, scaled_w, scaled_h); gtk_snapshot_push_rounded_clip (snapshot, &rect); gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, widget_width, widget_height)); } else { rect.bounds = GRAPHENE_RECT_INIT (0, 0, widget_width, widget_height); gtk_snapshot_push_rounded_clip (snapshot, &rect); } } gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); /* TODO: doesn't handle all cases properly */ if (self->filter == GSK_SCALING_FILTER_NEAREST && BZ_IS_ASYNC_TEXTURE (self->paintable)) { g_autoptr (GdkTexture) texture = NULL; texture = bz_async_texture_dup_texture (BZ_ASYNC_TEXTURE (self->paintable)); if (texture != NULL) gtk_snapshot_append_scaled_texture ( snapshot, texture, self->filter, &GRAPHENE_RECT_INIT (0.0, 0.0, scaled_w, scaled_h)); } else if (self->filter == GSK_SCALING_FILTER_NEAREST && GDK_IS_TEXTURE (self->paintable)) gtk_snapshot_append_scaled_texture ( snapshot, GDK_TEXTURE (self->paintable), self->filter, &GRAPHENE_RECT_INIT (0.0, 0.0, scaled_w, scaled_h)); else gdk_paintable_snapshot (self->paintable, snapshot, scaled_w, scaled_h); if (self->rounded_corners) { gtk_snapshot_pop (snapshot); if (self->top_half) gtk_snapshot_pop (snapshot); } } static void bz_screenshot_class_init (BzScreenshotClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_screenshot_dispose; object_class->get_property = bz_screenshot_get_property; object_class->set_property = bz_screenshot_set_property; props[PROP_PAINTABLE] = g_param_spec_object ( "paintable", NULL, NULL, GDK_TYPE_PAINTABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FOCUS_X] = g_param_spec_double ( "focus-x", NULL, NULL, -1.0, G_MAXDOUBLE, -1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FOCUS_Y] = g_param_spec_double ( "focus-y", NULL, NULL, -1.0, G_MAXDOUBLE, -1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_ROUNDED_CORNERS] = g_param_spec_boolean ( "rounded-corners", NULL, NULL, TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TOP_HALF] = g_param_spec_boolean ( "top-half", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FILTER] = g_param_spec_enum ( "filter", NULL, NULL, GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_TRILINEAR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->get_request_mode = bz_screenshot_get_request_mode; widget_class->measure = bz_screenshot_measure; widget_class->snapshot = bz_screenshot_snapshot; } static void bz_screenshot_init (BzScreenshot *self) { self->focus_x = -1.0; self->focus_y = -1.0; self->rounded_corners = TRUE; self->top_half = FALSE; self->filter = GSK_SCALING_FILTER_TRILINEAR; } GtkWidget * bz_screenshot_new (void) { return g_object_new (BZ_TYPE_SCREENSHOT, NULL); } void bz_screenshot_set_paintable (BzScreenshot *self, GdkPaintable *paintable) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); g_return_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable)); if (self->paintable != NULL) { g_signal_handlers_disconnect_by_func (self->paintable, invalidate_contents, self); g_signal_handlers_disconnect_by_func (self->paintable, invalidate_size, self); g_signal_handlers_disconnect_by_func (self->paintable, async_loaded, self); } g_clear_object (&self->paintable); if (paintable != NULL) { self->paintable = g_object_ref (paintable); g_signal_connect_swapped (paintable, "invalidate-contents", G_CALLBACK (invalidate_contents), self); g_signal_connect_swapped (paintable, "invalidate-size", G_CALLBACK (invalidate_size), self); if (BZ_IS_ASYNC_TEXTURE (paintable)) g_signal_connect_swapped (paintable, "notify::loaded", G_CALLBACK (async_loaded), self); } gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PAINTABLE]); } GdkPaintable * bz_screenshot_get_paintable (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), NULL); return self->paintable; } void bz_screenshot_set_focus_x (BzScreenshot *self, double focus_x) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); self->focus_x = focus_x; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FOCUS_X]); } double bz_screenshot_get_focus_x (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), 0.0); return self->focus_x; } void bz_screenshot_set_focus_y (BzScreenshot *self, double focus_y) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); self->focus_y = focus_y; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FOCUS_Y]); } double bz_screenshot_get_focus_y (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), 0.0); return self->focus_y; } void bz_screenshot_set_rounded_corners (BzScreenshot *self, gboolean rounded_corners) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); if (self->rounded_corners == rounded_corners) return; self->rounded_corners = rounded_corners; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ROUNDED_CORNERS]); } gboolean bz_screenshot_get_rounded_corners (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), TRUE); return self->rounded_corners; } void bz_screenshot_set_top_half (BzScreenshot *self, gboolean top_half) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); if (self->top_half == top_half) return; self->top_half = top_half; gtk_widget_queue_resize (GTK_WIDGET (self)); gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TOP_HALF]); } gboolean bz_screenshot_get_top_half (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), FALSE); return self->top_half; } void bz_screenshot_set_filter (BzScreenshot *self, GskScalingFilter filter) { g_return_if_fail (BZ_IS_SCREENSHOT (self)); if (self->filter == filter) return; self->filter = filter; gtk_widget_queue_draw (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FILTER]); } GskScalingFilter bz_screenshot_get_filter (BzScreenshot *self) { g_return_val_if_fail (BZ_IS_SCREENSHOT (self), FALSE); return self->filter; } static void invalidate_contents (BzScreenshot *self, GdkPaintable *paintable) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void invalidate_size (BzScreenshot *self, GdkPaintable *paintable) { gtk_widget_queue_resize (GTK_WIDGET (self)); } static void async_loaded (BzScreenshot *self, GParamSpec *pspec, BzAsyncTexture *texture) { gtk_widget_queue_draw (GTK_WIDGET (self)); gtk_widget_queue_resize (GTK_WIDGET (self)); } kolunmi-bazaar-7b9c8e1/src/bz-screenshot.h000066400000000000000000000037441514314607700206200ustar00rootroot00000000000000/* bz-screenshot.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_SCREENSHOT (bz_screenshot_get_type ()) G_DECLARE_FINAL_TYPE (BzScreenshot, bz_screenshot, BZ, SCREENSHOT, GtkWidget) GtkWidget * bz_screenshot_new (void); void bz_screenshot_set_paintable (BzScreenshot *self, GdkPaintable *paintable); GdkPaintable * bz_screenshot_get_paintable (BzScreenshot *self); void bz_screenshot_set_focus_x (BzScreenshot *self, double focus_x); double bz_screenshot_get_focus_x (BzScreenshot *self); void bz_screenshot_set_focus_y (BzScreenshot *self, double focus_y); double bz_screenshot_get_focus_y (BzScreenshot *self); void bz_screenshot_set_rounded_corners (BzScreenshot *self, gboolean rounded_corners); gboolean bz_screenshot_get_rounded_corners (BzScreenshot *self); void bz_screenshot_set_top_half (BzScreenshot *self, gboolean top_half); gboolean bz_screenshot_get_top_half (BzScreenshot *self); void bz_screenshot_set_filter (BzScreenshot *self, GskScalingFilter filter); GskScalingFilter bz_screenshot_get_filter (BzScreenshot *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-screenshots-carousel.blp000066400000000000000000000042121514314607700231330ustar00rootroot00000000000000using Gtk 4.0; template $BzScreenshotsCarousel: Gtk.Widget { accessibility { label: _("Screenshots Carousel"); } styles [ "screenshot-carousel", "frame", "carousel-box", ] layout-manager: Gtk.BinLayout {}; Gtk.Overlay { halign: fill; valign: fill; child: Gtk.Box { orientation: vertical; halign: fill; valign: fill; $BzCarousel carousel { vexpand: true; hexpand: true; valign: center; height-request: bind $get_carousel_height(template.compact) as ; notify::position => $on_notify_position() swapped; notify::n-pages => $on_notify_n_pages() swapped; } $BzCarouselIndicatorDots carousel_indicator { carousel: carousel; opacity: 0; hexpand: true; halign: center; styles [ "boxed-indicator", "indicator-box", ] } }; [overlay] Gtk.Revealer prev_button_revealer { transition-type: crossfade; reveal-child: false; halign: start; valign: center; can-focus: false; Gtk.Button prev_button { icon-name: "go-previous-symbolic"; valign: center; halign: start; clicked => $on_prev_clicked() swapped; styles [ "circular", "osd", ] } } [overlay] Gtk.Revealer next_button_revealer { transition-type: crossfade; reveal-child: false; halign: end; valign: center; can-focus: false; Gtk.Button next_button { icon-name: "go-next-symbolic"; valign: center; clicked => $on_next_clicked() swapped; styles [ "circular", "osd", ] } } [overlay] Box { styles [ "osd-box", "pip-button", ] margin-end: 8; margin-bottom: 8; halign: end; valign: end; can-focus:false; Gtk.Button { icon-name: "pip-out-symbolic"; tooltip-text: _("Open Screenshot Viewer"); clicked => $on_expand_clicked() swapped; styles [ "flat", ] } } } } kolunmi-bazaar-7b9c8e1/src/bz-screenshots-carousel.c000066400000000000000000000510271514314607700226060ustar00rootroot00000000000000/* bz-screenshots-carousel.c * * Copyright 2025 Alexander Vanhee * * Adapted from gs-screenshot-carousel.c * * Copyright (C) 2013-2016 Richard Hughes * Copyright (C) 2013 Matthias Clasen * Copyright (C) 2015-2019 Kalev Lember * Copyright (C) 2019 Joaquim Rocha * Copyright (C) 2021 Adrien Plazas * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-carousel-indicator-dots.h" #include "bz-carousel.h" #include "bz-decorated-screenshot.h" #include "bz-screenshots-carousel.h" #define LIGHT_CLASS "screenshot-carousel-light" #define DARK_CLASS "screenshot-carousel-dark" #define LIGHT_MIX_PERCENTAGE 15 #define DARK_MIX_PERCENTAGE 4 struct _BzScreenshotsCarousel { GtkWidget parent_instance; BzCarousel *carousel; GtkWidget *carousel_indicator; GtkButton *prev_button; GtkWidget *prev_button_revealer; GtkButton *next_button; GtkWidget *next_button_revealer; GListModel *model; gboolean compact; char *light_accent_color; char *dark_accent_color; char *widget_css_class; GtkCssProvider *css; gulong items_changed_id; }; G_DEFINE_FINAL_TYPE (BzScreenshotsCarousel, bz_screenshots_carousel, GTK_TYPE_WIDGET) enum { PROP_0, PROP_MODEL, PROP_COMPACT, PROP_LIGHT_ACCENT_COLOR, PROP_DARK_ACCENT_COLOR, N_PROPS }; static GParamSpec *properties[N_PROPS]; enum { SIGNAL_CLICKED, N_SIGNALS }; static guint signals[N_SIGNALS]; static void refresh_css (BzScreenshotsCarousel *self); static void clear_css (BzScreenshotsCarousel *self); static gboolean is_window_wide (BzScreenshotsCarousel *self) { GtkRoot *root; int width, height; root = gtk_widget_get_root (GTK_WIDGET (self)); if (root == NULL || !GTK_IS_WINDOW (root)) return FALSE; gtk_window_get_default_size (GTK_WINDOW (root), &width, &height); return width > 1000; } static void update_button_visibility (BzScreenshotsCarousel *self) { gdouble position; guint n_pages; if (!self->carousel) return; position = bz_carousel_get_position (self->carousel); n_pages = bz_carousel_get_n_pages (self->carousel); gtk_widget_set_opacity (self->carousel_indicator, n_pages > 1); gtk_revealer_set_reveal_child (GTK_REVEALER (self->prev_button_revealer), position >= 0.5); gtk_revealer_set_reveal_child (GTK_REVEALER (self->next_button_revealer), position < n_pages - 1.5); } static void carousel_navigate (BzCarousel *carousel, AdwNavigationDirection direction) { g_autolist (GtkWidget) children = NULL; gdouble position = 0.0; guint n_children = 0; GtkWidget *nth_child = NULL; for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (carousel)); child != NULL; child = gtk_widget_get_next_sibling (child)) { children = g_list_prepend (children, g_object_ref (child)); n_children++; } children = g_list_reverse (children); position = bz_carousel_get_position (carousel); position += (direction == ADW_NAVIGATION_DIRECTION_BACK) ? -1 : 1; position = round (position); position = MIN (position, n_children - 1); position = MAX (0, position); nth_child = g_list_nth_data (children, position); if (nth_child != NULL) bz_carousel_scroll_to (carousel, nth_child, TRUE); } static void on_prev_clicked (BzScreenshotsCarousel *self) { if (!self->carousel) return; carousel_navigate (self->carousel, ADW_NAVIGATION_DIRECTION_BACK); } static void on_next_clicked (BzScreenshotsCarousel *self) { if (!self->carousel) return; carousel_navigate (self->carousel, ADW_NAVIGATION_DIRECTION_FORWARD); } static void on_notify_position (BzScreenshotsCarousel *self) { update_button_visibility (self); } static void on_notify_n_pages (BzScreenshotsCarousel *self) { update_button_visibility (self); } static void open_screenshot_at_index (BzScreenshotsCarousel *self, guint index) { guint n_items; if (!self->model) return; n_items = g_list_model_get_n_items (self->model); if (index >= n_items) return; g_signal_emit (self, signals[SIGNAL_CLICKED], 0, index); } static void on_screenshot_clicked (BzDecoratedScreenshot *screenshot, BzScreenshotsCarousel *self) { BzAsyncTexture *async_texture = NULL; guint index = 0; guint n_items = 0; if (!self->model) return; async_texture = bz_decorated_screenshot_get_async_texture (screenshot); if (async_texture == NULL) return; n_items = g_list_model_get_n_items (self->model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzAsyncTexture) item = NULL; item = g_list_model_get_item (self->model, i); if (item == async_texture) { index = i; break; } } open_screenshot_at_index (self, index); } static void on_expand_clicked (BzScreenshotsCarousel *self) { gdouble position; guint index; guint n_pages; if (!self->carousel || !self->model) return; n_pages = bz_carousel_get_n_pages (self->carousel); if (n_pages == 0) return; position = bz_carousel_get_position (self->carousel); index = (guint) round (position); index = MIN (index, n_pages - 1); open_screenshot_at_index (self, index); } static int get_carousel_height (BzScreenshotsCarousel *self) { return self->compact ? 250 : 375; } static void on_screenshot_focus_changed (BzDecoratedScreenshot *screenshot, GParamSpec *pspec, BzScreenshotsCarousel *self) { if (!self->carousel) return; if (gtk_widget_has_focus (GTK_WIDGET (screenshot))) bz_carousel_scroll_to (self->carousel, GTK_WIDGET (screenshot), TRUE); } static void populate_carousel (BzScreenshotsCarousel *self) { guint i; guint n_items = 0; gboolean wide = FALSE; GList *widgets = NULL; if (!self->carousel || self->model == NULL) return; n_items = g_list_model_get_n_items (self->model); wide = is_window_wide (self); for (i = 0; i < n_items; i++) { g_autoptr (GdkPaintable) paintable = NULL; GtkWidget *screenshot; guint index; if (wide && i == 0 && n_items > 3) index = 1; else if (wide && i == 1 && n_items > 3) index = 0; else index = i; paintable = g_list_model_get_item (self->model, index); screenshot = g_object_new (BZ_TYPE_DECORATED_SCREENSHOT, "async-texture", paintable, NULL); g_signal_connect (screenshot, "clicked", G_CALLBACK (on_screenshot_clicked), self); g_signal_connect (screenshot, "notify::has-focus", G_CALLBACK (on_screenshot_focus_changed), self); widgets = g_list_append (widgets, screenshot); gtk_widget_set_visible (screenshot, TRUE); } bz_carousel_set_widgets (self->carousel, widgets); g_list_free (widgets); update_button_visibility (self); } static void on_model_items_changed (GListModel *model, guint position, guint removed, guint added, BzScreenshotsCarousel *self) { GtkWidget *child; guint n_pages; guint target_page; populate_carousel (self); n_pages = bz_carousel_get_n_pages (self->carousel); if (n_pages == 0) return; target_page = (is_window_wide (self) && model != NULL && g_list_model_get_n_items (model) >= 3) ? 1 : 0; child = bz_carousel_get_nth_page (self->carousel, target_page); if (child != NULL) bz_carousel_scroll_to (self->carousel, child, FALSE); } static void dark_changed (BzScreenshotsCarousel *self, GParamSpec *pspec, AdwStyleManager *mgr) { gboolean is_dark; if (self->css == NULL) return; is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_widget_remove_css_class (GTK_WIDGET (self), LIGHT_CLASS); gtk_widget_remove_css_class (GTK_WIDGET (self), DARK_CLASS); gtk_widget_add_css_class (GTK_WIDGET (self), is_dark ? DARK_CLASS : LIGHT_CLASS); } static void bz_screenshots_carousel_dispose (GObject *object) { BzScreenshotsCarousel *self = BZ_SCREENSHOTS_CAROUSEL (object); GtkWidget *root_child = gtk_widget_get_first_child (GTK_WIDGET (self)); if (self->model && self->items_changed_id) { g_signal_handler_disconnect (self->model, self->items_changed_id); self->items_changed_id = 0; } g_clear_object (&self->model); clear_css (self); g_clear_pointer (&self->light_accent_color, g_free); g_clear_pointer (&self->dark_accent_color, g_free); g_clear_pointer (&self->widget_css_class, g_free); if (root_child != NULL) gtk_widget_unparent (root_child); gtk_widget_dispose_template (GTK_WIDGET (self), BZ_TYPE_SCREENSHOTS_CAROUSEL); G_OBJECT_CLASS (bz_screenshots_carousel_parent_class)->dispose (object); } static void bz_screenshots_carousel_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzScreenshotsCarousel *self = BZ_SCREENSHOTS_CAROUSEL (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, self->model); break; case PROP_COMPACT: g_value_set_boolean (value, self->compact); break; case PROP_LIGHT_ACCENT_COLOR: g_value_set_string (value, self->light_accent_color); break; case PROP_DARK_ACCENT_COLOR: g_value_set_string (value, self->dark_accent_color); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_screenshots_carousel_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzScreenshotsCarousel *self = BZ_SCREENSHOTS_CAROUSEL (object); switch (prop_id) { case PROP_MODEL: bz_screenshots_carousel_set_model (self, g_value_get_object (value)); break; case PROP_COMPACT: bz_screenshots_carousel_set_compact (self, g_value_get_boolean (value)); break; case PROP_LIGHT_ACCENT_COLOR: bz_screenshots_carousel_set_light_accent_color (self, g_value_get_string (value)); break; case PROP_DARK_ACCENT_COLOR: bz_screenshots_carousel_set_dark_accent_color (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_screenshots_carousel_class_init (BzScreenshotsCarouselClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_screenshots_carousel_dispose; object_class->get_property = bz_screenshots_carousel_get_property; object_class->set_property = bz_screenshots_carousel_set_property; properties[PROP_MODEL] = g_param_spec_object ("model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_COMPACT] = g_param_spec_boolean ("compact", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_LIGHT_ACCENT_COLOR] = g_param_spec_string ("light-accent-color", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_DARK_ACCENT_COLOR] = g_param_spec_string ("dark-accent-color", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); signals[SIGNAL_CLICKED] = g_signal_new ("clicked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); g_type_ensure (BZ_TYPE_CAROUSEL); g_type_ensure (BZ_TYPE_CAROUSEL_INDICATOR_DOTS); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-screenshots-carousel.ui"); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, carousel); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, carousel_indicator); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, prev_button); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, prev_button_revealer); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, next_button); gtk_widget_class_bind_template_child (widget_class, BzScreenshotsCarousel, next_button_revealer); gtk_widget_class_bind_template_callback (widget_class, on_prev_clicked); gtk_widget_class_bind_template_callback (widget_class, on_next_clicked); gtk_widget_class_bind_template_callback (widget_class, on_notify_position); gtk_widget_class_bind_template_callback (widget_class, on_notify_n_pages); gtk_widget_class_bind_template_callback (widget_class, on_expand_clicked); gtk_widget_class_bind_template_callback (widget_class, get_carousel_height); gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); gtk_widget_class_set_css_name (widget_class, "screenshot-carousel"); } static void bz_screenshots_carousel_init (BzScreenshotsCarousel *self) { gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect_object ( adw_style_manager_get_default (), "notify::dark", G_CALLBACK (dark_changed), self, G_CONNECT_SWAPPED); } GtkWidget * bz_screenshots_carousel_new (void) { return g_object_new (BZ_TYPE_SCREENSHOTS_CAROUSEL, NULL); } void bz_screenshots_carousel_set_model (BzScreenshotsCarousel *self, GListModel *model) { g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); if (self->model == model) return; if (self->model && self->items_changed_id) { g_signal_handler_disconnect (self->model, self->items_changed_id); self->items_changed_id = 0; } g_clear_object (&self->model); if (model) { self->model = g_object_ref (model); self->items_changed_id = g_signal_connect (self->model, "items-changed", G_CALLBACK (on_model_items_changed), self); } populate_carousel (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]); } GListModel * bz_screenshots_carousel_get_model (BzScreenshotsCarousel *self) { g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self), NULL); return self->model; } void bz_screenshots_carousel_set_compact (BzScreenshotsCarousel *self, gboolean compact) { g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self)); if (self->compact == compact) return; self->compact = compact; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMPACT]); } gboolean bz_screenshots_carousel_get_compact (BzScreenshotsCarousel *self) { g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self), FALSE); return self->compact; } void bz_screenshots_carousel_set_light_accent_color (BzScreenshotsCarousel *self, const char *color) { g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self)); if (color == self->light_accent_color || (color != NULL && g_strcmp0 (self->light_accent_color, color) == 0)) return; g_clear_pointer (&self->light_accent_color, g_free); if (color != NULL) self->light_accent_color = g_strdup (color); refresh_css (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LIGHT_ACCENT_COLOR]); } const char * bz_screenshots_carousel_get_light_accent_color (BzScreenshotsCarousel *self) { g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self), NULL); return self->light_accent_color; } void bz_screenshots_carousel_set_dark_accent_color (BzScreenshotsCarousel *self, const char *color) { g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self)); if (color == self->dark_accent_color || (color != NULL && g_strcmp0 (self->dark_accent_color, color) == 0)) return; g_clear_pointer (&self->dark_accent_color, g_free); if (color != NULL) self->dark_accent_color = g_strdup (color); refresh_css (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DARK_ACCENT_COLOR]); } const char * bz_screenshots_carousel_get_dark_accent_color (BzScreenshotsCarousel *self) { g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self), NULL); return self->dark_accent_color; } static void refresh_css (BzScreenshotsCarousel *self) { g_autofree char *css_string = NULL; g_autofree char *light_bg = NULL; g_autofree char *dark_bg = NULL; gboolean is_dark; clear_css (self); if (self->light_accent_color == NULL && self->dark_accent_color == NULL) return; self->widget_css_class = g_strdup_printf ("screenshot-carousel-%p", (void *) self); gtk_widget_add_css_class (GTK_WIDGET (self), self->widget_css_class); if (self->light_accent_color != NULL && self->dark_accent_color != NULL) light_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(255,255,255))", self->light_accent_color, LIGHT_MIX_PERCENTAGE); else if (self->light_accent_color != NULL) light_bg = g_strdup (self->light_accent_color); else if (self->dark_accent_color != NULL) light_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(255,255,255))", self->dark_accent_color, LIGHT_MIX_PERCENTAGE); if (self->light_accent_color != NULL && self->dark_accent_color != NULL) dark_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(29,29,32))", self->dark_accent_color, DARK_MIX_PERCENTAGE); else if (self->dark_accent_color != NULL) dark_bg = g_strdup (self->dark_accent_color); else if (self->light_accent_color != NULL) dark_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(29,29,32))", self->light_accent_color, DARK_MIX_PERCENTAGE); css_string = g_strdup_printf ( ".%s.%s{background-color:%s;}\n" ".%s.%s{background-color:%s;}", self->widget_css_class, LIGHT_CLASS, light_bg, self->widget_css_class, DARK_CLASS, dark_bg); self->css = gtk_css_provider_new (); gtk_css_provider_load_from_string (self->css, css_string); gtk_style_context_add_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (self->css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_widget_add_css_class (GTK_WIDGET (self), is_dark ? DARK_CLASS : LIGHT_CLASS); } static void clear_css (BzScreenshotsCarousel *self) { gtk_widget_remove_css_class (GTK_WIDGET (self), LIGHT_CLASS); gtk_widget_remove_css_class (GTK_WIDGET (self), DARK_CLASS); if (self->widget_css_class != NULL) { gtk_widget_remove_css_class (GTK_WIDGET (self), self->widget_css_class); g_clear_pointer (&self->widget_css_class, g_free); } if (self->css != NULL) gtk_style_context_remove_provider_for_display ( gdk_display_get_default (), GTK_STYLE_PROVIDER (self->css)); g_clear_pointer (&self->css, g_object_unref); } kolunmi-bazaar-7b9c8e1/src/bz-screenshots-carousel.h000066400000000000000000000037221514314607700226120ustar00rootroot00000000000000/* bz-screenshots-carousel.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_SCREENSHOTS_CAROUSEL (bz_screenshots_carousel_get_type ()) G_DECLARE_FINAL_TYPE (BzScreenshotsCarousel, bz_screenshots_carousel, BZ, SCREENSHOTS_CAROUSEL, GtkWidget) GtkWidget * bz_screenshots_carousel_new (void); void bz_screenshots_carousel_set_model (BzScreenshotsCarousel *self, GListModel *model); GListModel * bz_screenshots_carousel_get_model (BzScreenshotsCarousel *self); void bz_screenshots_carousel_set_compact (BzScreenshotsCarousel *self, gboolean compact); gboolean bz_screenshots_carousel_get_compact (BzScreenshotsCarousel *self); void bz_screenshots_carousel_set_light_accent_color (BzScreenshotsCarousel *self, const char *color); const char * bz_screenshots_carousel_get_light_accent_color (BzScreenshotsCarousel *self); void bz_screenshots_carousel_set_dark_accent_color (BzScreenshotsCarousel *self, const char *color); const char * bz_screenshots_carousel_get_dark_accent_color (BzScreenshotsCarousel *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-search-engine.c000066400000000000000000000377371514314607700211570ustar00rootroot00000000000000/* bz-search-engine.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-search-engine.h" #include "bz-entry-group.h" #include "bz-env.h" #include "bz-search-result.h" #include "bz-util.h" struct _BzSearchEngine { GObject parent_instance; GListModel *model; }; G_DEFINE_FINAL_TYPE (BzSearchEngine, bz_search_engine, G_TYPE_OBJECT); enum { PROP_0, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static double test_strings (const char *query, const char *against, gssize accept_min_size); typedef struct { guint idx; double val; } Score; static gint cmp_scores (Score *a, Score *b); #define PERFECT 1.0 #define ALMOST_PERFECT 0.95 #define SAME_CLASS 0.2 #define SAME_CLUSTER 0.1 #define NO_MATCH 0.0 BZ_DEFINE_DATA ( query_task, QueryTask, { char **terms; GPtrArray *snapshot; }, BZ_RELEASE_DATA (terms, g_strfreev); BZ_RELEASE_DATA (snapshot, g_ptr_array_unref)) static DexFuture * query_task_fiber (QueryTaskData *data); BZ_DEFINE_DATA ( query_sub_task, QuerySubTask, { char *query_utf8; GPtrArray *shallow_mirror; double threshold; guint work_offset; guint work_length; }, BZ_RELEASE_DATA (query_utf8, g_free); BZ_RELEASE_DATA (shallow_mirror, g_ptr_array_unref)); static DexFuture * query_sub_task_fiber (QuerySubTaskData *data); static inline GUnicodeType utf8_char_class (const char *s, gunichar *ch_out); static inline const char * utf8_skip_to_next_of_class (const char **s, GUnicodeType class, gsize *read_utf8); static void bz_search_engine_dispose (GObject *object) { BzSearchEngine *self = BZ_SEARCH_ENGINE (object); g_clear_object (&self->model); G_OBJECT_CLASS (bz_search_engine_parent_class)->dispose (object); } static void bz_search_engine_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSearchEngine *self = BZ_SEARCH_ENGINE (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_search_engine_get_model (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_search_engine_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSearchEngine *self = BZ_SEARCH_ENGINE (object); switch (prop_id) { case PROP_MODEL: bz_search_engine_set_model (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_search_engine_class_init (BzSearchEngineClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_search_engine_set_property; object_class->get_property = bz_search_engine_get_property; object_class->dispose = bz_search_engine_dispose; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_search_engine_init (BzSearchEngine *self) { } BzSearchEngine * bz_search_engine_new (void) { return g_object_new (BZ_TYPE_SEARCH_ENGINE, NULL); } GListModel * bz_search_engine_get_model (BzSearchEngine *self) { g_return_val_if_fail (BZ_IS_SEARCH_ENGINE (self), NULL); return self->model; } void bz_search_engine_set_model (BzSearchEngine *self, GListModel *model) { g_return_if_fail (BZ_IS_SEARCH_ENGINE (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); g_clear_object (&self->model); if (model != NULL) self->model = g_object_ref (model); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } DexFuture * bz_search_engine_query (BzSearchEngine *self, const char *const *terms) { guint n_groups = 0; dex_return_error_if_fail (BZ_IS_SEARCH_ENGINE (self)); dex_return_error_if_fail (terms != NULL && *terms != NULL); if (self->model != NULL) n_groups = g_list_model_get_n_items (self->model); if (self->model == NULL || n_groups == 0 || **terms == '\0') { g_autoptr (GPtrArray) ret = NULL; ret = g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_set_size (ret, n_groups); for (guint i = 0; i < ret->len; i++) { g_autoptr (BzEntryGroup) group = NULL; g_autoptr (BzSearchResult) result = NULL; group = g_list_model_get_item (self->model, i); result = bz_search_result_new (); bz_search_result_set_group (result, group); bz_search_result_set_original_index (result, i); g_ptr_array_index (ret, i) = g_steal_pointer (&result); } return dex_future_new_take_boxed ( G_TYPE_PTR_ARRAY, g_steal_pointer (&ret)); } else { g_autoptr (GPtrArray) snapshot = NULL; g_autoptr (QueryTaskData) data = NULL; snapshot = g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_set_size (snapshot, n_groups); for (guint i = 0; i < snapshot->len; i++) g_ptr_array_index (snapshot, i) = g_list_model_get_item (self->model, i); data = query_task_data_new (); data->terms = g_strdupv ((gchar **) terms); data->snapshot = g_steal_pointer (&snapshot); return dex_scheduler_spawn ( dex_thread_pool_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) query_task_fiber, query_task_data_ref (data), query_task_data_unref); } } static DexFuture * query_task_fiber (QueryTaskData *data) { char **terms = data->terms; GPtrArray *shallow_mirror = data->snapshot; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; g_autofree char *query_utf8 = NULL; guint n_sub_tasks = 0; guint scores_per_task = 0; g_autoptr (GPtrArray) sub_futures = NULL; g_autoptr (GArray) scores = NULL; g_autoptr (GPtrArray) results = NULL; query_utf8 = g_strjoinv (" ", terms); n_sub_tasks = MAX (1, MIN (shallow_mirror->len / 512, g_get_num_processors ())); scores_per_task = shallow_mirror->len / n_sub_tasks; sub_futures = g_ptr_array_new_with_free_func (dex_unref); for (guint i = 0; i < n_sub_tasks; i++) { g_autoptr (QuerySubTaskData) sub_data = NULL; g_autoptr (DexFuture) future = NULL; sub_data = query_sub_task_data_new (); sub_data->query_utf8 = g_strdup (query_utf8); sub_data->shallow_mirror = g_ptr_array_ref (shallow_mirror); sub_data->threshold = 1.0; sub_data->work_offset = i * scores_per_task; sub_data->work_length = scores_per_task; if (i >= n_sub_tasks - 1) sub_data->work_length += shallow_mirror->len % n_sub_tasks; future = dex_scheduler_spawn ( dex_thread_pool_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) query_sub_task_fiber, query_sub_task_data_ref (sub_data), query_sub_task_data_unref); g_ptr_array_add (sub_futures, g_steal_pointer (&future)); } result = dex_await (dex_future_allv ( (DexFuture *const *) sub_futures->pdata, sub_futures->len), &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); scores = g_array_new (FALSE, FALSE, sizeof (Score)); for (guint i = 0; i < sub_futures->len; i++) { DexFuture *future = NULL; GArray *scores_out = NULL; future = g_ptr_array_index (sub_futures, i); scores_out = g_value_get_boxed (dex_future_get_value (future, NULL)); if (scores_out->len > 0) g_array_append_vals (scores, scores_out->data, scores_out->len); } if (scores->len > 0) g_array_sort (scores, (GCompareFunc) cmp_scores); results = g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_set_size (results, scores->len); for (guint i = 0; i < scores->len; i++) { Score *score = NULL; BzEntryGroup *group = NULL; g_autoptr (BzSearchResult) search_result = NULL; score = &g_array_index (scores, Score, i); group = g_ptr_array_index (shallow_mirror, score->idx); search_result = bz_search_result_new (); bz_search_result_set_group (search_result, group); bz_search_result_set_original_index (search_result, score->idx); bz_search_result_set_score (search_result, score->val); g_ptr_array_index (results, i) = g_steal_pointer (&search_result); } return dex_future_new_take_boxed ( G_TYPE_PTR_ARRAY, g_steal_pointer (&results)); } static DexFuture * query_sub_task_fiber (QuerySubTaskData *data) { GPtrArray *shallow_mirror = data->shallow_mirror; char *query_utf8 = data->query_utf8; double threshold = data->threshold; guint work_offset = data->work_offset; guint work_length = data->work_length; g_autoptr (GArray) scores_out = NULL; scores_out = g_array_new (FALSE, FALSE, sizeof (Score)); for (guint i = 0; i < work_length; i++) { g_autoptr (GMutexLocker) locker = NULL; BzEntryGroup *group = NULL; const char *id = NULL; const char *title = NULL; double score = 0.0; group = g_ptr_array_index (shallow_mirror, work_offset + i); locker = bz_entry_group_lock (group); if (!bz_entry_group_is_searchable (group)) continue; id = bz_entry_group_get_id (group); title = bz_entry_group_get_title (group); if ((id != NULL && g_strcmp0 (query_utf8, id) == 0) || (title != NULL && strcasecmp (query_utf8, title) == 0)) score = G_MAXDOUBLE; else { const char *developer = NULL; const char *description = NULL; const char *search_tokens = NULL; developer = bz_entry_group_get_developer (group); description = bz_entry_group_get_description (group); search_tokens = bz_entry_group_get_search_tokens (group); #define EVALUATE_STRING(_s, _accept_min_size) \ ((_s) != NULL \ ? (test_strings (query_utf8, (_s), (_accept_min_size))) \ : 0.0) score += EVALUATE_STRING (title, 2) * 2.0; score += EVALUATE_STRING (developer, 2) * 1.0; score += EVALUATE_STRING (description, 3) * 1.0; score += EVALUATE_STRING (search_tokens, -1) * 1.5; #undef EVALUATE_STRING } if (score > threshold) { Score append = { 0 }; append.idx = work_offset + i; append.val = score; g_array_append_val (scores_out, append); } } return dex_future_new_take_boxed (G_TYPE_ARRAY, g_steal_pointer (&scores_out)); } #define UTF8_FOREACH_FORWARD(_var, _s) \ for (const char *_var = (_s); \ _var != NULL && *_var != '\0'; \ _var = g_utf8_next_char (_var)) #define UTF8_FOREACH_FORWARD_WITH_END(_var, _s, _end) \ for (const char *_var = (_s); \ _var != NULL && *_var != '\0' && _var < (_end); \ _var = g_utf8_next_char (_var)) #define UTF8_FOREACH_BACKWARD(_var, _s, _start) \ for (const char *_var = (_s); \ _var != NULL && _var >= (_start); \ _var = g_utf8_prev_char (_var)) #define UTF8_FOREACH_TOKEN_FORWARDS(_start_var, _end_var, _s, _token_len) \ for (const char *_start_var = (_s), *_end_var = utf8_skip_to_next_of_class (&_start_var, G_UNICODE_SPACE_SEPARATOR, (_token_len)); \ _start_var != NULL && *_start_var != '\0'; \ _start_var = _end_var, _end_var = utf8_skip_to_next_of_class (&_start_var, G_UNICODE_SPACE_SEPARATOR, (_token_len))) static double test_strings (const char *query, const char *against, gssize accept_min_size) { double score = 0.0; gsize full_query_utf8_length = 0; gsize full_against_utf8_length = 0; gsize query_tok_utf8_len = 0; gsize against_tok_utf8_len = 0; full_query_utf8_length = g_utf8_strlen (query, -1); full_against_utf8_length = g_utf8_strlen (against, -1); if (accept_min_size > 0 && full_against_utf8_length < accept_min_size) return 0.0; if (full_query_utf8_length <= full_against_utf8_length && strcasestr (against, query) != NULL) return (double) full_query_utf8_length; UTF8_FOREACH_TOKEN_FORWARDS (query_tok_start, query_tok_end, query, &query_tok_utf8_len) { UTF8_FOREACH_TOKEN_FORWARDS (against_tok_start, against_tok_end, against, &against_tok_utf8_len) { gboolean match = FALSE; gsize consumed = 0; if (accept_min_size > 0 && against_tok_utf8_len < accept_min_size) continue; UTF8_FOREACH_FORWARD_WITH_END (against_ptr, against_tok_start, against_tok_end) { gunichar against_ch = 0; if (query_tok_utf8_len > against_tok_utf8_len - consumed) break; match = TRUE; against_ch = g_unichar_tolower (g_utf8_get_char (against_ptr)); UTF8_FOREACH_FORWARD_WITH_END (query_ptr, query_tok_start, query_tok_end) { gunichar query_ch = 0; query_ch = g_unichar_tolower (g_utf8_get_char (query_ptr)); if (against_ch != query_ch) { match = FALSE; break; } } consumed++; if (match) break; } if (match) score += (double) (query_tok_utf8_len * query_tok_utf8_len) / (double) against_tok_utf8_len; } } return score; } static inline GUnicodeType utf8_char_class (const char *s, gunichar *ch_out) { gunichar ch = 0; GUnicodeType cl = 0; ch = g_utf8_get_char (s); cl = g_unichar_type (ch); if (ch_out != NULL) *ch_out = ch; return cl; } static inline const char * utf8_skip_to_next_of_class (const char **s, GUnicodeType class, gsize *read_utf8) { gboolean skipped = FALSE; if (read_utf8 != NULL) *read_utf8 = 0; UTF8_FOREACH_FORWARD (p, *s) { if (utf8_char_class (p, NULL) == class) { if (skipped) return p; } else { if (!skipped) { *s = p; skipped = TRUE; } if (read_utf8 != NULL) (*read_utf8)++; } } /* return the end of the string if nothing was found */ return *s + strlen (*s); } static gint cmp_scores (Score *a, Score *b) { return (b->val - a->val < 0.0) ? -1 : 1; } /* End of bz-search-engine.c */ kolunmi-bazaar-7b9c8e1/src/bz-search-engine.h000066400000000000000000000025131514314607700211440ustar00rootroot00000000000000/* bz-search-engine.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define BZ_TYPE_SEARCH_ENGINE (bz_search_engine_get_type ()) G_DECLARE_FINAL_TYPE (BzSearchEngine, bz_search_engine, BZ, SEARCH_ENGINE, GObject) BzSearchEngine * bz_search_engine_new (void); GListModel * bz_search_engine_get_model (BzSearchEngine *self); void bz_search_engine_set_model (BzSearchEngine *self, GListModel *model); DexFuture * bz_search_engine_query (BzSearchEngine *self, const char *const *terms); G_END_DECLS /* End of bz-search-engine.h */ kolunmi-bazaar-7b9c8e1/src/bz-search-result.txt000066400000000000000000000004551514314607700216100ustar00rootroot00000000000000prefix=bz name=search_result parent-prefix=g parent-name=object author=AUTOGEN include="bz-entry-group.h" property=group BzEntryGroup BZ_TYPE_ENTRY_GROUP object property=original_index guint G_TYPE_UINT uint property=score double G_TYPE_DOUBLE double property=title_markup char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-search-widget.blp000066400000000000000000000122321514314607700215070ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzSearchWidget: Adw.Bin { child: Adw.BreakpointBin { width-request: 360; height-request: 294; Adw.Breakpoint { condition ("max-width: 1000sp") setters { grid_view.min-columns: 2; grid_view.max-columns: 2; clamp_scrollable.maximum-size: 700; } } Adw.Breakpoint { condition ("max-width: 700sp") setters { empty_box.margin-start: 10; empty_box.margin-end: 10; empty_box.margin-top: 5; search_box_clamp.margin-start: 12; search_box_clamp.margin-end: 12; grid_view.min-columns: 1; grid_view.max-columns: 1; clamp_scrollable.maximum-size: 400; } } child: Box { orientation: vertical; Adw.Clamp search_box_clamp { margin-start: 12; margin-end: 12; maximum-size: 375; child: Adw.Bin { halign: fill; margin-top: 10; margin-bottom: 10; child: Box { spacing: 8; height-request: 40; Image { icon-name: "system-search-symbolic"; } Text search_bar { hexpand: true; placeholder-text: _("Search Apps, Games, Software"); } Adw.Spinner search_busy { visible: false; width-request: 16; height-request: 16; } Button clear_button { visible: bind $is_valid_string(search_bar.text) as ; icon-name: "edit-clear-symbolic"; styles [ "flat", "circular", "clear-button", ] clicked => $reset_search_cb(template); } styles [ "search-box", ] }; }; } Stack search_stack { transition-type: crossfade; StackPage { name: "empty"; child: Box { Adw.StatusPage { visible: bind $is_empty(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories) as ; hexpand: true; icon-name: "system-search-symbolic"; title: _("Categories Unavailable"); description: _("Search for apps using the search bar above."); } ScrolledWindow { hscrollbar-policy: never; visible: bind $invert_boolean($is_empty(template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories) as ) as ; child: Adw.Clamp { maximum-size: 1000; tightening-threshold: 900; valign: start; child: Box empty_box { margin-start: 30; margin-end: 30; margin-top: 20; margin-bottom: 50; $BzDynamicListView { styles [ "flathub-page-section", ] hexpand: true; max-children-per-line: 4; scroll: false; noscroll-kind: flow-box; child-type: "BzCategoryTile"; child-prop: "category"; model: bind template.state as <$BzStateInfo>.flathub as <$BzFlathubState>.categories; bind-widget => $bind_category_tile_cb(template); unbind-widget => $unbind_category_tile_cb(template); } }; }; } }; } StackPage { name: "results"; child: Box content_box { orientation: horizontal; visible: bind $invert_boolean($is_null(grid_view.model as .selected-item) as ) as ; ScrolledWindow entry_grid_scroll { hexpand: true; vexpand: true; hscrollbar-policy: never; child: Adw.ClampScrollable clamp_scrollable { maximum-size: 1000; tightening-threshold: 900; child: GridView grid_view { styles [ "search-grid", ] min-columns: 3; max-columns: 3; factory: BuilderListItemFactory { template ListItem { child: $BzRichAppTile { group: bind template.item as <$BzSearchResult>.group as <$BzEntryGroup>; install-clicked => $tile_install_clicked_cb(template); activated => $tile_activated_cb(template); }; } }; }; }; } }; } StackPage { name: "no-results"; child: Adw.StatusPage { vexpand: true; icon-name: "edit-find-symbolic"; title: _("No Applications Found"); description: bind $no_results_found_subtitle(search_bar.text) as ; }; } } }; }; } kolunmi-bazaar-7b9c8e1/src/bz-search-widget.c000066400000000000000000000537371514314607700211730ustar00rootroot00000000000000/* bz-search-widget.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-apps-page.h" #include "bz-async-texture.h" #include "bz-category-tile.h" #include "bz-dynamic-list-view.h" #include "bz-group-tile-css-watcher.h" #include "bz-rich-app-tile.h" #include "bz-screenshot.h" #include "bz-search-result.h" #include "bz-search-widget.h" #include "bz-util.h" struct _BzSearchWidget { AdwBin parent_instance; BzStateInfo *state; BzEntryGroup *selected; gboolean remove; gboolean search_in_progress; BzContentProvider *blocklists_provider; BzContentProvider *txt_blocklists_provider; GListStore *search_model; GtkSelectionModel *selection_model; guint search_update_timeout; DexFuture *search_query; /* Template widgets */ GtkText *search_bar; AdwSpinner *search_busy; GtkBox *content_box; GtkStack *search_stack; GtkGridView *grid_view; }; G_DEFINE_FINAL_TYPE (BzSearchWidget, bz_search_widget, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, PROP_TEXT, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SELECT, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void search_changed (GtkEditable *editable, BzSearchWidget *self); static void search_activate (GtkText *text, BzSearchWidget *self); static void grid_activate (GtkGridView *grid_view, guint position, BzSearchWidget *self); static void invalidating_state_prop_changed (BzSearchWidget *self, GParamSpec *pspec, BzStateInfo *info); static void blocklists_items_changed (BzSearchWidget *self, guint position, guint removed, guint added, GListModel *model); static DexFuture * search_query_then (DexFuture *future, GWeakRef *wr); static void update_filter (BzSearchWidget *self); static void emit_idx (BzSearchWidget *self, GListModel *model, guint selected_idx); static void bz_search_widget_dispose (GObject *object) { BzSearchWidget *self = BZ_SEARCH_WIDGET (object); if (self->state != NULL) g_signal_handlers_disconnect_by_func (self->state, invalidating_state_prop_changed, self); if (self->blocklists_provider != NULL) g_signal_handlers_disconnect_by_func (self->blocklists_provider, blocklists_items_changed, self); if (self->txt_blocklists_provider != NULL) g_signal_handlers_disconnect_by_func (self->txt_blocklists_provider, blocklists_items_changed, self); g_clear_handle_id (&self->search_update_timeout, g_source_remove); dex_clear (&self->search_query); g_clear_object (&self->state); g_clear_object (&self->selected); g_clear_object (&self->blocklists_provider); g_clear_object (&self->txt_blocklists_provider); g_clear_object (&self->search_model); g_clear_object (&self->selection_model); G_OBJECT_CLASS (bz_search_widget_parent_class)->dispose (object); } static void bz_search_widget_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSearchWidget *self = BZ_SEARCH_WIDGET (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_search_widget_get_state (self)); break; case PROP_TEXT: g_value_set_string (value, bz_search_widget_get_text (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_search_widget_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSearchWidget *self = BZ_SEARCH_WIDGET (object); switch (prop_id) { case PROP_STATE: bz_search_widget_set_state (self, g_value_get_object (value)); break; case PROP_TEXT: bz_search_widget_set_text (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_empty (gpointer object, GListModel *model) { if (model == NULL) return TRUE; return g_list_model_get_n_items (model) == 0; } static gboolean is_valid_string (gpointer object, const char *value) { return value != NULL && *value != '\0'; } static char * idx_to_string (gpointer object, guint value) { return g_strdup_printf ("%d", value + 1); } static char * score_to_string (gpointer object, double value) { return g_strdup_printf ("%0.1f", value); } static char * no_results_found_subtitle (gpointer object, const char *search_text) { if (search_text == NULL || *search_text == '\0') return g_strdup (""); return g_strdup_printf (_ ("No results found for \"%s\" in Flathub"), search_text); } static void apps_page_select_cb (BzSearchWidget *self, BzEntryGroup *group, BzAppsPage *page) { g_signal_emit (self, signals[SIGNAL_SELECT], 0, group, FALSE); } static void category_clicked (BzFlathubCategory *category, GtkButton *button) { GtkWidget *self = NULL; GtkWidget *nav_view = NULL; AdwNavigationPage *apps_page = NULL; self = gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_SEARCH_WIDGET); g_assert (self != NULL); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); g_assert (nav_view != NULL); apps_page = bz_apps_page_new_from_category (category); g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb), self); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } static void bind_category_tile_cb (BzSearchWidget *self, BzCategoryTile *tile, BzFlathubCategory *category, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (category_clicked), category); } static void unbind_category_tile_cb (BzSearchWidget *self, BzCategoryTile *tile, BzFlathubCategory *category, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (tile, category_clicked, category); } static void tile_activated_cb (GtkListItem *list_item, BzRichAppTile *tile) { BzSearchWidget *self = NULL; BzSearchResult *result = NULL; BzEntryGroup *group = NULL; g_assert (GTK_IS_LIST_ITEM (list_item)); g_assert (BZ_IS_RICH_APP_TILE (tile)); self = BZ_SEARCH_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_SEARCH_WIDGET)); result = gtk_list_item_get_item (list_item); group = bz_search_result_get_group (result); g_signal_emit (self, signals[SIGNAL_SELECT], 0, group, FALSE); } static void reset_search_cb (BzSearchWidget *self, GtkButton *button) { bz_search_widget_set_text (self, ""); bz_search_widget_refresh (self); } static void tile_install_clicked_cb (GtkListItem *list_item, BzRichAppTile *tile) { BzSearchWidget *self = NULL; BzSearchResult *result = NULL; BzEntryGroup *group = NULL; self = BZ_SEARCH_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (tile), BZ_TYPE_SEARCH_WIDGET)); g_assert (self != NULL); result = gtk_list_item_get_item (list_item); group = bz_search_result_get_group (result); g_signal_emit (self, signals[SIGNAL_SELECT], 0, group, TRUE); } static void bz_search_widget_class_init (BzSearchWidgetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_search_widget_dispose; object_class->get_property = bz_search_widget_get_property; object_class->set_property = bz_search_widget_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TEXT] = g_param_spec_string ( "text", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SELECT] = g_signal_new ( "select", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, BZ_TYPE_ENTRY_GROUP, G_TYPE_BOOLEAN); g_type_ensure (BZ_TYPE_ASYNC_TEXTURE); g_type_ensure (BZ_TYPE_CATEGORY_TILE); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_GROUP_TILE_CSS_WATCHER); g_type_ensure (BZ_TYPE_RICH_APP_TILE); g_type_ensure (BZ_TYPE_SCREENSHOT); g_type_ensure (BZ_TYPE_SEARCH_RESULT); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-search-widget.ui"); gtk_widget_class_bind_template_child (widget_class, BzSearchWidget, search_bar); gtk_widget_class_bind_template_child (widget_class, BzSearchWidget, search_busy); gtk_widget_class_bind_template_child (widget_class, BzSearchWidget, content_box); gtk_widget_class_bind_template_child (widget_class, BzSearchWidget, search_stack); gtk_widget_class_bind_template_child (widget_class, BzSearchWidget, grid_view); gtk_widget_class_bind_template_callback (widget_class, bind_category_tile_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_category_tile_cb); gtk_widget_class_bind_template_callback (widget_class, tile_install_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_empty); gtk_widget_class_bind_template_callback (widget_class, is_valid_string); gtk_widget_class_bind_template_callback (widget_class, idx_to_string); gtk_widget_class_bind_template_callback (widget_class, score_to_string); gtk_widget_class_bind_template_callback (widget_class, reset_search_cb); gtk_widget_class_bind_template_callback (widget_class, no_results_found_subtitle); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); } static void bz_search_widget_init (BzSearchWidget *self) { self->search_model = g_list_store_new (BZ_TYPE_SEARCH_RESULT); gtk_widget_init_template (GTK_WIDGET (self)); /* TODO: move all this to blueprint */ self->selection_model = GTK_SELECTION_MODEL (gtk_no_selection_new (NULL)); gtk_no_selection_set_model (GTK_NO_SELECTION (self->selection_model), G_LIST_MODEL (self->search_model)); gtk_grid_view_set_model (self->grid_view, self->selection_model); g_signal_connect (self->search_bar, "changed", G_CALLBACK (search_changed), self); g_signal_connect (self->search_bar, "activate", G_CALLBACK (search_activate), self); g_signal_connect (self->grid_view, "activate", G_CALLBACK (grid_activate), self); } GtkWidget * bz_search_widget_new (GListModel *model, const char *initial) { BzSearchWidget *self = NULL; self = g_object_new ( BZ_TYPE_SEARCH_WIDGET, "model", model, NULL); if (initial != NULL) gtk_editable_set_text (GTK_EDITABLE (self->search_bar), initial); return GTK_WIDGET (self); } BzEntryGroup * bz_search_widget_get_selected (BzSearchWidget *self, gboolean *remove) { g_return_val_if_fail (BZ_IS_SEARCH_WIDGET (self), NULL); if (remove != NULL) *remove = self->remove; return self->selected; } void bz_search_widget_set_state (BzSearchWidget *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_SEARCH_WIDGET (self)); if (self->state != NULL) g_signal_handlers_disconnect_by_func (self->state, invalidating_state_prop_changed, self); g_clear_object (&self->state); if (self->blocklists_provider != NULL) g_signal_handlers_disconnect_by_func (self->blocklists_provider, blocklists_items_changed, self); g_clear_object (&self->blocklists_provider); if (self->txt_blocklists_provider != NULL) g_signal_handlers_disconnect_by_func (self->txt_blocklists_provider, blocklists_items_changed, self); g_clear_object (&self->txt_blocklists_provider); if (state != NULL) { self->state = g_object_ref (state); g_signal_connect_swapped ( state, "notify::disable-blocklists", G_CALLBACK (invalidating_state_prop_changed), self); g_signal_connect_swapped ( state, "notify::hide-eol", G_CALLBACK (invalidating_state_prop_changed), self); g_signal_connect_swapped ( state, "notify::show-only-foss", G_CALLBACK (invalidating_state_prop_changed), self); g_signal_connect_swapped ( state, "notify::show-only-flathub", G_CALLBACK (invalidating_state_prop_changed), self); g_signal_connect_swapped ( state, "notify::show-only-verified", G_CALLBACK (invalidating_state_prop_changed), self); g_object_get ( state, "blocklists-provider", &self->blocklists_provider, "txt-blocklists-provider", &self->txt_blocklists_provider, NULL); if (self->blocklists_provider != NULL) g_signal_connect_data ( self->blocklists_provider, "items-changed", G_CALLBACK (blocklists_items_changed), self, NULL, G_CONNECT_SWAPPED | G_CONNECT_AFTER); if (self->txt_blocklists_provider != NULL) g_signal_connect_data ( self->txt_blocklists_provider, "items-changed", G_CALLBACK (blocklists_items_changed), self, NULL, G_CONNECT_SWAPPED | G_CONNECT_AFTER); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } BzStateInfo * bz_search_widget_get_state (BzSearchWidget *self) { g_return_val_if_fail (BZ_IS_SEARCH_WIDGET (self), NULL); return self->state; } void bz_search_widget_set_text (BzSearchWidget *self, const char *text) { g_return_if_fail (BZ_IS_SEARCH_WIDGET (self)); gtk_editable_set_text (GTK_EDITABLE (self->search_bar), text); if (text != NULL) gtk_editable_set_position (GTK_EDITABLE (self->search_bar), g_utf8_strlen (text, -1)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TEXT]); } const char * bz_search_widget_get_text (BzSearchWidget *self) { g_return_val_if_fail (BZ_IS_SEARCH_WIDGET (self), NULL); return gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); } void bz_search_widget_refresh (BzSearchWidget *self) { g_return_if_fail (BZ_IS_SEARCH_WIDGET (self)); update_filter (self); } gboolean bz_search_widget_ensure_active (BzSearchWidget *self, const char *initial) { const char *text = NULL; g_return_val_if_fail (BZ_IS_SEARCH_WIDGET (self), FALSE); text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (text != NULL && *text != '\0' && gtk_widget_has_focus (GTK_WIDGET (self->search_bar))) return FALSE; gtk_widget_grab_focus (GTK_WIDGET (self->search_bar)); bz_search_widget_set_text (self, initial); return TRUE; } static void search_changed (GtkEditable *editable, BzSearchWidget *self) { GSettings *settings = NULL; g_clear_handle_id (&self->search_update_timeout, g_source_remove); settings = bz_state_info_get_settings (self->state); if (settings != NULL && g_settings_get_boolean (settings, "search-debounce")) { self->search_update_timeout = g_timeout_add_once ( 150, (GSourceOnceFunc) update_filter, self); gtk_widget_set_visible (GTK_WIDGET (self->search_busy), TRUE); } else update_filter (self); } static void search_activate (GtkText *text, BzSearchWidget *self) { GtkSelectionModel *model = NULL; guint n_items = 0; g_autoptr (BzSearchResult) result = NULL; BzEntryGroup *group = NULL; g_clear_object (&self->selected); model = gtk_grid_view_get_model (self->grid_view); n_items = g_list_model_get_n_items (G_LIST_MODEL (model)); if (n_items > 0) { result = g_list_model_get_item (G_LIST_MODEL (model), 0); group = bz_search_result_get_group (result); if (bz_entry_group_get_installable_and_available (group) > 0 || bz_entry_group_get_removable_and_available (group) > 0) { g_signal_emit (self, signals[SIGNAL_SELECT], 0, group, TRUE); } } } static void grid_activate (GtkGridView *grid_view, guint position, BzSearchWidget *self) { GtkSelectionModel *model = NULL; model = gtk_grid_view_get_model (self->grid_view); emit_idx (self, G_LIST_MODEL (model), position); } static void invalidating_state_prop_changed (BzSearchWidget *self, GParamSpec *pspec, BzStateInfo *info) { update_filter (self); } static void blocklists_items_changed (BzSearchWidget *self, guint position, guint removed, guint added, GListModel *model) { update_filter (self); } static DexFuture * search_query_then (DexFuture *future, GWeakRef *wr) { g_autoptr (BzSearchWidget) self = NULL; GPtrArray *results = NULL; guint old_length = 0; const char *page_name = NULL; bz_weak_get_or_return_reject (self, wr); results = g_value_get_boxed (dex_future_get_value (future, NULL)); old_length = g_list_model_get_n_items (G_LIST_MODEL (self->search_model)); g_list_store_splice ( self->search_model, 0, old_length, (gpointer *) results->pdata, results->len); gtk_widget_set_visible (GTK_WIDGET (self->search_busy), FALSE); if (results->len > 0) { page_name = "results"; gtk_widget_activate_action (GTK_WIDGET (self->grid_view), "list.scroll-to-item", "u", 0); } else { const char *search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); page_name = (search_text && *search_text) ? "no-results" : "empty"; } gtk_stack_set_visible_child_name (self->search_stack, page_name); dex_clear (&self->search_query); return NULL; } static void update_filter (BzSearchWidget *self) { BzSearchEngine *engine = NULL; const char *search_text = NULL; g_autoptr (GStrvBuilder) builder = NULL; guint n_terms = 0; g_auto (GStrv) terms = NULL; g_autoptr (DexFuture) future = NULL; g_autofree gchar **tokens = NULL; g_clear_handle_id (&self->search_update_timeout, g_source_remove); dex_clear (&self->search_query); gtk_widget_set_visible (GTK_WIDGET (self->search_busy), FALSE); if (self->state == NULL) return; engine = bz_state_info_get_search_engine (self->state); if (engine == NULL) return; search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_bar)); if (search_text == NULL || *search_text == '\0') { g_list_store_remove_all (self->search_model); gtk_stack_set_visible_child_name (self->search_stack, "empty"); return; } builder = g_strv_builder_new (); tokens = g_strsplit_set (search_text, " \t\n", -1); for (gchar **token = tokens; *token != NULL; token++) { if (**token != '\0') { g_strv_builder_take (builder, *token); n_terms++; } else g_free (*token); } if (n_terms == 0) { g_list_store_remove_all (self->search_model); gtk_stack_set_visible_child_name (self->search_stack, "empty"); return; } terms = g_strv_builder_end (builder); self->search_in_progress = TRUE; future = bz_search_engine_query ( engine, (const char *const *) terms); gtk_widget_set_visible ( GTK_WIDGET (self->search_busy), dex_future_is_pending (future)); future = dex_future_then ( future, (DexFutureCallback) search_query_then, bz_track_weak (self), bz_weak_release); self->search_query = g_steal_pointer (&future); } static void emit_idx (BzSearchWidget *self, GListModel *model, guint selected_idx) { g_autoptr (BzSearchResult) result = NULL; BzEntryGroup *group = NULL; result = g_list_model_get_item (G_LIST_MODEL (model), selected_idx); group = bz_search_result_get_group (result); g_signal_emit (self, signals[SIGNAL_SELECT], 0, group, FALSE); } kolunmi-bazaar-7b9c8e1/src/bz-search-widget.h000066400000000000000000000034241514314607700211640ustar00rootroot00000000000000/* bz-search-widget.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_SEARCH_WIDGET (bz_search_widget_get_type ()) G_DECLARE_FINAL_TYPE (BzSearchWidget, bz_search_widget, BZ, SEARCH_WIDGET, AdwBin) GtkWidget * bz_search_widget_new (GListModel *model, const char *initial); void bz_search_widget_set_state (BzSearchWidget *self, BzStateInfo *state); BzStateInfo * bz_search_widget_get_state (BzSearchWidget *self); void bz_search_widget_set_text (BzSearchWidget *self, const char *text); const char * bz_search_widget_get_text (BzSearchWidget *self); BzEntryGroup * bz_search_widget_get_selected (BzSearchWidget *self, gboolean *remove); BzEntryGroup * bz_search_widget_get_previewing (BzSearchWidget *self); void bz_search_widget_refresh (BzSearchWidget *self); gboolean bz_search_widget_ensure_active (BzSearchWidget *self, const char *initial); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-section-view.blp000066400000000000000000000136601514314607700214030ustar00rootroot00000000000000using Gtk 4.0; using Gio 2.0; using Adw 1; template $BzSectionView: Adw.Bin { hexpand: bind template.section as <$BzCuratedSection>.expand_horizontally; vexpand: bind template.section as <$BzCuratedSection>.expand_vertically; child: Box { hexpand: true; vexpand: true; halign: center; valign: center; Box { visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.category) as ) as ; orientation: vertical; spacing: 5; Overlay { hexpand: true; child: Picture { css-name: "banner"; height-request: bind $clamp_banner_height(template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-height) as ; styles [ "browser-banner", ] can-shrink: true; paintable: bind $get_banner(template.section as <$BzCuratedSection>.category) as <$GdkPaintable>; content-fit: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-fit; }; [overlay] Overlay banner_text_overlay { css-name: "banner-text-overlay"; hexpand: false; vexpand: false; child: Box banner_text_bg { css-name: "banner-text-bg"; }; halign: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-text-halign; valign: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-text-valign; [overlay] Box banner_text { css-name: "banner-text"; hexpand: false; vexpand: false; halign: center; valign: center; orientation: vertical; spacing: 5; Label { css-name: "title"; styles [ "browser-banner-title", ] wrap: true; wrap-mode: word_char; ellipsize: end; lines: 3; margin-start: 25; margin-end: 25; visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.title) as ) as ; xalign: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-text-label-xalign; label: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.title; } Label { css-name: "subtitle"; styles [ "browser-banner-subtitle", ] wrap: true; wrap-mode: word_char; ellipsize: end; lines: 3; margin-start: 25; margin-end: 25; visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.subtitle) as ) as ; xalign: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-text-label-xalign; label: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.subtitle; } Label { css-name: "description"; styles [ "browser-banner-description", ] wrap: true; wrap-mode: word_char; ellipsize: end; lines: 10; margin-start: 25; margin-end: 25; visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.description) as ) as ; xalign: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.banner-text-label-xalign; label: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.description; } } } } $BzDynamicListView { margin-start: 25; margin-end: 25; margin-top: 20; margin-bottom: 20; hexpand: true; scroll: false; noscroll-kind: flow-box; child-type: "BzCuratedAppTile"; child-prop: "group"; model: bind $convert_to_groups(template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.appids) as ; bind-widget => $bind_widget_cb(template); unbind-widget => $unbind_widget_cb(template); } Button { styles [ "pill", ] margin-start: 25; margin-end: 25; margin-bottom: 20; halign: center; visible: bind template.section as <$BzCuratedSection>.category as <$BzCuratedCategoryInfo>.enable-bulk-install as ; label: _("Install All"); clicked => $install_all_clicked(template); } } Box { visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.markdown) as ) as ; $BzMarkdownRender { markdown: bind template.section as <$BzCuratedSection>.markdown as <$BzCuratedMarkdownInfo>.string as ; } } Box { visible: bind $invert_boolean($is_null(template.section as <$BzCuratedSection>.image) as ) as ; width-request: bind $clamp_image_dimension(template.section as <$BzCuratedSection>.image as <$BzCuratedImageInfo>.width) as ; height-request: bind $clamp_image_dimension(template.section as <$BzCuratedSection>.image as <$BzCuratedImageInfo>.height) as ; Picture { css-name: "image"; paintable: bind $get_image(template.section as <$BzCuratedSection>.image) as <$GdkPaintable>; can-shrink: bind template.section as <$BzCuratedSection>.category as <$BzCuratedImageInfo>.can-shrink; content-fit: bind template.section as <$BzCuratedSection>.category as <$BzCuratedImageInfo>.fit; } } }; } kolunmi-bazaar-7b9c8e1/src/bz-section-view.c000066400000000000000000000347021514314607700210500ustar00rootroot00000000000000/* bz-section-view.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-section-view.h" #include "bz-application.h" #include "bz-async-texture.h" #include "bz-curated-app-tile.h" #include "bz-curated-section.h" #include "bz-dynamic-list-view.h" #include "bz-entry-group.h" #include "bz-markdown-render.h" #include "bz-window.h" struct _BzSectionView { AdwBin parent_instance; BzCuratedSection *section; GListModel *classes; AdwStyleManager *style_manager; GListModel *applied_classes; /* Template widgets */ GtkOverlay *banner_text_overlay; GtkBox *banner_text_bg; GtkBox *banner_text; }; G_DEFINE_FINAL_TYPE (BzSectionView, bz_section_view, ADW_TYPE_BIN) enum { PROP_0, PROP_SECTION, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_GROUP_ACTIVATED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static void tile_clicked (BzEntryGroup *group, GtkButton *button); static void dark_changed (BzSectionView *self, GParamSpec *pspec, AdwStyleManager *mgr); static void refresh_dark_light_classes (BzSectionView *self, AdwStyleManager *mgr); static BzAsyncTexture * choose_image (const char *default_variant_uri, const char *light_variant_uri, const char *dark_variant_uri); static void bz_section_view_dispose (GObject *object) { BzSectionView *self = BZ_SECTION_VIEW (object); g_signal_handlers_disconnect_by_func ( self->style_manager, dark_changed, self); g_clear_object (&self->section); g_clear_object (&self->classes); g_clear_object (&self->style_manager); g_clear_object (&self->applied_classes); G_OBJECT_CLASS (bz_section_view_parent_class)->dispose (object); } static void bz_section_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSectionView *self = BZ_SECTION_VIEW (object); switch (prop_id) { case PROP_SECTION: g_value_set_object (value, bz_section_view_get_section (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_section_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSectionView *self = BZ_SECTION_VIEW (object); switch (prop_id) { case PROP_SECTION: bz_section_view_set_section (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static BzAsyncTexture * get_banner (gpointer object, BzCuratedCategoryInfo *info) { const char *banner = NULL; const char *light_banner = NULL; const char *dark_banner = NULL; if (!BZ_IS_CURATED_CATEGORY_INFO (info)) return NULL; banner = bz_curated_category_info_get_banner (info); light_banner = bz_curated_category_info_get_light_banner (info); dark_banner = bz_curated_category_info_get_dark_banner (info); return choose_image (banner, light_banner, dark_banner); } static BzAsyncTexture * get_image (gpointer object, BzCuratedImageInfo *info) { const char *image = NULL; const char *light_image = NULL; const char *dark_image = NULL; if (!BZ_IS_CURATED_IMAGE_INFO (info)) return NULL; image = bz_curated_image_info_get_uri (info); light_image = bz_curated_image_info_get_light_uri (info); dark_image = bz_curated_image_info_get_dark_uri (info); return choose_image (image, light_image, dark_image); } static int clamp_banner_height (gpointer object, int value) { if (value == 0) return 300; return CLAMP (value, 100, 1000); } static int clamp_image_dimension (gpointer object, int value) { if (value == 0) return 200; return CLAMP (value, 100, 1000); } static GListModel * convert_to_groups (gpointer object, GListModel *value) { BzStateInfo *info = NULL; BzApplicationMapFactory *factory = NULL; info = bz_state_info_get_default (); factory = bz_state_info_get_application_factory (info); return bz_application_map_factory_generate (factory, value); } static void bind_widget_cb (BzSectionView *self, BzCuratedAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_connect_swapped (tile, "clicked", G_CALLBACK (tile_clicked), group); } static void unbind_widget_cb (BzSectionView *self, BzCuratedAppTile *tile, BzEntryGroup *group, BzDynamicListView *view) { g_signal_handlers_disconnect_by_func (tile, G_CALLBACK (tile_clicked), group); } static void install_all_clicked (BzSectionView *self, GtkButton *button) { GtkWidget *window = NULL; BzCuratedCategoryInfo *category = NULL; GListModel *appids = NULL; guint n_appids = 0; BzStateInfo *info = NULL; BzApplicationMapFactory *factory = NULL; g_autoptr (GListModel) groups = NULL; window = gtk_widget_get_ancestor (GTK_WIDGET (self), BZ_TYPE_WINDOW); if (window == NULL) return; /* If the button is visible and the user clicked it, this must be non-null */ category = bz_curated_section_get_category (self->section); appids = bz_curated_category_info_get_appids (category); if (appids == NULL) return; n_appids = g_list_model_get_n_items (appids); if (n_appids == 0) return; /* TODO: bind state via object properties */ info = bz_state_info_get_default (); factory = bz_state_info_get_application_factory (info); groups = bz_application_map_factory_generate (factory, appids); /* TODO: use signals to chain up the blueprints; it is cleaner, but more work... :( */ bz_window_bulk_install (BZ_WINDOW (window), groups); } static void bz_section_view_class_init (BzSectionViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_section_view_dispose; object_class->get_property = bz_section_view_get_property; object_class->set_property = bz_section_view_set_property; props[PROP_SECTION] = g_param_spec_object ( "section", NULL, NULL, BZ_TYPE_CURATED_SECTION, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_GROUP_ACTIVATED] = g_signal_new ( "group-activated", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); g_signal_set_va_marshaller ( signals[SIGNAL_GROUP_ACTIVATED], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); g_type_ensure (BZ_TYPE_CURATED_APP_TILE); g_type_ensure (BZ_TYPE_DYNAMIC_LIST_VIEW); g_type_ensure (BZ_TYPE_MARKDOWN_RENDER); g_type_ensure (BZ_TYPE_ASYNC_TEXTURE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-section-view.ui"); gtk_widget_class_bind_template_child (widget_class, BzSectionView, banner_text_overlay); gtk_widget_class_bind_template_child (widget_class, BzSectionView, banner_text_bg); gtk_widget_class_bind_template_child (widget_class, BzSectionView, banner_text); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, get_banner); gtk_widget_class_bind_template_callback (widget_class, get_image); gtk_widget_class_bind_template_callback (widget_class, clamp_banner_height); gtk_widget_class_bind_template_callback (widget_class, clamp_image_dimension); gtk_widget_class_bind_template_callback (widget_class, convert_to_groups); gtk_widget_class_bind_template_callback (widget_class, bind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, unbind_widget_cb); gtk_widget_class_bind_template_callback (widget_class, install_all_clicked); } static void dark_changed (BzSectionView *self, GParamSpec *pspec, AdwStyleManager *mgr) { refresh_dark_light_classes (self, mgr); if (self->section != NULL) { g_object_notify (G_OBJECT (self->section), "category"); g_object_notify (G_OBJECT (self->section), "markdown"); g_object_notify (G_OBJECT (self->section), "image"); } } static void bz_section_view_init (BzSectionView *self) { gtk_widget_init_template (GTK_WIDGET (self)); gtk_overlay_set_measure_overlay ( self->banner_text_overlay, GTK_WIDGET (self->banner_text), TRUE); gtk_overlay_set_clip_overlay ( self->banner_text_overlay, GTK_WIDGET (self->banner_text), TRUE); self->style_manager = g_object_ref ( adw_style_manager_get_default ()); g_signal_connect_swapped ( self->style_manager, "notify::dark", G_CALLBACK (dark_changed), self); } GtkWidget * bz_section_view_new (BzCuratedSection *section) { return g_object_new ( BZ_TYPE_SECTION_VIEW, "section", section, NULL); } void bz_section_view_set_section (BzSectionView *self, BzCuratedSection *section) { g_return_if_fail (BZ_IS_SECTION_VIEW (self)); g_return_if_fail (section == NULL || BZ_IS_CURATED_SECTION (section)); g_clear_object (&self->section); if (self->classes != NULL) { guint n_classes = 0; n_classes = g_list_model_get_n_items (self->classes); for (guint i = 0; i < n_classes; i++) { g_autoptr (GtkStringObject) string = NULL; const char *class = NULL; string = g_list_model_get_item (self->classes, i); class = gtk_string_object_get_string (string); gtk_widget_remove_css_class (GTK_WIDGET (self), class); } } g_clear_object (&self->classes); if (section != NULL) { self->section = g_object_ref (section); g_object_get (section, "classes", &self->classes, NULL); if (self->classes != NULL) { guint n_classes = 0; n_classes = g_list_model_get_n_items (self->classes); for (guint i = 0; i < n_classes; i++) { g_autoptr (GtkStringObject) string = NULL; const char *class = NULL; string = g_list_model_get_item (self->classes, i); class = gtk_string_object_get_string (string); gtk_widget_add_css_class (GTK_WIDGET (self), class); } } refresh_dark_light_classes (self, NULL); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SECTION]); } BzCuratedSection * bz_section_view_get_section (BzSectionView *self) { g_return_val_if_fail (BZ_IS_SECTION_VIEW (self), NULL); return self->section; } static void tile_clicked (BzEntryGroup *group, GtkButton *button) { GtkWidget *self = NULL; self = gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_SECTION_VIEW); g_signal_emit (self, signals[SIGNAL_GROUP_ACTIVATED], 0, group); } static void refresh_dark_light_classes (BzSectionView *self, AdwStyleManager *mgr) { if (self->applied_classes != NULL) { guint n_applied_classes = 0; n_applied_classes = g_list_model_get_n_items (self->applied_classes); for (guint i = 0; i < n_applied_classes; i++) { g_autoptr (GtkStringObject) string = NULL; const char *class = NULL; string = g_list_model_get_item (self->applied_classes, i); class = gtk_string_object_get_string (string); gtk_widget_remove_css_class (GTK_WIDGET (self), class); } } g_clear_object (&self->applied_classes); if (self->section == NULL) return; if (mgr == NULL) mgr = adw_style_manager_get_default (); if (adw_style_manager_get_dark (mgr)) g_object_get (self->section, "dark-classes", &self->applied_classes, NULL); else g_object_get (self->section, "light-classes", &self->applied_classes, NULL); if (self->applied_classes != NULL) { guint n_classes = 0; n_classes = g_list_model_get_n_items (self->applied_classes); for (guint i = 0; i < n_classes; i++) { g_autoptr (GtkStringObject) string = NULL; const char *class = NULL; string = g_list_model_get_item (self->applied_classes, i); class = gtk_string_object_get_string (string); gtk_widget_add_css_class (GTK_WIDGET (self), class); } } } static BzAsyncTexture * choose_image (const char *default_variant_uri, const char *light_variant_uri, const char *dark_variant_uri) { gboolean is_dark = FALSE; const char *uri = NULL; g_autoptr (GFile) source = NULL; g_autoptr (GdkPaintable) paintable = NULL; is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); if (is_dark) uri = dark_variant_uri; else uri = light_variant_uri; if (uri == NULL) uri = default_variant_uri; if (uri == NULL) return NULL; source = g_file_new_for_uri (uri); return bz_async_texture_new_lazy (source, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-section-view.h000066400000000000000000000023341514314607700210510ustar00rootroot00000000000000/* bz-section-view.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-curated-section.h" G_BEGIN_DECLS #define BZ_TYPE_SECTION_VIEW (bz_section_view_get_type ()) G_DECLARE_FINAL_TYPE (BzSectionView, bz_section_view, BZ, SECTION_VIEW, AdwBin) GtkWidget * bz_section_view_new (BzCuratedSection *section); void bz_section_view_set_section (BzSectionView *self, BzCuratedSection *section); BzCuratedSection * bz_section_view_get_section (BzSectionView *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-serializable.c000066400000000000000000000037761514314607700211110ustar00rootroot00000000000000/* bz-serializable.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-serializable.h" G_DEFINE_INTERFACE (BzSerializable, bz_serializable, G_TYPE_OBJECT) static void bz_serializable_real_serialize (BzSerializable *self, GVariantBuilder *builder) { return; } static gboolean bz_serializable_real_deserialize (BzSerializable *self, GVariant *import, GError **error) { return TRUE; } static void bz_serializable_default_init (BzSerializableInterface *iface) { iface->serialize = bz_serializable_real_serialize; iface->deserialize = bz_serializable_real_deserialize; } void bz_serializable_serialize (BzSerializable *self, GVariantBuilder *builder) { g_return_if_fail (BZ_IS_SERIALIZABLE (self)); g_return_if_fail (builder != NULL); BZ_SERIALIZABLE_GET_IFACE (self)->serialize ( self, builder); } gboolean bz_serializable_deserialize (BzSerializable *self, GVariant *import, GError **error) { g_return_val_if_fail (BZ_IS_SERIALIZABLE (self), FALSE); g_return_val_if_fail (import != NULL, FALSE); return BZ_SERIALIZABLE_GET_IFACE (self)->deserialize ( self, import, error); } kolunmi-bazaar-7b9c8e1/src/bz-serializable.h000066400000000000000000000030261514314607700211020ustar00rootroot00000000000000/* bz-serializable.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_SERIALIZABLE (bz_serializable_get_type ()) G_DECLARE_INTERFACE (BzSerializable, bz_serializable, BZ, SERIALIZABLE, GObject) struct _BzSerializableInterface { GTypeInterface parent_iface; void (*serialize) (BzSerializable *self, GVariantBuilder *builder); gboolean (*deserialize) (BzSerializable *self, GVariant *import, GError **error); }; void bz_serializable_serialize (BzSerializable *self, GVariantBuilder *builder); gboolean bz_serializable_deserialize (BzSerializable *self, GVariant *import, GError **error); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-share-list.c000066400000000000000000000162461514314607700205120ustar00rootroot00000000000000/* bz-share-list.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-share-list.h" #include "bz-url.h" #include "bz-window.h" #include struct _BzShareList { GtkBox parent_instance; GListModel *urls; AdwPreferencesGroup *group; }; G_DEFINE_FINAL_TYPE (BzShareList, bz_share_list, GTK_TYPE_BOX) enum { PROP_0, PROP_URLS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void copy_cb (BzShareList *self, GtkButton *button) { const char *link = NULL; GdkClipboard *clipboard = NULL; AdwToast *toast = NULL; GtkRoot *root = NULL; link = g_object_get_data (G_OBJECT (button), "url"); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); gdk_clipboard_set_text (clipboard, link); root = gtk_widget_get_root (GTK_WIDGET (self)); if (root && BZ_IS_WINDOW (root)) { toast = adw_toast_new (_ ("Copied!")); adw_toast_set_timeout (toast, 1); bz_window_add_toast (BZ_WINDOW (root), toast); } } static void follow_link_cb (BzShareList *self, GtkButton *button) { const char *link = NULL; link = g_object_get_data (G_OBJECT (button), "url"); g_app_info_launch_default_for_uri (link, NULL, NULL); } static AdwActionRow * create_url_action_row (BzShareList *self, BzUrl *url_item) { g_autofree char *url_string = NULL; g_autofree char *url_title = NULL; g_autofree char *icon_name = NULL; AdwActionRow *action_row; GtkBox *suffix_box; GtkButton *copy_button; GtkButton *open_button; GtkSeparator *separator; GtkImage *prefix_icon; g_object_get (url_item, "url", &url_string, "name", &url_title, "icon-name", &icon_name, NULL); action_row = ADW_ACTION_ROW (adw_action_row_new ()); adw_preferences_row_set_use_markup (ADW_PREFERENCES_ROW (action_row), FALSE); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (action_row), url_title ? url_title : url_string); adw_action_row_set_subtitle (action_row, url_string); if (icon_name != NULL && icon_name[0] != '\0') { prefix_icon = GTK_IMAGE (gtk_image_new_from_icon_name (icon_name)); gtk_image_set_icon_size (prefix_icon, GTK_ICON_SIZE_NORMAL); adw_action_row_add_prefix (action_row, GTK_WIDGET (prefix_icon)); } suffix_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4)); gtk_widget_set_valign (GTK_WIDGET (suffix_box), GTK_ALIGN_CENTER); copy_button = GTK_BUTTON (gtk_button_new_from_icon_name ("edit-copy-symbolic")); gtk_widget_set_tooltip_text (GTK_WIDGET (copy_button), _ ("Copy Link")); gtk_button_set_has_frame (copy_button, FALSE); g_object_set_data_full (G_OBJECT (copy_button), "url", g_strdup (url_string), g_free); g_signal_connect_swapped (copy_button, "clicked", G_CALLBACK (copy_cb), self); separator = GTK_SEPARATOR (gtk_separator_new (GTK_ORIENTATION_VERTICAL)); gtk_widget_set_margin_top (GTK_WIDGET (separator), 6); gtk_widget_set_margin_bottom (GTK_WIDGET (separator), 6); open_button = GTK_BUTTON (gtk_button_new_from_icon_name ("external-link-symbolic")); gtk_widget_set_tooltip_text (GTK_WIDGET (open_button), _ ("Open Link")); gtk_button_set_has_frame (open_button, FALSE); g_object_set_data_full (G_OBJECT (open_button), "url", g_strdup (url_string), g_free); g_signal_connect_swapped (open_button, "clicked", G_CALLBACK (follow_link_cb), self); gtk_box_append (suffix_box, GTK_WIDGET (copy_button)); gtk_box_append (suffix_box, GTK_WIDGET (separator)); gtk_box_append (suffix_box, GTK_WIDGET (open_button)); adw_action_row_add_suffix (action_row, GTK_WIDGET (suffix_box)); adw_action_row_set_activatable_widget (action_row, GTK_WIDGET (open_button)); adw_action_row_set_subtitle_lines (action_row, 1); return action_row; } static void populate_urls (BzShareList *self) { guint n_items = 0; if (self->group) { gtk_box_remove (GTK_BOX (self), GTK_WIDGET (self->group)); self->group = NULL; } self->group = ADW_PREFERENCES_GROUP (adw_preferences_group_new ()); gtk_box_append (GTK_BOX (self), GTK_WIDGET (self->group)); if (!self->urls) return; n_items = g_list_model_get_n_items (self->urls); for (guint i = 0; i < n_items; i++) { g_autoptr (BzUrl) url_item = NULL; AdwActionRow *action_row; url_item = g_list_model_get_item (self->urls, i); action_row = create_url_action_row (self, url_item); adw_preferences_group_add (self->group, GTK_WIDGET (action_row)); } } static void bz_share_list_dispose (GObject *object) { BzShareList *self = BZ_SHARE_LIST (object); g_clear_object (&self->urls); G_OBJECT_CLASS (bz_share_list_parent_class)->dispose (object); } static void bz_share_list_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzShareList *self = BZ_SHARE_LIST (object); switch (prop_id) { case PROP_URLS: g_value_set_object (value, self->urls); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_share_list_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzShareList *self = BZ_SHARE_LIST (object); switch (prop_id) { case PROP_URLS: g_clear_object (&self->urls); self->urls = g_value_dup_object (value); populate_urls (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_share_list_class_init (BzShareListClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_share_list_dispose; object_class->get_property = bz_share_list_get_property; object_class->set_property = bz_share_list_set_property; props[PROP_URLS] = g_param_spec_object ( "urls", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_URL); } static void bz_share_list_init (BzShareList *self) { gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL); } GtkWidget * bz_share_list_new (void) { return g_object_new (BZ_TYPE_SHARE_LIST, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-share-list.h000066400000000000000000000017361514314607700205150ustar00rootroot00000000000000/* bz-share-list.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_SHARE_LIST (bz_share_list_get_type ()) G_DECLARE_FINAL_TYPE (BzShareList, bz_share_list, BZ, SHARE_LIST, GtkBox) GtkWidget * bz_share_list_new (void); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-spdx.c000066400000000000000000000031761514314607700174130ustar00rootroot00000000000000/* bz-spdx.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-spdx.h" gboolean bz_spdx_is_valid (const char *license_id) { g_autofree char *url = NULL; g_return_val_if_fail (license_id != NULL, FALSE); url = as_get_license_url (license_id); return url != NULL; } char * bz_spdx_get_url (const char *license_id) { g_return_val_if_fail (license_id != NULL, NULL); return as_get_license_url (license_id); } char * bz_spdx_get_name (const char *license_id) { char *result = NULL; g_return_val_if_fail (license_id != NULL, NULL); if (bz_spdx_is_proprietary (license_id)) return g_strdup ("Proprietary"); result = as_license_to_spdx_id (license_id); if (result == NULL) return g_strdup (license_id); return result; } gboolean bz_spdx_is_proprietary (const char *license_id) { g_return_val_if_fail (license_id != NULL, FALSE); return g_str_has_prefix (license_id, "LicenseRef-proprietary"); } kolunmi-bazaar-7b9c8e1/src/bz-spdx.h000066400000000000000000000020031514314607700174040ustar00rootroot00000000000000/* bz-spdx.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS gboolean bz_spdx_is_valid (const char *license_id); char * bz_spdx_get_url (const char *license_id); char * bz_spdx_get_name (const char *license_id); gboolean bz_spdx_is_proprietary (const char *license_id); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-state-info.txt000066400000000000000000000054301514314607700210760ustar00rootroot00000000000000prefix=bz name=state_info parent-prefix=g parent-name=object author=AUTOGEN include="bz-application-map-factory.h" include="bz-auth-state.h" include="bz-backend.h" include="bz-content-provider.h" include="bz-entry-cache-manager.h" include="bz-flathub-state.h" include="bz-main-config.h" include="bz-search-engine.h" include="bz-transaction-manager.h" property=all_entries GListModel G_TYPE_LIST_MODEL object property=all_entry_groups GListModel G_TYPE_LIST_MODEL object property=all_installed_entry_groups GListModel G_TYPE_LIST_MODEL object property=all_user_data_entry_groups GListModel G_TYPE_LIST_MODEL object property=allow_manual_sync gboolean G_TYPE_BOOLEAN boolean property=application_factory BzApplicationMapFactory BZ_TYPE_APPLICATION_MAP_FACTORY object property=auth_state BzAuthState BZ_TYPE_AUTH_STATE object property=available_updates GListModel G_TYPE_LIST_MODEL object property=backend BzBackend BZ_TYPE_BACKEND object property=background_task_label char G_TYPE_STRING string property=blocklists GListModel G_TYPE_LIST_MODEL object property=blocklists_provider BzContentProvider BZ_TYPE_CONTENT_PROVIDER object property=busy gboolean G_TYPE_BOOLEAN boolean property=busy_progress double G_TYPE_DOUBLE double property=busy_progress_label char G_TYPE_STRING string property=busy_step_label char G_TYPE_STRING string property=cache_manager BzEntryCacheManager BZ_TYPE_ENTRY_CACHE_MANAGER object property=checking_for_updates gboolean G_TYPE_BOOLEAN boolean property=curated_configs GListModel G_TYPE_LIST_MODEL object property=curated_provider BzContentProvider BZ_TYPE_CONTENT_PROVIDER object property=debug_mode gboolean G_TYPE_BOOLEAN boolean property=disable_blocklists gboolean G_TYPE_BOOLEAN boolean property=donation_prompt_dismissed gboolean G_TYPE_BOOLEAN boolean property=entry_factory BzApplicationMapFactory BZ_TYPE_APPLICATION_MAP_FACTORY object property=flathub BzFlathubState BZ_TYPE_FLATHUB_STATE object property=have_connection gboolean G_TYPE_BOOLEAN boolean property=hide_eol gboolean G_TYPE_BOOLEAN boolean property=main_config BzMainConfig BZ_TYPE_MAIN_CONFIG object property=metered_connection gboolean G_TYPE_BOOLEAN boolean property=online gboolean G_TYPE_BOOLEAN boolean property=repositories GListModel G_TYPE_LIST_MODEL object property=search_engine BzSearchEngine BZ_TYPE_SEARCH_ENGINE object property=settings GSettings G_TYPE_SETTINGS object property=show_only_flathub gboolean G_TYPE_BOOLEAN boolean property=show_only_foss gboolean G_TYPE_BOOLEAN boolean property=show_only_verified gboolean G_TYPE_BOOLEAN boolean property=syncing gboolean G_TYPE_BOOLEAN boolean property=transaction_manager BzTransactionManager BZ_TYPE_TRANSACTION_MANAGER object property=txt_blocklists GListModel G_TYPE_LIST_MODEL object property=txt_blocklists_provider BzContentProvider BZ_TYPE_CONTENT_PROVIDER object kolunmi-bazaar-7b9c8e1/src/bz-stats-dialog.blp000066400000000000000000000033051514314607700213550ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzStatsDialog: Adw.Dialog { width-request: 360; height-request: 450; content-width: 1250; content-height: 750; child: Adw.ToolbarView { bottom-bar-style: raised_border; [top] Adw.HeaderBar { title-widget: Adw.ViewSwitcher switcher_title { stack: stack; policy: wide; }; } content: Box { orientation: vertical; Adw.ViewStack stack { vexpand: true; Adw.ViewStackPage { name: "graph"; title: _("Timeline"); icon-name: "graph2-symbolic"; child: Box { orientation: vertical; Label { label: bind $format_total_downloads(template.total-downloads) as ; halign: end; hexpand: true; margin-end: 34; margin-bottom: 2; styles ["dimmed"] } $BzDataGraph graph { model: bind template.model; tooltip-prefix: _("Installs:"); vexpand: true; hexpand: true; } }; } Adw.ViewStackPage { name: "map"; title: _("World"); icon-name: "globe-symbolic"; child: $BzWorldMap world_map { model: bind template.country-model; margin-top:10; margin-bottom: 10; }; } } Adw.ViewSwitcherBar switcher_bar { stack: stack; } }; }; Adw.Breakpoint { condition ("max-width: 450sp") setters { switcher_title.stack: null; switcher_bar.reveal: true; template.content-height: 300; } } }kolunmi-bazaar-7b9c8e1/src/bz-stats-dialog.c000066400000000000000000000125641514314607700210310ustar00rootroot00000000000000/* bz-stats-dialog.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-data-graph.h" #include "bz-stats-dialog.h" #include "bz-world-map.h" struct _BzStatsDialog { AdwDialog parent_instance; GListModel *model; GListModel *country_model; int total_downloads; /* Template widgets */ BzDataGraph *graph; BzWorldMap *world_map; }; G_DEFINE_FINAL_TYPE (BzStatsDialog, bz_stats_dialog, ADW_TYPE_DIALOG) enum { PROP_0, PROP_MODEL, PROP_COUNTRY_MODEL, PROP_TOTAL_DOWNLOADS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_stats_dialog_dispose (GObject *object) { BzStatsDialog *self = BZ_STATS_DIALOG (object); g_clear_object (&self->model); g_clear_object (&self->country_model); G_OBJECT_CLASS (bz_stats_dialog_parent_class)->dispose (object); } static void bz_stats_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzStatsDialog *self = BZ_STATS_DIALOG (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, self->model); break; case PROP_COUNTRY_MODEL: g_value_set_object (value, self->country_model); break; case PROP_TOTAL_DOWNLOADS: g_value_set_int (value, self->total_downloads); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_stats_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzStatsDialog *self = BZ_STATS_DIALOG (object); switch (prop_id) { case PROP_MODEL: g_clear_object (&self->model); self->model = g_value_dup_object (value); break; case PROP_COUNTRY_MODEL: g_clear_object (&self->country_model); self->country_model = g_value_dup_object (value); break; case PROP_TOTAL_DOWNLOADS: self->total_downloads = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * format_total_downloads (gpointer object, int value) { if (value <= 0) return g_strdup ("---"); if (value >= 1000000) /* Translators: M is the suffix for millions */ return g_strdup_printf (_("%.2fM Total Installs"), value / 1000000.0); else if (value >= 1000) /* Translators: K is the suffix for thousands*/ return g_strdup_printf (_("%.2fK Total Installs"), value / 1000.0); else return g_strdup_printf (_("%'d Total Installs"), value); } static void bz_stats_dialog_class_init (BzStatsDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_stats_dialog_dispose; object_class->get_property = bz_stats_dialog_get_property; object_class->set_property = bz_stats_dialog_set_property; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_COUNTRY_MODEL] = g_param_spec_object ( "country-model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE); props[PROP_TOTAL_DOWNLOADS] = g_param_spec_int ( "total-downloads", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READWRITE); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_DATA_GRAPH); g_type_ensure (BZ_TYPE_WORLD_MAP); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-stats-dialog.ui"); gtk_widget_class_bind_template_callback (widget_class, format_total_downloads); gtk_widget_class_bind_template_child (widget_class, BzStatsDialog, graph); gtk_widget_class_bind_template_child (widget_class, BzStatsDialog, world_map); } static void bz_stats_dialog_init (BzStatsDialog *self) { gtk_widget_init_template (GTK_WIDGET (self)); } AdwDialog * bz_stats_dialog_new (GListModel *model, GListModel *country_model, int total_downloads) { BzStatsDialog *stats_dialog = NULL; stats_dialog = g_object_new ( BZ_TYPE_STATS_DIALOG, "model", model, "country-model", country_model, "total-downloads", total_downloads, NULL); return ADW_DIALOG (stats_dialog); } void bz_stats_dialog_animate_open (BzStatsDialog *self) { g_return_if_fail (BZ_IS_STATS_DIALOG (self)); bz_data_graph_animate_open (self->graph); } kolunmi-bazaar-7b9c8e1/src/bz-stats-dialog.h000066400000000000000000000022271514314607700210310ustar00rootroot00000000000000/* bz-stats-dialog.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_STATS_DIALOG (bz_stats_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzStatsDialog, bz_stats_dialog, BZ, STATS_DIALOG, AdwDialog) AdwDialog * bz_stats_dialog_new (GListModel *model, GListModel *country_model, int total_downloads); void bz_stats_dialog_animate_open (BzStatsDialog *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-subcategory-list.c000066400000000000000000000262541514314607700217370ustar00rootroot00000000000000/* bz-subcategory-list.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include "bz-apps-page.h" #include "bz-flathub-state.h" #include "bz-flathub-sub-category.h" #include "bz-subcategory-list.h" #include "bz-util.h" #include "bz-window.h" struct _BzSubcategoryList { GtkBox parent_instance; BzFlathubCategory *category; BzFlathubState *flathub_state; DexFuture *task; }; G_DEFINE_FINAL_TYPE (BzSubcategoryList, bz_subcategory_list, GTK_TYPE_BOX); enum { PROP_0, PROP_CATEGORY, PROP_FLATHUB_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SELECT, LAST_SIGNAL }; static guint signals[LAST_SIGNAL]; static void apps_page_select_cb (BzSubcategoryList *self, BzEntryGroup *group, BzAppsPage *page) { GtkWidget *parentPage = NULL; parentPage = gtk_widget_get_ancestor (GTK_WIDGET (self), BZ_TYPE_APPS_PAGE); g_signal_emit_by_name (parentPage, "select", group); } static DexFuture * search_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzSubcategoryList) self = NULL; g_autoptr (GError) local_error = NULL; GtkRoot *root = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, wr); root = gtk_widget_get_root (GTK_WIDGET (self)); value = dex_future_get_value (future, &local_error); if (value != NULL) { GListModel *model = NULL; guint n_items = 0; model = g_value_get_object (value); n_items = g_list_model_get_n_items (model); if (n_items <= 1) { AdwToast *toast = adw_toast_new (_ ("No Results Found")); bz_window_add_toast (BZ_WINDOW (root), toast); } else { const char *subcategory_name = NULL; g_autofree char *subtitle = NULL; AdwNavigationPage *apps_page = NULL; GtkWidget *nav_view = NULL; subcategory_name = g_object_get_data (G_OBJECT (self), "current-subcategory"); subtitle = g_strdup_printf (_ ("%d Applications"), n_items); apps_page = bz_apps_page_new (subcategory_name, model); bz_apps_page_set_subtitle (BZ_APPS_PAGE (apps_page), subtitle); g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb), self); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } } else { AdwToast *toast = adw_toast_new (_ ("Search failed")); bz_window_add_toast (BZ_WINDOW (root), toast); g_warning ("Search failed: %s", local_error->message); } dex_clear (&self->task); return dex_future_new_true (); } static void subcategory_button_clicked_cb (BzSubcategoryList *self, GtkButton *button) { g_autoptr (DexFuture) future = NULL; const char *category = NULL; const char *label = NULL; g_autofree char *route = NULL; g_return_if_fail (BZ_IS_SUBCATEGORY_LIST (self)); g_return_if_fail (GTK_IS_BUTTON (button)); if (self->flathub_state == NULL) return; if (self->category == NULL) return; if (self->task != NULL) return; category = bz_flathub_category_get_name (self->category); if (category == NULL || *category == '\0') return; label = gtk_button_get_label (button); if (label == NULL || *label == '\0') return; g_object_set_data_full (G_OBJECT (self), "current-subcategory", g_strdup (label), g_free); route = g_strdup (g_object_get_data (G_OBJECT (button), "subcategory-id")); if (route == NULL) return; future = bz_flathub_state_search_collection (self->flathub_state, route); future = dex_future_finally ( future, (DexFutureCallback) search_finally, bz_track_weak (self), bz_weak_release); self->task = g_steal_pointer (&future); } static void rebuild_subcategories (BzSubcategoryList *self) { GtkWidget *child; GListModel *subcategories; guint n_items; dex_clear (&self->task); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))) != NULL) gtk_box_remove (GTK_BOX (self), child); if (self->category == NULL) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); return; } subcategories = bz_flathub_category_get_subcategories (self->category); if (subcategories == NULL) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); return; } n_items = g_list_model_get_n_items (subcategories); if (n_items == 0) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); return; } gtk_widget_set_visible (GTK_WIDGET (self), TRUE); for (guint i = 0; i < n_items; i++) { g_autoptr (BzFlathubSubCategory) subcategory = NULL; const char *label = NULL; const char *subcat_id = NULL; const char *category = NULL; g_autofree char *route = NULL; GtkWidget *button = NULL; subcategory = g_list_model_get_item (subcategories, i); if (subcategory == NULL) continue; label = bz_flathub_sub_category_get_name(subcategory); subcat_id = bz_flathub_sub_category_get_id(subcategory); category = bz_flathub_category_get_name (self->category); route = g_strdup_printf ("/collection/category/%s/subcategories?subcategory=%s", category, subcat_id); button = gtk_button_new_with_label (label); gtk_widget_add_css_class (button, "small-pill"); g_object_set_data_full (G_OBJECT (button), "subcategory-id", g_steal_pointer (&route), g_free); g_signal_connect_swapped (button, "clicked", G_CALLBACK (subcategory_button_clicked_cb), self); gtk_box_append (GTK_BOX (self), button); } } static void bz_subcategory_list_dispose (GObject *object) { BzSubcategoryList *self = BZ_SUBCATEGORY_LIST (object); dex_clear (&self->task); g_clear_object (&self->category); g_clear_object (&self->flathub_state); G_OBJECT_CLASS (bz_subcategory_list_parent_class)->dispose (object); } static void bz_subcategory_list_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzSubcategoryList *self = BZ_SUBCATEGORY_LIST (object); switch (prop_id) { case PROP_CATEGORY: g_value_set_object (value, bz_subcategory_list_get_category (self)); break; case PROP_FLATHUB_STATE: g_value_set_object (value, bz_subcategory_list_get_flathub_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_subcategory_list_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzSubcategoryList *self = BZ_SUBCATEGORY_LIST (object); switch (prop_id) { case PROP_CATEGORY: bz_subcategory_list_set_category (self, g_value_get_object (value)); break; case PROP_FLATHUB_STATE: bz_subcategory_list_set_flathub_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_subcategory_list_class_init (BzSubcategoryListClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_subcategory_list_set_property; object_class->get_property = bz_subcategory_list_get_property; object_class->dispose = bz_subcategory_list_dispose; props[PROP_CATEGORY] = g_param_spec_object ( "category", NULL, NULL, BZ_TYPE_FLATHUB_CATEGORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FLATHUB_STATE] = g_param_spec_object ( "flathub-state", NULL, NULL, BZ_TYPE_FLATHUB_STATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SELECT] = g_signal_new ("select", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); } static void bz_subcategory_list_init (BzSubcategoryList *self) { GtkLayoutManager *layout; gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL); gtk_widget_set_visible (GTK_WIDGET (self), FALSE); layout = GTK_LAYOUT_MANAGER (adw_wrap_layout_new ()); adw_wrap_layout_set_child_spacing (ADW_WRAP_LAYOUT (layout), 8); adw_wrap_layout_set_line_spacing (ADW_WRAP_LAYOUT (layout), 8); gtk_widget_set_layout_manager (GTK_WIDGET (self), layout); } GtkWidget * bz_subcategory_list_new (void) { return g_object_new (BZ_TYPE_SUBCATEGORY_LIST, NULL); } BzFlathubCategory * bz_subcategory_list_get_category (BzSubcategoryList *self) { g_return_val_if_fail (BZ_IS_SUBCATEGORY_LIST (self), NULL); return self->category; } void bz_subcategory_list_set_category (BzSubcategoryList *self, BzFlathubCategory *category) { g_return_if_fail (BZ_IS_SUBCATEGORY_LIST (self)); g_return_if_fail (category == NULL || BZ_IS_FLATHUB_CATEGORY (category)); g_clear_object (&self->category); if (category != NULL) self->category = g_object_ref (category); rebuild_subcategories (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CATEGORY]); } BzFlathubState * bz_subcategory_list_get_flathub_state (BzSubcategoryList *self) { g_return_val_if_fail (BZ_IS_SUBCATEGORY_LIST (self), NULL); return self->flathub_state; } void bz_subcategory_list_set_flathub_state (BzSubcategoryList *self, BzFlathubState *flathub_state) { g_return_if_fail (BZ_IS_SUBCATEGORY_LIST (self)); g_return_if_fail (flathub_state == NULL || BZ_IS_FLATHUB_STATE (flathub_state)); g_clear_object (&self->flathub_state); if (flathub_state != NULL) self->flathub_state = g_object_ref (flathub_state); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FLATHUB_STATE]); } kolunmi-bazaar-7b9c8e1/src/bz-subcategory-list.h000066400000000000000000000030051514314607700217310ustar00rootroot00000000000000/* bz-subcategory-list.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-flathub-category.h" #include "bz-flathub-state.h" #include G_BEGIN_DECLS #define BZ_TYPE_SUBCATEGORY_LIST (bz_subcategory_list_get_type ()) G_DECLARE_FINAL_TYPE (BzSubcategoryList, bz_subcategory_list, BZ, SUBCATEGORY_LIST, GtkBox) GtkWidget *bz_subcategory_list_new (void); BzFlathubCategory *bz_subcategory_list_get_category (BzSubcategoryList *self); void bz_subcategory_list_set_category (BzSubcategoryList *self, BzFlathubCategory *category); BzFlathubState *bz_subcategory_list_get_flathub_state (BzSubcategoryList *self); void bz_subcategory_list_set_flathub_state (BzSubcategoryList *self, BzFlathubState *flathub_state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-tag-list.c000066400000000000000000000267501514314607700201640ustar00rootroot00000000000000/* bz-tag-list.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include "bz-apps-page.h" #include "bz-flathub-state.h" #include "bz-tag-list.h" #include "bz-util.h" #include "bz-window.h" struct _BzTagList { GtkBox parent_instance; GListModel *model; GtkWidget *prefix; BzFlathubState *flathub_state; DexFuture *task; }; G_DEFINE_FINAL_TYPE (BzTagList, bz_tag_list, GTK_TYPE_BOX); enum { PROP_0, PROP_MODEL, PROP_PREFIX, PROP_FLATHUB_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SELECT, LAST_SIGNAL }; static guint signals[LAST_SIGNAL]; static void apps_page_select_cb (BzTagList *self, BzEntryGroup *group, BzAppsPage *page) { GtkWidget *nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); adw_navigation_view_pop (ADW_NAVIGATION_VIEW (nav_view)); g_signal_emit (self, signals[SIGNAL_SELECT], 0, group); } static DexFuture * search_finally (DexFuture *future, GWeakRef *wr) { g_autoptr (BzTagList) self = NULL; g_autoptr (GError) local_error = NULL; GtkRoot *root = NULL; const GValue *value = NULL; bz_weak_get_or_return_reject (self, wr); root = gtk_widget_get_root (GTK_WIDGET (self)); value = dex_future_get_value (future, &local_error); if (value != NULL) { GListModel *model = NULL; guint n_items = 0; model = g_value_get_object (value); n_items = g_list_model_get_n_items (model); if (n_items <= 1) { AdwToast *toast = adw_toast_new (_ ("No Results Found")); bz_window_add_toast (BZ_WINDOW (root), toast); } else { const char *tag = NULL; g_autofree char *title = NULL; g_autofree char *subtitle = NULL; AdwNavigationPage *apps_page = NULL; GtkWidget *nav_view = NULL; tag = g_object_get_data (G_OBJECT (self), "current-tag"); title = g_strdup_printf (_ ("Apps Tagged \"%s\""), tag); subtitle = g_strdup_printf (_ ("%d Applications"), n_items); apps_page = bz_apps_page_new (title, model); bz_apps_page_set_subtitle (BZ_APPS_PAGE (apps_page), subtitle); g_signal_connect_swapped ( apps_page, "select", G_CALLBACK (apps_page_select_cb), self); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); adw_navigation_view_push (ADW_NAVIGATION_VIEW (nav_view), apps_page); } } else { AdwToast *toast = adw_toast_new (_ ("Search failed")); bz_window_add_toast (BZ_WINDOW (root), toast); g_warning ("Search failed: %s", local_error->message); } dex_clear (&self->task); return dex_future_new_true (); } static void tag_button_clicked_cb (BzTagList *self, GtkButton *button) { g_autoptr (BzResult) result = NULL; g_autoptr (DexFuture) future = NULL; const char *tag = NULL; g_autofree char *route = NULL; g_return_if_fail (BZ_IS_TAG_LIST (self)); g_return_if_fail (GTK_IS_BUTTON (button)); if (self->flathub_state == NULL) return; if (self->task != NULL) return; tag = gtk_button_get_label (button); if (tag == NULL || *tag == '\0') return; g_object_set_data_full (G_OBJECT (self), "current-tag", g_strdup (tag), g_free); route = g_strdup_printf ("/collection/keyword?keyword=%s", tag); future = bz_flathub_state_search_collection (self->flathub_state, route); future = dex_future_finally ( future, (DexFutureCallback) search_finally, bz_track_weak (self), bz_weak_release); self->task = g_steal_pointer (&future); } static void rebuild_tags (BzTagList *self) { GtkWidget *child; guint n_items; dex_clear (&self->task); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))) != NULL) { if (child == self->prefix) { child = gtk_widget_get_next_sibling (child); if (child == NULL) break; } gtk_box_remove (GTK_BOX (self), child); } if (self->model == NULL) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); return; } n_items = g_list_model_get_n_items (self->model); if (n_items == 0) { gtk_widget_set_visible (GTK_WIDGET (self), FALSE); return; } gtk_widget_set_visible (GTK_WIDGET (self), TRUE); for (guint i = 0; i < n_items; i++) { g_autoptr (GtkStringObject) item = NULL; const char *tag; GtkWidget *button; item = g_list_model_get_item (self->model, i); if (item == NULL) continue; tag = gtk_string_object_get_string (item); if (tag == NULL || *tag == '\0') continue; button = gtk_button_new_with_label (tag); gtk_widget_add_css_class (button, "small-pill"); g_signal_connect_swapped (button, "clicked", G_CALLBACK (tag_button_clicked_cb), self); gtk_box_append (GTK_BOX (self), button); } } static void on_items_changed (BzTagList *self, guint position, guint removed, guint added, GListModel *model) { rebuild_tags (self); } static void bz_tag_list_dispose (GObject *object) { BzTagList *self = BZ_TAG_LIST (object); dex_clear (&self->task); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, on_items_changed, self); g_clear_object (&self->model); g_clear_object (&self->flathub_state); g_clear_pointer (&self->prefix, gtk_widget_unparent); G_OBJECT_CLASS (bz_tag_list_parent_class)->dispose (object); } static void bz_tag_list_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzTagList *self = BZ_TAG_LIST (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, bz_tag_list_get_model (self)); break; case PROP_PREFIX: g_value_set_object (value, bz_tag_list_get_prefix (self)); break; case PROP_FLATHUB_STATE: g_value_set_object (value, bz_tag_list_get_flathub_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_tag_list_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzTagList *self = BZ_TAG_LIST (object); switch (prop_id) { case PROP_MODEL: bz_tag_list_set_model (self, g_value_get_object (value)); break; case PROP_PREFIX: bz_tag_list_set_prefix (self, g_value_get_object (value)); break; case PROP_FLATHUB_STATE: bz_tag_list_set_flathub_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_tag_list_class_init (BzTagListClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_tag_list_set_property; object_class->get_property = bz_tag_list_get_property; object_class->dispose = bz_tag_list_dispose; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PREFIX] = g_param_spec_object ( "prefix", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_FLATHUB_STATE] = g_param_spec_object ( "flathub-state", NULL, NULL, BZ_TYPE_FLATHUB_STATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SELECT] = g_signal_new ("select", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_ENTRY_GROUP); } static void bz_tag_list_init (BzTagList *self) { GtkLayoutManager *layout; gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL); gtk_widget_set_visible (GTK_WIDGET (self), FALSE); layout = GTK_LAYOUT_MANAGER (adw_wrap_layout_new ()); adw_wrap_layout_set_child_spacing (ADW_WRAP_LAYOUT (layout), 8); adw_wrap_layout_set_line_spacing (ADW_WRAP_LAYOUT (layout), 8); gtk_widget_set_layout_manager (GTK_WIDGET (self), layout); } GtkWidget * bz_tag_list_new (void) { return g_object_new (BZ_TYPE_TAG_LIST, NULL); } GListModel * bz_tag_list_get_model (BzTagList *self) { g_return_val_if_fail (BZ_IS_TAG_LIST (self), NULL); return self->model; } void bz_tag_list_set_model (BzTagList *self, GListModel *model) { g_return_if_fail (BZ_IS_TAG_LIST (self)); g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, on_items_changed, self); g_clear_object (&self->model); if (model != NULL) { self->model = g_object_ref (model); g_signal_connect_swapped ( self->model, "items-changed", G_CALLBACK (on_items_changed), self); } rebuild_tags (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); } GtkWidget * bz_tag_list_get_prefix (BzTagList *self) { g_return_val_if_fail (BZ_IS_TAG_LIST (self), NULL); return self->prefix; } void bz_tag_list_set_prefix (BzTagList *self, GtkWidget *prefix) { g_return_if_fail (BZ_IS_TAG_LIST (self)); g_return_if_fail (prefix == NULL || GTK_IS_WIDGET (prefix)); if (self->prefix != NULL) gtk_widget_unparent (self->prefix); self->prefix = prefix; if (self->prefix != NULL) gtk_widget_set_parent (self->prefix, GTK_WIDGET (self)); rebuild_tags (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PREFIX]); } BzFlathubState * bz_tag_list_get_flathub_state (BzTagList *self) { g_return_val_if_fail (BZ_IS_TAG_LIST (self), NULL); return self->flathub_state; } void bz_tag_list_set_flathub_state (BzTagList *self, BzFlathubState *flathub_state) { g_return_if_fail (BZ_IS_TAG_LIST (self)); g_return_if_fail (flathub_state == NULL || BZ_IS_FLATHUB_STATE (flathub_state)); g_clear_object (&self->flathub_state); if (flathub_state != NULL) self->flathub_state = g_object_ref (flathub_state); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FLATHUB_STATE]); } kolunmi-bazaar-7b9c8e1/src/bz-tag-list.h000066400000000000000000000027341514314607700201650ustar00rootroot00000000000000/* bz-tag-list.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-flathub-state.h" #include G_BEGIN_DECLS #define BZ_TYPE_TAG_LIST (bz_tag_list_get_type ()) G_DECLARE_FINAL_TYPE (BzTagList, bz_tag_list, BZ, TAG_LIST, GtkBox) GtkWidget *bz_tag_list_new (void); GListModel *bz_tag_list_get_model (BzTagList *self); void bz_tag_list_set_model (BzTagList *self, GListModel *model); GtkWidget *bz_tag_list_get_prefix (BzTagList *self); void bz_tag_list_set_prefix (BzTagList *self, GtkWidget *prefix); BzFlathubState *bz_tag_list_get_flathub_state (BzTagList *self); void bz_tag_list_set_flathub_state (BzTagList *self, BzFlathubState *flathub_state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-template-callbacks.c000066400000000000000000000070541514314607700221640ustar00rootroot00000000000000/* bz-template-callbacks.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-template-callbacks.h" static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } /* Let's try to use this more for conciseness */ static gboolean not (gpointer object, gboolean value) { return invert_boolean (object, value); } static gboolean is_zero (gpointer object, int value) { return value == 0; } static gboolean is_double_zero (gpointer object, double value) { return value == 0.0; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean logical_and (gpointer object, gboolean value1, gboolean value2) { return value1 && value2; } static gboolean logical_or (gpointer object, gboolean value1, gboolean value2) { return value1 || value2; } static gboolean is_positive (gpointer object, int value) { return value >= 0; } static gboolean is_empty (gpointer object, GListModel *model) { return model == NULL || g_list_model_get_n_items (model) == 0; } static gboolean is_empty_string (gpointer object, const char *str) { return str == NULL || *str == '\0'; } static gboolean is_longer (gpointer object, GListModel *model, int value) { return model != NULL && g_list_model_get_n_items (model) > value; } static char * bool_to_string (gpointer object, gboolean condition, char *if_true, char *if_false) { return g_strdup (condition ? if_true : if_false); } static gpointer choose (gpointer object, gboolean condition, gpointer if_true, gpointer if_false) { return condition ? if_true : if_false; } void bz_widget_class_bind_all_util_callbacks (GtkWidgetClass *widget_class) { g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class)); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, not); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, is_double_zero); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, logical_and); gtk_widget_class_bind_template_callback (widget_class, logical_or); gtk_widget_class_bind_template_callback (widget_class, is_positive); gtk_widget_class_bind_template_callback (widget_class, is_empty); gtk_widget_class_bind_template_callback (widget_class, is_empty_string); gtk_widget_class_bind_template_callback (widget_class, is_longer); gtk_widget_class_bind_template_callback (widget_class, bool_to_string); gtk_widget_class_bind_template_callback (widget_class, choose); } kolunmi-bazaar-7b9c8e1/src/bz-template-callbacks.h000066400000000000000000000015461514314607700221710ustar00rootroot00000000000000/* bz-template-callbacks.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include void bz_widget_class_bind_all_util_callbacks (GtkWidgetClass *widget_class); kolunmi-bazaar-7b9c8e1/src/bz-themed-entry-group-rect.c000066400000000000000000000170331514314607700231240ustar00rootroot00000000000000/* bz-themed-entry-group-rect.c * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-themed-entry-group-rect.h" struct _BzThemedEntryGroupRect { GtkWidget parent_instance; GtkWidget *child; BzEntryGroup *group; }; G_DEFINE_FINAL_TYPE (BzThemedEntryGroupRect, bz_themed_entry_group_rect, GTK_TYPE_WIDGET); enum { PROP_0, PROP_CHILD, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_themed_entry_group_rect_dispose (GObject *object) { BzThemedEntryGroupRect *self = BZ_THEMED_ENTRY_GROUP_RECT (object); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_pointer (&self->group, g_object_unref); G_OBJECT_CLASS (bz_themed_entry_group_rect_parent_class)->dispose (object); } static void bz_themed_entry_group_rect_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzThemedEntryGroupRect *self = BZ_THEMED_ENTRY_GROUP_RECT (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_themed_entry_group_rect_get_child (self)); break; case PROP_GROUP: g_value_set_object (value, bz_themed_entry_group_rect_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_themed_entry_group_rect_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzThemedEntryGroupRect *self = BZ_THEMED_ENTRY_GROUP_RECT (object); switch (prop_id) { case PROP_CHILD: bz_themed_entry_group_rect_set_child (self, g_value_get_object (value)); break; case PROP_GROUP: bz_themed_entry_group_rect_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_themed_entry_group_rect_allocate (GtkWidget *widget, int width, int height, int baseline) { BzThemedEntryGroupRect *self = BZ_THEMED_ENTRY_GROUP_RECT (widget); if (self->child != NULL) gtk_widget_allocate (self->child, width, height, baseline, NULL); gtk_widget_queue_draw (widget); } static void bz_themed_entry_group_rect_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzThemedEntryGroupRect *self = BZ_THEMED_ENTRY_GROUP_RECT (widget); double widget_width = 0.0; double widget_height = 0.0; widget_width = (double) gtk_widget_get_width (widget); widget_height = (double) gtk_widget_get_height (widget); if (self->group != NULL) { const char *light_color = NULL; const char *dark_color = NULL; light_color = bz_entry_group_get_light_accent_color (self->group); dark_color = bz_entry_group_get_dark_accent_color (self->group); if (light_color != NULL || dark_color != NULL) { GdkRGBA light_rgba = { 0 }; GdkRGBA dark_rgba = { 0 }; gboolean is_dark = FALSE; if (light_color != NULL) gdk_rgba_parse (&light_rgba, light_color); if (dark_color != NULL) gdk_rgba_parse (&dark_rgba, dark_color); is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ()); gtk_snapshot_append_color ( snapshot, dark_color != NULL && is_dark ? &dark_rgba : &light_rgba, &GRAPHENE_RECT_INIT (0.0, 0.0, widget_width, widget_height)); } } if (self->child != NULL) gtk_widget_snapshot_child (widget, self->child, snapshot); } static void bz_themed_entry_group_rect_class_init (BzThemedEntryGroupRectClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_themed_entry_group_rect_set_property; object_class->get_property = bz_themed_entry_group_rect_get_property; object_class->dispose = bz_themed_entry_group_rect_dispose; widget_class->size_allocate = bz_themed_entry_group_rect_allocate; widget_class->snapshot = bz_themed_entry_group_rect_snapshot; props[PROP_CHILD] = g_param_spec_object ( "child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); } static void dark_changed (BzThemedEntryGroupRect *self, GParamSpec *pspec, AdwStyleManager *mgr) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void bz_themed_entry_group_rect_init (BzThemedEntryGroupRect *self) { g_signal_connect_object ( adw_style_manager_get_default (), "notify::dark", G_CALLBACK (dark_changed), self, G_CONNECT_SWAPPED); } GtkWidget * bz_themed_entry_group_rect_new (void) { return g_object_new (BZ_TYPE_THEMED_ENTRY_GROUP_RECT, NULL); } BzEntryGroup * bz_themed_entry_group_rect_get_group (BzThemedEntryGroupRect *self) { g_return_val_if_fail (BZ_IS_THEMED_ENTRY_GROUP_RECT (self), NULL); return self->group; } void bz_themed_entry_group_rect_set_group (BzThemedEntryGroupRect *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_THEMED_ENTRY_GROUP_RECT (self)); g_clear_pointer (&self->group, g_object_unref); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } GtkWidget * bz_themed_entry_group_rect_get_child (BzThemedEntryGroupRect *self) { g_return_val_if_fail (BZ_IS_THEMED_ENTRY_GROUP_RECT (self), NULL); return self->child; } void bz_themed_entry_group_rect_set_child (BzThemedEntryGroupRect *self, GtkWidget *child) { g_return_if_fail (BZ_THEMED_ENTRY_GROUP_RECT (self)); g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (self->child == child) return; if (child != NULL) g_return_if_fail (gtk_widget_get_parent (child) == NULL); g_clear_pointer (&self->child, gtk_widget_unparent); self->child = child; if (child != NULL) gtk_widget_set_parent (child, GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]); } /* End of bz-themed-entry-group-rect.c */ kolunmi-bazaar-7b9c8e1/src/bz-themed-entry-group-rect.h000066400000000000000000000031001514314607700231170ustar00rootroot00000000000000/* bz-themed-entry-group-rect.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-entry-group.h" G_BEGIN_DECLS #define BZ_TYPE_THEMED_ENTRY_GROUP_RECT (bz_themed_entry_group_rect_get_type ()) G_DECLARE_FINAL_TYPE (BzThemedEntryGroupRect, bz_themed_entry_group_rect, BZ, THEMED_ENTRY_GROUP_RECT, GtkWidget) GtkWidget * bz_themed_entry_group_rect_new (void); BzEntryGroup * bz_themed_entry_group_rect_get_group (BzThemedEntryGroupRect *self); void bz_themed_entry_group_rect_set_group (BzThemedEntryGroupRect *self, BzEntryGroup *group); GtkWidget * bz_themed_entry_group_rect_get_child (BzThemedEntryGroupRect *self); void bz_themed_entry_group_rect_set_child (BzThemedEntryGroupRect *self, GtkWidget *child); G_END_DECLS /* End of bz-themed-entry-group-rect.h */ kolunmi-bazaar-7b9c8e1/src/bz-transaction-dialog-result.txt000066400000000000000000000004241514314607700241210ustar00rootroot00000000000000prefix=bz name=transaction_dialog_result parent-prefix=g parent-name=object author=AUTOGEN include="bz-entry.h" property=selected_entry BzEntry BZ_TYPE_ENTRY object property=delete_user_data gboolean G_TYPE_BOOLEAN boolean property=confirmed gboolean G_TYPE_BOOLEAN boolean kolunmi-bazaar-7b9c8e1/src/bz-transaction-dialog.c000066400000000000000000000537621514314607700222250ustar00rootroot00000000000000/* bz-transaction-dialog.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-application.h" #include "bz-entry-selection-row.h" #include "bz-env.h" #include "bz-error.h" #include "bz-flatpak-entry.h" #include "bz-safety-calculator.h" #include "bz-state-info.h" #include "bz-transaction-dialog.h" #include "bz-transaction-list-dialog.h" #include "bz-util.h" static gboolean should_skip_entry (BzEntry *entry, gboolean remove) { gboolean is_installed; if (bz_entry_is_holding (entry)) return TRUE; if (!remove && BZ_IS_FLATPAK_ENTRY (entry) && bz_flatpak_entry_is_installed_ref (BZ_FLATPAK_ENTRY (entry))) return TRUE; is_installed = bz_entry_is_installed (entry); return (!remove && is_installed) || (remove && !is_installed); } static GtkWidget * create_entry_radio_button (BzEntry *entry, GtkWidget **out_radio) { BzStateInfo *state_info = NULL; GListModel *repositories = NULL; g_autoptr (BzRepository) repo = NULL; BzEntrySelectionRow *row = NULL; GtkCheckButton *radio = NULL; state_info = bz_state_info_get_default (); repositories = bz_state_info_get_repositories (state_info); if (repositories != NULL) repo = bz_entry_get_repository (entry, repositories); row = bz_entry_selection_row_new (BZ_FLATPAK_ENTRY (entry), repo); radio = bz_entry_selection_row_get_radio (row); if (out_radio != NULL) *out_radio = GTK_WIDGET (radio); return GTK_WIDGET (row); } static GPtrArray * create_entry_radio_buttons (AdwAlertDialog *alert, GListStore *store, gboolean remove) { g_autoptr (GPtrArray) radios = NULL; GtkWidget *container = NULL; container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); radios = g_ptr_array_new (); if (store != NULL) { guint n_total_entries = g_list_model_get_n_items (G_LIST_MODEL (store)); if (n_total_entries > 1) { GtkWidget *listbox = NULL; GtkCheckButton *first_valid_radio = NULL; GtkCheckButton *dummy_radio = NULL; listbox = gtk_list_box_new (); gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE); gtk_widget_add_css_class (listbox, "boxed-list"); dummy_radio = GTK_CHECK_BUTTON (gtk_check_button_new ()); for (guint i = 0; i < n_total_entries; i++) { g_autoptr (BzEntry) entry = NULL; GtkWidget *row = NULL; GtkWidget *radio = NULL; gboolean should_skip = FALSE; entry = g_list_model_get_item (G_LIST_MODEL (store), i); should_skip = should_skip_entry (entry, remove); row = create_entry_radio_button (entry, &radio); g_ptr_array_add (radios, radio); gtk_check_button_set_group (GTK_CHECK_BUTTON (radio), dummy_radio); if (should_skip) { gtk_widget_set_sensitive (row, FALSE); gtk_widget_set_sensitive (radio, FALSE); } else { if (first_valid_radio == NULL) { gtk_check_button_set_active (GTK_CHECK_BUTTON (radio), TRUE); first_valid_radio = (GtkCheckButton *) radio; } } gtk_list_box_append (GTK_LIST_BOX (listbox), row); } gtk_box_append (GTK_BOX (container), listbox); } } if (remove) { GtkWidget *listbox = NULL; GtkWidget *keep_data_row = NULL; GtkWidget *delete_data_row = NULL; GtkWidget *keep_radio = NULL; GtkWidget *delete_radio = NULL; listbox = gtk_list_box_new (); gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE); gtk_widget_add_css_class (listbox, "boxed-list"); keep_data_row = adw_action_row_new (); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (keep_data_row), _ ("Keep Data")); adw_action_row_set_subtitle (ADW_ACTION_ROW (keep_data_row), _ ("Allow restoring settings and content")); keep_radio = gtk_check_button_new (); gtk_widget_set_valign (keep_radio, GTK_ALIGN_CENTER); gtk_check_button_set_active (GTK_CHECK_BUTTON (keep_radio), TRUE); adw_action_row_add_prefix (ADW_ACTION_ROW (keep_data_row), keep_radio); adw_action_row_set_activatable_widget (ADW_ACTION_ROW (keep_data_row), keep_radio); gtk_list_box_append (GTK_LIST_BOX (listbox), keep_data_row); delete_data_row = adw_action_row_new (); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (delete_data_row), _ ("Delete Data")); adw_action_row_set_subtitle (ADW_ACTION_ROW (delete_data_row), _ ("Permanently remove app data to save space")); delete_radio = gtk_check_button_new (); gtk_widget_set_valign (delete_radio, GTK_ALIGN_CENTER); gtk_check_button_set_group (GTK_CHECK_BUTTON (delete_radio), GTK_CHECK_BUTTON (keep_radio)); adw_action_row_add_prefix (ADW_ACTION_ROW (delete_data_row), delete_radio); adw_action_row_set_activatable_widget (ADW_ACTION_ROW (delete_data_row), delete_radio); gtk_list_box_append (GTK_LIST_BOX (listbox), delete_data_row); g_ptr_array_add (radios, keep_radio); g_ptr_array_add (radios, delete_radio); gtk_box_append (GTK_BOX (container), listbox); } adw_alert_dialog_set_extra_child (alert, container); return g_steal_pointer (&radios); } static void configure_install_dialog (AdwAlertDialog *alert, const char *title, const char *id, gboolean has_multiple_entries) { g_autofree char *heading = NULL; heading = g_strdup_printf (_ ("Install %s?"), title); adw_alert_dialog_set_heading (alert, heading); if (has_multiple_entries) adw_alert_dialog_set_body (alert, _ ("Select which version to install. May install additional shared components")); else adw_alert_dialog_set_body (alert, _ ("May install additional shared components")); adw_alert_dialog_add_responses (alert, "cancel", _ ("Cancel"), "install", _ ("Install"), NULL); adw_alert_dialog_set_response_appearance (alert, "install", ADW_RESPONSE_SUGGESTED); adw_alert_dialog_set_default_response (alert, "install"); adw_alert_dialog_set_close_response (alert, "cancel"); } static void configure_remove_dialog (AdwAlertDialog *alert, const char *title, const char *id, gboolean has_multiple_entries) { g_autofree char *heading = NULL; g_autofree char *body = NULL; heading = g_strdup_printf (_ ("Remove %s?"), title); if (has_multiple_entries) body = g_strdup (_ ("Select which version to remove.")); else body = g_strdup_printf (_ ("It will not be possible to use %s after it is uninstalled."), title); adw_alert_dialog_set_heading (alert, heading); adw_alert_dialog_set_body (alert, body); adw_alert_dialog_add_responses (alert, "cancel", _ ("Cancel"), "remove", _ ("Remove"), NULL); adw_alert_dialog_set_response_appearance (alert, "remove", ADW_RESPONSE_DESTRUCTIVE); adw_alert_dialog_set_default_response (alert, "remove"); adw_alert_dialog_set_close_response (alert, "cancel"); } static void configure_high_risk_warning_dialog (AdwAlertDialog *alert, const char *title, BzHighRiskGroup risk_groups) { g_autofree char *heading = NULL; g_autofree char *body = NULL; heading = g_strdup_printf (_ ("“%s” is High Risk"), title); if (risk_groups & BZ_HIGH_RISK_GROUP_DISK) { body = g_strdup (_ ("This app has full access to your system, including all " "your files, browser history, saved passwords, and " "more. It also has access to the internet, meaning it " "could send your data to outside parties.\n\n" "Because the app is proprietary, it can not be audited " "for what it does with these permissions.")); } else if (risk_groups & BZ_HIGH_RISK_GROUP_X11) { body = g_strdup (_ ("This app uses the legacy X11 windowing system, which " "allows it to record all keystrokes, capture screenshots, " "and monitor other applications. It also has access " "to the internet, meaning it could send your data to " "outside parties.\n\n" "Because the app is proprietary, it can not be audited " "for what it does with these permissions.")); } adw_alert_dialog_set_heading (alert, heading); adw_alert_dialog_set_body (alert, body); adw_alert_dialog_set_body_use_markup (alert, TRUE); adw_alert_dialog_set_prefer_wide_layout (alert, TRUE); adw_alert_dialog_add_responses (alert, "cancel", _ ("Cancel"), "install", _ ("Install Anyway"), NULL); adw_alert_dialog_set_response_appearance (alert, "install", ADW_RESPONSE_DESTRUCTIVE); adw_alert_dialog_set_default_response (alert, "cancel"); adw_alert_dialog_set_close_response (alert, "cancel"); } static BzHighRiskGroup get_entry_high_risk_groups (BzEntry *entry) { if (bz_entry_get_is_foss (entry)) return BZ_HIGH_RISK_GROUP_NONE; return bz_safety_calculator_get_high_risk_groups (entry); } BZ_DEFINE_DATA ( show_dialog, ShowDialog, { GtkWidget *parent; BzEntry *entry; BzEntryGroup *group; gboolean remove; gboolean auto_confirm; }, BZ_RELEASE_DATA (entry, g_object_unref); BZ_RELEASE_DATA (group, g_object_unref)) static DexFuture * show_dialog_fiber (ShowDialogData *data) { g_autoptr (GError) local_error = NULL; g_autoptr (GListStore) store = NULL; const char *title = NULL; const char *id = NULL; g_autoptr (AdwDialog) alert = NULL; g_autoptr (AdwDialog) risk_alert = NULL; g_autoptr (GPtrArray) radios = NULL; g_autofree char *dialog_response = NULL; g_autofree char *risk_response = NULL; g_autoptr (BzTransactionDialogResult) result = NULL; g_autoptr (BzEntry) check_entry = NULL; BzHighRiskGroup risk_groups = BZ_HIGH_RISK_GROUP_NONE; guint n_total_entries = 0; gboolean confirmed = 0; result = bz_transaction_dialog_result_new (); if (data->group != NULL) { store = dex_await_object (bz_entry_group_dup_all_into_store (data->group), &local_error); if (store == NULL) { bz_show_error_for_widget (data->parent, local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } for (guint i = g_list_model_get_n_items (G_LIST_MODEL (store)); i > 0; i--) { g_autoptr (BzEntry) entry = NULL; entry = g_list_model_get_item (G_LIST_MODEL (store), i - 1); if (BZ_IS_FLATPAK_ENTRY (entry) && bz_flatpak_entry_is_installed_ref (BZ_FLATPAK_ENTRY (entry)) && (!data->remove || !bz_entry_is_installed (entry))) g_list_store_remove (store, i - 1); } title = bz_entry_group_get_title (data->group); id = bz_entry_group_get_id (data->group); n_total_entries = g_list_model_get_n_items (G_LIST_MODEL (store)); if (n_total_entries > 0) check_entry = g_list_model_get_item (G_LIST_MODEL (store), 0); } else { title = bz_entry_get_title (data->entry); id = bz_entry_get_id (data->entry); check_entry = g_object_ref (data->entry); } if (!data->remove && check_entry != NULL) risk_groups = get_entry_high_risk_groups (check_entry); if (risk_groups != BZ_HIGH_RISK_GROUP_NONE) { risk_alert = g_object_ref_sink (adw_alert_dialog_new (NULL, NULL)); configure_high_risk_warning_dialog (ADW_ALERT_DIALOG (risk_alert), title, risk_groups); adw_dialog_present (risk_alert, data->parent); risk_response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (risk_alert)), &local_error); if (risk_response == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (g_strcmp0 (risk_response, "install") != 0) { bz_transaction_dialog_result_set_confirmed (result, FALSE); return dex_future_new_for_object (result); } data->auto_confirm = TRUE; } alert = g_object_ref_sink (adw_alert_dialog_new (NULL, NULL)); if (data->remove) configure_remove_dialog (ADW_ALERT_DIALOG (alert), title, id, n_total_entries > 1); else configure_install_dialog (ADW_ALERT_DIALOG (alert), title, id, n_total_entries > 1); radios = create_entry_radio_buttons (ADW_ALERT_DIALOG (alert), store, data->remove); if (!data->remove && data->auto_confirm && radios->len <= 1) { dialog_response = g_strdup ("install"); g_ptr_array_set_size (radios, 0); g_clear_object (&alert); } else if (data->remove && data->auto_confirm && radios->len <= 1) { dialog_response = g_strdup ("remove"); g_ptr_array_set_size (radios, 0); g_clear_object (&alert); } else { adw_dialog_present (alert, data->parent); dialog_response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (alert)), &local_error); if (dialog_response == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (data->remove && radios->len >= 2) { GtkCheckButton *delete_radio = g_ptr_array_index (radios, radios->len - 1); bz_transaction_dialog_result_set_delete_user_data (result, gtk_check_button_get_active (delete_radio)); } } confirmed = (g_strcmp0 (dialog_response, "install") == 0) || (g_strcmp0 (dialog_response, "remove") == 0); bz_transaction_dialog_result_set_confirmed (result, confirmed); if (!confirmed) return dex_future_new_for_object (result); if (data->group != NULL) { guint n_entries = g_list_model_get_n_items (G_LIST_MODEL (store)); for (guint i = 0; i < MIN (n_entries, radios->len); i++) { GtkCheckButton *check = g_ptr_array_index (radios, i); if (gtk_check_button_get_active (check)) { g_autoptr (BzEntry) entry = NULL; entry = g_list_model_get_item (G_LIST_MODEL (store), i); bz_transaction_dialog_result_set_selected_entry (result, entry); break; } } if (bz_transaction_dialog_result_get_selected_entry (result) == NULL && n_entries > 0) { g_autoptr (BzEntry) entry = NULL; entry = g_list_model_get_item (G_LIST_MODEL (store), 0); bz_transaction_dialog_result_set_selected_entry (result, entry); } } else bz_transaction_dialog_result_set_selected_entry (result, data->entry); return dex_future_new_for_object (result); } DexFuture * bz_transaction_dialog_show (GtkWidget *parent, BzEntry *entry, BzEntryGroup *group, gboolean remove, gboolean auto_confirm) { g_autoptr (ShowDialogData) data = NULL; g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); g_return_val_if_fail (entry != NULL || group != NULL, NULL); data = show_dialog_data_new (); data->parent = parent; data->entry = bz_object_maybe_ref (entry); data->group = bz_object_maybe_ref (group); data->remove = remove; data->auto_confirm = auto_confirm; return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) show_dialog_fiber, g_steal_pointer (&data), show_dialog_data_unref); } BZ_DEFINE_DATA ( bulk_install_dialog, BulkInstallDialog, { GtkWidget *parent; GListModel *groups; }, BZ_RELEASE_DATA (groups, g_object_unref)); static DexFuture * bulk_install_dialog_fiber (BulkInstallDialogData *data) { g_autoptr (GError) local_error = NULL; g_autoptr (BzBulkInstallDialogResult) result = NULL; g_autoptr (GPtrArray) resolved_entries = NULL; g_autoptr (GListStore) entries_store = NULL; AdwDialog *dialog = NULL; g_autofree char *dialog_response = NULL; g_autofree char *heading = NULL; guint n_groups = 0; gboolean confirmed = FALSE; result = bz_bulk_install_dialog_result_new (); resolved_entries = g_ptr_array_new_with_free_func (g_object_unref); if (data->groups == NULL) { bz_bulk_install_dialog_result_set_confirmed (result, FALSE); return dex_future_new_for_object (result); } n_groups = g_list_model_get_n_items (data->groups); for (guint i = 0; i < n_groups; i++) { g_autoptr (BzEntryGroup) group = NULL; g_autoptr (GListStore) store = NULL; g_autoptr (BzEntry) entry = NULL; group = g_list_model_get_item (data->groups, i); if (bz_entry_group_get_removable (group) > 0) continue; store = dex_await_object (bz_entry_group_dup_all_into_store (group), &local_error); if (store == NULL || g_list_model_get_n_items (G_LIST_MODEL (store)) == 0) continue; entry = g_list_model_get_item (G_LIST_MODEL (store), 0); if (entry == NULL) continue; if (bz_entry_is_installed (entry) || bz_entry_is_holding (entry)) continue; g_ptr_array_add (resolved_entries, g_object_ref (entry)); } if (resolved_entries->len == 0) { g_autoptr (AdwDialog) info_alert = NULL; info_alert = g_object_ref_sink (adw_alert_dialog_new ( _ ("All apps are already installed"), NULL)); adw_alert_dialog_add_response (ADW_ALERT_DIALOG (info_alert), "ok", _ ("OK")); adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (info_alert), "ok"); adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (info_alert), "ok"); adw_dialog_present (info_alert, data->parent); dex_await (bz_make_alert_dialog_future (ADW_ALERT_DIALOG (info_alert)), NULL); bz_bulk_install_dialog_result_set_confirmed (result, FALSE); return dex_future_new_for_object (result); } entries_store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < resolved_entries->len; i++) g_list_store_append (entries_store, g_ptr_array_index (resolved_entries, i)); heading = g_strdup_printf (ngettext ("Install %u App?", "Install %u Apps?", resolved_entries->len), resolved_entries->len); dialog = bz_transaction_list_dialog_new ( G_LIST_MODEL (entries_store), heading, _ ("The following will be installed. Additional shared components may also be installed"), _ ("%d addons will be installed."), _ ("Additionally, addons will be installed."), _ ("Cancel"), _ ("Install All")); adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (dialog), "confirm"); adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (dialog), "cancel"); adw_dialog_present (dialog, data->parent); dialog_response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (dialog)), &local_error); if (dialog_response == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); confirmed = bz_transaction_list_dialog_was_confirmed ( BZ_TRANSACTION_LIST_DIALOG (dialog)); bz_bulk_install_dialog_result_set_confirmed (result, confirmed); if (confirmed) { g_autoptr (GListStore) store = NULL; store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < resolved_entries->len; i++) { BzEntry *entry = g_ptr_array_index (resolved_entries, i); g_list_store_append (store, entry); } bz_bulk_install_dialog_result_set_entries (result, G_LIST_MODEL (store)); } return dex_future_new_for_object (result); } DexFuture * bz_bulk_install_dialog_show (GtkWidget *parent, GListModel *groups) { g_autoptr (BulkInstallDialogData) data; g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); g_return_val_if_fail (G_IS_LIST_MODEL (groups), NULL); data = bulk_install_dialog_data_new (); data->parent = parent; data->groups = g_object_ref (groups); return dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) bulk_install_dialog_fiber, g_steal_pointer (&data), bulk_install_dialog_data_unref); } kolunmi-bazaar-7b9c8e1/src/bz-transaction-dialog.h000066400000000000000000000025421514314607700222200ustar00rootroot00000000000000/* bz-transaction-dialog.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-bulk-install-dialog-result.h" #include "bz-entry-group.h" #include "bz-transaction-dialog-result.h" G_BEGIN_DECLS DexFuture *bz_transaction_dialog_show (GtkWidget *parent, BzEntry *entry, BzEntryGroup *group, gboolean remove, gboolean auto_confirm); DexFuture *bz_bulk_install_dialog_show (GtkWidget *parent, GListModel *groups); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-transaction-entry-tracker.txt000066400000000000000000000010511514314607700241350ustar00rootroot00000000000000prefix=bz name=transaction_entry_tracker parent-prefix=g parent-name=object author=AUTOGEN enum=bz transaction_entry_kind install update removal enum=bz transaction_entry_status queued ongoing done include= include="bz-entry.h" property=entry BzEntry BZ_TYPE_ENTRY object property=current_ops GListModel G_TYPE_LIST_MODEL object property=finished_ops GListModel G_TYPE_LIST_MODEL object property=kind BzTransactionEntryKind BZ_TYPE_TRANSACTION_ENTRY_KIND enum property=status BzTransactionEntryStatus BZ_TYPE_TRANSACTION_ENTRY_STATUS enum kolunmi-bazaar-7b9c8e1/src/bz-transaction-list-dialog.blp000066400000000000000000000042231514314607700235150ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzTransactionListDialog: Adw.AlertDialog { extra-child: ScrolledWindow { width-request: 300; propagate-natural-height: true; overflow: hidden; vexpand: true; hscrollbar-policy: never; child: Box { orientation: vertical; spacing: 5; ListView list_view { styles [ "navigation-sidebar", ] model: NoSelection selection_model {}; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { orientation: horizontal; margin-top: 5; margin-bottom: 5; spacing: 6; Image { icon-size: large; paintable: bind template.item as <$BzEntry>.icon-paintable; visible: bind $invert_boolean($is_null(template.item as <$BzEntry>.icon-paintable) as ) as ; } Image { icon-size: large; icon-name: "application-x-executable"; visible: bind $is_null(template.item as <$BzEntry>.icon-paintable) as ; } Box { orientation: vertical; spacing: 3; Label { styles [ "heading", ] hexpand: true; xalign: 0.0; ellipsize: end; single-line-mode: true; label: bind template.item as <$BzEntry>.title; } Label { styles [ "dimmed", ] hexpand: true; xalign: 0.0; wrap: true; single-line-mode: true; selectable: true; label: bind template.item as <$BzEntry>.id; } } }; } }; } Label secondary_label { styles [ "dimmed", ] visible: false; wrap: true; justify: center; } }; }; }kolunmi-bazaar-7b9c8e1/src/bz-transaction-list-dialog.c000066400000000000000000000134771514314607700231750ustar00rootroot00000000000000/* bz-transaction-list-dialog.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-entry.h" #include "bz-transaction-list-dialog.h" struct _BzTransactionListDialog { AdwAlertDialog parent_instance; GListModel *entries; gboolean confirmed; GtkFilterListModel *app_filter; /* Template widgets */ GtkNoSelection *selection_model; GtkLabel *secondary_label; }; G_DEFINE_FINAL_TYPE (BzTransactionListDialog, bz_transaction_list_dialog, ADW_TYPE_ALERT_DIALOG) static gboolean match_for_app (BzEntry *item, gpointer user_data); static void on_response (AdwAlertDialog *alert, gchar *response, BzTransactionListDialog *self); static void bz_transaction_list_dialog_dispose (GObject *object) { BzTransactionListDialog *self = BZ_TRANSACTION_LIST_DIALOG (object); g_clear_object (&self->entries); g_clear_object (&self->app_filter); G_OBJECT_CLASS (bz_transaction_list_dialog_parent_class)->dispose (object); } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static void bz_transaction_list_dialog_class_init (BzTransactionListDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_transaction_list_dialog_dispose; gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-transaction-list-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, BzTransactionListDialog, selection_model); gtk_widget_class_bind_template_child (widget_class, BzTransactionListDialog, secondary_label); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); } static void bz_transaction_list_dialog_init (BzTransactionListDialog *self) { GtkCustomFilter *filter = NULL; gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect (self, "response", G_CALLBACK (on_response), self); filter = gtk_custom_filter_new ((GtkCustomFilterFunc) match_for_app, NULL, NULL); self->app_filter = gtk_filter_list_model_new (NULL, GTK_FILTER (filter)); gtk_no_selection_set_model (self->selection_model, G_LIST_MODEL (self->app_filter)); } static void on_response (AdwAlertDialog *alert, gchar *response, BzTransactionListDialog *self) { self->confirmed = g_strcmp0 (response, "confirm") == 0; } AdwDialog * bz_transaction_list_dialog_new (GListModel *entries, const gchar *heading, const gchar *body, const gchar *body_no_apps, const gchar *secondary_label, const gchar *cancel_label, const gchar *confirm_label) { BzTransactionListDialog *dialog = NULL; guint n_total = 0; guint n_apps = 0; guint n_other = 0; g_return_val_if_fail (G_IS_LIST_MODEL (entries), NULL); dialog = g_object_new (BZ_TYPE_TRANSACTION_LIST_DIALOG, NULL); dialog->entries = g_object_ref (entries); gtk_filter_list_model_set_model (dialog->app_filter, entries); adw_alert_dialog_add_response (ADW_ALERT_DIALOG (dialog), "cancel", cancel_label); adw_alert_dialog_add_response (ADW_ALERT_DIALOG (dialog), "confirm", confirm_label); adw_alert_dialog_set_response_appearance (ADW_ALERT_DIALOG (dialog), "confirm", ADW_RESPONSE_SUGGESTED); adw_alert_dialog_set_heading (ADW_ALERT_DIALOG (dialog), heading); n_total = g_list_model_get_n_items (entries); n_apps = g_list_model_get_n_items (G_LIST_MODEL (dialog->app_filter)); n_other = n_total - n_apps; if (n_total > 0) { if (n_apps == 0 && body_no_apps != NULL) { g_autofree char *formatted_body = NULL; formatted_body = g_strdup_printf (body_no_apps, n_other); adw_alert_dialog_set_body (ADW_ALERT_DIALOG (dialog), formatted_body); adw_alert_dialog_set_extra_child (ADW_ALERT_DIALOG (dialog), NULL); } else { adw_alert_dialog_set_body (ADW_ALERT_DIALOG (dialog), body); if (n_other > 0 && secondary_label != NULL) { g_autofree char *formatted_label = NULL; formatted_label = g_strdup_printf (secondary_label, n_other); gtk_label_set_label (dialog->secondary_label, formatted_label); gtk_widget_set_visible (GTK_WIDGET (dialog->secondary_label), TRUE); } } } return ADW_DIALOG (dialog); } gboolean bz_transaction_list_dialog_was_confirmed (BzTransactionListDialog *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_LIST_DIALOG (self), FALSE); return self->confirmed; } static gboolean match_for_app (BzEntry *item, gpointer user_data) { return bz_entry_is_of_kinds (item, BZ_ENTRY_KIND_APPLICATION); } kolunmi-bazaar-7b9c8e1/src/bz-transaction-list-dialog.h000066400000000000000000000027751514314607700232010ustar00rootroot00000000000000/* bz-transaction-list-dialog.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_TRANSACTION_LIST_DIALOG (bz_transaction_list_dialog_get_type ()) G_DECLARE_FINAL_TYPE (BzTransactionListDialog, bz_transaction_list_dialog, BZ, TRANSACTION_LIST_DIALOG, AdwAlertDialog) AdwDialog * bz_transaction_list_dialog_new (GListModel *entries, const gchar *heading, const gchar *body, const gchar *body_no_apps, const gchar *secondary_label, const gchar *cancel_label, const gchar *confirm_label); gboolean bz_transaction_list_dialog_was_confirmed (BzTransactionListDialog *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-transaction-manager.c000066400000000000000000001267261514314607700224010ustar00rootroot00000000000000/* bz-transaction-manager.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::TRANSACTIONS" #include "config.h" #include #include "bz-backend-transaction-op-payload.h" #include "bz-backend-transaction-op-progress-payload.h" #include "bz-env.h" #include "bz-error.h" #include "bz-marshalers.h" #include "bz-transaction-manager.h" #include "bz-util.h" /* clang-format off */ G_DEFINE_QUARK (bz-transaction-mgr-error-quark, bz_transaction_mgr_error); /* clang-format on */ enum { HOOK_CONTINUE, HOOK_STOP, HOOK_CONFIRM, HOOK_DENY, }; static inline void finish_queued_schedule_data (gpointer ptr); BZ_DEFINE_DATA ( queued_schedule, QueuedSchedule, { GWeakRef *self; BzTransaction *transaction; DexPromise *promise; GTimer *timer; }, finish_queued_schedule_data (self);) struct _BzTransactionManager { GObject parent_instance; BzMainConfig *config; BzBackend *backend; gboolean paused; GListStore *transactions; double current_progress; gboolean pending; QueuedScheduleData *current; DexFuture *loop; GtkFlattenListModel *all_trackers; GtkFilterListModel *install_trackers; GtkFilterListModel *removal_trackers; GQueue queue; }; G_DEFINE_FINAL_TYPE (BzTransactionManager, bz_transaction_manager, G_TYPE_OBJECT) enum { PROP_0, PROP_CONFIG, PROP_BACKEND, PROP_PAUSED, PROP_TRANSACTIONS, PROP_HAS_TRANSACTIONS, PROP_ACTIVE, PROP_PENDING, PROP_CURRENT_PROGRESS, PROP_INSTALL_TRACKERS, PROP_REMOVAL_TRACKERS, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_SUCCESS, SIGNAL_FAILURE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; BZ_DEFINE_DATA ( dialog, Dialog, { char *id; AdwDialog *dialog; }, BZ_RELEASE_DATA (id, g_free); BZ_RELEASE_DATA (dialog, g_object_unref)); static DexFuture * transaction_fiber (QueuedScheduleData *data); static int execute_hook (BzTransactionManager *self, BzHook *hook, const char *hook_type, const char *ts_type, const char *ts_appid); static DexFuture * transaction_finally (DexFuture *future, QueuedScheduleData *data); static DexFuture * then_loop_cb (DexFuture *future, GWeakRef *wr); static DexFuture * dispatch_next (BzTransactionManager *self); static void bz_transaction_manager_dispose (GObject *object) { BzTransactionManager *self = BZ_TRANSACTION_MANAGER (object); g_clear_object (&self->config); g_clear_object (&self->backend); g_clear_object (&self->transactions); g_queue_clear_full (&self->queue, queued_schedule_data_unref); g_clear_pointer (&self->current, queued_schedule_data_unref); dex_clear (&self->loop); G_OBJECT_CLASS (bz_transaction_manager_parent_class)->dispose (object); } static void bz_transaction_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzTransactionManager *self = BZ_TRANSACTION_MANAGER (object); switch (prop_id) { case PROP_CONFIG: g_value_set_boxed (value, bz_transaction_manager_get_config (self)); break; case PROP_BACKEND: g_value_set_object (value, bz_transaction_manager_get_backend (self)); break; case PROP_PAUSED: g_value_set_boolean (value, bz_transaction_manager_get_paused (self)); break; case PROP_TRANSACTIONS: g_value_set_object (value, self->transactions); break; case PROP_HAS_TRANSACTIONS: g_value_set_boolean (value, bz_transaction_manager_get_has_transactions (self)); break; case PROP_ACTIVE: g_value_set_boolean (value, bz_transaction_manager_get_active (self)); break; case PROP_PENDING: g_value_set_boolean (value, bz_transaction_manager_get_pending (self)); break; case PROP_CURRENT_PROGRESS: g_value_set_double (value, self->current_progress); break; case PROP_INSTALL_TRACKERS: g_value_set_object (value, self->install_trackers); break; case PROP_REMOVAL_TRACKERS: g_value_set_object (value, self->removal_trackers); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transaction_manager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzTransactionManager *self = BZ_TRANSACTION_MANAGER (object); switch (prop_id) { case PROP_CONFIG: bz_transaction_manager_set_config (self, g_value_get_boxed (value)); break; case PROP_BACKEND: bz_transaction_manager_set_backend (self, g_value_get_object (value)); break; case PROP_PAUSED: bz_transaction_manager_set_paused (self, g_value_get_boolean (value)); break; case PROP_TRANSACTIONS: case PROP_HAS_TRANSACTIONS: case PROP_ACTIVE: case PROP_PENDING: case PROP_CURRENT_PROGRESS: case PROP_INSTALL_TRACKERS: case PROP_REMOVAL_TRACKERS: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean filter_install_trackers (gpointer item, gpointer user_data) { BzTransactionEntryTracker *tracker = NULL; BzTransactionEntryKind kind = 0; tracker = BZ_TRANSACTION_ENTRY_TRACKER (item); if (tracker == NULL) return FALSE; kind = bz_transaction_entry_tracker_get_kind (tracker); return kind == BZ_TRANSACTION_ENTRY_KIND_INSTALL || kind == BZ_TRANSACTION_ENTRY_KIND_UPDATE; } static gboolean filter_removal_trackers (gpointer item, gpointer user_data) { BzTransactionEntryTracker *tracker = NULL; tracker = BZ_TRANSACTION_ENTRY_TRACKER (item); if (tracker == NULL) return FALSE; return bz_transaction_entry_tracker_get_kind (tracker) == BZ_TRANSACTION_ENTRY_KIND_REMOVAL; } static gpointer get_trackers_model (gpointer item, gpointer user_data) { BzTransaction *transaction = NULL; g_autoptr (GListModel) trackers = NULL; transaction = BZ_TRANSACTION (item); if (transaction == NULL) return NULL; trackers = g_object_ref (bz_transaction_get_trackers (transaction)); g_object_unref (item); return g_steal_pointer (&trackers); } static void bz_transaction_manager_class_init (BzTransactionManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_transaction_manager_dispose; object_class->get_property = bz_transaction_manager_get_property; object_class->set_property = bz_transaction_manager_set_property; props[PROP_CONFIG] = g_param_spec_object ( "config", NULL, NULL, BZ_TYPE_MAIN_CONFIG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_BACKEND] = g_param_spec_object ( "backend", NULL, NULL, BZ_TYPE_BACKEND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_PAUSED] = g_param_spec_boolean ( "paused", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_TRANSACTIONS] = g_param_spec_object ( "transactions", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_HAS_TRANSACTIONS] = g_param_spec_boolean ( "has-transactions", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_ACTIVE] = g_param_spec_boolean ( "active", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_PENDING] = g_param_spec_boolean ( "pending", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_CURRENT_PROGRESS] = g_param_spec_double ( "current-progress", NULL, NULL, 0.0, 1.0, 0.0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_INSTALL_TRACKERS] = g_param_spec_object ( "install-trackers", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_REMOVAL_TRACKERS] = g_param_spec_object ( "removal-trackers", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_SUCCESS] = g_signal_new ( "success", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_TRANSACTION, 0); g_signal_set_va_marshaller ( signals[SIGNAL_SUCCESS], G_TYPE_FROM_CLASS (klass), bz_marshal_VOID__OBJECT_BOXEDv); signals[SIGNAL_FAILURE] = g_signal_new ( "failure", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BZ_TYPE_TRANSACTION, 0); g_signal_set_va_marshaller ( signals[SIGNAL_FAILURE], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); } static void bz_transaction_manager_init (BzTransactionManager *self) { GtkCustomFilter *install_filter; GtkCustomFilter *removal_filter; GtkMapListModel *map_model; self->transactions = g_list_store_new (BZ_TYPE_TRANSACTION); g_queue_init (&self->queue); map_model = gtk_map_list_model_new ( g_object_ref (G_LIST_MODEL (self->transactions)), get_trackers_model, NULL, NULL); self->all_trackers = gtk_flatten_list_model_new (G_LIST_MODEL (map_model)); install_filter = gtk_custom_filter_new ( filter_install_trackers, NULL, NULL); self->install_trackers = gtk_filter_list_model_new ( g_object_ref (G_LIST_MODEL (self->all_trackers)), GTK_FILTER (install_filter)); removal_filter = gtk_custom_filter_new ( filter_removal_trackers, NULL, NULL); self->removal_trackers = gtk_filter_list_model_new ( g_object_ref (G_LIST_MODEL (self->all_trackers)), GTK_FILTER (removal_filter)); } BzTransactionManager * bz_transaction_manager_new (void) { return g_object_new (BZ_TYPE_TRANSACTION_MANAGER, NULL); } void bz_transaction_manager_set_config (BzTransactionManager *self, BzMainConfig *config) { g_return_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); g_clear_object (&self->config); if (config != NULL) self->config = g_object_ref (config); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONFIG]); } BzMainConfig * bz_transaction_manager_get_config (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), NULL); return self->config; } void bz_transaction_manager_set_backend (BzTransactionManager *self, BzBackend *backend) { g_return_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); g_return_if_fail (backend == NULL || BZ_IS_BACKEND (backend)); g_clear_object (&self->backend); if (backend != NULL) self->backend = g_object_ref (backend); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_BACKEND]); } BzBackend * bz_transaction_manager_get_backend (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), NULL); return self->backend; } void bz_transaction_manager_set_paused (BzTransactionManager *self, gboolean paused) { g_return_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); if (!!self->paused == !!paused) return; self->paused = paused; if (!paused) dex_future_disown (dispatch_next (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PAUSED]); } gboolean bz_transaction_manager_get_paused (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), FALSE); return self->paused; } gboolean bz_transaction_manager_get_active (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), FALSE); return self->loop != NULL; } gboolean bz_transaction_manager_get_pending (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), FALSE); return self->loop != NULL && self->pending; } gboolean bz_transaction_manager_get_has_transactions (BzTransactionManager *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_MANAGER (self), FALSE); return g_list_model_get_n_items (G_LIST_MODEL (self->transactions)) > 0; } DexFuture * bz_transaction_manager_add (BzTransactionManager *self, BzTransaction *transaction) { g_autoptr (QueuedScheduleData) data = NULL; dex_return_error_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); dex_return_error_if_fail (self->backend != NULL); dex_return_error_if_fail (BZ_IS_TRANSACTION (transaction)); bz_transaction_hold (transaction); if (self->queue.length > 0) { BzTransaction *to_merge[2] = { 0 }; g_autoptr (BzTransaction) new_transaction = NULL; guint position = 0; data = g_queue_pop_head (&self->queue); g_list_store_find (self->transactions, data->transaction, &position); g_assert (position != G_MAXUINT); to_merge[0] = g_steal_pointer (&data->transaction); to_merge[1] = g_object_ref (transaction); new_transaction = bz_transaction_new_merged (to_merge, G_N_ELEMENTS (to_merge)); g_list_store_splice (self->transactions, position, 1, (gpointer *) &new_transaction, 1); for (guint i = 0; i < G_N_ELEMENTS (to_merge); i++) g_object_unref (to_merge[i]); data->transaction = g_steal_pointer (&new_transaction); } else { data = queued_schedule_data_new (); data->self = bz_track_weak (self); data->transaction = g_object_ref (transaction); data->promise = dex_promise_new_cancellable (); g_list_store_insert (self->transactions, 0, transaction); } g_queue_push_head (&self->queue, queued_schedule_data_ref (data)); if (self->loop == NULL && !self->paused) dex_future_disown (dispatch_next (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_TRANSACTIONS]); return dex_ref (data->promise); } void bz_transaction_manager_cancel_current (BzTransactionManager *self) { g_return_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); if (self->current == NULL) return; dex_promise_reject ( self->current->promise, g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled by API")); g_object_set ( self->current->transaction, "status", "Cancelled", "progress", 1.0, "finished", TRUE, "success", FALSE, "error", "Cancelled by API", NULL); g_clear_pointer (&self->current, queued_schedule_data_unref); dex_clear (&self->loop); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); } void bz_transaction_manager_clear_finished (BzTransactionManager *self) { guint n_items = 0; gboolean had_items = FALSE; g_return_if_fail (BZ_IS_TRANSACTION_MANAGER (self)); n_items = g_list_model_get_n_items (G_LIST_MODEL (self->transactions)); had_items = n_items > 0; for (guint i = 0; i < n_items;) { g_autoptr (BzTransaction) transaction = NULL; gboolean finished = FALSE; transaction = g_list_model_get_item (G_LIST_MODEL (self->transactions), i); g_object_get (transaction, "finished", &finished, NULL); if (finished) { g_list_store_remove (self->transactions, i); n_items--; } else i++; } if (had_items && n_items == 0) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_TRANSACTIONS]); } static DexFuture * transaction_fiber (QueuedScheduleData *data) { g_autoptr (BzTransactionManager) self = NULL; BzTransaction *transaction = data->transaction; DexPromise *promise = data->promise; g_autoptr (GError) local_error = NULL; gboolean result = FALSE; guint n_installs = 0; guint n_updates = 0; guint n_removals = 0; g_autoptr (GListStore) store = NULL; g_autoptr (DexChannel) channel = NULL; g_autoptr (DexFuture) future = NULL; g_autoptr (GHashTable) op_set = NULL; g_autoptr (GHashTable) pending_set = NULL; bz_weak_get_or_return_reject (self, data->self); g_object_set ( transaction, "status", "Starting up...", "progress", 0.0, NULL); self->current_progress = 0.0; self->pending = TRUE; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_PROGRESS]); #define COUNT(type) \ G_STMT_START \ { \ GListModel *model = NULL; \ \ model = bz_transaction_get_##type (transaction); \ if (model != NULL) \ n_##type = g_list_model_get_n_items (model); \ } \ G_STMT_END COUNT (installs); COUNT (updates); COUNT (removals); #undef COUNT /* TODO: make reading config less bad */ if (self->config != NULL && bz_main_config_get_hooks (self->config) != NULL) { GListModel *hooks = NULL; guint n_hooks = 0; hooks = bz_main_config_get_hooks (self->config); n_hooks = g_list_model_get_n_items (hooks); for (guint i = 0; i < n_installs + n_updates + n_removals; i++) { const char *ts_kind = NULL; g_autoptr (BzEntry) entry = NULL; const char *ts_appid = NULL; if (i < n_installs) { ts_kind = "install"; entry = g_list_model_get_item ( bz_transaction_get_installs (transaction), i); } else if (i < n_installs + n_updates) { ts_kind = "update"; entry = g_list_model_get_item ( bz_transaction_get_updates (transaction), i - n_installs); } else { ts_kind = "removal"; entry = g_list_model_get_item ( bz_transaction_get_removals (transaction), i - n_updates - n_installs); } ts_appid = bz_entry_get_id (entry); for (guint j = 0; j < n_hooks; j++) { g_autoptr (BzHook) hook = NULL; BzHookSignal when = 0; int hook_result = HOOK_CONTINUE; hook = g_list_model_get_item (hooks, j); when = bz_hook_get_when (hook); if (when == BZ_HOOK_SIGNAL_BEFORE_TRANSACTION) hook_result = execute_hook (self, hook, "before-transaction", ts_kind, ts_appid); if (hook_result == HOOK_CONFIRM || hook_result == HOOK_STOP) break; else if (hook_result == HOOK_DENY) return dex_future_new_reject ( BZ_TRANSACTION_MGR_ERROR, BZ_TRANSACTION_MGR_ERROR_CANCELLED_BY_HOOK, "The transaction was prevented by a configured hook"); } } } store = g_list_store_new (BZ_TYPE_TRANSACTION); g_list_store_append (store, transaction); channel = dex_channel_new (0); future = bz_backend_merge_and_schedule_transactions ( self->backend, G_LIST_MODEL (store), channel, dex_promise_get_cancellable (promise)); op_set = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); pending_set = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); for (;;) { g_autoptr (GObject) object = NULL; object = dex_await_object (dex_channel_receive (channel), NULL); if (object == NULL) break; if (BZ_IS_BACKEND_TRANSACTION_OP_PAYLOAD (object)) { if (g_hash_table_contains (op_set, object)) { g_autofree char *error = NULL; error = g_object_steal_data (object, "error"); if (error != NULL) bz_transaction_error_out_task ( transaction, BZ_BACKEND_TRANSACTION_OP_PAYLOAD (object), error); else bz_transaction_finish_task ( transaction, BZ_BACKEND_TRANSACTION_OP_PAYLOAD (object)); g_hash_table_remove (op_set, object); if (g_hash_table_contains (pending_set, object)) { g_hash_table_remove (pending_set, object); self->pending = g_hash_table_size (pending_set) == g_hash_table_size (op_set); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); } } else { bz_transaction_add_task ( transaction, BZ_BACKEND_TRANSACTION_OP_PAYLOAD (object)); g_hash_table_replace (op_set, g_object_ref (object), NULL); } } else if (BZ_IS_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (object)) { const char *status = NULL; gboolean is_estimating = FALSE; double total_progress = 0.0; bz_transaction_update_task ( transaction, BZ_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (object)); status = bz_backend_transaction_op_progress_payload_get_status ( BZ_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (object)); is_estimating = bz_backend_transaction_op_progress_payload_get_is_estimating ( BZ_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (object)); total_progress = bz_backend_transaction_op_progress_payload_get_total_progress ( BZ_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (object)); g_object_set ( transaction, "pending", is_estimating, "status", status, "progress", total_progress, NULL); self->current_progress = total_progress; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_PROGRESS]); if (is_estimating && !g_hash_table_contains (pending_set, object)) { g_hash_table_replace (pending_set, g_object_ref (object), NULL); self->pending = g_hash_table_size (pending_set) == g_hash_table_size (op_set); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); } else if (!is_estimating && g_hash_table_contains (pending_set, object)) { g_hash_table_remove (pending_set, object); self->pending = g_hash_table_size (pending_set) == g_hash_table_size (op_set); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); } } } result = dex_await (g_steal_pointer (&future), &local_error); if (!result) return dex_future_new_for_error (g_steal_pointer (&local_error)); /* FIXME: duplicate code */ if (self->config != NULL && bz_main_config_get_hooks (self->config) != NULL) { GListModel *hooks = NULL; guint n_hooks = 0; hooks = bz_main_config_get_hooks (self->config); n_hooks = g_list_model_get_n_items (hooks); for (guint i = 0; i < n_installs + n_updates + n_removals; i++) { const char *ts_kind = NULL; g_autoptr (BzEntry) entry = NULL; const char *ts_appid = NULL; if (i < n_installs) { ts_kind = "install"; entry = g_list_model_get_item ( bz_transaction_get_installs (transaction), i); } else if (i < n_installs + n_updates) { ts_kind = "update"; entry = g_list_model_get_item ( bz_transaction_get_updates (transaction), i - n_installs); } else { ts_kind = "removal"; entry = g_list_model_get_item ( bz_transaction_get_removals (transaction), i - n_updates - n_installs); } ts_appid = bz_entry_get_id (entry); for (guint j = 0; j < n_hooks; j++) { g_autoptr (BzHook) hook = NULL; BzHookSignal when = 0; int hook_result = HOOK_CONTINUE; hook = g_list_model_get_item (hooks, j); when = bz_hook_get_when (hook); if (when == BZ_HOOK_SIGNAL_AFTER_TRANSACTION) hook_result = execute_hook (self, hook, "after-transaction", ts_kind, ts_appid); if (hook_result == HOOK_STOP) break; } } } return dex_future_new_true (); } static int execute_hook (BzTransactionManager *self, BzHook *hook, const char *hook_type, const char *ts_type, const char *ts_appid) { g_autoptr (GDateTime) date = NULL; g_autofree char *timestamp_sec = NULL; g_autofree char *timestamp_usec = NULL; const char *id = NULL; const char *shell = NULL; g_autoptr (GPtrArray) dialogs = NULL; g_autoptr (DialogData) current_dialog = NULL; gboolean hook_aborted = FALSE; gboolean finish = FALSE; date = g_date_time_new_now_utc (); timestamp_sec = g_strdup_printf ("%zu", g_date_time_to_unix (date)); timestamp_usec = g_strdup_printf ("%zu", g_date_time_to_unix_usec (date)); id = bz_hook_get_id (hook); shell = bz_hook_get_shell (hook); if (shell == NULL) { g_warning ("Main Config: hook definition must have shell code, skipping this hook"); return HOOK_CONTINUE; } dialogs = g_ptr_array_new_with_free_func (dialog_data_unref); if (bz_hook_get_dialogs (hook) != NULL) { GListModel *config_dialogs = NULL; guint n_dialogs = 0; config_dialogs = bz_hook_get_dialogs (hook); n_dialogs = g_list_model_get_n_items (config_dialogs); for (guint i = 0; i < n_dialogs; i++) { g_autoptr (BzHookDialog) config_dialog = NULL; const char *dialog_id = NULL; const char *dialog_title = NULL; const char *dialog_body = NULL; gboolean dialog_body_use_markup = FALSE; const char *dialog_default_response = NULL; g_autoptr (AdwDialog) dialog = NULL; guint n_opts = 0; g_autoptr (DialogData) data = NULL; config_dialog = g_list_model_get_item (config_dialogs, i); dialog_id = bz_hook_dialog_get_id (config_dialog); dialog_title = bz_hook_dialog_get_title (config_dialog); dialog_body = bz_hook_dialog_get_body (config_dialog); dialog_body_use_markup = bz_hook_dialog_get_body_use_markup (config_dialog); dialog_default_response = bz_hook_dialog_get_default_response_id (config_dialog); if (dialog_title == NULL || dialog_body == NULL) { g_warning ("Main Config: dialog definition must have a title and body, skipping this hook"); return HOOK_CONTINUE; } if (dialog_default_response == NULL) { g_warning ("Main Config: dialog definition must have a default response, skipping this hook"); return HOOK_CONTINUE; } dialog = g_object_ref_sink (adw_alert_dialog_new (dialog_title, dialog_body)); if (bz_hook_dialog_get_options (config_dialog) != NULL) { GListModel *config_opts = NULL; guint n_options = 0; config_opts = bz_hook_dialog_get_options (config_dialog); n_options = g_list_model_get_n_items (config_opts); for (guint j = 0; j < n_options; j++) { g_autoptr (BzHookDialogOption) config_opt = NULL; const char *opt_id = NULL; const char *opt_string = NULL; const char *opt_style = NULL; config_opt = g_list_model_get_item (config_opts, j); opt_id = bz_hook_dialog_option_get_id (config_opt); if (opt_id == NULL) { g_warning ("Main Config: dialog option definition must have an id, skipping this hook"); return HOOK_CONTINUE; } opt_string = bz_hook_dialog_option_get_string (config_opt); if (opt_string == NULL) { g_warning ("Main Config: dialog option definition must have a string, skipping this hook"); return HOOK_CONTINUE; } opt_style = bz_hook_dialog_option_get_style (config_opt); adw_alert_dialog_add_response (ADW_ALERT_DIALOG (dialog), opt_id, opt_string); if (opt_style != NULL) { AdwResponseAppearance appearance = ADW_RESPONSE_DEFAULT; if (g_strcmp0 (opt_style, "suggested") == 0) appearance = ADW_RESPONSE_SUGGESTED; else if (g_strcmp0 (opt_style, "destructive") == 0) appearance = ADW_RESPONSE_DESTRUCTIVE; else g_warning ("Main Config: dialog option definition appearance can be " "\"suggested\" or \"destructive\". \"%s\" is invalid.", opt_style); adw_alert_dialog_set_response_appearance ( ADW_ALERT_DIALOG (dialog), opt_id, appearance); } n_opts++; } } if (n_opts == 0) { g_warning ("Main Config: dialog definition must have options, skipping this hook"); return HOOK_CONTINUE; } adw_alert_dialog_set_body_use_markup ( ADW_ALERT_DIALOG (dialog), dialog_body_use_markup); adw_alert_dialog_set_default_response ( ADW_ALERT_DIALOG (dialog), dialog_default_response); data = dialog_data_new (); data->id = dialog_id != NULL ? g_strdup (dialog_id) : NULL; data->dialog = g_steal_pointer (&dialog); g_ptr_array_add (dialogs, g_steal_pointer (&data)); } } for (guint stage = 0;; stage++) { g_autoptr (GError) local_error = NULL; g_autoptr (GSubprocessLauncher) launcher = NULL; g_autofree char *stage_str = NULL; const char *hook_stage = NULL; g_autoptr (GSubprocess) subprocess = NULL; gboolean result = FALSE; GInputStream *stdout_pipe = NULL; g_autoptr (GBytes) stdout_bytes = NULL; gsize stdout_size = 0; gconstpointer stdout_data = NULL; g_autofree char *stdout_str = NULL; char *stdout_newline = NULL; launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE); g_subprocess_launcher_set_cwd (launcher, g_get_home_dir ()); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_INITIATED_UNIX_STAMP", timestamp_sec, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_INITIATED_UNIX_STAMP_USEC", timestamp_usec, TRUE); stage_str = g_strdup_printf ("%d", stage); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_STAGE_IDX", stage_str, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_ID", id, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_TYPE", hook_type, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_WAS_ABORTED", hook_aborted ? "true" : "false", TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_TS_APPID", ts_appid, TRUE); g_subprocess_launcher_setenv (launcher, "BAZAAR_TS_TYPE", ts_type, TRUE); if (finish) hook_stage = "teardown"; else if (hook_aborted) hook_stage = "catch"; else if (stage == 0) hook_stage = "setup"; else if (current_dialog != NULL) { GApplication *application = NULL; GtkWindow *window = NULL; g_autofree char *response = NULL; hook_stage = "teardown-dialog"; application = g_application_get_default (); window = gtk_application_get_active_window (GTK_APPLICATION (application)); if (window != NULL) { adw_dialog_present (current_dialog->dialog, GTK_WIDGET (window)); response = dex_await_string ( bz_make_alert_dialog_future (ADW_ALERT_DIALOG (current_dialog->dialog)), &local_error); if (response == NULL) g_warning ("Failed to resolve response from dialog " "\"%s\", assuming default response \"%s\": %s", current_dialog->id, adw_alert_dialog_get_default_response ( ADW_ALERT_DIALOG (current_dialog->dialog)), local_error->message); g_clear_pointer (&local_error, g_error_free); } else g_warning ("A window was not available to present dialog " "\"%s\" on, assuming default response \"%s\"", current_dialog->id, adw_alert_dialog_get_default_response ( ADW_ALERT_DIALOG (current_dialog->dialog))); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_DIALOG_ID", current_dialog->id, TRUE); g_subprocess_launcher_setenv ( launcher, "BAZAAR_HOOK_DIALOG_RESPONSE_ID", response != NULL ? response : adw_alert_dialog_get_default_response ( ADW_ALERT_DIALOG (current_dialog->dialog)), TRUE); g_clear_pointer (¤t_dialog, dialog_data_unref); } else if (dialogs->len > 0) { hook_stage = "setup-dialog"; current_dialog = g_ptr_array_steal_index (dialogs, 0); g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_DIALOG_ID", current_dialog->id, TRUE); } else hook_stage = "action"; g_subprocess_launcher_setenv (launcher, "BAZAAR_HOOK_STAGE", hook_stage, TRUE); subprocess = g_subprocess_launcher_spawn ( launcher, &local_error, "/bin/sh", "-c", shell, NULL); if (subprocess == NULL) { g_warning ("Hook failed to spawn, abandoning it now: %s", local_error->message); return HOOK_CONTINUE; } result = dex_await ( dex_subprocess_wait_check (subprocess), &local_error); if (!result) { g_warning ("Hook failed to exit cleanly, abandoning it now: %s", local_error->message); return HOOK_CONTINUE; } stdout_pipe = g_subprocess_get_stdout_pipe (subprocess); stdout_bytes = g_input_stream_read_bytes (stdout_pipe, 1024, NULL, &local_error); if (!stdout_bytes) { g_warning ("Failed to read stdout pipe of hook, abandoning it now: %s", local_error->message); return HOOK_CONTINUE; } stdout_data = g_bytes_get_data (stdout_bytes, &stdout_size); stdout_str = g_malloc (stdout_size + 1); memcpy (stdout_str, stdout_data, stdout_size); stdout_str[stdout_size] = '\0'; stdout_newline = strchr (stdout_str, '\n'); if (stdout_newline != NULL) *stdout_newline = '\0'; if (g_strcmp0 (hook_stage, "setup") == 0) { if (g_strcmp0 (stdout_str, "ok") == 0) continue; else if (g_strcmp0 (stdout_str, "pass") == 0) return HOOK_CONTINUE; } else if (g_strcmp0 (hook_stage, "setup-dialog") == 0) { if (g_strcmp0 (stdout_str, "ok") == 0) continue; else if (g_strcmp0 (stdout_str, "pass") == 0) { g_clear_pointer (¤t_dialog, dialog_data_unref); continue; } } else if (g_strcmp0 (hook_stage, "teardown-dialog") == 0) { if (g_strcmp0 (stdout_str, "ok") == 0) continue; else if (g_strcmp0 (stdout_str, "abort") == 0) { hook_aborted = TRUE; continue; } } else if (g_strcmp0 (hook_stage, "catch") == 0) { if (g_strcmp0 (stdout_str, "recover") == 0) { hook_aborted = FALSE; continue; } else if (g_strcmp0 (stdout_str, "abort") == 0) { finish = TRUE; continue; } } else if (g_strcmp0 (hook_stage, "action") == 0) { finish = TRUE; continue; } else if (g_strcmp0 (hook_stage, "teardown") == 0) { if (g_strcmp0 (stdout_str, "continue") == 0) return HOOK_CONTINUE; else if (g_strcmp0 (stdout_str, "stop") == 0) return HOOK_STOP; else if (g_strcmp0 (stdout_str, "confirm") == 0) return HOOK_CONFIRM; else if (g_strcmp0 (stdout_str, "deny") == 0) return HOOK_DENY; } else g_assert_not_reached (); g_warning ("Received invalid response from hook for stage \"%s\", abandoning it now", hook_stage); return HOOK_CONTINUE; } } static DexFuture * transaction_finally (DexFuture *future, QueuedScheduleData *data) { g_autoptr (BzTransactionManager) self = NULL; g_autoptr (GError) local_error = NULL; BzTransaction *transaction = data->transaction; DexPromise *promise = data->promise; GTimer *timer = data->timer; const GValue *value = NULL; g_autofree char *status = NULL; bz_weak_get_or_return_reject (self, data->self); g_timer_stop (timer); status = g_strdup_printf ( _ ("Finished in %.02f seconds"), g_timer_elapsed (data->timer, NULL)); value = dex_future_get_value (future, &local_error); g_object_set ( transaction, "status", status, "progress", 1.0, "finished", TRUE, "success", value != NULL, "error", local_error != NULL ? local_error->message : NULL, NULL); self->current_progress = 1.0; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CURRENT_PROGRESS]); if (value != NULL) { g_signal_emit (self, signals[SIGNAL_SUCCESS], 0, transaction); dex_promise_resolve_boolean (promise, TRUE); } else { g_warning ("Transaction failed to complete: %s", local_error->message); g_signal_emit (self, signals[SIGNAL_FAILURE], 0, transaction); dex_promise_resolve_boolean (promise, FALSE); } return dex_future_new_true (); } static DexFuture * then_loop_cb (DexFuture *future, GWeakRef *wr) { g_autoptr (BzTransactionManager) self = NULL; bz_weak_get_or_return_reject (self, wr); g_clear_pointer (&self->current, queued_schedule_data_unref); return dispatch_next (self); } static DexFuture * dispatch_next (BzTransactionManager *self) { g_autoptr (QueuedScheduleData) data = NULL; g_autoptr (DexFuture) future = NULL; if (self->queue.length == 0 || self->paused) { dex_clear (&self->loop); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVE]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PENDING]); if (self->queue.length == 0) return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "No more futures in queue"); if (self->paused) return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Paused"); } if (self->current != NULL) { QueuedScheduleData *peek = NULL; peek = g_queue_peek_head (&self->queue); return dex_ref (peek->promise); } data = g_queue_pop_tail (&self->queue); g_clear_pointer (&data->timer, g_timer_destroy); data->timer = g_timer_new (); future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) transaction_fiber, queued_schedule_data_ref (data), queued_schedule_data_unref); future = dex_future_finally ( future, (DexFutureCallback) transaction_finally, queued_schedule_data_ref (data), queued_schedule_data_unref); future = dex_future_first ( future, dex_ref (data->promise), NULL); self->current = queued_schedule_data_ref (data); if (self->loop == NULL) self->loop = dex_future_then_loop ( dex_ref (future), (DexFutureCallback) then_loop_cb, bz_track_weak (self), bz_weak_release); return dex_ref (future); } static inline void finish_queued_schedule_data (gpointer ptr) { QueuedScheduleData *data = ptr; g_clear_pointer (&data->self, bz_weak_release); if (data->transaction != NULL) bz_transaction_release (data->transaction); g_clear_object (&data->transaction); if (data->promise != NULL && dex_future_is_pending (DEX_FUTURE (data->promise))) dex_promise_reject ( data->promise, g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "User data was destroyed")); dex_clear (&data->promise); g_clear_pointer (&data->timer, g_timer_destroy); } kolunmi-bazaar-7b9c8e1/src/bz-transaction-manager.h000066400000000000000000000047171514314607700224010ustar00rootroot00000000000000/* bz-transaction-manager.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-backend.h" #include "bz-main-config.h" #include "bz-transaction.h" G_BEGIN_DECLS #define BZ_TRANSACTION_MGR_ERROR (bz_transaction_mgr_error_quark ()) GQuark bz_transaction_mgr_error_quark (void); typedef enum { BZ_TRANSACTION_MGR_ERROR_CANCELLED_BY_HOOK = 0, } BzTransaction_MgrError; #define BZ_TYPE_TRANSACTION_MANAGER (bz_transaction_manager_get_type ()) G_DECLARE_FINAL_TYPE (BzTransactionManager, bz_transaction_manager, BZ, TRANSACTION_MANAGER, GObject) BzTransactionManager * bz_transaction_manager_new (void); void bz_transaction_manager_set_config (BzTransactionManager *self, BzMainConfig *config); BzMainConfig * bz_transaction_manager_get_config (BzTransactionManager *self); void bz_transaction_manager_set_backend (BzTransactionManager *self, BzBackend *backend); BzBackend * bz_transaction_manager_get_backend (BzTransactionManager *self); void bz_transaction_manager_set_paused (BzTransactionManager *self, gboolean paused); gboolean bz_transaction_manager_get_paused (BzTransactionManager *self); gboolean bz_transaction_manager_get_active (BzTransactionManager *self); gboolean bz_transaction_manager_get_pending (BzTransactionManager *self); gboolean bz_transaction_manager_get_has_transactions (BzTransactionManager *self); G_GNUC_WARN_UNUSED_RESULT DexFuture * bz_transaction_manager_add (BzTransactionManager *self, BzTransaction *transaction); void bz_transaction_manager_cancel_current (BzTransactionManager *self); void bz_transaction_manager_clear_finished (BzTransactionManager *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-transaction-task.txt000066400000000000000000000006561514314607700223170ustar00rootroot00000000000000prefix=bz name=transaction_task parent-prefix=g parent-name=object author=AUTOGEN include="bz-backend-transaction-op-payload.h" include="bz-backend-transaction-op-progress-payload.h" property=op BzBackendTransactionOpPayload BZ_TYPE_BACKEND_TRANSACTION_OP_PAYLOAD object property=last_progress BzBackendTransactionOpProgressPayload BZ_TYPE_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD object property=error char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-transaction-tile.blp000066400000000000000000000263431514314607700222510ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzTransactionTile: $BzListTile { child: Adw.Bin { child: Box { orientation: vertical; Box { orientation: horizontal; spacing: 10; margin-top: 10; margin-bottom: 10; margin-start: 10; margin-end: 4; Image { paintable: bind $get_main_icon(template.tracker) as <$GdkPaintable>; pixel-size: 64; valign: start; halign: start; styles [ "icon-dropshadow", ] } Box { valign: center; orientation: vertical; Label { styles [ "transaction-tile-title", ] hexpand: true; ellipsize: end; xalign: 0.0; label: bind template.tracker as <$BzTransactionEntryTracker>.entry as <$BzEntry>.title as ; } Revealer progress_bars_revealer { reveal-child: bind $list_has_items(template.tracker as <$BzTransactionEntryTracker>.current-ops) as ; transition-type: slide_down; styles [ "no-min-height", ] child: ListView { styles [ "navigation-sidebar", "installed-list-view", "user-data-list-view" ] visible: bind $invert_boolean($is_transaction_tracker_removal(template.tracker) as ) as ; model: NoSelection { model: bind template.tracker as <$BzTransactionEntryTracker>.current-ops; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { orientation: vertical; spacing: 3; $BzProgressBar { hexpand: "true"; fraction: bind template.item as <$BzTransactionTask>.last-progress as <$BzBackendTransactionOpProgressPayload>.progress; } Label { styles [ "dimmed", "caption-heading", ] hexpand: true; xalign: 0; ellipsize: end; single-line-mode: true; label: bind $format_download_progress(template.item as <$BzTransactionTask>.last-progress as <$BzBackendTransactionOpProgressPayload>.progress, template.item as <$BzTransactionTask>.op as <$BzBackendTransactionOpPayload>.download-size) as ; } }; } }; }; } Revealer { reveal-child: bind progress_bars_revealer.reveal-child inverted; child: Box { orientation: horizontal; spacing: 4; Box { visible: bind $is_entry_addon(template.tracker) as ; halign: start; spacing: 4; margin-top: 8; styles [ "green", "colored", "small-pill", "download-size-pill", ] Image { icon-name: "puzzle-piece-symbolic"; pixel-size: 12; } Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: _("App Add-on"); } } Box { visible: bind $is_entry_runtime(template.tracker) as ; halign: start; spacing: 4; margin-top: 8; styles [ "blue", "colored", "small-pill", "download-size-pill", ] Image { icon-name: "application-x-sharedlib-symbolic"; pixel-size: 12; } Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: _("Runtime"); } } Box { visible: bind $is_queued(template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus>) as ; halign: start; spacing: 4; margin-top: 8; styles [ "grey", "colored", "small-pill", "download-size-pill", ] Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: _("In Queue"); } } Box { visible: bind $is_completed(template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus>) as ; halign: start; spacing: 4; margin-top: 8; styles [ "grey", "colored", "small-pill", "download-size-pill", ] Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: _("Done"); } } Box { visible: bind $is_transaction_tracker_errored(template.tracker as <$BzTransactionEntryTracker>.finished-ops) as ; halign: start; spacing: 4; margin-top: 8; styles [ "error", "colored", "small-pill", "download-size-pill", ] Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: _("Error"); } } Box { halign: start; spacing: 4; margin-top: 8; styles [ "installed-pill", "small-pill", "download-size-pill", ] visible: bind $is_transaction_tracker_removal(template.tracker) as ; Label { styles [ "caption-heading", ] valign: center; xalign: 0.0; label: bind $format_removal_size(template.tracker as <$BzTransactionEntryTracker>.entry as <$BzEntry>.size) as ; } } }; } } Box { Button { visible: bind $is_both( $is_both($is_entry_application(template.tracker as <$BzTransactionEntryTracker>) as ,$is_completed(template.tracker as <$BzTransactionEntryTracker>.status as <$BzTransactionEntryStatus>) as ) as , $is_transaction_tracker_install(template.tracker as <$BzTransactionEntryTracker>) as ) as ; icon-name: "execute-to-symbolic"; has-tooltip: true; valign: center; tooltip-text: _("Open App"); clicked => $run_cb(template); styles [ "flat", ] } ToggleButton toggle { sensitive: bind $invert_boolean($is_empty(template.tracker as <$BzTransactionEntryTracker>.finished-ops) as ) as ; child: Image { pixel-size: 14; icon-name: "go-next-symbolic"; styles [ "accent", ] }; valign: center; styles [ "flat", "circular", "ops-toggle", ] } } } Revealer { reveal-child: bind toggle.active; child: Box { orientation: vertical; styles [ "operations", ] Separator {} ListView { styles [ "navigation-sidebar", "installed-list-view", ] model: NoSelection { model: bind template.tracker as <$BzTransactionEntryTracker>.finished-ops; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { orientation: horizontal; spacing: 10; margin-start: 7; margin-end: 7; Image { styles [ "success", ] valign: center; icon-name: "check-plain-symbolic"; visible: bind $is_null(template.item as <$BzTransactionTask>.error) as ; } Image { styles [ "error", ] valign: center; icon-name: "cross-large-circle-filled-symbolic"; visible: bind $invert_boolean($is_null(template.item as <$BzTransactionTask>.error) as ) as ; } Box { valign: center; orientation: horizontal; spacing: 5; hexpand: true; Label { styles [ "dimmed", ] valign: center; hexpand: true; xalign: 0.0; ellipsize: end; single-line-mode: true; label: bind template.item as <$BzTransactionTask>.op as <$BzBackendTransactionOpPayload>.name; visible: bind $is_null(template.item as <$BzTransactionTask>.error) as ; } Label { styles [ "error", ] valign: center; hexpand: true; xalign: 0.0; ellipsize: end; single-line-mode: true; label: bind template.item as <$BzTransactionTask>.op as <$BzBackendTransactionOpPayload>.name; visible: bind $invert_boolean($is_null(template.item as <$BzTransactionTask>.error) as ) as ; has-tooltip: true; tooltip-text: bind template.item as <$BzTransactionTask>.error as ; } } }; } }; } }; } }; }; } kolunmi-bazaar-7b9c8e1/src/bz-transaction-tile.c000066400000000000000000000324361514314607700217160ustar00rootroot00000000000000/* bz-transaction-tile.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-application-map-factory.h" #include "bz-entry-group.h" #include "bz-entry.h" #include "bz-error.h" #include "bz-flatpak-entry.h" #include "bz-list-tile.h" #include "bz-state-info.h" #include "bz-template-callbacks.h" #include "bz-transaction-tile.h" #include "bz-window.h" struct _BzTransactionTile { BzListTile parent_instance; BzTransactionEntryTracker *tracker; }; G_DEFINE_FINAL_TYPE (BzTransactionTile, bz_transaction_tile, BZ_TYPE_LIST_TILE); enum { PROP_0, PROP_TRACKER, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static BzEntryGroup * resolve_group_from_entry (BzEntry *entry, BzWindow *window); static void bz_transaction_tile_dispose (GObject *object) { BzTransactionTile *self = BZ_TRANSACTION_TILE (object); g_clear_pointer (&self->tracker, g_object_unref); G_OBJECT_CLASS (bz_transaction_tile_parent_class)->dispose (object); } static void bz_transaction_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzTransactionTile *self = BZ_TRANSACTION_TILE (object); switch (prop_id) { case PROP_TRACKER: g_value_set_object (value, bz_transaction_tile_get_tracker (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transaction_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzTransactionTile *self = BZ_TRANSACTION_TILE (object); switch (prop_id) { case PROP_TRACKER: bz_transaction_tile_set_tracker (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * format_removal_size (gpointer object, guint64 value) { g_autofree char *size = NULL; size = g_format_size (value); return g_strdup_printf (_ ("%s Freed"), size); } static char * format_download_progress (gpointer object, double progress, guint64 total_size) { guint64 downloaded = (guint64) (progress * total_size); g_autofree char *downloaded_str = g_format_size (downloaded); g_autofree char *total_str = g_format_size (total_size); return g_strdup_printf ("%s / %s", downloaded_str, total_str); } static gboolean is_transaction_type (gpointer object, BzTransactionEntryTracker *tracker, int type) { if (tracker == NULL) return FALSE; return bz_transaction_entry_tracker_get_kind (tracker) == type; } static gboolean is_transaction_tracker_install (gpointer object, BzTransactionEntryTracker *tracker) { return is_transaction_type (object, tracker, BZ_TRANSACTION_ENTRY_KIND_INSTALL); } static gboolean is_transaction_tracker_update (gpointer object, BzTransactionEntryTracker *tracker) { return is_transaction_type (object, tracker, BZ_TRANSACTION_ENTRY_KIND_UPDATE); } static gboolean is_transaction_tracker_removal (gpointer object, BzTransactionEntryTracker *tracker) { return is_transaction_type (object, tracker, BZ_TRANSACTION_ENTRY_KIND_REMOVAL); } static gboolean is_transaction_tracker_errored (gpointer object, GListModel *finished_ops) { guint n_items = 0; if (finished_ops == NULL) return FALSE; n_items = g_list_model_get_n_items (finished_ops); for (guint i = 0; i < n_items; i++) { g_autoptr (BzTransactionTask) task = NULL; task = g_list_model_get_item (finished_ops, i); if (bz_transaction_task_get_error (task) != NULL) return TRUE; } return FALSE; } static gboolean list_has_items (gpointer object, GListModel *model) { if (model == NULL) return FALSE; return g_list_model_get_n_items (model) > 0; } static gboolean is_queued (gpointer object, BzTransactionEntryStatus status) { return status == BZ_TRANSACTION_ENTRY_STATUS_QUEUED; } static gboolean is_ongoing (gpointer object, BzTransactionEntryStatus status) { return status == BZ_TRANSACTION_ENTRY_STATUS_ONGOING; } static gboolean is_completed (gpointer object, BzTransactionEntryStatus status) { return status == BZ_TRANSACTION_ENTRY_STATUS_DONE; } static gboolean is_both (gpointer object, gboolean first, gboolean second) { return first && second; } static GdkPaintable * get_main_icon (gpointer object, BzTransactionEntryTracker *tracker) { BzEntry *entry = NULL; GdkPaintable *icon_paintable = NULL; if (tracker == NULL) goto return_generic; entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL) goto return_generic; icon_paintable = bz_entry_get_icon_paintable (entry); if (icon_paintable != NULL) return g_object_ref (icon_paintable); else if (BZ_IS_FLATPAK_ENTRY (entry)) { BzWindow *window = NULL; g_autoptr (BzEntryGroup) group = NULL; window = (BzWindow *) gtk_widget_get_ancestor (object, BZ_TYPE_WINDOW); if (window == NULL) goto return_generic; group = resolve_group_from_entry (entry, window); if (group == NULL) goto return_generic; icon_paintable = bz_entry_group_get_icon_paintable (group); if (icon_paintable != NULL) return g_object_ref (icon_paintable); } return_generic: return (GdkPaintable *) gtk_icon_theme_lookup_icon ( gtk_icon_theme_get_for_display (gdk_display_get_default ()), "application-x-executable", NULL, 64, 1, gtk_widget_get_default_direction (), GTK_ICON_LOOKUP_NONE); } static gboolean is_entry_kind (gpointer object, BzTransactionEntryTracker *tracker, int kind) { BzEntry *entry = NULL; if (tracker == NULL) return FALSE; entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL) return FALSE; return bz_entry_is_of_kinds (entry, kind); } static gboolean is_entry_application (gpointer object, BzTransactionEntryTracker *tracker) { return is_entry_kind (object, tracker, BZ_ENTRY_KIND_APPLICATION); } static gboolean is_entry_runtime (gpointer object, BzTransactionEntryTracker *tracker) { return is_entry_kind (object, tracker, BZ_ENTRY_KIND_RUNTIME); } static gboolean is_entry_addon (gpointer object, BzTransactionEntryTracker *tracker) { return is_entry_kind (object, tracker, BZ_ENTRY_KIND_ADDON); } static void run_cb (BzTransactionTile *self, GtkButton *button) { BzTransactionEntryTracker *tracker = NULL; BzEntry *entry = NULL; tracker = bz_transaction_tile_get_tracker (self); if (tracker == NULL) return; entry = bz_transaction_entry_tracker_get_entry (tracker); if (entry == NULL || !BZ_IS_FLATPAK_ENTRY (entry)) return; if (bz_entry_is_installed (entry)) { g_autoptr (GError) local_error = NULL; gboolean result = FALSE; BzWindow *window = NULL; BzStateInfo *state = NULL; window = (BzWindow *) gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_WINDOW); if (window == NULL) return; state = bz_window_get_state_info (window); if (state == NULL) return; result = bz_flatpak_entry_launch ( BZ_FLATPAK_ENTRY (entry), BZ_FLATPAK_INSTANCE (bz_state_info_get_backend (state)), &local_error); if (!result) bz_show_error_for_widget (GTK_WIDGET (window), local_error->message); } } static void bz_transaction_tile_class_init (BzTransactionTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_transaction_tile_set_property; object_class->get_property = bz_transaction_tile_get_property; object_class->dispose = bz_transaction_tile_dispose; props[PROP_TRACKER] = g_param_spec_object ( "tracker", NULL, NULL, BZ_TYPE_TRANSACTION_ENTRY_TRACKER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LIST_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-transaction-tile.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_callback (widget_class, format_removal_size); gtk_widget_class_bind_template_callback (widget_class, format_download_progress); gtk_widget_class_bind_template_callback (widget_class, get_main_icon); gtk_widget_class_bind_template_callback (widget_class, is_entry_application); gtk_widget_class_bind_template_callback (widget_class, is_entry_runtime); gtk_widget_class_bind_template_callback (widget_class, is_entry_addon); gtk_widget_class_bind_template_callback (widget_class, is_transaction_tracker_install); gtk_widget_class_bind_template_callback (widget_class, is_transaction_tracker_update); gtk_widget_class_bind_template_callback (widget_class, is_transaction_tracker_removal); gtk_widget_class_bind_template_callback (widget_class, is_transaction_tracker_errored); gtk_widget_class_bind_template_callback (widget_class, list_has_items); gtk_widget_class_bind_template_callback (widget_class, is_queued); gtk_widget_class_bind_template_callback (widget_class, is_ongoing); gtk_widget_class_bind_template_callback (widget_class, is_completed); gtk_widget_class_bind_template_callback (widget_class, is_both); gtk_widget_class_bind_template_callback (widget_class, run_cb); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_transaction_tile_init (BzTransactionTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } BzTransactionTile * bz_transaction_tile_new (void) { return g_object_new (BZ_TYPE_TRANSACTION_TILE, NULL); } BzTransactionEntryTracker * bz_transaction_tile_get_tracker (BzTransactionTile *self) { g_return_val_if_fail (BZ_IS_TRANSACTION_TILE (self), NULL); return self->tracker; } void bz_transaction_tile_set_tracker (BzTransactionTile *self, BzTransactionEntryTracker *tracker) { g_return_if_fail (BZ_IS_TRANSACTION_TILE (self)); g_clear_pointer (&self->tracker, g_object_unref); if (tracker != NULL) self->tracker = g_object_ref (tracker); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRACKER]); } static BzEntryGroup * resolve_group_from_entry (BzEntry *entry, BzWindow *window) { BzStateInfo *info = NULL; const char *extension_of_ref = NULL; g_autofree char *extension_of_ref_dup = NULL; char *generic_id = NULL; char *generic_id_term = NULL; g_autoptr (BzEntryGroup) group = NULL; info = bz_window_get_state_info (window); if (info == NULL) return NULL; if (bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION)) { const char *id = NULL; id = bz_entry_get_id (entry); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (info), gtk_string_object_new (id)); if (group != NULL) return g_steal_pointer (&group); } extension_of_ref = bz_flatpak_entry_get_addon_extension_of_ref (BZ_FLATPAK_ENTRY (entry)); if (extension_of_ref == NULL) return NULL; extension_of_ref_dup = g_strdup (extension_of_ref); generic_id = strchr (extension_of_ref_dup, '/'); if (generic_id == NULL) return NULL; generic_id++; generic_id_term = strchr (generic_id, '/'); if (generic_id_term != NULL) *generic_id_term = '\0'; group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (info), gtk_string_object_new (generic_id)); if (group == NULL) return NULL; return g_steal_pointer (&group); } /* End of bz-transaction-tile.c */ kolunmi-bazaar-7b9c8e1/src/bz-transaction-tile.h000066400000000000000000000025111514314607700217120ustar00rootroot00000000000000/* bz-transaction-tile.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-transaction-entry-tracker.h" G_BEGIN_DECLS #define BZ_TYPE_TRANSACTION_TILE (bz_transaction_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzTransactionTile, bz_transaction_tile, BZ, TRANSACTION_TILE, BzListTile) BzTransactionTile * bz_transaction_tile_new (void); BzTransactionEntryTracker * bz_transaction_tile_get_tracker (BzTransactionTile *self); void bz_transaction_tile_set_tracker (BzTransactionTile *self, BzTransactionEntryTracker *tracker); G_END_DECLS /* End of bz-transaction-tile.h */ kolunmi-bazaar-7b9c8e1/src/bz-transaction.c000066400000000000000000000610601514314607700207560ustar00rootroot00000000000000/* bz-transaction.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ /* TODO: This file probably needs to be rewritten */ #include "config.h" #include #include "bz-transaction.h" typedef struct { GListStore *installs; GListStore *updates; GListStore *removals; char *name; gboolean pending; GListStore *current_tasks; GListStore *finished_tasks; GListStore *trackers; char *status; double progress; gboolean finished; gboolean success; char *error; } BzTransactionPrivate; G_DEFINE_TYPE_WITH_PRIVATE (BzTransaction, bz_transaction, G_TYPE_OBJECT) enum { PROP_0, PROP_NAME, PROP_INSTALLS, PROP_UPDATES, PROP_REMOVALS, PROP_PENDING, PROP_CURRENT_OPS, PROP_FINISHED_OPS, PROP_TRACKERS, PROP_STATUS, PROP_PROGRESS, PROP_FINISHED, PROP_SUCCESS, PROP_ERROR, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void finish (BzTransactionPrivate *priv); static gboolean find_payload_eq_func (BzTransactionTask *task, gpointer none, BzBackendTransactionOpPayload *payload); static gboolean find_entry_eq_func (BzTransactionEntryTracker *tracker, gpointer none, BzEntry *entry); static gboolean find_and_maybe_transfer (GListStore *from, GListStore *to, gpointer lookup, GEqualFuncFull eql, gpointer *out); static void tracker_update (BzTransactionPrivate *priv, BzBackendTransactionOpPayload *payload, gboolean transfer); static void bz_transaction_dispose (GObject *object) { BzTransaction *self = BZ_TRANSACTION (object); BzTransactionPrivate *priv = bz_transaction_get_instance_private (self); g_clear_pointer (&priv->name, g_free); g_clear_object (&priv->installs); g_clear_object (&priv->updates); g_clear_object (&priv->removals); g_clear_object (&priv->current_tasks); g_clear_object (&priv->finished_tasks); g_clear_object (&priv->trackers); g_clear_pointer (&priv->status, g_free); g_clear_pointer (&priv->error, g_free); G_OBJECT_CLASS (bz_transaction_parent_class)->dispose (object); } static void bz_transaction_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzTransaction *self = BZ_TRANSACTION (object); BzTransactionPrivate *priv = bz_transaction_get_instance_private (self); switch (prop_id) { case PROP_NAME: g_value_set_string (value, priv->name); break; case PROP_INSTALLS: g_value_set_object (value, priv->installs); break; case PROP_UPDATES: g_value_set_object (value, priv->updates); break; case PROP_REMOVALS: g_value_set_object (value, priv->removals); break; case PROP_PENDING: g_value_set_boolean (value, priv->pending); break; case PROP_CURRENT_OPS: g_value_set_object (value, priv->current_tasks); break; case PROP_FINISHED_OPS: g_value_set_object (value, priv->finished_tasks); break; case PROP_TRACKERS: g_value_set_object (value, priv->trackers); break; case PROP_STATUS: g_value_set_string (value, priv->status); break; case PROP_PROGRESS: g_value_set_double (value, priv->progress); break; case PROP_FINISHED: g_value_set_boolean (value, priv->finished); break; case PROP_SUCCESS: g_value_set_boolean (value, priv->success); break; case PROP_ERROR: g_value_set_string (value, priv->error); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transaction_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzTransaction *self = BZ_TRANSACTION (object); BzTransactionPrivate *priv = bz_transaction_get_instance_private (self); switch (prop_id) { case PROP_NAME: g_clear_pointer (&priv->name, g_free); priv->name = g_value_dup_string (value); break; case PROP_INSTALLS: g_clear_object (&priv->installs); priv->installs = g_value_dup_object (value); break; case PROP_UPDATES: g_clear_object (&priv->updates); priv->updates = g_value_dup_object (value); break; case PROP_REMOVALS: g_clear_object (&priv->removals); priv->removals = g_value_dup_object (value); break; case PROP_PENDING: priv->pending = g_value_get_boolean (value); break; case PROP_STATUS: g_clear_pointer (&priv->status, g_free); priv->status = g_value_dup_string (value); break; case PROP_PROGRESS: priv->progress = g_value_get_double (value); break; case PROP_FINISHED: priv->finished = g_value_get_boolean (value); if (priv->finished) finish (priv); break; case PROP_SUCCESS: priv->success = g_value_get_boolean (value); break; case PROP_ERROR: g_clear_pointer (&priv->error, g_free); priv->error = g_value_dup_string (value); break; case PROP_CURRENT_OPS: case PROP_FINISHED_OPS: case PROP_TRACKERS: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_transaction_class_init (BzTransactionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = bz_transaction_set_property; object_class->get_property = bz_transaction_get_property; object_class->dispose = bz_transaction_dispose; props[PROP_NAME] = g_param_spec_string ( "name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_INSTALLS] = g_param_spec_object ( "installs", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_UPDATES] = g_param_spec_object ( "updates", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_REMOVALS] = g_param_spec_object ( "removals", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_PENDING] = g_param_spec_boolean ( "pending", NULL, NULL, TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_CURRENT_OPS] = g_param_spec_object ( "current-ops", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_FINISHED_OPS] = g_param_spec_object ( "finished-ops", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_TRACKERS] = g_param_spec_object ( "trackers", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); props[PROP_STATUS] = g_param_spec_string ( "status", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_PROGRESS] = g_param_spec_double ( "progress", NULL, NULL, 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_FINISHED] = g_param_spec_boolean ( "finished", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_SUCCESS] = g_param_spec_boolean ( "success", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_ERROR] = g_param_spec_string ( "error", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_transaction_init (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_autoptr (GDateTime) now = NULL; priv = bz_transaction_get_instance_private (self); now = g_date_time_new_now_local (); priv->name = g_date_time_format (now, "%X"); priv->installs = g_list_store_new (BZ_TYPE_ENTRY); priv->updates = g_list_store_new (BZ_TYPE_ENTRY); priv->removals = g_list_store_new (BZ_TYPE_ENTRY); priv->pending = TRUE; priv->current_tasks = g_list_store_new (BZ_TYPE_TRANSACTION_TASK); priv->finished_tasks = g_list_store_new (BZ_TYPE_TRANSACTION_TASK); priv->trackers = g_list_store_new (BZ_TYPE_TRANSACTION_ENTRY_TRACKER); priv->status = g_strdup (_ ("Pending")); priv->success = TRUE; } BzTransaction * bz_transaction_new_full (BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals) { g_autoptr (BzTransaction) self = NULL; BzTransactionPrivate *priv = NULL; g_return_val_if_fail ((installs != NULL && n_installs > 0) || (updates != NULL && n_updates > 0) || (removals != NULL && n_removals > 0), NULL); for (guint i = 0; i < n_installs; i++) g_return_val_if_fail (BZ_IS_ENTRY (installs[i]), NULL); for (guint i = 0; i < n_updates; i++) g_return_val_if_fail (BZ_IS_ENTRY (updates[i]), NULL); for (guint i = 0; i < n_removals; i++) g_return_val_if_fail (BZ_IS_ENTRY (removals[i]), NULL); self = g_object_new (BZ_TYPE_TRANSACTION, NULL); priv = bz_transaction_get_instance_private (self); #define ADD_ENTRY(type, entry, transaction_type) \ G_STMT_START \ { \ g_autoptr (BzTransactionEntryTracker) tracker = NULL; \ g_autoptr (GListStore) current_ops = NULL; \ g_autoptr (GListStore) finished_ops = NULL; \ \ g_list_store_append (priv->type, (entry)); \ \ tracker = bz_transaction_entry_tracker_new (); \ current_ops = g_list_store_new (BZ_TYPE_TRANSACTION_TASK); \ finished_ops = g_list_store_new (BZ_TYPE_TRANSACTION_TASK); \ \ bz_transaction_entry_tracker_set_entry (tracker, (entry)); \ bz_transaction_entry_tracker_set_current_ops (tracker, G_LIST_MODEL (current_ops)); \ bz_transaction_entry_tracker_set_finished_ops (tracker, G_LIST_MODEL (finished_ops)); \ bz_transaction_entry_tracker_set_kind (tracker, transaction_type); \ bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_QUEUED); \ \ g_list_store_append (priv->trackers, tracker); \ } \ G_STMT_END for (guint i = 0; i < n_installs; i++) ADD_ENTRY (installs, installs[i], BZ_TRANSACTION_ENTRY_KIND_INSTALL); for (guint i = 0; i < n_updates; i++) ADD_ENTRY (updates, updates[i], BZ_TRANSACTION_ENTRY_KIND_UPDATE); for (guint i = 0; i < n_removals; i++) ADD_ENTRY (removals, removals[i], BZ_TRANSACTION_ENTRY_KIND_REMOVAL); #undef ADD_ENTRY return g_steal_pointer (&self); } BzTransaction * bz_transaction_new_merged (BzTransaction **transactions, guint n_transactions) { g_autoptr (GPtrArray) installs_pa = NULL; g_autoptr (GPtrArray) updates_pa = NULL; g_autoptr (GPtrArray) removals_pa = NULL; g_return_val_if_fail (transactions != NULL, NULL); g_return_val_if_fail (n_transactions >= 2, NULL); installs_pa = g_ptr_array_new_with_free_func (g_object_unref); updates_pa = g_ptr_array_new_with_free_func (g_object_unref); removals_pa = g_ptr_array_new_with_free_func (g_object_unref); for (guint i = 0; i < n_transactions; i++) { GListModel *installs = NULL; GListModel *updates = NULL; GListModel *removals = NULL; guint n_installs = 0; guint n_updates = 0; guint n_removals = 0; installs = bz_transaction_get_installs (transactions[i]); updates = bz_transaction_get_updates (transactions[i]); removals = bz_transaction_get_removals (transactions[i]); if (installs != NULL) n_installs = g_list_model_get_n_items (installs); if (updates != NULL) n_updates = g_list_model_get_n_items (updates); if (removals != NULL) n_removals = g_list_model_get_n_items (removals); for (guint j = 0; j < n_installs; j++) g_ptr_array_add (installs_pa, g_list_model_get_item (installs, j)); for (guint j = 0; j < n_updates; j++) g_ptr_array_add (updates_pa, g_list_model_get_item (updates, j)); for (guint j = 0; j < n_removals; j++) g_ptr_array_add (removals_pa, g_list_model_get_item (removals, j)); } return bz_transaction_new_full ( (BzEntry **) installs_pa->pdata, installs_pa->len, (BzEntry **) updates_pa->pdata, updates_pa->len, (BzEntry **) removals_pa->pdata, removals_pa->len); } GListModel * bz_transaction_get_installs (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_TRANSACTION (self), NULL); priv = bz_transaction_get_instance_private (self); return G_LIST_MODEL (priv->installs); } GListModel * bz_transaction_get_updates (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_TRANSACTION (self), NULL); priv = bz_transaction_get_instance_private (self); return G_LIST_MODEL (priv->updates); } GListModel * bz_transaction_get_removals (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_TRANSACTION (self), NULL); priv = bz_transaction_get_instance_private (self); return G_LIST_MODEL (priv->removals); } GListModel * bz_transaction_get_trackers (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_val_if_fail (BZ_IS_TRANSACTION (self), NULL); priv = bz_transaction_get_instance_private (self); return G_LIST_MODEL (priv->trackers); } void bz_transaction_hold (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_if_fail (BZ_IS_TRANSACTION (self)); priv = bz_transaction_get_instance_private (self); #define HOLD_MODEL(_model) \ if ((_model) != NULL) \ { \ guint n_items = 0; \ \ n_items = g_list_model_get_n_items (G_LIST_MODEL ((_model))); \ for (guint i = 0; i < n_items; i++) \ { \ g_autoptr (BzEntry) entry = NULL; \ \ entry = g_list_model_get_item (G_LIST_MODEL ((_model)), i); \ bz_entry_hold (entry); \ } \ } HOLD_MODEL (priv->installs); HOLD_MODEL (priv->updates); HOLD_MODEL (priv->removals); #undef HOLD_MODEL } void bz_transaction_release (BzTransaction *self) { BzTransactionPrivate *priv = NULL; g_return_if_fail (BZ_IS_TRANSACTION (self)); priv = bz_transaction_get_instance_private (self); #define RELEASE_MODEL(_model) \ if ((_model) != NULL) \ { \ guint n_items = 0; \ \ n_items = g_list_model_get_n_items (G_LIST_MODEL ((_model))); \ for (guint i = 0; i < n_items; i++) \ { \ g_autoptr (BzEntry) entry = NULL; \ \ entry = g_list_model_get_item (G_LIST_MODEL ((_model)), i); \ bz_entry_release (entry); \ } \ } RELEASE_MODEL (priv->installs); RELEASE_MODEL (priv->updates); RELEASE_MODEL (priv->removals); #undef RELEASE_MODEL } void bz_transaction_add_task (BzTransaction *self, BzBackendTransactionOpPayload *payload) { BzTransactionPrivate *priv = NULL; g_autoptr (BzTransactionTask) task = NULL; BzEntry *entry = NULL; g_autoptr (BzTransactionEntryTracker) tracker = NULL; gboolean result = FALSE; g_return_if_fail (BZ_IS_TRANSACTION (self)); g_return_if_fail (BZ_IS_BACKEND_TRANSACTION_OP_PAYLOAD (payload)); priv = bz_transaction_get_instance_private (self); task = bz_transaction_task_new (); bz_transaction_task_set_op (task, payload); g_list_store_append (priv->current_tasks, task); entry = bz_backend_transaction_op_payload_get_entry (payload); result = find_and_maybe_transfer ( priv->trackers, NULL, entry, (GEqualFuncFull) find_entry_eq_func, (gpointer *) &tracker); if (result) { GListModel *current_ops = NULL; current_ops = bz_transaction_entry_tracker_get_current_ops (tracker); g_list_store_append (G_LIST_STORE (current_ops), task); g_object_notify (G_OBJECT (tracker), "current-ops"); } } void bz_transaction_update_task (BzTransaction *self, BzBackendTransactionOpProgressPayload *payload) { BzTransactionPrivate *priv = NULL; BzBackendTransactionOpPayload *op = NULL; g_autoptr (BzTransactionTask) task = NULL; gboolean result = FALSE; g_return_if_fail (BZ_IS_TRANSACTION (self)); g_return_if_fail (BZ_IS_BACKEND_TRANSACTION_OP_PROGRESS_PAYLOAD (payload)); priv = bz_transaction_get_instance_private (self); op = bz_backend_transaction_op_progress_payload_get_op (payload); result = find_and_maybe_transfer ( priv->current_tasks, NULL, op, (GEqualFuncFull) find_payload_eq_func, (gpointer *) &task); if (result) bz_transaction_task_set_last_progress (task, payload); tracker_update (priv, op, FALSE); } void bz_transaction_finish_task (BzTransaction *self, BzBackendTransactionOpPayload *payload) { BzTransactionPrivate *priv = NULL; g_return_if_fail (BZ_IS_TRANSACTION (self)); g_return_if_fail (BZ_IS_BACKEND_TRANSACTION_OP_PAYLOAD (payload)); priv = bz_transaction_get_instance_private (self); find_and_maybe_transfer ( priv->current_tasks, priv->finished_tasks, payload, (GEqualFuncFull) find_payload_eq_func, NULL); tracker_update (priv, payload, TRUE); } void bz_transaction_error_out_task (BzTransaction *self, BzBackendTransactionOpPayload *payload, const char *message) { BzTransactionPrivate *priv = NULL; gboolean result = FALSE; g_autoptr (BzTransactionTask) task = NULL; g_return_if_fail (BZ_IS_TRANSACTION (self)); g_return_if_fail (BZ_IS_BACKEND_TRANSACTION_OP_PAYLOAD (payload)); g_return_if_fail (message != NULL); priv = bz_transaction_get_instance_private (self); result = find_and_maybe_transfer ( priv->current_tasks, priv->finished_tasks, payload, (GEqualFuncFull) find_payload_eq_func, (gpointer *) &task); if (result) bz_transaction_task_set_error (task, message); tracker_update (priv, payload, TRUE); } static void finish (BzTransactionPrivate *priv) { guint n_trackers = 0; n_trackers = g_list_model_get_n_items (G_LIST_MODEL (priv->trackers)); for (guint i = 0; i < n_trackers; i++) { g_autoptr (BzTransactionEntryTracker) tracker = NULL; tracker = g_list_model_get_item (G_LIST_MODEL (priv->trackers), i); bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_DONE); } } static gboolean find_payload_eq_func (BzTransactionTask *task, gpointer none, BzBackendTransactionOpPayload *payload) { return bz_transaction_task_get_op (task) == payload; } static gboolean find_entry_eq_func (BzTransactionEntryTracker *tracker, gpointer none, BzEntry *entry) { return bz_transaction_entry_tracker_get_entry (tracker) == entry; } /* This kinda sucks */ static gboolean find_and_maybe_transfer (GListStore *from, GListStore *to, gpointer lookup, GEqualFuncFull eql, gpointer *out) { guint op_pos = 0; gboolean found = FALSE; g_autoptr (GObject) object = NULL; found = g_list_store_find_with_equal_func_full (from, NULL, eql, lookup, &op_pos); if (!found) return FALSE; object = g_list_model_get_item (G_LIST_MODEL (from), op_pos); if (to != NULL) { /* transfer if `to` is provided */ g_list_store_remove (from, op_pos); g_list_store_append (to, object); } if (out != NULL) *out = g_steal_pointer (&object); return TRUE; } static void tracker_update (BzTransactionPrivate *priv, BzBackendTransactionOpPayload *payload, gboolean transfer) { BzEntry *entry = NULL; g_autoptr (BzTransactionEntryTracker) tracker = NULL; gboolean result = FALSE; entry = bz_backend_transaction_op_payload_get_entry (payload); result = find_and_maybe_transfer ( priv->trackers, NULL, entry, (GEqualFuncFull) find_entry_eq_func, (gpointer *) &tracker); if (result) { if (transfer) { GListModel *from = NULL; GListModel *to = NULL; bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_DONE); from = bz_transaction_entry_tracker_get_current_ops (tracker); to = bz_transaction_entry_tracker_get_finished_ops (tracker); result = find_and_maybe_transfer ( G_LIST_STORE (from), G_LIST_STORE (to), payload, (GEqualFuncFull) find_payload_eq_func, NULL); g_object_notify (G_OBJECT (tracker), "current-ops"); g_object_notify (G_OBJECT (tracker), "finished-ops"); } else bz_transaction_entry_tracker_set_status (tracker, BZ_TRANSACTION_ENTRY_STATUS_ONGOING); } } kolunmi-bazaar-7b9c8e1/src/bz-transaction.h000066400000000000000000000047451514314607700207720ustar00rootroot00000000000000/* bz-transaction.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry.h" #include "bz-transaction-entry-tracker.h" #include "bz-transaction-task.h" G_BEGIN_DECLS #define BZ_TYPE_TRANSACTION (bz_transaction_get_type ()) G_DECLARE_DERIVABLE_TYPE (BzTransaction, bz_transaction, BZ, TRANSACTION, GObject) struct _BzTransactionClass { GObjectClass parent_class; }; BzTransaction * bz_transaction_new_full (BzEntry **installs, guint n_installs, BzEntry **updates, guint n_updates, BzEntry **removals, guint n_removals); BzTransaction * bz_transaction_new_merged (BzTransaction **transactions, guint n_transactions); GListModel * bz_transaction_get_installs (BzTransaction *self); GListModel * bz_transaction_get_updates (BzTransaction *self); GListModel * bz_transaction_get_removals (BzTransaction *self); GListModel * bz_transaction_get_trackers (BzTransaction *self); void bz_transaction_hold (BzTransaction *self); void bz_transaction_release (BzTransaction *self); void bz_transaction_add_task (BzTransaction *self, BzBackendTransactionOpPayload *payload); void bz_transaction_update_task (BzTransaction *self, BzBackendTransactionOpProgressPayload *payload); void bz_transaction_finish_task (BzTransaction *self, BzBackendTransactionOpPayload *payload); void bz_transaction_error_out_task (BzTransaction *self, BzBackendTransactionOpPayload *payload, const char *message); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-updates-card.blp000066400000000000000000000124751514314607700213460ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzUpdatesCard: Adw.Bin { child: Box { orientation: vertical; margin-start: 4; margin-end: 4; margin-bottom: 4; overflow: hidden; styles [ "update-card", ] $BzListTile { activated => $tile_activated_cb(); styles [ "update-toggle", ] child: Box { height-request: 65; spacing: 8; margin-start: 12; margin-end: 8; Label { label: bind $format_update_count(template.state as <$BzStateInfo>.available-updates) as ; hexpand: true; halign: start; } Button { label: _("Update All"); valign: center; clicked => $update_all_cb(); styles [ "suggested-action", ] } Image toggle_icon { pixel-size: 14; margin-start: 4; margin-end: 4; icon-name: "go-next-symbolic"; valign: center; styles [ "dimmed", "accent", "ops-toggle", ] } }; } Revealer revealer { reveal-child: false; transition-type: slide_down; styles [ "update-list", ] child: Box { orientation: vertical; styles ["operations"] Separator {} ListView app_list { styles [ "navigation-sidebar", "installed-list-view", ] visible: bind $invert_boolean($is_zero(apps_filter_list as .n-items) as ) as ; model: NoSelection { model: FilterListModel apps_filter_list { filter: CustomFilter apps_filter {}; model: bind template.state as <$BzStateInfo>.available-updates; }; }; factory: BuilderListItemFactory { template ListItem { activatable: false; child: Box { orientation: horizontal; spacing: 10; margin-end: 8; margin-start: 4; margin-top: 2; margin-bottom: 2; Picture { height-request: 48; width-request: 48; paintable: bind template.item as <$BzEntry>.icon-paintable; visible: bind $invert_boolean($is_null(template.item as <$BzEntry>.icon-paintable) as ) as ; styles ["icon-dropshadow"] } Image { height-request: 48; width-request: 48; pixel-size: 48; icon-name: "application-x-executable"; visible: bind $is_null(template.item as <$BzEntry>.icon-paintable) as ; styles ["icon-dropshadow"] } Box { spacing: 2; hexpand: true; valign: center; orientation: vertical; Label { label: bind template.item as <$BzEntry>.title; xalign: 0; ellipsize: end; } Label version_label { label: bind $format_version_change(template.item as <$BzEntry>.version-history, template.item as <$BzEntry>.installed-version) as ; visible: bind $invert_boolean($is_empty_string(version_label.label) as ) as ; xalign: 0; ellipsize: end; styles [ "dimmed", "caption", "installed-size", ] } } Button { icon-name: "view-list-bullet-symbolic"; valign: center; has-tooltip: true; tooltip-text: _("Version History"); visible: bind $invert_boolean($is_null(template.item as <$BzEntry>.version-history) as ) as ; clicked => $show_version_history_cb(template); styles [ "flat", ] } Button { valign: center; label: _("Update"); clicked => $update_entry_cb(template); } }; } }; } Box runtimes_row { orientation: horizontal; spacing: 10; margin-end: 12; margin-start: 12; margin-top: bind $choose(app_list.visible as , 8 , 12) as ; margin-bottom: 12; visible: bind $invert_boolean($is_zero(runtimes_filter_model as .n-items) as ) as ; Label { label: bind $format_runtime_count(runtimes_filter_model as .n-items) as ; hexpand: true; xalign: 0; } Button { valign: center; label: _("Update"); clicked => $update_runtimes_cb(); } } }; } }; } FilterListModel runtimes_filter_model { filter: CustomFilter runtimes_filter {}; model: bind template.state as <$BzStateInfo>.available-updates; }kolunmi-bazaar-7b9c8e1/src/bz-updates-card.c000066400000000000000000000274271514314607700210160ustar00rootroot00000000000000/* bz-updates-card.c * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include "bz-list-tile.h" #include "bz-release.h" #include "bz-releases-list.h" #include "bz-template-callbacks.h" #include "bz-updates-card.h" struct _BzUpdatesCard { AdwBin parent_instance; BzStateInfo *state; /* Template widgets */ GtkRevealer *revealer; GtkImage *toggle_icon; GtkCustomFilter *apps_filter; GtkCustomFilter *runtimes_filter; GtkFilterListModel *runtimes_filter_model; }; G_DEFINE_FINAL_TYPE (BzUpdatesCard, bz_updates_card, ADW_TYPE_BIN) enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; enum { SIGNAL_UPDATE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL]; static char * format_update_count (gpointer object, GListModel *updates); static char * format_version_change (gpointer object, GListModel *version_history, const char *installed_version); static char * format_runtime_count (gpointer object, guint n_items); static void tile_activated_cb (BzListTile *tile, BzUpdatesCard *self); static void show_version_history_cb (GtkListItem *template, GtkButton *button); static void update_entry_cb (GtkListItem *template, GtkButton *button); static void update_all_cb (GtkButton *button, BzUpdatesCard *self); static void update_runtimes_cb (GtkButton *button, BzUpdatesCard *self); static gboolean filter_apps (BzEntry *entry, BzUpdatesCard *self); static gboolean filter_runtimes (BzEntry *entry, BzUpdatesCard *self); static void bz_updates_card_dispose (GObject *object) { BzUpdatesCard *self = BZ_UPDATES_CARD (object); g_clear_object (&self->state); G_OBJECT_CLASS (bz_updates_card_parent_class)->dispose (object); } static void bz_updates_card_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzUpdatesCard *self = BZ_UPDATES_CARD (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, bz_updates_card_get_state (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_updates_card_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzUpdatesCard *self = BZ_UPDATES_CARD (object); switch (prop_id) { case PROP_STATE: bz_updates_card_set_state (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_updates_card_class_init (BzUpdatesCardClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_updates_card_dispose; object_class->get_property = bz_updates_card_get_property; object_class->set_property = bz_updates_card_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_UPDATE] = g_signal_new ( "update", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_LIST_MODEL); g_signal_set_va_marshaller ( signals[SIGNAL_UPDATE], G_TYPE_FROM_CLASS (klass), g_cclosure_marshal_VOID__OBJECTv); g_type_ensure (BZ_TYPE_LIST_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-updates-card.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzUpdatesCard, revealer); gtk_widget_class_bind_template_child (widget_class, BzUpdatesCard, toggle_icon); gtk_widget_class_bind_template_child (widget_class, BzUpdatesCard, apps_filter); gtk_widget_class_bind_template_child (widget_class, BzUpdatesCard, runtimes_filter); gtk_widget_class_bind_template_child (widget_class, BzUpdatesCard, runtimes_filter_model); gtk_widget_class_bind_template_callback (widget_class, format_update_count); gtk_widget_class_bind_template_callback (widget_class, format_version_change); gtk_widget_class_bind_template_callback (widget_class, format_runtime_count); gtk_widget_class_bind_template_callback (widget_class, tile_activated_cb); gtk_widget_class_bind_template_callback (widget_class, show_version_history_cb); gtk_widget_class_bind_template_callback (widget_class, update_entry_cb); gtk_widget_class_bind_template_callback (widget_class, update_all_cb); gtk_widget_class_bind_template_callback (widget_class, update_runtimes_cb); } static void bz_updates_card_init (BzUpdatesCard *self) { gtk_widget_init_template (GTK_WIDGET (self)); gtk_custom_filter_set_filter_func ( self->apps_filter, (GtkCustomFilterFunc) filter_apps, self, NULL); gtk_custom_filter_set_filter_func ( self->runtimes_filter, (GtkCustomFilterFunc) filter_runtimes, self, NULL); } GtkWidget * bz_updates_card_new (void) { return g_object_new (BZ_TYPE_UPDATES_CARD, NULL); } void bz_updates_card_set_state (BzUpdatesCard *self, BzStateInfo *state) { g_return_if_fail (BZ_IS_UPDATES_CARD (self)); g_return_if_fail (state == NULL || BZ_IS_STATE_INFO (state)); g_clear_object (&self->state); if (state != NULL) self->state = g_object_ref (state); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]); } BzStateInfo * bz_updates_card_get_state (BzUpdatesCard *self) { g_return_val_if_fail (BZ_IS_UPDATES_CARD (self), NULL); return self->state; } static char * format_update_count (gpointer object, GListModel *updates) { guint n_updates = 0; if (updates == NULL) return g_strdup (""); n_updates = g_list_model_get_n_items (updates); return g_strdup_printf (ngettext ("%u Available Update", "%u Available Updates", n_updates), n_updates); } static char * format_version_change (gpointer object, GListModel *version_history, const char *installed_version) { const char *new_version = NULL; // This will probably the same as the installed version if using cache... g_autoptr (BzRelease) first_release = NULL; if (installed_version == NULL) return g_strdup (""); if (version_history == NULL || g_list_model_get_n_items (version_history) == 0) return g_strdup (""); first_release = g_list_model_get_item (version_history, 0); new_version = bz_release_get_version (first_release); if (new_version == NULL) return g_strdup (""); if (g_strcmp0 (installed_version, new_version) == 0) return g_strdup (""); return g_strdup_printf ("%s → %s", installed_version, new_version); } static char * format_runtime_count (gpointer object, guint n_items) { return g_strdup_printf (ngettext ("%u Runtime Update", "%u Runtime Updates", n_items), n_items); } static void tile_activated_cb (BzListTile *tile, BzUpdatesCard *self) { gboolean current_state = FALSE; g_assert (BZ_IS_LIST_TILE (tile)); g_assert (BZ_IS_UPDATES_CARD (self)); current_state = gtk_revealer_get_reveal_child (self->revealer); gtk_revealer_set_reveal_child (self->revealer, !current_state); if (!current_state) gtk_widget_add_css_class (GTK_WIDGET (self->toggle_icon), "rotated"); else gtk_widget_remove_css_class (GTK_WIDGET (self->toggle_icon), "rotated"); } static void show_version_history_cb (GtkListItem *template, GtkButton *button) { GtkWidget *dialog = NULL; GtkRoot *root = NULL; GListModel *version_history = NULL; BzEntry *entry = NULL; g_return_if_fail (GTK_IS_BUTTON (button)); g_return_if_fail (GTK_IS_LIST_ITEM (template)); root = gtk_widget_get_root (GTK_WIDGET (button)); if (root == NULL) return; entry = gtk_list_item_get_item (template); if (entry == NULL || !BZ_IS_ENTRY (entry)) return; g_object_get (entry, "version-history", &version_history, NULL); dialog = bz_releases_dialog_new (version_history, NULL); adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (root)); g_clear_object (&version_history); } static void update_entry_cb (GtkListItem *template, GtkButton *button) { BzUpdatesCard *self = NULL; BzEntry *entry = NULL; g_autoptr (GListStore) store = NULL; g_return_if_fail (GTK_IS_BUTTON (button)); g_return_if_fail (GTK_IS_LIST_ITEM (template)); self = BZ_UPDATES_CARD (gtk_widget_get_ancestor (GTK_WIDGET (button), BZ_TYPE_UPDATES_CARD)); if (self == NULL) return; entry = gtk_list_item_get_item (template); if (entry == NULL || !BZ_IS_ENTRY (entry)) return; store = g_list_store_new (BZ_TYPE_ENTRY); g_list_store_append (store, entry); g_signal_emit (self, signals[SIGNAL_UPDATE], 0, store); } static void update_all_cb (GtkButton *button, BzUpdatesCard *self) { GListModel *updates = NULL; g_return_if_fail (GTK_IS_BUTTON (button)); g_return_if_fail (BZ_IS_UPDATES_CARD (self)); if (self->state == NULL) return; updates = bz_state_info_get_available_updates (self->state); if (updates == NULL) return; g_signal_emit (self, signals[SIGNAL_UPDATE], 0, updates); } static void update_runtimes_cb (GtkButton *button, BzUpdatesCard *self) { GListModel *runtimes = NULL; g_autoptr (GListStore) store = NULL; guint n_items = 0; runtimes = G_LIST_MODEL (self->runtimes_filter_model); n_items = g_list_model_get_n_items (runtimes); if (n_items == 0) return; store = g_list_store_new (BZ_TYPE_ENTRY); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntry) entry = g_list_model_get_item (runtimes, i); if (entry != NULL) g_list_store_append (store, entry); } g_signal_emit (self, signals[SIGNAL_UPDATE], 0, store); } static gboolean filter_apps (BzEntry *entry, BzUpdatesCard *self) { g_return_val_if_fail (BZ_IS_ENTRY (entry), FALSE); return bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_APPLICATION); } static gboolean filter_runtimes (BzEntry *entry, BzUpdatesCard *self) { g_return_val_if_fail (BZ_IS_ENTRY (entry), FALSE); return bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_RUNTIME) || bz_entry_is_of_kinds (entry, BZ_ENTRY_KIND_ADDON); } kolunmi-bazaar-7b9c8e1/src/bz-updates-card.h000066400000000000000000000022621514314607700210110ustar00rootroot00000000000000/* bz-updates-card.h * * Copyright 2026 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-state-info.h" #include G_BEGIN_DECLS #define BZ_TYPE_UPDATES_CARD (bz_updates_card_get_type ()) G_DECLARE_FINAL_TYPE (BzUpdatesCard, bz_updates_card, BZ, UPDATES_CARD, AdwBin) GtkWidget * bz_updates_card_new (void); void bz_updates_card_set_state (BzUpdatesCard *self, BzStateInfo *state); BzStateInfo * bz_updates_card_get_state (BzUpdatesCard *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-url.txt000066400000000000000000000003011514314607700176170ustar00rootroot00000000000000prefix=bz name=url parent-prefix=g parent-name=object author=AUTOGEN property=name char G_TYPE_STRING string property=url char G_TYPE_STRING string property=icon_name char G_TYPE_STRING string kolunmi-bazaar-7b9c8e1/src/bz-user-data-page.blp000066400000000000000000000065271514314607700215720ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzUserDataPage: Adw.NavigationPage { title: _("Manage Leftover User Data"); Adw.ToolbarView { [top] Adw.HeaderBar { [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: menu { section { item { label: _("_Donate to Bazaar ❤️"); action: "app.donate"; } } section { item { label: _("_Preferences"); action: "app.preferences"; } item { label: _("_Login with Flathub"); action: "app.flathub-login"; hidden-when: "action-disabled"; } item { label: _("_Manage Leftover User Data"); action: "window.user-data"; } item { label: _("_Synchronize Remotes"); action: "app.sync-remotes"; } item { label: _("_Keyboard Shortcuts"); action: "app.shortcuts"; } item { label: _("_About Bazaar"); action: "app.about"; } } section { item { label: _("_Quit Bazaar"); action: "app.quit"; } } }; } } content: Adw.BreakpointBin { width-request: 360; height-request: 450; child: Adw.ViewStack stack { enable-transitions: true; transition-duration: 400; Adw.ViewStackPage { name: "loading"; title: _("Loading"); child:Adw.Spinner { halign: fill; valign: center; width-request: 64; height-request: 64; margin-bottom: 18; }; } Adw.ViewStackPage { name: "empty"; title: _("Empty"); child: Adw.StatusPage { icon-name: "folder-documents-symbolic"; title: _("No User Data found"); }; } Adw.ViewStackPage { name: "content"; title: _("User Data"); child: ScrolledWindow { hscrollbar-policy: never; child: Adw.ClampScrollable { maximum-size: 650; child: ListView list_view { styles [ "navigation-sidebar", "user-data-list-view" ] margin-start: 25; margin-end: 25; overflow: visible; model: NoSelection { model: bind template.model; }; factory: BuilderListItemFactory { template ListItem { activatable: false; selectable: false; focusable: false; child: $BzUserDataTile { group: bind template.item as <$BzEntryGroup>; }; } }; }; }; }; } }; Adw.Breakpoint { condition ("max-width: 700px") setters { list_view.margin-start: 0; list_view.margin-end: 0; } } }; } } kolunmi-bazaar-7b9c8e1/src/bz-user-data-page.c000066400000000000000000000211161514314607700212260ustar00rootroot00000000000000/* bz-user-data-page.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-application-map-factory.h" #include "bz-env.h" #include "bz-io.h" #include "bz-user-data-page.h" #include "bz-user-data-tile.h" #include "bz-util.h" struct _BzUserDataPage { AdwNavigationPage parent_instance; BzStateInfo *state; GListModel *model; /* Template widgets */ AdwViewStack *stack; }; G_DEFINE_FINAL_TYPE (BzUserDataPage, bz_user_data_page, ADW_TYPE_NAVIGATION_PAGE) enum { PROP_0, PROP_STATE, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static DexFuture * fetch_user_data_fiber (GWeakRef *wr); static void items_changed (BzUserDataPage *self, guint position, guint removed, guint added, GListModel *model); static void set_page (BzUserDataPage *self); static void bz_user_data_page_dispose (GObject *object) { BzUserDataPage *self = BZ_USER_DATA_PAGE (object); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); g_clear_object (&self->state); G_OBJECT_CLASS (bz_user_data_page_parent_class)->dispose (object); } static void bz_user_data_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzUserDataPage *self = BZ_USER_DATA_PAGE (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, self->state); break; case PROP_MODEL: g_value_set_object (value, self->model); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_user_data_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzUserDataPage *self = BZ_USER_DATA_PAGE (object); switch (prop_id) { case PROP_STATE: self->state = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_user_data_page_constructed (GObject *object) { BzUserDataPage *self = BZ_USER_DATA_PAGE (object); g_autoptr (DexFuture) future = NULL; G_OBJECT_CLASS (bz_user_data_page_parent_class)->constructed (object); future = dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) fetch_user_data_fiber, bz_track_weak (self), bz_weak_release); dex_future_disown (g_steal_pointer (&future)); } static gboolean is_zero (gpointer object, int value) { return value == 0; } static void bz_user_data_page_class_init (BzUserDataPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_user_data_page_dispose; object_class->constructed = bz_user_data_page_constructed; object_class->get_property = bz_user_data_page_get_property; object_class->set_property = bz_user_data_page_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_USER_DATA_TILE); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-user-data-page.ui"); gtk_widget_class_bind_template_child (widget_class, BzUserDataPage, stack); gtk_widget_class_bind_template_callback (widget_class, is_zero); } static void bz_user_data_page_init (BzUserDataPage *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_user_data_page_new (BzStateInfo *state) { return g_object_new (BZ_TYPE_USER_DATA_PAGE, "state", state, NULL); } static void items_changed (BzUserDataPage *self, guint position, guint removed, guint added, GListModel *model) { set_page (self); } static void set_page (BzUserDataPage *self) { if (self->model != NULL && g_list_model_get_n_items (G_LIST_MODEL (self->model)) > 0) adw_view_stack_set_visible_child_name (self->stack, "content"); else adw_view_stack_set_visible_child_name (self->stack, "empty"); } static int compare_entry_groups_by_title (BzEntryGroup *group_a, BzEntryGroup *group_b) { const char *title_a = bz_entry_group_get_title (group_a); const char *title_b = bz_entry_group_get_title (group_b); return g_utf8_collate (title_a, title_b); } static DexFuture * fetch_user_data_fiber (GWeakRef *wr) { g_autoptr (BzUserDataPage) self = NULL; g_autoptr (GHashTable) ids_hash = NULL; g_autoptr (GError) local_error = NULL; GHashTableIter iter = { 0 }; g_autoptr (GtkStringList) id_list = NULL; BzApplicationMapFactory *factory = NULL; g_autoptr (GListModel) model = NULL; g_autoptr (GListStore) sorted_store = NULL; GListModel *installed_groups = NULL; g_autoptr (GHashTable) installed_ids = NULL; guint n_items; self = g_weak_ref_get (wr); if (self == NULL) return dex_future_new_reject (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Page destroyed"); installed_groups = bz_state_info_get_all_installed_entry_groups (self->state); installed_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); if (installed_groups != NULL) { guint n_installed = g_list_model_get_n_items (installed_groups); for (guint i = 0; i < n_installed; i++) { g_autoptr (BzEntryGroup) group = NULL; const char *id = NULL; group = g_list_model_get_item (installed_groups, i); id = bz_entry_group_get_id (group); if (id != NULL) g_hash_table_replace (installed_ids, g_strdup (id), NULL); } } ids_hash = dex_await_boxed ( bz_get_user_data_ids_dex (), &local_error); if (ids_hash == NULL) { g_warning ("Failed to enumerate user data directories: %s", local_error->message); return dex_future_new_for_error (g_steal_pointer (&local_error)); } id_list = gtk_string_list_new (NULL); g_hash_table_iter_init (&iter, ids_hash); for (;;) { char *app_id = NULL; if (!g_hash_table_iter_next (&iter, (gpointer *) &app_id, NULL)) break; if (!g_hash_table_contains (installed_ids, app_id)) gtk_string_list_append (id_list, app_id); } factory = bz_state_info_get_application_factory (self->state); model = bz_application_map_factory_generate (factory, G_LIST_MODEL (id_list)); sorted_store = g_list_store_new (BZ_TYPE_ENTRY_GROUP); n_items = g_list_model_get_n_items (model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzEntryGroup) group = g_list_model_get_item (model, i); g_list_store_append (sorted_store, group); } g_list_store_sort (sorted_store, (GCompareDataFunc) compare_entry_groups_by_title, NULL); if (self->model != NULL) g_signal_handlers_disconnect_by_func (self->model, items_changed, self); g_clear_object (&self->model); self->model = G_LIST_MODEL (g_steal_pointer (&sorted_store)); g_signal_connect_swapped (self->model, "items-changed", G_CALLBACK (items_changed), self); set_page (self); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); return dex_future_new_true (); } kolunmi-bazaar-7b9c8e1/src/bz-user-data-page.h000066400000000000000000000020761514314607700212370ustar00rootroot00000000000000/* bz-user-data-page.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-state-info.h" #include G_BEGIN_DECLS #define BZ_TYPE_USER_DATA_PAGE (bz_user_data_page_get_type ()) G_DECLARE_FINAL_TYPE (BzUserDataPage, bz_user_data_page, BZ, USER_DATA_PAGE, AdwNavigationPage) GtkWidget * bz_user_data_page_new (BzStateInfo *state); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-user-data-tile.blp000066400000000000000000000046401514314607700216050ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzUserDataTile: Adw.Bin { child: Revealer { transition-type: slide_down; reveal-child: bind $invert_boolean($is_zero(template.group as <$BzEntryGroup>.user-data-size) as ) as ; child: Adw.Bin { accessibility { labelled-by: title_label; described-by: description_label; } margin-bottom: 4; margin-start: 4; margin-end: 4; margin-top: 4; styles [ "card", ] child: Box { orientation: horizontal; spacing: 10; Picture icon_picture { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 48; width-request: 48; paintable: bind template.group as <$BzEntryGroup>.icon-paintable; visible: bind $invert_boolean($is_null(template.group as <$BzEntryGroup>.icon-paintable) as ) as ; styles ["icon-dropshadow"] } Image fallback_icon { margin-start: 10; margin-top: 10; margin-bottom: 10; height-request: 48; width-request: 48; pixel-size: 48; icon-name: "application-x-executable"; visible: bind $is_null(template.group as <$BzEntryGroup>.icon-paintable) as ; styles ["icon-dropshadow"] } Box { orientation: vertical; valign: center; spacing: 4; Label title_label { xalign: 0.0; ellipsize: end; single-line-mode: true; has-tooltip: true; tooltip-text: bind template.group as <$BzEntryGroup>.id; label: bind template.group as <$BzEntryGroup>.title; } Label description_label { halign: start; label: bind $format_size(template.group as <$BzEntryGroup>.user-data-size) as ; styles ["accent", "caption-heading"] } } Button remove_button { styles [ "flat", "destructive-action", ] hexpand: true; halign: end; width-request: 32; height-request: 32; valign: center; margin-end: 16; has-tooltip: true; tooltip-text: _("Trash User Data"); icon-name: "user-trash-symbolic"; clicked => $remove_cb() swapped; } }; }; }; }kolunmi-bazaar-7b9c8e1/src/bz-user-data-tile.c000066400000000000000000000133451514314607700212540ustar00rootroot00000000000000/* bz-user-data-tile.c * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-entry-group.h" #include "bz-env.h" #include "bz-error.h" #include "bz-state-info.h" #include "bz-user-data-page.h" #include "bz-user-data-tile.h" #include "bz-window.h" struct _BzUserDataTile { BzListTile parent_instance; BzEntryGroup *group; GtkPicture *icon_picture; GtkImage *fallback_icon; GtkLabel *title_label; GtkButton *remove_button; }; G_DEFINE_FINAL_TYPE (BzUserDataTile, bz_user_data_tile, ADW_TYPE_BIN) enum { PROP_0, PROP_GROUP, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_user_data_tile_dispose (GObject *object) { BzUserDataTile *self = BZ_USER_DATA_TILE (object); g_clear_object (&self->group); G_OBJECT_CLASS (bz_user_data_tile_parent_class)->dispose (object); } static void bz_user_data_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzUserDataTile *self = BZ_USER_DATA_TILE (object); switch (prop_id) { case PROP_GROUP: g_value_set_object (value, bz_user_data_tile_get_group (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_user_data_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzUserDataTile *self = BZ_USER_DATA_TILE (object); switch (prop_id) { case PROP_GROUP: bz_user_data_tile_set_group (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gboolean invert_boolean (gpointer object, gboolean value) { return !value; } static gboolean is_null (gpointer object, GObject *value) { return value == NULL; } static gboolean is_zero (gpointer object, int value) { return value == 0; } static char * format_size (gpointer object, guint64 value) { return g_format_size (value); } static void remove_cb (BzUserDataTile *self, GtkButton *button) { BzWindow *window; AdwToast *toast; const char *title; g_autofree char *message = NULL; if (self->group == NULL) return; title = bz_entry_group_get_title (self->group); bz_entry_group_reap_user_data (self->group); window = BZ_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))); message = g_strdup_printf (_ ("Trashed User Data for %s"), title); toast = adw_toast_new (message); bz_window_add_toast (window, toast); } static void bz_user_data_tile_class_init (BzUserDataTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_user_data_tile_dispose; object_class->get_property = bz_user_data_tile_get_property; object_class->set_property = bz_user_data_tile_set_property; props[PROP_GROUP] = g_param_spec_object ( "group", NULL, NULL, BZ_TYPE_ENTRY_GROUP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_LIST_TILE); g_type_ensure (BZ_TYPE_ENTRY_GROUP); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-user-data-tile.ui"); gtk_widget_class_bind_template_child (widget_class, BzUserDataTile, icon_picture); gtk_widget_class_bind_template_child (widget_class, BzUserDataTile, fallback_icon); gtk_widget_class_bind_template_child (widget_class, BzUserDataTile, title_label); gtk_widget_class_bind_template_child (widget_class, BzUserDataTile, remove_button); gtk_widget_class_bind_template_callback (widget_class, invert_boolean); gtk_widget_class_bind_template_callback (widget_class, is_null); gtk_widget_class_bind_template_callback (widget_class, is_zero); gtk_widget_class_bind_template_callback (widget_class, format_size); gtk_widget_class_bind_template_callback (widget_class, remove_cb); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } static void bz_user_data_tile_init (BzUserDataTile *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_user_data_tile_new (void) { return g_object_new (BZ_TYPE_USER_DATA_TILE, NULL); } void bz_user_data_tile_set_group (BzUserDataTile *self, BzEntryGroup *group) { g_return_if_fail (BZ_IS_USER_DATA_TILE (self)); g_return_if_fail (group == NULL || BZ_IS_ENTRY_GROUP (group)); g_clear_object (&self->group); if (group != NULL) self->group = g_object_ref (group); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_GROUP]); } BzEntryGroup * bz_user_data_tile_get_group (BzUserDataTile *self) { g_return_val_if_fail (BZ_IS_USER_DATA_TILE (self), NULL); return self->group; } kolunmi-bazaar-7b9c8e1/src/bz-user-data-tile.h000066400000000000000000000023631514314607700212570ustar00rootroot00000000000000/* bz-user-data-tile.h * * Copyright 2025 Adam Masciola, Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "bz-entry-group.h" #include "bz-list-tile.h" #include G_BEGIN_DECLS #define BZ_TYPE_USER_DATA_TILE (bz_user_data_tile_get_type ()) G_DECLARE_FINAL_TYPE (BzUserDataTile, bz_user_data_tile, BZ, USER_DATA_TILE, AdwBin) GtkWidget * bz_user_data_tile_new (void); void bz_user_data_tile_set_group (BzUserDataTile *self, BzEntryGroup *group); BzEntryGroup * bz_user_data_tile_get_group (BzUserDataTile *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-util.h000066400000000000000000000214741514314607700174200ustar00rootroot00000000000000/* bz-util.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #define bz_maybe(_ptr, _func) ((_ptr) != NULL ? (_func) ((_ptr)) : NULL) #define bz_maybe_strdup(_ptr) bz_maybe (_ptr, g_strdup) #define bz_maybe_ref(_ptr, _ref) ((typeof (_ptr)) bz_maybe (_ptr, _ref)) #define bz_object_maybe_ref(_obj) bz_maybe_ref ((_obj), g_object_ref) #define bz_dex_maybe_ref(_obj) bz_maybe_ref ((_obj), dex_ref) #define BZ_RELEASE_DATA(name, unref) \ if ((unref) != NULL) \ { \ g_clear_pointer (&self->name, (unref)); \ } #define BZ_RELEASE_UTAG(name, remove) \ if ((remove) != NULL) \ { \ g_clear_handle_id (&self->name, (remove)); \ } /* va args = releases */ #define BZ_DEFINE_DATA(name, Name, layout, ...) \ typedef struct _##Name##Data Name##Data; \ struct _##Name##Data \ { \ gatomicrefcount rc; \ struct layout; \ }; \ G_GNUC_UNUSED \ static inline Name##Data * \ name##_data_new (void) \ { \ Name##Data *data = NULL; \ data = g_new0 (typeof (*data), 1); \ g_atomic_ref_count_init (&data->rc); \ return data; \ } \ G_GNUC_UNUSED \ static inline Name##Data * \ name##_data_ref (gpointer ptr) \ { \ Name##Data *self = ptr; \ g_atomic_ref_count_inc (&self->rc); \ return self; \ } \ G_GNUC_UNUSED \ static void \ name##_data_deinit (gpointer ptr) \ { \ Name##Data *self = ptr; \ __VA_ARGS__ \ } \ G_GNUC_UNUSED \ static void \ name##_data_unref (gpointer ptr) \ { \ Name##Data *self = ptr; \ if (g_atomic_ref_count_dec (&self->rc)) \ { \ name##_data_deinit (self); \ g_free (self); \ } \ } \ G_GNUC_UNUSED \ static void \ name##_data_unref_closure (gpointer data, \ GClosure *closure) \ { \ name##_data_unref (data); \ } \ G_DEFINE_AUTOPTR_CLEANUP_FUNC (Name##Data, name##_data_unref); /* Be careful with deadlocks */ typedef DexFuture BzGuard; static inline void bz_guard_destroy (BzGuard *guard) { if (dex_future_is_pending (guard)) dex_promise_resolve_boolean (DEX_PROMISE (guard), TRUE); dex_unref (guard); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (BzGuard, bz_guard_destroy); #define bz_clear_guard(_pp) g_clear_pointer (_pp, bz_guard_destroy) #define BZ_BEGIN_GUARD_WITH_CONTEXT(_guard, _mutex, _gate) \ G_STMT_START \ { \ g_autoptr (GMutexLocker) _locker = NULL; \ g_autoptr (DexFuture) _wait = NULL; \ \ _locker = g_mutex_locker_new (_mutex); \ if (*(_guard) == NULL) \ *(_guard) = (DexFuture *) dex_promise_new (); \ if (*(_gate) != NULL) \ { \ if (dex_future_is_pending (*(_gate))) \ _wait = g_steal_pointer (_gate); \ else \ dex_clear (_gate); \ } \ *(_gate) = dex_ref (*(_guard)); \ g_clear_pointer (&_locker, g_mutex_locker_free); \ \ if (_wait != NULL) \ dex_await (g_steal_pointer (&_wait), NULL); \ } \ G_STMT_END #define BZ_BEGIN_GUARD(_guard) \ G_STMT_START \ { \ static GMutex _mutex = { 0 }; \ static BzGuard *_gate = NULL; \ BZ_BEGIN_GUARD_WITH_CONTEXT (_guard, &_mutex, &_gate); \ } \ G_STMT_END /* Use with dex_scheduler_spawn */ G_GNUC_UNUSED static GWeakRef * bz_track_weak (gpointer object) { GWeakRef *wr = NULL; if (object == NULL) return NULL; wr = g_new0 (typeof (*wr), 1); g_weak_ref_init (wr, object); return wr; } G_GNUC_UNUSED static void bz_weak_release (gpointer ptr) { GWeakRef *wr = ptr; g_weak_ref_clear (wr); g_free (wr); } #define bz_weak_get_or_return(self, wr) \ G_STMT_START \ { \ (self) = g_weak_ref_get (wr); \ if ((self) == NULL) \ return; \ } \ G_STMT_END #define bz_weak_get_or_return_reject(self, wr) \ G_STMT_START \ { \ (self) = g_weak_ref_get (wr); \ if ((self) == NULL) \ return dex_future_new_reject ( \ G_IO_ERROR, \ G_IO_ERROR_CANCELLED, \ "Object was discarded"); \ } \ G_STMT_END G_GNUC_UNUSED static void _bz_debug_print_when_disposed_cb (gpointer ptr); BZ_DEFINE_DATA ( _bz_debug_dispose_cb, _BzDebugDisposeCb, { GType type; const char *loc; guint64 time; }, _bz_debug_print_when_disposed_cb (self);) G_GNUC_UNUSED static void _bz_debug_print_when_disposed_cb (gpointer ptr) { _BzDebugDisposeCbData *data = ptr; g_print ("%zu OBJECT DISPOSE: type %s; from %s at %zu\n", g_get_monotonic_time (), g_type_name (data->type), data->loc, data->time); } #define BZ_DEBUG_PRINT_WHEN_DISPOSED(_object) \ G_STMT_START \ { \ g_autoptr (_BzDebugDisposeCbData) _data = NULL; \ \ _data = _bz_debug_dispose_cb_data_new (); \ _data->type = G_OBJECT_TYPE (_object); \ _data->loc = G_STRLOC; \ _data->time = g_get_monotonic_time (); \ \ g_object_set_data_full ( \ G_OBJECT (_object), \ "BZ_DEBUG_PRINT_WHEN_DISPOSED", \ _bz_debug_dispose_cb_data_ref (_data), \ _bz_debug_dispose_cb_data_unref); \ } \ G_STMT_END kolunmi-bazaar-7b9c8e1/src/bz-verification-status.txt000066400000000000000000000006511514314607700230300ustar00rootroot00000000000000prefix=bz name=verification_status parent-prefix=g parent-name=object author=AUTOGEN property=verified gboolean G_TYPE_BOOLEAN boolean property=method char G_TYPE_STRING string property=website char G_TYPE_STRING string property=login_name char G_TYPE_STRING string property=login_provider char G_TYPE_STRING string property=timestamp char G_TYPE_STRING string property=login_is_organization gboolean G_TYPE_BOOLEAN boolean kolunmi-bazaar-7b9c8e1/src/bz-view-switcher-button.blp000066400000000000000000000006431514314607700230750ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; template $BzViewSwitcherButton: Adw.Bin { child: Button toggle { styles [ "flat", ] child: Box { orientation: horizontal; spacing: 8; Image { icon-size: normal; icon-name: bind template.page as .icon-name; } Label { label: bind template.page as .title; } }; }; } kolunmi-bazaar-7b9c8e1/src/bz-view-switcher-button.c000066400000000000000000000103411514314607700225360ustar00rootroot00000000000000/* bz-view-switcher-button.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-view-switcher-button.h" struct _BzViewSwitcherButton { AdwBin parent_instance; AdwViewStackPage *page; GtkButton *toggle; }; G_DEFINE_FINAL_TYPE (BzViewSwitcherButton, bz_view_switcher_button, ADW_TYPE_BIN); enum { PROP_0, PROP_PAGE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_view_switcher_button_dispose (GObject *object) { BzViewSwitcherButton *self = BZ_VIEW_SWITCHER_BUTTON (object); g_clear_pointer (&self->page, g_object_unref); G_OBJECT_CLASS (bz_view_switcher_button_parent_class)->dispose (object); } static void bz_view_switcher_button_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzViewSwitcherButton *self = BZ_VIEW_SWITCHER_BUTTON (object); switch (prop_id) { case PROP_PAGE: g_value_set_object (value, bz_view_switcher_button_get_page (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_view_switcher_button_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzViewSwitcherButton *self = BZ_VIEW_SWITCHER_BUTTON (object); switch (prop_id) { case PROP_PAGE: bz_view_switcher_button_set_page (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_view_switcher_button_class_init (BzViewSwitcherButtonClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_view_switcher_button_set_property; object_class->get_property = bz_view_switcher_button_get_property; object_class->dispose = bz_view_switcher_button_dispose; props[PROP_PAGE] = g_param_spec_object ( "page", NULL, NULL, ADW_TYPE_VIEW_STACK_PAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-view-switcher-button.ui"); gtk_widget_class_bind_template_child (widget_class, BzViewSwitcherButton, toggle); } static void bz_view_switcher_button_init (BzViewSwitcherButton *self) { gtk_widget_init_template (GTK_WIDGET (self)); } GtkWidget * bz_view_switcher_button_new (void) { return g_object_new (BZ_TYPE_VIEW_SWITCHER_BUTTON, NULL); } GtkButton * bz_view_switcher_button_get_toggle (BzViewSwitcherButton *self) { g_return_val_if_fail (BZ_IS_VIEW_SWITCHER_BUTTON (self), NULL); return self->toggle; } AdwViewStackPage * bz_view_switcher_button_get_page (BzViewSwitcherButton *self) { g_return_val_if_fail (BZ_IS_VIEW_SWITCHER_BUTTON (self), NULL); return self->page; } void bz_view_switcher_button_set_page (BzViewSwitcherButton *self, AdwViewStackPage *page) { g_return_if_fail (BZ_IS_VIEW_SWITCHER_BUTTON (self)); if (page == self->page) return; g_clear_pointer (&self->page, g_object_unref); if (page != NULL) self->page = g_object_ref (page); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PAGE]); } /* End of bz-view-switcher-button.c */ kolunmi-bazaar-7b9c8e1/src/bz-view-switcher-button.h000066400000000000000000000025461514314607700225530ustar00rootroot00000000000000/* bz-view-switcher-button.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_VIEW_SWITCHER_BUTTON (bz_view_switcher_button_get_type ()) G_DECLARE_FINAL_TYPE (BzViewSwitcherButton, bz_view_switcher_button, BZ, VIEW_SWITCHER_BUTTON, AdwBin) GtkWidget * bz_view_switcher_button_new (void); GtkButton * bz_view_switcher_button_get_toggle (BzViewSwitcherButton *self); AdwViewStackPage * bz_view_switcher_button_get_page (BzViewSwitcherButton *self); void bz_view_switcher_button_set_page (BzViewSwitcherButton *self, AdwViewStackPage *page); G_END_DECLS /* End of bz-view-switcher-button.h */ kolunmi-bazaar-7b9c8e1/src/bz-view-switcher.c000066400000000000000000000235431514314607700212350ustar00rootroot00000000000000/* bz-view-switcher.c * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-view-switcher.h" #include "bz-view-switcher-button.h" struct _BzViewSwitcher { GtkWidget parent_instance; GtkWidget *box; AdwViewStack *stack; GtkSelectionModel *pages; GPtrArray *buttons; }; G_DEFINE_FINAL_TYPE (BzViewSwitcher, bz_view_switcher, GTK_TYPE_WIDGET); enum { PROP_0, PROP_STACK, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void pages_changed (BzViewSwitcher *self, guint position, guint removed, guint added, GListModel *model); static void selection_changed (BzViewSwitcher *self, guint position, guint n_items, GtkSelectionModel *model); static void button_clicked (GtkButton *toggle, BzViewSwitcherButton *button); static void refresh_selection (BzViewSwitcher *self); static void bz_view_switcher_dispose (GObject *object) { BzViewSwitcher *self = BZ_VIEW_SWITCHER (object); if (self->pages != NULL) { g_signal_handlers_disconnect_by_func ( self->pages, pages_changed, self); g_signal_handlers_disconnect_by_func ( self->pages, selection_changed, self); } g_clear_pointer (&self->box, gtk_widget_unparent); g_clear_pointer (&self->stack, g_object_unref); g_clear_pointer (&self->pages, g_object_unref); g_clear_pointer (&self->buttons, g_ptr_array_unref); G_OBJECT_CLASS (bz_view_switcher_parent_class)->dispose (object); } static void bz_view_switcher_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzViewSwitcher *self = BZ_VIEW_SWITCHER (object); switch (prop_id) { case PROP_STACK: g_value_set_object (value, bz_view_switcher_get_stack (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_view_switcher_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzViewSwitcher *self = BZ_VIEW_SWITCHER (object); switch (prop_id) { case PROP_STACK: bz_view_switcher_set_stack (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_view_switcher_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzViewSwitcher *self = BZ_VIEW_SWITCHER (widget); gtk_widget_allocate (self->box, width, height, baseline, NULL); } static void bz_view_switcher_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzViewSwitcher *self = BZ_VIEW_SWITCHER (widget); gtk_widget_measure ( self->box, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); } static void bz_view_switcher_class_init (BzViewSwitcherClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = bz_view_switcher_set_property; object_class->get_property = bz_view_switcher_get_property; object_class->dispose = bz_view_switcher_dispose; props[PROP_STACK] = g_param_spec_object ( "stack", NULL, NULL, ADW_TYPE_VIEW_STACK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->measure = bz_view_switcher_measure; widget_class->size_allocate = bz_view_switcher_size_allocate; g_type_ensure (BZ_TYPE_VIEW_SWITCHER_BUTTON); } static void bz_view_switcher_init (BzViewSwitcher *self) { self->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_widget_set_parent (self->box, GTK_WIDGET (self)); self->buttons = g_ptr_array_new (); } BzViewSwitcher * bz_view_switcher_new (void) { return g_object_new (BZ_TYPE_VIEW_SWITCHER, NULL); } AdwViewStack * bz_view_switcher_get_stack (BzViewSwitcher *self) { g_return_val_if_fail (BZ_IS_VIEW_SWITCHER (self), NULL); return self->stack; } void bz_view_switcher_set_stack (BzViewSwitcher *self, AdwViewStack *stack) { g_return_if_fail (BZ_IS_VIEW_SWITCHER (self)); g_return_if_fail (stack == NULL || ADW_IS_VIEW_STACK (stack)); if (stack == self->stack) return; if (self->pages != NULL) { guint n_items = 0; g_signal_handlers_disconnect_by_func ( self->pages, pages_changed, self); g_signal_handlers_disconnect_by_func ( self->pages, selection_changed, self); n_items = g_list_model_get_n_items (G_LIST_MODEL (self->pages)); pages_changed (self, 0, n_items, 0, G_LIST_MODEL (self->pages)); } for (guint i = 0; i < self->buttons->len; i++) { GtkWidget *button = NULL; button = g_ptr_array_index (self->buttons, i); gtk_widget_unparent (button); } g_ptr_array_set_size (self->buttons, 0); g_clear_pointer (&self->stack, g_object_unref); g_clear_pointer (&self->pages, g_object_unref); if (stack != NULL) { guint n_items = 0; self->stack = g_object_ref (stack); self->pages = adw_view_stack_get_pages (stack); n_items = g_list_model_get_n_items (G_LIST_MODEL (self->pages)); pages_changed (self, 0, 0, n_items, G_LIST_MODEL (self->pages)); refresh_selection (self); g_signal_connect_swapped ( self->pages, "items-changed", G_CALLBACK (pages_changed), self); g_signal_connect_swapped ( self->pages, "selection-changed", G_CALLBACK (selection_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STACK]); } static void pages_changed (BzViewSwitcher *self, guint position, guint removed, guint added, GListModel *model) { for (guint i = 0; i < removed; i++) { GtkWidget *button = NULL; button = g_ptr_array_index (self->buttons, position + i); gtk_widget_unparent (button); } if (removed > 0) g_ptr_array_remove_range (self->buttons, position, removed); for (guint i = 0; i < added; i++) { g_autoptr (AdwViewStackPage) page = NULL; GtkWidget *button = NULL; GtkButton *toggle = NULL; GtkWidget *sibling = NULL; page = g_list_model_get_item (G_LIST_MODEL (self->pages), position + i); button = bz_view_switcher_button_new (); bz_view_switcher_button_set_page (BZ_VIEW_SWITCHER_BUTTON (button), page); toggle = bz_view_switcher_button_get_toggle (BZ_VIEW_SWITCHER_BUTTON (button)); g_signal_connect ( toggle, "clicked", G_CALLBACK (button_clicked), button); if (position + i > 0) sibling = g_ptr_array_index (self->buttons, position + i - 1); gtk_box_insert_child_after (GTK_BOX (self->box), button, sibling); g_ptr_array_insert (self->buttons, position + i, button); } } static void selection_changed (BzViewSwitcher *self, guint position, guint n_items, GtkSelectionModel *model) { refresh_selection (self); } static void button_clicked (GtkButton *toggle, BzViewSwitcherButton *button) { BzViewSwitcher *self = NULL; gboolean result = FALSE; guint idx = 0; if (!gtk_widget_has_css_class (GTK_WIDGET (toggle), "flat")) return; self = (BzViewSwitcher *) gtk_widget_get_ancestor ( GTK_WIDGET (button), BZ_TYPE_VIEW_SWITCHER); g_assert (self != NULL); result = g_ptr_array_find (self->buttons, button, &idx); if (result) gtk_selection_model_select_item (self->pages, idx, TRUE); } static void refresh_selection (BzViewSwitcher *self) { g_autoptr (GtkBitset) bitset = NULL; guint selected_idx = 0; g_assert (self->pages != NULL); bitset = gtk_selection_model_get_selection (self->pages); selected_idx = gtk_bitset_get_nth (bitset, 0); for (guint i = 0; i < self->buttons->len; i++) { BzViewSwitcherButton *button = NULL; GtkButton *toggle = NULL; button = g_ptr_array_index (self->buttons, i); toggle = bz_view_switcher_button_get_toggle (button); if (i == selected_idx) gtk_widget_remove_css_class (GTK_WIDGET (toggle), "flat"); else gtk_widget_add_css_class (GTK_WIDGET (toggle), "flat"); } } /* End of bz-view-switcher.c */ kolunmi-bazaar-7b9c8e1/src/bz-view-switcher.h000066400000000000000000000023021514314607700212300ustar00rootroot00000000000000/* bz-view-switcher.h * * Copyright 2026 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_VIEW_SWITCHER (bz_view_switcher_get_type ()) G_DECLARE_FINAL_TYPE (BzViewSwitcher, bz_view_switcher, BZ, VIEW_SWITCHER, GtkWidget) BzViewSwitcher * bz_view_switcher_new (void); AdwViewStack * bz_view_switcher_get_stack (BzViewSwitcher *self); void bz_view_switcher_set_stack (BzViewSwitcher *self, AdwViewStack *stack); G_END_DECLS /* End of bz-view-switcher.h */ kolunmi-bazaar-7b9c8e1/src/bz-window.blp000066400000000000000000000353171514314607700203010ustar00rootroot00000000000000using Gtk 4.0; using Gio 2.0; using Adw 1; template $BzWindow: Adw.ApplicationWindow { title: _("Bazaar"); default-width: 1220; default-height: 900; width-request: 360; height-request: 550; ShortcutController { Shortcut { trigger: "Escape"; action: "action(escape)"; } Shortcut { trigger: "Back"; action: "action(escape)"; } Shortcut { trigger: "BackSpace"; action: "action(escape)"; } Shortcut { trigger: "g"; action: "action(escape)"; } } content: Adw.ToolbarView { [bottom] Adw.HeaderBar { styles [ "bz-debug", ] visible: bind template.state as <$BzStateInfo>.debug_mode as ; show-title: false; show-start-title-buttons: false; show-end-title-buttons: false; [start] Box { visible: bind $invert_boolean($is_null(full_view.entry_group as <$BzEntryGroup>) as ) as ; orientation: horizontal; spacing: 10; Label { styles [ "caption-heading", ] label: "ID:"; } Label debug_id_label { styles [ "bz-monospace", ] label: bind full_view.entry_group as <$BzEntryGroup>.id as ; selectable: true; ellipsize: end; } Button { label: "Inspect UI Entry"; clicked => $debug_id_inspect_cb(template); } } [end] MenuButton { label: "All Debug Actions"; menu-model: debug_menu; } [end] Label { styles [ "caption-heading", ] visible: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active as ; label: bind $format_progress(template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.current-progress as ) as ; } [end] Label { visible: bind $invert_boolean($is_null(template.state as <$BzStateInfo>.background-task-label as ) as ) as ; label: bind template.state as <$BzStateInfo>.background-task-label as ; } } content: $BzPopupOverlay popup_overlay { child: $BzCometOverlay comet_overlay { child: Adw.BreakpointBin split_breakpoint_bin { width-request: 360; height-request: 450; child: Adw.ToastOverlay toasts { child: Adw.NavigationView navigation_view { pop-on-escape: false; Adw.NavigationPage { tag: "main"; title: _("Bazaar"); child: Adw.ToolbarView toolbar_view { top-bar-style: flat; bottom-bar-style: flat; reveal-bottom-bars: false; content: Stack main_stack { StackPage { name: "loading"; child: Box { halign: fill; valign: center; orientation: vertical; spacing: 6; Adw.Spinner { width-request: 64; height-request: 64; margin-bottom: 18; } Label { label: _("Refreshing Store Content"); wrap: true; justify: center; margin-bottom: 24; styles [ "title-3", ] } }; } StackPage { name: "main"; child: Adw.ViewStack main_view_stack { Adw.ViewStackPage { name: "browse"; title: _("Curated"); icon-name: "starred-symbolic"; visible: bind template.state as <$BzStateInfo>.curated-provider as <$BzContentProvider>.has-inputs; child: $BzCuratedView browse { state: bind template.state as <$BzStateInfo>; group-selected => $browser_group_selected_cb(template); browse-flathub => $browse_flathub_cb(template); }; } Adw.ViewStackPage { name: "flathub"; title: _("Flathub"); icon-name: "flathub-symbolic"; child: $BzFlathubPage { state: bind template.state as <$BzStateInfo>; group-selected => $browser_group_selected_cb(template); open-search => $open_search_cb(template); }; } Adw.ViewStackPage { name: "installed"; // Translators: . title: _("Library"); icon-name: "library-symbolic"; badge-number: bind template.state as <$BzStateInfo>.available-updates as .n-items; needs-attention: bind template.state as <$BzStateInfo>.available-updates as .n-items; child: $BzLibraryPage library_page { state: bind template.state; model: bind template.state as <$BzStateInfo>.all-installed-entry-groups; remove => $remove_installed_cb(template); remove-addon => $remove_addon_cb(template); install-addon => $install_addon_cb(template); show-entry => $library_page_show_cb(template); update => $update_cb(template); }; } Adw.ViewStackPage { name: "search"; title: _("Search"); icon-name: "system-search-symbolic"; child: $BzSearchWidget search_widget { state: bind template.state; select => $search_widget_select_cb(template); }; } }; } }; [top] Box { orientation: vertical; Adw.HeaderBar top_header_bar { [start] MenuButton { visible: bind template.state as <$BzStateInfo>.auth-state as <$BzAuthState>.authenticated; menu-model: account_menu; styles [ "circular", "flat", ] child: Adw.Avatar { size: 24; custom-image: bind template.state as <$BzStateInfo>.auth-state as <$BzAuthState>.paintable; }; } [start] Revealer { transition-type: crossfade; transition-duration: 750; reveal-child: bind $logical_or($invert_boolean($is_null(template.state as <$BzStateInfo>.background-task-label) as ) as , status_popover.visible) as ; child: MenuButton { styles [ "flat", ] child: Box { Adw.Spinner { visible: bind status_popover_label.visible; } Image { visible: bind $invert_boolean(status_popover_label.visible) as ; icon-name: "check-plain-symbolic"; } }; popover: Popover status_popover { has-arrow: true; position: right; child: Box { orientation: vertical; margin-top: 12; margin-bottom: 12; margin-start: 12; margin-end: 12; width-request: 300; Label status_popover_label { hexpand: true; visible: bind $invert_boolean($is_null(template.state as <$BzStateInfo>.background-task-label) as ) as ; label: bind template.state as <$BzStateInfo>.background-task-label; } Label { hexpand: true; visible: bind $invert_boolean(status_popover_label.visible) as ; label: _("No background tasks!"); } }; }; }; } [title] Adw.ViewSwitcher { stack: main_view_stack; policy: wide; sensitive: bind $invert_boolean(template.state as <$BzStateInfo>.busy) as ; } [end] MenuButton { primary: true; icon-name: "open-menu-symbolic"; has-tooltip: true; tooltip-text: _("Main Menu"); menu-model: primary_menu; } [end] Button { styles [ "flat", "global-progress-button", ] can-target: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; action-name: "window.open-library"; has-tooltip: true; tooltip-text: _("Open App Library"); child: $BzGlobalProgress { expand-size: 125; active: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.active; pending: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.pending; fraction: bind template.state as <$BzStateInfo>.transaction-manager as <$BzTransactionManager>.current-progress; settings: bind template.state as <$BzStateInfo>.settings; }; } } Adw.Banner { styles [ "bz-donations-banner", ] revealed: bind $invert_boolean(template.state as <$BzStateInfo>.donation-prompt-dismissed as ) as ; title: _("You are running a new version of Bazaar!"); button-label: _("See What's New"); action-name: "app.donate"; } Adw.Banner { sensitive: bind $invert_boolean(template.state as <$BzStateInfo>.syncing as ) as ; revealed: bind $logical_and($invert_boolean(template.state as <$BzStateInfo>.metered_connection as ) as , $logical_and(template.state as <$BzStateInfo>.have_connection as , $invert_boolean(template.state as <$BzStateInfo>.online as ) as ) as ) as ; title: _("You have a network connection but are viewing a cached version of Flathub"); button-label: _("Sync Manually"); button-clicked => $sync_cb(template); } } [bottom] Adw.ViewSwitcherBar { stack: main_view_stack; reveal: true; sensitive: bind $invert_boolean(template.state as <$BzStateInfo>.busy) as ; } }; } Adw.NavigationPage { tag: "view"; title: "view"; child: $BzFullView full_view { state: bind template.state; main-menu: primary_menu; install => $full_view_install_cb(template); remove => $full_view_remove_cb(template); install-addon => $install_addon_cb(template); remove-addon => $remove_addon_cb(template); }; } }; }; Adw.Breakpoint { condition ("max-width: 700px") setters { top_header_bar.title-widget: null; toolbar_view.reveal-bottom-bars: true; } apply => $breakpoint_apply_cb(template); unapply => $breakpoint_unapply_cb(template); } }; }; }; }; } menu primary_menu { section { item { label: _("_Donate to Bazaar ❤️"); action: "app.donate"; } } section { item { label: _("_Preferences"); action: "app.preferences"; } item { label: _("_Login with Flathub"); action: "app.flathub-login"; hidden-when: "action-disabled"; } item { label: _("_Manage Leftover User Data"); action: "window.user-data"; } item { label: _("_Synchronize Remotes"); action: "app.sync-remotes"; } item { label: _("_Keyboard Shortcuts"); action: "app.shortcuts"; } item { label: _("_About Bazaar"); action: "app.about"; } } section { item { label: _("_Quit Bazaar"); action: "app.quit"; } } } menu debug_menu { section { item { label: "Open Bazaar Inspector"; action: "app.bazaar-inspector"; } } } menu account_menu { section { item { label: _("Favorites"); action: "app.flathub-favorites"; } } section { item { label: _("Log Out"); action: "app.flathub-logout"; } } } kolunmi-bazaar-7b9c8e1/src/bz-window.c000066400000000000000000000716201514314607700177430ustar00rootroot00000000000000/* bz-window.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ // This file is an utter mess #include "config.h" #include #include "bz-comet-overlay.h" #include "bz-curated-view.h" #include "bz-entry-group.h" #include "bz-entry-inspector.h" #include "bz-env.h" #include "bz-error.h" #include "bz-favorites-page.h" #include "bz-flathub-page.h" #include "bz-full-view.h" #include "bz-global-progress.h" #include "bz-io.h" #include "bz-library-page.h" #include "bz-popup-overlay.h" #include "bz-progress-bar.h" #include "bz-search-widget.h" #include "bz-template-callbacks.h" #include "bz-transaction-dialog.h" #include "bz-transaction-manager.h" #include "bz-user-data-page.h" #include "bz-util.h" #include "bz-window.h" struct _BzWindow { AdwApplicationWindow parent_instance; BzStateInfo *state; GtkEventController *key_controller; gboolean breakpoint_applied; /* Template widgets */ BzCometOverlay *comet_overlay; BzPopupOverlay *popup_overlay; AdwNavigationView *navigation_view; BzFullView *full_view; BzSearchWidget *search_widget; BzLibraryPage *library_page; AdwToastOverlay *toasts; AdwViewStack *main_view_stack; GtkStack *main_stack; GtkLabel *debug_id_label; }; G_DEFINE_FINAL_TYPE (BzWindow, bz_window, ADW_TYPE_APPLICATION_WINDOW) enum { PROP_0, PROP_STATE, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; BZ_DEFINE_DATA ( transact, Transact, { GWeakRef *self; BzEntry *entry; BzEntryGroup *group; gboolean remove; gboolean auto_confirm; GtkWidget *source; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (entry, g_object_unref); BZ_RELEASE_DATA (group, g_object_unref); BZ_RELEASE_DATA (source, g_object_unref)) static DexFuture * transact_fiber (TransactData *data); BZ_DEFINE_DATA ( bulk_install, BulkInstall, { GWeakRef *self; GListModel *groups; }, BZ_RELEASE_DATA (self, bz_weak_release); BZ_RELEASE_DATA (groups, g_object_unref)) static DexFuture * bulk_install_fiber (BulkInstallData *data); static DexFuture * transact (BzWindow *self, BzEntry *entry, gboolean remove, GtkWidget *source); static void try_transact (BzWindow *self, BzEntry *entry, BzEntryGroup *group, gboolean remove, gboolean auto_confirm, GtkWidget *source); static void search (BzWindow *self, const char *text); static void bulk_install (BzWindow *self, BzEntry **installs, guint n_installs); static void set_page (BzWindow *self); static void bz_window_dispose (GObject *object) { BzWindow *self = BZ_WINDOW (object); g_clear_object (&self->state); G_OBJECT_CLASS (bz_window_parent_class)->dispose (object); } static void bz_window_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzWindow *self = BZ_WINDOW (object); switch (prop_id) { case PROP_STATE: g_value_set_object (value, self->state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_window_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { // BzWindow *self = BZ_WINDOW (object); switch (prop_id) { case PROP_STATE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static char * list_length (gpointer object, GListModel *model) { if (model == NULL) return g_strdup (0); return g_strdup_printf ("%u", g_list_model_get_n_items (model)); } static void browser_group_selected_cb (BzWindow *self, BzEntryGroup *group, gpointer browser) { bz_window_show_group (self, group); } static void search_widget_select_cb (BzWindow *self, BzEntryGroup *group, gboolean should_install, BzSearchWidget *search) { if (should_install) { int installable = 0; int removable = 0; gboolean remove = FALSE; g_object_get ( group, "installable", &installable, "removable", &removable, NULL); remove = removable > 0; try_transact (self, NULL, group, remove, FALSE, NULL); } else { bz_window_show_group (self, group); } } static void full_view_install_cb (BzWindow *self, GtkWidget *source, BzFullView *view) { try_transact (self, NULL, bz_full_view_get_entry_group (view), FALSE, TRUE, source); } static void full_view_remove_cb (BzWindow *self, GtkWidget *source, BzFullView *view) { try_transact (self, NULL, bz_full_view_get_entry_group (view), TRUE, FALSE, source); } static void install_addon_cb (BzWindow *self, BzEntry *entry, BzFullView *view) { try_transact (self, entry, NULL, FALSE, TRUE, NULL); } static void remove_addon_cb (BzWindow *self, BzEntry *entry, BzFullView *view) { try_transact (self, entry, NULL, TRUE, TRUE, NULL); } static void install_entry_cb (BzWindow *self, BzEntry *entry, BzFullView *view) { try_transact (self, entry, NULL, FALSE, FALSE, NULL); } static void remove_installed_cb (BzWindow *self, BzEntry *entry, BzFullView *view) { try_transact (self, entry, NULL, TRUE, FALSE, NULL); } static void update_cb (BzWindow *self, GListModel *entries, BzLibraryPage *library_page) { g_autoptr (BzTransaction) transaction = NULL; guint n_updates = 0; g_autofree BzEntry **updates_buf = NULL; GListModel *available_updates = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (G_IS_LIST_MODEL (entries)); g_return_if_fail (BZ_IS_LIBRARY_PAGE (library_page)); n_updates = g_list_model_get_n_items (entries); if (n_updates == 0) return; updates_buf = g_malloc_n (n_updates, sizeof (*updates_buf)); for (guint i = 0; i < n_updates; i++) updates_buf[i] = g_list_model_get_item (entries, i); transaction = bz_transaction_new_full ( NULL, 0, updates_buf, n_updates, NULL, 0); dex_future_disown (bz_transaction_manager_add ( bz_state_info_get_transaction_manager (self->state), transaction)); available_updates = bz_state_info_get_available_updates (self->state); if (G_IS_LIST_STORE (available_updates)) { GListStore *store = G_LIST_STORE (available_updates); guint n_available = g_list_model_get_n_items (available_updates); for (guint i = n_available; i > 0; i--) { guint current_size = 0; guint idx = 0; g_autoptr (BzEntry) available_entry = NULL; const char *available_id = NULL; idx = i - 1; current_size = g_list_model_get_n_items (available_updates); if (idx >= current_size) continue; available_entry = g_list_model_get_item (available_updates, idx); available_id = bz_entry_get_id (available_entry); for (guint j = 0; j < n_updates; j++) { if (g_strcmp0 (available_id, bz_entry_get_id (updates_buf[j])) == 0) { g_list_store_remove (store, idx); break; } } } } g_object_notify (G_OBJECT (self->state), "available-updates"); for (guint i = 0; i < n_updates; i++) g_object_unref (updates_buf[i]); } static void bulk_install_cb (BzWindow *self, GListModel *groups, gpointer source) { bz_window_bulk_install (self, groups); } static void library_page_show_cb (BzWindow *self, BzEntry *entry, BzFullView *view) { g_autoptr (BzEntryGroup) group = NULL; group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (bz_entry_get_id (entry))); if (group != NULL) bz_window_show_group (self, group); } void bz_window_show_app_id (BzWindow *self, const char *app_id) { g_autoptr (BzEntryGroup) group = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (app_id != NULL); group = bz_application_map_factory_convert_one ( bz_state_info_get_application_factory (self->state), gtk_string_object_new (app_id)); if (group != NULL) bz_window_show_group (self, group); } static void page_toggled_cb (BzWindow *self, GParamSpec *pspec, AdwToggleGroup *toggles) { set_page (self); } static void browse_flathub_cb (BzWindow *self, BzCuratedView *widget) { adw_view_stack_set_visible_child_name (self->main_view_stack, "flathub"); } static void open_search_cb (BzWindow *self, BzSearchWidget *widget) { adw_view_stack_set_visible_child_name (self->main_view_stack, "search"); } static void breakpoint_apply_cb (BzWindow *self, AdwBreakpoint *breakpoint) { self->breakpoint_applied = TRUE; gtk_widget_add_css_class (GTK_WIDGET (self), "narrow"); } static void breakpoint_unapply_cb (BzWindow *self, AdwBreakpoint *breakpoint) { self->breakpoint_applied = FALSE; gtk_widget_remove_css_class (GTK_WIDGET (self), "narrow"); } static void sync_cb (BzWindow *self, GtkButton *button) { g_action_group_activate_action ( G_ACTION_GROUP (g_application_get_default ()), "sync-remotes", NULL); } static void transactions_clear_cb (BzWindow *self, GtkButton *button) { bz_transaction_manager_clear_finished ( bz_state_info_get_transaction_manager (self->state)); } static void action_escape (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); GListModel *stack = NULL; guint n_pages = 0; stack = adw_navigation_view_get_navigation_stack (self->navigation_view); n_pages = g_list_model_get_n_items (stack); adw_navigation_view_pop (self->navigation_view); if (n_pages <= 2) set_page (self); } static char * format_progress (gpointer object, double value) { return g_strdup_printf ("%.0f%%", 100.0 * value); } static void action_user_data (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); AdwNavigationPage *user_data_page = NULL; user_data_page = ADW_NAVIGATION_PAGE (bz_user_data_page_new (self->state)); adw_navigation_view_push (self->navigation_view, user_data_page); } static void action_open_library (GtkWidget *widget, const char *action_name, GVariant *parameter) { BzWindow *self = BZ_WINDOW (widget); adw_navigation_view_pop_to_tag (self->navigation_view, "main"); adw_view_stack_set_visible_child_name (self->main_view_stack, "installed"); bz_library_page_reset_search (self->library_page); } static void debug_id_inspect_cb (BzWindow *self, GtkButton *button) { BzEntryGroup *group = NULL; g_autofree char *unique_id = NULL; g_autoptr (GtkStringObject) string = NULL; g_autoptr (BzResult) result = NULL; group = bz_full_view_get_entry_group (self->full_view); if (group == NULL) return; unique_id = bz_entry_group_dup_ui_entry_id (group); result = bz_application_map_factory_convert_one ( bz_state_info_get_entry_factory (self->state), gtk_string_object_new (unique_id)); if (result != NULL) { BzEntryInspector *inspector = NULL; inspector = bz_entry_inspector_new (); bz_entry_inspector_set_result (inspector, result); gtk_window_present (GTK_WINDOW (inspector)); } } static void bz_window_class_init (BzWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_window_dispose; object_class->get_property = bz_window_get_property; object_class->set_property = bz_window_set_property; props[PROP_STATE] = g_param_spec_object ( "state", NULL, NULL, BZ_TYPE_STATE_INFO, G_PARAM_READABLE); g_object_class_install_properties (object_class, LAST_PROP, props); g_type_ensure (BZ_TYPE_COMET_OVERLAY); g_type_ensure (BZ_TYPE_POPUP_OVERLAY); g_type_ensure (BZ_TYPE_SEARCH_WIDGET); g_type_ensure (BZ_TYPE_GLOBAL_PROGRESS); g_type_ensure (BZ_TYPE_PROGRESS_BAR); g_type_ensure (BZ_TYPE_CURATED_VIEW); g_type_ensure (BZ_TYPE_FULL_VIEW); g_type_ensure (BZ_TYPE_LIBRARY_PAGE); g_type_ensure (BZ_TYPE_FLATHUB_PAGE); // g_type_ensure (BZ_TYPE_VIEW_SWITCHER); gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/Bazaar/bz-window.ui"); bz_widget_class_bind_all_util_callbacks (widget_class); gtk_widget_class_bind_template_child (widget_class, BzWindow, comet_overlay); gtk_widget_class_bind_template_child (widget_class, BzWindow, popup_overlay); gtk_widget_class_bind_template_child (widget_class, BzWindow, navigation_view); gtk_widget_class_bind_template_child (widget_class, BzWindow, full_view); gtk_widget_class_bind_template_child (widget_class, BzWindow, toasts); gtk_widget_class_bind_template_child (widget_class, BzWindow, search_widget); gtk_widget_class_bind_template_child (widget_class, BzWindow, library_page); gtk_widget_class_bind_template_child (widget_class, BzWindow, main_view_stack); gtk_widget_class_bind_template_child (widget_class, BzWindow, main_stack); gtk_widget_class_bind_template_child (widget_class, BzWindow, debug_id_label); gtk_widget_class_bind_template_callback (widget_class, list_length); gtk_widget_class_bind_template_callback (widget_class, browser_group_selected_cb); gtk_widget_class_bind_template_callback (widget_class, search_widget_select_cb); gtk_widget_class_bind_template_callback (widget_class, full_view_install_cb); gtk_widget_class_bind_template_callback (widget_class, full_view_remove_cb); gtk_widget_class_bind_template_callback (widget_class, install_addon_cb); gtk_widget_class_bind_template_callback (widget_class, remove_addon_cb); gtk_widget_class_bind_template_callback (widget_class, remove_installed_cb); gtk_widget_class_bind_template_callback (widget_class, update_cb); gtk_widget_class_bind_template_callback (widget_class, library_page_show_cb); gtk_widget_class_bind_template_callback (widget_class, page_toggled_cb); gtk_widget_class_bind_template_callback (widget_class, breakpoint_apply_cb); gtk_widget_class_bind_template_callback (widget_class, breakpoint_unapply_cb); gtk_widget_class_bind_template_callback (widget_class, sync_cb); gtk_widget_class_bind_template_callback (widget_class, transactions_clear_cb); gtk_widget_class_bind_template_callback (widget_class, browse_flathub_cb); gtk_widget_class_bind_template_callback (widget_class, open_search_cb); gtk_widget_class_bind_template_callback (widget_class, format_progress); gtk_widget_class_bind_template_callback (widget_class, debug_id_inspect_cb); gtk_widget_class_install_action (widget_class, "escape", NULL, action_escape); gtk_widget_class_install_action (widget_class, "window.user-data", NULL, action_user_data); gtk_widget_class_install_action (widget_class, "window.open-library", NULL, action_open_library); gtk_widget_class_add_binding_action (widget_class, GDK_KEY_d, GDK_CONTROL_MASK, "window.open-library", NULL); } static gboolean key_pressed (BzWindow *self, guint keyval, guint keycode, GdkModifierType state, GtkEventControllerKey *controller) { gunichar unichar = 0; char buf[32] = { 0 }; const char *visible_child_name = NULL; /* Ignore if this is a modifier-shortcut of some sort */ if (state & ~(GDK_NO_MODIFIER_MASK | GDK_SHIFT_MASK)) return FALSE; unichar = gdk_keyval_to_unicode (keyval); if (unichar == 0 || !g_unichar_isgraph (unichar)) return FALSE; g_unichar_to_utf8 (unichar, buf); visible_child_name = adw_view_stack_get_visible_child_name (self->main_view_stack); if (g_strcmp0 (visible_child_name, "installed") == 0) return bz_library_page_ensure_active (self->library_page, buf); else { adw_view_stack_set_visible_child_name (self->main_view_stack, "search"); return bz_search_widget_ensure_active (self->search_widget, buf); } } static void bz_window_init (BzWindow *self) { gtk_widget_init_template (GTK_WIDGET (self)); #ifdef DEVELOPMENT_BUILD gtk_widget_add_css_class (GTK_WIDGET (self), "devel"); #endif adw_view_stack_set_visible_child_name (self->main_view_stack, "flathub"); self->key_controller = gtk_event_controller_key_new (); g_signal_connect_swapped (self->key_controller, "key-pressed", G_CALLBACK (key_pressed), self); gtk_widget_add_controller (GTK_WIDGET (self), self->key_controller); } static void app_busy_changed (BzWindow *self, GParamSpec *pspec, BzStateInfo *info) { bz_search_widget_refresh (self->search_widget); set_page (self); } static void has_inputs_changed (BzWindow *self, GParamSpec *pspec, BzContentProvider *provider) { if (!bz_content_provider_get_has_inputs (provider)) adw_view_stack_set_visible_child_name (self->main_view_stack, "flathub"); } static DexFuture * transact_fiber (TransactData *data) { g_autoptr (BzWindow) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (BzTransactionDialogResult) dialog_result = NULL; g_autoptr (DexFuture) transact_future = NULL; g_autofree char *id_dup = NULL; bz_weak_get_or_return_reject (self, data->self); // Get ID early before any async operations if (data->group != NULL) id_dup = g_strdup (bz_entry_group_get_id (data->group)); else id_dup = g_strdup (bz_entry_get_id (data->entry)); /* Prevent Bazaar from being removed by itself */ if (data->remove) { const char *bazaar_id = NULL; bazaar_id = g_application_get_application_id (g_application_get_default ()); if (g_strcmp0 (id_dup, bazaar_id) == 0) { bz_show_error_for_widget (GTK_WIDGET (self), _ ("You can't remove Bazaar from Bazaar!")); return dex_future_new_false (); } } // Show the dialog dialog_result = dex_await_object ( bz_transaction_dialog_show ( GTK_WIDGET (self), data->entry, data->group, data->remove, data->auto_confirm), &local_error); if (dialog_result == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (!bz_transaction_dialog_result_get_confirmed (dialog_result)) return dex_future_new_false (); // Perform the transaction transact_future = transact ( self, bz_transaction_dialog_result_get_selected_entry (dialog_result), data->remove, data->source); if (!dex_await (g_steal_pointer (&transact_future), &local_error)) return dex_future_new_for_error (g_steal_pointer (&local_error)); // Handle user data deletion if (bz_transaction_dialog_result_get_delete_user_data (dialog_result)) { if (data->group != NULL) bz_entry_group_reap_user_data (data->group); else dex_future_disown (bz_reap_user_data_dex (id_dup)); } return dex_future_new_true (); } BzWindow * bz_window_new (BzStateInfo *state) { BzWindow *window = NULL; g_return_val_if_fail (BZ_IS_STATE_INFO (state), NULL); window = g_object_new (BZ_TYPE_WINDOW, NULL); window->state = g_object_ref (state); g_signal_connect_object (state, "notify::busy", G_CALLBACK (app_busy_changed), window, G_CONNECT_SWAPPED); /* these seem unsafe but BzApplication never * changes the objects we are connecting to */ g_signal_connect_object (bz_state_info_get_curated_provider (state), "notify::has-inputs", G_CALLBACK (has_inputs_changed), window, G_CONNECT_SWAPPED); g_object_notify_by_pspec (G_OBJECT (window), props[PROP_STATE]); set_page (window); return window; } void bz_window_search (BzWindow *self, const char *text) { g_return_if_fail (BZ_IS_WINDOW (self)); search (self, text); } void bz_window_show_entry (BzWindow *self, BzEntry *entry) { g_autoptr (BzEntryGroup) group = NULL; AdwNavigationPage *visible_page = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (BZ_IS_ENTRY (entry)); group = bz_entry_group_new_for_single_entry (entry); bz_full_view_set_entry_group (self->full_view, group); visible_page = adw_navigation_view_get_visible_page (self->navigation_view); if (visible_page != adw_navigation_view_find_page (self->navigation_view, "view")) adw_navigation_view_push_by_tag (self->navigation_view, "view"); } void bz_window_show_group (BzWindow *self, BzEntryGroup *group) { AdwNavigationPage *visible_page = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (BZ_IS_ENTRY_GROUP (group)); bz_full_view_set_entry_group (self->full_view, group); visible_page = adw_navigation_view_get_visible_page (self->navigation_view); if (visible_page != adw_navigation_view_find_page (self->navigation_view, "view")) adw_navigation_view_push_by_tag (self->navigation_view, "view"); } void bz_window_add_toast (BzWindow *self, AdwToast *toast) { g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (ADW_IS_TOAST (toast)); adw_toast_overlay_add_toast (self->toasts, toast); } void bz_window_push_page (BzWindow *self, AdwNavigationPage *page) { g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (ADW_IS_NAVIGATION_PAGE (page)); if (BZ_IS_FAVORITES_PAGE (page)) { g_signal_connect_swapped (page, "install", G_CALLBACK (install_entry_cb), self); g_signal_connect_swapped (page, "remove", G_CALLBACK (remove_installed_cb), self); g_signal_connect_swapped (page, "show-entry", G_CALLBACK (library_page_show_cb), self); g_signal_connect_swapped (page, "bulk-install", G_CALLBACK (bulk_install_cb), self); } adw_navigation_view_push (self->navigation_view, page); } void bz_window_bulk_install (BzWindow *self, GListModel *groups) { g_autoptr (BulkInstallData) data = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (G_IS_LIST_MODEL (groups)); data = bulk_install_data_new (); data->self = bz_track_weak (self); data->groups = g_object_ref (groups); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) bulk_install_fiber, bulk_install_data_ref (data), bulk_install_data_unref)); } BzStateInfo * bz_window_get_state_info (BzWindow *self) { g_return_val_if_fail (BZ_IS_WINDOW (self), NULL); return self->state; } static DexFuture * transact (BzWindow *self, BzEntry *entry, gboolean remove, GtkWidget *source) { g_autoptr (BzTransaction) transaction = NULL; if (remove) transaction = bz_transaction_new_full ( NULL, 0, NULL, 0, &entry, 1); else transaction = bz_transaction_new_full ( &entry, 1, NULL, 0, NULL, 0); return bz_transaction_manager_add ( bz_state_info_get_transaction_manager (self->state), transaction); } static void try_transact (BzWindow *self, BzEntry *entry, BzEntryGroup *group, gboolean remove, gboolean auto_confirm, GtkWidget *source) { g_autoptr (TransactData) data = NULL; g_return_if_fail (entry != NULL || group != NULL); if (bz_state_info_get_busy (self->state)) { adw_toast_overlay_add_toast ( self->toasts, adw_toast_new_format (_ ("Can't do that right now!"))); return; } data = transact_data_new (); data->self = bz_track_weak (self); data->entry = bz_object_maybe_ref (entry); data->group = bz_object_maybe_ref (group); data->remove = remove; data->auto_confirm = auto_confirm; data->source = bz_object_maybe_ref (source); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) transact_fiber, transact_data_ref (data), transact_data_unref)); } static void bulk_install (BzWindow *self, BzEntry **installs, guint n_installs) { g_autoptr (BzTransaction) transaction = NULL; g_return_if_fail (BZ_IS_WINDOW (self)); g_return_if_fail (installs != NULL); g_return_if_fail (n_installs > 0); if (bz_state_info_get_busy (self->state)) { adw_toast_overlay_add_toast ( self->toasts, adw_toast_new_format (_ ("Can't do that right now!"))); return; } transaction = bz_transaction_new_full ( installs, n_installs, NULL, 0, NULL, 0); dex_future_disown (bz_transaction_manager_add ( bz_state_info_get_transaction_manager (self->state), transaction)); } static DexFuture * bulk_install_fiber (BulkInstallData *data) { g_autoptr (BzWindow) self = NULL; g_autoptr (GError) local_error = NULL; g_autoptr (BzBulkInstallDialogResult) result = NULL; GListModel *entries = NULL; guint n_installs = 0; g_autofree BzEntry **installs_buf = NULL; bz_weak_get_or_return_reject (self, data->self); result = dex_await_object ( bz_bulk_install_dialog_show (GTK_WIDGET (self), data->groups), &local_error); if (result == NULL) return dex_future_new_for_error (g_steal_pointer (&local_error)); if (!bz_bulk_install_dialog_result_get_confirmed (result)) return dex_future_new_false (); entries = bz_bulk_install_dialog_result_get_entries (result); n_installs = g_list_model_get_n_items (entries); if (n_installs == 0) return dex_future_new_false (); installs_buf = g_malloc_n (n_installs, sizeof (*installs_buf)); for (guint i = 0; i < n_installs; i++) installs_buf[i] = g_list_model_get_item (entries, i); bulk_install (self, installs_buf, n_installs); for (guint i = 0; i < n_installs; i++) g_object_unref (installs_buf[i]); return dex_future_new_true (); } static void search (BzWindow *self, const char *initial) { if (initial != NULL && *initial != '\0') { bz_search_widget_set_text (self->search_widget, initial); } adw_view_stack_set_visible_child_name (self->main_view_stack, "search"); adw_navigation_view_pop_to_tag (self->navigation_view, "main"); gtk_widget_grab_focus (GTK_WIDGET (self->search_widget)); } static void set_page (BzWindow *self) { const char *selected_navigation_page_name = NULL; if (self->state == NULL) return; if (bz_state_info_get_busy (self->state)) { gtk_stack_set_visible_child_name (self->main_stack, "loading"); adw_navigation_view_pop_to_tag (self->navigation_view, "main"); } else { gtk_stack_set_visible_child_name (self->main_stack, "main"); } selected_navigation_page_name = adw_navigation_view_get_visible_page_tag (self->navigation_view); if (g_strcmp0 (selected_navigation_page_name, "view") != 0) bz_full_view_set_entry_group (self->full_view, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-window.h000066400000000000000000000033241514314607700177440ustar00rootroot00000000000000/* bz-window.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "bz-state-info.h" G_BEGIN_DECLS #define BZ_TYPE_WINDOW (bz_window_get_type ()) G_DECLARE_FINAL_TYPE (BzWindow, bz_window, BZ, WINDOW, AdwApplicationWindow) BzWindow * bz_window_new (BzStateInfo *state); void bz_window_search (BzWindow *self, const char *text); void bz_window_push_update_dialog (BzWindow *self); void bz_window_show_entry (BzWindow *self, BzEntry *entry); void bz_window_show_group (BzWindow *self, BzEntryGroup *group); void bz_window_show_app_id (BzWindow *self, const char *app_id); void bz_window_push_page (BzWindow *self, AdwNavigationPage *page); void bz_window_add_toast (BzWindow *self, AdwToast *toast); void bz_window_bulk_install (BzWindow *self, GListModel *groups); BzStateInfo * bz_window_get_state_info (BzWindow *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-world-map-parser.c000066400000000000000000000125761514314607700216350ustar00rootroot00000000000000/* bz-world-map-parser.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "bz-world-map-parser.h" #include "bz-country.h" struct _BzWorldMapParser { GObject parent_instance; JsonParser *parser; GListStore *countries; }; G_DEFINE_FINAL_TYPE (BzWorldMapParser, bz_world_map_parser, G_TYPE_OBJECT) static void bz_world_map_parser_dispose (GObject *object) { BzWorldMapParser *self = BZ_WORLD_MAP_PARSER (object); g_clear_object (&self->parser); g_clear_object (&self->countries); G_OBJECT_CLASS (bz_world_map_parser_parent_class)->dispose (object); } static void bz_world_map_parser_class_init (BzWorldMapParserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_world_map_parser_dispose; } static void bz_world_map_parser_init (BzWorldMapParser *self) { self->parser = json_parser_new (); self->countries = g_list_store_new (BZ_TYPE_COUNTRY); } BzWorldMapParser * bz_world_map_parser_new (void) { return g_object_new (BZ_TYPE_WORLD_MAP_PARSER, NULL); } static const char * get_translated_name (JsonObject *feature_obj, const char *fallback_name) { const char * const *language_names = NULL; JsonObject *translations = NULL; const char *translated_name = NULL; if (!json_object_has_member (feature_obj, "translations")) return fallback_name; translations = json_object_get_object_member (feature_obj, "translations"); language_names = g_get_language_names (); for (guint i = 0; language_names[i] != NULL; i++) { if (json_object_has_member (translations, language_names[i])) { translated_name = json_object_get_string_member (translations, language_names[i]); if (translated_name != NULL) return translated_name; } } return fallback_name; } gboolean bz_world_map_parser_load_from_resource (BzWorldMapParser *self, const char *resource_path, GError **error) { g_autoptr (GBytes) bytes = NULL; JsonNode *root = NULL; JsonObject *root_object = NULL; JsonArray *features = NULL; const char *json_data = NULL; gsize size = 0; guint length = 0; g_return_val_if_fail (BZ_IS_WORLD_MAP_PARSER (self), FALSE); g_return_val_if_fail (resource_path != NULL, FALSE); bytes = g_resources_lookup_data (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); if (bytes == NULL) return FALSE; json_data = g_bytes_get_data (bytes, &size); if (!json_parser_load_from_data (self->parser, json_data, size, error)) return FALSE; root = json_parser_get_root (self->parser); if (!JSON_NODE_HOLDS_OBJECT (root)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Root node is not an object"); return FALSE; } root_object = json_node_get_object (root); if (!json_object_has_member (root_object, "features")) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Missing features member"); return FALSE; } features = json_object_get_array_member (root_object, "features"); length = json_array_get_length (features); g_list_store_remove_all (self->countries); for (guint i = 0; i < length; i++) { JsonObject *feature_obj = NULL; const char *name = NULL; const char *iso_code = NULL; const char *display_name = NULL; JsonArray *coordinates = NULL; g_autoptr (BzCountry) country = NULL; feature_obj = json_array_get_object_element (features, i); if (json_object_has_member (feature_obj, "N")) name = json_object_get_string_member (feature_obj, "N"); if (json_object_has_member (feature_obj, "I")) iso_code = json_object_get_string_member (feature_obj, "I"); if (json_object_has_member (feature_obj, "C")) coordinates = json_object_get_array_member (feature_obj, "C"); display_name = get_translated_name (feature_obj, name); country = bz_country_new (); bz_country_set_name (country, display_name); bz_country_set_iso_code (country, iso_code); bz_country_set_coordinates (country, coordinates); g_list_store_append (self->countries, country); } return TRUE; } GListModel * bz_world_map_parser_get_countries (BzWorldMapParser *self) { g_return_val_if_fail (BZ_IS_WORLD_MAP_PARSER (self), NULL); return G_LIST_MODEL (self->countries); } kolunmi-bazaar-7b9c8e1/src/bz-world-map-parser.h000066400000000000000000000025751514314607700216400ustar00rootroot00000000000000/* bz-world-map-parser.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_WORLD_MAP_PARSER (bz_world_map_parser_get_type ()) G_DECLARE_FINAL_TYPE (BzWorldMapParser, bz_world_map_parser, BZ, WORLD_MAP_PARSER, GObject) BzWorldMapParser *bz_world_map_parser_new (void); gboolean bz_world_map_parser_load_from_resource (BzWorldMapParser *self, const char *resource_path, GError **error); GListModel *bz_world_map_parser_get_countries (BzWorldMapParser *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-world-map.c000066400000000000000000000536461514314607700203460ustar00rootroot00000000000000/* bz-world-map.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include "bz-country-data-point.h" #include "bz-country.h" #include "bz-world-map-parser.h" #include "bz-world-map.h" #define CARD_EDGE_THRESHOLD 160 #define OPACITY_MULTIPLIER 2 struct _BzWorldMap { GtkWidget parent_instance; BzWorldMapParser *parser; GListModel *countries; GListModel *model; double min_lon; double max_lon; double min_lat; double max_lat; GskPath **country_paths; guint *path_to_country; guint n_paths; gboolean cache_valid; GtkEventController *motion; GtkGesture *gesture; double offset_x; double offset_y; double scale; int hovered_country; double motion_x; double motion_y; guint max_downloads; GtkWidget *tooltip_box; GtkWidget *tooltip_label1; GtkWidget *tooltip_prefix_label; GtkWidget *tooltip_label2; }; G_DEFINE_FINAL_TYPE (BzWorldMap, bz_world_map, GTK_TYPE_WIDGET) enum { PROP_0, PROP_MODEL, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static guint get_downloads_for_country (BzWorldMap *self, const char *iso_code) { guint n_items = 0; if (self->model == NULL) return 0; n_items = g_list_model_get_n_items (self->model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzCountryDataPoint) point = g_list_model_get_item (self->model, i); const char *country_code = bz_country_data_point_get_country_code (point); if (g_strcmp0 (country_code, iso_code) == 0) return bz_country_data_point_get_downloads (point); } return 0; } static void calculate_max_downloads (BzWorldMap *self) { guint n_items = 0; self->max_downloads = 0; if (self->model == NULL) return; n_items = g_list_model_get_n_items (self->model); for (guint i = 0; i < n_items; i++) { g_autoptr (BzCountryDataPoint) point = g_list_model_get_item (self->model, i); guint downloads = bz_country_data_point_get_downloads (point); if (downloads > self->max_downloads) self->max_downloads = downloads; } } static void calculate_bounds (BzWorldMap *self) { guint n_items = 0; if (self->countries == NULL) return; n_items = g_list_model_get_n_items (self->countries); self->min_lon = 180.0; self->max_lon = -180.0; self->min_lat = 90.0; self->max_lat = -90.0; for (guint i = 0; i < n_items; i++) { BzCountry *country = g_list_model_get_item (self->countries, i); JsonArray *coordinates = bz_country_get_coordinates (country); if (coordinates != NULL) { for (guint j = 0; j < json_array_get_length (coordinates); j++) { JsonArray *polygon_array = json_array_get_array_element (coordinates, j); for (guint k = 0; k < json_array_get_length (polygon_array); k++) { JsonArray *ring_array = json_array_get_array_element (polygon_array, k); for (guint l = 0; l < json_array_get_length (ring_array); l++) { JsonArray *point_array = json_array_get_array_element (ring_array, l); double lon = json_array_get_double_element (point_array, 0); double lat = json_array_get_double_element (point_array, 1); if (lon < self->min_lon) self->min_lon = lon; if (lon > self->max_lon) self->max_lon = lon; if (lat < self->min_lat) self->min_lat = lat; if (lat > self->max_lat) self->max_lat = lat; } } } } g_object_unref (country); } } static void project_point (BzWorldMap *self, double lon, double lat, double width, double height, double *x, double *y) { double lon_range = self->max_lon - self->min_lon; double lat_range = self->max_lat - self->min_lat; *x = ((lon - self->min_lon) / lon_range) * width; *y = height - ((lat - self->min_lat) / lat_range) * height; } static void calculate_transform (BzWorldMap *self, double widget_width, double widget_height, double map_width, double map_height) { double scale_x = widget_width / map_width; double scale_y = widget_height / map_height; self->scale = MIN (scale_x, scale_y); self->offset_x = (widget_width - map_width * self->scale) / 2.0; self->offset_y = (widget_height - map_height * self->scale) / 2.0; } static void build_paths (BzWorldMap *self, double width, double height) { guint n_items = 0; guint path_index = 0; if (self->countries == NULL) return; if (self->country_paths != NULL) { for (guint i = 0; i < self->n_paths; i++) g_clear_pointer (&self->country_paths[i], gsk_path_unref); g_free (self->country_paths); self->country_paths = NULL; } if (self->path_to_country != NULL) { g_free (self->path_to_country); self->path_to_country = NULL; } n_items = g_list_model_get_n_items (self->countries); self->n_paths = 0; for (guint i = 0; i < n_items; i++) { BzCountry *country = g_list_model_get_item (self->countries, i); JsonArray *coordinates = bz_country_get_coordinates (country); if (coordinates != NULL) { for (guint j = 0; j < json_array_get_length (coordinates); j++) { JsonArray *polygon_array = json_array_get_array_element (coordinates, j); self->n_paths += json_array_get_length (polygon_array); } } g_object_unref (country); } self->country_paths = g_new0 (GskPath *, self->n_paths); self->path_to_country = g_new0 (guint, self->n_paths); for (guint i = 0; i < n_items; i++) { BzCountry *country = g_list_model_get_item (self->countries, i); JsonArray *coordinates = bz_country_get_coordinates (country); if (coordinates != NULL) { for (guint j = 0; j < json_array_get_length (coordinates); j++) { JsonArray *polygon_array = json_array_get_array_element (coordinates, j); for (guint k = 0; k < json_array_get_length (polygon_array); k++) { JsonArray *ring_array = json_array_get_array_element (polygon_array, k); g_autoptr (GskPathBuilder) builder = gsk_path_builder_new (); gboolean first = TRUE; for (guint l = 0; l < json_array_get_length (ring_array); l++) { JsonArray *point_array = json_array_get_array_element (ring_array, l); double lon = json_array_get_double_element (point_array, 0); double lat = json_array_get_double_element (point_array, 1); double x = 0.0; double y = 0.0; project_point (self, lon, lat, width, height, &x, &y); if (first) { gsk_path_builder_move_to (builder, x, y); first = FALSE; } else { gsk_path_builder_line_to (builder, x, y); } } gsk_path_builder_close (builder); self->country_paths[path_index] = gsk_path_builder_to_path (builder); self->path_to_country[path_index] = i; path_index++; } } } g_object_unref (country); } self->cache_valid = TRUE; } static void invalidate_cache (BzWorldMap *self) { self->cache_valid = FALSE; gtk_widget_queue_draw (GTK_WIDGET (self)); } static void on_style_changed (AdwStyleManager *style_manager, GParamSpec *pspec, BzWorldMap *self) { invalidate_cache (self); } static void update_hovered_country (BzWorldMap *self, double x, double y) { double map_x; double map_y; map_x = (x - self->offset_x) / self->scale; map_y = (y - self->offset_y) / self->scale; self->motion_x = x; self->motion_y = y; self->hovered_country = -1; for (guint i = 0; i < self->n_paths; i++) { if (gsk_path_in_fill (self->country_paths[i], &GRAPHENE_POINT_INIT (map_x, map_y), GSK_FILL_RULE_WINDING)) { self->hovered_country = self->path_to_country[i]; break; } } } static void motion_event (BzWorldMap *self, gdouble x, gdouble y, GtkEventControllerMotion *controller) { int old_hovered; old_hovered = self->hovered_country; update_hovered_country (self, x, y); if (old_hovered != self->hovered_country || self->hovered_country >= 0) gtk_widget_queue_draw (GTK_WIDGET (self)); } static void motion_leave (BzWorldMap *self, GtkEventControllerMotion *controller) { if (self->hovered_country != -1) { self->hovered_country = -1; self->motion_x = -1.0; self->motion_y = -1.0; gtk_widget_queue_draw (GTK_WIDGET (self)); } } static void gesture_begin (BzWorldMap *self, double start_x, double start_y, GtkGestureDrag *gesture) { update_hovered_country (self, start_x, start_y); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void gesture_update (BzWorldMap *self, double offset_x, double offset_y, GtkGestureDrag *gesture) { double start_x; double start_y; gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y); update_hovered_country (self, start_x + offset_x, start_y + offset_y); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void gesture_end (BzWorldMap *self, double offset_x, double offset_y, GtkGestureDrag *gesture) { gtk_widget_queue_draw (GTK_WIDGET (self)); } static void bz_world_map_dispose (GObject *object) { BzWorldMap *self = BZ_WORLD_MAP (object); g_signal_handlers_disconnect_by_func (adw_style_manager_get_default (), on_style_changed, self); if (self->country_paths != NULL) { for (guint i = 0; i < self->n_paths; i++) g_clear_pointer (&self->country_paths[i], gsk_path_unref); g_free (self->country_paths); self->country_paths = NULL; } if (self->path_to_country != NULL) { g_free (self->path_to_country); self->path_to_country = NULL; } if (self->tooltip_box != NULL) gtk_widget_unparent (self->tooltip_box); g_clear_object (&self->countries); g_clear_object (&self->model); G_OBJECT_CLASS (bz_world_map_parent_class)->dispose (object); } static void bz_world_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzWorldMap *self = BZ_WORLD_MAP (object); switch (prop_id) { case PROP_MODEL: g_value_set_object (value, self->model); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_world_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzWorldMap *self = BZ_WORLD_MAP (object); switch (prop_id) { case PROP_MODEL: g_clear_object (&self->model); self->model = g_value_dup_object (value); calculate_max_downloads (self); gtk_widget_queue_draw (GTK_WIDGET (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_world_map_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzWorldMap *self = BZ_WORLD_MAP (widget); invalidate_cache (self); } static void bz_world_map_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzWorldMap *self = BZ_WORLD_MAP (widget); double widget_width = gtk_widget_get_width (widget); double widget_height = gtk_widget_get_height (widget); AdwStyleManager *style_manager = adw_style_manager_get_default (); g_autoptr (GdkRGBA) accent_color = adw_style_manager_get_accent_color_rgba (style_manager); GdkRGBA stroke_color = { 0 }; g_autoptr (GskStroke) stroke = gsk_stroke_new (0.5); g_autoptr (GskStroke) hover_stroke = gsk_stroke_new (1.5); double map_width = 1000.0; double map_height = 500.0; if (self->countries == NULL) return; gtk_widget_get_color (widget, &stroke_color); stroke_color.alpha = 0.3; if (!self->cache_valid) build_paths (self, map_width, map_height); calculate_transform (self, widget_width, widget_height, map_width, map_height); gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (self->offset_x, self->offset_y)); gtk_snapshot_scale (snapshot, self->scale, self->scale); for (guint i = 0; i < self->n_paths; i++) { guint country_idx = self->path_to_country[i]; g_autoptr (BzCountry) country = g_list_model_get_item (self->countries, country_idx); const char *iso_code = bz_country_get_iso_code (country); guint downloads = get_downloads_for_country (self, iso_code); GdkRGBA fill_color = *accent_color; if (self->max_downloads > 0 && downloads > 0) { double ratio = (double) downloads / (double) self->max_downloads; fill_color.alpha = CLAMP (ratio * OPACITY_MULTIPLIER, 0.1, 1.0); } else { fill_color.alpha = 0.0; } gtk_snapshot_append_fill (snapshot, self->country_paths[i], GSK_FILL_RULE_WINDING, &fill_color); gtk_snapshot_append_stroke (snapshot, self->country_paths[i], stroke, &stroke_color); } gtk_snapshot_restore (snapshot); if (self->hovered_country >= 0) { GdkRGBA hover_color = stroke_color; hover_color.alpha = 1.0; gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (self->offset_x, self->offset_y)); gtk_snapshot_scale (snapshot, self->scale, self->scale); for (guint i = 0; i < self->n_paths; i++) { if (self->path_to_country[i] == (guint) self->hovered_country) { gtk_snapshot_append_stroke (snapshot, self->country_paths[i], hover_stroke, &hover_color); } } gtk_snapshot_restore (snapshot); } if (self->hovered_country >= 0 && self->motion_x >= 0.0 && self->motion_y >= 0.0) { g_autoptr (BzCountry) country = g_list_model_get_item (self->countries, self->hovered_country); const char *iso_code = bz_country_get_iso_code (country); guint download_number = get_downloads_for_country (self, iso_code); const char *country_name = bz_country_get_name (country); g_autofree char *label1_text = g_strdup_printf ("%s", country_name); g_autofree char *label2_text = g_strdup_printf ("%'u", download_number); GtkRequisition natural_size; double card_x = 0.0; double card_y = 0.0; gtk_label_set_markup (GTK_LABEL (self->tooltip_label1), label1_text); gtk_label_set_text (GTK_LABEL (self->tooltip_prefix_label), C_ ("As in, \"100 Downloads\"", "Downloads")); gtk_label_set_text (GTK_LABEL (self->tooltip_label2), label2_text); gtk_widget_get_preferred_size (self->tooltip_box, NULL, &natural_size); gtk_widget_allocate (self->tooltip_box, natural_size.width, natural_size.height, -1, NULL); if (widget_width - self->motion_x < CARD_EDGE_THRESHOLD) card_x = self->motion_x - natural_size.width - 10.0; else card_x = self->motion_x + 10.0; card_y = self->motion_y + 10.0; gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (card_x, card_y)); gtk_widget_snapshot_child (widget, self->tooltip_box, snapshot); gtk_snapshot_restore (snapshot); } } static void bz_world_map_class_init (BzWorldMapClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_world_map_dispose; object_class->get_property = bz_world_map_get_property; object_class->set_property = bz_world_map_set_property; props[PROP_MODEL] = g_param_spec_object ( "model", NULL, NULL, G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, LAST_PROP, props); widget_class->snapshot = bz_world_map_snapshot; widget_class->size_allocate = bz_world_map_size_allocate; } static void bz_world_map_init (BzWorldMap *self) { AdwStyleManager *style_manager = adw_style_manager_get_default (); g_autoptr (GError) error = NULL; GtkWidget *inner_box = NULL; GtkWidget *label2_box = NULL; self->parser = bz_world_map_parser_new (); self->hovered_country = -1; self->motion_x = -1.0; self->motion_y = -1.0; self->max_downloads = 0; self->motion = gtk_event_controller_motion_new (); g_signal_connect_swapped (self->motion, "motion", G_CALLBACK (motion_event), self); g_signal_connect_swapped (self->motion, "leave", G_CALLBACK (motion_leave), self); gtk_widget_add_controller (GTK_WIDGET (self), self->motion); self->gesture = gtk_gesture_drag_new (); gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (self->gesture), TRUE); g_signal_connect_swapped (self->gesture, "drag-begin", G_CALLBACK (gesture_begin), self); g_signal_connect_swapped (self->gesture, "drag-update", G_CALLBACK (gesture_update), self); g_signal_connect_swapped (self->gesture, "drag-end", G_CALLBACK (gesture_end), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->gesture)); self->tooltip_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_widget_add_css_class (self->tooltip_box, "floating-tooltip"); gtk_widget_add_css_class (self->tooltip_box, "card"); inner_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); gtk_widget_set_margin_start (inner_box, 12); gtk_widget_set_margin_end (inner_box, 12); gtk_widget_set_margin_top (inner_box, 12); gtk_widget_set_margin_bottom (inner_box, 12); self->tooltip_label1 = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_label1, "heading"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_label1), 0.0); gtk_label_set_use_markup (GTK_LABEL (self->tooltip_label1), TRUE); gtk_box_append (GTK_BOX (inner_box), self->tooltip_label1); label2_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); self->tooltip_label2 = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_label2, "monospace"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_label2), 0.0); gtk_box_append (GTK_BOX (label2_box), self->tooltip_label2); self->tooltip_prefix_label = gtk_label_new (""); gtk_widget_add_css_class (self->tooltip_prefix_label, "body"); gtk_widget_add_css_class (self->tooltip_prefix_label, "dim-label"); gtk_label_set_xalign (GTK_LABEL (self->tooltip_prefix_label), 0.0); gtk_box_append (GTK_BOX (label2_box), self->tooltip_prefix_label); gtk_box_append (GTK_BOX (inner_box), label2_box); gtk_box_append (GTK_BOX (self->tooltip_box), inner_box); gtk_widget_set_parent (self->tooltip_box, GTK_WIDGET (self)); g_signal_connect (style_manager, "notify::dark", G_CALLBACK (on_style_changed), self); g_signal_connect (style_manager, "notify::accent-color", G_CALLBACK (on_style_changed), self); if (bz_world_map_parser_load_from_resource (self->parser, "/io/github/kolunmi/Bazaar/countries.json", &error)) { self->countries = g_object_ref (bz_world_map_parser_get_countries (self->parser)); calculate_bounds (self); g_clear_object (&self->parser); } else { g_warning ("BzWorldMap: Failed to load countries: %s", error->message); g_clear_object (&self->parser); } } GtkWidget * bz_world_map_new (void) { return g_object_new (BZ_TYPE_WORLD_MAP, NULL); } kolunmi-bazaar-7b9c8e1/src/bz-world-map.h000066400000000000000000000021621514314607700203360ustar00rootroot00000000000000/* bz-world-map.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_WORLD_MAP (bz_world_map_get_type ()) G_DECLARE_FINAL_TYPE (BzWorldMap, bz_world_map, BZ, WORLD_MAP, GtkWidget) GtkWidget * bz_world_map_new (void); GListModel * bz_world_map_get_model (BzWorldMap *self); void bz_world_map_set_model (BzWorldMap *self, GListModel *model); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-yaml-parser.c000066400000000000000000001222031514314607700206620ustar00rootroot00000000000000/* bz-yaml-parser.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::YAML" #include "config.h" #include #include #include #include "bz-parser.h" #include "bz-util.h" #include "bz-yaml-parser.h" /* clang-format off */ G_DEFINE_QUARK (bz-yaml-error-quark, bz_yaml_error); /* clang-format on */ static void deinit_schema_node (gpointer data); BZ_DEFINE_DATA ( schema_node, SchemaNode, { int kind; union { struct { char *vtype; } scalar; struct { GType type; GHashTable *type_hints; } object; struct { SchemaNodeData *child; } list; struct { GHashTable *children; } mappings; }; }, deinit_schema_node (self);) struct _BzYamlParser { GObject parent_instance; SchemaNodeData *schema; }; static void parser_iface_init (BzParserInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE ( BzYamlParser, bz_yaml_parser, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (BZ_TYPE_PARSER, parser_iface_init)) enum { KIND_SCALAR, KIND_OBJECT, KIND_LIST, KIND_MAPPINGS, }; static SchemaNodeData * compile_schema (XbNode *node); static gboolean parse (BzYamlParser *self, yaml_parser_t *parser, yaml_event_t *event, gboolean parse_first, gboolean toplevel, SchemaNodeData *schema, GHashTable *output, GHashTable *anchors, GPtrArray *path_stack, GError **error); static GObject * parse_object (BzYamlParser *self, yaml_parser_t *parser, yaml_event_t *event, GType object_gtype, GHashTable *type_hints, GHashTable *anchors, const char *prop_path, GError **error); static char * join_path_stack (GPtrArray *path_stack); static void destroy_gvalue (GValue *value); static GValue * make_gvalue_alloc (GType type); static GValue * copy_gvalue_alloc (GValue *value); static void bz_yaml_parser_dispose (GObject *object) { BzYamlParser *self = BZ_YAML_PARSER (object); g_clear_pointer (&self->schema, schema_node_data_unref); G_OBJECT_CLASS (bz_yaml_parser_parent_class)->dispose (object); } static void bz_yaml_parser_class_init (BzYamlParserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = bz_yaml_parser_dispose; g_type_ensure (GTK_TYPE_STRING_OBJECT); } static void bz_yaml_parser_init (BzYamlParser *self) { } static GHashTable * bz_yaml_parser_real_process_bytes (BzParser *iface_self, GBytes *bytes, GError **error) { BzYamlParser *self = BZ_YAML_PARSER (iface_self); g_autoptr (GError) local_error = NULL; gsize bytes_size = 0; const guchar *bytes_data = NULL; yaml_parser_t parser = { 0 }; yaml_event_t event = { 0 }; g_autoptr (GHashTable) output = NULL; g_autoptr (GHashTable) anchors = NULL; g_autoptr (GPtrArray) path_stack = NULL; gboolean result = FALSE; g_return_val_if_fail (BZ_IS_YAML_PARSER (self), NULL); g_return_val_if_fail (bytes != NULL, NULL); bytes_data = g_bytes_get_data (bytes, &bytes_size); yaml_parser_initialize (&parser); yaml_parser_set_input_string (&parser, bytes_data, bytes_size); output = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_gvalue); anchors = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_gvalue); path_stack = g_ptr_array_new_with_free_func (g_free); result = parse ( self, &parser, &event, TRUE, TRUE, self->schema, output, anchors, path_stack, &local_error); yaml_parser_delete (&parser); if (result) return g_steal_pointer (&output); else { g_propagate_error (error, g_steal_pointer (&local_error)); return NULL; } } static void parser_iface_init (BzParserInterface *iface) { iface->process_bytes = bz_yaml_parser_real_process_bytes; } BzYamlParser * bz_yaml_parser_new_for_resource_schema (const char *path) { g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) bytes = NULL; const char *resource_data = NULL; g_autoptr (XbSilo) silo = NULL; g_autoptr (XbNode) root = NULL; g_autoptr (SchemaNodeData) schema = NULL; g_autoptr (BzYamlParser) parser = NULL; g_return_val_if_fail (path != NULL, NULL); bytes = g_resources_lookup_data ( path, G_RESOURCE_LOOKUP_FLAGS_NONE, &local_error); if (bytes == NULL) g_critical ("Could not load internal resource: %s", local_error->message); g_assert (bytes != NULL); resource_data = g_bytes_get_data (bytes, NULL); silo = xb_silo_new_from_xml (resource_data, &local_error); if (silo == NULL) g_critical ("Could not parse internal xml resource: %s", local_error->message); g_assert (silo != NULL); root = xb_silo_get_root (silo); parser = g_object_new (BZ_TYPE_YAML_PARSER, NULL); parser->schema = compile_schema (root); return g_steal_pointer (&parser); } static SchemaNodeData * compile_schema (XbNode *node) { const char *element = NULL; g_autoptr (SchemaNodeData) schema = NULL; element = xb_node_get_element (node); schema = schema_node_data_new (); #define ERROR_OUT(...) \ G_STMT_START \ { \ g_critical ("Fatal: internal schema: " __VA_ARGS__); \ g_assert (FALSE); \ } \ G_STMT_END if (g_strcmp0 (element, "scalar") == 0) { const char *type = NULL; type = xb_node_get_attr (node, "type"); if (type == NULL) ERROR_OUT ("scalar must have a type"); if (!g_variant_type_is_basic ((const GVariantType *) type)) ERROR_OUT ("invalid variant type for scalar '%s'", type); schema->kind = KIND_SCALAR; schema->scalar.vtype = g_strdup (type); } else if (g_strcmp0 (element, "object") == 0) { const char *class = NULL; GType gtype = G_TYPE_INVALID; g_autoptr (GTypeClass) gtype_class = NULL; XbNode *child = NULL; class = xb_node_get_attr (node, "class"); if (class == NULL) ERROR_OUT ("object must have a class"); gtype = g_type_from_name (class); if (gtype == G_TYPE_INVALID || !g_type_is_a (gtype, G_TYPE_OBJECT)) ERROR_OUT ("'%s' is not a valid object class", class); schema->kind = KIND_OBJECT; schema->object.type = gtype; schema->object.type_hints = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL); gtype_class = g_type_class_ref (gtype); child = xb_node_get_child (node); while (child != NULL) { const char *child_element = NULL; const char *name = NULL; GParamSpec *property = NULL; const char *typehint_name = NULL; GType typehint_gtype = G_TYPE_INVALID; XbNode *next = NULL; child_element = xb_node_get_element (child); if (g_strcmp0 (child_element, "typehint") != 0) ERROR_OUT ("\"typehint\" is the only valid child element of \"object\""); name = xb_node_get_attr (child, "name"); if (name == NULL) ERROR_OUT ("typehint must have a name"); /* TODO: implement recursive checking */ if (strchr (name, '.') == NULL) { property = g_object_class_find_property (G_OBJECT_CLASS (gtype_class), name); if (property == NULL) ERROR_OUT ("typehint property '%s' is invalid", name); } typehint_name = xb_node_get_attr (child, "type"); if (typehint_name == NULL) ERROR_OUT ("typehint must have a type"); typehint_gtype = g_type_from_name (typehint_name); if (typehint_gtype == G_TYPE_INVALID || !g_type_is_a (typehint_gtype, G_TYPE_OBJECT)) ERROR_OUT ("'%s' is not a valid object class", typehint_name); g_hash_table_replace ( schema->object.type_hints, g_strdup (name), GSIZE_TO_POINTER (typehint_gtype)); next = xb_node_get_next (child); g_object_unref (child); child = next; } } else if (g_strcmp0 (element, "list") == 0) { g_autoptr (XbNode) child = NULL; child = xb_node_get_child (node); if (child == NULL) ERROR_OUT ("list must have a child"); schema->kind = KIND_LIST; schema->list.child = compile_schema (child); } else if (g_strcmp0 (element, "mappings") == 0) { XbNode *child = NULL; schema->kind = KIND_MAPPINGS; schema->mappings.children = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, schema_node_data_unref); child = xb_node_get_child (node); while (child != NULL) { const char *child_element = NULL; const char *key = NULL; g_autoptr (XbNode) child_child = NULL; XbNode *next = NULL; child_element = xb_node_get_element (child); if (g_strcmp0 (child_element, "mapping") != 0) ERROR_OUT ("\"mapping\" is the only valid child element of \"mappings\""); key = xb_node_get_attr (child, "key"); if (key == NULL) ERROR_OUT ("mapping must have a key"); child_child = xb_node_get_child (child); if (child == NULL) ERROR_OUT ("mapping must have a child"); g_hash_table_replace ( schema->mappings.children, g_strdup (key), compile_schema (child_child)); next = xb_node_get_next (child); g_object_unref (child); child = next; } } else ERROR_OUT ("unrecognized element '%s'", element); #undef ERROR_OUT return g_steal_pointer (&schema); } static gboolean parse (BzYamlParser *self, yaml_parser_t *parser, yaml_event_t *event, gboolean parse_first, gboolean toplevel, SchemaNodeData *schema, GHashTable *output, GHashTable *anchors, GPtrArray *path_stack, GError **error) { if (parse_first && !yaml_parser_parse (parser, event)) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_INVALID_YAML, "Failed to parse YAML at line %zu, column %zu: %s", parser->problem_mark.line, parser->problem_mark.column, parser->problem); return FALSE; } #define NEXT_EVENT() \ G_STMT_START \ { \ yaml_event_delete (event); \ if (!yaml_parser_parse (parser, event)) \ { \ g_set_error ( \ error, \ BZ_YAML_ERROR, \ BZ_YAML_ERROR_INVALID_YAML, \ "Failed to parse YAML at line %zu, column %zu: %s", \ parser->problem_mark.line, \ parser->problem_mark.column, \ parser->problem); \ return FALSE; \ } \ } \ G_STMT_END #define EXPECT(event_type, string_type) \ if (event->type != (event_type)) \ { \ g_set_error ( \ error, \ BZ_YAML_ERROR, \ BZ_YAML_ERROR_DOES_NOT_CONFORM, \ "Failed to validate YAML against schema at line %zu, column %zu: " \ "expected " string_type " here", \ event->start_mark.line, \ event->start_mark.column); \ yaml_event_delete (event); \ return FALSE; \ } #define TRY_ALIAS(var, gtype, string_type) \ if (event->type == YAML_ALIAS_EVENT) \ { \ GValue *_value = NULL; \ \ _value = g_hash_table_lookup ( \ anchors, \ event->data.alias.anchor); \ if (_value == NULL) \ { \ g_set_error ( \ error, \ BZ_YAML_ERROR, \ BZ_YAML_ERROR_INVALID_YAML, \ "Failed to resolve YAML alias at line %zu, column %zu: " \ "the anchor \"%s\" does not yet exist", \ event->start_mark.line, \ event->start_mark.column, \ (const char *) event->data.alias.anchor); \ yaml_event_delete (event); \ return FALSE; \ } \ \ if (!G_VALUE_HOLDS (_value, (gtype))) \ { \ g_set_error ( \ error, \ BZ_YAML_ERROR, \ BZ_YAML_ERROR_DOES_NOT_CONFORM, \ "Failed to validate YAML against schema at line %zu, column %zu: " \ "the alias needs to be of type " string_type " here", \ event->start_mark.line, \ event->start_mark.column); \ yaml_event_delete (event); \ return FALSE; \ } \ \ (var) = copy_gvalue_alloc (_value); \ } if (toplevel) { EXPECT (YAML_STREAM_START_EVENT, "start of stream"); NEXT_EVENT (); EXPECT (YAML_DOCUMENT_START_EVENT, "start of document"); NEXT_EVENT (); } switch (schema->kind) { case KIND_SCALAR: { GValue *value = NULL; TRY_ALIAS (value, G_TYPE_VARIANT, "scalar"); if (value != NULL) { GVariant *variant = NULL; variant = g_value_get_variant (value); if (!g_variant_type_equal ( g_variant_get_type (variant), (const GVariantType *) schema->scalar.vtype)) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_DOES_NOT_CONFORM, "Failed to validate YAML against schema at line %zu, column %zu: " "the alias needs to be of scalar type %s here", event->start_mark.line, event->start_mark.column, schema->scalar.vtype); destroy_gvalue (value); yaml_event_delete (event); return FALSE; } } else { g_autofree char *anchor = NULL; g_autoptr (GVariant) variant = NULL; EXPECT (YAML_SCALAR_EVENT, "scalar"); anchor = bz_maybe_strdup ((const char *) event->data.scalar.anchor); if (g_variant_type_equal ((const GVariantType *) schema->scalar.vtype, G_VARIANT_TYPE_STRING)) variant = g_variant_new_string ((const char *) event->data.scalar.value); else { g_autoptr (GError) local_error = NULL; variant = g_variant_parse ( (const GVariantType *) schema->scalar.vtype, (const char *) event->data.scalar.value, NULL, NULL, &local_error); if (variant == NULL) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_BAD_SCALAR, "Failed to parse scalar variant at line %zu, column %zu: " "%s", event->start_mark.line, event->start_mark.column, local_error->message); yaml_event_delete (event); return FALSE; } } value = make_gvalue_alloc (G_TYPE_VARIANT); g_value_set_variant (value, g_steal_pointer (&variant)); if (anchor != NULL) g_hash_table_replace ( anchors, g_steal_pointer (&anchor), copy_gvalue_alloc (value)); } g_hash_table_replace (output, join_path_stack (path_stack), value); } break; case KIND_OBJECT: { g_autoptr (GObject) object = NULL; GValue *value = NULL; TRY_ALIAS (value, schema->object.type, "object"); if (value == NULL) { object = parse_object ( self, parser, event, schema->object.type, schema->object.type_hints, anchors, NULL, error); if (object == NULL) /* event is already cleaned up */ return FALSE; value = make_gvalue_alloc (schema->object.type); g_value_set_object (value, object); } g_hash_table_replace (output, join_path_stack (path_stack), value); } break; case KIND_LIST: { GValue *value = NULL; TRY_ALIAS (value, G_TYPE_PTR_ARRAY, "list"); if (value == NULL) { g_autofree char *anchor = NULL; g_autoptr (GPtrArray) list = NULL; EXPECT (YAML_SEQUENCE_START_EVENT, "list"); anchor = bz_maybe_strdup ((const char *) event->data.sequence_start.anchor); list = g_ptr_array_new_with_free_func ((GDestroyNotify) destroy_gvalue); for (;;) { g_autoptr (GHashTable) list_output = NULL; g_autoptr (GPtrArray) list_path_stack = NULL; gboolean result = FALSE; GValue *append = NULL; NEXT_EVENT (); if (event->type == YAML_SEQUENCE_END_EVENT) break; list_output = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_gvalue); list_path_stack = g_ptr_array_new_with_free_func (g_free); result = parse ( self, parser, event, FALSE, FALSE, schema->list.child, list_output, anchors, list_path_stack, error); if (!result) /* event is already cleaned up */ return FALSE; append = make_gvalue_alloc (G_TYPE_HASH_TABLE); g_value_set_boxed (append, list_output); g_ptr_array_add (list, append); } value = make_gvalue_alloc (G_TYPE_PTR_ARRAY); g_value_set_boxed (value, list); if (anchor != NULL) g_hash_table_replace ( anchors, g_steal_pointer (&anchor), copy_gvalue_alloc (value)); } g_hash_table_replace (output, join_path_stack (path_stack), value); } break; case KIND_MAPPINGS: { EXPECT (YAML_MAPPING_START_EVENT, "mappings"); for (;;) { g_autofree char *key = NULL; SchemaNodeData *map_schema = NULL; gboolean result = FALSE; NEXT_EVENT (); if (event->type == YAML_MAPPING_END_EVENT) break; EXPECT (YAML_SCALAR_EVENT, "scalar key"); key = g_strdup ((const char *) event->data.scalar.value); map_schema = g_hash_table_lookup (schema->mappings.children, key); if (map_schema == NULL) { g_autofree char *path = NULL; path = join_path_stack (path_stack); g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_DOES_NOT_CONFORM, "Failed to validate YAML against schema at line %zu, column %zu: " "key '%s' shouldn't exist at path %s", event->start_mark.line, event->start_mark.column, key, path); yaml_event_delete (event); return FALSE; } g_ptr_array_add (path_stack, g_steal_pointer (&key)); result = parse ( self, parser, event, TRUE, FALSE, map_schema, output, anchors, path_stack, error); if (!result) /* event is already cleaned up */ return FALSE; g_ptr_array_set_size (path_stack, path_stack->len - 1); } } break; default: g_assert_not_reached (); } if (toplevel) { NEXT_EVENT (); EXPECT (YAML_DOCUMENT_END_EVENT, "end of document"); NEXT_EVENT (); EXPECT (YAML_STREAM_END_EVENT, "end of stream"); } yaml_event_delete (event); return TRUE; } static GObject * parse_object (BzYamlParser *self, yaml_parser_t *parser, yaml_event_t *event, GType object_gtype, GHashTable *type_hints, GHashTable *anchors, const char *prop_path, GError **error) { GValue *value = NULL; g_autofree char *object_anchor = NULL; g_autoptr (GTypeClass) gtype_class = NULL; g_autoptr (GObject) object = NULL; TRY_ALIAS (value, object_gtype, "object mapping"); if (value != NULL) { object = g_value_dup_object (value); destroy_gvalue (value); return g_steal_pointer (&object); } EXPECT (YAML_MAPPING_START_EVENT, "object mapping"); object_anchor = bz_maybe_strdup ((const char *) event->data.mapping_start.anchor); gtype_class = g_type_class_ref (object_gtype); object = g_object_new (object_gtype, NULL); for (;;) { g_autofree char *property = NULL; GParamSpec *spec = NULL; NEXT_EVENT (); if (event->type == YAML_MAPPING_END_EVENT) break; EXPECT (YAML_SCALAR_EVENT, "scalar key"); property = g_strdup ((const char *) event->data.scalar.value); spec = g_object_class_find_property (G_OBJECT_CLASS (gtype_class), property); if (spec == NULL) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_DOES_NOT_CONFORM, "Failed to validate YAML against schema at line %zu, column %zu: " "property '%s' doesn't exist on type %s", event->start_mark.line, event->start_mark.column, property, g_type_name (object_gtype)); yaml_event_delete (event); return FALSE; } NEXT_EVENT (); if (g_type_is_a (spec->value_type, G_TYPE_LIST_MODEL)) { g_autofree char *replace_prop_path = NULL; GType element_gtype = 0; g_autoptr (GListModel) list = NULL; if (prop_path != NULL) replace_prop_path = g_strdup_printf ("%s.%s", prop_path, property); element_gtype = GPOINTER_TO_SIZE (g_hash_table_lookup ( type_hints, replace_prop_path != NULL ? replace_prop_path : property)); TRY_ALIAS (value, G_TYPE_LIST_MODEL, "mappings"); if (value != NULL) { list = g_value_dup_object (value); if (!G_IS_LIST_MODEL (list) || g_list_model_get_item_type (list) != element_gtype) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_DOES_NOT_CONFORM, "Failed to validate YAML against schema at line %zu, column %zu: " "the alias needs to be a list of object type %s here", event->start_mark.line, event->start_mark.column, g_type_name (element_gtype)); destroy_gvalue (value); yaml_event_delete (event); return FALSE; } } else { g_autofree char *anchor = NULL; EXPECT (YAML_SEQUENCE_START_EVENT, "sequence"); anchor = bz_maybe_strdup ((const char *) event->data.sequence_start.anchor); if (element_gtype == GTK_TYPE_STRING_OBJECT) { list = (GListModel *) gtk_string_list_new (NULL); for (;;) { NEXT_EVENT (); if (event->type == YAML_SEQUENCE_END_EVENT) break; EXPECT (YAML_SCALAR_EVENT, "scalar list value"); gtk_string_list_append ( GTK_STRING_LIST (list), (const char *) event->data.scalar.value); } } else { if (element_gtype == 0) element_gtype = G_TYPE_OBJECT; list = (GListModel *) g_list_store_new (element_gtype); for (;;) { g_autoptr (GObject) child_object = NULL; NEXT_EVENT (); if (event->type == YAML_SEQUENCE_END_EVENT) break; child_object = parse_object ( self, parser, event, element_gtype, type_hints, anchors, replace_prop_path != NULL ? replace_prop_path : property, error); if (child_object == NULL) /* event is already cleaned up */ return FALSE; g_list_store_append (G_LIST_STORE (list), child_object); } } if (anchor != NULL) { value = make_gvalue_alloc (G_TYPE_LIST_MODEL); g_value_set_object (value, list); g_hash_table_replace ( anchors, g_steal_pointer (&anchor), value); } } g_object_set (object, property, list, NULL); } else if (g_type_is_a (spec->value_type, G_TYPE_OBJECT)) { g_autofree char *replace_prop_path = NULL; g_autoptr (GObject) prop_object = NULL; if (prop_path != NULL) replace_prop_path = g_strdup_printf ("%s.%s", prop_path, property); prop_object = parse_object ( self, parser, event, spec->value_type, type_hints, anchors, replace_prop_path != NULL ? replace_prop_path : property, error); if (prop_object == NULL) /* event is already cleaned up */ return FALSE; g_object_set (object, property, prop_object, NULL); } else if (g_type_is_a (spec->value_type, G_TYPE_ENUM)) { g_autoptr (GEnumClass) class = NULL; GEnumValue *enum_value = NULL; TRY_ALIAS (value, spec->value_type, "scalar enum value"); if (value != NULL) { g_object_set_property (object, property, value); destroy_gvalue (value); } else { g_autofree char *anchor = NULL; EXPECT (YAML_SCALAR_EVENT, "scalar enum value"); anchor = bz_maybe_strdup ((const char *) event->data.scalar.anchor); class = g_type_class_ref (spec->value_type); enum_value = g_enum_get_value_by_nick ( class, (const char *) event->data.scalar.value); if (enum_value == NULL) enum_value = g_enum_get_value_by_name ( class, (const char *) event->data.scalar.value); if (enum_value == NULL) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_BAD_SCALAR, "Failed to parse scalar enum at line %zu, column %zu: " "'%s' does not exist in type %s", event->start_mark.line, event->start_mark.column, (const char *) event->data.scalar.value, g_type_name (spec->value_type)); yaml_event_delete (event); return FALSE; } if (anchor != NULL) { value = make_gvalue_alloc (spec->value_type); g_value_set_enum (value, enum_value->value); g_hash_table_replace ( anchors, g_steal_pointer (&anchor), value); } g_object_set (object, property, enum_value->value, NULL); } } else { g_autoptr (GError) local_error = NULL; const GVariantType *vtype = NULL; g_autoptr (GVariant) variant = NULL; TRY_ALIAS (value, spec->value_type, "scalar"); if (value != NULL) { g_object_set_property (object, property, value); destroy_gvalue (value); } else { g_autofree char *anchor = NULL; if (spec->value_type == G_TYPE_STRING && event->type == YAML_MAPPING_START_EVENT) { /* Handle optional translated strings */ const char *const *langs = NULL; g_autofree char *english = NULL; anchor = bz_maybe_strdup ((const char *) event->data.mapping_start.anchor); langs = g_get_language_names (); for (;;) { g_autofree char *code = NULL; NEXT_EVENT (); if (event->type == YAML_MAPPING_END_EVENT) break; EXPECT (YAML_SCALAR_EVENT, "scalar key language code"); if (variant != NULL) continue; code = g_strdup ((const char *) event->data.scalar.value); NEXT_EVENT (); EXPECT (YAML_SCALAR_EVENT, "scalar translated string"); if (g_strv_contains (langs, code)) variant = g_variant_new_string ((const char *) event->data.scalar.value); else if (english == NULL && g_strcmp0 (code, "en") == 0) english = g_strdup ((const char *) event->data.scalar.value); } if (variant == NULL) variant = g_variant_new_string (english != NULL ? english : "NULL"); } else { EXPECT (YAML_SCALAR_EVENT, "scalar value"); anchor = bz_maybe_strdup ((const char *) event->data.scalar.anchor); switch (spec->value_type) { case G_TYPE_BOOLEAN: vtype = G_VARIANT_TYPE_BOOLEAN; break; case G_TYPE_INT: vtype = G_VARIANT_TYPE_INT32; break; case G_TYPE_INT64: vtype = G_VARIANT_TYPE_INT64; break; case G_TYPE_UINT: vtype = G_VARIANT_TYPE_UINT32; break; case G_TYPE_UINT64: vtype = G_VARIANT_TYPE_UINT64; break; case G_TYPE_DOUBLE: case G_TYPE_FLOAT: vtype = G_VARIANT_TYPE_DOUBLE; break; case G_TYPE_STRING: default: vtype = G_VARIANT_TYPE_STRING; break; } if (g_variant_type_equal (vtype, G_VARIANT_TYPE_STRING)) variant = g_variant_new_string ((const char *) event->data.scalar.value); else { variant = g_variant_parse ( vtype, (const char *) event->data.scalar.value, NULL, NULL, &local_error); if (variant == NULL) { g_set_error ( error, BZ_YAML_ERROR, BZ_YAML_ERROR_BAD_SCALAR, "Failed to parse scalar variant at line %zu, column %zu: %s", event->start_mark.line, event->start_mark.column, local_error->message); yaml_event_delete (event); return FALSE; } } } if (anchor != NULL) value = make_gvalue_alloc (spec->value_type); switch (spec->value_type) { case G_TYPE_BOOLEAN: g_object_set (object, property, g_variant_get_boolean (variant), NULL); if (anchor != NULL) g_value_set_boolean (value, g_variant_get_boolean (variant)); break; case G_TYPE_INT: g_object_set (object, property, g_variant_get_int32 (variant), NULL); if (anchor != NULL) g_value_set_int (value, g_variant_get_int32 (variant)); break; case G_TYPE_INT64: g_object_set (object, property, g_variant_get_int64 (variant), NULL); if (anchor != NULL) g_value_set_int64 (value, g_variant_get_int64 (variant)); break; case G_TYPE_UINT: g_object_set (object, property, g_variant_get_uint32 (variant), NULL); if (anchor != NULL) g_value_set_uint (value, g_variant_get_uint32 (variant)); break; case G_TYPE_UINT64: g_object_set (object, property, g_variant_get_uint64 (variant), NULL); if (anchor != NULL) g_value_set_uint64 (value, g_variant_get_uint64 (variant)); break; case G_TYPE_DOUBLE: case G_TYPE_FLOAT: g_object_set (object, property, g_variant_get_double (variant), NULL); if (anchor != NULL) g_value_set_double (value, g_variant_get_double (variant)); break; case G_TYPE_STRING: default: g_object_set (object, property, g_variant_get_string (variant, NULL), NULL); if (anchor != NULL) g_value_set_string (value, g_variant_get_string (variant, NULL)); break; } if (anchor != NULL) g_hash_table_replace ( anchors, g_steal_pointer (&anchor), value); } } } if (object_anchor != NULL) { value = make_gvalue_alloc (G_TYPE_LIST_MODEL); g_value_set_object (value, object); g_hash_table_replace ( anchors, g_steal_pointer (&object_anchor), value); } return g_steal_pointer (&object); } static char * join_path_stack (GPtrArray *path_stack) { GString *string = NULL; if (path_stack->len == 0) return g_strdup ("/"); string = g_string_new (NULL); for (guint i = 0; i < path_stack->len; i++) { const char *component = NULL; component = g_ptr_array_index (path_stack, i); g_string_append_printf (string, "/%s", component); } return g_string_free_and_steal (string); } static void destroy_gvalue (GValue *value) { g_value_unset (value); g_free (value); } static GValue * make_gvalue_alloc (GType type) { GValue *ret = NULL; ret = g_new0 (typeof (*ret), 1); g_value_init (ret, type); return ret; } static GValue * copy_gvalue_alloc (GValue *value) { GValue *ret = NULL; ret = g_new0 (typeof (*ret), 1); g_value_init (ret, value->g_type); g_value_copy (value, ret); return ret; } static void deinit_schema_node (gpointer data) { SchemaNodeData *self = data; switch (self->kind) { case KIND_SCALAR: g_clear_pointer (&self->scalar.vtype, g_free); break; case KIND_OBJECT: g_clear_pointer (&self->object.type_hints, g_hash_table_unref); break; case KIND_LIST: g_clear_pointer (&self->list.child, schema_node_data_unref); break; case KIND_MAPPINGS: g_clear_pointer (&self->mappings.children, g_hash_table_unref); break; default: g_assert_not_reached (); } } kolunmi-bazaar-7b9c8e1/src/bz-yaml-parser.h000066400000000000000000000023321514314607700206670ustar00rootroot00000000000000/* bz-yaml-parser.h * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_YAML_ERROR (bz_yaml_error_quark ()) GQuark bz_yaml_error_quark (void); typedef enum { BZ_YAML_ERROR_INVALID_YAML = 0, BZ_YAML_ERROR_DOES_NOT_CONFORM, BZ_YAML_ERROR_BAD_SCALAR, } BzYamlError; #define BZ_TYPE_YAML_PARSER (bz_yaml_parser_get_type ()) G_DECLARE_FINAL_TYPE (BzYamlParser, bz_yaml_parser, BZ, YAML_PARSER, GObject) BzYamlParser * bz_yaml_parser_new_for_resource_schema (const char *path); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/bz-zoom.c000066400000000000000000000470111514314607700174150ustar00rootroot00000000000000/* bz-zoom.c * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "bz-zoom.h" #include #include #define OVERPAN_FACTOR 0.5 struct _BzZoom { GtkWidget parent_instance; GtkWidget *child; double zoom_level; double min_zoom; double max_zoom; double pan_x; double pan_y; double mouse_x; double mouse_y; double gesture_start_zoom; double drag_start_x; double drag_start_y; gboolean is_dragging; AdwAnimation *zoom_animation; double target_zoom; double target_pan_x; double target_pan_y; double start_zoom; double start_pan_x; double start_pan_y; GtkGesture *zoom_gesture; GtkGesture *drag_gesture; GtkEventController *scroll_controller; GtkEventController *motion_controller; }; G_DEFINE_FINAL_TYPE (BzZoom, bz_zoom, GTK_TYPE_WIDGET) enum { PROP_0, PROP_CHILD, PROP_ZOOM_LEVEL, PROP_MIN_ZOOM, PROP_MAX_ZOOM, LAST_PROP }; static GParamSpec *props[LAST_PROP] = { 0 }; static void bz_zoom_constrain_pan (BzZoom *self); static void bz_zoom_zoom_at_point (BzZoom *self, double zoom_factor, double center_x, double center_y); static void bz_zoom_dispose (GObject *object) { BzZoom *self; self = BZ_ZOOM (object); g_clear_pointer (&self->child, gtk_widget_unparent); g_clear_object (&self->zoom_animation); G_OBJECT_CLASS (bz_zoom_parent_class)->dispose (object); } static void bz_zoom_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { BzZoom *self; self = BZ_ZOOM (object); switch (prop_id) { case PROP_CHILD: g_value_set_object (value, bz_zoom_get_child (self)); break; case PROP_ZOOM_LEVEL: g_value_set_double (value, bz_zoom_get_zoom_level (self)); break; case PROP_MIN_ZOOM: g_value_set_double (value, bz_zoom_get_min_zoom (self)); break; case PROP_MAX_ZOOM: g_value_set_double (value, bz_zoom_get_max_zoom (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void bz_zoom_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { BzZoom *self; self = BZ_ZOOM (object); switch (prop_id) { case PROP_CHILD: bz_zoom_set_child (self, g_value_get_object (value)); break; case PROP_ZOOM_LEVEL: bz_zoom_set_zoom_level (self, g_value_get_double (value)); break; case PROP_MIN_ZOOM: bz_zoom_set_min_zoom (self, g_value_get_double (value)); break; case PROP_MAX_ZOOM: bz_zoom_set_max_zoom (self, g_value_get_double (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void on_motion (BzZoom *self, double x, double y, GtkEventControllerMotion *controller) { self->mouse_x = x; self->mouse_y = y; } static void on_zoom_begin (BzZoom *self, GdkEventSequence *sequence, GtkGesture *gesture) { self->gesture_start_zoom = self->zoom_level; } static void on_zoom_changed (BzZoom *self, double scale, GtkGesture *gesture) { double target_zoom; double zoom_factor; double center_x; double center_y; target_zoom = self->gesture_start_zoom * scale; if (self->zoom_level > 0) zoom_factor = target_zoom / self->zoom_level; else zoom_factor = 1.0; gtk_gesture_get_bounding_box_center (gesture, ¢er_x, ¢er_y); bz_zoom_zoom_at_point (self, zoom_factor, center_x, center_y); } static gboolean on_scroll (BzZoom *self, double dx, double dy, GtkEventControllerScroll *controller) { GdkEvent *event; GdkDevice *device; GdkInputSource source; double zoom_factor; event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (controller)); if (event == NULL) return GDK_EVENT_PROPAGATE; device = gdk_event_get_device (event); if (device == NULL) return GDK_EVENT_PROPAGATE; source = gdk_device_get_source (device); if (source != GDK_SOURCE_MOUSE) return GDK_EVENT_PROPAGATE; zoom_factor = dy < 0 ? 1.1 : 0.9; bz_zoom_zoom_at_point (self, zoom_factor, self->mouse_x, self->mouse_y); return GDK_EVENT_STOP; } static void on_drag_begin (BzZoom *self, double start_x, double start_y, GtkGesture *gesture) { if (fabs (self->zoom_level - 1.0) < 0.001) { gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED); return; } self->drag_start_x = self->pan_x; self->drag_start_y = self->pan_y; self->is_dragging = TRUE; } static void on_drag_update (BzZoom *self, double offset_x, double offset_y, GtkGesture *gesture) { if (!self->is_dragging) return; self->pan_x = self->drag_start_x + offset_x; self->pan_y = self->drag_start_y + offset_y; bz_zoom_constrain_pan (self); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void on_drag_end (BzZoom *self, double offset_x, double offset_y, GtkGesture *gesture) { self->is_dragging = FALSE; } static void bz_zoom_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { BzZoom *self; int width; int height; GskTransform *transform; graphene_point_t point; self = BZ_ZOOM (widget); width = gtk_widget_get_width (widget); height = gtk_widget_get_height (widget); if (width <= 0 || height <= 0) return; transform = NULL; graphene_point_init (&point, width / 2.0 + self->pan_x, height / 2.0 + self->pan_y); transform = gsk_transform_translate (transform, &point); /* See bz_zoom_size_allocate */ // transform = gsk_transform_scale (transform, self->zoom_level, self->zoom_level); graphene_point_init ( &point, -(width * self->zoom_level) / 2.0, -(height * self->zoom_level) / 2.0); transform = gsk_transform_translate (transform, &point); gtk_snapshot_save (snapshot); gtk_snapshot_transform (snapshot, transform); if (self->child) gtk_widget_snapshot_child (widget, self->child, snapshot); gtk_snapshot_restore (snapshot); gsk_transform_unref (transform); } static void bz_zoom_measure (GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { BzZoom *self; self = BZ_ZOOM (widget); if (self->child) gtk_widget_measure (self->child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); else { *minimum = 0; *natural = 0; } } static void bz_zoom_size_allocate (GtkWidget *widget, int width, int height, int baseline) { BzZoom *self; self = BZ_ZOOM (widget); if (self->child) /* TODO: maybe add a property to control whether the child is artificially scaled? */ gtk_widget_allocate ( self->child, self->zoom_level * width, self->zoom_level * height, baseline, NULL); bz_zoom_constrain_pan (self); } static void bz_zoom_class_init (BzZoomClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; object_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = bz_zoom_dispose; object_class->get_property = bz_zoom_get_property; object_class->set_property = bz_zoom_set_property; widget_class->snapshot = bz_zoom_snapshot; widget_class->measure = bz_zoom_measure; widget_class->size_allocate = bz_zoom_size_allocate; props[PROP_CHILD] = g_param_spec_object ( "child", NULL, NULL, GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_ZOOM_LEVEL] = g_param_spec_double ( "zoom-level", NULL, NULL, 0.1, 10.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PROP_MIN_ZOOM] = g_param_spec_double ( "min-zoom", NULL, NULL, 0.1, 1.0, 0.25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PROP_MAX_ZOOM] = g_param_spec_double ( "max-zoom", NULL, NULL, 1.0, 10.0, 5.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, props); } static void bz_zoom_init (BzZoom *self) { self->zoom_level = 1.0; self->min_zoom = 0.25; self->max_zoom = 5.0; self->pan_x = 0.0; self->pan_y = 0.0; self->mouse_x = 0.0; self->mouse_y = 0.0; self->gesture_start_zoom = 1.0; self->is_dragging = FALSE; self->zoom_gesture = gtk_gesture_zoom_new (); g_signal_connect_swapped (self->zoom_gesture, "begin", G_CALLBACK (on_zoom_begin), self); g_signal_connect_swapped (self->zoom_gesture, "scale-changed", G_CALLBACK (on_zoom_changed), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->zoom_gesture)); self->drag_gesture = gtk_gesture_drag_new (); gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->drag_gesture), GDK_BUTTON_PRIMARY); g_signal_connect_swapped (self->drag_gesture, "drag-begin", G_CALLBACK (on_drag_begin), self); g_signal_connect_swapped (self->drag_gesture, "drag-update", G_CALLBACK (on_drag_update), self); g_signal_connect_swapped (self->drag_gesture, "drag-end", G_CALLBACK (on_drag_end), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->drag_gesture)); self->scroll_controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_VERTICAL | GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL); g_signal_connect_swapped (self->scroll_controller, "scroll", G_CALLBACK (on_scroll), self); gtk_widget_add_controller (GTK_WIDGET (self), self->scroll_controller); self->motion_controller = gtk_event_controller_motion_new (); g_signal_connect_swapped (self->motion_controller, "motion", G_CALLBACK (on_motion), self); gtk_widget_add_controller (GTK_WIDGET (self), self->motion_controller); gtk_widget_set_focusable (GTK_WIDGET (self), TRUE); } GtkWidget * bz_zoom_new (void) { return g_object_new (BZ_TYPE_ZOOM, NULL); } GtkWidget * bz_zoom_get_child (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), NULL); return self->child; } void bz_zoom_set_child (BzZoom *self, GtkWidget *child) { g_return_if_fail (BZ_IS_ZOOM (self)); g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (self->child == child) return; g_clear_pointer (&self->child, gtk_widget_unparent); self->child = child; if (self->child) gtk_widget_set_parent (self->child, GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]); } double bz_zoom_get_zoom_level (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), 1.0); return self->zoom_level; } void bz_zoom_set_zoom_level (BzZoom *self, double zoom_level) { double new_zoom; g_return_if_fail (BZ_IS_ZOOM (self)); new_zoom = CLAMP (zoom_level, self->min_zoom, self->max_zoom); if (fabs (new_zoom - self->zoom_level) < 0.001) return; self->zoom_level = new_zoom; bz_zoom_constrain_pan (self); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ZOOM_LEVEL]); } double bz_zoom_get_min_zoom (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), 0.25); return self->min_zoom; } void bz_zoom_set_min_zoom (BzZoom *self, double min_zoom) { g_return_if_fail (BZ_IS_ZOOM (self)); self->min_zoom = min_zoom; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MIN_ZOOM]); } double bz_zoom_get_max_zoom (BzZoom *self) { g_return_val_if_fail (BZ_IS_ZOOM (self), 5.0); return self->max_zoom; } void bz_zoom_set_max_zoom (BzZoom *self, double max_zoom) { g_return_if_fail (BZ_IS_ZOOM (self)); self->max_zoom = max_zoom; g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MAX_ZOOM]); } static void bz_zoom_constrain_pan (BzZoom *self) { int widget_width; int widget_height; double overpan_x; double overpan_y; double range_x; double range_y; double max_pan_x; double max_pan_y; widget_width = gtk_widget_get_width (GTK_WIDGET (self)); widget_height = gtk_widget_get_height (GTK_WIDGET (self)); if (widget_width <= 0 || widget_height <= 0) return; overpan_x = widget_width * OVERPAN_FACTOR; overpan_y = widget_height * OVERPAN_FACTOR; range_x = MAX (0, (widget_width * self->zoom_level - widget_width) / 2.0); range_y = MAX (0, (widget_height * self->zoom_level - widget_height) / 2.0); max_pan_x = range_x + overpan_x; max_pan_y = range_y + overpan_y; self->pan_x = CLAMP (self->pan_x, -max_pan_x, max_pan_x); self->pan_y = CLAMP (self->pan_y, -max_pan_y, max_pan_y); } static void bz_zoom_zoom_at_point (BzZoom *self, double zoom_factor, double center_x, double center_y) { double old_zoom; double new_zoom; int widget_width; int widget_height; double widget_center_x; double widget_center_y; double old_content_x; double old_content_y; double zoom_ratio; double new_content_x; double new_content_y; old_zoom = self->zoom_level; new_zoom = old_zoom * zoom_factor; new_zoom = CLAMP (new_zoom, self->min_zoom, self->max_zoom); if (fabs (new_zoom - old_zoom) < 0.001) return; widget_width = gtk_widget_get_width (GTK_WIDGET (self)); widget_height = gtk_widget_get_height (GTK_WIDGET (self)); widget_center_x = widget_width / 2.0; widget_center_y = widget_height / 2.0; old_content_x = center_x - widget_center_x - self->pan_x; old_content_y = center_y - widget_center_y - self->pan_y; zoom_ratio = new_zoom / old_zoom; new_content_x = old_content_x * zoom_ratio; new_content_y = old_content_y * zoom_ratio; self->zoom_level = new_zoom; self->pan_x = center_x - widget_center_x - new_content_x; self->pan_y = center_y - widget_center_y - new_content_y; bz_zoom_constrain_pan (self); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ZOOM_LEVEL]); } static void on_animation_value (double value, BzZoom *self) { self->zoom_level = self->start_zoom + (self->target_zoom - self->start_zoom) * value; self->pan_x = self->start_pan_x + (self->target_pan_x - self->start_pan_x) * value; self->pan_y = self->start_pan_y + (self->target_pan_y - self->start_pan_y) * value; bz_zoom_constrain_pan (self); gtk_widget_queue_resize (GTK_WIDGET (self)); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ZOOM_LEVEL]); } static void bz_zoom_animate_to (BzZoom *self, double target_zoom, double target_pan_x, double target_pan_y) { AdwAnimationTarget *target; if (self->zoom_animation) adw_animation_skip (self->zoom_animation); self->start_zoom = self->zoom_level; self->start_pan_x = self->pan_x; self->start_pan_y = self->pan_y; self->target_zoom = target_zoom; self->target_pan_x = target_pan_x; self->target_pan_y = target_pan_y; target = adw_callback_animation_target_new ((AdwAnimationTargetFunc) on_animation_value, self, NULL); self->zoom_animation = adw_timed_animation_new (GTK_WIDGET (self), 0, 1, 150, target); adw_timed_animation_set_easing (ADW_TIMED_ANIMATION (self->zoom_animation), ADW_EASE_OUT_CUBIC); adw_animation_play (self->zoom_animation); } void bz_zoom_zoom_in (BzZoom *self) { int width; int height; double old_zoom; double new_zoom; double widget_center_x; double widget_center_y; double center_x; double center_y; double old_content_x; double old_content_y; double zoom_ratio; double new_content_x; double new_content_y; double new_pan_x; double new_pan_y; g_return_if_fail (BZ_IS_ZOOM (self)); width = gtk_widget_get_width (GTK_WIDGET (self)); height = gtk_widget_get_height (GTK_WIDGET (self)); center_x = width / 2.0; center_y = height / 2.0; old_zoom = self->zoom_level; new_zoom = old_zoom * 1.2; new_zoom = CLAMP (new_zoom, self->min_zoom, self->max_zoom); if (fabs (new_zoom - old_zoom) < 0.001) return; widget_center_x = width / 2.0; widget_center_y = height / 2.0; old_content_x = center_x - widget_center_x - self->pan_x; old_content_y = center_y - widget_center_y - self->pan_y; zoom_ratio = new_zoom / old_zoom; new_content_x = old_content_x * zoom_ratio; new_content_y = old_content_y * zoom_ratio; new_pan_x = center_x - widget_center_x - new_content_x; new_pan_y = center_y - widget_center_y - new_content_y; bz_zoom_animate_to (self, new_zoom, new_pan_x, new_pan_y); } void bz_zoom_zoom_out (BzZoom *self) { int width; int height; double old_zoom; double new_zoom; double widget_center_x; double widget_center_y; double center_x; double center_y; double old_content_x; double old_content_y; double zoom_ratio; double new_content_x; double new_content_y; double new_pan_x; double new_pan_y; g_return_if_fail (BZ_IS_ZOOM (self)); width = gtk_widget_get_width (GTK_WIDGET (self)); height = gtk_widget_get_height (GTK_WIDGET (self)); center_x = width / 2.0; center_y = height / 2.0; old_zoom = self->zoom_level; new_zoom = old_zoom * 0.8; new_zoom = CLAMP (new_zoom, self->min_zoom, self->max_zoom); if (fabs (new_zoom - old_zoom) < 0.001) return; widget_center_x = width / 2.0; widget_center_y = height / 2.0; old_content_x = center_x - widget_center_x - self->pan_x; old_content_y = center_y - widget_center_y - self->pan_y; zoom_ratio = new_zoom / old_zoom; new_content_x = old_content_x * zoom_ratio; new_content_y = old_content_y * zoom_ratio; new_pan_x = center_x - widget_center_x - new_content_x; new_pan_y = center_y - widget_center_y - new_content_y; bz_zoom_animate_to (self, new_zoom, new_pan_x, new_pan_y); } void bz_zoom_reset (BzZoom *self) { g_return_if_fail (BZ_IS_ZOOM (self)); bz_zoom_animate_to (self, 1.0, 0.0, 0.0); } void bz_zoom_fit_to_window (BzZoom *self) { g_return_if_fail (BZ_IS_ZOOM (self)); bz_zoom_animate_to (self, 1.0, 0.0, 0.0); } /* End of bz-zoom.c */ kolunmi-bazaar-7b9c8e1/src/bz-zoom.h000066400000000000000000000032021514314607700174140ustar00rootroot00000000000000/* bz-zoom.h * * Copyright 2025 Alexander Vanhee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define BZ_TYPE_ZOOM (bz_zoom_get_type ()) G_DECLARE_FINAL_TYPE (BzZoom, bz_zoom, BZ, ZOOM, GtkWidget) GtkWidget *bz_zoom_new (void); GtkWidget *bz_zoom_get_child (BzZoom *self); void bz_zoom_set_child (BzZoom *self, GtkWidget *child); double bz_zoom_get_zoom_level (BzZoom *self); void bz_zoom_set_zoom_level (BzZoom *self, double zoom_level); double bz_zoom_get_min_zoom (BzZoom *self); void bz_zoom_set_min_zoom (BzZoom *self, double min_zoom); double bz_zoom_get_max_zoom (BzZoom *self); void bz_zoom_set_max_zoom (BzZoom *self, double max_zoom); void bz_zoom_zoom_in (BzZoom *self); void bz_zoom_zoom_out (BzZoom *self); void bz_zoom_reset (BzZoom *self); void bz_zoom_fit_to_window (BzZoom *self); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/countries.json000066400000000000000000007025531514314607700205730ustar00rootroot00000000000000{"features":[{"N":"Fiji","I":"FJ","C":[[[[180,-16.067],[180,-16.555],[179.364,-16.801],[178.725,-17.012],[178.597,-16.639],[179.097,-16.434],[179.414,-16.379],[180,-16.067]]],[[[178.126,-17.505],[178.374,-17.34],[178.718,-17.628],[178.553,-18.151],[177.933,-18.288],[177.381,-18.164],[177.285,-17.725],[177.671,-17.381],[178.126,-17.505]]],[[[-179.793,-16.021],[-179.917,-16.502],[-180,-16.555],[-180,-16.067],[-179.793,-16.021]]]],"translations":{"ar":"فيجي","bs":"FidĹži","cs":"FidĹži","de":"Fidschi","es":"Fiyi","fa_IR":"فیجی","fr":"Fidji","id":"Fiji","it":"Figi","ja":"フィジー","pl":"FidĹźi","pt_BR":"Fiji","pt_PT":"Fiji","ru":"ФидМи","uk":"Фіджі","zh_CN":"斐济","zh_TW":"斐濟"}},{"N":"Tanzania","I":"TZ","C":[[[[33.904,-0.95],[34.073,-1.06],[37.699,-3.097],[37.767,-3.677],[39.202,-4.677],[38.741,-5.909],[38.8,-6.476],[39.44,-6.84],[39.47,-7.1],[39.195,-7.704],[39.252,-8.008],[39.187,-8.486],[39.536,-9.112],[39.95,-10.098],[40.317,-10.317],[40.317,-10.317],[39.521,-10.897],[38.428,-11.285],[37.828,-11.269],[37.471,-11.569],[36.775,-11.595],[36.514,-11.721],[35.312,-11.439],[34.56,-11.52],[34.28,-10.16],[33.941,-9.694],[33.74,-9.417],[32.759,-9.231],[32.192,-8.93],[31.556,-8.762],[31.158,-8.595],[30.74,-8.34],[30.74,-8.34],[30.2,-7.08],[29.62,-6.52],[29.42,-5.94],[29.52,-5.42],[29.34,-4.5],[29.754,-4.452],[30.116,-4.09],[30.506,-3.569],[30.752,-3.359],[30.743,-3.034],[30.528,-2.808],[30.47,-2.414],[30.47,-2.414],[30.758,-2.287],[30.816,-1.699],[30.419,-1.135],[30.77,-1.015],[31.866,-1.027],[33.904,-0.95]]]],"translations":{"ar":"تنزانيا","bs":"Tanzanija","cs":"Tanzanie","de":"Tansania","es":"Tanzania","fa_IR":"تانزانیا","fr":"Tanzanie","id":"Tanzania","it":"Tanzania","ja":"タンザニア","pl":"Tanzania","pt_BR":"Tanzânia","pt_PT":"Tanzânia","ru":"Танзания","uk":"Танзанія","zh_CN":"坦桑尼亚","zh_TW":"坦尚尼亞"}},{"N":"Western Sahara","I":"EH","C":[[[[-8.666,27.656],[-8.665,27.589],[-8.684,27.396],[-8.687,25.881],[-11.969,25.933],[-11.937,23.375],[-12.874,23.285],[-13.119,22.771],[-12.929,21.327],[-16.845,21.333],[-17.063,21],[-17.02,21.422],[-17.003,21.421],[-14.751,21.501],[-14.631,21.861],[-14.221,22.31],[-13.891,23.691],[-12.501,24.77],[-12.031,26.031],[-11.718,26.104],[-11.393,26.883],[-10.551,26.991],[-10.189,26.861],[-9.735,26.861],[-9.413,27.088],[-8.795,27.121],[-8.818,27.656],[-8.666,27.656]]]],"translations":{"ar":"الصحراء الغربية","bs":"Zapadna Sahara","cs":"ZĂĄpadnĂ­ Sahara","de":"Westsahara","es":"SĂĄhara Occidental","fa_IR":"صحرای غربی","fr":"Sahara occidental","id":"Sahara Barat","it":"Sahara Occidentale","ja":"西サハラ","pl":"Sahara Zachodnia","pt_BR":"Saara Ocidental","pt_PT":"Sara Ocidental","ru":"Западная Сахара","uk":"Західна Сахара","zh_CN":"西撒哈拉","zh_TW":"西撒哈拉"}},{"N":"Canada","I":"CA","C":[[[[-122.84,49],[-122.974,49.003],[-124.91,49.985],[-125.625,50.417],[-127.436,50.831],[-127.993,51.716],[-127.85,52.33],[-129.13,52.755],[-129.305,53.562],[-130.515,54.288],[-130.536,54.803],[-130.536,54.803],[-129.98,55.285],[-130.008,55.916],[-131.708,56.552],[-132.73,57.693],[-133.356,58.41],[-134.271,58.861],[-134.945,59.271],[-135.476,59.788],[-136.48,59.464],[-137.452,58.905],[-138.341,59.562],[-139.039,60],[-140.013,60.277],[-140.998,60.306],[-140.993,66],[-140.986,69.712],[-140.986,69.712],[-139.121,69.471],[-137.546,68.99],[-136.504,68.898],[-135.626,69.315],[-134.415,69.627],[-132.929,69.505],[-131.431,69.945],[-129.795,70.194],[-129.108,69.779],[-128.362,70.013],[-128.138,70.484],[-127.447,70.377],[-125.756,69.481],[-124.425,70.158],[-124.29,69.4],[-123.061,69.564],[-122.683,69.856],[-121.472,69.798],[-119.943,69.378],[-117.603,69.011],[-116.226,68.842],[-115.247,68.906],[-113.898,68.399],[-115.305,67.903],[-113.497,67.688],[-110.798,67.806],[-109.946,67.981],[-108.88,67.381],[-107.792,67.887],[-108.813,68.312],[-108.167,68.654],[-106.95,68.7],[-106.15,68.8],[-105.343,68.561],[-104.338,68.018],[-103.221,68.098],[-101.454,67.647],[-99.902,67.806],[-98.443,67.782],[-98.559,68.404],[-97.669,68.579],[-96.12,68.239],[-96.126,67.293],[-95.489,68.091],[-94.685,68.064],[-94.233,69.069],[-95.304,69.686],[-96.471,70.09],[-96.391,71.195],[-95.209,71.921],[-93.89,71.76],[-92.878,71.319],[-91.52,70.191],[-92.407,69.7],[-90.547,69.498],[-90.552,68.475],[-89.215,69.259],[-88.02,68.615],[-88.317,67.873],[-87.35,67.199],[-86.306,67.921],[-85.577,68.785],[-85.522,69.882],[-84.101,69.805],[-82.623,69.658],[-81.28,69.162],[-81.22,68.666],[-81.964,68.133],[-81.259,67.597],[-81.387,67.111],[-83.345,66.412],[-84.735,66.257],[-85.769,66.558],[-86.068,66.056],[-87.031,65.213],[-87.323,64.776],[-88.483,64.099],[-89.914,64.033],[-90.704,63.61],[-90.77,62.96],[-91.933,62.835],[-93.157,62.025],[-94.242,60.899],[-94.629,60.11],[-94.685,58.949],[-93.215,58.782],[-92.765,57.846],[-92.297,57.087],[-90.898,57.285],[-89.04,56.852],[-88.04,56.472],[-87.324,55.999],[-86.071,55.724],[-85.012,55.303],[-83.361,55.245],[-82.273,55.148],[-82.436,54.282],[-82.125,53.277],[-81.401,52.158],[-79.913,51.208],[-79.143,51.534],[-78.602,52.562],[-79.124,54.141],[-79.83,54.668],[-78.229,55.136],[-77.096,55.837],[-76.541,56.534],[-76.623,57.203],[-77.302,58.052],[-78.517,58.805],[-77.337,59.853],[-77.773,60.758],[-78.107,62.32],[-77.411,62.551],[-75.696,62.278],[-74.668,62.181],[-73.84,62.444],[-72.909,62.105],[-71.677,61.525],[-71.374,61.137],[-69.59,61.061],[-69.62,60.221],[-69.288,58.957],[-68.375,58.801],[-67.65,58.212],[-66.202,58.767],[-65.245,59.871],[-64.584,60.336],[-63.805,59.443],[-62.502,58.167],[-61.397,56.967],[-61.799,56.339],[-60.469,55.775],[-59.57,55.204],[-57.975,54.945],[-57.333,54.627],[-56.937,53.78],[-56.158,53.647],[-55.756,53.27],[-55.683,52.147],[-56.409,51.771],[-57.127,51.42],[-58.775,51.064],[-60.033,50.243],[-61.724,50.08],[-63.863,50.291],[-65.363,50.298],[-66.399,50.229],[-67.236,49.512],[-68.511,49.068],[-69.954,47.745],[-71.105,46.822],[-70.255,46.986],[-68.65,48.3],[-66.552,49.133],[-65.056,49.233],[-64.171,48.742],[-65.115,48.071],[-64.799,46.993],[-64.472,46.238],[-63.173,45.739],[-61.521,45.884],[-60.518,47.008],[-60.449,46.283],[-59.803,45.92],[-61.04,45.265],[-63.255,44.67],[-64.247,44.266],[-65.364,43.545],[-66.123,43.619],[-66.162,44.465],[-64.425,45.292],[-66.026,45.259],[-67.137,45.138],[-67.791,45.703],[-67.79,47.066],[-68.234,47.355],[-68.905,47.185],[-69.237,47.448],[-70,46.693],[-70.305,45.915],[-70.66,45.46],[-71.085,45.305],[-71.405,45.255],[-71.505,45.008],[-73.348,45.007],[-74.867,45],[-75.318,44.816],[-76.375,44.096],[-76.5,44.018],[-76.82,43.629],[-77.738,43.629],[-78.72,43.625],[-79.172,43.466],[-79.01,43.27],[-78.92,42.965],[-78.939,42.864],[-80.247,42.366],[-81.278,42.209],[-82.439,41.675],[-82.69,41.675],[-83.03,41.833],[-83.142,41.976],[-83.12,42.08],[-82.9,42.43],[-82.43,42.98],[-82.138,43.571],[-82.338,44.44],[-82.551,45.348],[-83.593,45.817],[-83.47,45.995],[-83.616,46.117],[-83.891,46.117],[-84.092,46.275],[-84.142,46.512],[-84.337,46.409],[-84.605,46.44],[-84.544,46.539],[-84.779,46.637],[-84.876,46.9],[-85.652,47.22],[-86.462,47.553],[-87.44,47.94],[-88.378,48.303],[-89.273,48.02],[-89.6,48.01],[-90.83,48.27],[-91.64,48.14],[-92.61,48.45],[-93.631,48.609],[-94.329,48.671],[-94.64,48.84],[-94.818,49.389],[-95.156,49.384],[-95.159,49],[-97.229,49.001],[-100.65,49],[-104.048,49],[-107.05,49],[-110.05,49],[-113,49],[-116.048,49],[-117.031,49],[-120,49],[-122.84,49]]],[[[-83.994,62.453],[-83.25,62.914],[-81.877,62.905],[-81.898,62.711],[-83.069,62.159],[-83.775,62.182],[-83.994,62.453]]],[[[-79.776,72.803],[-80.876,73.333],[-80.834,73.693],[-80.353,73.76],[-78.064,73.652],[-76.34,73.103],[-76.251,72.826],[-77.314,72.856],[-78.392,72.877],[-79.486,72.742],[-79.776,72.803]]],[[[-80.315,62.086],[-79.929,62.386],[-79.52,62.364],[-79.266,62.159],[-79.658,61.633],[-80.1,61.718],[-80.362,62.016],[-80.315,62.086]]],[[[-93.613,74.98],[-94.157,74.592],[-95.609,74.667],[-96.821,74.928],[-96.289,75.378],[-94.851,75.647],[-93.978,75.296],[-93.613,74.98]]],[[[-93.84,77.52],[-94.296,77.491],[-96.17,77.555],[-96.436,77.835],[-94.423,77.82],[-93.721,77.634],[-93.84,77.52]]],[[[-96.754,78.766],[-95.559,78.418],[-95.83,78.057],[-97.31,77.851],[-98.124,78.083],[-98.553,78.458],[-98.632,78.872],[-97.337,78.832],[-96.754,78.766]]],[[[-88.15,74.392],[-89.765,74.516],[-92.422,74.838],[-92.768,75.387],[-92.89,75.883],[-93.894,76.319],[-95.962,76.441],[-97.121,76.751],[-96.745,77.161],[-94.684,77.098],[-93.574,76.776],[-91.605,76.779],[-90.742,76.45],[-90.97,76.074],[-89.822,75.848],[-89.187,75.61],[-87.838,75.566],[-86.379,75.482],[-84.79,75.699],[-82.753,75.784],[-81.129,75.714],[-80.058,75.337],[-79.834,74.923],[-80.458,74.657],[-81.949,74.442],[-83.229,74.564],[-86.097,74.41],[-88.15,74.392]]],[[[-111.264,78.153],[-109.854,77.996],[-110.187,77.697],[-112.051,77.409],[-113.534,77.732],[-112.725,78.051],[-111.264,78.153]]],[[[-110.964,78.804],[-109.663,78.602],[-110.881,78.407],[-112.542,78.408],[-112.526,78.551],[-111.5,78.85],[-110.964,78.804]]],[[[-55.6,51.317],[-56.134,50.687],[-56.796,49.812],[-56.143,50.15],[-55.471,49.936],[-55.822,49.587],[-54.935,49.313],[-54.474,49.557],[-53.477,49.249],[-53.786,48.517],[-53.086,48.688],[-52.959,48.157],[-52.648,47.536],[-53.069,46.655],[-53.521,46.618],[-54.179,46.807],[-53.962,47.625],[-54.24,47.752],[-55.401,46.885],[-55.997,46.92],[-55.291,47.39],[-56.251,47.633],[-57.325,47.573],[-59.266,47.603],[-59.419,47.899],[-58.797,48.252],[-59.232,48.523],[-58.392,49.126],[-57.359,50.718],[-56.739,51.287],[-55.871,51.632],[-55.407,51.588],[-55.6,51.317]]],[[[-83.883,65.11],[-82.788,64.767],[-81.642,64.455],[-81.553,63.98],[-80.817,64.057],[-80.103,63.726],[-80.991,63.411],[-82.547,63.652],[-83.109,64.102],[-84.1,63.57],[-85.523,63.052],[-85.867,63.637],[-87.222,63.541],[-86.353,64.036],[-86.225,64.823],[-85.884,65.739],[-85.161,65.657],[-84.976,65.218],[-84.464,65.372],[-83.883,65.11]]],[[[-78.771,72.352],[-77.825,72.75],[-75.606,72.244],[-74.229,71.767],[-74.099,71.331],[-72.242,71.557],[-71.2,70.92],[-68.786,70.525],[-67.915,70.122],[-66.969,69.186],[-68.805,68.72],[-66.45,68.067],[-64.862,67.848],[-63.425,66.928],[-61.852,66.862],[-62.163,66.16],[-63.918,64.999],[-65.149,65.426],[-66.721,66.388],[-68.015,66.263],[-68.141,65.69],[-67.09,65.108],[-65.732,64.648],[-65.32,64.383],[-64.669,63.393],[-65.014,62.674],[-66.275,62.945],[-68.783,63.746],[-67.37,62.884],[-66.328,62.28],[-66.166,61.931],[-68.877,62.33],[-71.023,62.911],[-72.235,63.398],[-71.886,63.68],[-73.378,64.194],[-74.834,64.679],[-74.819,64.389],[-77.71,64.23],[-78.556,64.573],[-77.897,65.309],[-76.018,65.327],[-73.96,65.455],[-74.294,65.812],[-73.945,66.311],[-72.651,67.285],[-72.926,67.727],[-73.312,68.069],[-74.843,68.555],[-76.869,68.895],[-76.229,69.148],[-77.287,69.77],[-78.169,69.826],[-78.957,70.167],[-79.492,69.872],[-81.305,69.743],[-84.945,69.967],[-87.06,70.26],[-88.682,70.411],[-89.513,70.762],[-88.468,71.218],[-89.888,71.223],[-90.205,72.235],[-89.437,73.129],[-88.408,73.538],[-85.826,73.804],[-86.562,73.157],[-85.774,72.534],[-84.85,73.34],[-82.316,73.751],[-80.6,72.717],[-80.749,72.062],[-78.771,72.352]]],[[[-94.504,74.135],[-92.42,74.1],[-90.51,73.857],[-92.004,72.966],[-93.196,72.772],[-94.269,72.025],[-95.41,72.062],[-96.034,72.94],[-96.018,73.437],[-95.496,73.862],[-94.504,74.135]]],[[[-122.855,76.117],[-122.855,76.117],[-121.158,76.865],[-119.104,77.512],[-117.57,77.498],[-116.199,77.645],[-116.336,76.877],[-117.106,76.53],[-118.04,76.481],[-119.899,76.053],[-121.5,75.9],[-122.855,76.117]]],[[[-132.71,54.04],[-131.75,54.12],[-132.049,52.985],[-131.179,52.18],[-131.578,52.182],[-132.18,52.64],[-132.55,53.1],[-133.055,53.411],[-133.24,53.851],[-133.18,54.17],[-132.71,54.04]]],[[[-105.492,79.302],[-103.529,79.165],[-100.825,78.8],[-100.06,78.325],[-99.671,77.908],[-101.304,78.019],[-102.95,78.343],[-105.176,78.38],[-104.21,78.677],[-105.42,78.918],[-105.492,79.302]]],[[[-123.51,48.51],[-124.013,48.371],[-125.655,48.825],[-125.955,49.18],[-126.85,49.53],[-127.03,49.815],[-128.059,49.995],[-128.445,50.539],[-128.358,50.771],[-127.309,50.553],[-126.695,50.401],[-125.755,50.295],[-125.415,49.95],[-124.921,49.475],[-123.923,49.062],[-123.51,48.51]]],[[[-121.538,74.449],[-120.11,74.241],[-117.556,74.186],[-116.584,73.896],[-115.511,73.475],[-116.768,73.223],[-119.22,72.52],[-120.46,71.82],[-120.46,71.384],[-123.092,70.902],[-123.62,71.34],[-125.929,71.869],[-125.5,72.292],[-124.807,73.023],[-123.94,73.68],[-124.918,74.293],[-121.538,74.449]]],[[[-107.819,75.846],[-106.929,76.013],[-105.881,75.969],[-105.705,75.48],[-106.313,75.005],[-109.7,74.85],[-112.223,74.417],[-113.744,74.394],[-113.871,74.72],[-111.794,75.162],[-116.312,75.043],[-117.71,75.222],[-116.346,76.199],[-115.405,76.479],[-112.591,76.141],[-110.814,75.549],[-109.067,75.473],[-110.497,76.43],[-109.581,76.794],[-108.549,76.678],[-108.211,76.202],[-107.819,75.846]]],[[[-106.523,73.076],[-105.402,72.673],[-104.775,71.698],[-104.465,70.993],[-102.785,70.498],[-100.981,70.024],[-101.089,69.584],[-102.731,69.504],[-102.093,69.12],[-102.43,68.753],[-104.24,68.91],[-105.96,69.18],[-107.123,69.119],[-109,68.78],[-111.534,68.63],[-113.313,68.536],[-113.855,69.007],[-115.22,69.28],[-116.108,69.168],[-117.34,69.96],[-116.675,70.067],[-115.131,70.237],[-113.721,70.192],[-112.416,70.366],[-114.35,70.6],[-116.487,70.52],[-117.905,70.541],[-118.432,70.909],[-116.113,71.309],[-117.656,71.295],[-119.402,71.559],[-118.563,72.308],[-117.866,72.706],[-115.189,73.315],[-114.167,73.121],[-114.666,72.653],[-112.441,72.955],[-111.05,72.45],[-109.92,72.961],[-109.007,72.633],[-108.188,71.651],[-107.686,72.065],[-108.396,73.09],[-107.516,73.236],[-106.523,73.076]]],[[[-100.438,72.706],[-101.54,73.36],[-100.356,73.844],[-99.164,73.633],[-97.38,73.76],[-97.12,73.47],[-98.054,72.991],[-96.54,72.56],[-96.72,71.66],[-98.36,71.273],[-99.323,71.356],[-100.015,71.738],[-102.5,72.51],[-102.48,72.83],[-100.438,72.706]]],[[[-106.6,73.6],[-105.26,73.64],[-104.5,73.42],[-105.38,72.76],[-106.94,73.46],[-106.6,73.6]]],[[[-98.5,76.72],[-97.736,76.257],[-97.704,75.743],[-98.16,75],[-99.809,74.897],[-100.884,75.057],[-100.863,75.641],[-102.502,75.564],[-102.566,76.337],[-101.49,76.305],[-99.983,76.646],[-98.577,76.589],[-98.5,76.72]]],[[[-96.016,80.602],[-95.323,80.907],[-94.298,80.977],[-94.735,81.206],[-92.41,81.257],[-91.133,80.723],[-89.45,80.509],[-87.81,80.32],[-87.02,79.66],[-85.814,79.337],[-87.188,79.039],[-89.035,78.287],[-90.804,78.215],[-92.877,78.343],[-93.951,78.751],[-93.936,79.114],[-93.145,79.38],[-94.974,79.372],[-96.076,79.705],[-96.71,80.158],[-96.016,80.602]]],[[[-91.587,81.894],[-90.1,82.085],[-88.932,82.118],[-86.97,82.28],[-85.5,82.652],[-84.26,82.6],[-83.18,82.32],[-82.42,82.86],[-81.1,83.02],[-79.307,83.131],[-76.25,83.172],[-75.719,83.064],[-72.832,83.233],[-70.666,83.17],[-68.5,83.106],[-65.827,83.028],[-63.68,82.9],[-61.85,82.629],[-61.894,82.362],[-64.334,81.928],[-66.753,81.725],[-67.658,81.501],[-65.48,81.507],[-67.84,80.9],[-69.47,80.617],[-71.18,79.8],[-73.243,79.634],[-73.88,79.43],[-76.908,79.323],[-75.529,79.198],[-76.22,79.019],[-75.393,78.526],[-76.344,78.183],[-77.889,77.9],[-78.363,77.509],[-79.76,77.21],[-79.62,76.983],[-77.911,77.022],[-77.889,76.778],[-80.561,76.178],[-83.174,76.454],[-86.112,76.299],[-87.6,76.42],[-89.491,76.472],[-89.616,76.952],[-87.767,77.178],[-88.26,77.9],[-87.65,77.97],[-84.976,77.539],[-86.34,78.18],[-87.962,78.372],[-87.152,78.759],[-85.379,78.997],[-85.095,79.345],[-86.507,79.736],[-86.932,80.251],[-84.198,80.208],[-83.409,80.1],[-81.848,80.464],[-84.1,80.58],[-87.599,80.516],[-89.367,80.856],[-90.2,81.26],[-91.368,81.553],[-91.587,81.894]]],[[[-75.216,67.444],[-75.866,67.149],[-76.987,67.099],[-77.236,67.588],[-76.812,68.149],[-75.895,68.287],[-75.115,68.01],[-75.103,67.582],[-75.216,67.444]]],[[[-96.257,69.49],[-95.648,69.108],[-96.27,68.757],[-97.617,69.06],[-98.432,68.951],[-99.797,69.4],[-98.917,69.71],[-98.218,70.144],[-97.157,69.86],[-96.557,69.68],[-96.257,69.49]]],[[[-64.519,49.873],[-64.173,49.957],[-62.858,49.706],[-61.836,49.289],[-61.806,49.105],[-62.293,49.087],[-63.589,49.401],[-64.519,49.873]]],[[[-64.015,47.036],[-63.664,46.55],[-62.939,46.416],[-62.012,46.443],[-62.504,46.033],[-62.874,45.968],[-64.143,46.393],[-64.393,46.727],[-64.015,47.036]]]],"translations":{"ar":"كندا","bs":"Kanada","cs":"Kanada","de":"Kanada","es":"CanadĂĄ","fa_IR":"کانادا","fr":"Canada","id":"Kanada","it":"Canada","ja":"カナダ","pl":"Kanada","pt_BR":"CanadĂĄ","pt_PT":"CanadĂĄ","ru":"Канада","uk":"Канада","zh_CN":"加拿大","zh_TW":"加拿大"}},{"N":"United States","I":"US","C":[[[[-155.402,20.08],[-155.225,19.993],[-155.062,19.859],[-154.807,19.509],[-154.831,19.453],[-155.222,19.24],[-155.542,19.083],[-155.688,18.916],[-155.937,19.059],[-155.908,19.339],[-156.073,19.703],[-156.024,19.814],[-155.85,19.977],[-155.919,20.174],[-155.861,20.267],[-155.785,20.249],[-155.402,20.08]]],[[[-155.996,20.764],[-156.079,20.644],[-156.414,20.572],[-156.587,20.783],[-156.702,20.864],[-156.711,20.927],[-156.613,21.012],[-156.257,20.917],[-155.996,20.764]]],[[[-156.758,21.177],[-156.789,21.069],[-157.325,21.098],[-157.25,21.22],[-156.758,21.177]]],[[[-158.025,21.717],[-157.942,21.653],[-157.653,21.322],[-157.707,21.264],[-157.779,21.277],[-158.127,21.312],[-158.254,21.539],[-158.293,21.579],[-158.025,21.717]]],[[[-159.366,22.215],[-159.345,21.982],[-159.464,21.883],[-159.801,22.065],[-159.749,22.138],[-159.596,22.236],[-159.366,22.215]]],[[[-166.468,60.384],[-165.674,60.294],[-165.579,59.91],[-166.193,59.754],[-166.848,59.941],[-167.455,60.213],[-166.468,60.384]]],[[[-153.229,57.969],[-152.565,57.901],[-152.141,57.591],[-153.006,57.116],[-154.005,56.735],[-154.516,56.993],[-154.671,57.461],[-153.763,57.817],[-153.229,57.969]]],[[[-140.986,69.712],[-140.986,69.712],[-140.993,66],[-140.998,60.306],[-140.013,60.277],[-139.039,60],[-138.341,59.562],[-137.452,58.905],[-136.48,59.464],[-135.476,59.788],[-134.945,59.271],[-134.271,58.861],[-133.356,58.41],[-132.73,57.693],[-131.708,56.552],[-130.008,55.916],[-129.98,55.285],[-130.536,54.803],[-130.536,54.803],[-130.536,54.803],[-131.086,55.179],[-131.967,55.498],[-132.25,56.37],[-133.539,57.179],[-134.078,58.123],[-135.038,58.188],[-136.628,58.212],[-137.8,58.5],[-139.868,59.538],[-140.825,59.728],[-142.574,60.084],[-143.959,59.999],[-145.926,60.459],[-147.114,60.885],[-148.224,60.673],[-148.018,59.978],[-148.571,59.914],[-149.728,59.706],[-150.608,59.368],[-151.716,59.156],[-151.859,59.745],[-151.41,60.726],[-150.347,61.034],[-150.621,61.284],[-151.896,60.727],[-152.578,60.062],[-154.019,59.35],[-153.288,58.865],[-154.232,58.146],[-155.307,57.728],[-156.308,57.423],[-156.556,56.98],[-158.117,56.464],[-158.433,55.994],[-159.603,55.567],[-160.29,55.644],[-161.223,55.365],[-162.238,55.024],[-163.069,54.69],[-164.786,54.404],[-164.942,54.572],[-163.848,55.039],[-162.87,55.348],[-161.804,55.895],[-160.564,56.008],[-160.071,56.418],[-158.684,57.017],[-158.461,57.217],[-157.723,57.57],[-157.55,58.328],[-157.042,58.919],[-158.195,58.616],[-158.517,58.788],[-159.059,58.424],[-159.712,58.931],[-159.981,58.573],[-160.355,59.071],[-161.355,58.671],[-161.969,58.672],[-162.055,59.267],[-161.874,59.634],[-162.518,59.99],[-163.818,59.798],[-164.662,60.267],[-165.346,60.507],[-165.351,61.074],[-166.121,61.5],[-165.734,62.075],[-164.919,62.633],[-164.563,63.146],[-163.753,63.219],[-163.067,63.059],[-162.261,63.542],[-161.534,63.456],[-160.773,63.766],[-160.958,64.223],[-161.518,64.403],[-160.778,64.789],[-161.392,64.777],[-162.453,64.559],[-162.758,64.339],[-163.546,64.559],[-164.961,64.447],[-166.425,64.687],[-166.845,65.089],[-168.111,65.67],[-166.705,66.088],[-164.475,66.577],[-163.653,66.577],[-163.789,66.077],[-161.678,66.116],[-162.49,66.736],[-163.72,67.116],[-164.431,67.616],[-165.39,68.043],[-166.764,68.359],[-166.205,68.883],[-164.431,68.916],[-163.169,69.371],[-162.931,69.858],[-161.909,70.333],[-160.935,70.448],[-159.039,70.892],[-158.12,70.825],[-156.581,71.358],[-155.068,71.148],[-154.344,70.696],[-153.9,70.89],[-152.21,70.83],[-152.27,70.6],[-150.74,70.43],[-149.72,70.53],[-147.613,70.214],[-145.69,70.12],[-144.92,69.99],[-143.589,70.153],[-142.073,69.852],[-140.986,69.712],[-140.986,69.712]]],[[[-171.732,63.783],[-171.114,63.592],[-170.491,63.695],[-169.683,63.431],[-168.689,63.298],[-168.772,63.189],[-169.529,62.977],[-170.291,63.194],[-170.671,63.376],[-171.553,63.318],[-171.791,63.406],[-171.732,63.783]]],[[[-122.84,49],[-120,49],[-117.031,49],[-116.048,49],[-113,49],[-110.05,49],[-107.05,49],[-104.048,49],[-100.65,49],[-97.229,49.001],[-95.159,49],[-95.156,49.384],[-94.818,49.389],[-94.64,48.84],[-94.329,48.671],[-93.631,48.609],[-92.61,48.45],[-91.64,48.14],[-90.83,48.27],[-89.6,48.01],[-89.273,48.02],[-88.378,48.303],[-87.44,47.94],[-86.462,47.553],[-85.652,47.22],[-84.876,46.9],[-84.779,46.637],[-84.544,46.539],[-84.605,46.44],[-84.337,46.409],[-84.142,46.512],[-84.092,46.275],[-83.891,46.117],[-83.616,46.117],[-83.47,45.995],[-83.593,45.817],[-82.551,45.348],[-82.338,44.44],[-82.138,43.571],[-82.43,42.98],[-82.9,42.43],[-83.12,42.08],[-83.142,41.976],[-83.03,41.833],[-82.69,41.675],[-82.439,41.675],[-81.278,42.209],[-80.247,42.366],[-78.939,42.864],[-78.92,42.965],[-79.01,43.27],[-79.172,43.466],[-78.72,43.625],[-77.738,43.629],[-76.82,43.629],[-76.5,44.018],[-76.375,44.096],[-75.318,44.816],[-74.867,45],[-73.348,45.007],[-71.505,45.008],[-71.405,45.255],[-71.085,45.305],[-70.66,45.46],[-70.305,45.915],[-70,46.693],[-69.237,47.448],[-68.905,47.185],[-68.234,47.355],[-67.79,47.066],[-67.791,45.703],[-67.137,45.138],[-66.965,44.81],[-68.033,44.325],[-69.06,43.98],[-70.116,43.684],[-70.645,43.09],[-70.815,42.865],[-70.825,42.335],[-70.495,41.805],[-70.08,41.78],[-70.185,42.145],[-69.885,41.923],[-69.965,41.637],[-70.64,41.475],[-71.12,41.494],[-71.86,41.32],[-72.295,41.27],[-72.876,41.221],[-73.71,40.931],[-72.241,41.119],[-71.945,40.93],[-73.345,40.63],[-73.982,40.628],[-73.952,40.751],[-74.257,40.474],[-73.962,40.428],[-74.178,39.709],[-74.906,38.94],[-74.98,39.196],[-75.2,39.248],[-75.528,39.498],[-75.32,38.96],[-75.072,38.782],[-75.057,38.404],[-75.377,38.016],[-75.94,37.217],[-76.031,37.257],[-75.722,37.937],[-76.233,38.319],[-76.35,39.15],[-76.543,38.718],[-76.329,38.083],[-76.99,38.24],[-76.302,37.918],[-76.259,36.966],[-75.972,36.897],[-75.868,36.551],[-75.727,35.551],[-76.363,34.809],[-77.398,34.512],[-78.055,33.925],[-78.554,33.861],[-79.061,33.494],[-79.204,33.158],[-80.301,32.509],[-80.865,32.033],[-81.336,31.44],[-81.49,30.73],[-81.314,30.036],[-80.98,29.18],[-80.536,28.472],[-80.53,28.04],[-80.057,26.88],[-80.088,26.206],[-80.132,25.817],[-80.381,25.206],[-80.68,25.08],[-81.172,25.201],[-81.33,25.64],[-81.71,25.87],[-82.24,26.73],[-82.705,27.495],[-82.855,27.886],[-82.65,28.55],[-82.93,29.1],[-83.71,29.937],[-84.1,30.09],[-85.109,29.636],[-85.288,29.686],[-85.773,30.153],[-86.4,30.4],[-87.53,30.274],[-88.418,30.385],[-89.18,30.316],[-89.594,30.16],[-89.414,29.894],[-89.43,29.489],[-89.218,29.291],[-89.408,29.16],[-89.779,29.307],[-90.155,29.117],[-90.88,29.149],[-91.627,29.677],[-92.499,29.552],[-93.226,29.784],[-93.848,29.714],[-94.69,29.48],[-95.6,28.739],[-96.594,28.307],[-97.14,27.83],[-97.37,27.38],[-97.38,26.69],[-97.33,26.21],[-97.14,25.87],[-97.53,25.84],[-98.24,26.06],[-99.02,26.37],[-99.3,26.84],[-99.52,27.54],[-100.11,28.11],[-100.456,28.696],[-100.958,29.381],[-101.662,29.779],[-102.48,29.76],[-103.11,28.97],[-103.94,29.27],[-104.457,29.572],[-104.706,30.122],[-105.037,30.644],[-105.632,31.084],[-106.143,31.4],[-106.508,31.755],[-108.24,31.755],[-108.242,31.342],[-109.035,31.342],[-111.024,31.335],[-113.305,32.039],[-114.815,32.525],[-114.721,32.721],[-115.991,32.612],[-117.128,32.535],[-117.296,33.046],[-117.944,33.621],[-118.411,33.741],[-118.52,34.028],[-119.081,34.078],[-119.439,34.348],[-120.368,34.447],[-120.623,34.609],[-120.744,35.157],[-121.715,36.162],[-122.547,37.552],[-122.512,37.783],[-122.953,38.114],[-123.727,38.952],[-123.865,39.767],[-124.398,40.313],[-124.179,41.142],[-124.214,42],[-124.533,42.766],[-124.142,43.708],[-124.021,44.616],[-123.899,45.523],[-124.08,46.865],[-124.396,47.72],[-124.687,48.184],[-124.566,48.38],[-123.12,48.04],[-122.587,47.096],[-122.34,47.36],[-122.5,48.18],[-122.84,49]]]],"translations":{"ar":"الولايات المتحدة","bs":"Sjedinjene DrĹžave","cs":"SpojenĂŠ stĂĄty","de":"Vereinigte Staaten","es":"Estados Unidos","fa_IR":"ایالات متحده","fr":"États-Unis","id":"Amerika Serikat","it":"Stati Uniti","ja":"アメリカ合衆国","pl":"Stany Zjednoczone","pt_BR":"Estados Unidos","pt_PT":"Estados Unidos","ru":"Соединенные Штаты","uk":"Сполучені Штати","zh_CN":"美国","zh_TW":"美國"}},{"N":"Kazakhstan","I":"KZ","C":[[[[87.36,49.215],[86.599,48.549],[85.768,48.456],[85.72,47.453],[85.164,47.001],[83.18,47.33],[82.459,45.54],[81.947,45.317],[79.966,44.918],[80.866,43.18],[80.18,42.92],[80.26,42.35],[79.644,42.497],[79.142,42.856],[77.658,42.961],[76,42.988],[75.637,42.878],[74.213,43.298],[73.645,43.091],[73.49,42.501],[71.845,42.845],[71.186,42.704],[70.962,42.266],[70.389,42.081],[69.07,41.384],[68.632,40.669],[68.26,40.662],[67.986,41.136],[66.714,41.168],[66.511,41.988],[66.023,41.995],[66.098,42.998],[64.901,43.728],[63.186,43.65],[62.013,43.504],[61.058,44.406],[60.24,44.784],[58.69,45.5],[58.503,45.587],[55.929,44.996],[55.968,41.309],[55.455,41.26],[54.755,42.044],[54.079,42.324],[52.944,42.116],[52.502,41.783],[52.446,42.027],[52.692,42.444],[52.501,42.792],[51.342,43.133],[50.891,44.031],[50.339,44.284],[50.306,44.61],[51.279,44.515],[51.317,45.246],[52.167,45.408],[53.041,45.259],[53.221,46.235],[53.043,46.853],[52.042,46.805],[51.192,47.049],[50.034,46.609],[49.101,46.399],[48.593,46.561],[48.695,47.076],[48.057,47.744],[47.315,47.716],[46.466,48.394],[47.044,49.152],[46.752,49.356],[47.549,50.455],[48.578,49.875],[48.702,50.605],[50.767,51.693],[52.329,51.719],[54.533,51.026],[55.717,50.622],[56.778,51.044],[58.363,51.064],[59.642,50.545],[59.933,50.842],[61.337,50.799],[61.588,51.273],[59.968,51.96],[60.927,52.448],[60.74,52.72],[61.7,52.98],[60.978,53.665],[61.437,54.006],[65.179,54.354],[65.667,54.601],[68.169,54.97],[69.068,55.385],[70.865,55.17],[71.18,54.133],[72.224,54.377],[73.509,54.036],[73.426,53.49],[74.385,53.547],[76.891,54.491],[76.525,54.177],[77.801,53.404],[80.036,50.865],[80.568,51.388],[81.946,50.812],[83.383,51.069],[83.935,50.889],[84.416,50.311],[85.116,50.117],[85.541,49.693],[86.829,49.827],[87.36,49.215]]]],"translations":{"ar":"كازاخستان","bs":"Kazahstan","cs":"KazachstĂĄn","de":"Kasachstan","es":"KazajistĂĄn","fa_IR":"قزاقستان","fr":"Kazakhstan","id":"Kazakhstan","it":"Kazakistan","ja":"カザフスタン","pl":"Kazachstan","pt_BR":"CazaquistĂŁo","pt_PT":"CazaquistĂŁo","ru":"Казахстан","uk":"Казахстан","zh_CN":"哈萨克斯坦","zh_TW":"哈薩克"}},{"N":"Uzbekistan","I":"UZ","C":[[[[55.968,41.309],[55.929,44.996],[58.503,45.587],[58.69,45.5],[60.24,44.784],[61.058,44.406],[62.013,43.504],[63.186,43.65],[64.901,43.728],[66.098,42.998],[66.023,41.995],[66.511,41.988],[66.714,41.168],[67.986,41.136],[68.26,40.662],[68.632,40.669],[69.07,41.384],[70.389,42.081],[70.962,42.266],[71.259,42.168],[70.42,41.52],[71.158,41.144],[71.87,41.393],[73.055,40.866],[71.775,40.146],[71.014,40.244],[70.601,40.219],[70.458,40.496],[70.667,40.96],[69.329,40.728],[69.012,40.086],[68.536,39.533],[67.701,39.58],[67.442,39.14],[68.176,38.902],[68.392,38.157],[67.83,37.145],[67.076,37.356],[66.519,37.363],[66.546,37.975],[65.216,38.403],[64.17,38.892],[63.518,39.363],[62.374,40.054],[61.883,41.085],[61.547,41.266],[60.466,41.22],[60.083,41.425],[59.976,42.223],[58.629,42.752],[57.787,42.171],[56.932,41.826],[57.096,41.322],[55.968,41.309]]]],"translations":{"ar":"أوزبكستان","bs":"Uzbekistan","cs":"UzbekistĂĄn","de":"Usbekistan","es":"UzbekistĂĄn","fa_IR":"ازبکستان","fr":"OuzbĂŠkistan","id":"Uzbekistan","it":"Uzbekistan","ja":"ウズベキスタン","pl":"Uzbekistan","pt_BR":"UzbequistĂŁo","pt_PT":"UsbequistĂŁo","ru":"Узбекистан","uk":"Узбекистан","zh_CN":"乌兹别克斯坦","zh_TW":"烏茲別克"}},{"N":"Papua New Guinea","I":"PG","C":[[[[141,-2.6],[142.735,-3.289],[144.584,-3.861],[145.273,-4.374],[145.83,-4.876],[145.982,-5.466],[147.648,-6.084],[147.891,-6.614],[146.971,-6.722],[147.192,-7.388],[148.085,-8.044],[148.734,-9.105],[149.307,-9.071],[149.267,-9.514],[150.039,-9.684],[149.739,-9.873],[150.802,-10.294],[150.691,-10.583],[150.028,-10.652],[149.782,-10.393],[148.923,-10.281],[147.913,-10.13],[147.135,-9.492],[146.568,-8.943],[146.048,-8.067],[144.744,-7.63],[143.897,-7.915],[143.286,-8.245],[143.414,-8.983],[142.628,-9.327],[142.068,-9.16],[141.034,-9.118],[141.017,-5.859],[141,-2.6]]],[[[152.64,-3.66],[153.02,-3.98],[153.14,-4.5],[152.827,-4.766],[152.639,-4.176],[152.406,-3.79],[151.953,-3.462],[151.384,-3.035],[150.662,-2.741],[150.94,-2.5],[151.48,-2.78],[151.82,-3],[152.24,-3.24],[152.64,-3.66]]],[[[151.301,-5.841],[150.754,-6.084],[150.241,-6.318],[149.71,-6.317],[148.89,-6.026],[148.319,-5.747],[148.402,-5.438],[149.298,-5.584],[149.846,-5.506],[149.996,-5.026],[150.14,-5.001],[150.237,-5.532],[150.807,-5.456],[151.09,-5.114],[151.648,-4.757],[151.538,-4.168],[152.137,-4.149],[152.339,-4.313],[152.319,-4.868],[151.983,-5.478],[151.459,-5.56],[151.301,-5.841]]],[[[154.76,-5.34],[155.063,-5.567],[155.548,-6.201],[156.02,-6.54],[155.88,-6.82],[155.6,-6.92],[155.167,-6.536],[154.729,-5.901],[154.514,-5.139],[154.653,-5.042],[154.76,-5.34]]]],"translations":{"ar":"بابوا غينيا الجديدة","bs":"Papua Nova Gvineja","cs":"Papua-NovĂĄ Guinea","de":"Papua-Neuguinea","es":"PapĂşa Nueva Guinea","fa_IR":"ٞاٞوا گینهٔ نو","fr":"Papouasie-Nouvelle-GuinĂŠe","id":"Papua Nugini","it":"Papua Nuova Guinea","ja":"パプアニューギニア","pl":"Papua-Nowa Gwinea","pt_BR":"Papua-Nova GuinĂŠ","pt_PT":"Papua-Nova GuinĂŠ","ru":"Папуа — Новая Гвинея","uk":"Папуа-Нова Гвінея","zh_CN":"巴布亚新几内亚","zh_TW":"巴布亞紐幾內亞"}},{"N":"Indonesia","I":"ID","C":[[[[141,-2.6],[141.017,-5.859],[141.034,-9.118],[140.143,-8.297],[139.128,-8.096],[138.881,-8.381],[137.614,-8.412],[138.039,-7.598],[138.669,-7.32],[138.408,-6.233],[137.928,-5.393],[135.989,-4.547],[135.165,-4.463],[133.663,-3.539],[133.368,-4.025],[132.984,-4.113],[132.757,-3.746],[132.754,-3.312],[131.99,-2.821],[133.067,-2.46],[133.78,-2.48],[133.696,-2.215],[132.232,-2.213],[131.836,-1.617],[130.943,-1.433],[130.52,-0.938],[131.868,-0.695],[132.38,-0.37],[133.986,-0.78],[134.143,-1.152],[134.423,-2.769],[135.458,-3.368],[136.293,-2.307],[137.441,-1.704],[138.33,-1.703],[139.185,-2.051],[139.927,-2.409],[141,-2.6]]],[[[124.969,-8.893],[125.07,-9.09],[125.089,-9.393],[124.436,-10.14],[123.58,-10.36],[123.46,-10.24],[123.55,-9.9],[123.98,-9.29],[124.969,-8.893]]],[[[134.21,-6.895],[134.113,-6.142],[134.29,-5.783],[134.5,-5.445],[134.727,-5.738],[134.725,-6.214],[134.21,-6.895]]],[[[117.882,4.138],[117.313,3.234],[118.048,2.288],[117.876,1.828],[118.997,0.902],[117.812,0.784],[117.478,0.102],[117.522,-0.804],[116.56,-1.488],[116.534,-2.484],[116.148,-4.013],[116.001,-3.657],[114.865,-4.107],[114.469,-3.496],[113.756,-3.439],[113.257,-3.119],[112.068,-3.478],[111.703,-2.994],[111.048,-3.049],[110.224,-2.934],[110.071,-1.593],[109.572,-1.315],[109.092,-0.46],[108.953,0.415],[109.069,1.342],[109.663,2.006],[109.83,1.338],[110.514,0.773],[111.159,0.976],[111.798,0.904],[112.38,1.41],[112.86,1.498],[113.806,1.218],[114.621,1.431],[115.134,2.821],[115.519,3.169],[115.866,4.307],[117.015,4.306],[117.882,4.138]]],[[[129.371,-2.802],[130.471,-3.094],[130.835,-3.858],[129.991,-3.446],[129.155,-3.363],[128.591,-3.429],[127.899,-3.393],[128.136,-2.844],[129.371,-2.802]]],[[[126.875,-3.791],[126.184,-3.607],[125.989,-3.177],[127.001,-3.129],[127.249,-3.459],[126.875,-3.791]]],[[[127.932,2.175],[128.004,1.629],[128.595,1.541],[128.688,1.132],[128.636,0.258],[128.12,0.356],[127.968,-0.252],[128.38,-0.78],[128.1,-0.9],[127.696,-0.267],[127.399,1.012],[127.601,1.811],[127.932,2.175]]],[[[122.928,0.875],[124.078,0.917],[125.066,1.643],[125.241,1.42],[124.437,0.428],[123.686,0.236],[122.723,0.431],[121.057,0.381],[120.183,0.237],[120.041,-0.52],[120.936,-1.409],[121.476,-0.956],[123.341,-0.616],[123.258,-1.076],[122.823,-0.931],[122.389,-1.517],[121.508,-1.904],[122.455,-3.186],[122.272,-3.53],[123.171,-4.684],[123.162,-5.341],[122.629,-5.635],[122.236,-5.283],[122.72,-4.464],[121.738,-4.851],[121.489,-4.575],[121.619,-4.188],[120.898,-3.602],[120.972,-2.628],[120.305,-2.932],[120.39,-4.098],[120.431,-5.528],[119.797,-5.673],[119.367,-5.38],[119.654,-4.459],[119.499,-3.494],[119.078,-3.487],[118.768,-2.802],[119.181,-2.147],[119.323,-1.353],[119.826,0.154],[120.036,0.566],[120.886,1.309],[121.667,1.014],[122.928,0.875]]],[[[120.295,-10.259],[118.968,-9.558],[119.9,-9.361],[120.426,-9.666],[120.776,-9.97],[120.716,-10.24],[120.295,-10.259]]],[[[121.342,-8.537],[122.007,-8.461],[122.904,-8.094],[122.757,-8.65],[121.254,-8.934],[119.924,-8.81],[119.921,-8.445],[120.715,-8.237],[121.342,-8.537]]],[[[118.261,-8.362],[118.878,-8.281],[119.127,-8.706],[117.97,-8.907],[117.278,-9.041],[116.74,-9.033],[117.084,-8.457],[117.632,-8.449],[117.9,-8.096],[118.261,-8.362]]],[[[108.487,-6.422],[108.623,-6.778],[110.539,-6.877],[110.76,-6.465],[112.615,-6.946],[112.979,-7.594],[114.479,-7.777],[115.706,-8.371],[114.565,-8.752],[113.465,-8.349],[112.56,-8.376],[111.522,-8.302],[110.586,-8.123],[109.428,-7.741],[108.694,-7.642],[108.278,-7.767],[106.454,-7.355],[106.281,-6.925],[105.365,-6.851],[106.052,-5.896],[107.265,-5.955],[108.072,-6.346],[108.487,-6.422]]],[[[104.37,-1.085],[104.539,-1.782],[104.888,-2.34],[105.622,-2.429],[106.109,-3.062],[105.857,-4.306],[105.818,-5.852],[104.71,-5.873],[103.868,-5.037],[102.584,-4.22],[102.156,-3.614],[101.399,-2.8],[100.903,-2.05],[100.142,-0.65],[99.264,0.183],[98.97,1.043],[98.601,1.824],[97.7,2.453],[97.177,3.309],[96.424,3.869],[95.381,4.971],[95.293,5.48],[95.937,5.44],[97.485,5.246],[98.369,4.268],[99.143,3.59],[99.694,3.174],[100.641,2.099],[101.658,2.084],[102.498,1.399],[103.077,0.561],[103.838,0.105],[103.438,-0.712],[104.011,-1.059],[104.37,-1.085]]]],"translations":{"ar":"إندونيسيا","bs":"Indonezija","cs":"IndonĂŠsie","de":"Indonesien","es":"Indonesia","fa_IR":"اندونزی","fr":"IndonĂŠsie","id":"Indonesia","it":"Indonesia","ja":"インドネシア","pl":"Indonezja","pt_BR":"IndonĂŠsia","pt_PT":"IndonĂŠsia","ru":"Индонезия","uk":"Індонезія","zh_CN":"印度尼西亚","zh_TW":"印尼"}},{"N":"Argentina","I":"AR","C":[[[[-68.634,-52.636],[-68.25,-53.1],[-67.75,-53.85],[-66.45,-54.45],[-65.05,-54.7],[-65.5,-55.2],[-66.45,-55.25],[-66.96,-54.897],[-67.562,-54.87],[-68.633,-54.87],[-68.634,-52.636]]],[[[-57.625,-30.216],[-57.875,-31.017],[-58.142,-32.045],[-58.133,-33.041],[-58.35,-33.263],[-58.427,-33.909],[-58.495,-34.431],[-57.226,-35.288],[-57.362,-35.977],[-56.737,-36.413],[-56.788,-36.902],[-57.749,-38.184],[-59.232,-38.72],[-61.237,-38.928],[-62.336,-38.828],[-62.126,-39.424],[-62.331,-40.173],[-62.146,-40.677],[-62.746,-41.029],[-63.77,-41.167],[-64.732,-40.803],[-65.118,-41.064],[-64.979,-42.058],[-64.303,-42.359],[-63.756,-42.044],[-63.458,-42.563],[-64.379,-42.874],[-65.182,-43.495],[-65.329,-44.501],[-65.565,-45.037],[-66.51,-45.04],[-67.294,-45.552],[-67.581,-46.302],[-66.597,-47.034],[-65.641,-47.236],[-65.985,-48.133],[-67.166,-48.697],[-67.816,-49.87],[-68.729,-50.264],[-69.139,-50.733],[-68.816,-51.771],[-68.15,-52.35],[-68.572,-52.299],[-69.498,-52.143],[-71.915,-52.009],[-72.329,-51.426],[-72.31,-50.677],[-72.976,-50.741],[-73.328,-50.379],[-73.415,-49.318],[-72.648,-48.879],[-72.331,-48.244],[-72.447,-47.739],[-71.917,-46.885],[-71.552,-45.561],[-71.659,-44.974],[-71.223,-44.784],[-71.33,-44.408],[-71.794,-44.207],[-71.464,-43.788],[-71.915,-43.409],[-72.149,-42.255],[-71.747,-42.051],[-71.916,-40.832],[-71.681,-39.808],[-71.414,-38.916],[-70.815,-38.553],[-71.119,-37.577],[-71.122,-36.658],[-70.365,-36.005],[-70.388,-35.17],[-69.817,-34.194],[-69.815,-33.274],[-70.074,-33.091],[-70.535,-31.365],[-69.919,-30.336],[-70.014,-29.368],[-69.656,-28.459],[-69.001,-27.521],[-68.296,-26.899],[-68.595,-26.507],[-68.386,-26.185],[-68.418,-24.519],[-67.328,-24.025],[-66.985,-22.986],[-67.107,-22.736],[-66.273,-21.832],[-64.965,-22.076],[-64.377,-22.798],[-63.987,-21.994],[-62.846,-22.035],[-62.685,-22.249],[-60.847,-23.881],[-60.029,-24.033],[-58.807,-24.771],[-57.777,-25.162],[-57.634,-25.604],[-58.618,-27.124],[-57.61,-27.396],[-56.487,-27.548],[-55.696,-27.388],[-54.789,-26.622],[-54.625,-25.739],[-54.13,-25.548],[-53.628,-26.125],[-53.649,-26.923],[-54.491,-27.475],[-55.162,-27.882],[-56.291,-28.853],[-57.625,-30.216]]]],"translations":{"ar":"الأرجنتين","bs":"Argentina","cs":"Argentina","de":"Argentinien","es":"Argentina","fa_IR":"آرژانتین","fr":"Argentine","id":"Argentina","it":"Argentina","ja":"アルゼンチン","pl":"Argentyna","pt_BR":"Argentina","pt_PT":"Argentina","ru":"Аргентина","uk":"Аргентина","zh_CN":"阿栚坡","zh_TW":"阿栚坡"}},{"N":"Chile","I":"CL","C":[[[[-68.634,-52.636],[-68.633,-54.87],[-67.562,-54.87],[-66.96,-54.897],[-67.291,-55.301],[-68.149,-55.612],[-68.64,-55.58],[-69.232,-55.499],[-69.958,-55.198],[-71.006,-55.054],[-72.264,-54.495],[-73.285,-53.958],[-74.663,-52.837],[-73.838,-53.047],[-72.434,-53.715],[-71.108,-54.074],[-70.592,-53.616],[-70.267,-52.931],[-69.346,-52.518],[-68.634,-52.636]]],[[[-69.59,-17.58],[-69.1,-18.26],[-68.967,-18.982],[-68.442,-19.405],[-68.757,-20.373],[-68.22,-21.494],[-67.828,-22.873],[-67.107,-22.736],[-66.985,-22.986],[-67.328,-24.025],[-68.418,-24.519],[-68.386,-26.185],[-68.595,-26.507],[-68.296,-26.899],[-69.001,-27.521],[-69.656,-28.459],[-70.014,-29.368],[-69.919,-30.336],[-70.535,-31.365],[-70.074,-33.091],[-69.815,-33.274],[-69.817,-34.194],[-70.388,-35.17],[-70.365,-36.005],[-71.122,-36.658],[-71.119,-37.577],[-70.815,-38.553],[-71.414,-38.916],[-71.681,-39.808],[-71.916,-40.832],[-71.747,-42.051],[-72.149,-42.255],[-71.915,-43.409],[-71.464,-43.788],[-71.794,-44.207],[-71.33,-44.408],[-71.223,-44.784],[-71.659,-44.974],[-71.552,-45.561],[-71.917,-46.885],[-72.447,-47.739],[-72.331,-48.244],[-72.648,-48.879],[-73.415,-49.318],[-73.328,-50.379],[-72.976,-50.741],[-72.31,-50.677],[-72.329,-51.426],[-71.915,-52.009],[-69.498,-52.143],[-68.572,-52.299],[-69.461,-52.292],[-69.943,-52.538],[-70.845,-52.899],[-71.006,-53.833],[-71.43,-53.856],[-72.558,-53.531],[-73.703,-52.835],[-73.703,-52.835],[-74.947,-52.263],[-75.26,-51.629],[-74.977,-51.043],[-75.48,-50.378],[-75.608,-48.674],[-75.183,-47.712],[-74.127,-46.939],[-75.644,-46.648],[-74.692,-45.764],[-74.352,-44.103],[-73.24,-44.455],[-72.718,-42.383],[-73.389,-42.118],[-73.701,-43.366],[-74.332,-43.225],[-74.018,-41.795],[-73.677,-39.942],[-73.218,-39.259],[-73.506,-38.283],[-73.588,-37.156],[-73.167,-37.124],[-72.553,-35.509],[-71.862,-33.909],[-71.438,-32.419],[-71.669,-30.921],[-71.37,-30.096],[-71.49,-28.861],[-70.905,-27.64],[-70.725,-25.706],[-70.404,-23.629],[-70.091,-21.393],[-70.164,-19.756],[-70.373,-18.348],[-69.858,-18.093],[-69.59,-17.58]]]],"translations":{"ar":"تشيلي","bs":"Čile","cs":"Chile","de":"Chile","es":"Chile","fa_IR":"شیلی","fr":"Chili","id":"Cile","it":"Cile","ja":"チリ","pl":"Chile","pt_BR":"Chile","pt_PT":"Chile","ru":"ЧиНи","uk":"Чилі","zh_CN":"智利","zh_TW":"智利"}},{"N":"Democratic Republic of the Congo","I":"CD","C":[[[[29.34,-4.5],[29.52,-5.42],[29.42,-5.94],[29.62,-6.52],[30.2,-7.08],[30.74,-8.34],[30.74,-8.34],[30.346,-8.238],[29.003,-8.407],[28.735,-8.527],[28.45,-9.165],[28.674,-9.606],[28.496,-10.79],[28.372,-11.794],[28.642,-11.972],[29.342,-12.361],[29.616,-12.179],[29.7,-13.257],[28.934,-13.249],[28.524,-12.699],[28.155,-12.272],[27.389,-12.133],[27.164,-11.609],[26.553,-11.924],[25.752,-11.785],[25.418,-11.331],[24.783,-11.239],[24.315,-11.263],[24.257,-10.952],[23.912,-10.927],[23.457,-10.868],[22.837,-11.018],[22.403,-10.993],[22.155,-11.085],[22.209,-9.895],[21.875,-9.524],[21.802,-8.909],[21.949,-8.306],[21.746,-7.92],[21.728,-7.291],[20.515,-7.3],[20.602,-6.939],[20.092,-6.943],[20.038,-7.116],[19.418,-7.155],[19.167,-7.738],[19.017,-7.988],[18.464,-7.847],[18.134,-7.988],[17.473,-8.069],[17.09,-7.546],[16.86,-7.222],[16.573,-6.623],[16.327,-5.877],[13.376,-5.864],[13.025,-5.984],[12.735,-5.966],[12.322,-6.1],[12.182,-5.79],[12.437,-5.684],[12.468,-5.248],[12.632,-4.991],[12.996,-4.781],[13.258,-4.883],[13.6,-4.5],[14.145,-4.51],[14.209,-4.793],[14.583,-4.97],[15.171,-4.344],[15.754,-3.855],[16.006,-3.535],[15.973,-2.712],[16.407,-1.741],[16.865,-1.226],[17.524,-0.744],[17.639,-0.425],[17.664,-0.058],[17.827,0.289],[17.774,0.856],[17.899,1.742],[18.094,2.366],[18.394,2.9],[18.453,3.504],[18.543,4.202],[18.932,4.71],[19.468,5.032],[20.291,4.692],[20.928,4.323],[21.659,4.224],[22.405,4.029],[22.704,4.633],[22.841,4.71],[23.297,4.61],[24.411,5.109],[24.805,4.897],[25.129,4.927],[25.279,5.17],[25.65,5.256],[26.403,5.151],[27.044,5.128],[27.374,5.234],[27.98,4.408],[28.429,4.287],[28.697,4.455],[29.159,4.389],[29.716,4.601],[29.954,4.174],[30.834,3.509],[30.834,3.509],[30.773,2.34],[31.174,2.204],[30.853,1.849],[30.469,1.584],[30.086,1.062],[29.876,0.597],[29.82,-0.205],[29.588,-0.587],[29.579,-1.341],[29.292,-1.62],[29.255,-2.215],[29.117,-2.292],[29.025,-2.839],[29.276,-3.294],[29.34,-4.5]]]],"translations":{"ar":"الكونغو - كينشاسا","bs":"Demokratska Republika Kongo","cs":"Kongo – Kinshasa","de":"Kongo-Kinshasa","es":"RepĂşblica DemocrĂĄtica del Congo","fa_IR":"کنگو - کینشاسا","fr":"Congo-Kinshasa","id":"Kongo - Kinshasa","it":"Congo - Kinshasa","ja":"コンゴ民主共和国(キンシャサ)","pl":"Demokratyczna Republika Konga","pt_BR":"Congo - Kinshasa","pt_PT":"Congo-Kinshasa","ru":"Конго - Киншаса","uk":"Конго – Кіншаса","zh_CN":"刚果(金)","zh_TW":"剛果(金夏沙)"}},{"N":"Somalia","I":"SO","C":[[[[41.585,-1.683],[40.993,-0.858],[40.981,2.785],[41.855,3.919],[42.129,4.234],[42.77,4.253],[43.661,4.958],[44.964,5.002],[47.789,8.003],[48.487,8.838],[48.938,9.452],[48.938,9.974],[48.938,10.982],[48.942,11.394],[48.948,11.411],[48.948,11.411],[49.268,11.43],[49.729,11.579],[50.259,11.68],[50.732,12.022],[51.111,12.025],[51.134,11.748],[51.042,11.167],[51.045,10.641],[50.834,10.28],[50.552,9.199],[50.071,8.082],[49.453,6.805],[48.595,5.339],[47.741,4.219],[46.565,2.855],[45.564,2.046],[44.068,1.053],[43.136,0.292],[42.042,-0.919],[41.811,-1.446],[41.585,-1.683]]]],"translations":{"ar":"الصومال","bs":"Somalija","cs":"SomĂĄlsko","de":"Somalia","es":"Somalia","fa_IR":"سومالی","fr":"Somalie","id":"Somalia","it":"Somalia","ja":"ソマリア","pl":"Somalia","pt_BR":"SomĂĄlia","pt_PT":"SomĂĄlia","ru":"ХОПаНи","uk":"Сомалі","zh_CN":"索马里","zh_TW":"索馬利亞"}},{"N":"Kenya","I":"KE","C":[[[[39.202,-4.677],[37.767,-3.677],[37.699,-3.097],[34.073,-1.06],[33.904,-0.95],[33.894,0.11],[34.18,0.515],[34.672,1.177],[35.036,1.906],[34.596,3.054],[34.479,3.556],[34.005,4.25],[34.62,4.847],[35.298,5.506],[35.817,5.338],[35.817,4.777],[36.159,4.448],[36.855,4.448],[38.121,3.599],[38.437,3.589],[38.671,3.616],[38.893,3.501],[39.559,3.422],[39.855,3.839],[40.768,4.257],[41.172,3.919],[41.855,3.919],[40.981,2.785],[40.993,-0.858],[41.585,-1.683],[40.885,-2.083],[40.638,-2.5],[40.263,-2.573],[40.121,-3.278],[39.8,-3.681],[39.605,-4.347],[39.202,-4.677]]]],"translations":{"ar":"كينيا","bs":"Kenija","cs":"Keňa","de":"Kenia","es":"Kenia","fa_IR":"کنیا","fr":"Kenya","id":"Kenya","it":"Kenya","ja":"ケニア","pl":"Kenia","pt_BR":"QuĂŞnia","pt_PT":"QuĂŠnia","ru":"Кения","uk":"Кенія","zh_CN":"肯尼亚","zh_TW":"肯亞"}},{"N":"Sudan","I":"SD","C":[[[[24.567,8.229],[23.806,8.666],[23.459,8.954],[23.395,9.265],[23.557,9.681],[23.554,10.089],[22.978,10.714],[22.864,11.142],[22.876,11.385],[22.509,11.679],[22.498,12.26],[22.288,12.646],[21.937,12.588],[22.038,12.955],[22.297,13.372],[22.183,13.786],[22.512,14.093],[22.304,14.327],[22.568,14.944],[23.025,15.681],[23.887,15.611],[23.838,19.58],[23.85,20],[25,20.003],[25,22],[29.02,22],[32.9,22],[36.866,22],[37.189,21.019],[36.969,20.837],[37.115,19.808],[37.482,18.614],[37.863,18.368],[38.41,17.998],[37.904,17.428],[37.167,17.263],[36.853,16.957],[36.754,16.292],[36.323,14.822],[36.43,14.422],[36.27,13.563],[35.864,12.578],[35.26,12.083],[34.832,11.319],[34.731,10.91],[34.257,10.63],[33.962,9.584],[33.975,8.685],[33.963,9.464],[33.825,9.484],[33.842,9.982],[33.722,10.325],[33.207,10.72],[33.087,11.441],[33.207,12.179],[32.743,12.248],[32.675,12.025],[32.074,11.973],[32.314,11.681],[32.4,11.081],[31.851,10.531],[31.353,9.81],[30.838,9.707],[29.997,10.291],[29.619,10.085],[29.516,9.793],[29.001,9.604],[28.967,9.398],[27.971,9.398],[27.834,9.604],[27.113,9.639],[26.752,9.467],[26.477,9.553],[25.962,10.136],[25.791,10.411],[25.07,10.274],[24.795,9.81],[24.537,8.918],[24.194,8.729],[23.887,8.62],[24.567,8.229]]]],"translations":{"ar":"السودان","bs":"Sudan","cs":"SĂşdĂĄn","de":"Sudan","es":"SudĂĄn","fa_IR":"سودان","fr":"Soudan","id":"Sudan","it":"Sudan","ja":"スーダン","pl":"Sudan","pt_BR":"SudĂŁo","pt_PT":"SudĂŁo","ru":"Худан","uk":"Худан","zh_CN":"苏丹","zh_TW":"蘇丹"}},{"N":"Chad","I":"TD","C":[[[[23.838,19.58],[23.887,15.611],[23.025,15.681],[22.568,14.944],[22.304,14.327],[22.512,14.093],[22.183,13.786],[22.297,13.372],[22.038,12.955],[21.937,12.588],[22.288,12.646],[22.498,12.26],[22.509,11.679],[22.876,11.385],[22.864,11.142],[22.231,10.972],[21.724,10.567],[21.001,9.476],[20.06,9.013],[19.094,9.075],[18.812,8.983],[18.911,8.631],[18.39,8.281],[17.965,7.891],[16.706,7.508],[16.456,7.735],[16.291,7.754],[16.106,7.497],[15.279,7.422],[15.436,7.693],[15.121,8.382],[14.98,8.796],[14.544,8.966],[13.954,9.549],[14.171,10.021],[14.627,9.921],[14.909,9.992],[15.468,9.982],[14.924,10.891],[14.96,11.556],[14.893,12.219],[14.496,12.859],[14.596,13.33],[13.954,13.353],[13.957,13.997],[13.54,14.367],[13.972,15.684],[15.248,16.627],[15.3,17.928],[15.686,19.957],[15.903,20.388],[15.487,20.73],[15.471,21.048],[15.097,21.309],[14.851,22.863],[15.861,23.41],[19.849,21.495],[23.838,19.58]]]],"translations":{"ar":"تشاد","bs":"Čad","cs":"Čad","de":"Tschad","es":"Chad","fa_IR":"چاد","fr":"Tchad","id":"Chad","it":"Ciad","ja":"チャド","pl":"Czad","pt_BR":"Chade","pt_PT":"Chade","ru":"Чад","uk":"Чад","zh_CN":"乍得","zh_TW":"查德"}},{"N":"Haiti","I":"HT","C":[[[[-71.712,19.714],[-71.625,19.17],[-71.701,18.785],[-71.945,18.617],[-71.688,18.317],[-71.708,18.045],[-72.372,18.215],[-72.844,18.146],[-73.455,18.218],[-73.922,18.031],[-74.458,18.343],[-74.37,18.665],[-73.45,18.526],[-72.695,18.446],[-72.335,18.668],[-72.792,19.102],[-72.784,19.484],[-73.415,19.64],[-73.19,19.916],[-72.58,19.872],[-71.712,19.714]]]],"translations":{"ar":"هايتي","bs":"Haiti","cs":"Haiti","de":"Haiti","es":"HaitĂ­","fa_IR":"هائیتی","fr":"HaĂŻti","id":"Haiti","it":"Haiti","ja":"ハイチ","pl":"Haiti","pt_BR":"Haiti","pt_PT":"Haiti","ru":"Гаити","uk":"Гаїті","zh_CN":"海地","zh_TW":"海地"}},{"N":"Dominican Republic","I":"DO","C":[[[[-71.708,18.045],[-71.688,18.317],[-71.945,18.617],[-71.701,18.785],[-71.625,19.17],[-71.712,19.714],[-71.587,19.885],[-70.807,19.88],[-70.214,19.623],[-69.951,19.648],[-69.769,19.293],[-69.222,19.313],[-69.254,19.015],[-68.809,18.979],[-68.318,18.612],[-68.689,18.205],[-69.165,18.423],[-69.624,18.381],[-69.953,18.428],[-70.133,18.246],[-70.517,18.184],[-70.669,18.427],[-71,18.283],[-71.4,17.599],[-71.658,17.758],[-71.708,18.045]]]],"translations":{"ar":"جمهورية الدومينيكان","bs":"Dominikanska Republika","cs":"DominikĂĄnskĂĄ republika","de":"Dominikanische Republik","es":"RepĂşblica Dominicana","fa_IR":"جمهوری دومینیکن","fr":"RĂŠpublique dominicaine","id":"Republik Dominika","it":"Repubblica Dominicana","ja":"ドミニカ共和国","pl":"Dominikana","pt_BR":"RepĂşblica Dominicana","pt_PT":"RepĂşblica Dominicana","ru":"Доминиканская РоспуйНика","uk":"Домініканська Республіка","zh_CN":"多米尼加共和国","zh_TW":"多明尼加共和國"}},{"N":"Russia","I":"RU","C":[[[[178.725,71.099],[180,71.516],[180,70.832],[178.903,70.781],[178.725,71.099]]],[[[93.778,81.025],[95.941,81.25],[97.884,80.747],[100.187,79.78],[99.94,78.881],[97.758,78.756],[94.973,79.045],[93.313,79.427],[92.545,80.144],[91.181,80.341],[93.778,81.025]]],[[[102.838,79.281],[105.372,78.713],[105.075,78.307],[99.438,77.921],[101.265,79.234],[102.086,79.346],[102.838,79.281]]],[[[138.831,76.137],[141.472,76.093],[145.086,75.563],[144.3,74.82],[140.614,74.848],[138.955,74.611],[136.974,75.262],[137.512,75.949],[138.831,76.137]]],[[[148.222,75.346],[150.732,75.084],[149.576,74.689],[147.977,74.778],[146.119,75.173],[146.358,75.497],[148.222,75.346]]],[[[139.863,73.37],[140.812,73.765],[142.062,73.858],[143.483,73.475],[143.604,73.212],[142.088,73.205],[140.038,73.317],[139.863,73.37]]],[[[44.847,80.59],[46.799,80.772],[48.318,80.784],[48.523,80.515],[49.097,80.754],[50.04,80.919],[51.523,80.7],[51.136,80.547],[49.794,80.415],[48.894,80.34],[48.755,80.175],[47.586,80.01],[46.503,80.247],[47.072,80.559],[44.847,80.59]]],[[[22.731,54.328],[20.892,54.313],[19.661,54.426],[19.888,54.866],[21.268,55.19],[22.316,55.015],[22.758,54.857],[22.651,54.583],[22.731,54.328]]],[[[53.508,73.75],[55.902,74.627],[55.632,75.081],[57.869,75.609],[61.17,76.252],[64.498,76.439],[66.211,76.81],[68.157,76.94],[68.852,76.545],[68.181,76.234],[64.637,75.738],[61.584,75.261],[58.477,74.309],[56.987,73.333],[55.419,72.371],[55.623,71.541],[57.536,70.72],[56.945,70.633],[53.677,70.763],[53.412,71.207],[51.602,71.475],[51.456,72.015],[52.478,72.229],[52.444,72.775],[54.428,73.628],[53.508,73.75]]],[[[142.915,53.705],[143.261,52.741],[143.235,51.757],[143.648,50.748],[144.654,48.976],[143.174,49.307],[142.559,47.862],[143.533,46.837],[143.505,46.138],[142.748,46.741],[142.092,45.967],[141.907,46.806],[142.018,47.78],[141.904,48.859],[142.136,49.615],[142.18,50.952],[141.594,51.935],[141.683,53.302],[142.607,53.762],[142.21,54.225],[142.655,54.366],[142.915,53.705]]],[[[-174.928,67.206],[-175.014,66.584],[-174.34,66.336],[-174.572,67.062],[-171.857,66.913],[-169.9,65.977],[-170.891,65.541],[-172.53,65.438],[-172.555,64.461],[-172.955,64.253],[-173.892,64.283],[-174.654,64.631],[-175.984,64.923],[-176.207,65.357],[-177.223,65.52],[-178.36,65.391],[-178.903,65.74],[-178.686,66.112],[-179.884,65.875],[-179.433,65.404],[-180,64.98],[-180,68.964],[-177.55,68.2],[-174.928,67.206]]],[[[-178.694,70.893],[-180,70.832],[-180,71.516],[-179.872,71.558],[-179.024,71.556],[-177.578,71.269],[-177.664,71.133],[-178.694,70.893]]],[[[49.101,46.399],[48.645,45.806],[47.676,45.641],[46.682,44.609],[47.591,43.66],[47.493,42.987],[48.584,41.809],[48.584,41.809],[47.987,41.406],[47.816,41.151],[47.373,41.22],[46.686,41.827],[46.405,41.861],[45.776,42.092],[45.47,42.503],[44.538,42.712],[43.931,42.555],[43.756,42.741],[42.394,43.22],[40.922,43.382],[40.077,43.553],[39.955,43.435],[38.68,44.28],[37.539,44.657],[36.675,45.245],[37.403,45.405],[38.233,46.241],[37.674,46.637],[39.148,47.045],[39.121,47.263],[38.224,47.102],[38.255,47.546],[38.771,47.826],[39.738,47.899],[39.896,48.232],[39.675,48.784],[40.081,49.307],[40.069,49.601],[38.595,49.926],[38.011,49.916],[37.393,50.384],[36.626,50.226],[35.356,50.577],[35.378,50.774],[35.022,51.208],[34.225,51.256],[34.142,51.566],[34.392,51.769],[33.753,52.335],[32.716,52.238],[32.412,52.289],[32.159,52.061],[31.786,52.102],[31.786,52.102],[31.54,52.742],[31.305,53.074],[31.498,53.167],[32.305,53.133],[32.694,53.351],[32.406,53.618],[31.731,53.794],[31.791,53.975],[31.384,54.157],[30.758,54.812],[30.972,55.082],[30.874,55.551],[29.896,55.789],[29.372,55.67],[29.23,55.918],[28.177,56.169],[27.855,56.759],[27.77,57.244],[27.288,57.475],[27.717,57.792],[27.42,58.725],[28.132,59.301],[27.981,59.475],[27.981,59.475],[29.118,60.028],[28.07,60.504],[28.07,60.504],[30.211,61.78],[31.14,62.358],[31.516,62.868],[30.036,63.553],[30.445,64.204],[29.544,64.949],[30.218,65.806],[29.055,66.944],[29.977,67.698],[28.446,68.365],[28.592,69.065],[29.4,69.157],[31.101,69.558],[31.101,69.558],[32.133,69.906],[33.775,69.301],[36.514,69.063],[40.292,67.932],[41.06,67.457],[41.126,66.792],[40.016,66.266],[38.383,66],[33.919,66.76],[33.184,66.633],[34.815,65.9],[34.879,65.436],[34.944,64.414],[36.231,64.109],[37.013,63.85],[37.142,64.335],[36.54,64.764],[37.176,65.143],[39.593,64.521],[40.436,64.764],[39.763,65.497],[42.093,66.476],[43.016,66.419],[43.95,66.069],[44.532,66.756],[43.698,67.352],[44.188,67.951],[43.453,68.571],[46.25,68.25],[46.821,67.69],[45.555,67.567],[45.562,67.01],[46.349,66.668],[47.894,66.885],[48.139,67.522],[50.228,67.999],[53.717,68.857],[54.472,68.808],[53.486,68.201],[54.726,68.097],[55.443,68.439],[57.317,68.466],[58.802,68.881],[59.941,68.278],[61.078,68.941],[60.03,69.52],[60.55,69.85],[63.504,69.547],[64.888,69.235],[68.512,68.092],[69.181,68.616],[68.164,69.144],[68.135,69.356],[66.93,69.455],[67.26,69.929],[66.725,70.709],[66.695,71.029],[68.54,71.935],[69.196,72.843],[69.94,73.04],[72.588,72.776],[72.796,72.22],[71.848,71.409],[72.47,71.09],[72.792,70.391],[72.565,69.021],[73.668,68.408],[73.239,67.74],[71.28,66.32],[72.423,66.173],[72.821,66.533],[73.921,66.789],[74.187,67.284],[75.052,67.76],[74.469,68.329],[74.936,68.989],[73.842,69.071],[73.602,69.628],[74.4,70.632],[73.101,71.447],[74.891,72.121],[74.659,72.832],[75.158,72.855],[75.684,72.301],[75.289,71.336],[76.359,71.153],[75.903,71.874],[77.577,72.267],[79.652,72.32],[81.5,71.75],[80.611,72.583],[80.511,73.648],[82.25,73.85],[84.655,73.806],[86.822,73.937],[86.01,74.46],[87.167,75.116],[88.316,75.144],[90.26,75.64],[92.901,75.773],[93.234,76.047],[95.86,76.14],[96.678,75.915],[98.923,76.447],[100.76,76.43],[101.035,76.862],[101.991,77.288],[104.352,77.698],[106.067,77.374],[104.705,77.127],[106.97,76.974],[107.24,76.48],[108.154,76.723],[111.077,76.71],[113.332,76.222],[114.134,75.848],[113.885,75.328],[112.779,75.032],[110.151,74.477],[109.4,74.18],[110.64,74.04],[112.119,73.788],[113.02,73.977],[113.53,73.335],[113.969,73.595],[115.568,73.753],[118.776,73.588],[119.02,73.12],[123.201,72.971],[123.258,73.735],[125.38,73.56],[126.976,73.565],[128.591,73.039],[129.052,72.399],[128.46,71.98],[129.716,71.193],[131.289,70.787],[132.254,71.836],[133.858,71.386],[135.562,71.655],[137.498,71.348],[138.234,71.628],[139.87,71.488],[139.148,72.416],[140.468,72.849],[149.5,72.2],[150.351,71.606],[152.969,70.842],[157.007,71.031],[158.998,70.867],[159.83,70.453],[159.709,69.722],[160.941,69.437],[162.279,69.642],[164.052,69.668],[165.94,69.472],[167.836,69.583],[169.578,68.694],[170.817,69.014],[170.008,69.653],[170.453,70.097],[173.644,69.817],[175.724,69.877],[178.6,69.4],[180,68.964],[180,64.98],[179.993,64.974],[178.707,64.535],[177.411,64.608],[178.313,64.076],[178.908,63.252],[179.37,62.983],[179.486,62.569],[179.228,62.304],[177.364,62.522],[174.569,61.769],[173.68,61.653],[172.15,60.95],[170.698,60.336],[170.331,59.882],[168.9,60.574],[166.295,59.789],[165.84,60.16],[164.877,59.732],[163.539,59.869],[163.217,59.211],[162.017,58.243],[162.053,57.839],[163.192,57.615],[163.058,56.159],[162.13,56.122],[161.701,55.286],[162.117,54.855],[160.369,54.344],[160.022,53.203],[158.531,52.959],[158.231,51.943],[156.79,51.011],[156.42,51.7],[155.992,53.159],[155.434,55.381],[155.914,56.768],[156.758,57.365],[156.81,57.832],[158.364,58.056],[160.151,59.315],[161.872,60.343],[163.67,61.141],[164.474,62.551],[163.258,62.466],[162.658,61.642],[160.121,60.544],[159.302,61.774],[156.721,61.434],[154.218,59.758],[155.044,59.145],[152.812,58.884],[151.266,58.781],[151.338,59.504],[149.784,59.656],[148.545,59.164],[145.487,59.336],[142.198,59.04],[138.958,57.088],[135.126,54.73],[136.702,54.604],[137.193,53.977],[138.165,53.755],[138.805,54.255],[139.902,54.19],[141.345,53.09],[141.379,52.239],[140.597,51.24],[140.513,50.046],[140.062,48.447],[138.555,47],[138.22,46.308],[136.862,45.144],[135.515,43.989],[134.869,43.398],[133.537,42.811],[132.906,42.798],[132.278,43.285],[130.936,42.553],[130.78,42.22],[130.78,42.22],[130.78,42.22],[130.78,42.22],[130.64,42.395],[130.64,42.395],[130.634,42.903],[131.145,42.93],[131.289,44.112],[131.025,44.968],[131.883,45.321],[133.097,45.144],[133.77,46.117],[134.112,47.212],[134.501,47.578],[135.026,48.478],[133.374,48.183],[132.507,47.789],[130.987,47.79],[130.582,48.73],[129.398,49.441],[127.657,49.76],[127.287,50.74],[126.939,51.354],[126.564,51.784],[125.946,52.793],[125.068,53.161],[123.571,53.459],[122.246,53.432],[121.003,53.251],[120.177,52.754],[120.726,52.516],[120.738,51.964],[120.182,51.644],[119.279,50.583],[119.288,50.143],[117.879,49.511],[116.679,49.889],[115.486,49.805],[114.962,50.14],[114.362,50.248],[112.898,49.544],[111.581,49.378],[110.662,49.13],[109.402,49.293],[108.475,49.283],[107.868,49.794],[106.889,50.274],[105.887,50.406],[104.622,50.275],[103.677,50.09],[102.256,50.511],[102.065,51.26],[100.889,51.517],[99.982,51.634],[98.861,52.047],[97.826,51.011],[98.232,50.422],[97.26,49.726],[95.814,49.977],[94.816,50.013],[94.148,50.481],[93.104,50.495],[92.235,50.802],[90.714,50.332],[88.806,49.471],[87.751,49.297],[87.36,49.215],[86.829,49.827],[85.541,49.693],[85.116,50.117],[84.416,50.311],[83.935,50.889],[83.383,51.069],[81.946,50.812],[80.568,51.388],[80.036,50.865],[77.801,53.404],[76.525,54.177],[76.891,54.491],[74.385,53.547],[73.426,53.49],[73.509,54.036],[72.224,54.377],[71.18,54.133],[70.865,55.17],[69.068,55.385],[68.169,54.97],[65.667,54.601],[65.179,54.354],[61.437,54.006],[60.978,53.665],[61.7,52.98],[60.74,52.72],[60.927,52.448],[59.968,51.96],[61.588,51.273],[61.337,50.799],[59.933,50.842],[59.642,50.545],[58.363,51.064],[56.778,51.044],[55.717,50.622],[54.533,51.026],[52.329,51.719],[50.767,51.693],[48.702,50.605],[48.578,49.875],[47.549,50.455],[46.752,49.356],[47.044,49.152],[46.466,48.394],[47.315,47.716],[48.057,47.744],[48.695,47.076],[48.593,46.561],[49.101,46.399]]]],"translations":{"ar":"روسيا","bs":"Rusija","cs":"Rusko","de":"Russland","es":"Rusia","fa_IR":"روسیه","fr":"Russie","id":"Rusia","it":"Russia","ja":"ロシア","pl":"Rosja","pt_BR":"RĂşssia","pt_PT":"RĂşssia","ru":"Россия","uk":"Росія","zh_CN":"俄罗斯","zh_TW":"俄羅斯"}},{"N":"Bahamas","I":"BS","C":[[[[-78.98,26.79],[-78.51,26.87],[-77.85,26.84],[-77.82,26.58],[-78.91,26.42],[-78.98,26.79]]],[[[-77.79,27.04],[-77,26.59],[-77.173,25.879],[-77.356,26.007],[-77.34,26.53],[-77.788,26.925],[-77.79,27.04]]],[[[-78.191,25.21],[-77.89,25.17],[-77.54,24.34],[-77.535,23.76],[-77.78,23.71],[-78.034,24.286],[-78.408,24.576],[-78.191,25.21]]]],"translations":{"ar":"؏زع البهاما","bs":"Bahami","cs":"Bahamy","de":"Bahamas","es":"Bahamas","fa_IR":"باهاما","fr":"Bahamas","id":"Bahama","it":"Bahamas","ja":"バハマ","pl":"Bahamy","pt_BR":"Bahamas","pt_PT":"Baamas","ru":"Багамы","uk":"Багамські Острови","zh_CN":"巴哈马","zh_TW":"巴哈馬"}},{"N":"Falkland Islands","I":"FK","C":[[[[-61.2,-51.85],[-60,-51.25],[-59.15,-51.5],[-58.55,-51.1],[-57.75,-51.55],[-58.05,-51.9],[-59.4,-52.2],[-59.85,-51.85],[-60.7,-52.3],[-61.2,-51.85]]]],"translations":{"ar":"؏زع فوكلاند","bs":"Folklandska ostrva","cs":"FalklandskĂŠ ostrovy","de":"Falklandinseln","es":"Islas Malvinas","fa_IR":"جزایر فالکلند","fr":"Îles Malouines","id":"Kepulauan Falkland","it":"Isole Falkland","ja":"フォークランド諸島","pl":"Falklandy","pt_BR":"Ilhas Malvinas","pt_PT":"Ilhas Falkland","ru":"ФОНкНондскио Đž-ва","uk":"Фолклендські Острови","zh_CN":"福克兰群岛","zh_TW":"福克蘭群島"}},{"N":"Norway","I":"NO","C":[[[[15.143,79.674],[15.523,80.016],[16.991,80.051],[18.252,79.702],[21.544,78.956],[19.027,78.563],[18.472,77.827],[17.594,77.638],[17.118,76.809],[15.913,76.77],[13.763,77.38],[14.67,77.736],[13.171,78.025],[11.222,78.869],[10.445,79.652],[13.171,80.01],[13.719,79.66],[15.143,79.674]]],[[[27.408,80.056],[25.925,79.518],[23.024,79.4],[20.075,79.567],[19.897,79.842],[18.462,79.86],[17.368,80.319],[20.456,80.598],[21.908,80.358],[22.919,80.657],[25.448,80.407],[27.408,80.056]]],[[[24.724,77.854],[22.49,77.445],[20.726,77.677],[21.416,77.935],[20.812,78.255],[22.884,78.455],[23.281,78.08],[24.724,77.854]]],[[[31.101,69.558],[29.4,69.157],[28.592,69.065],[29.016,69.766],[27.732,70.164],[26.18,69.825],[25.689,69.092],[24.736,68.65],[23.662,68.891],[22.356,68.842],[21.245,69.37],[20.646,69.106],[20.025,69.065],[19.879,68.407],[17.994,68.567],[17.729,68.011],[16.769,68.014],[16.109,67.302],[15.108,66.194],[13.556,64.787],[13.92,64.445],[13.572,64.049],[12.58,64.066],[11.931,63.128],[11.992,61.8],[12.631,61.294],[12.3,60.118],[11.468,59.432],[11.027,58.856],[10.357,59.47],[8.382,58.313],[7.049,58.079],[5.666,58.588],[5.308,59.663],[4.992,61.971],[5.913,62.614],[8.553,63.454],[10.528,64.486],[12.358,65.88],[14.761,67.811],[16.436,68.563],[19.184,69.817],[21.378,70.255],[23.024,70.202],[24.547,71.03],[26.37,70.986],[28.166,71.185],[31.293,70.454],[30.005,70.186],[31.101,69.558]]]],"translations":{"ar":"النرويج","bs":"NorveĹĄka","cs":"Norsko","de":"Norwegen","es":"Noruega","fa_IR":"نروژ","fr":"Norvège","id":"Norwegia","it":"Norvegia","ja":"ノルウェー","pl":"Norwegia","pt_BR":"Noruega","pt_PT":"Noruega","ru":"Норвегия","uk":"Норвегія","zh_CN":"挪威","zh_TW":"挪威"}},{"N":"Greenland","I":"GL","C":[[[[-46.764,82.628],[-43.406,83.225],[-39.898,83.18],[-38.622,83.549],[-35.088,83.645],[-27.1,83.52],[-20.845,82.727],[-22.692,82.342],[-26.518,82.298],[-31.9,82.2],[-31.396,82.022],[-27.857,82.132],[-24.844,81.787],[-22.903,82.093],[-22.072,81.734],[-23.17,81.153],[-20.624,81.525],[-15.768,81.912],[-12.77,81.719],[-12.209,81.292],[-16.285,80.58],[-16.85,80.35],[-20.046,80.177],[-17.73,80.129],[-18.9,79.4],[-19.705,78.751],[-19.674,77.639],[-18.473,76.986],[-20.035,76.944],[-21.679,76.628],[-19.834,76.098],[-19.599,75.248],[-20.668,75.156],[-19.373,74.296],[-21.594,74.224],[-20.435,73.817],[-20.762,73.464],[-22.172,73.31],[-23.566,73.307],[-22.313,72.629],[-22.3,72.184],[-24.278,72.598],[-24.793,72.33],[-23.443,72.08],[-22.133,71.469],[-21.754,70.664],[-23.536,70.471],[-24.307,70.856],[-25.543,71.431],[-25.201,70.752],[-26.363,70.226],[-23.727,70.184],[-22.349,70.129],[-25.029,69.259],[-27.747,68.47],[-30.674,68.125],[-31.777,68.121],[-32.811,67.735],[-34.202,66.68],[-36.353,65.979],[-37.044,65.938],[-38.375,65.692],[-39.812,65.458],[-40.669,64.84],[-40.683,64.139],[-41.189,63.482],[-42.819,62.682],[-42.417,61.901],[-42.866,61.074],[-43.378,60.098],[-44.788,60.037],[-46.264,60.853],[-48.263,60.858],[-49.233,61.407],[-49.9,62.383],[-51.633,63.627],[-52.14,64.278],[-52.277,65.177],[-53.662,66.1],[-53.302,66.837],[-53.969,67.189],[-52.98,68.358],[-51.475,68.73],[-51.08,69.148],[-50.871,69.929],[-52.014,69.575],[-52.558,69.426],[-53.456,69.284],[-54.683,69.61],[-54.75,70.289],[-54.359,70.821],[-53.431,70.836],[-51.39,70.57],[-53.109,71.205],[-54.004,71.547],[-55,71.407],[-55.835,71.654],[-54.718,72.586],[-55.326,72.959],[-56.12,73.65],[-57.324,74.71],[-58.597,75.099],[-58.585,75.517],[-61.269,76.102],[-63.392,76.175],[-66.064,76.135],[-68.504,76.061],[-69.665,76.38],[-71.403,77.009],[-68.777,77.323],[-66.764,77.376],[-71.043,77.636],[-73.297,78.044],[-73.159,78.433],[-69.373,78.914],[-65.711,79.394],[-65.324,79.758],[-68.023,80.117],[-67.151,80.516],[-63.689,81.214],[-62.234,81.321],[-62.651,81.77],[-60.282,82.034],[-57.207,82.191],[-54.134,82.2],[-53.043,81.888],[-50.391,82.439],[-48.004,82.065],[-46.6,81.986],[-44.523,81.661],[-46.901,82.2],[-46.764,82.628]]]],"translations":{"ar":"غرينلاند","bs":"Grenland","cs":"GrĂłnsko","de":"GrĂśnland","es":"Groenlandia","fa_IR":"گرینلند","fr":"Groenland","id":"Greenland","it":"Groenlandia","ja":"グリーンランド","pl":"Grenlandia","pt_BR":"Groenlândia","pt_PT":"Gronelândia","ru":"Гренландия","uk":"Гренландія","zh_CN":"格陵兰","zh_TW":"格陵蘭"}},{"N":"Timor-Leste","I":"TL","C":[[[[124.969,-8.893],[125.086,-8.657],[125.947,-8.432],[126.645,-8.398],[126.957,-8.273],[127.336,-8.397],[126.968,-8.668],[125.926,-9.106],[125.089,-9.393],[125.07,-9.09],[124.969,-8.893]]]],"translations":{"ar":"تيمور - ليشتي","bs":"Istočni Timor","cs":"VĂ˝chodnĂ­ Timor","de":"Timor-Leste","es":"Timor-Leste","fa_IR":"تیمور-لسته","fr":"Timor oriental","id":"Timor Leste","it":"Timor Est","ja":"東ティモール","pl":"Timor Wschodni","pt_BR":"Timor-Leste","pt_PT":"Timor-Leste","ru":"Восточный Тимор","uk":"Тимор-Лешті","zh_CN":"东帝汶","zh_TW":"東帝汶"}},{"N":"South Africa","I":"ZA","C":[[[[16.345,-28.577],[16.824,-28.082],[17.219,-28.356],[17.387,-28.784],[17.836,-28.856],[18.465,-29.045],[19.002,-28.972],[19.895,-28.461],[19.896,-24.768],[20.166,-24.918],[20.759,-25.868],[20.666,-26.477],[20.89,-26.829],[21.606,-26.727],[22.106,-26.28],[22.58,-25.979],[22.824,-25.5],[23.312,-25.269],[23.734,-25.39],[24.211,-25.67],[25.025,-25.72],[25.665,-25.487],[25.766,-25.175],[25.942,-24.696],[26.486,-24.616],[26.786,-24.241],[27.119,-23.574],[28.017,-22.828],[29.432,-22.091],[29.839,-22.102],[30.323,-22.272],[30.66,-22.152],[31.191,-22.252],[31.67,-23.659],[31.931,-24.369],[31.752,-25.484],[31.838,-25.843],[31.333,-25.66],[31.044,-25.731],[30.95,-26.023],[30.677,-26.398],[30.686,-26.744],[31.283,-27.286],[31.868,-27.178],[32.072,-26.734],[32.83,-26.742],[32.58,-27.47],[32.462,-28.301],[32.203,-28.752],[31.521,-29.257],[31.326,-29.402],[30.902,-29.91],[30.623,-30.424],[30.056,-31.14],[28.926,-32.172],[28.22,-32.772],[27.465,-33.227],[26.419,-33.615],[25.91,-33.667],[25.781,-33.945],[25.173,-33.797],[24.678,-33.987],[23.594,-33.794],[22.988,-33.916],[22.574,-33.864],[21.543,-34.259],[20.689,-34.417],[20.071,-34.795],[19.616,-34.819],[19.193,-34.463],[18.855,-34.444],[18.425,-33.998],[18.377,-34.137],[18.244,-33.868],[18.25,-33.281],[17.925,-32.611],[18.248,-32.429],[18.222,-31.662],[17.567,-30.726],[17.064,-29.879],[17.063,-29.876],[16.345,-28.577]],[[28.978,-28.956],[28.542,-28.648],[28.074,-28.851],[27.533,-29.243],[26.999,-29.876],[27.749,-30.645],[28.107,-30.546],[28.291,-30.226],[28.848,-30.07],[29.018,-29.744],[29.325,-29.257],[28.978,-28.956]]]],"translations":{"ar":"جنوب أفريقيا","bs":"JuĹžnoafrička Republika","cs":"JihoafrickĂĄ republika","de":"SĂźdafrika","es":"SudĂĄfrica","fa_IR":"افریقای جنوبی","fr":"Afrique du Sud","id":"Afrika Selatan","it":"Sudafrica","ja":"南アフリカ","pl":"Republika Południowej Afryki","pt_BR":"África do Sul","pt_PT":"África do Sul","ru":"ЎМнО-Африканская РоспуйНика","uk":"Південно-Африканська Республіка","zh_CN":"南非","zh_TW":"南非"}},{"N":"Lesotho","I":"LS","C":[[[[28.978,-28.956],[29.325,-29.257],[29.018,-29.744],[28.848,-30.07],[28.291,-30.226],[28.107,-30.546],[27.749,-30.645],[26.999,-29.876],[27.533,-29.243],[28.074,-28.851],[28.542,-28.648],[28.978,-28.956]]]],"translations":{"ar":"ليسوتو","bs":"Lesoto","cs":"Lesotho","de":"Lesotho","es":"Lesoto","fa_IR":"لسوتو","fr":"Lesotho","id":"Lesotho","it":"Lesotho","ja":"レソト","pl":"Lesotho","pt_BR":"Lesoto","pt_PT":"Lesoto","ru":"Лесото","uk":"Лесото","zh_CN":"莱索托","zh_TW":"賴索托"}},{"N":"Mexico","I":"MX","C":[[[[-117.128,32.535],[-115.991,32.612],[-114.721,32.721],[-114.815,32.525],[-113.305,32.039],[-111.024,31.335],[-109.035,31.342],[-108.242,31.342],[-108.24,31.755],[-106.508,31.755],[-106.143,31.4],[-105.632,31.084],[-105.037,30.644],[-104.706,30.122],[-104.457,29.572],[-103.94,29.27],[-103.11,28.97],[-102.48,29.76],[-101.662,29.779],[-100.958,29.381],[-100.456,28.696],[-100.11,28.11],[-99.52,27.54],[-99.3,26.84],[-99.02,26.37],[-98.24,26.06],[-97.53,25.84],[-97.14,25.87],[-97.528,24.992],[-97.703,24.272],[-97.776,22.933],[-97.872,22.444],[-97.699,21.899],[-97.389,21.411],[-97.189,20.635],[-96.526,19.891],[-96.292,19.32],[-95.901,18.828],[-94.839,18.563],[-94.426,18.144],[-93.549,18.424],[-92.786,18.525],[-92.037,18.705],[-91.408,18.876],[-90.772,19.284],[-90.534,19.867],[-90.451,20.708],[-90.279,21],[-89.601,21.262],[-88.544,21.494],[-87.658,21.459],[-87.052,21.544],[-86.812,21.332],[-86.846,20.85],[-87.383,20.255],[-87.621,19.647],[-87.437,19.472],[-87.587,19.04],[-87.837,18.26],[-88.091,18.517],[-88.3,18.5],[-88.49,18.487],[-88.848,17.883],[-89.03,18.002],[-89.151,17.955],[-89.143,17.808],[-90.068,17.819],[-91.002,17.818],[-91.002,17.255],[-91.454,17.252],[-91.082,16.918],[-90.712,16.687],[-90.601,16.471],[-90.439,16.41],[-90.464,16.07],[-91.748,16.067],[-92.229,15.251],[-92.087,15.065],[-92.203,14.83],[-92.228,14.539],[-93.359,15.615],[-93.875,15.94],[-94.692,16.201],[-95.25,16.128],[-96.053,15.752],[-96.557,15.654],[-97.264,15.917],[-98.013,16.107],[-98.948,16.566],[-99.697,16.706],[-100.829,17.171],[-101.666,17.649],[-101.919,17.916],[-102.478,17.976],[-103.501,18.292],[-103.918,18.749],[-104.992,19.316],[-105.493,19.947],[-105.731,20.434],[-105.398,20.532],[-105.501,20.817],[-105.271,21.076],[-105.266,21.422],[-105.603,21.871],[-105.693,22.269],[-106.029,22.774],[-106.91,23.768],[-107.915,24.549],[-108.402,25.172],[-109.26,25.581],[-109.444,25.825],[-109.292,26.443],[-109.801,26.676],[-110.392,27.162],[-110.641,27.86],[-111.179,27.941],[-111.76,28.468],[-112.228,28.954],[-112.272,29.267],[-112.81,30.021],[-113.164,30.787],[-113.149,31.171],[-113.872,31.568],[-114.206,31.524],[-114.776,31.8],[-114.937,31.393],[-114.771,30.914],[-114.674,30.163],[-114.331,29.75],[-113.589,29.062],[-113.424,28.826],[-113.272,28.755],[-113.14,28.411],[-112.962,28.425],[-112.762,27.78],[-112.458,27.526],[-112.245,27.172],[-111.616,26.663],[-111.285,25.733],[-110.988,25.295],[-110.71,24.826],[-110.655,24.299],[-110.173,24.266],[-109.772,23.811],[-109.409,23.365],[-109.433,23.186],[-109.854,22.818],[-110.031,22.823],[-110.295,23.431],[-110.95,24.001],[-111.671,24.484],[-112.182,24.738],[-112.149,25.47],[-112.301,26.012],[-112.777,26.322],[-113.465,26.768],[-113.597,26.639],[-113.849,26.9],[-114.466,27.142],[-115.055,27.723],[-114.982,27.798],[-114.57,27.741],[-114.199,28.115],[-114.162,28.566],[-114.932,29.279],[-115.519,29.556],[-115.887,30.181],[-116.258,30.836],[-116.722,31.636],[-117.128,32.535]]]],"translations":{"ar":"المكسيك","bs":"Meksiko","cs":"Mexiko","de":"Mexiko","es":"MĂŠxico","fa_IR":"مکزیک","fr":"Mexique","id":"Meksiko","it":"Messico","ja":"メキシコ","pl":"Meksyk","pt_BR":"MĂŠxico","pt_PT":"MĂŠxico","ru":"Мексика","uk":"Мексика","zh_CN":"墨西哥","zh_TW":"墨西哥"}},{"N":"Uruguay","I":"UY","C":[[[[-57.625,-30.216],[-56.976,-30.11],[-55.973,-30.883],[-55.602,-30.854],[-54.572,-31.495],[-53.788,-32.047],[-53.21,-32.728],[-53.651,-33.202],[-53.374,-33.768],[-53.806,-34.397],[-54.936,-34.953],[-55.674,-34.753],[-56.215,-34.86],[-57.14,-34.43],[-57.818,-34.463],[-58.427,-33.909],[-58.35,-33.263],[-58.133,-33.041],[-58.142,-32.045],[-57.875,-31.017],[-57.625,-30.216]]]],"translations":{"ar":"أورغواي","bs":"Urugvaj","cs":"Uruguay","de":"Uruguay","es":"Uruguay","fa_IR":"اروگوئه","fr":"Uruguay","id":"Uruguay","it":"Uruguay","ja":"ウルグアイ","pl":"Urugwaj","pt_BR":"Uruguai","pt_PT":"Uruguai","ru":"Уругвай","uk":"Уругвай","zh_CN":"乌拉圭","zh_TW":"烏拉圭"}},{"N":"Brazil","I":"BR","C":[[[[-53.374,-33.768],[-53.651,-33.202],[-53.21,-32.728],[-53.788,-32.047],[-54.572,-31.495],[-55.602,-30.854],[-55.973,-30.883],[-56.976,-30.11],[-57.625,-30.216],[-56.291,-28.853],[-55.162,-27.882],[-54.491,-27.475],[-53.649,-26.923],[-53.628,-26.125],[-54.13,-25.548],[-54.625,-25.739],[-54.429,-25.162],[-54.293,-24.571],[-54.293,-24.021],[-54.653,-23.84],[-55.028,-24.001],[-55.401,-23.957],[-55.518,-23.572],[-55.611,-22.656],[-55.798,-22.357],[-56.473,-22.086],[-56.882,-22.282],[-57.937,-22.09],[-57.871,-20.733],[-58.166,-20.177],[-57.854,-19.97],[-57.95,-19.4],[-57.676,-18.962],[-57.498,-18.174],[-57.735,-17.552],[-58.281,-17.272],[-58.388,-16.877],[-58.241,-16.3],[-60.158,-16.258],[-60.543,-15.094],[-60.251,-15.077],[-60.264,-14.646],[-60.459,-14.354],[-60.503,-13.776],[-61.084,-13.479],[-61.713,-13.489],[-62.127,-13.199],[-62.803,-13.001],[-63.196,-12.627],[-64.316,-12.462],[-65.402,-11.566],[-65.322,-10.896],[-65.445,-10.511],[-65.338,-9.762],[-66.647,-9.931],[-67.174,-10.307],[-68.048,-10.712],[-68.271,-11.015],[-68.786,-11.036],[-69.53,-10.952],[-70.094,-11.124],[-70.549,-11.009],[-70.482,-9.49],[-71.302,-10.079],[-72.185,-10.054],[-72.563,-9.52],[-73.227,-9.462],[-73.015,-9.033],[-73.571,-8.424],[-73.987,-7.524],[-73.723,-7.341],[-73.724,-6.919],[-73.12,-6.63],[-73.22,-6.089],[-72.965,-5.741],[-72.892,-5.275],[-71.748,-4.594],[-70.929,-4.402],[-70.795,-4.251],[-69.894,-4.298],[-69.444,-1.556],[-69.42,-1.123],[-69.577,-0.55],[-70.021,-0.185],[-70.016,0.541],[-69.452,0.706],[-69.252,0.603],[-69.219,0.986],[-69.805,1.089],[-69.817,1.715],[-67.869,1.692],[-67.538,2.037],[-67.26,1.72],[-67.065,1.13],[-66.876,1.253],[-66.326,0.724],[-65.548,0.789],[-65.355,1.095],[-64.611,1.329],[-64.199,1.493],[-64.083,1.916],[-63.369,2.201],[-63.423,2.411],[-64.27,2.497],[-64.409,3.127],[-64.368,3.797],[-64.816,4.056],[-64.629,4.148],[-63.888,4.021],[-63.093,3.771],[-62.805,4.007],[-62.085,4.162],[-60.967,4.536],[-60.601,4.918],[-60.734,5.2],[-60.214,5.244],[-59.981,5.014],[-60.111,4.575],[-59.767,4.424],[-59.538,3.959],[-59.815,3.606],[-59.975,2.755],[-59.719,2.25],[-59.646,1.787],[-59.031,1.318],[-58.54,1.268],[-58.429,1.464],[-58.113,1.507],[-57.661,1.683],[-57.336,1.949],[-56.783,1.864],[-56.539,1.9],[-55.996,1.818],[-55.906,2.022],[-56.073,2.221],[-55.973,2.51],[-55.57,2.422],[-55.098,2.524],[-54.525,2.312],[-54.088,2.106],[-53.779,2.377],[-53.555,2.335],[-53.418,2.053],[-52.94,2.125],[-52.556,2.505],[-52.249,3.241],[-51.658,4.156],[-51.317,4.203],[-51.07,3.65],[-50.509,1.902],[-49.974,1.736],[-49.947,1.046],[-50.699,0.223],[-50.388,-0.078],[-48.621,-0.235],[-48.584,-1.238],[-47.825,-0.582],[-46.567,-0.941],[-44.906,-1.552],[-44.418,-2.138],[-44.582,-2.691],[-43.419,-2.383],[-41.473,-2.912],[-39.979,-2.873],[-38.5,-3.701],[-37.223,-4.821],[-36.453,-5.109],[-35.598,-5.15],[-35.235,-5.465],[-34.896,-6.738],[-34.73,-7.343],[-35.128,-8.996],[-35.637,-9.649],[-37.047,-11.041],[-37.684,-12.171],[-38.424,-13.038],[-38.674,-13.058],[-38.953,-13.793],[-38.882,-15.667],[-39.161,-17.208],[-39.267,-17.868],[-39.584,-18.262],[-39.761,-19.599],[-40.775,-20.905],[-40.945,-21.937],[-41.754,-22.371],[-41.988,-22.97],[-43.075,-22.968],[-44.648,-23.352],[-45.352,-23.797],[-46.472,-24.089],[-47.649,-24.885],[-48.495,-25.877],[-48.641,-26.624],[-48.475,-27.176],[-48.662,-28.186],[-48.888,-28.674],[-49.587,-29.224],[-50.697,-30.984],[-51.576,-31.778],[-52.256,-32.245],[-52.712,-33.197],[-53.374,-33.768]]]],"translations":{"ar":"البرازيل","bs":"Brazil","cs":"BrazĂ­lie","de":"Brasilien","es":"Brasil","fa_IR":"برزیل","fr":"BrĂŠsil","id":"Brasil","it":"Brasile","ja":"ブラジル","pl":"Brazylia","pt_BR":"Brasil","pt_PT":"Brasil","ru":"Бразилия","uk":"Бразилія","zh_CN":"塴輿","zh_TW":"塴輿"}},{"N":"Bolivia","I":"BO","C":[[[[-69.53,-10.952],[-68.786,-11.036],[-68.271,-11.015],[-68.048,-10.712],[-67.174,-10.307],[-66.647,-9.931],[-65.338,-9.762],[-65.445,-10.511],[-65.322,-10.896],[-65.402,-11.566],[-64.316,-12.462],[-63.196,-12.627],[-62.803,-13.001],[-62.127,-13.199],[-61.713,-13.489],[-61.084,-13.479],[-60.503,-13.776],[-60.459,-14.354],[-60.264,-14.646],[-60.251,-15.077],[-60.543,-15.094],[-60.158,-16.258],[-58.241,-16.3],[-58.388,-16.877],[-58.281,-17.272],[-57.735,-17.552],[-57.498,-18.174],[-57.676,-18.962],[-57.95,-19.4],[-57.854,-19.97],[-58.166,-20.177],[-58.183,-19.868],[-59.115,-19.357],[-60.044,-19.343],[-61.786,-19.634],[-62.266,-20.514],[-62.291,-21.052],[-62.685,-22.249],[-62.846,-22.035],[-63.987,-21.994],[-64.377,-22.798],[-64.965,-22.076],[-66.273,-21.832],[-67.107,-22.736],[-67.828,-22.873],[-68.22,-21.494],[-68.757,-20.373],[-68.442,-19.405],[-68.967,-18.982],[-69.1,-18.26],[-69.59,-17.58],[-68.96,-16.501],[-69.39,-15.66],[-69.16,-15.324],[-69.34,-14.953],[-68.949,-14.454],[-68.929,-13.603],[-68.88,-12.9],[-68.665,-12.561],[-69.53,-10.952]]]],"translations":{"ar":"بوليفيا","bs":"Bolivija","cs":"BolĂ­vie","de":"Bolivien","es":"Bolivia","fa_IR":"بولیوی","fr":"Bolivie","id":"Bolivia","it":"Bolivia","ja":"ボリビア","pl":"Boliwia","pt_BR":"BolĂ­via","pt_PT":"BolĂ­via","ru":"Боливия","uk":"Болівія","zh_CN":"玻利维亚","zh_TW":"玻利維亞"}},{"N":"Peru","I":"PE","C":[[[[-69.894,-4.298],[-70.795,-4.251],[-70.929,-4.402],[-71.748,-4.594],[-72.892,-5.275],[-72.965,-5.741],[-73.22,-6.089],[-73.12,-6.63],[-73.724,-6.919],[-73.723,-7.341],[-73.987,-7.524],[-73.571,-8.424],[-73.015,-9.033],[-73.227,-9.462],[-72.563,-9.52],[-72.185,-10.054],[-71.302,-10.079],[-70.482,-9.49],[-70.549,-11.009],[-70.094,-11.124],[-69.53,-10.952],[-68.665,-12.561],[-68.88,-12.9],[-68.929,-13.603],[-68.949,-14.454],[-69.34,-14.953],[-69.16,-15.324],[-69.39,-15.66],[-68.96,-16.501],[-69.59,-17.58],[-69.858,-18.093],[-70.373,-18.348],[-71.375,-17.774],[-71.462,-17.363],[-73.445,-16.359],[-75.238,-15.266],[-76.009,-14.649],[-76.423,-13.823],[-76.259,-13.535],[-77.106,-12.223],[-78.092,-10.378],[-79.037,-8.387],[-79.446,-7.931],[-79.761,-7.194],[-80.537,-6.542],[-81.25,-6.137],[-80.926,-5.691],[-81.411,-4.737],[-81.1,-4.036],[-80.303,-3.405],[-80.184,-3.821],[-80.469,-4.059],[-80.442,-4.426],[-80.029,-4.346],[-79.625,-4.454],[-79.205,-4.959],[-78.64,-4.548],[-78.451,-3.873],[-77.838,-3.003],[-76.635,-2.609],[-75.545,-1.562],[-75.234,-0.911],[-75.373,-0.152],[-75.107,-0.057],[-74.442,-0.531],[-74.122,-1.003],[-73.66,-1.26],[-73.07,-2.309],[-72.326,-2.434],[-71.775,-2.17],[-71.414,-2.343],[-70.813,-2.257],[-70.048,-2.725],[-70.693,-3.743],[-70.394,-3.767],[-69.894,-4.298]]]],"translations":{"ar":"بيرو","bs":"Peru","cs":"Peru","de":"Peru","es":"PerĂş","fa_IR":"ٞعو","fr":"PĂŠrou","id":"Peru","it":"PerĂš","ja":"ペルー","pl":"Peru","pt_BR":"Peru","pt_PT":"Peru","ru":"Перу","uk":"Перу","zh_CN":"秘鲁","zh_TW":"秘魯"}},{"N":"Colombia","I":"CO","C":[[[[-66.876,1.253],[-67.065,1.13],[-67.26,1.72],[-67.538,2.037],[-67.869,1.692],[-69.817,1.715],[-69.805,1.089],[-69.219,0.986],[-69.252,0.603],[-69.452,0.706],[-70.016,0.541],[-70.021,-0.185],[-69.577,-0.55],[-69.42,-1.123],[-69.444,-1.556],[-69.894,-4.298],[-70.394,-3.767],[-70.693,-3.743],[-70.048,-2.725],[-70.813,-2.257],[-71.414,-2.343],[-71.775,-2.17],[-72.326,-2.434],[-73.07,-2.309],[-73.66,-1.26],[-74.122,-1.003],[-74.442,-0.531],[-75.107,-0.057],[-75.373,-0.152],[-75.801,0.085],[-76.292,0.416],[-76.576,0.257],[-77.425,0.396],[-77.669,0.826],[-77.855,0.81],[-78.855,1.381],[-78.991,1.691],[-78.618,1.766],[-78.662,2.267],[-78.428,2.63],[-77.932,2.697],[-77.51,3.325],[-77.128,3.85],[-77.496,4.088],[-77.308,4.668],[-77.533,5.583],[-77.319,5.845],[-77.477,6.691],[-77.882,7.224],[-77.753,7.71],[-77.431,7.638],[-77.243,7.935],[-77.475,8.524],[-77.353,8.671],[-76.837,8.639],[-76.086,9.337],[-75.675,9.443],[-75.665,9.774],[-75.48,10.619],[-74.907,11.083],[-74.277,11.102],[-74.197,11.31],[-73.415,11.227],[-72.628,11.732],[-72.238,11.956],[-71.754,12.437],[-71.4,12.376],[-71.137,12.113],[-71.332,11.776],[-71.974,11.609],[-72.228,11.109],[-72.615,10.822],[-72.905,10.45],[-73.028,9.737],[-73.305,9.152],[-72.789,9.085],[-72.66,8.625],[-72.44,8.405],[-72.361,8.003],[-72.48,7.633],[-72.444,7.424],[-72.198,7.34],[-71.96,6.992],[-70.674,7.088],[-70.093,6.96],[-69.389,6.1],[-68.985,6.207],[-68.265,6.153],[-67.695,6.267],[-67.341,6.095],[-67.522,5.557],[-67.745,5.221],[-67.823,4.504],[-67.622,3.839],[-67.338,3.542],[-67.303,3.318],[-67.81,2.821],[-67.447,2.6],[-67.181,2.251],[-66.876,1.253]]]],"translations":{"ar":"كولومبيا","bs":"Kolumbija","cs":"Kolumbie","de":"Kolumbien","es":"Colombia","fa_IR":"کلمبیا","fr":"Colombie","id":"Kolombia","it":"Colombia","ja":"コロンビア","pl":"Kolumbia","pt_BR":"ColĂ´mbia","pt_PT":"ColĂ´mbia","ru":"Колумбия","uk":"Колумбія","zh_CN":"哥伦比亚","zh_TW":"哥倫比亞"}},{"N":"Panama","I":"PA","C":[[[[-77.353,8.671],[-77.475,8.524],[-77.243,7.935],[-77.431,7.638],[-77.753,7.71],[-77.882,7.224],[-78.215,7.512],[-78.429,8.052],[-78.182,8.319],[-78.435,8.388],[-78.622,8.718],[-79.12,8.996],[-79.558,8.932],[-79.761,8.585],[-80.164,8.333],[-80.383,8.298],[-80.481,8.09],[-80.004,7.548],[-80.277,7.42],[-80.421,7.272],[-80.886,7.221],[-81.06,7.818],[-81.19,7.648],[-81.52,7.707],[-81.721,8.109],[-82.131,8.175],[-82.391,8.292],[-82.82,8.291],[-82.851,8.074],[-82.966,8.225],[-82.913,8.424],[-82.83,8.626],[-82.869,8.807],[-82.719,8.926],[-82.927,9.074],[-82.933,9.477],[-82.546,9.566],[-82.187,9.207],[-82.208,8.996],[-81.809,8.951],[-81.714,9.032],[-81.439,8.786],[-80.947,8.859],[-80.522,9.111],[-79.915,9.313],[-79.573,9.612],[-79.021,9.553],[-79.058,9.455],[-78.501,9.42],[-78.056,9.248],[-77.73,8.947],[-77.353,8.671]]]],"translations":{"ar":"بنما","bs":"Panama","cs":"Panama","de":"Panama","es":"PanamĂĄ","fa_IR":"پاناما","fr":"Panama","id":"Panama","it":"Panama","ja":"パナマ","pl":"Panama","pt_BR":"PanamĂĄ","pt_PT":"PanamĂĄ","ru":"Панама","uk":"Панама","zh_CN":"巴拿马","zh_TW":"巴拿馬"}},{"N":"Costa Rica","I":"CR","C":[[[[-82.546,9.566],[-82.933,9.477],[-82.927,9.074],[-82.719,8.926],[-82.869,8.807],[-82.83,8.626],[-82.913,8.424],[-82.966,8.225],[-83.508,8.447],[-83.711,8.657],[-83.596,8.83],[-83.633,9.051],[-83.91,9.291],[-84.303,9.487],[-84.648,9.616],[-84.713,9.908],[-84.976,10.087],[-84.911,9.796],[-85.111,9.557],[-85.339,9.835],[-85.661,9.933],[-85.797,10.135],[-85.792,10.439],[-85.659,10.754],[-85.942,10.895],[-85.713,11.088],[-85.562,11.217],[-84.903,10.952],[-84.673,11.083],[-84.356,10.999],[-84.19,10.793],[-83.895,10.727],[-83.656,10.939],[-83.402,10.395],[-83.016,9.993],[-82.546,9.566]]]],"translations":{"ar":"كوستاريكا","bs":"Kostarika","cs":"Kostarika","de":"Costa Rica","es":"Costa Rica","fa_IR":"کاستاریکا","fr":"Costa Rica","id":"Kosta Rika","it":"Costa Rica","ja":"コスタリカ","pl":"Kostaryka","pt_BR":"Costa Rica","pt_PT":"Costa Rica","ru":"Коста-Рика","uk":"Коста-Рика","zh_CN":"哥斯达黎加","zh_TW":"哥斯大黎加"}},{"N":"Nicaragua","I":"NI","C":[[[[-83.656,10.939],[-83.895,10.727],[-84.19,10.793],[-84.356,10.999],[-84.673,11.083],[-84.903,10.952],[-85.562,11.217],[-85.713,11.088],[-86.058,11.403],[-86.526,11.807],[-86.746,12.144],[-87.168,12.458],[-87.668,12.91],[-87.557,13.065],[-87.392,12.914],[-87.317,12.985],[-87.006,13.026],[-86.881,13.254],[-86.734,13.263],[-86.755,13.755],[-86.521,13.778],[-86.312,13.771],[-86.096,14.038],[-85.801,13.836],[-85.699,13.96],[-85.514,14.079],[-85.165,14.354],[-85.149,14.56],[-85.053,14.552],[-84.925,14.79],[-84.82,14.82],[-84.65,14.667],[-84.449,14.622],[-84.228,14.749],[-83.976,14.749],[-83.629,14.88],[-83.49,15.016],[-83.147,14.996],[-83.233,14.9],[-83.284,14.677],[-83.182,14.311],[-83.412,13.97],[-83.52,13.568],[-83.552,13.127],[-83.499,12.869],[-83.473,12.419],[-83.626,12.321],[-83.72,11.893],[-83.651,11.629],[-83.855,11.373],[-83.809,11.103],[-83.656,10.939]]]],"translations":{"ar":"نيكاراغوا","bs":"Nikaragva","cs":"Nikaragua","de":"Nicaragua","es":"Nicaragua","fa_IR":"نیکاراگوئه","fr":"Nicaragua","id":"Nikaragua","it":"Nicaragua","ja":"ニカラグア","pl":"Nikaragua","pt_BR":"NicarĂĄgua","pt_PT":"NicarĂĄgua","ru":"Никарагуа","uk":"Нікарагуа","zh_CN":"尼加拉瓜","zh_TW":"尼加拉瓜"}},{"N":"Honduras","I":"HN","C":[[[[-83.147,14.996],[-83.49,15.016],[-83.629,14.88],[-83.976,14.749],[-84.228,14.749],[-84.449,14.622],[-84.65,14.667],[-84.82,14.82],[-84.925,14.79],[-85.053,14.552],[-85.149,14.56],[-85.165,14.354],[-85.514,14.079],[-85.699,13.96],[-85.801,13.836],[-86.096,14.038],[-86.312,13.771],[-86.521,13.778],[-86.755,13.755],[-86.734,13.263],[-86.881,13.254],[-87.006,13.026],[-87.317,12.985],[-87.489,13.298],[-87.793,13.384],[-87.724,13.785],[-87.86,13.893],[-88.065,13.965],[-88.504,13.845],[-88.541,13.98],[-88.843,14.141],[-89.059,14.34],[-89.353,14.424],[-89.146,14.678],[-89.225,14.874],[-89.155,15.066],[-88.681,15.346],[-88.225,15.728],[-88.121,15.689],[-87.902,15.864],[-87.616,15.879],[-87.523,15.797],[-87.368,15.847],[-86.903,15.757],[-86.441,15.783],[-86.119,15.893],[-86.002,16.005],[-85.683,15.954],[-85.444,15.886],[-85.182,15.909],[-84.984,15.996],[-84.527,15.857],[-84.368,15.835],[-84.063,15.648],[-83.774,15.424],[-83.41,15.271],[-83.147,14.996]]]],"translations":{"ar":"هندوراس","bs":"Honduras","cs":"Honduras","de":"Honduras","es":"Honduras","fa_IR":"هندوراس","fr":"Honduras","id":"Honduras","it":"Honduras","ja":"ホンジュラス","pl":"Honduras","pt_BR":"Honduras","pt_PT":"Honduras","ru":"Гондурас","uk":"Гондурас","zh_CN":"洪都拉斯","zh_TW":"宏都拉斯"}},{"N":"El Salvador","I":"SV","C":[[[[-89.353,14.424],[-89.059,14.34],[-88.843,14.141],[-88.541,13.98],[-88.504,13.845],[-88.065,13.965],[-87.86,13.893],[-87.724,13.785],[-87.793,13.384],[-87.904,13.149],[-88.483,13.164],[-88.843,13.26],[-89.257,13.459],[-89.812,13.521],[-90.096,13.735],[-90.065,13.882],[-89.722,14.134],[-89.534,14.245],[-89.587,14.363],[-89.353,14.424]]]],"translations":{"ar":"السلفادور","bs":"Salvador","cs":"Salvador","de":"El Salvador","es":"El Salvador","fa_IR":"السالوادور","fr":"Salvador","id":"El Salvador","it":"El Salvador","ja":"エルサルバドル","pl":"Salwador","pt_BR":"El Salvador","pt_PT":"Salvador","ru":"Сальвадор","uk":"Сальвадор","zh_CN":"萨尔瓦多","zh_TW":"薩爾瓦多"}},{"N":"Guatemala","I":"GT","C":[[[[-92.228,14.539],[-92.203,14.83],[-92.087,15.065],[-92.229,15.251],[-91.748,16.067],[-90.464,16.07],[-90.439,16.41],[-90.601,16.471],[-90.712,16.687],[-91.082,16.918],[-91.454,17.252],[-91.002,17.255],[-91.002,17.818],[-90.068,17.819],[-89.143,17.808],[-89.151,17.016],[-89.229,15.887],[-88.931,15.887],[-88.605,15.706],[-88.518,15.855],[-88.225,15.728],[-88.681,15.346],[-89.155,15.066],[-89.225,14.874],[-89.146,14.678],[-89.353,14.424],[-89.587,14.363],[-89.534,14.245],[-89.722,14.134],[-90.065,13.882],[-90.096,13.735],[-90.609,13.91],[-91.232,13.928],[-91.69,14.126],[-92.228,14.539]]]],"translations":{"ar":"غواتيمالا","bs":"Gvatemala","cs":"Guatemala","de":"Guatemala","es":"Guatemala","fa_IR":"گواتمالا","fr":"Guatemala","id":"Guatemala","it":"Guatemala","ja":"グアテマラ","pl":"Gwatemala","pt_BR":"Guatemala","pt_PT":"Guatemala","ru":"Гватемала","uk":"Гватемала","zh_CN":"危地马拉","zh_TW":"瓜地馬拉"}},{"N":"Belize","I":"BZ","C":[[[[-89.143,17.808],[-89.151,17.955],[-89.03,18.002],[-88.848,17.883],[-88.49,18.487],[-88.3,18.5],[-88.296,18.353],[-88.107,18.349],[-88.123,18.077],[-88.285,17.644],[-88.198,17.489],[-88.303,17.132],[-88.24,17.036],[-88.355,16.531],[-88.552,16.265],[-88.732,16.234],[-88.931,15.887],[-89.229,15.887],[-89.151,17.016],[-89.143,17.808]]]],"translations":{"ar":"بليز","bs":"Belize","cs":"Belize","de":"Belize","es":"Belice","fa_IR":"بلیز","fr":"Belize","id":"Belize","it":"Belize","ja":"ベリーズ","pl":"Belize","pt_BR":"Belize","pt_PT":"Belize","ru":"Белиз","uk":"Беліз","zh_CN":"伯利兹","zh_TW":"貝里斯"}},{"N":"Venezuela","I":"VE","C":[[[[-60.734,5.2],[-60.601,4.918],[-60.967,4.536],[-62.085,4.162],[-62.805,4.007],[-63.093,3.771],[-63.888,4.021],[-64.629,4.148],[-64.816,4.056],[-64.368,3.797],[-64.409,3.127],[-64.27,2.497],[-63.423,2.411],[-63.369,2.201],[-64.083,1.916],[-64.199,1.493],[-64.611,1.329],[-65.355,1.095],[-65.548,0.789],[-66.326,0.724],[-66.876,1.253],[-67.181,2.251],[-67.447,2.6],[-67.81,2.821],[-67.303,3.318],[-67.338,3.542],[-67.622,3.839],[-67.823,4.504],[-67.745,5.221],[-67.522,5.557],[-67.341,6.095],[-67.695,6.267],[-68.265,6.153],[-68.985,6.207],[-69.389,6.1],[-70.093,6.96],[-70.674,7.088],[-71.96,6.992],[-72.198,7.34],[-72.444,7.424],[-72.48,7.633],[-72.361,8.003],[-72.44,8.405],[-72.66,8.625],[-72.789,9.085],[-73.305,9.152],[-73.028,9.737],[-72.905,10.45],[-72.615,10.822],[-72.228,11.109],[-71.974,11.609],[-71.332,11.776],[-71.36,11.54],[-71.947,11.423],[-71.621,10.969],[-71.633,10.446],[-72.074,9.866],[-71.696,9.072],[-71.265,9.137],[-71.04,9.86],[-71.35,10.212],[-71.401,10.969],[-70.155,11.375],[-70.294,11.847],[-69.943,12.162],[-69.584,11.46],[-68.883,11.443],[-68.233,10.886],[-68.194,10.555],[-67.296,10.546],[-66.228,10.649],[-65.655,10.201],[-64.89,10.077],[-64.329,10.39],[-64.318,10.641],[-63.079,10.702],[-61.881,10.716],[-62.73,10.42],[-62.389,9.948],[-61.589,9.873],[-60.831,9.381],[-60.671,8.58],[-60.15,8.603],[-59.758,8.367],[-60.551,7.78],[-60.638,7.415],[-60.296,7.044],[-60.544,6.857],[-61.159,6.696],[-61.139,6.234],[-61.41,5.959],[-60.734,5.2]]]],"translations":{"ar":"فنزويلا","bs":"Venecuela","cs":"Venezuela","de":"Venezuela","es":"Venezuela","fa_IR":"ونزوئلا","fr":"Venezuela","id":"Venezuela","it":"Venezuela","ja":"ベネズエラ","pl":"Wenezuela","pt_BR":"Venezuela","pt_PT":"Venezuela","ru":"Венесуэла","uk":"Венесуела","zh_CN":"委内瑞拉","zh_TW":"委內瑞拉"}},{"N":"Guyana","I":"GY","C":[[[[-56.539,1.9],[-56.783,1.864],[-57.336,1.949],[-57.661,1.683],[-58.113,1.507],[-58.429,1.464],[-58.54,1.268],[-59.031,1.318],[-59.646,1.787],[-59.719,2.25],[-59.975,2.755],[-59.815,3.606],[-59.538,3.959],[-59.767,4.424],[-60.111,4.575],[-59.981,5.014],[-60.214,5.244],[-60.734,5.2],[-61.41,5.959],[-61.139,6.234],[-61.159,6.696],[-60.544,6.857],[-60.296,7.044],[-60.638,7.415],[-60.551,7.78],[-59.758,8.367],[-59.102,7.999],[-58.483,7.348],[-58.455,6.833],[-58.078,6.809],[-57.542,6.321],[-57.147,5.973],[-57.307,5.074],[-57.914,4.813],[-57.86,4.577],[-58.045,4.061],[-57.602,3.335],[-57.281,3.333],[-57.15,2.769],[-56.539,1.9]]]],"translations":{"ar":"غيانا","bs":"Gvajana","cs":"Guyana","de":"Guyana","es":"Guyana","fa_IR":"گویان","fr":"Guyana","id":"Guyana","it":"Guyana","ja":"ガイアナ","pl":"Gujana","pt_BR":"Guiana","pt_PT":"Guiana","ru":"Гайана","uk":"Гаяна","zh_CN":"圭亚那","zh_TW":"蓋亞那"}},{"N":"Suriname","I":"SR","C":[[[[-54.525,2.312],[-55.098,2.524],[-55.57,2.422],[-55.973,2.51],[-56.073,2.221],[-55.906,2.022],[-55.996,1.818],[-56.539,1.9],[-57.15,2.769],[-57.281,3.333],[-57.602,3.335],[-58.045,4.061],[-57.86,4.577],[-57.914,4.813],[-57.307,5.074],[-57.147,5.973],[-55.949,5.773],[-55.842,5.953],[-55.033,6.025],[-53.958,5.757],[-54.479,4.897],[-54.4,4.213],[-54.007,3.62],[-54.182,3.19],[-54.27,2.732],[-54.525,2.312]]]],"translations":{"ar":"سورينام","bs":"Surinam","cs":"Surinam","de":"Suriname","es":"Surinam","fa_IR":"سورینام","fr":"Suriname","id":"Suriname","it":"Suriname","ja":"スリナム","pl":"Surinam","pt_BR":"Suriname","pt_PT":"Suriname","ru":"Суринам","uk":"Суринам","zh_CN":"苏里南","zh_TW":"蘇利南"}},{"N":"France","I":"FR","C":[[[[-51.658,4.156],[-52.249,3.241],[-52.556,2.505],[-52.94,2.125],[-53.418,2.053],[-53.555,2.335],[-53.779,2.377],[-54.088,2.106],[-54.525,2.312],[-54.27,2.732],[-54.182,3.19],[-54.007,3.62],[-54.4,4.213],[-54.479,4.897],[-53.958,5.757],[-53.618,5.647],[-52.882,5.41],[-51.823,4.566],[-51.658,4.156]]],[[[8.746,42.628],[9.39,43.01],[9.56,42.152],[9.23,41.38],[8.776,41.584],[8.544,42.257],[8.746,42.628]]],[[[6.186,49.464],[6.658,49.202],[8.099,49.018],[7.594,48.333],[7.467,47.621],[7.192,47.45],[6.737,47.542],[6.769,47.288],[6.037,46.726],[6.023,46.273],[6.5,46.43],[6.844,45.991],[6.802,45.709],[7.097,45.333],[6.75,45.029],[7.008,44.255],[7.55,44.128],[7.435,43.694],[6.529,43.129],[4.557,43.4],[3.1,43.075],[2.986,42.473],[1.827,42.343],[0.702,42.796],[0.338,42.58],[-1.503,43.034],[-1.901,43.423],[-1.384,44.023],[-1.194,46.015],[-2.226,47.064],[-2.963,47.57],[-4.492,47.955],[-4.592,48.684],[-3.296,48.902],[-1.617,48.644],[-1.933,49.776],[-0.989,49.347],[1.339,50.127],[1.639,50.947],[2.514,51.149],[2.658,50.797],[3.123,50.78],[3.588,50.379],[4.286,49.907],[4.799,49.985],[5.674,49.529],[5.898,49.443],[6.186,49.464]]],[[[8.746,42.628],[9.39,43.01],[9.56,42.152],[9.23,41.38],[8.776,41.584],[8.544,42.257],[8.746,42.628]]]],"translations":{"ar":"فرنسا","bs":"Francuska","cs":"Francie","de":"Frankreich","es":"Francia","fa_IR":"فرانسه","fr":"France","id":"Prancis","it":"Francia","ja":"フランス","pl":"Francja","pt_BR":"França","pt_PT":"França","ru":"Франция","uk":"Франція","zh_CN":"法国","zh_TW":"法國"}},{"N":"Ecuador","I":"EC","C":[[[[-75.373,-0.152],[-75.234,-0.911],[-75.545,-1.562],[-76.635,-2.609],[-77.838,-3.003],[-78.451,-3.873],[-78.64,-4.548],[-79.205,-4.959],[-79.625,-4.454],[-80.029,-4.346],[-80.442,-4.426],[-80.469,-4.059],[-80.184,-3.821],[-80.303,-3.405],[-79.77,-2.658],[-79.987,-2.221],[-80.369,-2.685],[-80.968,-2.247],[-80.765,-1.965],[-80.934,-1.057],[-80.583,-0.907],[-80.399,-0.284],[-80.021,0.36],[-80.091,0.768],[-79.543,0.983],[-78.855,1.381],[-77.855,0.81],[-77.669,0.826],[-77.425,0.396],[-76.576,0.257],[-76.292,0.416],[-75.801,0.085],[-75.373,-0.152]]]],"translations":{"ar":"الإكوادور","bs":"Ekvador","cs":"EkvĂĄdor","de":"Ecuador","es":"Ecuador","fa_IR":"اڊوادوع","fr":"Équateur","id":"Ekuador","it":"Ecuador","ja":"エクアドル","pl":"Ekwador","pt_BR":"Equador","pt_PT":"Equador","ru":"Эквадор","uk":"Еквадор","zh_CN":"厄瓜多尔","zh_TW":"厄瓜多"}},{"N":"Puerto Rico","I":"PR","C":[[[[-66.282,18.515],[-65.771,18.427],[-65.591,18.228],[-65.847,17.976],[-66.6,17.982],[-67.184,17.947],[-67.242,18.374],[-67.101,18.521],[-66.282,18.515]]]],"translations":{"ar":"بورتوريكو","bs":"Porto Riko","cs":"Portoriko","de":"Puerto Rico","es":"Puerto Rico","fa_IR":"پورتوریکو","fr":"Porto Rico","id":"Puerto Riko","it":"Portorico","ja":"プエルトリコ","pl":"Portoryko","pt_BR":"Porto Rico","pt_PT":"Porto Rico","ru":"Пуэрто-РикО","uk":"Пуерто-РикО","zh_CN":"波多黎各","zh_TW":"波多黎各"}},{"N":"Jamaica","I":"JM","C":[[[[-77.57,18.491],[-76.897,18.401],[-76.365,18.161],[-76.2,17.887],[-76.903,17.868],[-77.206,17.701],[-77.766,17.862],[-78.338,18.226],[-78.218,18.455],[-77.797,18.524],[-77.57,18.491]]]],"translations":{"ar":"جامايكا","bs":"Jamajka","cs":"Jamajka","de":"Jamaika","es":"Jamaica","fa_IR":"جامائیکا","fr":"JamaĂŻque","id":"Jamaika","it":"Giamaica","ja":"ジャマイカ","pl":"Jamajka","pt_BR":"Jamaica","pt_PT":"Jamaica","ru":"ЯПаКка","uk":"ЯПаКка","zh_CN":"牙买加","zh_TW":"牙買加"}},{"N":"Cuba","I":"CU","C":[[[[-82.268,23.189],[-81.404,23.117],[-80.619,23.106],[-79.68,22.765],[-79.281,22.399],[-78.347,22.512],[-77.993,22.277],[-77.146,21.658],[-76.524,21.207],[-76.195,21.221],[-75.598,21.017],[-75.671,20.735],[-74.934,20.694],[-74.178,20.285],[-74.297,20.05],[-74.962,19.923],[-75.635,19.874],[-76.324,19.953],[-77.755,19.855],[-77.085,20.413],[-77.493,20.673],[-78.137,20.74],[-78.483,21.029],[-78.72,21.598],[-79.285,21.559],[-80.217,21.827],[-80.518,22.037],[-81.821,22.192],[-82.17,22.387],[-81.795,22.637],[-82.776,22.688],[-83.494,22.169],[-83.909,22.155],[-84.052,21.911],[-84.547,21.801],[-84.975,21.896],[-84.447,22.205],[-84.23,22.566],[-83.778,22.788],[-83.268,22.983],[-82.51,23.079],[-82.268,23.189]]]],"translations":{"ar":"كوبا","bs":"Kuba","cs":"Kuba","de":"Kuba","es":"Cuba","fa_IR":"ڊوبا","fr":"Cuba","id":"Kuba","it":"Cuba","ja":"キューバ","pl":"Kuba","pt_BR":"Cuba","pt_PT":"Cuba","ru":"Куба","uk":"Куба","zh_CN":"古巴","zh_TW":"古巴"}},{"N":"Zimbabwe","I":"ZW","C":[[[[31.191,-22.252],[30.66,-22.152],[30.323,-22.272],[29.839,-22.102],[29.432,-22.091],[28.795,-21.639],[28.021,-21.486],[27.727,-20.852],[27.725,-20.499],[27.297,-20.392],[26.165,-19.293],[25.85,-18.714],[25.649,-18.536],[25.264,-17.737],[26.382,-17.846],[26.707,-17.961],[27.044,-17.938],[27.598,-17.291],[28.468,-16.468],[28.826,-16.39],[28.947,-16.043],[29.517,-15.645],[30.274,-15.508],[30.339,-15.881],[31.173,-15.861],[31.636,-16.072],[31.852,-16.319],[32.328,-16.392],[32.848,-16.713],[32.85,-17.979],[32.655,-18.672],[32.612,-19.419],[32.773,-19.716],[32.66,-20.304],[32.509,-20.395],[32.245,-21.116],[31.191,-22.252]]]],"translations":{"ar":"زيمبابوي","bs":"Zimbabve","cs":"Zimbabwe","de":"Simbabwe","es":"Zimbabue","fa_IR":"زیمبابوه","fr":"Zimbabwe","id":"Zimbabwe","it":"Zimbabwe","ja":"ジンバブエ","pl":"Zimbabwe","pt_BR":"ZimbĂĄbue","pt_PT":"ZimbabuĂŠ","ru":"Зимбабве","uk":"Зімбабве","zh_CN":"津巴布韦","zh_TW":"辛巴威"}},{"N":"Botswana","I":"BW","C":[[[[29.432,-22.091],[28.017,-22.828],[27.119,-23.574],[26.786,-24.241],[26.486,-24.616],[25.942,-24.696],[25.766,-25.175],[25.665,-25.487],[25.025,-25.72],[24.211,-25.67],[23.734,-25.39],[23.312,-25.269],[22.824,-25.5],[22.58,-25.979],[22.106,-26.28],[21.606,-26.727],[20.89,-26.829],[20.666,-26.477],[20.759,-25.868],[20.166,-24.918],[19.896,-24.768],[19.895,-21.849],[20.881,-21.814],[20.911,-18.252],[21.655,-18.219],[23.197,-17.869],[23.579,-18.281],[24.217,-17.889],[24.521,-17.887],[25.084,-17.662],[25.264,-17.737],[25.649,-18.536],[25.85,-18.714],[26.165,-19.293],[27.297,-20.392],[27.725,-20.499],[27.727,-20.852],[28.021,-21.486],[28.795,-21.639],[29.432,-22.091]]]],"translations":{"ar":"بوتسوانا","bs":"Bocvana","cs":"Botswana","de":"Botsuana","es":"Botsuana","fa_IR":"بوتسوانا","fr":"Botswana","id":"Botswana","it":"Botswana","ja":"ボツワナ","pl":"Botswana","pt_BR":"Botsuana","pt_PT":"Botsuana","ru":"Ботсвана","uk":"Ботсвана","zh_CN":"博茨瓦纳","zh_TW":"波札那"}},{"N":"Namibia","I":"NA","C":[[[[19.896,-24.768],[19.895,-28.461],[19.002,-28.972],[18.465,-29.045],[17.836,-28.856],[17.387,-28.784],[17.219,-28.356],[16.824,-28.082],[16.345,-28.577],[15.602,-27.821],[15.21,-27.091],[14.99,-26.117],[14.743,-25.393],[14.408,-23.853],[14.386,-22.657],[14.258,-22.111],[13.869,-21.699],[13.352,-20.873],[12.827,-19.673],[12.609,-19.045],[11.795,-18.069],[11.734,-17.302],[12.215,-17.112],[12.814,-16.941],[13.462,-16.971],[14.059,-17.423],[14.21,-17.353],[18.263,-17.31],[18.956,-17.789],[21.377,-17.931],[23.215,-17.523],[24.034,-17.296],[24.682,-17.353],[25.077,-17.579],[25.084,-17.662],[24.521,-17.887],[24.217,-17.889],[23.579,-18.281],[23.197,-17.869],[21.655,-18.219],[20.911,-18.252],[20.881,-21.814],[19.895,-21.849],[19.896,-24.768]]]],"translations":{"ar":"ناميبيا","bs":"Namibija","cs":"Namibie","de":"Namibia","es":"Namibia","fa_IR":"نامیبیا","fr":"Namibie","id":"Namibia","it":"Namibia","ja":"ナミビア","pl":"Namibia","pt_BR":"NamĂ­bia","pt_PT":"NamĂ­bia","ru":"Намибия","uk":"Намібія","zh_CN":"纳米比亚","zh_TW":"納米比亞"}},{"N":"Senegal","I":"SN","C":[[[[-16.714,13.595],[-17.126,14.374],[-17.625,14.73],[-17.185,14.919],[-16.701,15.622],[-16.463,16.135],[-16.121,16.456],[-15.624,16.369],[-15.136,16.587],[-14.577,16.598],[-14.1,16.304],[-13.436,16.039],[-12.831,15.304],[-12.171,14.617],[-12.125,13.995],[-11.928,13.422],[-11.553,13.141],[-11.468,12.755],[-11.514,12.443],[-11.658,12.387],[-12.204,12.466],[-12.279,12.354],[-12.499,12.332],[-13.218,12.576],[-13.7,12.586],[-15.548,12.628],[-15.817,12.516],[-16.148,12.548],[-16.677,12.385],[-16.842,13.151],[-15.931,13.13],[-15.691,13.27],[-15.512,13.279],[-15.141,13.51],[-14.712,13.298],[-14.278,13.281],[-13.845,13.505],[-14.047,13.794],[-14.377,13.626],[-14.687,13.63],[-15.082,13.876],[-15.399,13.86],[-15.625,13.624],[-16.714,13.595]]]],"translations":{"ar":"السنغال","bs":"Senegal","cs":"Senegal","de":"Senegal","es":"Senegal","fa_IR":"سنگال","fr":"SĂŠnĂŠgal","id":"Senegal","it":"Senegal","ja":"セネガル","pl":"Senegal","pt_BR":"Senegal","pt_PT":"Senegal","ru":"ХоногаН","uk":"ХоногаН","zh_CN":"塞内加尔","zh_TW":"塞內加爾"}},{"N":"Mali","I":"ML","C":[[[[-11.514,12.443],[-11.468,12.755],[-11.553,13.141],[-11.928,13.422],[-12.125,13.995],[-12.171,14.617],[-11.834,14.799],[-11.666,15.388],[-11.349,15.411],[-10.651,15.133],[-10.087,15.33],[-9.7,15.264],[-9.55,15.486],[-5.538,15.502],[-5.315,16.202],[-5.489,16.325],[-5.971,20.641],[-6.454,24.957],[-4.923,24.975],[-1.55,22.793],[1.823,20.611],[2.061,20.142],[2.684,19.856],[3.147,19.694],[3.158,19.057],[4.267,19.155],[4.27,16.852],[3.723,16.184],[3.638,15.568],[2.75,15.41],[1.386,15.324],[1.016,14.968],[0.375,14.929],[-0.266,14.924],[-0.516,15.116],[-1.066,14.974],[-2.001,14.559],[-2.192,14.246],[-2.968,13.798],[-3.104,13.541],[-3.523,13.338],[-4.006,13.472],[-4.28,13.228],[-4.427,12.543],[-5.221,11.714],[-5.198,11.375],[-5.471,10.951],[-5.404,10.371],[-5.817,10.223],[-6.05,10.096],[-6.205,10.524],[-6.494,10.411],[-6.666,10.431],[-6.851,10.139],[-7.623,10.147],[-7.9,10.297],[-8.03,10.207],[-8.335,10.495],[-8.282,10.793],[-8.407,10.909],[-8.62,10.811],[-8.581,11.136],[-8.376,11.394],[-8.786,11.813],[-8.905,12.088],[-9.127,12.308],[-9.328,12.334],[-9.568,12.194],[-9.891,12.06],[-10.165,11.844],[-10.593,11.924],[-10.871,12.178],[-11.037,12.211],[-11.298,12.078],[-11.456,12.077],[-11.514,12.443]]]],"translations":{"ar":"مالي","bs":"Mali","cs":"Mali","de":"Mali","es":"Mali","fa_IR":"مالی","fr":"Mali","id":"Mali","it":"Mali","ja":"マリ","pl":"Mali","pt_BR":"Mali","pt_PT":"Mali","ru":"Мали","uk":"Малі","zh_CN":"马里","zh_TW":"錏刊"}},{"N":"Mauritania","I":"MR","C":[[[[-17.063,21],[-16.845,21.333],[-12.929,21.327],[-13.119,22.771],[-12.874,23.285],[-11.937,23.375],[-11.969,25.933],[-8.687,25.881],[-8.684,27.396],[-4.923,24.975],[-6.454,24.957],[-5.971,20.641],[-5.489,16.325],[-5.315,16.202],[-5.538,15.502],[-9.55,15.486],[-9.7,15.264],[-10.087,15.33],[-10.651,15.133],[-11.349,15.411],[-11.666,15.388],[-11.834,14.799],[-12.171,14.617],[-12.831,15.304],[-13.436,16.039],[-14.1,16.304],[-14.577,16.598],[-15.136,16.587],[-15.624,16.369],[-16.121,16.456],[-16.463,16.135],[-16.55,16.674],[-16.271,17.167],[-16.146,18.108],[-16.257,19.097],[-16.378,19.594],[-16.278,20.093],[-16.536,20.568],[-17.063,21]]]],"translations":{"ar":"موريتانيا","bs":"Mauritanija","cs":"MauritĂĄnie","de":"Mauretanien","es":"Mauritania","fa_IR":"موریتانی","fr":"Mauritanie","id":"Mauritania","it":"Mauritania","ja":"モーリタニア","pl":"Mauretania","pt_BR":"Mauritânia","pt_PT":"Mauritânia","ru":"Мавритания","uk":"Мавританія","zh_CN":"毛里塔尼亚","zh_TW":"茅利塔尼亞"}},{"N":"Benin","I":"BJ","C":[[[[2.692,6.259],[1.865,6.142],[1.619,6.832],[1.664,9.129],[1.463,9.335],[1.425,9.825],[1.078,10.176],[0.772,10.471],[0.9,10.997],[1.243,11.111],[1.447,11.548],[1.936,11.641],[2.154,11.94],[2.49,12.233],[2.849,12.236],[3.611,11.66],[3.572,11.328],[3.797,10.735],[3.6,10.332],[3.705,10.063],[3.22,9.444],[2.912,9.138],[2.724,8.507],[2.749,7.871],[2.692,6.259]]]],"translations":{"ar":"بنين","bs":"Benin","cs":"Benin","de":"Benin","es":"BenĂ­n","fa_IR":"بنین","fr":"BĂŠnin","id":"Benin","it":"Benin","ja":"ベナン","pl":"Benin","pt_BR":"Benin","pt_PT":"Benim","ru":"Бенин","uk":"Бенін","zh_CN":"贝宁","zh_TW":"貝南"}},{"N":"Niger","I":"NE","C":[[[[14.851,22.863],[15.097,21.309],[15.471,21.048],[15.487,20.73],[15.903,20.388],[15.686,19.957],[15.3,17.928],[15.248,16.627],[13.972,15.684],[13.54,14.367],[13.957,13.997],[13.954,13.353],[14.596,13.33],[14.496,12.859],[14.214,12.802],[14.181,12.484],[13.995,12.462],[13.319,13.556],[13.084,13.596],[12.302,13.037],[11.528,13.329],[10.99,13.387],[10.701,13.247],[10.115,13.277],[9.525,12.851],[9.015,12.827],[7.805,13.344],[7.331,13.098],[6.82,13.115],[6.445,13.493],[5.443,13.866],[4.368,13.747],[4.108,13.531],[3.967,12.956],[3.681,12.553],[3.611,11.66],[2.849,12.236],[2.49,12.233],[2.154,11.94],[2.177,12.625],[1.024,12.852],[0.993,13.336],[0.43,13.989],[0.296,14.444],[0.375,14.929],[1.016,14.968],[1.386,15.324],[2.75,15.41],[3.638,15.568],[3.723,16.184],[4.27,16.852],[4.267,19.155],[5.678,19.601],[8.573,21.566],[12,23.472],[13.581,23.041],[14.144,22.491],[14.851,22.863]]]],"translations":{"ar":"النيجر","bs":"Niger","cs":"Niger","de":"Niger","es":"NĂ­ger","fa_IR":"نیجر","fr":"Niger","id":"Niger","it":"Niger","ja":"ニジェール","pl":"Niger","pt_BR":"NĂ­ger","pt_PT":"NĂ­ger","ru":"Нигер","uk":"Нігер","zh_CN":"尼日尔","zh_TW":"尼日"}},{"N":"Nigeria","I":"NG","C":[[[[2.692,6.259],[2.749,7.871],[2.724,8.507],[2.912,9.138],[3.22,9.444],[3.705,10.063],[3.6,10.332],[3.797,10.735],[3.572,11.328],[3.611,11.66],[3.681,12.553],[3.967,12.956],[4.108,13.531],[4.368,13.747],[5.443,13.866],[6.445,13.493],[6.82,13.115],[7.331,13.098],[7.805,13.344],[9.015,12.827],[9.525,12.851],[10.115,13.277],[10.701,13.247],[10.99,13.387],[11.528,13.329],[12.302,13.037],[13.084,13.596],[13.319,13.556],[13.995,12.462],[14.181,12.484],[14.577,12.085],[14.468,11.905],[14.415,11.572],[13.573,10.799],[13.309,10.16],[13.168,9.641],[12.955,9.418],[12.754,8.718],[12.219,8.306],[12.064,7.8],[11.839,7.397],[11.746,6.981],[11.059,6.644],[10.497,7.055],[10.118,7.039],[9.523,6.453],[9.233,6.444],[8.758,5.48],[8.5,4.772],[7.462,4.412],[7.083,4.465],[6.698,4.241],[5.898,4.262],[5.363,4.888],[5.034,5.612],[4.326,6.271],[3.574,6.258],[2.692,6.259]]]],"translations":{"ar":"نيجيريا","bs":"Nigerija","cs":"NigĂŠrie","de":"Nigeria","es":"Nigeria","fa_IR":"نیجریه","fr":"Nigeria","id":"Nigeria","it":"Nigeria","ja":"ナイジェリア","pl":"Nigeria","pt_BR":"NigĂŠria","pt_PT":"NigĂŠria","ru":"Нигерия","uk":"Нігерія","zh_CN":"尼日利亚","zh_TW":"奈及利亞"}},{"N":"Cameroon","I":"CM","C":[[[[14.496,12.859],[14.893,12.219],[14.96,11.556],[14.924,10.891],[15.468,9.982],[14.909,9.992],[14.627,9.921],[14.171,10.021],[13.954,9.549],[14.544,8.966],[14.98,8.796],[15.121,8.382],[15.436,7.693],[15.279,7.422],[14.777,6.408],[14.537,6.227],[14.459,5.452],[14.559,5.031],[14.478,4.733],[14.951,4.21],[15.036,3.851],[15.405,3.335],[15.863,3.014],[15.907,2.557],[16.013,2.268],[15.941,1.728],[15.146,1.964],[14.338,2.228],[13.076,2.267],[12.951,2.322],[12.359,2.193],[11.752,2.327],[11.276,2.261],[9.649,2.284],[9.795,3.073],[9.404,3.735],[8.948,3.904],[8.745,4.352],[8.489,4.496],[8.5,4.772],[8.758,5.48],[9.233,6.444],[9.523,6.453],[10.118,7.039],[10.497,7.055],[11.059,6.644],[11.746,6.981],[11.839,7.397],[12.064,7.8],[12.219,8.306],[12.754,8.718],[12.955,9.418],[13.168,9.641],[13.309,10.16],[13.573,10.799],[14.415,11.572],[14.468,11.905],[14.577,12.085],[14.181,12.484],[14.214,12.802],[14.496,12.859]]]],"translations":{"ar":"الكاميرون","bs":"Kamerun","cs":"Kamerun","de":"Kamerun","es":"CamerĂşn","fa_IR":"کامرون","fr":"Cameroun","id":"Kamerun","it":"Camerun","ja":"カメルーン","pl":"Kamerun","pt_BR":"CamarĂľes","pt_PT":"CamarĂľes","ru":"Камерун","uk":"Камерун","zh_CN":"喀麦隆","zh_TW":"喀麥隆"}},{"N":"Togo","I":"TG","C":[[[[0.9,10.997],[0.772,10.471],[1.078,10.176],[1.425,9.825],[1.463,9.335],[1.664,9.129],[1.619,6.832],[1.865,6.142],[1.06,5.929],[0.837,6.28],[0.57,6.914],[0.491,7.412],[0.712,8.312],[0.461,8.677],[0.366,9.465],[0.368,10.191],[-0.05,10.707],[0.024,11.019],[0.9,10.997]]]],"translations":{"ar":"توغو","bs":"Togo","cs":"Togo","de":"Togo","es":"Togo","fa_IR":"توگو","fr":"Togo","id":"Togo","it":"Togo","ja":"トーゴ","pl":"Togo","pt_BR":"Togo","pt_PT":"Togo","ru":"ТОгО","uk":"ТОгО","zh_CN":"多哥","zh_TW":"多哥"}},{"N":"Ghana","I":"GH","C":[[[[0.024,11.019],[-0.05,10.707],[0.368,10.191],[0.366,9.465],[0.461,8.677],[0.712,8.312],[0.491,7.412],[0.57,6.914],[0.837,6.28],[1.06,5.929],[-0.508,5.343],[-1.064,5.001],[-1.965,4.71],[-2.856,4.994],[-2.811,5.389],[-3.244,6.25],[-2.984,7.38],[-2.562,8.22],[-2.827,9.642],[-2.964,10.395],[-2.94,10.963],[-1.203,11.01],[-0.762,10.937],[-0.439,11.098],[0.024,11.019]]]],"translations":{"ar":"غانا","bs":"Gana","cs":"Ghana","de":"Ghana","es":"Ghana","fa_IR":"غنا","fr":"Ghana","id":"Ghana","it":"Ghana","ja":"ガーナ","pl":"Ghana","pt_BR":"Gana","pt_PT":"Gana","ru":"Гана","uk":"Гана","zh_CN":"加纳","zh_TW":"迦納"}},{"N":"CĂ´ted'Ivoire","I":"CI","C":[[[[-8.03,10.207],[-7.9,10.297],[-7.623,10.147],[-6.851,10.139],[-6.666,10.431],[-6.494,10.411],[-6.205,10.524],[-6.05,10.096],[-5.817,10.223],[-5.404,10.371],[-4.955,10.153],[-4.78,9.822],[-4.33,9.611],[-3.98,9.862],[-3.512,9.9],[-2.827,9.642],[-2.562,8.22],[-2.984,7.38],[-3.244,6.25],[-2.811,5.389],[-2.856,4.994],[-3.311,4.984],[-4.009,5.18],[-4.65,5.168],[-5.834,4.994],[-6.529,4.705],[-7.519,4.338],[-7.712,4.365],[-7.635,5.188],[-7.54,5.313],[-7.57,5.707],[-7.994,6.126],[-8.311,6.193],[-8.603,6.468],[-8.385,6.912],[-8.485,7.395],[-8.439,7.686],[-8.281,7.687],[-8.222,8.123],[-8.299,8.316],[-8.203,8.455],[-7.832,8.576],[-8.079,9.376],[-8.31,9.79],[-8.229,10.129],[-8.03,10.207]]]],"translations":{"ar":"ساحل العاج","bs":"Obala Slonovače","cs":"PobřeŞí slonoviny","de":"CĂ´te d’Ivoire","es":"CĂ´te d’Ivoire","fa_IR":"ساحل ؚا؏","fr":"CĂ´te d’Ivoire","id":"CĂ´te d’Ivoire","it":"Costa d’Avorio","ja":"コートジボワール","pl":"CĂ´te d’Ivoire","pt_BR":"Costa do Marfim","pt_PT":"CĂ´te d’Ivoire (Costa do Marfim)","ru":"Кот-д’Ивуар","uk":"Кот-дʼІвуар","zh_CN":"科特迪瓦","zh_TW":"象牙海岸"}},{"N":"Guinea","I":"GN","C":[[[[-13.7,12.586],[-13.218,12.576],[-12.499,12.332],[-12.279,12.354],[-12.204,12.466],[-11.658,12.387],[-11.514,12.443],[-11.456,12.077],[-11.298,12.078],[-11.037,12.211],[-10.871,12.178],[-10.593,11.924],[-10.165,11.844],[-9.891,12.06],[-9.568,12.194],[-9.328,12.334],[-9.127,12.308],[-8.905,12.088],[-8.786,11.813],[-8.376,11.394],[-8.581,11.136],[-8.62,10.811],[-8.407,10.909],[-8.282,10.793],[-8.335,10.495],[-8.03,10.207],[-8.229,10.129],[-8.31,9.79],[-8.079,9.376],[-7.832,8.576],[-8.203,8.455],[-8.299,8.316],[-8.222,8.123],[-8.281,7.687],[-8.439,7.686],[-8.722,7.712],[-8.926,7.309],[-9.209,7.314],[-9.403,7.527],[-9.337,7.929],[-9.755,8.541],[-10.017,8.429],[-10.23,8.406],[-10.505,8.349],[-10.494,8.716],[-10.655,8.977],[-10.622,9.268],[-10.839,9.688],[-11.117,10.046],[-11.917,10.047],[-12.15,9.859],[-12.426,9.836],[-12.597,9.62],[-12.712,9.343],[-13.247,8.903],[-13.685,9.495],[-14.074,9.886],[-14.33,10.016],[-14.58,10.214],[-14.693,10.656],[-14.84,10.877],[-15.13,11.04],[-14.686,11.528],[-14.382,11.509],[-14.121,11.677],[-13.901,11.679],[-13.743,11.811],[-13.828,12.143],[-13.719,12.247],[-13.7,12.586]]]],"translations":{"ar":"غينيا","bs":"Gvineja","cs":"Guinea","de":"Guinea","es":"Guinea","fa_IR":"گینه","fr":"GuinĂŠe","id":"Guinea","it":"Guinea","ja":"ギニア","pl":"Gwinea","pt_BR":"GuinĂŠ","pt_PT":"GuinĂŠ","ru":"Гвинея","uk":"Гвінея","zh_CN":"几内亚","zh_TW":"幾內亞"}},{"N":"Guinea-Bissau","I":"GW","C":[[[[-16.677,12.385],[-16.148,12.548],[-15.817,12.516],[-15.548,12.628],[-13.7,12.586],[-13.719,12.247],[-13.828,12.143],[-13.743,11.811],[-13.901,11.679],[-14.121,11.677],[-14.382,11.509],[-14.686,11.528],[-15.13,11.04],[-15.664,11.458],[-16.085,11.525],[-16.315,11.807],[-16.309,11.959],[-16.614,12.171],[-16.677,12.385]]]],"translations":{"ar":"غينيا بيساو","bs":"Gvineja-Bisao","cs":"Guinea-Bissau","de":"Guinea-Bissau","es":"Guinea-BisĂĄu","fa_IR":"گینهٔ بیسائو","fr":"GuinĂŠe-Bissau","id":"Guinea-Bissau","it":"Guinea-Bissau","ja":"ギニアビサウ","pl":"Gwinea Bissau","pt_BR":"GuinĂŠ-Bissau","pt_PT":"GuinĂŠ-Bissau","ru":"Гвинея-Бисау","uk":"Гвінея-Бісау","zh_CN":"几内亚比绍","zh_TW":"幾內亞比索"}},{"N":"Liberia","I":"LR","C":[[[[-8.439,7.686],[-8.485,7.395],[-8.385,6.912],[-8.603,6.468],[-8.311,6.193],[-7.994,6.126],[-7.57,5.707],[-7.54,5.313],[-7.635,5.188],[-7.712,4.365],[-7.974,4.356],[-9.005,4.832],[-9.913,5.594],[-10.765,6.141],[-11.439,6.786],[-11.2,7.106],[-11.147,7.397],[-10.696,7.939],[-10.23,8.406],[-10.017,8.429],[-9.755,8.541],[-9.337,7.929],[-9.403,7.527],[-9.209,7.314],[-8.926,7.309],[-8.722,7.712],[-8.439,7.686]]]],"translations":{"ar":"ليبيريا","bs":"Liberija","cs":"LibĂŠrie","de":"Liberia","es":"Liberia","fa_IR":"لیبریا","fr":"Liberia","id":"Liberia","it":"Liberia","ja":"リベリア","pl":"Liberia","pt_BR":"LibĂŠria","pt_PT":"LibĂŠria","ru":"Либерия","uk":"Ліберія","zh_CN":"利比里亚","zh_TW":"賴比瑞亞"}},{"N":"Sierra Leone","I":"SL","C":[[[[-13.247,8.903],[-12.712,9.343],[-12.597,9.62],[-12.426,9.836],[-12.15,9.859],[-11.917,10.047],[-11.117,10.046],[-10.839,9.688],[-10.622,9.268],[-10.655,8.977],[-10.494,8.716],[-10.505,8.349],[-10.23,8.406],[-10.696,7.939],[-11.147,7.397],[-11.2,7.106],[-11.439,6.786],[-11.708,6.86],[-12.428,7.263],[-12.949,7.799],[-13.124,8.164],[-13.247,8.903]]]],"translations":{"ar":"سيراليون","bs":"Sijera Leone","cs":"Sierra Leone","de":"Sierra Leone","es":"Sierra Leona","fa_IR":"سیرالئون","fr":"Sierra Leone","id":"Sierra Leone","it":"Sierra Leone","ja":"シエラレオネ","pl":"Sierra Leone","pt_BR":"Serra Leoa","pt_PT":"Serra Leoa","ru":"Сьерра-Леоне","uk":"Сьєрра-Леоне","zh_CN":"塞拉利昂","zh_TW":"獅子山"}},{"N":"Burkina Faso","I":"BF","C":[[[[-5.404,10.371],[-5.471,10.951],[-5.198,11.375],[-5.221,11.714],[-4.427,12.543],[-4.28,13.228],[-4.006,13.472],[-3.523,13.338],[-3.104,13.541],[-2.968,13.798],[-2.192,14.246],[-2.001,14.559],[-1.066,14.974],[-0.516,15.116],[-0.266,14.924],[0.375,14.929],[0.296,14.444],[0.43,13.989],[0.993,13.336],[1.024,12.852],[2.177,12.625],[2.154,11.94],[1.936,11.641],[1.447,11.548],[1.243,11.111],[0.9,10.997],[0.024,11.019],[-0.439,11.098],[-0.762,10.937],[-1.203,11.01],[-2.94,10.963],[-2.964,10.395],[-2.827,9.642],[-3.512,9.9],[-3.98,9.862],[-4.33,9.611],[-4.78,9.822],[-4.955,10.153],[-5.404,10.371]]]],"translations":{"ar":"بوركينا فاسو","bs":"Burkina Faso","cs":"Burkina Faso","de":"Burkina Faso","es":"Burkina Faso","fa_IR":"بورکینافاسو","fr":"Burkina Faso","id":"Burkina Faso","it":"Burkina Faso","ja":"ブルキナファソ","pl":"Burkina Faso","pt_BR":"Burquina Faso","pt_PT":"Burquina Faso","ru":"Буркина-ФасО","uk":"Буркіна-ФасО","zh_CN":"布基纳法索","zh_TW":"布吉納法索"}},{"N":"Central African Republic","I":"CF","C":[[[[27.374,5.234],[27.044,5.128],[26.403,5.151],[25.65,5.256],[25.279,5.17],[25.129,4.927],[24.805,4.897],[24.411,5.109],[23.297,4.61],[22.841,4.71],[22.704,4.633],[22.405,4.029],[21.659,4.224],[20.928,4.323],[20.291,4.692],[19.468,5.032],[18.932,4.71],[18.543,4.202],[18.453,3.504],[17.81,3.56],[17.133,3.728],[16.537,3.198],[16.013,2.268],[15.907,2.557],[15.863,3.014],[15.405,3.335],[15.036,3.851],[14.951,4.21],[14.478,4.733],[14.559,5.031],[14.459,5.452],[14.537,6.227],[14.777,6.408],[15.279,7.422],[16.106,7.497],[16.291,7.754],[16.456,7.735],[16.706,7.508],[17.965,7.891],[18.39,8.281],[18.911,8.631],[18.812,8.983],[19.094,9.075],[20.06,9.013],[21.001,9.476],[21.724,10.567],[22.231,10.972],[22.864,11.142],[22.978,10.714],[23.554,10.089],[23.557,9.681],[23.395,9.265],[23.459,8.954],[23.806,8.666],[24.567,8.229],[25.115,7.825],[25.124,7.5],[25.797,6.979],[26.213,6.547],[26.466,5.947],[27.213,5.551],[27.374,5.234]]]],"translations":{"ar":"جمهورية أفريقيا الوسطى","bs":"Centralnoafrička Republika","cs":"StředoafrickĂĄ republika","de":"Zentralafrikanische Republik","es":"RepĂşblica Centroafricana","fa_IR":"جمهوری افریقای مرکزی","fr":"RĂŠpublique centrafricaine","id":"Republik Afrika Tengah","it":"Repubblica Centrafricana","ja":"中央アフリカ共和国","pl":"Republika Środkowoafrykańska","pt_BR":"RepĂşblica Centro-Africana","pt_PT":"RepĂşblica Centro-Africana","ru":"Центрально-Африканская РоспуйНика","uk":"Центральноафриканська Республіка","zh_CN":"中非共和国","zh_TW":"中非共和國"}},{"N":"Republic of the Congo","I":"CG","C":[[[[18.453,3.504],[18.394,2.9],[18.094,2.366],[17.899,1.742],[17.774,0.856],[17.827,0.289],[17.664,-0.058],[17.639,-0.425],[17.524,-0.744],[16.865,-1.226],[16.407,-1.741],[15.973,-2.712],[16.006,-3.535],[15.754,-3.855],[15.171,-4.344],[14.583,-4.97],[14.209,-4.793],[14.145,-4.51],[13.6,-4.5],[13.258,-4.883],[12.996,-4.781],[12.621,-4.438],[12.319,-4.606],[11.915,-5.038],[11.094,-3.979],[11.855,-3.427],[11.478,-2.766],[11.821,-2.514],[12.496,-2.392],[12.575,-1.949],[13.11,-2.429],[13.992,-2.471],[14.299,-1.998],[14.425,-1.333],[14.316,-0.553],[13.843,0.039],[14.276,1.197],[14.027,1.396],[13.283,1.314],[13.003,1.831],[13.076,2.267],[14.338,2.228],[15.146,1.964],[15.941,1.728],[16.013,2.268],[16.537,3.198],[17.133,3.728],[17.81,3.56],[18.453,3.504]]]],"translations":{"ar":"الكونغو - برازافيل","bs":"Kongo","cs":"Kongo – Brazzaville","de":"Kongo-Brazzaville","es":"Congo","fa_IR":"کنگو - برازویل","fr":"Congo-Brazzaville","id":"Kongo - Brazzaville","it":"Congo-Brazzaville","ja":"コンゴ共和国(ブラザビル)","pl":"Kongo","pt_BR":"RepĂşblica do Congo","pt_PT":"Congo-Brazzaville","ru":"Конго - Браззавиль","uk":"Конго – Браззавіль","zh_CN":"刚果(布)","zh_TW":"剛果(布拉薩)"}},{"N":"Gabon","I":"GA","C":[[[[11.276,2.261],[11.752,2.327],[12.359,2.193],[12.951,2.322],[13.076,2.267],[13.003,1.831],[13.283,1.314],[14.027,1.396],[14.276,1.197],[13.843,0.039],[14.316,-0.553],[14.425,-1.333],[14.299,-1.998],[13.992,-2.471],[13.11,-2.429],[12.575,-1.949],[12.496,-2.392],[11.821,-2.514],[11.478,-2.766],[11.855,-3.427],[11.094,-3.979],[10.066,-2.969],[9.405,-2.144],[8.798,-1.111],[8.83,-0.779],[9.048,-0.459],[9.291,0.269],[9.493,1.01],[9.83,1.068],[11.285,1.058],[11.276,2.261]]]],"translations":{"ar":"الغابون","bs":"Gabon","cs":"Gabon","de":"Gabun","es":"GabĂłn","fa_IR":"گابن","fr":"Gabon","id":"Gabon","it":"Gabon","ja":"ガボン","pl":"Gabon","pt_BR":"GabĂŁo","pt_PT":"GabĂŁo","ru":"Габон","uk":"Габон","zh_CN":"加蓬","zh_TW":"加彭"}},{"N":"Equatorial Guinea","I":"GQ","C":[[[[9.649,2.284],[11.276,2.261],[11.285,1.058],[9.83,1.068],[9.493,1.01],[9.306,1.161],[9.649,2.284]]]],"translations":{"ar":"غينيا الاستوائية","bs":"Ekvatorijalna Gvineja","cs":"RovnĂ­kovĂĄ Guinea","de":"Äquatorialguinea","es":"Guinea Ecuatorial","fa_IR":"گینهٔ استوایی","fr":"GuinĂŠe ĂŠquatoriale","id":"Guinea Ekuatorial","it":"Guinea Equatoriale","ja":"赤道ギニア","pl":"Gwinea RĂłwnikowa","pt_BR":"GuinĂŠ Equatorial","pt_PT":"GuinĂŠ Equatorial","ru":"Экваториальная Гвинея","uk":"Екваторіальна Гвінея","zh_CN":"赤道几内亚","zh_TW":"赤道幾內亞"}},{"N":"Zambia","I":"ZM","C":[[[[30.74,-8.34],[31.158,-8.595],[31.556,-8.762],[32.192,-8.93],[32.759,-9.231],[33.231,-9.677],[33.486,-10.526],[33.315,-10.797],[33.114,-11.607],[33.306,-12.436],[32.992,-12.784],[32.688,-13.713],[33.214,-13.972],[30.179,-14.796],[30.274,-15.508],[29.517,-15.645],[28.947,-16.043],[28.826,-16.39],[28.468,-16.468],[27.598,-17.291],[27.044,-17.938],[26.707,-17.961],[26.382,-17.846],[25.264,-17.737],[25.084,-17.662],[25.077,-17.579],[24.682,-17.353],[24.034,-17.296],[23.215,-17.523],[22.562,-16.898],[21.888,-16.08],[21.934,-12.898],[24.016,-12.911],[23.931,-12.566],[24.08,-12.191],[23.904,-11.722],[24.018,-11.237],[23.912,-10.927],[24.257,-10.952],[24.315,-11.263],[24.783,-11.239],[25.418,-11.331],[25.752,-11.785],[26.553,-11.924],[27.164,-11.609],[27.389,-12.133],[28.155,-12.272],[28.524,-12.699],[28.934,-13.249],[29.7,-13.257],[29.616,-12.179],[29.342,-12.361],[28.642,-11.972],[28.372,-11.794],[28.496,-10.79],[28.674,-9.606],[28.45,-9.165],[28.735,-8.527],[29.003,-8.407],[30.346,-8.238],[30.74,-8.34]]]],"translations":{"ar":"زامبيا","bs":"Zambija","cs":"Zambie","de":"Sambia","es":"Zambia","fa_IR":"زامبیا","fr":"Zambie","id":"Zambia","it":"Zambia","ja":"ザンビア","pl":"Zambia","pt_BR":"Zâmbia","pt_PT":"Zâmbia","ru":"Замбия","uk":"Замбія","zh_CN":"赞比亚","zh_TW":"尚比亞"}},{"N":"Malawi","I":"MW","C":[[[[32.759,-9.231],[33.74,-9.417],[33.941,-9.694],[34.28,-10.16],[34.56,-11.52],[34.28,-12.28],[34.56,-13.58],[34.907,-13.565],[35.268,-13.888],[35.687,-14.611],[35.772,-15.897],[35.339,-16.107],[35.034,-16.801],[34.381,-16.184],[34.307,-15.479],[34.518,-15.014],[34.46,-14.613],[34.065,-14.36],[33.79,-14.452],[33.214,-13.972],[32.688,-13.713],[32.992,-12.784],[33.306,-12.436],[33.114,-11.607],[33.315,-10.797],[33.486,-10.526],[33.231,-9.677],[32.759,-9.231]]]],"translations":{"ar":"ملاوي","bs":"Malavi","cs":"Malawi","de":"Malawi","es":"Malaui","fa_IR":"مالاوی","fr":"Malawi","id":"Malawi","it":"Malawi","ja":"マラウイ","pl":"Malawi","pt_BR":"Malaui","pt_PT":"MalĂĄui","ru":"Малави","uk":"Малаві","zh_CN":"马拉维","zh_TW":"馬拉威"}},{"N":"Mozambique","I":"MZ","C":[[[[34.56,-11.52],[35.312,-11.439],[36.514,-11.721],[36.775,-11.595],[37.471,-11.569],[37.828,-11.269],[38.428,-11.285],[39.521,-10.897],[40.317,-10.317],[40.317,-10.317],[40.317,-10.317],[40.478,-10.765],[40.437,-11.762],[40.561,-12.639],[40.6,-14.202],[40.775,-14.692],[40.477,-15.406],[40.089,-16.101],[39.453,-16.721],[38.538,-17.101],[37.411,-17.586],[36.281,-18.66],[35.896,-18.842],[35.198,-19.553],[34.786,-19.784],[34.702,-20.497],[35.176,-21.254],[35.373,-21.841],[35.386,-22.14],[35.563,-22.09],[35.534,-23.071],[35.372,-23.535],[35.607,-23.707],[35.459,-24.123],[35.041,-24.478],[34.216,-24.816],[33.013,-25.358],[32.575,-25.727],[32.66,-26.149],[32.916,-26.216],[32.83,-26.742],[32.072,-26.734],[31.986,-26.292],[31.838,-25.843],[31.752,-25.484],[31.931,-24.369],[31.67,-23.659],[31.191,-22.252],[32.245,-21.116],[32.509,-20.395],[32.66,-20.304],[32.773,-19.716],[32.612,-19.419],[32.655,-18.672],[32.85,-17.979],[32.848,-16.713],[32.328,-16.392],[31.852,-16.319],[31.636,-16.072],[31.173,-15.861],[30.339,-15.881],[30.274,-15.508],[30.179,-14.796],[33.214,-13.972],[33.79,-14.452],[34.065,-14.36],[34.46,-14.613],[34.518,-15.014],[34.307,-15.479],[34.381,-16.184],[35.034,-16.801],[35.339,-16.107],[35.772,-15.897],[35.687,-14.611],[35.268,-13.888],[34.907,-13.565],[34.56,-13.58],[34.28,-12.28],[34.56,-11.52]]]],"translations":{"ar":"موزمبيق","bs":"Mozambik","cs":"Mosambik","de":"Mosambik","es":"Mozambique","fa_IR":"موزامبیک","fr":"Mozambique","id":"Mozambik","it":"Mozambico","ja":"モザンビーク","pl":"Mozambik","pt_BR":"Moçambique","pt_PT":"Moçambique","ru":"Мозамбик","uk":"Мозамбік","zh_CN":"莫桑比克","zh_TW":"莫三比克"}},{"N":"Eswatini","I":"SZ","C":[[[[32.072,-26.734],[31.868,-27.178],[31.283,-27.286],[30.686,-26.744],[30.677,-26.398],[30.95,-26.023],[31.044,-25.731],[31.333,-25.66],[31.838,-25.843],[31.986,-26.292],[32.072,-26.734]]]],"translations":{"ar":"إسواتيني","bs":"Esvatini","cs":"Eswatini","de":"Eswatini","es":"Esuatini","fa_IR":"اسواتینی","fr":"Eswatini","id":"eSwatini","it":"Eswatini","ja":"エスワティニ","pl":"Eswatini","pt_BR":"EssuatĂ­ni","pt_PT":"EssuatĂ­ni","ru":"Эсватини","uk":"Есватіні","zh_CN":"斯威士兰","zh_TW":"史瓦帝尼"}},{"N":"Angola","I":"AO","C":[[[[12.996,-4.781],[12.632,-4.991],[12.468,-5.248],[12.437,-5.684],[12.182,-5.79],[11.915,-5.038],[12.319,-4.606],[12.621,-4.438],[12.996,-4.781]]],[[[12.322,-6.1],[12.735,-5.966],[13.025,-5.984],[13.376,-5.864],[16.327,-5.877],[16.573,-6.623],[16.86,-7.222],[17.09,-7.546],[17.473,-8.069],[18.134,-7.988],[18.464,-7.847],[19.017,-7.988],[19.167,-7.738],[19.418,-7.155],[20.038,-7.116],[20.092,-6.943],[20.602,-6.939],[20.515,-7.3],[21.728,-7.291],[21.746,-7.92],[21.949,-8.306],[21.802,-8.909],[21.875,-9.524],[22.209,-9.895],[22.155,-11.085],[22.403,-10.993],[22.837,-11.018],[23.457,-10.868],[23.912,-10.927],[24.018,-11.237],[23.904,-11.722],[24.08,-12.191],[23.931,-12.566],[24.016,-12.911],[21.934,-12.898],[21.888,-16.08],[22.562,-16.898],[23.215,-17.523],[21.377,-17.931],[18.956,-17.789],[18.263,-17.31],[14.21,-17.353],[14.059,-17.423],[13.462,-16.971],[12.814,-16.941],[12.215,-17.112],[11.734,-17.302],[11.64,-16.673],[11.779,-15.794],[12.124,-14.878],[12.176,-14.449],[12.5,-13.548],[12.738,-13.138],[13.313,-12.484],[13.634,-12.039],[13.739,-11.298],[13.686,-10.731],[13.387,-10.374],[13.121,-9.767],[12.875,-9.167],[12.929,-8.959],[13.236,-8.563],[12.933,-7.597],[12.728,-6.927],[12.227,-6.294],[12.322,-6.1]]]],"translations":{"ar":"أنغولا","bs":"Angola","cs":"Angola","de":"Angola","es":"Angola","fa_IR":"آنگولا","fr":"Angola","id":"Angola","it":"Angola","ja":"アンゴラ","pl":"Angola","pt_BR":"Angola","pt_PT":"Angola","ru":"АнгОНа","uk":"АнгОНа","zh_CN":"安哥拉","zh_TW":"安哥拉"}},{"N":"Burundi","I":"BI","C":[[[[30.47,-2.414],[30.528,-2.808],[30.743,-3.034],[30.752,-3.359],[30.506,-3.569],[30.116,-4.09],[29.754,-4.452],[29.34,-4.5],[29.276,-3.294],[29.025,-2.839],[29.632,-2.918],[29.938,-2.348],[30.47,-2.414]]]],"translations":{"ar":"بوروندي","bs":"Burundi","cs":"Burundi","de":"Burundi","es":"Burundi","fa_IR":"بوروندی","fr":"Burundi","id":"Burundi","it":"Burundi","ja":"ブルンジ","pl":"Burundi","pt_BR":"Burundi","pt_PT":"Burundi","ru":"Бурунди","uk":"Бурунді","zh_CN":"布隆迪","zh_TW":"蒲隆地"}},{"N":"Israel","I":"IL","C":[[[[35.72,32.709],[35.546,32.394],[35.184,32.533],[34.975,31.867],[35.226,31.754],[34.971,31.617],[34.927,31.353],[35.398,31.489],[35.421,31.1],[34.923,29.501],[34.823,29.761],[34.265,31.219],[34.265,31.219],[34.265,31.219],[34.556,31.549],[34.488,31.606],[34.753,32.073],[34.955,32.827],[35.098,33.081],[35.126,33.091],[35.461,33.089],[35.553,33.264],[35.821,33.277],[35.836,32.868],[35.701,32.716],[35.72,32.709]]]],"translations":{"ar":"إسرائيل","bs":"Izrael","cs":"Izrael","de":"Israel","es":"Israel","fa_IR":"اسرائیل","fr":"IsraĂŤl","id":"Israel","it":"Israele","ja":"イスラエル","pl":"Izrael","pt_BR":"Israel","pt_PT":"Israel","ru":"Израиль","uk":"Ізраїль","zh_CN":"以色列","zh_TW":"以色列"}},{"N":"Lebanon","I":"LB","C":[[[[35.821,33.277],[35.553,33.264],[35.461,33.089],[35.126,33.091],[35.482,33.905],[35.98,34.61],[35.998,34.645],[36.448,34.594],[36.612,34.202],[36.066,33.825],[35.821,33.277]]]],"translations":{"ar":"لبنان","bs":"Liban","cs":"Libanon","de":"Libanon","es":"LĂ­bano","fa_IR":"لبنان","fr":"Liban","id":"Lebanon","it":"Libano","ja":"レバノン","pl":"Liban","pt_BR":"LĂ­bano","pt_PT":"LĂ­bano","ru":"Ливан","uk":"Ліван","zh_CN":"黎巴嫩","zh_TW":"黎巴嫩"}},{"N":"Madagascar","I":"MG","C":[[[[49.544,-12.47],[49.809,-12.895],[50.057,-13.556],[50.217,-14.759],[50.477,-15.227],[50.377,-15.706],[50.2,-16],[49.861,-15.414],[49.673,-15.71],[49.863,-16.451],[49.775,-16.875],[49.499,-17.106],[49.436,-17.953],[49.042,-19.119],[48.549,-20.497],[47.931,-22.392],[47.548,-23.782],[47.096,-24.942],[46.282,-25.178],[45.41,-25.601],[44.834,-25.346],[44.04,-24.988],[43.764,-24.461],[43.698,-23.574],[43.346,-22.777],[43.254,-22.057],[43.433,-21.336],[43.894,-21.163],[43.896,-20.83],[44.374,-20.072],[44.464,-19.435],[44.232,-18.962],[44.043,-18.331],[43.963,-17.41],[44.312,-16.85],[44.447,-16.216],[44.945,-16.179],[45.503,-15.974],[45.873,-15.793],[46.312,-15.78],[46.882,-15.21],[47.705,-14.594],[48.005,-14.091],[47.869,-13.664],[48.294,-13.784],[48.845,-13.089],[48.864,-12.488],[49.195,-12.041],[49.544,-12.47]]]],"translations":{"ar":"مدغشقر","bs":"Madagaskar","cs":"Madagaskar","de":"Madagaskar","es":"Madagascar","fa_IR":"ماداگاسکار","fr":"Madagascar","id":"Madagaskar","it":"Madagascar","ja":"マダガスカル","pl":"Madagaskar","pt_BR":"Madagascar","pt_PT":"MadagĂĄscar","ru":"Мадагаскар","uk":"Мадагаскар","zh_CN":"马达加斯加","zh_TW":"馬達加斯加"}},{"N":"Palestine","I":"PS","C":[[[[35.398,31.489],[34.927,31.353],[34.971,31.617],[35.226,31.754],[34.975,31.867],[35.184,32.533],[35.546,32.394],[35.545,31.783],[35.398,31.489]]]],"translations":{"ar":"الأراضي الفلسطينية","bs":"Palestinska Teritorija","cs":"PalestinskĂĄ ĂşzemĂ­","de":"Palästinensische Autonomiegebiete","es":"Territorios Palestinos","fa_IR":"سرزمین‌های فلسطینی","fr":"Territoires palestiniens","id":"Wilayah Palestina","it":"Territori Palestinesi","ja":"パレスチナ自治区","pl":"Terytoria Palestyńskie","pt_BR":"TerritĂłrios palestinos","pt_PT":"TerritĂłrios palestinianos","ru":"Палестинские территории","uk":"Палестинські території","zh_CN":"巴勒斯坦领土","zh_TW":"巴勒斯坦自治區"}},{"N":"The Gambia","I":"GM","C":[[[[-16.714,13.595],[-15.625,13.624],[-15.399,13.86],[-15.082,13.876],[-14.687,13.63],[-14.377,13.626],[-14.047,13.794],[-13.845,13.505],[-14.278,13.281],[-14.712,13.298],[-15.141,13.51],[-15.512,13.279],[-15.691,13.27],[-15.931,13.13],[-16.842,13.151],[-16.714,13.595]]]],"translations":{"ar":"غامبيا","bs":"Gambija","cs":"Gambie","de":"Gambia","es":"Gambia","fa_IR":"گامبیا","fr":"Gambie","id":"Gambia","it":"Gambia","ja":"ガンビア","pl":"Gambia","pt_BR":"Gâmbia","pt_PT":"Gâmbia","ru":"Гамбия","uk":"Гамбія","zh_CN":"冈比亚","zh_TW":"甘比亞"}},{"N":"Tunisia","I":"TN","C":[[[[9.482,30.308],[9.056,32.103],[8.439,32.506],[8.43,32.748],[7.613,33.344],[7.524,34.097],[8.141,34.655],[8.376,35.48],[8.218,36.433],[8.421,36.946],[9.51,37.35],[10.21,37.23],[10.181,36.724],[11.029,37.092],[11.1,36.9],[10.6,36.41],[10.593,35.947],[10.94,35.699],[10.808,34.834],[10.15,34.331],[10.34,33.786],[10.857,33.769],[11.109,33.293],[11.489,33.137],[11.432,32.369],[10.945,32.082],[10.637,31.761],[9.95,31.376],[10.057,30.962],[9.97,30.539],[9.482,30.308]]]],"translations":{"ar":"تونس","bs":"Tunis","cs":"Tunisko","de":"Tunesien","es":"TĂşnez","fa_IR":"تونس","fr":"Tunisie","id":"Tunisia","it":"Tunisia","ja":"チュニジア","pl":"Tunezja","pt_BR":"TunĂ­sia","pt_PT":"TunĂ­sia","ru":"Тунис","uk":"Туніс","zh_CN":"突尼斯","zh_TW":"突尼西亞"}},{"N":"Algeria","I":"DZ","C":[[[[-8.684,27.396],[-8.665,27.589],[-8.666,27.656],[-8.674,28.841],[-7.059,29.579],[-6.061,29.732],[-5.242,30],[-4.86,30.501],[-3.69,30.897],[-3.647,31.637],[-3.069,31.724],[-2.617,32.094],[-1.308,32.263],[-1.125,32.652],[-1.388,32.864],[-1.733,33.92],[-1.793,34.528],[-2.17,35.168],[-1.209,35.715],[-0.127,35.889],[0.504,36.301],[1.467,36.606],[3.162,36.784],[4.816,36.865],[5.32,36.717],[6.262,37.111],[7.33,37.118],[7.737,36.886],[8.421,36.946],[8.218,36.433],[8.376,35.48],[8.141,34.655],[7.524,34.097],[7.613,33.344],[8.43,32.748],[8.439,32.506],[9.056,32.103],[9.482,30.308],[9.806,29.425],[9.86,28.96],[9.684,28.144],[9.756,27.688],[9.629,27.141],[9.716,26.512],[9.319,26.094],[9.911,25.365],[9.948,24.937],[10.304,24.379],[10.771,24.563],[11.561,24.098],[12,23.472],[8.573,21.566],[5.678,19.601],[4.267,19.155],[3.158,19.057],[3.147,19.694],[2.684,19.856],[2.061,20.142],[1.823,20.611],[-1.55,22.793],[-4.923,24.975],[-8.684,27.396]]]],"translations":{"ar":"الجزائر","bs":"AlĹžir","cs":"AlŞírsko","de":"Algerien","es":"Argelia","fa_IR":"الجزایر","fr":"AlgĂŠrie","id":"Aljazair","it":"Algeria","ja":"アルジェリア","pl":"Algieria","pt_BR":"ArgĂŠlia","pt_PT":"ArgĂŠlia","ru":"Алжир","uk":"Алжир","zh_CN":"阿尔及利亚","zh_TW":"阿爾及利亞"}},{"N":"Jordan","I":"JO","C":[[[[35.546,32.394],[35.72,32.709],[36.834,32.313],[38.792,33.379],[39.195,32.161],[39.005,32.01],[37.002,31.508],[37.999,30.508],[37.668,30.339],[37.504,30.004],[36.741,29.865],[36.501,29.505],[36.069,29.197],[34.956,29.357],[34.923,29.501],[35.421,31.1],[35.398,31.489],[35.545,31.783],[35.546,32.394]]]],"translations":{"ar":"الأردن","bs":"Jordan","cs":"JordĂĄnsko","de":"Jordanien","es":"Jordania","fa_IR":"اردن","fr":"Jordanie","id":"Yordania","it":"Giordania","ja":"ヨルダン","pl":"Jordania","pt_BR":"Jordânia","pt_PT":"Jordânia","ru":"Иордания","uk":"Йорданія","zh_CN":"约旦","zh_TW":"約旦"}},{"N":"United Arab Emirates","I":"AE","C":[[[[51.58,24.245],[51.757,24.294],[51.794,24.02],[52.577,24.177],[53.404,24.151],[54.008,24.122],[54.693,24.798],[55.439,25.439],[56.071,26.055],[56.261,25.715],[56.397,24.925],[55.886,24.921],[55.804,24.27],[55.981,24.131],[55.529,23.934],[55.526,23.525],[55.234,23.111],[55.208,22.708],[55.007,22.497],[52.001,23.001],[51.618,24.014],[51.58,24.245]]]],"translations":{"ar":"الإمارات العربية المتحدة","bs":"Ujedinjeni Arapski Emirati","cs":"SpojenĂŠ arabskĂŠ emirĂĄty","de":"Vereinigte Arabische Emirate","es":"Emiratos Árabes Unidos","fa_IR":"امارات متحدهٔ عربی","fr":"Émirats arabes unis","id":"Uni Emirat Arab","it":"Emirati Arabi Uniti","ja":"アラブ首長国連邦","pl":"Zjednoczone Emiraty Arabskie","pt_BR":"Emirados Árabes Unidos","pt_PT":"Emirados Árabes Unidos","ru":"ОАЭ","uk":"Обʼєднані Арабські Емірати","zh_CN":"阿拉伯联合酋长国","zh_TW":"阿拉伯聯合大公國"}},{"N":"Qatar","I":"QA","C":[[[[50.81,24.755],[50.744,25.482],[51.013,26.007],[51.286,26.115],[51.589,25.801],[51.607,25.216],[51.39,24.627],[51.112,24.556],[50.81,24.755]]]],"translations":{"ar":"قطر","bs":"Katar","cs":"Katar","de":"Katar","es":"Catar","fa_IR":"قطر","fr":"Qatar","id":"Qatar","it":"Qatar","ja":"カタール","pl":"Katar","pt_BR":"Catar","pt_PT":"Catar","ru":"Катар","uk":"Катар","zh_CN":"卡塔尔","zh_TW":"卡達"}},{"N":"Kuwait","I":"KW","C":[[[[47.975,29.976],[48.183,29.534],[48.094,29.306],[48.416,28.552],[47.709,28.526],[47.46,29.003],[46.569,29.099],[47.303,30.059],[47.975,29.976]]]],"translations":{"ar":"الكويت","bs":"Kuvajt","cs":"Kuvajt","de":"Kuwait","es":"Kuwait","fa_IR":"کویت","fr":"KoweĂŻt","id":"Kuwait","it":"Kuwait","ja":"クウェート","pl":"Kuwejt","pt_BR":"Kuwait","pt_PT":"Koweit","ru":"Кувейт","uk":"Кувейт","zh_CN":"科威特","zh_TW":"科威特"}},{"N":"Iraq","I":"IQ","C":[[[[39.195,32.161],[38.792,33.379],[41.006,34.419],[41.384,35.628],[41.29,36.359],[41.837,36.606],[42.35,37.23],[42.779,37.385],[43.942,37.256],[44.293,37.002],[44.773,37.17],[45.421,35.978],[46.076,35.677],[46.152,35.093],[45.648,34.748],[45.417,33.968],[46.109,33.017],[47.335,32.469],[47.849,31.709],[47.685,30.985],[48.005,30.985],[48.015,30.452],[48.568,29.927],[47.975,29.976],[47.303,30.059],[46.569,29.099],[44.709,29.179],[41.89,31.19],[40.4,31.89],[39.195,32.161]]]],"translations":{"ar":"العراق","bs":"Irak","cs":"IrĂĄk","de":"Irak","es":"Irak","fa_IR":"عراق","fr":"Irak","id":"Irak","it":"Iraq","ja":"イラク","pl":"Irak","pt_BR":"Iraque","pt_PT":"Iraque","ru":"Ирак","uk":"Ірак","zh_CN":"伊拉克","zh_TW":"伊拉克"}},{"N":"Oman","I":"OM","C":[[[[55.208,22.708],[55.234,23.111],[55.526,23.525],[55.529,23.934],[55.981,24.131],[55.804,24.27],[55.886,24.921],[56.397,24.925],[56.845,24.242],[57.403,23.879],[58.137,23.748],[58.729,23.566],[59.181,22.992],[59.45,22.66],[59.808,22.534],[59.806,22.311],[59.442,21.715],[59.282,21.434],[58.861,21.114],[58.488,20.429],[58.034,20.481],[57.826,20.243],[57.666,19.736],[57.789,19.068],[57.694,18.945],[57.234,18.948],[56.61,18.574],[56.512,18.087],[56.284,17.876],[55.661,17.884],[55.27,17.632],[55.275,17.228],[54.791,16.951],[54.239,17.045],[53.571,16.708],[53.109,16.651],[52.782,17.35],[52,19],[55,20],[55.667,22],[55.208,22.708]]],[[[56.261,25.715],[56.071,26.055],[56.362,26.396],[56.486,26.309],[56.391,25.896],[56.261,25.715]]]],"translations":{"ar":"عُمان","bs":"Oman","cs":"OmĂĄn","de":"Oman","es":"OmĂĄn","fa_IR":"عمان","fr":"Oman","id":"Oman","it":"Oman","ja":"オマーン","pl":"Oman","pt_BR":"OmĂŁ","pt_PT":"OmĂŁ","ru":"Оман","uk":"Оман","zh_CN":"阿曼","zh_TW":"阿曼"}},{"N":"Vanuatu","I":"VU","C":[[[[167.217,-15.892],[167.845,-16.466],[167.515,-16.598],[167.18,-16.16],[167.217,-15.892]]],[[[166.793,-15.669],[166.65,-15.393],[166.629,-14.626],[167.108,-14.934],[167.27,-15.74],[167.001,-15.615],[166.793,-15.669]]]],"translations":{"ar":"فانواتو","bs":"Vanuatu","cs":"Vanuatu","de":"Vanuatu","es":"Vanuatu","fa_IR":"وانواتو","fr":"Vanuatu","id":"Vanuatu","it":"Vanuatu","ja":"バヌアツ","pl":"Vanuatu","pt_BR":"Vanuatu","pt_PT":"Vanuatu","ru":"Вануату","uk":"Вануату","zh_CN":"瓦努阿图","zh_TW":"萬那杜"}},{"N":"Cambodia","I":"KH","C":[[[[102.585,12.187],[102.348,13.394],[102.988,14.226],[104.281,14.417],[105.219,14.273],[106.044,13.881],[106.496,14.571],[107.383,14.202],[107.615,13.536],[107.491,12.337],[105.811,11.568],[106.25,10.962],[105.2,10.889],[104.334,10.487],[103.497,10.633],[103.091,11.154],[102.585,12.187]]]],"translations":{"ar":"كمبوديا","bs":"KambodĹža","cs":"KambodĹža","de":"Kambodscha","es":"Camboya","fa_IR":"کامبوج","fr":"Cambodge","id":"Kamboja","it":"Cambogia","ja":"カンボジア","pl":"KambodĹźa","pt_BR":"Camboja","pt_PT":"Camboja","ru":"Камбоджа","uk":"Камбоджа","zh_CN":"柬埔寨","zh_TW":"柬埔寨"}},{"N":"Thailand","I":"TH","C":[[[[105.219,14.273],[104.281,14.417],[102.988,14.226],[102.348,13.394],[102.585,12.187],[101.687,12.646],[100.832,12.627],[100.978,13.413],[100.098,13.407],[100.019,12.307],[99.479,10.846],[99.154,9.963],[99.222,9.239],[99.874,9.208],[100.28,8.295],[100.459,7.43],[101.017,6.857],[101.623,6.741],[102.141,6.222],[101.814,5.811],[101.154,5.691],[101.076,6.205],[100.26,6.643],[100.086,6.464],[99.691,6.848],[99.52,7.343],[98.988,7.908],[98.504,8.382],[98.34,7.795],[98.15,8.35],[98.259,8.974],[98.554,9.933],[99.038,10.961],[99.587,11.893],[99.196,12.805],[99.212,13.269],[99.098,13.828],[98.431,14.622],[98.192,15.124],[98.537,15.308],[98.903,16.178],[98.494,16.838],[97.859,17.568],[97.376,18.445],[97.798,18.627],[98.254,19.708],[98.96,19.753],[99.543,20.187],[100.116,20.418],[100.549,20.109],[100.606,19.508],[101.282,19.463],[101.036,18.409],[101.06,17.512],[102.114,18.109],[102.413,17.933],[102.999,17.962],[103.2,18.31],[103.956,18.241],[104.717,17.429],[104.779,16.442],[105.589,15.57],[105.544,14.724],[105.219,14.273]]]],"translations":{"ar":"تايلاند","bs":"Tajland","cs":"Thajsko","de":"Thailand","es":"Tailandia","fa_IR":"تایلند","fr":"ThaĂŻlande","id":"Thailand","it":"Thailandia","ja":"タイ","pl":"Tajlandia","pt_BR":"Tailândia","pt_PT":"Tailândia","ru":"ТаиНанд","uk":"Таїланд","zh_CN":"泰国","zh_TW":"泰國"}},{"N":"Lao PDR","I":"LA","C":[[[[107.383,14.202],[106.496,14.571],[106.044,13.881],[105.219,14.273],[105.544,14.724],[105.589,15.57],[104.779,16.442],[104.717,17.429],[103.956,18.241],[103.2,18.31],[102.999,17.962],[102.413,17.933],[102.114,18.109],[101.06,17.512],[101.036,18.409],[101.282,19.463],[100.606,19.508],[100.549,20.109],[100.116,20.418],[100.329,20.786],[101.18,21.437],[101.27,21.202],[101.803,21.174],[101.652,22.318],[102.17,22.465],[102.755,21.675],[103.204,20.767],[104.435,20.759],[104.823,19.887],[104.183,19.625],[103.897,19.265],[105.095,18.667],[105.926,17.485],[106.556,16.604],[107.313,15.909],[107.565,15.202],[107.383,14.202]]]],"translations":{"ar":"لاوس","bs":"Laos","cs":"Laos","de":"Laos","es":"Laos","fa_IR":"لائوس","fr":"Laos","id":"Laos","it":"Laos","ja":"ラオス","pl":"Laos","pt_BR":"Laos","pt_PT":"Laos","ru":"Лаос","uk":"Лаос","zh_CN":"老挝","zh_TW":"寮國"}},{"N":"Myanmar","I":"MM","C":[[[[100.116,20.418],[99.543,20.187],[98.96,19.753],[98.254,19.708],[97.798,18.627],[97.376,18.445],[97.859,17.568],[98.494,16.838],[98.903,16.178],[98.537,15.308],[98.192,15.124],[98.431,14.622],[99.098,13.828],[99.212,13.269],[99.196,12.805],[99.587,11.893],[99.038,10.961],[98.554,9.933],[98.457,10.675],[98.765,11.441],[98.428,12.033],[98.51,13.122],[98.104,13.64],[97.778,14.837],[97.597,16.101],[97.165,16.929],[96.506,16.427],[95.369,15.714],[94.808,15.803],[94.189,16.038],[94.533,17.277],[94.325,18.214],[93.541,19.366],[93.663,19.727],[93.078,19.855],[92.369,20.671],[92.303,21.475],[92.652,21.324],[92.673,22.041],[93.166,22.278],[93.06,22.703],[93.286,23.044],[93.325,24.079],[94.107,23.851],[94.553,24.675],[94.603,25.162],[95.155,26.001],[95.125,26.574],[96.419,27.265],[97.134,27.084],[97.052,27.699],[97.403,27.883],[97.327,28.262],[97.912,28.336],[98.246,27.747],[98.683,27.509],[98.712,26.744],[98.672,25.919],[97.725,25.084],[97.605,23.897],[98.66,24.063],[98.899,23.143],[99.532,22.949],[99.241,22.118],[99.983,21.743],[100.417,21.559],[101.15,21.85],[101.18,21.437],[100.329,20.786],[100.116,20.418]]]],"translations":{"ar":"ميانمار (بورما)","bs":"Mijanmar","cs":"Myanmar (Barma)","de":"Myanmar","es":"Myanmar (Birmania)","fa_IR":"میانمار (برمه)","fr":"Myanmar (Birmanie)","id":"Myanmar (Burma)","it":"Myanmar (Birmania)","ja":"ミャンマー (ビルマ)","pl":"Mjanma (Birma)","pt_BR":"Mianmar (Birmânia)","pt_PT":"Mianmar (Birmânia)","ru":"Мьянма (Бирма)","uk":"Мʼянма (Бірма)","zh_CN":"缅甸","zh_TW":"緬甸"}},{"N":"Vietnam","I":"VN","C":[[[[104.334,10.487],[105.2,10.889],[106.25,10.962],[105.811,11.568],[107.491,12.337],[107.615,13.536],[107.383,14.202],[107.565,15.202],[107.313,15.909],[106.556,16.604],[105.926,17.485],[105.095,18.667],[103.897,19.265],[104.183,19.625],[104.823,19.887],[104.435,20.759],[103.204,20.767],[102.755,21.675],[102.17,22.465],[102.707,22.709],[103.505,22.704],[104.477,22.819],[105.329,23.352],[105.811,22.977],[106.725,22.794],[106.567,22.218],[107.043,21.812],[108.05,21.552],[106.715,20.697],[105.882,19.752],[105.662,19.058],[106.427,18.004],[107.362,16.697],[108.269,16.08],[108.877,15.277],[109.335,13.426],[109.2,11.667],[108.366,11.008],[107.221,10.364],[106.405,9.531],[105.158,8.6],[104.795,9.241],[105.076,9.918],[104.334,10.487]]]],"translations":{"ar":"فيتنام","bs":"Vijetnam","cs":"Vietnam","de":"Vietnam","es":"Vietnam","fa_IR":"ویتنام","fr":"ViĂŞt Nam","id":"Vietnam","it":"Vietnam","ja":"ベトナム","pl":"Wietnam","pt_BR":"VietnĂŁ","pt_PT":"Vietname","ru":"Вьетнам","uk":"Вʼєтнам","zh_CN":"越南","zh_TW":"越南"}},{"N":"Dem. Rep. Korea","I":"KP","C":[[[[130.78,42.22],[130.78,42.22],[130.78,42.22],[130.78,42.22]]],[[[130.64,42.395],[130.64,42.395],[130.78,42.22],[130.4,42.28],[129.966,41.941],[129.667,41.601],[129.705,40.883],[129.188,40.662],[129.01,40.485],[128.633,40.19],[127.967,40.025],[127.533,39.757],[127.502,39.324],[127.385,39.213],[127.783,39.051],[128.35,38.612],[128.206,38.37],[127.78,38.305],[127.073,38.256],[126.684,37.805],[126.237,37.84],[126.175,37.75],[125.689,37.94],[125.568,37.752],[125.275,37.669],[125.24,37.857],[124.981,37.949],[124.712,38.108],[124.986,38.548],[125.222,38.666],[125.133,38.849],[125.387,39.388],[125.321,39.551],[124.737,39.66],[124.266,39.928],[125.08,40.57],[126.182,41.107],[126.869,41.817],[127.344,41.503],[128.208,41.467],[128.052,41.994],[129.597,42.425],[129.994,42.985],[130.64,42.395]]]],"translations":{"ar":"كوريا الشمالية","bs":"Sjeverna Koreja","cs":"SevernĂ­ Korea","de":"Nordkorea","es":"Corea del Norte","fa_IR":"کرهٔ شمالی","fr":"CorĂŠe du Nord","id":"Korea Utara","it":"Corea del Nord","ja":"北朝鮮","pl":"Korea Północna","pt_BR":"Coreia do Norte","pt_PT":"Coreia do Norte","ru":"КНДР","uk":"Північна Корея","zh_CN":"朝鲜","zh_TW":"北韓"}},{"N":"Republic of Korea","I":"KR","C":[[[[126.175,37.75],[126.237,37.84],[126.684,37.805],[127.073,38.256],[127.78,38.305],[128.206,38.37],[128.35,38.612],[129.213,37.432],[129.46,36.784],[129.468,35.632],[129.091,35.082],[128.186,34.89],[127.387,34.476],[126.486,34.39],[126.374,34.935],[126.559,35.685],[126.117,36.725],[126.86,36.894],[126.175,37.75]]]],"translations":{"ar":"كوريا الجنوبية","bs":"JuĹžna Koreja","cs":"JiĹžnĂ­ Korea","de":"SĂźdkorea","es":"Corea del Sur","fa_IR":"کرهٔ جنوبی","fr":"CorĂŠe du Sud","id":"Korea Selatan","it":"Corea del Sud","ja":"韓国","pl":"Korea Południowa","pt_BR":"Coreia do Sul","pt_PT":"Coreia do Sul","ru":"РоспуйНика Корея","uk":"Південна Корея","zh_CN":"韩国","zh_TW":"南韓"}},{"N":"Mongolia","I":"MN","C":[[[[87.751,49.297],[88.806,49.471],[90.714,50.332],[92.235,50.802],[93.104,50.495],[94.148,50.481],[94.816,50.013],[95.814,49.977],[97.26,49.726],[98.232,50.422],[97.826,51.011],[98.861,52.047],[99.982,51.634],[100.889,51.517],[102.065,51.26],[102.256,50.511],[103.677,50.09],[104.622,50.275],[105.887,50.406],[106.889,50.274],[107.868,49.794],[108.475,49.283],[109.402,49.293],[110.662,49.13],[111.581,49.378],[112.898,49.544],[114.362,50.248],[114.962,50.14],[115.486,49.805],[116.679,49.889],[116.192,49.135],[115.485,48.135],[115.743,47.727],[116.309,47.853],[117.296,47.698],[118.064,48.067],[118.867,47.747],[119.773,47.048],[119.663,46.693],[118.874,46.805],[117.422,46.673],[116.718,46.388],[115.985,45.727],[114.46,45.34],[113.464,44.809],[112.436,45.012],[111.873,45.102],[111.348,44.457],[111.668,44.073],[111.83,43.743],[111.13,43.407],[110.412,42.871],[109.244,42.519],[107.745,42.482],[106.129,42.134],[104.965,41.597],[104.522,41.908],[103.312,41.907],[101.833,42.515],[100.846,42.664],[99.516,42.525],[97.452,42.749],[96.349,42.726],[95.762,43.319],[95.307,44.241],[94.689,44.352],[93.481,44.975],[92.134,45.115],[90.946,45.286],[90.586,45.72],[90.971,46.888],[90.281,47.694],[88.854,48.069],[88.014,48.599],[87.751,49.297]]]],"translations":{"ar":"منغوليا","bs":"Mongolija","cs":"Mongolsko","de":"Mongolei","es":"Mongolia","fa_IR":"مغولستان","fr":"Mongolie","id":"Mongolia","it":"Mongolia","ja":"モンゴル","pl":"Mongolia","pt_BR":"MongĂłlia","pt_PT":"MongĂłlia","ru":"Монголия","uk":"Монголія","zh_CN":"蒙古","zh_TW":"蒙古"}},{"N":"India","I":"IN","C":[[[[97.327,28.262],[97.403,27.883],[97.052,27.699],[97.134,27.084],[96.419,27.265],[95.125,26.574],[95.155,26.001],[94.603,25.162],[94.553,24.675],[94.107,23.851],[93.325,24.079],[93.286,23.044],[93.06,22.703],[93.166,22.278],[92.673,22.041],[92.146,23.627],[91.87,23.624],[91.706,22.985],[91.159,23.504],[91.468,24.073],[91.915,24.13],[92.376,24.977],[91.8,25.147],[90.872,25.133],[89.921,25.27],[89.832,25.965],[89.355,26.014],[88.563,26.447],[88.21,25.768],[88.932,25.239],[88.306,24.866],[88.084,24.502],[88.7,24.234],[88.53,23.631],[88.876,22.879],[89.032,22.056],[88.889,21.691],[88.208,21.703],[86.976,21.496],[87.033,20.743],[86.499,20.152],[85.06,19.479],[83.941,18.302],[83.189,17.671],[82.193,17.017],[82.191,16.557],[81.693,16.31],[80.792,15.952],[80.325,15.899],[80.025,15.136],[80.233,13.836],[80.286,13.006],[79.863,12.056],[79.858,10.357],[79.341,10.309],[78.885,9.546],[79.19,9.217],[78.278,8.933],[77.941,8.253],[77.54,7.966],[76.593,8.899],[76.13,10.3],[75.746,11.308],[75.396,11.781],[74.865,12.742],[74.617,13.993],[74.444,14.617],[73.534,15.991],[73.12,17.929],[72.821,19.208],[72.824,20.42],[72.631,21.356],[71.175,20.757],[70.47,20.877],[69.164,22.089],[69.645,22.451],[69.35,22.843],[68.177,23.692],[68.843,24.359],[71.043,24.357],[70.845,25.215],[70.283,25.722],[70.169,26.492],[69.514,26.941],[70.616,27.989],[71.778,27.913],[72.824,28.962],[73.451,29.976],[74.421,30.98],[74.406,31.693],[75.259,32.271],[74.452,32.765],[74.104,33.441],[73.75,34.318],[74.24,34.749],[75.757,34.505],[76.872,34.654],[77.837,35.494],[78.912,34.322],[78.811,33.506],[79.209,32.994],[79.176,32.484],[78.458,32.618],[78.739,31.516],[79.721,30.883],[81.111,30.183],[80.477,29.73],[80.088,28.794],[81.057,28.416],[82,27.925],[83.304,27.365],[84.675,27.235],[85.252,26.726],[86.024,26.631],[87.227,26.398],[88.06,26.415],[88.175,26.81],[88.043,27.446],[88.12,27.877],[88.73,28.087],[88.814,27.299],[88.836,27.099],[89.745,26.719],[90.373,26.876],[91.218,26.809],[92.033,26.838],[92.104,27.453],[91.697,27.772],[92.503,27.897],[93.413,28.641],[94.566,29.277],[95.405,29.032],[96.118,29.453],[96.587,28.831],[96.249,28.411],[97.327,28.262]]]],"translations":{"ar":"الهند","bs":"Indija","cs":"Indie","de":"Indien","es":"India","fa_IR":"هند","fr":"Inde","id":"India","it":"India","ja":"インド","pl":"Indie","pt_BR":"Índia","pt_PT":"Índia","ru":"Индия","uk":"Індія","zh_CN":"印度","zh_TW":"印度"}},{"N":"Bangladesh","I":"BD","C":[[[[92.673,22.041],[92.652,21.324],[92.303,21.475],[92.369,20.671],[92.083,21.192],[92.025,21.702],[91.835,22.183],[91.417,22.765],[90.496,22.805],[90.587,22.393],[90.273,21.836],[89.847,22.039],[89.702,21.857],[89.419,21.966],[89.032,22.056],[88.876,22.879],[88.53,23.631],[88.7,24.234],[88.084,24.502],[88.306,24.866],[88.932,25.239],[88.21,25.768],[88.563,26.447],[89.355,26.014],[89.832,25.965],[89.921,25.27],[90.872,25.133],[91.8,25.147],[92.376,24.977],[91.915,24.13],[91.468,24.073],[91.159,23.504],[91.706,22.985],[91.87,23.624],[92.146,23.627],[92.673,22.041]]]],"translations":{"ar":"بنغلاديش","bs":"BangladeĹĄ","cs":"BangladĂŠĹĄ","de":"Bangladesch","es":"BangladĂŠs","fa_IR":"بنگلادش","fr":"Bangladesh","id":"Bangladesh","it":"Bangladesh","ja":"バングラデシュ","pl":"Bangladesz","pt_BR":"Bangladesh","pt_PT":"Bangladeche","ru":"Бангладеш","uk":"Бангладеш","zh_CN":"孟加拉国","zh_TW":"孟加拉"}},{"N":"Bhutan","I":"BT","C":[[[[91.697,27.772],[92.104,27.453],[92.033,26.838],[91.218,26.809],[90.373,26.876],[89.745,26.719],[88.836,27.099],[88.814,27.299],[89.476,28.043],[90.016,28.296],[90.731,28.065],[91.259,28.041],[91.697,27.772]]]],"translations":{"ar":"بوتان","bs":"Butan","cs":"BhĂştĂĄn","de":"Bhutan","es":"ButĂĄn","fa_IR":"بوتان","fr":"Bhoutan","id":"Bhutan","it":"Bhutan","ja":"ブータン","pl":"Bhutan","pt_BR":"ButĂŁo","pt_PT":"ButĂŁo","ru":"Бутан","uk":"Бутан","zh_CN":"不业","zh_TW":"不业"}},{"N":"Nepal","I":"NP","C":[[[[88.12,27.877],[88.043,27.446],[88.175,26.81],[88.06,26.415],[87.227,26.398],[86.024,26.631],[85.252,26.726],[84.675,27.235],[83.304,27.365],[82,27.925],[81.057,28.416],[80.088,28.794],[80.477,29.73],[81.111,30.183],[81.526,30.423],[82.328,30.115],[83.337,29.464],[83.899,29.32],[84.235,28.84],[85.012,28.643],[85.823,28.204],[86.955,27.974],[88.12,27.877]]]],"translations":{"ar":"نيبال","bs":"Nepal","cs":"NepĂĄl","de":"Nepal","es":"Nepal","fa_IR":"نپال","fr":"NĂŠpal","id":"Nepal","it":"Nepal","ja":"ネパール","pl":"Nepal","pt_BR":"Nepal","pt_PT":"Nepal","ru":"Непал","uk":"Непал","zh_CN":"尼泊尔","zh_TW":"尼泊爾"}},{"N":"Pakistan","I":"PK","C":[[[[77.837,35.494],[76.872,34.654],[75.757,34.505],[74.24,34.749],[73.75,34.318],[74.104,33.441],[74.452,32.765],[75.259,32.271],[74.406,31.693],[74.421,30.98],[73.451,29.976],[72.824,28.962],[71.778,27.913],[70.616,27.989],[69.514,26.941],[70.169,26.492],[70.283,25.722],[70.845,25.215],[71.043,24.357],[68.843,24.359],[68.177,23.692],[67.444,23.945],[67.145,24.664],[66.373,25.425],[64.53,25.237],[62.906,25.218],[61.497,25.078],[61.874,26.24],[63.317,26.757],[63.234,27.217],[62.755,27.379],[62.728,28.26],[61.772,28.699],[61.369,29.303],[60.874,29.829],[62.55,29.319],[63.55,29.468],[64.148,29.341],[64.35,29.56],[65.047,29.472],[66.346,29.888],[66.381,30.739],[66.939,31.305],[67.683,31.303],[67.793,31.583],[68.557,31.713],[68.927,31.62],[69.318,31.901],[69.263,32.502],[69.687,33.105],[70.324,33.359],[69.931,34.02],[70.882,33.989],[71.157,34.349],[71.115,34.733],[71.613,35.153],[71.499,35.651],[71.262,36.074],[71.846,36.51],[72.92,36.72],[74.068,36.836],[74.576,37.021],[75.158,37.133],[75.897,36.667],[76.193,35.898],[77.837,35.494]]]],"translations":{"ar":"باكستان","bs":"Pakistan","cs":"PĂĄkistĂĄn","de":"Pakistan","es":"PakistĂĄn","fa_IR":"پاکستان","fr":"Pakistan","id":"Pakistan","it":"Pakistan","ja":"パキスタン","pl":"Pakistan","pt_BR":"PaquistĂŁo","pt_PT":"PaquistĂŁo","ru":"Пакистан","uk":"Пакистан","zh_CN":"巴基斯坦","zh_TW":"巴基斯坦"}},{"N":"Afghanistan","I":"AF","C":[[[[66.519,37.363],[67.076,37.356],[67.83,37.145],[68.136,37.023],[68.859,37.344],[69.196,37.151],[69.519,37.609],[70.117,37.588],[70.271,37.735],[70.376,38.138],[70.807,38.486],[71.348,38.259],[71.239,37.953],[71.542,37.906],[71.449,37.066],[71.845,36.738],[72.193,36.948],[72.637,37.048],[73.26,37.495],[73.949,37.422],[74.98,37.42],[75.158,37.133],[74.576,37.021],[74.068,36.836],[72.92,36.72],[71.846,36.51],[71.262,36.074],[71.499,35.651],[71.613,35.153],[71.115,34.733],[71.157,34.349],[70.882,33.989],[69.931,34.02],[70.324,33.359],[69.687,33.105],[69.263,32.502],[69.318,31.901],[68.927,31.62],[68.557,31.713],[67.793,31.583],[67.683,31.303],[66.939,31.305],[66.381,30.739],[66.346,29.888],[65.047,29.472],[64.35,29.56],[64.148,29.341],[63.55,29.468],[62.55,29.319],[60.874,29.829],[61.781,30.736],[61.699,31.38],[60.942,31.548],[60.864,32.183],[60.536,32.981],[60.964,33.529],[60.528,33.676],[60.803,34.404],[61.211,35.65],[62.231,35.271],[62.985,35.404],[63.194,35.857],[63.983,36.008],[64.546,36.312],[64.746,37.112],[65.589,37.305],[65.746,37.661],[66.217,37.394],[66.519,37.363]]]],"translations":{"ar":"أفغانستان","bs":"Afganistan","cs":"AfghĂĄnistĂĄn","de":"Afghanistan","es":"AfganistĂĄn","fa_IR":"افغانستان","fr":"Afghanistan","id":"Afganistan","it":"Afghanistan","ja":"アフガニスタン","pl":"Afganistan","pt_BR":"AfeganistĂŁo","pt_PT":"AfeganistĂŁo","ru":"Афганистан","uk":"Афганістан","zh_CN":"阿富汗","zh_TW":"阿富汗"}},{"N":"Tajikistan","I":"TJ","C":[[[[67.83,37.145],[68.392,38.157],[68.176,38.902],[67.442,39.14],[67.701,39.58],[68.536,39.533],[69.012,40.086],[69.329,40.728],[70.667,40.96],[70.458,40.496],[70.601,40.219],[71.014,40.244],[70.648,39.936],[69.56,40.103],[69.465,39.527],[70.549,39.604],[71.785,39.279],[73.675,39.431],[73.929,38.506],[74.258,38.607],[74.865,38.379],[74.83,37.99],[74.98,37.42],[73.949,37.422],[73.26,37.495],[72.637,37.048],[72.193,36.948],[71.845,36.738],[71.449,37.066],[71.542,37.906],[71.239,37.953],[71.348,38.259],[70.807,38.486],[70.376,38.138],[70.271,37.735],[70.117,37.588],[69.519,37.609],[69.196,37.151],[68.859,37.344],[68.136,37.023],[67.83,37.145]]]],"translations":{"ar":"طاجيكستان","bs":"TadĹžikistan","cs":"TĂĄdĹžikistĂĄn","de":"Tadschikistan","es":"TayikistĂĄn","fa_IR":"تاجیکستان","fr":"Tadjikistan","id":"Tajikistan","it":"Tagikistan","ja":"タジキスタン","pl":"TadĹźykistan","pt_BR":"TadjiquistĂŁo","pt_PT":"TajiquistĂŁo","ru":"Таджикистан","uk":"Таджикистан","zh_CN":"塔吉克斯坦","zh_TW":"塔吉克"}},{"N":"Kyrgyzstan","I":"KG","C":[[[[70.962,42.266],[71.186,42.704],[71.845,42.845],[73.49,42.501],[73.645,43.091],[74.213,43.298],[75.637,42.878],[76,42.988],[77.658,42.961],[79.142,42.856],[79.644,42.497],[80.26,42.35],[80.119,42.124],[78.544,41.582],[78.187,41.185],[76.904,41.066],[76.526,40.428],[75.468,40.562],[74.777,40.366],[73.822,39.894],[73.96,39.66],[73.675,39.431],[71.785,39.279],[70.549,39.604],[69.465,39.527],[69.56,40.103],[70.648,39.936],[71.014,40.244],[71.775,40.146],[73.055,40.866],[71.87,41.393],[71.158,41.144],[70.42,41.52],[71.259,42.168],[70.962,42.266]]]],"translations":{"ar":"قيرغيزستان","bs":"Kirgistan","cs":"KyrgyzstĂĄn","de":"Kirgisistan","es":"KirguistĂĄn","fa_IR":"قرقیزستان","fr":"Kirghizstan","id":"Kirgizstan","it":"Kirghizistan","ja":"キルギス","pl":"Kirgistan","pt_BR":"QuirguistĂŁo","pt_PT":"QuirguistĂŁo","ru":"Киргизия","uk":"Киргизстан","zh_CN":"吉尔吉斯斯坦","zh_TW":"吉爾吉斯"}},{"N":"Turkmenistan","I":"TM","C":[[[[52.502,41.783],[52.944,42.116],[54.079,42.324],[54.755,42.044],[55.455,41.26],[55.968,41.309],[57.096,41.322],[56.932,41.826],[57.787,42.171],[58.629,42.752],[59.976,42.223],[60.083,41.425],[60.466,41.22],[61.547,41.266],[61.883,41.085],[62.374,40.054],[63.518,39.363],[64.17,38.892],[65.216,38.403],[66.546,37.975],[66.519,37.363],[66.217,37.394],[65.746,37.661],[65.589,37.305],[64.746,37.112],[64.546,36.312],[63.983,36.008],[63.194,35.857],[62.985,35.404],[62.231,35.271],[61.211,35.65],[61.123,36.492],[60.378,36.527],[59.235,37.413],[58.436,37.522],[57.33,38.029],[56.619,38.121],[56.18,37.935],[55.512,37.964],[54.8,37.392],[53.922,37.199],[53.736,37.906],[53.881,38.952],[53.101,39.291],[53.358,39.975],[52.694,40.034],[52.915,40.877],[53.858,40.631],[54.737,40.951],[54.008,41.551],[53.722,42.123],[52.917,41.868],[52.815,41.135],[52.502,41.783]]]],"translations":{"ar":"تركمانستان","bs":"Turkmenistan","cs":"TurkmenistĂĄn","de":"Turkmenistan","es":"TurkmenistĂĄn","fa_IR":"ترکمنستان","fr":"TurkmĂŠnistan","id":"Turkmenistan","it":"Turkmenistan","ja":"トルクメニスタン","pl":"Turkmenistan","pt_BR":"TurcomenistĂŁo","pt_PT":"TurquemenistĂŁo","ru":"Туркменистан","uk":"Туркменістан","zh_CN":"土库曼斯坦","zh_TW":"土庫曼"}},{"N":"Iran","I":"IR","C":[[[[48.568,29.927],[48.015,30.452],[48.005,30.985],[47.685,30.985],[47.849,31.709],[47.335,32.469],[46.109,33.017],[45.417,33.968],[45.648,34.748],[46.152,35.093],[46.076,35.677],[45.421,35.978],[44.773,37.17],[44.773,37.17],[44.226,37.972],[44.421,38.281],[44.109,39.428],[44.794,39.713],[44.953,39.336],[45.458,38.874],[46.144,38.741],[46.506,38.771],[47.685,39.508],[48.06,39.582],[48.356,39.289],[48.011,38.794],[48.634,38.27],[48.883,38.32],[49.2,37.583],[50.148,37.375],[50.842,36.873],[52.264,36.7],[53.826,36.965],[53.922,37.199],[54.8,37.392],[55.512,37.964],[56.18,37.935],[56.619,38.121],[57.33,38.029],[58.436,37.522],[59.235,37.413],[60.378,36.527],[61.123,36.492],[61.211,35.65],[60.803,34.404],[60.528,33.676],[60.964,33.529],[60.536,32.981],[60.864,32.183],[60.942,31.548],[61.699,31.38],[61.781,30.736],[60.874,29.829],[61.369,29.303],[61.772,28.699],[62.728,28.26],[62.755,27.379],[63.234,27.217],[63.317,26.757],[61.874,26.24],[61.497,25.078],[59.616,25.38],[58.526,25.61],[57.397,25.74],[56.971,26.966],[56.492,27.143],[55.724,26.965],[54.715,26.481],[53.493,26.812],[52.484,27.581],[51.521,27.866],[50.853,28.815],[50.115,30.148],[49.577,29.986],[48.941,30.317],[48.568,29.927]]]],"translations":{"ar":"إيران","bs":"Iran","cs":"ÍrĂĄn","de":"Iran","es":"IrĂĄn","fa_IR":"ایران","fr":"Iran","id":"Iran","it":"Iran","ja":"イラン","pl":"Iran","pt_BR":"IrĂŁ","pt_PT":"IrĂŁo","ru":"Иран","uk":"Іран","zh_CN":"伊朗","zh_TW":"伊朗"}},{"N":"Syria","I":"SY","C":[[[[35.72,32.709],[35.701,32.716],[35.836,32.868],[35.821,33.277],[36.066,33.825],[36.612,34.202],[36.448,34.594],[35.998,34.645],[35.905,35.41],[36.15,35.822],[36.418,36.041],[36.685,36.26],[36.739,36.818],[37.067,36.623],[38.168,36.901],[38.7,36.713],[39.523,36.716],[40.673,37.091],[41.212,37.074],[42.35,37.23],[41.837,36.606],[41.29,36.359],[41.384,35.628],[41.006,34.419],[38.792,33.379],[36.834,32.313],[35.72,32.709]]]],"translations":{"ar":"سوريا","bs":"Sirija","cs":"SĂ˝rie","de":"Syrien","es":"Siria","fa_IR":"سوریه","fr":"Syrie","id":"Suriah","it":"Siria","ja":"シリア","pl":"Syria","pt_BR":"SĂ­ria","pt_PT":"SĂ­ria","ru":"Сирия","uk":"Сирія","zh_CN":"叙利亚","zh_TW":"敘利亞"}},{"N":"Armenia","I":"AM","C":[[[[46.506,38.771],[46.144,38.741],[45.735,39.32],[45.74,39.474],[45.298,39.472],[45.002,39.74],[44.794,39.713],[44.4,40.005],[43.656,40.254],[43.753,40.74],[43.583,41.092],[44.972,41.248],[45.179,40.985],[45.56,40.812],[45.359,40.562],[45.892,40.218],[45.61,39.9],[46.035,39.628],[46.483,39.464],[46.506,38.771]]]],"translations":{"ar":"أرمينيا","bs":"Armenija","cs":"ArmĂŠnie","de":"Armenien","es":"Armenia","fa_IR":"ارمنستان","fr":"ArmĂŠnie","id":"Armenia","it":"Armenia","ja":"アルメニア","pl":"Armenia","pt_BR":"ArmĂŞnia","pt_PT":"ArmĂŠnia","ru":"Армения","uk":"Вірменія","zh_CN":"亚美尼亚","zh_TW":"亞美尼亞"}},{"N":"Sweden","I":"SE","C":[[[[11.027,58.856],[11.468,59.432],[12.3,60.118],[12.631,61.294],[11.992,61.8],[11.931,63.128],[12.58,64.066],[13.572,64.049],[13.92,64.445],[13.556,64.787],[15.108,66.194],[16.109,67.302],[16.769,68.014],[17.729,68.011],[17.994,68.567],[19.879,68.407],[20.025,69.065],[20.646,69.106],[21.979,68.617],[23.539,67.936],[23.566,66.396],[23.903,66.007],[22.183,65.724],[21.214,65.026],[21.37,64.414],[19.779,63.61],[17.848,62.749],[17.12,61.341],[17.831,60.637],[18.788,60.082],[17.869,58.954],[16.829,58.72],[16.448,57.041],[15.88,56.104],[14.667,56.201],[14.101,55.408],[12.943,55.362],[12.625,56.307],[11.788,57.442],[11.027,58.856]]]],"translations":{"ar":"السويد","bs":"Ĺ vedska","cs":"Ĺ vĂŠdsko","de":"Schweden","es":"Suecia","fa_IR":"سو،د","fr":"Suède","id":"Swedia","it":"Svezia","ja":"スウェーデン","pl":"Szwecja","pt_BR":"SuĂŠcia","pt_PT":"SuĂŠcia","ru":"Швеция","uk":"Швеція","zh_CN":"瑞典","zh_TW":"瑞典"}},{"N":"Belarus","I":"BY","C":[[[[28.177,56.169],[29.23,55.918],[29.372,55.67],[29.896,55.789],[30.874,55.551],[30.972,55.082],[30.758,54.812],[31.384,54.157],[31.791,53.975],[31.731,53.794],[32.406,53.618],[32.694,53.351],[32.305,53.133],[31.498,53.167],[31.305,53.074],[31.54,52.742],[31.786,52.102],[31.786,52.102],[30.928,52.042],[30.619,51.823],[30.555,51.32],[30.157,51.416],[29.255,51.368],[28.993,51.602],[28.618,51.428],[28.242,51.572],[27.454,51.592],[26.338,51.832],[25.328,51.911],[24.553,51.888],[24.005,51.617],[23.527,51.578],[23.508,52.024],[23.199,52.487],[23.799,52.691],[23.805,53.09],[23.528,53.47],[23.484,53.912],[24.451,53.906],[25.536,54.282],[25.768,54.847],[26.588,55.167],[26.494,55.615],[27.102,55.783],[28.177,56.169]]]],"translations":{"ar":"بيلاروس","bs":"Bjelorusija","cs":"Bělorusko","de":"Belarus","es":"Bielorrusia","fa_IR":"بلاروس","fr":"BiĂŠlorussie","id":"Belarus","it":"Bielorussia","ja":"ベラルーシ","pl":"Białoruś","pt_BR":"BielorrĂşssia","pt_PT":"BielorrĂşssia","ru":"Беларусь","uk":"Білорусь","zh_CN":"白俄罗斯","zh_TW":"白俄羅斯"}},{"N":"Ukraine","I":"UA","C":[[[[31.786,52.102],[32.159,52.061],[32.412,52.289],[32.716,52.238],[33.753,52.335],[34.392,51.769],[34.142,51.566],[34.225,51.256],[35.022,51.208],[35.378,50.774],[35.356,50.577],[36.626,50.226],[37.393,50.384],[38.011,49.916],[38.595,49.926],[40.069,49.601],[40.081,49.307],[39.675,48.784],[39.896,48.232],[39.738,47.899],[38.771,47.826],[38.255,47.546],[38.224,47.102],[37.425,47.022],[36.76,46.699],[35.824,46.646],[34.962,46.273],[35.013,45.738],[34.862,45.768],[34.732,45.966],[34.41,46.005],[33.699,46.22],[33.436,45.972],[33.299,46.081],[31.744,46.333],[31.675,46.706],[30.749,46.583],[30.378,46.032],[29.603,45.293],[29.15,45.465],[28.68,45.304],[28.234,45.488],[28.485,45.597],[28.66,45.94],[28.934,46.259],[28.863,46.438],[29.072,46.518],[29.171,46.379],[29.76,46.35],[30.025,46.424],[29.838,46.525],[29.909,46.674],[29.56,46.929],[29.415,47.347],[29.051,47.51],[29.123,47.849],[28.671,48.118],[28.26,48.156],[27.523,48.467],[26.858,48.368],[26.619,48.221],[26.197,48.221],[25.946,47.987],[25.208,47.891],[24.866,47.738],[24.402,47.982],[23.761,47.986],[23.142,48.096],[22.711,47.882],[22.641,48.15],[22.086,48.422],[22.281,48.825],[22.558,49.086],[22.776,49.027],[22.518,49.477],[23.427,50.309],[23.923,50.425],[24.03,50.705],[23.527,51.578],[24.005,51.617],[24.553,51.888],[25.328,51.911],[26.338,51.832],[27.454,51.592],[28.242,51.572],[28.618,51.428],[28.993,51.602],[29.255,51.368],[30.157,51.416],[30.555,51.32],[30.619,51.823],[30.928,52.042],[31.786,52.102]]],[[[33.436,45.972],[33.699,46.22],[34.41,46.005],[34.732,45.966],[34.862,45.768],[35.013,45.738],[35.021,45.651],[35.51,45.41],[36.53,45.47],[36.335,45.113],[35.24,44.94],[33.883,44.361],[33.326,44.565],[33.547,45.035],[32.454,45.327],[32.631,45.519],[33.588,45.852],[33.436,45.972]]]],"translations":{"ar":"أوكرانيا","bs":"Ukrajina","cs":"Ukrajina","de":"Ukraine","es":"Ucrania","fa_IR":"اوکراین","fr":"Ukraine","id":"Ukraina","it":"Ucraina","ja":"ウクライナ","pl":"Ukraina","pt_BR":"Ucrânia","pt_PT":"Ucrânia","ru":"Украина","uk":"Україна","zh_CN":"乌克兰","zh_TW":"烏克蘭"}},{"N":"Poland","I":"PL","C":[[[[23.484,53.912],[23.528,53.47],[23.805,53.09],[23.799,52.691],[23.199,52.487],[23.508,52.024],[23.527,51.578],[24.03,50.705],[23.923,50.425],[23.427,50.309],[22.518,49.477],[22.776,49.027],[22.558,49.086],[21.608,49.47],[20.888,49.329],[20.416,49.431],[19.825,49.217],[19.321,49.572],[18.91,49.436],[18.853,49.496],[18.393,49.989],[17.649,50.049],[17.555,50.362],[16.869,50.474],[16.719,50.216],[16.176,50.423],[16.239,50.698],[15.491,50.785],[15.017,51.107],[14.607,51.745],[14.685,52.09],[14.438,52.625],[14.075,52.981],[14.353,53.248],[14.12,53.757],[14.803,54.051],[16.363,54.513],[17.623,54.852],[18.621,54.683],[18.696,54.439],[19.661,54.426],[20.892,54.313],[22.731,54.328],[23.244,54.221],[23.484,53.912]]]],"translations":{"ar":"بولندا","bs":"Poljska","cs":"Polsko","de":"Polen","es":"Polonia","fa_IR":"لهستان","fr":"Pologne","id":"Polandia","it":"Polonia","ja":"ポーランド","pl":"Polska","pt_BR":"PolĂ´nia","pt_PT":"PolĂłnia","ru":"Польша","uk":"Польща","zh_CN":"波兰","zh_TW":"波蘭"}},{"N":"Austria","I":"AT","C":[[[[16.98,48.123],[16.904,47.715],[16.341,47.713],[16.534,47.496],[16.202,46.852],[16.012,46.684],[15.137,46.659],[14.632,46.432],[13.806,46.509],[12.376,46.768],[12.153,47.115],[11.165,46.942],[11.049,46.751],[10.443,46.894],[9.932,46.921],[9.48,47.103],[9.633,47.348],[9.594,47.525],[9.896,47.58],[10.402,47.302],[10.545,47.566],[11.426,47.524],[12.141,47.703],[12.621,47.672],[12.933,47.468],[13.026,47.638],[12.884,48.289],[13.243,48.416],[13.596,48.877],[14.339,48.555],[14.901,48.964],[15.253,49.039],[16.03,48.734],[16.499,48.786],[16.96,48.597],[16.88,48.47],[16.98,48.123]]]],"translations":{"ar":"النمسا","bs":"Austrija","cs":"Rakousko","de":"Österreich","es":"Austria","fa_IR":"اتریش","fr":"Autriche","id":"Austria","it":"Austria","ja":"オーストリア","pl":"Austria","pt_BR":"Áustria","pt_PT":"Áustria","ru":"Австрия","uk":"Австрія","zh_CN":"奥地利","zh_TW":"奧地利"}},{"N":"Hungary","I":"HU","C":[[[[22.086,48.422],[22.641,48.15],[22.711,47.882],[22.1,47.672],[21.627,46.994],[21.022,46.316],[20.22,46.127],[19.596,46.172],[18.83,45.909],[18.83,45.909],[18.456,45.759],[17.63,45.952],[16.883,46.381],[16.565,46.504],[16.371,46.841],[16.202,46.852],[16.534,47.496],[16.341,47.713],[16.904,47.715],[16.98,48.123],[17.488,47.867],[17.857,47.758],[18.697,47.881],[18.777,48.082],[19.174,48.111],[19.661,48.267],[19.769,48.203],[20.239,48.328],[20.474,48.563],[20.801,48.624],[21.872,48.32],[22.086,48.422]]]],"translations":{"ar":"هنغاريا","bs":"Mađarska","cs":"Maďarsko","de":"Ungarn","es":"HungrĂ­a","fa_IR":"مجارستان","fr":"Hongrie","id":"Hungaria","it":"Ungheria","ja":"ハンガリー","pl":"Węgry","pt_BR":"Hungria","pt_PT":"Hungria","ru":"Венгрия","uk":"Угорщина","zh_CN":"匈牙利","zh_TW":"匈牙利"}},{"N":"Moldova","I":"MD","C":[[[[26.619,48.221],[26.858,48.368],[27.523,48.467],[28.26,48.156],[28.671,48.118],[29.123,47.849],[29.051,47.51],[29.415,47.347],[29.56,46.929],[29.909,46.674],[29.838,46.525],[30.025,46.424],[29.76,46.35],[29.171,46.379],[29.072,46.518],[28.863,46.438],[28.934,46.259],[28.66,45.94],[28.485,45.597],[28.234,45.488],[28.054,45.945],[28.16,46.372],[28.128,46.81],[27.551,47.405],[27.234,47.827],[26.924,48.123],[26.619,48.221]]]],"translations":{"ar":"مولدوفا","bs":"Moldavija","cs":"Moldavsko","de":"Republik Moldau","es":"Moldavia","fa_IR":"مولداوی","fr":"Moldavie","id":"Moldova","it":"Moldavia","ja":"モルドバ","pl":"Mołdawia","pt_BR":"MoldĂĄvia","pt_PT":"MoldĂĄvia","ru":"Молдова","uk":"Молдова","zh_CN":"摩尔多瓦","zh_TW":"摩爾多瓦"}},{"N":"Romania","I":"RO","C":[[[[28.234,45.488],[28.68,45.304],[29.15,45.465],[29.603,45.293],[29.627,45.035],[29.142,44.82],[28.838,44.914],[28.558,43.707],[27.97,43.812],[27.242,44.176],[26.065,43.943],[25.569,43.688],[24.101,43.741],[23.332,43.897],[22.945,43.824],[22.657,44.235],[22.474,44.409],[22.706,44.578],[22.459,44.703],[22.145,44.478],[21.562,44.769],[21.484,45.181],[20.874,45.416],[20.762,45.735],[20.22,46.127],[21.022,46.316],[21.627,46.994],[22.1,47.672],[22.711,47.882],[23.142,48.096],[23.761,47.986],[24.402,47.982],[24.866,47.738],[25.208,47.891],[25.946,47.987],[26.197,48.221],[26.619,48.221],[26.924,48.123],[27.234,47.827],[27.551,47.405],[28.128,46.81],[28.16,46.372],[28.054,45.945],[28.234,45.488]]]],"translations":{"ar":"رومانيا","bs":"Rumunija","cs":"Rumunsko","de":"Rumänien","es":"RumanĂ­a","fa_IR":"رومانی","fr":"Roumanie","id":"Rumania","it":"Romania","ja":"ルーマニア","pl":"Rumunia","pt_BR":"RomĂŞnia","pt_PT":"RomĂŠnia","ru":"Румыния","uk":"Румунія","zh_CN":"罗马尼亚","zh_TW":"羅馬尼亞"}},{"N":"Lithuania","I":"LT","C":[[[[26.494,55.615],[26.588,55.167],[25.768,54.847],[25.536,54.282],[24.451,53.906],[23.484,53.912],[23.244,54.221],[22.731,54.328],[22.651,54.583],[22.758,54.857],[22.316,55.015],[21.268,55.19],[21.056,56.031],[22.201,56.338],[23.878,56.274],[24.861,56.373],[25.001,56.165],[25.533,56.1],[26.494,55.615]]]],"translations":{"ar":"ليتوانيا","bs":"Litvanija","cs":"Litva","de":"Litauen","es":"Lituania","fa_IR":"لیتوانی","fr":"Lituanie","id":"Lituania","it":"Lituania","ja":"リトアニア","pl":"Litwa","pt_BR":"Lituânia","pt_PT":"Lituânia","ru":"Литва","uk":"Литва","zh_CN":"立陶宛","zh_TW":"立陶宛"}},{"N":"Latvia","I":"LV","C":[[[[27.288,57.475],[27.77,57.244],[27.855,56.759],[28.177,56.169],[27.102,55.783],[26.494,55.615],[25.533,56.1],[25.001,56.165],[24.861,56.373],[23.878,56.274],[22.201,56.338],[21.056,56.031],[21.09,56.784],[21.582,57.412],[22.524,57.753],[23.318,57.006],[24.121,57.026],[24.313,57.793],[25.165,57.97],[25.603,57.848],[26.464,57.476],[27.288,57.475]]]],"translations":{"ar":"لاتفيا","bs":"Latvija","cs":"LotyĹĄsko","de":"Lettland","es":"Letonia","fa_IR":"لتونی","fr":"Lettonie","id":"Latvia","it":"Lettonia","ja":"ラトビア","pl":"Łotwa","pt_BR":"LetĂ´nia","pt_PT":"LetĂłnia","ru":"Латвия","uk":"Латвія","zh_CN":"拉脱维亚","zh_TW":"拉脫維亞"}},{"N":"Estonia","I":"EE","C":[[[[27.981,59.475],[27.981,59.475],[28.132,59.301],[27.42,58.725],[27.717,57.792],[27.288,57.475],[26.464,57.476],[25.603,57.848],[25.165,57.97],[24.313,57.793],[24.429,58.383],[24.061,58.257],[23.427,58.613],[23.34,59.187],[24.604,59.466],[25.864,59.611],[26.949,59.446],[27.981,59.475],[27.981,59.475]]]],"translations":{"ar":"إستونيا","bs":"Estonija","cs":"Estonsko","de":"Estland","es":"Estonia","fa_IR":"استونی","fr":"Estonie","id":"Estonia","it":"Estonia","ja":"エストニア","pl":"Estonia","pt_BR":"EstĂ´nia","pt_PT":"EstĂłnia","ru":"Эстония","uk":"Естонія","zh_CN":"爱沙尼亚","zh_TW":"愛沙尼亞"}},{"N":"Germany","I":"DE","C":[[[[14.12,53.757],[14.353,53.248],[14.075,52.981],[14.438,52.625],[14.685,52.09],[14.607,51.745],[15.017,51.107],[14.571,51.002],[14.307,51.117],[14.056,50.927],[13.338,50.733],[12.967,50.484],[12.24,50.266],[12.415,49.969],[12.521,49.547],[13.031,49.307],[13.596,48.877],[13.243,48.416],[12.884,48.289],[13.026,47.638],[12.933,47.468],[12.621,47.672],[12.141,47.703],[11.426,47.524],[10.545,47.566],[10.402,47.302],[9.896,47.58],[9.594,47.525],[8.523,47.831],[8.317,47.614],[7.467,47.621],[7.594,48.333],[8.099,49.018],[6.658,49.202],[6.186,49.464],[6.243,49.902],[6.043,50.128],[6.157,50.804],[5.989,51.852],[6.589,51.852],[6.843,52.228],[7.092,53.144],[6.905,53.482],[7.1,53.694],[7.936,53.748],[8.122,53.528],[8.801,54.021],[8.572,54.396],[8.526,54.963],[9.282,54.831],[9.922,54.983],[9.94,54.597],[10.95,54.364],[10.939,54.009],[11.956,54.196],[12.518,54.47],[13.647,54.076],[14.12,53.757]]]],"translations":{"ar":"ألمانيا","bs":"Njemačka","cs":"Německo","de":"Deutschland","es":"Alemania","fa_IR":"آلمان","fr":"Allemagne","id":"Jerman","it":"Germania","ja":"ドイツ","pl":"Niemcy","pt_BR":"Alemanha","pt_PT":"Alemanha","ru":"Германия","uk":"Німеччина","zh_CN":"德国","zh_TW":"德國"}},{"N":"Bulgaria","I":"BG","C":[[[[22.657,44.235],[22.945,43.824],[23.332,43.897],[24.101,43.741],[25.569,43.688],[26.065,43.943],[27.242,44.176],[27.97,43.812],[28.558,43.707],[28.039,43.293],[27.674,42.578],[27.997,42.007],[27.136,42.141],[26.117,41.827],[26.106,41.329],[25.197,41.234],[24.493,41.584],[23.692,41.309],[22.952,41.338],[22.881,41.999],[22.381,42.32],[22.545,42.461],[22.437,42.58],[22.605,42.899],[22.986,43.211],[22.5,43.643],[22.41,44.008],[22.657,44.235]]]],"translations":{"ar":"بلغاريا","bs":"Bugarska","cs":"Bulharsko","de":"Bulgarien","es":"Bulgaria","fa_IR":"بلغارستان","fr":"Bulgarie","id":"Bulgaria","it":"Bulgaria","ja":"ブルガリア","pl":"Bułgaria","pt_BR":"BulgĂĄria","pt_PT":"BulgĂĄria","ru":"Болгария","uk":"Болгарія","zh_CN":"保加利亚","zh_TW":"保加利亞"}},{"N":"Greece","I":"GR","C":[[[[26.29,35.3],[26.165,35.005],[24.725,34.92],[24.735,35.085],[23.515,35.28],[23.7,35.705],[24.247,35.368],[25.025,35.425],[25.769,35.354],[25.745,35.18],[26.29,35.3]]],[[[22.952,41.338],[23.692,41.309],[24.493,41.584],[25.197,41.234],[26.106,41.329],[26.117,41.827],[26.604,41.562],[26.295,40.936],[26.057,40.824],[25.448,40.853],[24.926,40.947],[23.715,40.687],[24.408,40.125],[23.9,39.962],[23.343,39.961],[22.814,40.476],[22.626,40.257],[22.85,39.659],[23.35,39.19],[22.973,38.971],[23.53,38.51],[24.025,38.22],[24.04,37.655],[23.115,37.92],[23.41,37.41],[22.775,37.305],[23.154,36.423],[22.49,36.41],[21.67,36.845],[21.295,37.645],[21.12,38.31],[20.73,38.77],[20.218,39.34],[20.15,39.625],[20.615,40.11],[20.675,40.435],[21,40.58],[21.02,40.843],[21.674,40.931],[22.055,41.15],[22.597,41.13],[22.762,41.305],[22.952,41.338]]]],"translations":{"ar":"اليونان","bs":"Grčka","cs":"Řecko","de":"Griechenland","es":"Grecia","fa_IR":"یونان","fr":"Grèce","id":"Yunani","it":"Grecia","ja":"ギリシャ","pl":"Grecja","pt_BR":"GrĂŠcia","pt_PT":"GrĂŠcia","ru":"Греция","uk":"Греція","zh_CN":"希腊","zh_TW":"希臘"}},{"N":"Turkey","I":"TR","C":[[[[44.773,37.17],[44.293,37.002],[43.942,37.256],[42.779,37.385],[42.35,37.23],[41.212,37.074],[40.673,37.091],[39.523,36.716],[38.7,36.713],[38.168,36.901],[37.067,36.623],[36.739,36.818],[36.685,36.26],[36.418,36.041],[36.15,35.822],[35.782,36.275],[36.161,36.651],[35.551,36.565],[34.715,36.796],[34.027,36.22],[32.509,36.108],[31.7,36.644],[30.622,36.678],[30.391,36.263],[29.7,36.144],[28.733,36.677],[27.641,36.659],[27.049,37.653],[26.318,38.208],[26.805,38.986],[26.171,39.464],[27.28,40.42],[28.82,40.46],[29.24,41.22],[31.146,41.088],[32.348,41.736],[33.513,42.019],[35.168,42.04],[36.913,41.335],[38.348,40.949],[39.513,41.103],[40.373,41.014],[41.554,41.536],[42.62,41.583],[43.583,41.092],[43.753,40.74],[43.656,40.254],[44.4,40.005],[44.794,39.713],[44.109,39.428],[44.421,38.281],[44.226,37.972],[44.773,37.17],[44.773,37.17]]],[[[26.117,41.827],[27.136,42.141],[27.997,42.007],[28.116,41.623],[28.988,41.3],[28.806,41.055],[27.619,41],[27.192,40.691],[26.358,40.152],[26.043,40.618],[26.057,40.824],[26.295,40.936],[26.604,41.562],[26.117,41.827]]]],"translations":{"ar":"تركيا","bs":"Turska","cs":"Turecko","de":"TĂźrkei","es":"TurquĂ­a","fa_IR":"ترکیه","fr":"Turquie","id":"Turki","it":"Turchia","ja":"トルコ","pl":"Turcja","pt_BR":"Turquia","pt_PT":"Turquia","ru":"Турция","uk":"Туреччина","zh_CN":"土耳其","zh_TW":"土耳其"}},{"N":"Albania","I":"AL","C":[[[[21.02,40.843],[21,40.58],[20.675,40.435],[20.615,40.11],[20.15,39.625],[19.98,39.695],[19.96,39.915],[19.406,40.251],[19.319,40.727],[19.404,41.41],[19.54,41.72],[19.372,41.878],[19.372,41.878],[19.304,42.196],[19.738,42.688],[19.802,42.5],[20.071,42.589],[20.284,42.32],[20.523,42.218],[20.59,41.855],[20.59,41.855],[20.463,41.515],[20.605,41.086],[21.02,40.843]]]],"translations":{"ar":"ألبانيا","bs":"Albanija","cs":"AlbĂĄnie","de":"Albanien","es":"Albania","fa_IR":"آلبانی","fr":"Albanie","id":"Albania","it":"Albania","ja":"アルバニア","pl":"Albania","pt_BR":"Albânia","pt_PT":"Albânia","ru":"Албания","uk":"Албанія","zh_CN":"阿尔巴尼亚","zh_TW":"阿爾巴尼亞"}},{"N":"Croatia","I":"HR","C":[[[[16.565,46.504],[16.883,46.381],[17.63,45.952],[18.456,45.759],[18.83,45.909],[19.073,45.522],[19.39,45.237],[19.005,44.86],[18.553,45.082],[17.862,45.068],[17.002,45.234],[16.535,45.212],[16.318,45.004],[15.959,45.234],[15.75,44.819],[16.24,44.351],[16.456,44.041],[16.916,43.668],[17.297,43.446],[17.675,43.029],[18.56,42.65],[18.45,42.48],[18.45,42.48],[17.51,42.85],[16.93,43.21],[16.015,43.507],[15.174,44.243],[15.376,44.318],[14.92,44.738],[14.902,45.076],[14.259,45.234],[13.952,44.802],[13.657,45.137],[13.679,45.484],[13.715,45.5],[14.412,45.466],[14.595,45.635],[14.935,45.472],[15.328,45.452],[15.324,45.732],[15.672,45.834],[15.769,46.238],[16.565,46.504]]]],"translations":{"ar":"كرواتيا","bs":"Hrvatska","cs":"Chorvatsko","de":"Kroatien","es":"Croacia","fa_IR":"کرواسی","fr":"Croatie","id":"Kroasia","it":"Croazia","ja":"クロアチア","pl":"Chorwacja","pt_BR":"CroĂĄcia","pt_PT":"CroĂĄcia","ru":"Хорватия","uk":"Хорватія","zh_CN":"克罗地亚","zh_TW":"克羅埃西亞"}},{"N":"Switzerland","I":"CH","C":[[[[9.594,47.525],[9.633,47.348],[9.48,47.103],[9.932,46.921],[10.443,46.894],[10.363,46.484],[9.923,46.315],[9.183,46.44],[8.966,46.037],[8.49,46.005],[8.317,46.164],[7.756,45.824],[7.274,45.777],[6.844,45.991],[6.5,46.43],[6.023,46.273],[6.037,46.726],[6.769,47.288],[6.737,47.542],[7.192,47.45],[7.467,47.621],[8.317,47.614],[8.523,47.831],[9.594,47.525]]]],"translations":{"ar":"سويسرا","bs":"Ĺ vicarska","cs":"Ĺ vĂ˝carsko","de":"Schweiz","es":"Suiza","fa_IR":"سوئیس","fr":"Suisse","id":"Swiss","it":"Svizzera","ja":"スイス","pl":"Szwajcaria","pt_BR":"Suíça","pt_PT":"Suíça","ru":"Швейцария","uk":"Швейцарія","zh_CN":"瑞士","zh_TW":"瑞士"}},{"N":"Luxembourg","I":"LU","C":[[[[6.043,50.128],[6.243,49.902],[6.186,49.464],[5.898,49.443],[5.674,49.529],[5.782,50.09],[6.043,50.128]]]],"translations":{"ar":"لوكسمبورغ","bs":"Luksemburg","cs":"Lucembursko","de":"Luxemburg","es":"Luxemburgo","fa_IR":"لوکزامبورگ","fr":"Luxembourg","id":"Luksemburg","it":"Lussemburgo","ja":"ルクセンブルク","pl":"Luksemburg","pt_BR":"Luxemburgo","pt_PT":"Luxemburgo","ru":"Люксембург","uk":"Люксембург","zh_CN":"卢森堡","zh_TW":"盧森堡"}},{"N":"Belgium","I":"BE","C":[[[[6.157,50.804],[6.043,50.128],[5.782,50.09],[5.674,49.529],[4.799,49.985],[4.286,49.907],[3.588,50.379],[3.123,50.78],[2.658,50.797],[2.514,51.149],[3.315,51.346],[3.315,51.346],[3.315,51.346],[4.047,51.267],[4.974,51.475],[5.607,51.037],[6.157,50.804]]]],"translations":{"ar":"بلجيكا","bs":"Belgija","cs":"Belgie","de":"Belgien","es":"BĂŠlgica","fa_IR":"بلژیک","fr":"Belgique","id":"Belgia","it":"Belgio","ja":"ベルギー","pl":"Belgia","pt_BR":"BĂŠlgica","pt_PT":"BĂŠlgica","ru":"Бельгия","uk":"Бельгія","zh_CN":"比利时","zh_TW":"比利時"}},{"N":"Netherlands","I":"NL","C":[[[[6.905,53.482],[7.092,53.144],[6.843,52.228],[6.589,51.852],[5.989,51.852],[6.157,50.804],[5.607,51.037],[4.974,51.475],[4.047,51.267],[3.315,51.346],[3.315,51.346],[3.83,51.621],[4.706,53.092],[6.074,53.51],[6.905,53.482]]]],"translations":{"ar":"هولندا","bs":"Nizozemska","cs":"Nizozemsko","de":"Niederlande","es":"PaĂ­ses Bajos","fa_IR":"هلند","fr":"Pays-Bas","id":"Belanda","it":"Paesi Bassi","ja":"オランダ","pl":"Holandia","pt_BR":"PaĂ­ses Baixos","pt_PT":"PaĂ­ses Baixos","ru":"Нидерланды","uk":"Нідерланди","zh_CN":"荷兰","zh_TW":"荷蘭"}},{"N":"Portugal","I":"PT","C":[[[[-9.035,41.881],[-8.672,42.135],[-8.264,42.28],[-8.013,41.791],[-7.423,41.792],[-7.251,41.918],[-6.669,41.883],[-6.389,41.382],[-6.851,41.111],[-6.864,40.331],[-7.026,40.185],[-7.067,39.712],[-7.499,39.63],[-7.098,39.03],[-7.374,38.373],[-7.029,38.076],[-7.167,37.804],[-7.537,37.429],[-7.454,37.098],[-7.856,36.838],[-8.383,36.979],[-8.899,36.869],[-8.746,37.651],[-8.84,38.266],[-9.287,38.358],[-9.527,38.737],[-9.447,39.392],[-9.048,39.755],[-8.977,40.159],[-8.769,40.761],[-8.791,41.184],[-8.991,41.543],[-9.035,41.881]]]],"translations":{"ar":"البرتغال","bs":"Portugal","cs":"Portugalsko","de":"Portugal","es":"Portugal","fa_IR":"پرتغال","fr":"Portugal","id":"Portugal","it":"Portogallo","ja":"ポルトガル","pl":"Portugalia","pt_BR":"Portugal","pt_PT":"Portugal","ru":"Португалия","uk":"Португалія","zh_CN":"葡萄牙","zh_TW":"葡萄牙"}},{"N":"Spain","I":"ES","C":[[[[-7.454,37.098],[-7.537,37.429],[-7.167,37.804],[-7.029,38.076],[-7.374,38.373],[-7.098,39.03],[-7.499,39.63],[-7.067,39.712],[-7.026,40.185],[-6.864,40.331],[-6.851,41.111],[-6.389,41.382],[-6.669,41.883],[-7.251,41.918],[-7.423,41.792],[-8.013,41.791],[-8.264,42.28],[-8.672,42.135],[-9.035,41.881],[-8.984,42.593],[-9.393,43.027],[-7.978,43.748],[-6.754,43.568],[-5.412,43.574],[-4.348,43.403],[-3.518,43.456],[-1.901,43.423],[-1.503,43.034],[0.338,42.58],[0.702,42.796],[1.827,42.343],[2.986,42.473],[3.039,41.892],[2.092,41.226],[0.811,41.015],[0.721,40.678],[0.107,40.124],[-0.279,39.31],[0.111,38.739],[-0.467,38.292],[-0.683,37.642],[-1.438,37.443],[-2.146,36.674],[-3.416,36.659],[-4.369,36.678],[-4.995,36.325],[-5.377,35.947],[-5.866,36.03],[-6.237,36.368],[-6.52,36.943],[-7.454,37.098]]]],"translations":{"ar":"إسبانيا","bs":"Ĺ panija","cs":"Ĺ panělsko","de":"Spanien","es":"EspaĂąa","fa_IR":"اسپانیا","fr":"Espagne","id":"Spanyol","it":"Spagna","ja":"スペイン","pl":"Hiszpania","pt_BR":"Espanha","pt_PT":"Espanha","ru":"Испания","uk":"Іспанія","zh_CN":"西班牙","zh_TW":"西班牙"}},{"N":"Ireland","I":"IE","C":[[[[-6.198,53.868],[-6.033,53.153],[-6.789,52.26],[-8.562,51.669],[-9.977,51.82],[-9.166,52.865],[-9.689,53.881],[-8.328,54.665],[-7.572,55.132],[-7.366,54.596],[-7.572,54.06],[-6.954,54.074],[-6.198,53.868]]]],"translations":{"ar":"أيرلندا","bs":"Irska","cs":"Irsko","de":"Irland","es":"Irlanda","fa_IR":"ایرلند","fr":"Irlande","id":"Irlandia","it":"Irlanda","ja":"アイルランド","pl":"Irlandia","pt_BR":"Irlanda","pt_PT":"Irlanda","ru":"Ирландия","uk":"Ірландія","zh_CN":"爱尔兰","zh_TW":"愛爾蘭"}},{"N":"New Caledonia","I":"NC","C":[[[[165.78,-21.08],[166.6,-21.7],[167.12,-22.16],[166.74,-22.4],[166.19,-22.13],[165.474,-21.68],[164.83,-21.15],[164.168,-20.445],[164.03,-20.106],[164.46,-20.12],[165.02,-20.46],[165.46,-20.8],[165.78,-21.08]]]],"translations":{"ar":"كاليدونيا الجديدة","bs":"Nova Kaledonija","cs":"NovĂĄ Kaledonie","de":"Neukaledonien","es":"Nueva Caledonia","fa_IR":"کالدونیای جدید","fr":"Nouvelle-CalĂŠdonie","id":"Kaledonia Baru","it":"Nuova Caledonia","ja":"ニューカレドニア","pl":"Nowa Kaledonia","pt_BR":"Nova CaledĂ´nia","pt_PT":"Nova CaledĂłnia","ru":"Новая Каледония","uk":"Нова Каледонія","zh_CN":"新喀里多尼亚","zh_TW":"新喀里多尼亞"}},{"N":"Solomon Islands","I":"SB","C":[[[[162.119,-10.483],[162.399,-10.826],[161.7,-10.82],[161.32,-10.205],[161.917,-10.447],[162.119,-10.483]]],[[[161.68,-9.6],[161.529,-9.784],[160.788,-8.918],[160.58,-8.32],[160.92,-8.32],[161.28,-9.12],[161.68,-9.6]]],[[[160.852,-9.873],[160.463,-9.895],[159.849,-9.794],[159.64,-9.64],[159.703,-9.243],[160.363,-9.4],[160.689,-9.61],[160.852,-9.873]]],[[[159.64,-8.02],[159.875,-8.337],[159.917,-8.538],[159.134,-8.114],[158.586,-7.755],[158.211,-7.422],[158.36,-7.32],[158.82,-7.56],[159.64,-8.02]]],[[[157.14,-7.022],[157.538,-7.348],[157.339,-7.405],[156.902,-7.177],[156.491,-6.766],[156.543,-6.599],[157.14,-7.022]]]],"translations":{"ar":"؏زع سليمان","bs":"Solomonska Ostrva","cs":"Ĺ alamounovy ostrovy","de":"Salomonen","es":"Islas SalomĂłn","fa_IR":"جزایر سلیمان","fr":"Îles Salomon","id":"Kepulauan Solomon","it":"Isole Salomone","ja":"ソロモン諸島","pl":"Wyspy Salomona","pt_BR":"Ilhas SalomĂŁo","pt_PT":"Ilhas SalomĂŁo","ru":"Соломоновы Đž-ва","uk":"Соломонові Острови","zh_CN":"所罗门群岛","zh_TW":"索羅門群島"}},{"N":"New Zealand","I":"NZ","C":[[[[176.886,-40.066],[176.508,-40.605],[176.012,-41.29],[175.24,-41.688],[175.068,-41.426],[174.651,-41.282],[175.228,-40.459],[174.9,-39.909],[173.824,-39.509],[173.852,-39.147],[174.575,-38.798],[174.743,-38.028],[174.697,-37.381],[174.292,-36.711],[174.319,-36.535],[173.841,-36.122],[173.054,-35.237],[172.636,-34.529],[173.007,-34.451],[173.551,-35.006],[174.329,-35.265],[174.612,-36.156],[175.337,-37.209],[175.358,-36.526],[175.809,-36.799],[175.958,-37.555],[176.763,-37.881],[177.439,-37.961],[178.01,-37.58],[178.517,-37.695],[178.275,-38.583],[177.97,-39.166],[177.207,-39.146],[176.94,-39.45],[177.033,-39.88],[176.886,-40.066]]],[[[169.668,-43.555],[170.525,-43.032],[171.125,-42.513],[171.57,-41.767],[171.949,-41.514],[172.097,-40.956],[172.799,-40.494],[173.02,-40.919],[173.247,-41.332],[173.958,-40.927],[174.248,-41.349],[174.249,-41.77],[173.876,-42.233],[173.223,-42.97],[172.711,-43.372],[173.08,-43.853],[172.309,-43.866],[171.453,-44.243],[171.185,-44.897],[170.617,-45.909],[169.831,-46.356],[169.332,-46.641],[168.411,-46.62],[167.764,-46.29],[166.677,-46.22],[166.509,-45.853],[167.046,-45.111],[168.304,-44.124],[168.949,-43.936],[169.668,-43.555]]]],"translations":{"ar":"نيوزيلندا","bs":"Novi Zeland","cs":"NovĂ˝ ZĂŠland","de":"Neuseeland","es":"Nueva Zelanda","fa_IR":"نیوزیلند","fr":"Nouvelle-ZĂŠlande","id":"Selandia Baru","it":"Nuova Zelanda","ja":"ニュージーランド","pl":"Nowa Zelandia","pt_BR":"Nova Zelândia","pt_PT":"Nova Zelândia","ru":"Новая Зеландия","uk":"Нова Зеландія","zh_CN":"新西兰","zh_TW":"紐輿蘭"}},{"N":"Australia","I":"AU","C":[[[[147.689,-40.808],[148.289,-40.875],[148.36,-42.062],[148.017,-42.407],[147.914,-43.212],[147.565,-42.938],[146.87,-43.635],[146.663,-43.581],[146.048,-43.55],[145.432,-42.694],[145.295,-42.034],[144.718,-41.163],[144.744,-40.704],[145.398,-40.793],[146.364,-41.138],[146.909,-41.001],[147.689,-40.808]]],[[[126.149,-32.216],[125.089,-32.729],[124.222,-32.959],[124.029,-33.484],[123.66,-33.89],[122.811,-33.914],[122.183,-34.003],[121.299,-33.821],[120.58,-33.93],[119.894,-33.976],[119.299,-34.509],[119.007,-34.464],[118.506,-34.747],[118.025,-35.065],[117.296,-35.025],[116.625,-35.025],[115.564,-34.386],[115.027,-34.197],[115.049,-33.623],[115.545,-33.487],[115.715,-33.26],[115.679,-32.9],[115.802,-32.205],[115.69,-31.612],[115.161,-30.602],[114.997,-30.031],[115.04,-29.461],[114.642,-28.81],[114.616,-28.516],[114.174,-28.118],[114.049,-27.335],[113.477,-26.543],[113.339,-26.117],[113.778,-26.549],[113.441,-25.621],[113.937,-25.911],[114.233,-26.298],[114.216,-25.786],[113.721,-24.999],[113.625,-24.684],[113.394,-24.385],[113.502,-23.806],[113.707,-23.56],[113.843,-23.06],[113.737,-22.475],[114.15,-21.756],[114.225,-22.517],[114.648,-21.83],[115.46,-21.495],[115.947,-21.069],[116.712,-20.702],[117.166,-20.624],[117.442,-20.747],[118.23,-20.374],[118.836,-20.263],[118.988,-20.044],[119.252,-19.953],[119.805,-19.977],[120.856,-19.684],[121.4,-19.24],[121.655,-18.705],[122.242,-18.198],[122.287,-17.799],[122.313,-17.255],[123.013,-16.405],[123.434,-17.269],[123.859,-17.069],[123.503,-16.597],[123.817,-16.111],[124.258,-16.328],[124.38,-15.567],[124.926,-15.075],[125.167,-14.68],[125.67,-14.51],[125.686,-14.231],[126.125,-14.347],[126.143,-14.096],[126.583,-13.953],[127.066,-13.818],[127.805,-14.277],[128.36,-14.869],[128.986,-14.876],[129.621,-14.97],[129.41,-14.421],[129.889,-13.619],[130.339,-13.357],[130.184,-13.108],[130.618,-12.536],[131.223,-12.184],[131.735,-12.302],[132.575,-12.114],[132.557,-11.603],[131.825,-11.274],[132.357,-11.129],[133.02,-11.376],[133.551,-11.787],[134.393,-12.042],[134.679,-11.941],[135.298,-12.249],[135.883,-11.962],[136.258,-12.049],[136.492,-11.857],[136.952,-12.352],[136.685,-12.887],[136.305,-13.291],[135.962,-13.325],[136.078,-13.724],[135.784,-14.224],[135.429,-14.715],[135.5,-14.998],[136.295,-15.55],[137.065,-15.871],[137.58,-16.215],[138.303,-16.808],[138.585,-16.807],[139.109,-17.063],[139.261,-17.372],[140.215,-17.711],[140.875,-17.369],[141.071,-16.832],[141.274,-16.389],[141.398,-15.841],[141.702,-15.045],[141.563,-14.561],[141.636,-14.27],[141.52,-13.698],[141.651,-12.945],[141.843,-12.742],[141.687,-12.408],[141.929,-11.877],[142.118,-11.328],[142.144,-11.043],[142.515,-10.668],[142.797,-11.157],[142.867,-11.785],[143.116,-11.906],[143.159,-12.326],[143.522,-12.834],[143.597,-13.4],[143.562,-13.764],[143.922,-14.548],[144.564,-14.171],[144.895,-14.594],[145.375,-14.985],[145.272,-15.428],[145.485,-16.286],[145.637,-16.785],[145.889,-16.907],[146.16,-17.762],[146.064,-18.28],[146.387,-18.958],[147.471,-19.481],[148.178,-19.956],[148.848,-20.391],[148.717,-20.633],[149.289,-21.261],[149.678,-22.343],[150.077,-22.123],[150.483,-22.556],[150.727,-22.402],[150.9,-23.462],[151.609,-24.076],[152.074,-24.458],[152.855,-25.268],[153.136,-26.071],[153.162,-26.641],[153.093,-27.26],[153.569,-28.11],[153.512,-28.995],[153.339,-29.458],[153.069,-30.35],[153.09,-30.924],[152.892,-31.64],[152.45,-32.55],[151.709,-33.041],[151.344,-33.816],[151.011,-34.31],[150.714,-35.173],[150.328,-35.672],[150.075,-36.42],[149.946,-37.109],[149.997,-37.425],[149.424,-37.773],[148.305,-37.809],[147.382,-38.219],[146.922,-38.607],[146.318,-39.036],[145.49,-38.594],[144.877,-38.417],[145.032,-37.896],[144.486,-38.085],[143.61,-38.809],[142.745,-38.538],[142.178,-38.38],[141.607,-38.309],[140.639,-38.019],[139.992,-37.403],[139.807,-36.644],[139.574,-36.138],[139.083,-35.733],[138.121,-35.612],[138.449,-35.127],[138.208,-34.385],[137.719,-35.077],[136.829,-35.261],[137.352,-34.707],[137.504,-34.13],[137.89,-33.64],[137.81,-32.9],[136.997,-33.753],[136.372,-34.095],[135.989,-34.89],[135.208,-34.479],[135.239,-33.948],[134.613,-33.223],[134.086,-32.848],[134.274,-32.617],[132.991,-32.011],[132.288,-31.983],[131.326,-31.496],[129.536,-31.59],[128.241,-31.948],[127.103,-32.282],[126.149,-32.216]]]],"translations":{"ar":"أستراليا","bs":"Australija","cs":"AustrĂĄlie","de":"Australien","es":"Australia","fa_IR":"استرالیا","fr":"Australie","id":"Australia","it":"Australia","ja":"オーストラリア","pl":"Australia","pt_BR":"AustrĂĄlia","pt_PT":"AustrĂĄlia","ru":"Австралия","uk":"Австралія","zh_CN":"澳大利亚","zh_TW":"ćžłć´˛"}},{"N":"Sri Lanka","I":"LK","C":[[[[81.788,7.523],[81.637,6.482],[81.218,6.197],[80.348,5.968],[79.872,6.763],[79.695,8.201],[80.148,9.824],[80.839,9.268],[81.304,8.564],[81.788,7.523]]]],"translations":{"ar":"سريلانكا","bs":"Ĺ ri Lanka","cs":"SrĂ­ Lanka","de":"Sri Lanka","es":"Sri Lanka","fa_IR":"سری‌لانکا","fr":"Sri Lanka","id":"Sri Lanka","it":"Sri Lanka","ja":"スリランカ","pl":"Sri Lanka","pt_BR":"Sri Lanka","pt_PT":"Sri Lanca","ru":"Шри-Ланка","uk":"Шрі-Ланка","zh_CN":"斯里兰卡","zh_TW":"斯里蘭卡"}},{"N":"China","I":"CN","C":[[[[109.475,18.198],[108.655,18.508],[108.626,19.368],[109.119,19.821],[110.212,20.101],[110.787,20.078],[111.01,19.696],[110.571,19.256],[110.339,18.678],[109.475,18.198]]],[[[80.26,42.35],[80.18,42.92],[80.866,43.18],[79.966,44.918],[81.947,45.317],[82.459,45.54],[83.18,47.33],[85.164,47.001],[85.72,47.453],[85.768,48.456],[86.599,48.549],[87.36,49.215],[87.751,49.297],[88.014,48.599],[88.854,48.069],[90.281,47.694],[90.971,46.888],[90.586,45.72],[90.946,45.286],[92.134,45.115],[93.481,44.975],[94.689,44.352],[95.307,44.241],[95.762,43.319],[96.349,42.726],[97.452,42.749],[99.516,42.525],[100.846,42.664],[101.833,42.515],[103.312,41.907],[104.522,41.908],[104.965,41.597],[106.129,42.134],[107.745,42.482],[109.244,42.519],[110.412,42.871],[111.13,43.407],[111.83,43.743],[111.668,44.073],[111.348,44.457],[111.873,45.102],[112.436,45.012],[113.464,44.809],[114.46,45.34],[115.985,45.727],[116.718,46.388],[117.422,46.673],[118.874,46.805],[119.663,46.693],[119.773,47.048],[118.867,47.747],[118.064,48.067],[117.296,47.698],[116.309,47.853],[115.743,47.727],[115.485,48.135],[116.192,49.135],[116.679,49.889],[117.879,49.511],[119.288,50.143],[119.279,50.583],[120.182,51.644],[120.738,51.964],[120.726,52.516],[120.177,52.754],[121.003,53.251],[122.246,53.432],[123.571,53.459],[125.068,53.161],[125.946,52.793],[126.564,51.784],[126.939,51.354],[127.287,50.74],[127.657,49.76],[129.398,49.441],[130.582,48.73],[130.987,47.79],[132.507,47.789],[133.374,48.183],[135.026,48.478],[134.501,47.578],[134.112,47.212],[133.77,46.117],[133.097,45.144],[131.883,45.321],[131.025,44.968],[131.289,44.112],[131.145,42.93],[130.634,42.903],[130.64,42.395],[129.994,42.985],[129.597,42.425],[128.052,41.994],[128.208,41.467],[127.344,41.503],[126.869,41.817],[126.182,41.107],[125.08,40.57],[124.266,39.928],[122.868,39.638],[122.131,39.17],[121.055,38.897],[121.586,39.361],[121.377,39.75],[122.169,40.422],[121.64,40.946],[120.769,40.593],[119.64,39.898],[119.023,39.252],[118.043,39.204],[117.533,38.738],[118.06,38.061],[118.878,37.897],[118.912,37.448],[119.703,37.156],[120.823,37.87],[121.711,37.481],[122.358,37.454],[122.52,36.931],[121.104,36.651],[120.637,36.111],[119.665,35.61],[119.151,34.91],[120.228,34.36],[120.62,33.377],[121.229,32.46],[121.908,31.692],[121.892,30.949],[121.264,30.676],[121.504,30.143],[122.092,29.833],[121.938,29.018],[121.684,28.226],[121.126,28.136],[120.395,27.053],[119.585,25.741],[118.657,24.547],[117.282,23.625],[115.891,22.783],[114.764,22.668],[114.153,22.224],[113.807,22.548],[113.241,22.051],[111.844,21.55],[110.785,21.397],[110.444,20.341],[109.89,20.282],[109.628,21.008],[109.864,21.395],[108.523,21.715],[108.05,21.552],[107.043,21.812],[106.567,22.218],[106.725,22.794],[105.811,22.977],[105.329,23.352],[104.477,22.819],[103.505,22.704],[102.707,22.709],[102.17,22.465],[101.652,22.318],[101.803,21.174],[101.27,21.202],[101.18,21.437],[101.15,21.85],[100.417,21.559],[99.983,21.743],[99.241,22.118],[99.532,22.949],[98.899,23.143],[98.66,24.063],[97.605,23.897],[97.725,25.084],[98.672,25.919],[98.712,26.744],[98.683,27.509],[98.246,27.747],[97.912,28.336],[97.327,28.262],[96.249,28.411],[96.587,28.831],[96.118,29.453],[95.405,29.032],[94.566,29.277],[93.413,28.641],[92.503,27.897],[91.697,27.772],[91.259,28.041],[90.731,28.065],[90.016,28.296],[89.476,28.043],[88.814,27.299],[88.73,28.087],[88.12,27.877],[86.955,27.974],[85.823,28.204],[85.012,28.643],[84.235,28.84],[83.899,29.32],[83.337,29.464],[82.328,30.115],[81.526,30.423],[81.111,30.183],[79.721,30.883],[78.739,31.516],[78.458,32.618],[79.176,32.484],[79.209,32.994],[78.811,33.506],[78.912,34.322],[77.837,35.494],[76.193,35.898],[75.897,36.667],[75.158,37.133],[74.98,37.42],[74.83,37.99],[74.865,38.379],[74.258,38.607],[73.929,38.506],[73.675,39.431],[73.96,39.66],[73.822,39.894],[74.777,40.366],[75.468,40.562],[76.526,40.428],[76.904,41.066],[78.187,41.185],[78.544,41.582],[80.119,42.124],[80.26,42.35]]]],"translations":{"ar":"الصين","bs":"Kina","cs":"Čína","de":"China","es":"China","fa_IR":"چین","fr":"Chine","id":"Tiongkok","it":"Cina","ja":"中国","pl":"Chiny","pt_BR":"China","pt_PT":"China","ru":"Китай","uk":"Китай","zh_CN":"中国","zh_TW":"中國"}},{"N":"Taiwan","I":"TW","C":[[[[121.778,24.394],[121.176,22.791],[120.747,21.971],[120.22,22.815],[120.106,23.556],[120.695,24.538],[121.495,25.295],[121.951,24.998],[121.778,24.394]]]],"translations":{"ar":"تايوان","bs":"Tajvan","cs":"Tchaj-wan","de":"Taiwan","es":"TaiwĂĄn","fa_IR":"تایوان","fr":"TaĂŻwan","id":"Taiwan","it":"Taiwan","ja":"台湾","pl":"Tajwan","pt_BR":"Taiwan","pt_PT":"Taiwan","ru":"Тайвань","uk":"Тайвань","zh_CN":"台湾","zh_TW":"台灣"}},{"N":"Italy","I":"IT","C":[[[[10.443,46.894],[11.049,46.751],[11.165,46.942],[12.153,47.115],[12.376,46.768],[13.806,46.509],[13.698,46.017],[13.938,45.591],[13.142,45.737],[12.329,45.382],[12.384,44.885],[12.261,44.6],[12.589,44.091],[13.527,43.588],[14.03,42.761],[15.143,41.955],[15.926,41.961],[16.17,41.74],[15.889,41.541],[16.785,41.18],[17.519,40.877],[18.377,40.356],[18.48,40.169],[18.293,39.811],[17.738,40.278],[16.87,40.442],[16.449,39.795],[17.171,39.425],[17.053,38.903],[16.635,38.844],[16.101,37.986],[15.684,37.909],[15.688,38.215],[15.892,38.751],[16.109,38.965],[15.719,39.544],[15.414,40.048],[14.998,40.173],[14.703,40.605],[14.061,40.786],[13.628,41.188],[12.888,41.253],[12.107,41.705],[11.192,42.355],[10.512,42.931],[10.2,43.92],[9.702,44.036],[8.889,44.366],[8.429,44.231],[7.851,43.767],[7.435,43.694],[7.55,44.128],[7.008,44.255],[6.75,45.029],[7.097,45.333],[6.802,45.709],[6.844,45.991],[7.274,45.777],[7.756,45.824],[8.317,46.164],[8.49,46.005],[8.966,46.037],[9.183,46.44],[9.923,46.315],[10.363,46.484],[10.443,46.894]]],[[[14.761,38.144],[15.52,38.231],[15.16,37.444],[15.31,37.134],[15.1,36.62],[14.335,36.997],[13.827,37.105],[12.431,37.613],[12.571,38.126],[13.741,38.035],[14.761,38.144]]],[[[8.71,40.9],[9.21,41.21],[9.81,40.5],[9.67,39.177],[9.215,39.24],[8.807,38.907],[8.428,39.172],[8.388,40.378],[8.16,40.95],[8.71,40.9]]]],"translations":{"ar":"إيطاليا","bs":"Italija","cs":"ItĂĄlie","de":"Italien","es":"Italia","fa_IR":"ایتالیا","fr":"Italie","id":"Italia","it":"Italia","ja":"イタリア","pl":"Włochy","pt_BR":"ItĂĄlia","pt_PT":"ItĂĄlia","ru":"Италия","uk":"Італія","zh_CN":"意大利","zh_TW":"瞊大刊"}},{"N":"Denmark","I":"DK","C":[[[[9.922,54.983],[9.282,54.831],[8.526,54.963],[8.12,55.518],[8.09,56.54],[8.257,56.81],[8.543,57.11],[9.424,57.172],[9.776,57.448],[10.58,57.73],[10.546,57.216],[10.25,56.89],[10.37,56.61],[10.912,56.459],[10.668,56.081],[10.37,56.19],[9.65,55.47],[9.922,54.983]]],[[[12.371,56.111],[12.69,55.61],[12.09,54.8],[11.044,55.365],[10.904,55.78],[12.371,56.111]]]],"translations":{"ar":"الدانمرك","bs":"Danska","cs":"DĂĄnsko","de":"Dänemark","es":"Dinamarca","fa_IR":"دانمارک","fr":"Danemark","id":"Denmark","it":"Danimarca","ja":"デンマーク","pl":"Dania","pt_BR":"Dinamarca","pt_PT":"Dinamarca","ru":"Дания","uk":"Данія","zh_CN":"业麌","zh_TW":"业麼"}},{"N":"United Kingdom","I":"GB","C":[[[[-6.198,53.868],[-6.954,54.074],[-7.572,54.06],[-7.366,54.596],[-7.572,55.132],[-6.734,55.173],[-5.662,54.555],[-6.198,53.868]]],[[[-3.094,53.405],[-3.092,53.404],[-2.945,53.985],[-3.615,54.601],[-3.63,54.615],[-4.844,54.791],[-5.083,55.062],[-4.719,55.508],[-5.048,55.784],[-5.586,55.311],[-5.645,56.275],[-6.15,56.785],[-5.787,57.819],[-5.01,58.63],[-4.211,58.551],[-3.005,58.635],[-4.074,57.553],[-3.055,57.69],[-1.959,57.685],[-2.22,56.87],[-3.119,55.974],[-2.085,55.91],[-2.006,55.805],[-1.115,54.625],[-0.43,54.464],[0.185,53.325],[0.47,52.93],[1.682,52.74],[1.56,52.1],[1.051,51.807],[1.45,51.289],[0.55,50.766],[-0.788,50.775],[-2.49,50.5],[-2.956,50.697],[-3.617,50.228],[-4.543,50.342],[-5.245,49.96],[-5.777,50.16],[-4.31,51.21],[-3.415,51.426],[-3.423,51.427],[-4.984,51.593],[-5.267,51.991],[-4.222,52.301],[-4.77,52.84],[-4.58,53.495],[-3.094,53.405]]]],"translations":{"ar":"المملكة المتحدة","bs":"Ujedinjeno Kraljevstvo","cs":"SpojenĂŠ krĂĄlovstvĂ­","de":"Vereinigtes KĂśnigreich","es":"Reino Unido","fa_IR":"بریتانیا","fr":"Royaume-Uni","id":"Inggris Raya","it":"Regno Unito","ja":"イギリス","pl":"Wielka Brytania","pt_BR":"Reino Unido","pt_PT":"Reino Unido","ru":"Великобритания","uk":"Велика Британія","zh_CN":"英国","zh_TW":"英國"}},{"N":"Iceland","I":"IS","C":[[[[-14.509,66.456],[-14.74,65.809],[-13.61,65.127],[-14.91,64.364],[-17.794,63.679],[-18.656,63.496],[-19.973,63.644],[-22.763,63.96],[-21.778,64.402],[-23.955,64.891],[-22.184,65.085],[-22.227,65.379],[-24.326,65.611],[-23.651,66.263],[-22.135,66.41],[-20.576,65.732],[-19.057,66.277],[-17.799,65.994],[-16.168,66.527],[-14.509,66.456]]]],"translations":{"ar":"آيسلندا","bs":"Island","cs":"Island","de":"Island","es":"Islandia","fa_IR":"ایسلند","fr":"Islande","id":"Islandia","it":"Islanda","ja":"アイスランド","pl":"Islandia","pt_BR":"Islândia","pt_PT":"Islândia","ru":"Исландия","uk":"Ісландія","zh_CN":"冰岛","zh_TW":"冰島"}},{"N":"Azerbaijan","I":"AZ","C":[[[[46.405,41.861],[46.686,41.827],[47.373,41.22],[47.816,41.151],[47.987,41.406],[48.584,41.809],[49.11,41.282],[49.619,40.573],[50.085,40.526],[50.393,40.257],[49.569,40.176],[49.395,39.399],[49.223,39.049],[48.857,38.815],[48.883,38.32],[48.634,38.27],[48.011,38.794],[48.356,39.289],[48.06,39.582],[47.685,39.508],[46.506,38.771],[46.483,39.464],[46.035,39.628],[45.61,39.9],[45.892,40.218],[45.359,40.562],[45.56,40.812],[45.179,40.985],[44.972,41.248],[45.217,41.411],[45.963,41.124],[46.502,41.064],[46.638,41.182],[46.145,41.723],[46.405,41.861]]],[[[46.144,38.741],[45.458,38.874],[44.953,39.336],[44.794,39.713],[45.002,39.74],[45.298,39.472],[45.74,39.474],[45.735,39.32],[46.144,38.741]]]],"translations":{"ar":"أذربيجان","bs":"AzerbejdĹžan","cs":"ÁzerbĂĄjdŞån","de":"Aserbaidschan","es":"AzerbaiyĂĄn","fa_IR":"جمهوری آذربایجان","fr":"AzerbaĂŻdjan","id":"Azerbaijan","it":"Azerbaigian","ja":"アゼルバイジャン","pl":"AzerbejdĹźan","pt_BR":"AzerbaijĂŁo","pt_PT":"AzerbaijĂŁo","ru":"Азербайджан","uk":"Азербайджан","zh_CN":"阿塞拜疆","zh_TW":"亞塞拜然"}},{"N":"Georgia","I":"GE","C":[[[[39.955,43.435],[40.077,43.553],[40.922,43.382],[42.394,43.22],[43.756,42.741],[43.931,42.555],[44.538,42.712],[45.47,42.503],[45.776,42.092],[46.405,41.861],[46.145,41.723],[46.638,41.182],[46.502,41.064],[45.963,41.124],[45.217,41.411],[44.972,41.248],[43.583,41.092],[42.62,41.583],[41.554,41.536],[41.703,41.963],[41.453,42.645],[40.875,43.014],[40.321,43.129],[39.955,43.435]]]],"translations":{"ar":"جورجيا","bs":"Gruzija","cs":"Gruzie","de":"Georgien","es":"Georgia","fa_IR":"گرجستان","fr":"GĂŠorgie","id":"Georgia","it":"Georgia","ja":"ジョージア","pl":"Gruzja","pt_BR":"GeĂłrgia","pt_PT":"GeĂłrgia","ru":"Грузия","uk":"Грузія","zh_CN":"格鲁吉亚","zh_TW":"喬治亞"}},{"N":"Philippines","I":"PH","C":[[[[120.834,12.704],[120.323,13.466],[121.18,13.43],[121.527,13.07],[121.262,12.206],[120.834,12.704]]],[[[122.586,9.981],[122.837,10.261],[122.947,10.882],[123.499,10.941],[123.338,10.267],[124.078,11.233],[123.982,10.279],[123.623,9.95],[123.31,9.318],[122.996,9.022],[122.38,9.713],[122.586,9.981]]],[[[126.377,8.415],[126.479,7.75],[126.537,7.189],[126.197,6.274],[125.831,7.294],[125.364,6.786],[125.683,6.05],[125.397,5.581],[124.22,6.161],[123.939,6.885],[124.244,7.361],[123.61,7.834],[123.296,7.419],[122.826,7.457],[122.085,6.899],[121.92,7.192],[122.312,8.035],[122.942,8.316],[123.488,8.693],[123.841,8.24],[124.601,8.514],[124.765,8.96],[125.471,8.987],[125.412,9.76],[126.223,9.286],[126.307,8.782],[126.377,8.415]]],[[[118.505,9.316],[117.174,8.367],[117.664,9.067],[118.387,9.684],[118.987,10.376],[119.511,11.37],[119.69,10.554],[119.029,10.004],[118.505,9.316]]],[[[122.337,18.225],[122.174,17.81],[122.516,17.094],[122.252,16.262],[121.663,15.931],[121.505,15.125],[121.729,14.328],[122.259,14.218],[122.701,14.337],[123.95,13.782],[123.855,13.238],[124.181,12.998],[124.077,12.537],[123.298,13.028],[122.929,13.553],[122.671,13.186],[122.035,13.784],[121.126,13.637],[120.629,13.858],[120.679,14.271],[120.992,14.525],[120.693,14.757],[120.564,14.396],[120.07,14.971],[119.921,15.406],[119.884,16.364],[120.286,16.035],[120.39,17.599],[120.716,18.505],[121.321,18.504],[121.938,18.219],[122.246,18.479],[122.337,18.225]]],[[[122.038,11.416],[121.884,11.892],[122.484,11.582],[123.12,11.584],[123.101,11.166],[122.638,10.741],[122.003,10.441],[121.967,10.906],[122.038,11.416]]],[[[125.503,12.163],[125.783,11.046],[125.012,11.311],[125.033,10.976],[125.277,10.359],[124.802,10.135],[124.76,10.838],[124.459,10.89],[124.303,11.495],[124.891,11.416],[124.878,11.794],[124.267,12.558],[125.227,12.536],[125.503,12.163]]]],"translations":{"ar":"الفلبين","bs":"Filipini","cs":"FilipĂ­ny","de":"Philippinen","es":"Filipinas","fa_IR":"فیلیپین","fr":"Philippines","id":"Filipina","it":"Filippine","ja":"フィリピン","pl":"Filipiny","pt_BR":"Filipinas","pt_PT":"Filipinas","ru":"Филиппины","uk":"Філіппіни","zh_CN":"菲律宾","zh_TW":"菲律賓"}},{"N":"Malaysia","I":"MY","C":[[[[100.086,6.464],[100.26,6.643],[101.076,6.205],[101.154,5.691],[101.814,5.811],[102.141,6.222],[102.371,6.128],[102.962,5.524],[103.381,4.855],[103.439,4.182],[103.332,3.727],[103.429,3.383],[103.502,2.791],[103.855,2.515],[104.248,1.631],[104.229,1.293],[103.52,1.226],[102.574,1.967],[101.391,2.761],[101.274,3.27],[100.695,3.939],[100.557,4.767],[100.197,5.312],[100.306,6.041],[100.086,6.464]]],[[[117.882,4.138],[117.015,4.306],[115.866,4.307],[115.519,3.169],[115.134,2.821],[114.621,1.431],[113.806,1.218],[112.86,1.498],[112.38,1.41],[111.798,0.904],[111.159,0.976],[110.514,0.773],[109.83,1.338],[109.663,2.006],[110.396,1.664],[111.169,1.851],[111.37,2.697],[111.797,2.886],[112.996,3.102],[113.713,3.894],[114.204,4.526],[114.66,4.008],[114.87,4.348],[115.347,4.317],[115.406,4.955],[115.451,5.448],[116.221,6.143],[116.725,6.925],[117.13,6.928],[117.643,6.422],[117.689,5.987],[118.348,5.709],[119.182,5.408],[119.111,5.016],[118.44,4.967],[118.618,4.478],[117.882,4.138]]]],"translations":{"ar":"ماليزيا","bs":"Malezija","cs":"Malajsie","de":"Malaysia","es":"Malasia","fa_IR":"مالزی","fr":"Malaisie","id":"Malaysia","it":"Malaysia","ja":"マレーシア","pl":"Malezja","pt_BR":"MalĂĄsia","pt_PT":"MalĂĄsia","ru":"Малайзия","uk":"Малайзія","zh_CN":"马来西亚","zh_TW":"馬來西亞"}},{"N":"Brunei Darussalam","I":"BN","C":[[[[115.451,5.448],[115.406,4.955],[115.347,4.317],[114.87,4.348],[114.66,4.008],[114.204,4.526],[114.6,4.9],[115.451,5.448]]]],"translations":{"ar":"بروناي","bs":"Brunej","cs":"Brunej","de":"Brunei Darussalam","es":"BrunĂŠi","fa_IR":"برونئی","fr":"Brunei","id":"Brunei","it":"Brunei","ja":"ブルネイ","pl":"Brunei","pt_BR":"Brunei","pt_PT":"Brunei","ru":"Бруней","uk":"Бруней","zh_CN":"文莱","zh_TW":"汶萊"}},{"N":"Slovenia","I":"SI","C":[[[[13.806,46.509],[14.632,46.432],[15.137,46.659],[16.012,46.684],[16.202,46.852],[16.371,46.841],[16.565,46.504],[15.769,46.238],[15.672,45.834],[15.324,45.732],[15.328,45.452],[14.935,45.472],[14.595,45.635],[14.412,45.466],[13.715,45.5],[13.938,45.591],[13.698,46.017],[13.806,46.509]]]],"translations":{"ar":"سلوفينيا","bs":"Slovenija","cs":"Slovinsko","de":"Slowenien","es":"Eslovenia","fa_IR":"اسلوونی","fr":"SlovĂŠnie","id":"Slovenia","it":"Slovenia","ja":"スロベニア","pl":"Słowenia","pt_BR":"EslovĂŞnia","pt_PT":"EslovĂŠnia","ru":"Словения","uk":"Словенія","zh_CN":"斯洛文尼亚","zh_TW":"斯洛維尼亞"}},{"N":"Finland","I":"FI","C":[[[[28.592,69.065],[28.446,68.365],[29.977,67.698],[29.055,66.944],[30.218,65.806],[29.544,64.949],[30.445,64.204],[30.036,63.553],[31.516,62.868],[31.14,62.358],[30.211,61.78],[28.07,60.504],[28.07,60.504],[28.07,60.504],[26.255,60.424],[24.497,60.057],[22.87,59.846],[22.291,60.392],[21.322,60.72],[21.545,61.705],[21.059,62.607],[21.536,63.19],[22.443,63.818],[24.731,64.902],[25.398,65.111],[25.294,65.534],[23.903,66.007],[23.566,66.396],[23.539,67.936],[21.979,68.617],[20.646,69.106],[21.245,69.37],[22.356,68.842],[23.662,68.891],[24.736,68.65],[25.689,69.092],[26.18,69.825],[27.732,70.164],[29.016,69.766],[28.592,69.065]]]],"translations":{"ar":"فنلندا","bs":"Finska","cs":"Finsko","de":"Finnland","es":"Finlandia","fa_IR":"فنلاند","fr":"Finlande","id":"Finlandia","it":"Finlandia","ja":"フィンランド","pl":"Finlandia","pt_BR":"Finlândia","pt_PT":"Finlândia","ru":"Финляндия","uk":"Фінляндія","zh_CN":"芬兰","zh_TW":"芬蘭"}},{"N":"Slovakia","I":"SK","C":[[[[22.558,49.086],[22.281,48.825],[22.086,48.422],[21.872,48.32],[20.801,48.624],[20.474,48.563],[20.239,48.328],[19.769,48.203],[19.661,48.267],[19.174,48.111],[18.777,48.082],[18.697,47.881],[17.857,47.758],[17.488,47.867],[16.98,48.123],[16.88,48.47],[16.96,48.597],[17.102,48.817],[17.545,48.8],[17.886,48.903],[17.914,48.996],[18.105,49.044],[18.17,49.272],[18.4,49.315],[18.555,49.495],[18.853,49.496],[18.91,49.436],[19.321,49.572],[19.825,49.217],[20.416,49.431],[20.888,49.329],[21.608,49.47],[22.558,49.086]]]],"translations":{"ar":"سلوفاكيا","bs":"Slovačka","cs":"Slovensko","de":"Slowakei","es":"Eslovaquia","fa_IR":"اسلواکی","fr":"Slovaquie","id":"Slovakia","it":"Slovacchia","ja":"スロバキア","pl":"Słowacja","pt_BR":"EslovĂĄquia","pt_PT":"EslovĂĄquia","ru":"Словакия","uk":"Словаччина","zh_CN":"斯洛伐克","zh_TW":"斯洛伐克"}},{"N":"Czech Republic","I":"CZ","C":[[[[15.017,51.107],[15.491,50.785],[16.239,50.698],[16.176,50.423],[16.719,50.216],[16.869,50.474],[17.555,50.362],[17.649,50.049],[18.393,49.989],[18.853,49.496],[18.555,49.495],[18.4,49.315],[18.17,49.272],[18.105,49.044],[17.914,48.996],[17.886,48.903],[17.545,48.8],[17.102,48.817],[16.96,48.597],[16.499,48.786],[16.03,48.734],[15.253,49.039],[14.901,48.964],[14.339,48.555],[13.596,48.877],[13.031,49.307],[12.521,49.547],[12.415,49.969],[12.24,50.266],[12.967,50.484],[13.338,50.733],[14.056,50.927],[14.307,51.117],[14.571,51.002],[15.017,51.107]]]],"translations":{"ar":"التشيك","bs":"ČeĹĄka","cs":"Česko","de":"Tschechien","es":"Chequia","fa_IR":"چک","fr":"TchĂŠquie","id":"Ceko","it":"Cechia","ja":"チェコ","pl":"Czechy","pt_BR":"TchĂŠquia","pt_PT":"ChĂŠquia","ru":"Чехия","uk":"Чехія","zh_CN":"捷克","zh_TW":"捷克"}},{"N":"Eritrea","I":"ER","C":[[[[36.43,14.422],[36.323,14.822],[36.754,16.292],[36.853,16.957],[37.167,17.263],[37.904,17.428],[38.41,17.998],[38.991,16.841],[39.266,15.923],[39.814,15.436],[41.179,14.491],[41.735,13.921],[42.277,13.344],[42.59,13],[43.081,12.7],[42.78,12.455],[42.352,12.542],[42.01,12.866],[41.599,13.452],[41.155,13.773],[40.897,14.119],[40.026,14.52],[39.341,14.532],[39.099,14.741],[38.513,14.505],[37.906,14.959],[37.594,14.213],[36.43,14.422]]]],"translations":{"ar":"إريتريا","bs":"Eritreja","cs":"Eritrea","de":"Eritrea","es":"Eritrea","fa_IR":"اریتره","fr":"ÉrythrĂŠe","id":"Eritrea","it":"Eritrea","ja":"エリトリア","pl":"Erytrea","pt_BR":"Eritreia","pt_PT":"Eritreia","ru":"Эритрея","uk":"Еритрея","zh_CN":"厄立特里亚","zh_TW":"厄利垂亞"}},{"N":"Japan","I":"JP","C":[[[[141.885,39.181],[140.959,38.174],[140.976,37.142],[140.6,36.344],[140.774,35.843],[140.253,35.138],[138.976,34.668],[137.218,34.606],[135.793,33.465],[135.121,33.849],[135.079,34.597],[133.34,34.376],[132.157,33.905],[130.986,33.886],[132,33.15],[131.333,31.45],[130.686,31.03],[130.202,31.418],[130.448,32.319],[129.815,32.61],[129.408,33.296],[130.354,33.604],[130.878,34.233],[131.884,34.75],[132.618,35.433],[134.608,35.732],[135.678,35.527],[136.724,37.305],[137.391,36.827],[138.858,37.827],[139.426,38.216],[140.055,39.439],[139.883,40.563],[140.306,41.195],[141.369,41.379],[141.914,39.992],[141.885,39.181]]],[[[144.613,43.961],[145.321,44.385],[145.543,43.262],[144.06,42.988],[143.184,41.995],[141.611,42.679],[141.067,41.585],[139.955,41.57],[139.818,42.564],[140.312,43.333],[141.381,43.389],[141.672,44.772],[141.968,45.551],[143.143,44.51],[143.91,44.174],[144.613,43.961]]],[[[132.371,33.464],[132.924,34.06],[133.493,33.945],[133.904,34.365],[134.638,34.149],[134.766,33.806],[134.203,33.201],[133.793,33.522],[133.28,33.29],[133.015,32.705],[132.363,32.989],[132.371,33.464]]]],"translations":{"ar":"اليابان","bs":"Japan","cs":"Japonsko","de":"Japan","es":"JapĂłn","fa_IR":"ژاپن","fr":"Japon","id":"Jepang","it":"Giappone","ja":"日本","pl":"Japonia","pt_BR":"JapĂŁo","pt_PT":"JapĂŁo","ru":"Япония","uk":"Японія","zh_CN":"日本","zh_TW":"日本"}},{"N":"Paraguay","I":"PY","C":[[[[-58.166,-20.177],[-57.871,-20.733],[-57.937,-22.09],[-56.882,-22.282],[-56.473,-22.086],[-55.798,-22.357],[-55.611,-22.656],[-55.518,-23.572],[-55.401,-23.957],[-55.028,-24.001],[-54.653,-23.84],[-54.293,-24.021],[-54.293,-24.571],[-54.429,-25.162],[-54.625,-25.739],[-54.789,-26.622],[-55.696,-27.388],[-56.487,-27.548],[-57.61,-27.396],[-58.618,-27.124],[-57.634,-25.604],[-57.777,-25.162],[-58.807,-24.771],[-60.029,-24.033],[-60.847,-23.881],[-62.685,-22.249],[-62.291,-21.052],[-62.266,-20.514],[-61.786,-19.634],[-60.044,-19.343],[-59.115,-19.357],[-58.183,-19.868],[-58.166,-20.177]]]],"translations":{"ar":"باراغواي","bs":"Paragvaj","cs":"Paraguay","de":"Paraguay","es":"Paraguay","fa_IR":"پاراگوئه","fr":"Paraguay","id":"Paraguay","it":"Paraguay","ja":"パラグアイ","pl":"Paragwaj","pt_BR":"Paraguai","pt_PT":"Paraguai","ru":"Парагвай","uk":"Парагвай","zh_CN":"巴拉圭","zh_TW":"巴拉圭"}},{"N":"Yemen","I":"YE","C":[[[[52,19],[52.782,17.35],[53.109,16.651],[52.385,16.382],[52.192,15.938],[52.168,15.597],[51.173,15.175],[49.575,14.709],[48.679,14.003],[48.239,13.948],[47.939,14.007],[47.354,13.592],[46.717,13.4],[45.878,13.348],[45.625,13.291],[45.406,13.027],[45.144,12.954],[44.99,12.7],[44.495,12.722],[44.175,12.586],[43.483,12.637],[43.223,13.221],[43.251,13.768],[43.088,14.063],[42.892,14.802],[42.605,15.213],[42.805,15.262],[42.702,15.719],[42.824,15.912],[42.779,16.348],[43.218,16.667],[43.116,17.088],[43.381,17.58],[43.792,17.32],[44.063,17.41],[45.217,17.433],[45.4,17.333],[46.367,17.233],[46.75,17.283],[47,16.95],[47.467,17.117],[48.183,18.167],[49.117,18.617],[52,19]]]],"translations":{"ar":"اليمن","bs":"Jemen","cs":"Jemen","de":"Jemen","es":"Yemen","fa_IR":"یمن","fr":"YĂŠmen","id":"Yaman","it":"Yemen","ja":"イエメン","pl":"Jemen","pt_BR":"IĂŞmen","pt_PT":"IĂŠmen","ru":"Йемен","uk":"Ємен","zh_CN":"也门","zh_TW":"葉門"}},{"N":"Saudi Arabia","I":"SA","C":[[[[34.956,29.357],[36.069,29.197],[36.501,29.505],[36.741,29.865],[37.504,30.004],[37.668,30.339],[37.999,30.508],[37.002,31.508],[39.005,32.01],[39.195,32.161],[40.4,31.89],[41.89,31.19],[44.709,29.179],[46.569,29.099],[47.46,29.003],[47.709,28.526],[48.416,28.552],[48.808,27.69],[49.3,27.461],[49.471,27.11],[50.152,26.69],[50.213,26.277],[50.113,25.944],[50.24,25.608],[50.527,25.328],[50.661,25],[50.81,24.755],[51.112,24.556],[51.39,24.627],[51.58,24.245],[51.618,24.014],[52.001,23.001],[55.007,22.497],[55.208,22.708],[55.667,22],[55,20],[52,19],[49.117,18.617],[48.183,18.167],[47.467,17.117],[47,16.95],[46.75,17.283],[46.367,17.233],[45.4,17.333],[45.217,17.433],[44.063,17.41],[43.792,17.32],[43.381,17.58],[43.116,17.088],[43.218,16.667],[42.779,16.348],[42.65,16.775],[42.348,17.076],[42.271,17.475],[41.754,17.833],[41.221,18.672],[40.939,19.486],[40.248,20.175],[39.802,20.339],[39.139,21.292],[39.024,21.987],[39.066,22.58],[38.493,23.688],[38.024,24.079],[37.484,24.285],[37.155,24.858],[37.209,25.085],[36.932,25.603],[36.64,25.826],[36.249,26.57],[35.64,27.377],[35.13,28.063],[34.632,28.059],[34.788,28.607],[34.832,28.957],[34.956,29.357]]]],"translations":{"ar":"المملكة العربية السعودية","bs":"Saudijska Arabija","cs":"SaĂşdskĂĄ ArĂĄbie","de":"Saudi-Arabien","es":"Arabia SaudĂ­","fa_IR":"عربستان سعودی","fr":"Arabie saoudite","id":"Arab Saudi","it":"Arabia Saudita","ja":"サウジアラビア","pl":"Arabia Saudyjska","pt_BR":"ArĂĄbia Saudita","pt_PT":"ArĂĄbia Saudita","ru":"Саудовская Аравия","uk":"Саудівська Аравія","zh_CN":"沙特阿拉伯","zh_TW":"沙烏地阿拉伯"}},{"N":"Northern Cyprus","I":"CYP","C":[[[[32.732,35.14],[32.802,35.146],[32.947,35.387],[33.667,35.373],[34.576,35.672],[33.901,35.246],[33.974,35.059],[33.866,35.094],[33.675,35.018],[33.526,35.039],[33.476,35],[33.456,35.101],[33.384,35.163],[33.191,35.173],[32.92,35.088],[32.732,35.14]]]],"translations":{"ar":"Northern Cyprus","bs":"Northern Cyprus","cs":"Northern Cyprus","de":"Northern Cyprus","es":"Northern Cyprus","fa_IR":"Northern Cyprus","fr":"Northern Cyprus","id":"Northern Cyprus","it":"Northern Cyprus","ja":"Northern Cyprus","pl":"Northern Cyprus","pt_BR":"Northern Cyprus","pt_PT":"Northern Cyprus","ru":"Northern Cyprus","uk":"Northern Cyprus","zh_CN":"Northern Cyprus","zh_TW":"Northern Cyprus"}},{"N":"Cyprus","I":"CY","C":[[[[32.732,35.14],[32.92,35.088],[33.191,35.173],[33.384,35.163],[33.456,35.101],[33.476,35],[33.526,35.039],[33.675,35.018],[33.866,35.094],[33.974,35.059],[34.005,34.978],[32.98,34.572],[32.49,34.702],[32.257,35.103],[32.732,35.14]]]],"translations":{"ar":"قبرص","bs":"Kipar","cs":"Kypr","de":"Zypern","es":"Chipre","fa_IR":"قبرس","fr":"Chypre","id":"Siprus","it":"Cipro","ja":"キプロス","pl":"Cypr","pt_BR":"Chipre","pt_PT":"Chipre","ru":"Кипр","uk":"Кіпр","zh_CN":"塞浦路斯","zh_TW":"賽普勒斯"}},{"N":"Morocco","I":"MA","C":[[[[-2.17,35.168],[-1.793,34.528],[-1.733,33.92],[-1.388,32.864],[-1.125,32.652],[-1.308,32.263],[-2.617,32.094],[-3.069,31.724],[-3.647,31.637],[-3.69,30.897],[-4.86,30.501],[-5.242,30],[-6.061,29.732],[-7.059,29.579],[-8.674,28.841],[-8.666,27.656],[-8.818,27.656],[-8.795,27.121],[-9.413,27.088],[-9.735,26.861],[-10.189,26.861],[-10.551,26.991],[-11.393,26.883],[-11.718,26.104],[-12.031,26.031],[-12.501,24.77],[-13.891,23.691],[-14.221,22.31],[-14.631,21.861],[-14.751,21.501],[-17.003,21.421],[-17.02,21.422],[-16.973,21.886],[-16.589,22.158],[-16.262,22.679],[-16.326,23.018],[-15.983,23.723],[-15.426,24.359],[-15.089,24.52],[-14.825,25.104],[-14.801,25.636],[-14.44,26.254],[-13.774,26.619],[-13.14,27.64],[-13.122,27.654],[-12.619,28.038],[-11.689,28.149],[-10.901,28.832],[-10.4,29.099],[-9.565,29.934],[-9.815,31.178],[-9.435,32.038],[-9.301,32.565],[-8.657,33.24],[-7.654,33.697],[-6.913,34.11],[-6.244,35.146],[-5.93,35.76],[-5.194,35.755],[-4.591,35.331],[-3.64,35.4],[-2.604,35.179],[-2.17,35.168]]]],"translations":{"ar":"المغرب","bs":"Maroko","cs":"Maroko","de":"Marokko","es":"Marruecos","fa_IR":"مراکش","fr":"Maroc","id":"Maroko","it":"Marocco","ja":"モロッコ","pl":"Maroko","pt_BR":"Marrocos","pt_PT":"Marrocos","ru":"Марокко","uk":"Марокко","zh_CN":"摩洛哥","zh_TW":"摩洛哥"}},{"N":"Egypt","I":"EG","C":[[[[36.866,22],[32.9,22],[29.02,22],[25,22],[25,25.682],[25,29.239],[24.7,30.044],[24.958,30.662],[24.803,31.089],[25.165,31.569],[26.495,31.586],[27.458,31.321],[28.45,31.026],[28.914,30.87],[29.683,31.187],[30.095,31.473],[30.977,31.556],[31.688,31.43],[31.96,30.934],[32.192,31.26],[32.994,31.024],[33.773,30.967],[34.265,31.219],[34.265,31.219],[34.823,29.761],[34.923,29.501],[34.642,29.099],[34.427,28.344],[34.155,27.823],[33.921,27.649],[33.588,27.971],[33.137,28.418],[32.423,29.851],[32.32,29.76],[32.735,28.705],[33.349,27.7],[34.105,26.142],[34.474,25.599],[34.795,25.034],[35.692,23.927],[35.494,23.752],[35.526,23.102],[36.691,22.205],[36.866,22]]]],"translations":{"ar":"مصر","bs":"Egipat","cs":"Egypt","de":"Ägypten","es":"Egipto","fa_IR":"مصر","fr":"Égypte","id":"Mesir","it":"Egitto","ja":"エジプト","pl":"Egipt","pt_BR":"Egito","pt_PT":"Egito","ru":"Египет","uk":"Єгипет","zh_CN":"埃及","zh_TW":"埃及"}},{"N":"Libya","I":"LY","C":[[[[25,22],[25,20.003],[23.85,20],[23.838,19.58],[19.849,21.495],[15.861,23.41],[14.851,22.863],[14.144,22.491],[13.581,23.041],[12,23.472],[11.561,24.098],[10.771,24.563],[10.304,24.379],[9.948,24.937],[9.911,25.365],[9.319,26.094],[9.716,26.512],[9.629,27.141],[9.756,27.688],[9.684,28.144],[9.86,28.96],[9.806,29.425],[9.482,30.308],[9.97,30.539],[10.057,30.962],[9.95,31.376],[10.637,31.761],[10.945,32.082],[11.432,32.369],[11.489,33.137],[12.663,32.793],[13.083,32.879],[13.919,32.712],[15.246,32.265],[15.714,31.376],[16.612,31.182],[18.021,30.764],[19.086,30.266],[19.574,30.526],[20.053,30.986],[19.82,31.752],[20.134,32.238],[20.855,32.707],[21.543,32.843],[22.896,32.639],[23.237,32.191],[23.609,32.187],[23.927,32.017],[24.921,31.899],[25.165,31.569],[24.803,31.089],[24.958,30.662],[24.7,30.044],[25,29.239],[25,25.682],[25,22]]]],"translations":{"ar":"ليبيا","bs":"Libija","cs":"Libye","de":"Libyen","es":"Libia","fa_IR":"لیبی","fr":"Libye","id":"Libya","it":"Libia","ja":"リビア","pl":"Libia","pt_BR":"LĂ­bia","pt_PT":"LĂ­bia","ru":"Ливия","uk":"Лівія","zh_CN":"利比亚","zh_TW":"利比亞"}},{"N":"Ethiopia","I":"ET","C":[[[[47.789,8.003],[44.964,5.002],[43.661,4.958],[42.77,4.253],[42.129,4.234],[41.855,3.919],[41.172,3.919],[40.768,4.257],[39.855,3.839],[39.559,3.422],[38.893,3.501],[38.671,3.616],[38.437,3.589],[38.121,3.599],[36.855,4.448],[36.159,4.448],[35.817,4.777],[35.817,5.338],[35.298,5.506],[34.707,6.594],[34.25,6.826],[34.075,7.226],[33.568,7.713],[32.954,7.785],[33.295,8.355],[33.826,8.379],[33.975,8.685],[33.962,9.584],[34.257,10.63],[34.731,10.91],[34.832,11.319],[35.26,12.083],[35.864,12.578],[36.27,13.563],[36.43,14.422],[37.594,14.213],[37.906,14.959],[38.513,14.505],[39.099,14.741],[39.341,14.532],[40.026,14.52],[40.897,14.119],[41.155,13.773],[41.599,13.452],[42.01,12.866],[42.352,12.542],[42,12.1],[41.662,11.631],[41.74,11.355],[41.756,11.051],[42.314,11.034],[42.555,11.105],[42.777,10.927],[42.559,10.573],[42.928,10.022],[43.297,9.54],[43.679,9.184],[46.948,7.997],[47.789,8.003]]]],"translations":{"ar":"إثيوبيا","bs":"Etiopija","cs":"Etiopie","de":"Äthiopien","es":"EtiopĂ­a","fa_IR":"اتیوپی","fr":"Éthiopie","id":"Etiopia","it":"Etiopia","ja":"エチオピア","pl":"Etiopia","pt_BR":"EtiĂłpia","pt_PT":"EtiĂłpia","ru":"Эфиопия","uk":"Ефіопія","zh_CN":"埃塞俄比亚","zh_TW":"衣索比亞"}},{"N":"Djibouti","I":"DJ","C":[[[[42.352,12.542],[42.78,12.455],[43.081,12.7],[43.318,12.39],[43.286,11.975],[42.716,11.736],[43.145,11.462],[42.777,10.927],[42.555,11.105],[42.314,11.034],[41.756,11.051],[41.74,11.355],[41.662,11.631],[42,12.1],[42.352,12.542]]]],"translations":{"ar":"جيبوتي","bs":"DĹžibuti","cs":"DĹžibutsko","de":"Dschibuti","es":"Yibuti","fa_IR":"جیبوتی","fr":"Djibouti","id":"Jibuti","it":"Gibuti","ja":"ジブチ","pl":"DĹźibuti","pt_BR":"Djibuti","pt_PT":"Jibuti","ru":"Джибути","uk":"Джибуті","zh_CN":"吉布提","zh_TW":"吉布地"}},{"N":"Somaliland","I":"SOM","C":[[[[48.948,11.411],[48.948,11.411],[48.942,11.394],[48.938,10.982],[48.938,9.974],[48.938,9.452],[48.487,8.838],[47.789,8.003],[46.948,7.997],[43.679,9.184],[43.297,9.54],[42.928,10.022],[42.559,10.573],[42.777,10.927],[43.145,11.462],[43.471,11.278],[43.667,10.864],[44.118,10.446],[44.614,10.442],[45.557,10.698],[46.645,10.817],[47.526,11.127],[48.022,11.193],[48.379,11.375],[48.948,11.411],[48.948,11.411]]]],"translations":{"ar":"Somaliland","bs":"Somaliland","cs":"Somaliland","de":"Somaliland","es":"Somaliland","fa_IR":"Somaliland","fr":"Somaliland","id":"Somaliland","it":"Somaliland","ja":"Somaliland","pl":"Somaliland","pt_BR":"Somaliland","pt_PT":"Somaliland","ru":"Somaliland","uk":"Somaliland","zh_CN":"Somaliland","zh_TW":"Somaliland"}},{"N":"Uganda","I":"UG","C":[[[[33.904,-0.95],[31.866,-1.027],[30.77,-1.015],[30.419,-1.135],[29.822,-1.443],[29.579,-1.341],[29.588,-0.587],[29.82,-0.205],[29.876,0.597],[30.086,1.062],[30.469,1.584],[30.853,1.849],[31.174,2.204],[30.773,2.34],[30.834,3.509],[30.834,3.509],[31.246,3.782],[31.881,3.558],[32.686,3.792],[33.39,3.79],[34.005,4.25],[34.479,3.556],[34.596,3.054],[35.036,1.906],[34.672,1.177],[34.18,0.515],[33.894,0.11],[33.904,-0.95]]]],"translations":{"ar":"أوغندا","bs":"Uganda","cs":"Uganda","de":"Uganda","es":"Uganda","fa_IR":"اوگاندا","fr":"Ouganda","id":"Uganda","it":"Uganda","ja":"ウガンダ","pl":"Uganda","pt_BR":"Uganda","pt_PT":"Uganda","ru":"Уганда","uk":"Уганда","zh_CN":"乌干达","zh_TW":"烏干達"}},{"N":"Rwanda","I":"RW","C":[[[[30.419,-1.135],[30.816,-1.699],[30.758,-2.287],[30.47,-2.414],[30.47,-2.414],[29.938,-2.348],[29.632,-2.918],[29.025,-2.839],[29.117,-2.292],[29.255,-2.215],[29.292,-1.62],[29.579,-1.341],[29.822,-1.443],[30.419,-1.135]]]],"translations":{"ar":"رواندا","bs":"Ruanda","cs":"Rwanda","de":"Ruanda","es":"Ruanda","fa_IR":"رواندا","fr":"Rwanda","id":"Rwanda","it":"Ruanda","ja":"ルワンダ","pl":"Rwanda","pt_BR":"Ruanda","pt_PT":"Ruanda","ru":"Руанда","uk":"Руанда","zh_CN":"卢旺达","zh_TW":"盧安達"}},{"N":"Bosnia and Herzegovina","I":"BA","C":[[[[18.56,42.65],[17.675,43.029],[17.297,43.446],[16.916,43.668],[16.456,44.041],[16.24,44.351],[15.75,44.819],[15.959,45.234],[16.318,45.004],[16.535,45.212],[17.002,45.234],[17.862,45.068],[18.553,45.082],[19.005,44.86],[19.005,44.86],[19.368,44.863],[19.118,44.423],[19.6,44.038],[19.454,43.568],[19.219,43.524],[19.032,43.433],[18.706,43.2],[18.56,42.65]]]],"translations":{"ar":"البوسنة والهرسك","bs":"Bosna i Hercegovina","cs":"Bosna a Hercegovina","de":"Bosnien und Herzegowina","es":"Bosnia y Herzegovina","fa_IR":"بوسنی و هرزگوین","fr":"Bosnie-HerzĂŠgovine","id":"Bosnia dan Herzegovina","it":"Bosnia ed Erzegovina","ja":"ボスニア・ヘルツェゴビナ","pl":"Bośnia i Hercegowina","pt_BR":"BĂłsnia e Herzegovina","pt_PT":"BĂłsnia e Herzegovina","ru":"Босния и Герцеговина","uk":"Боснія і Герцеговина","zh_CN":"波斯尼亚和黑塞哥维那","zh_TW":"波士尼亞與赫塞哥維納"}},{"N":"Macedonia","I":"MK","C":[[[[22.381,42.32],[22.881,41.999],[22.952,41.338],[22.762,41.305],[22.597,41.13],[22.055,41.15],[21.674,40.931],[21.02,40.843],[20.605,41.086],[20.463,41.515],[20.59,41.855],[20.59,41.855],[20.717,41.847],[20.762,42.052],[21.353,42.207],[21.577,42.245],[21.917,42.304],[22.381,42.32]]]],"translations":{"ar":"مقدونيا الشمالية","bs":"Sjeverna Makedonija","cs":"SevernĂ­ Makedonie","de":"Nordmazedonien","es":"Macedonia del Norte","fa_IR":"مقدونیهٔ شمالی","fr":"MacĂŠdoine du Nord","id":"Makedonia Utara","it":"Macedonia del Nord","ja":"北マケドニア","pl":"Macedonia Północna","pt_BR":"MacedĂ´nia do Norte","pt_PT":"MacedĂłnia do Norte","ru":"Северная Македония","uk":"Північна Македонія","zh_CN":"北马其顿","zh_TW":"北馬其頓"}},{"N":"Serbia","I":"RS","C":[[[[18.83,45.909],[18.83,45.909],[19.596,46.172],[20.22,46.127],[20.762,45.735],[20.874,45.416],[21.484,45.181],[21.562,44.769],[22.145,44.478],[22.459,44.703],[22.706,44.578],[22.474,44.409],[22.657,44.235],[22.41,44.008],[22.5,43.643],[22.986,43.211],[22.605,42.899],[22.437,42.58],[22.545,42.461],[22.381,42.32],[21.917,42.304],[21.577,42.245],[21.543,42.32],[21.663,42.439],[21.775,42.683],[21.633,42.677],[21.439,42.863],[21.274,42.91],[21.143,43.069],[20.957,43.131],[20.814,43.272],[20.635,43.217],[20.497,42.885],[20.258,42.813],[20.34,42.899],[19.959,43.106],[19.63,43.214],[19.484,43.352],[19.219,43.524],[19.454,43.568],[19.6,44.038],[19.118,44.423],[19.368,44.863],[19.005,44.86],[19.005,44.86],[19.39,45.237],[19.073,45.522],[18.83,45.909]]]],"translations":{"ar":"صربيا","bs":"Srbija","cs":"Srbsko","de":"Serbien","es":"Serbia","fa_IR":"صربستان","fr":"Serbie","id":"Serbia","it":"Serbia","ja":"セルビア","pl":"Serbia","pt_BR":"SĂŠrvia","pt_PT":"SĂŠrvia","ru":"Сербия","uk":"Сербія","zh_CN":"塞尔维亚","zh_TW":"塞爾維亞"}},{"N":"Montenegro","I":"ME","C":[[[[20.071,42.589],[19.802,42.5],[19.738,42.688],[19.304,42.196],[19.372,41.878],[19.162,41.955],[18.882,42.282],[18.45,42.48],[18.56,42.65],[18.706,43.2],[19.032,43.433],[19.219,43.524],[19.484,43.352],[19.63,43.214],[19.959,43.106],[20.34,42.899],[20.258,42.813],[20.071,42.589]]]],"translations":{"ar":"الجبل الأسود","bs":"Crna Gora","cs":"ČernĂĄ Hora","de":"Montenegro","es":"Montenegro","fa_IR":"مونته‌نگرو","fr":"MontĂŠnĂŠgro","id":"Montenegro","it":"Montenegro","ja":"モンテネグロ","pl":"CzarnogĂłra","pt_BR":"Montenegro","pt_PT":"Montenegro","ru":"Черногория","uk":"Чорногорія","zh_CN":"黑山","zh_TW":"蒙特內哥羅"}},{"N":"Kosovo","I":"XK","C":[[[[20.59,41.855],[20.523,42.218],[20.284,42.32],[20.071,42.589],[20.258,42.813],[20.497,42.885],[20.635,43.217],[20.814,43.272],[20.957,43.131],[21.143,43.069],[21.274,42.91],[21.439,42.863],[21.633,42.677],[21.775,42.683],[21.663,42.439],[21.543,42.32],[21.577,42.245],[21.353,42.207],[20.762,42.052],[20.717,41.847],[20.59,41.855]]]],"translations":{"ar":"كوسوفو","bs":"Kosovo","cs":"Kosovo","de":"Kosovo","es":"Kosovo","fa_IR":"ڊوزوو","fr":"Kosovo","id":"Kosovo","it":"Kosovo","ja":"コソボ","pl":"Kosowo","pt_BR":"Kosovo","pt_PT":"Kosovo","ru":"Косово","uk":"Косово","zh_CN":"科索沃","zh_TW":"科索沃"}},{"N":"Trinidad and Tobago","I":"TT","C":[[[[-61.68,10.76],[-61.105,10.89],[-60.895,10.855],[-60.935,10.11],[-61.77,10],[-61.95,10.09],[-61.66,10.365],[-61.68,10.76]]]],"translations":{"ar":"ترينيداد وتوباغو","bs":"Trinidad i Tobago","cs":"Trinidad a Tobago","de":"Trinidad und Tobago","es":"Trinidad y Tobago","fa_IR":"ترینیداد و توباگو","fr":"TrinitĂŠ-et-Tobago","id":"Trinidad dan Tobago","it":"Trinidad e Tobago","ja":"トリニダード・トバゴ","pl":"Trynidad i Tobago","pt_BR":"Trinidad e Tobago","pt_PT":"Trindade e Tobago","ru":"Тринидад и ТОйагО","uk":"Тринідад і ТОйагО","zh_CN":"特立尼达和多巴哥","zh_TW":"千里達及托巴哥"}},{"N":"South Sudan","I":"SS","C":[[[[30.834,3.509],[29.954,4.174],[29.716,4.601],[29.159,4.389],[28.697,4.455],[28.429,4.287],[27.98,4.408],[27.374,5.234],[27.213,5.551],[26.466,5.947],[26.213,6.547],[25.797,6.979],[25.124,7.5],[25.115,7.825],[24.567,8.229],[23.887,8.62],[24.194,8.729],[24.537,8.918],[24.795,9.81],[25.07,10.274],[25.791,10.411],[25.962,10.136],[26.477,9.553],[26.752,9.467],[27.113,9.639],[27.834,9.604],[27.971,9.398],[28.967,9.398],[29.001,9.604],[29.516,9.793],[29.619,10.085],[29.997,10.291],[30.838,9.707],[31.353,9.81],[31.851,10.531],[32.4,11.081],[32.314,11.681],[32.074,11.973],[32.675,12.025],[32.743,12.248],[33.207,12.179],[33.087,11.441],[33.207,10.72],[33.722,10.325],[33.842,9.982],[33.825,9.484],[33.963,9.464],[33.975,8.685],[33.826,8.379],[33.295,8.355],[32.954,7.785],[33.568,7.713],[34.075,7.226],[34.25,6.826],[34.707,6.594],[35.298,5.506],[34.62,4.847],[34.005,4.25],[33.39,3.79],[32.686,3.792],[31.881,3.558],[31.246,3.782],[30.834,3.509]]]],"translations":{"ar":"جنوب السودان","bs":"JuĹžni Sudan","cs":"JiĹžnĂ­ SĂşdĂĄn","de":"SĂźdsudan","es":"SudĂĄn del Sur","fa_IR":"سودان جنوبی","fr":"Soudan du Sud","id":"Sudan Selatan","it":"Sud Sudan","ja":"南スーダン","pl":"Sudan Południowy","pt_BR":"SudĂŁo do Sul","pt_PT":"SudĂŁo do Sul","ru":"Южный Худан","uk":"Південний Худан","zh_CN":"南苏丹","zh_TW":"南蘇丹"}}]}kolunmi-bazaar-7b9c8e1/src/curated-config-schema.xml000066400000000000000000000007321514314607700225250ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/dl-worker.c000066400000000000000000000130141514314607700177220ustar00rootroot00000000000000/* dl-worker.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::DL-WORKER-SUBPROCESS" #include "bz-env.h" #include "bz-global-net.h" #include "bz-util.h" BZ_DEFINE_DATA ( main, Main, { GMainLoop *loop; GIOChannel *stdout_channel; }, BZ_RELEASE_DATA (loop, g_main_loop_unref); BZ_RELEASE_DATA (stdout_channel, g_io_channel_unref)); BZ_DEFINE_DATA ( download, Download, { char *src; char *dest; GIOChannel *stdout_channel; }, BZ_RELEASE_DATA (src, g_free); BZ_RELEASE_DATA (dest, g_free); BZ_RELEASE_DATA (stdout_channel, g_io_channel_unref)); static DexFuture * read_stdin (MainData *data); static DexFuture * download_fiber (DownloadData *data); int main (int argc, char *argv[]) { g_autoptr (GIOChannel) stdout_channel = NULL; g_autoptr (GMainLoop) main_loop = NULL; g_autoptr (MainData) data = NULL; g_autoptr (DexFuture) future = NULL; g_log_writer_default_set_use_stderr (TRUE); dex_init (); stdout_channel = g_io_channel_unix_new (STDOUT_FILENO); g_assert (g_io_channel_set_encoding (stdout_channel, NULL, NULL)); g_io_channel_set_buffered (stdout_channel, FALSE); main_loop = g_main_loop_new (NULL, FALSE); data = main_data_new (); data->loop = g_main_loop_ref (main_loop); data->stdout_channel = g_io_channel_ref (stdout_channel); future = dex_scheduler_spawn ( dex_thread_pool_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) read_stdin, main_data_ref (data), main_data_unref); g_main_loop_run (main_loop); return EXIT_SUCCESS; } static DexFuture * read_stdin (MainData *data) { g_autoptr (GIOChannel) stdin_channel = NULL; stdin_channel = g_io_channel_unix_new (STDIN_FILENO); for (;;) { g_autoptr (GError) local_error = NULL; g_autofree char *string = NULL; char *newline = NULL; g_autoptr (GVariant) variant = NULL; g_autofree char *src_uri = NULL; g_autofree char *dest_path = NULL; g_autoptr (DownloadData) dl_data = NULL; g_io_channel_read_line ( stdin_channel, &string, NULL, NULL, &local_error); if (string == NULL) { if (local_error != NULL) g_warning ("FATAL: Failure reading stdin channel: %s", local_error->message); g_main_loop_quit (data->loop); return NULL; } newline = g_utf8_strchr (string, -1, '\n'); if (newline != NULL) *newline = '\0'; variant = g_variant_parse ( G_VARIANT_TYPE ("(ss)"), string, NULL, NULL, &local_error); if (variant == NULL) { g_warning ("Failure parsing variant text '%s' into structure: %s\n", string, local_error->message); g_main_loop_quit (data->loop); continue; } g_variant_get (variant, "(ss)", &src_uri, &dest_path); dl_data = download_data_new (); dl_data->src = g_steal_pointer (&src_uri); dl_data->dest = g_steal_pointer (&dest_path); dl_data->stdout_channel = g_io_channel_ref (data->stdout_channel); dex_future_disown (dex_scheduler_spawn ( dex_scheduler_get_default (), bz_get_dex_stack_size (), (DexFiberFunc) download_fiber, download_data_ref (dl_data), download_data_unref)); } return NULL; } static DexFuture * download_fiber (DownloadData *data) { gboolean success = FALSE; g_autoptr (GError) local_error = NULL; g_autoptr (GFile) dest_file = NULL; g_autoptr (GFileOutputStream) dest_output = NULL; g_autoptr (SoupMessage) message = NULL; g_autoptr (GVariant) variant = NULL; g_autofree char *output = NULL; g_autofree char *output_plus_nl = NULL; dest_file = g_file_new_for_path (data->dest); dest_output = g_file_replace ( dest_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); if (dest_output == NULL) { g_warning ("%s", local_error->message); goto done; } message = soup_message_new (SOUP_METHOD_GET, data->src); success = dex_await (bz_send_with_global_http_session_then_splice_into ( message, G_OUTPUT_STREAM (dest_output)), &local_error); if (!success) { g_warning ("%s", local_error->message); goto done; } done: variant = g_variant_new ("(sb)", data->dest, success); output = g_variant_print (variant, TRUE); output_plus_nl = g_strdup_printf ("%s\n", output); g_io_channel_write_chars (data->stdout_channel, output_plus_nl, -1, NULL, NULL); return dex_future_new_true (); } kolunmi-bazaar-7b9c8e1/src/gen_gobject.sh000077500000000000000000000435321514314607700204650ustar00rootroot00000000000000#!/bin/sh # gen_gobject.sh # author: kolunmi die() { echo "Usage: $0 [--header|--code] [spec] [output]" 1>&2 echo " [--header|--code] whether to output the header (.h) or code (.c)" 1>&2 echo " [spec] spec keyfile" 1>&2 echo " [output] output file" 1>&2 echo "" 1>&2 echo " The spec file should contain these keys:" 1>&2 echo " [prefix] lower case prefix, EX: my" 1>&2 echo " [name] lower case class name, EX: class" 1>&2 echo " [parent-prefix] prefix of parent class, EX: g" 1>&2 echo " [parent-name] name of parent class, EX: object" 1>&2 echo " [author] author name, EX: " 1>&2 echo " [include] #include for the header file (can have multiple)" 1>&2 echo " EX: " 1>&2 echo " EX: \"my-other-class.h\"" 1>&2 echo " [enum] declare an enum type (can have multiple)" 1>&2 echo " EX: my fruit_type apple orange pear" 1>&2 echo " [ensure] ensure another type (can have multiple), EX: GTK_TYPE_WIDGET" 1>&2 echo " [property] property spec (can have multiple), EX: (see below)" 1>&2 echo "" 1>&2 echo " The properties are parsed with the form:" 1>&2 echo " [name] [ctype] [gtype] [spec-type] [free (optional)] [ref (optional)]" 1>&2 echo " EX: my_widget GtkWidget GTK_TYPE_WIDGET object" 1>&2 echo " EX: my_string char G_TYPE_STRING string" 1>&2 echo " EX: my_int int G_TYPE_INT int" 1>&2 echo " EX: my_ptr_array GPtrArray G_TYPE_PTR_ARRAY boxed g_ptr_array_unref g_ptr_array_ref" 1>&2 echo "" 1>&2 echo "$@, aborting!" 1>&2 exit 1 } if [ "$#" -ne 3 ]; then die wrong number of args fi OUTPUT_TYPE="$1" SPEC_FILE="$2" OUTPUT_FILE="$3" if [ -z "$OUTPUT_TYPE" ] || [ -z "$SPEC_FILE" ] || [ -z "$OUTPUT_FILE" ]; then die one or more args are empty fi case "$OUTPUT_TYPE" in --header|--code) ;; *) die arg 1 must be '--header' or '--code' ;; esac if ! [ -f "$SPEC_FILE" ]; then die "$SPEC_FILE isn't a file" fi # if [ -e "$OUTPUT_FILE" ]; then # die "$OUTPUT_FILE already exists" # fi unset PREF unset NAME unset PAR_PREF unset PAR_NAME unset AUTHOR unset INCLUDES unset ENSURES unset ENUMS unset PROPS while IFS= read -r line; do [ -z "$line" ] && continue KEY="${line%%=*}" VAL="${line#*=}" case "$KEY" in prefix) PREF="$VAL" ;; name) NAME="$VAL" ;; parent-prefix) PAR_PREF="$VAL" ;; parent-name) PAR_NAME="$VAL" ;; author) AUTHOR="$VAL" ;; include) if [ -n "$INCLUDES" ]; then INCLUDES="${INCLUDES} #include ${VAL}" else INCLUDES="#include ${VAL}" fi ;; enum) if [ -n "$ENUMS" ]; then ENUMS="${ENUMS} ${VAL}" else ENUMS="$VAL" fi ;; ensure) if [ -n "$ENSURES" ]; then ENSURES="${ENSURES} g_type_ensure (${VAL});" else ENSURES=" g_type_ensure (${VAL});" fi ;; property) if [ -n "$PROPS" ]; then PROPS="${PROPS} ${VAL}" else PROPS="$VAL" fi ;; *) die "unknown key '${KEY}' in ${SPEC_FILE}" ;; esac done < "$SPEC_FILE" if [ -z "$PREF" ] || [ -z "$NAME" ] || [ -z "$PAR_PREF" ] || [ -z "$PAR_NAME" ] || [ -z "$AUTHOR" ] || [ -z "$PROPS" ]; then die "one or more params in $SPEC_FILE are empty" fi case "$OUTPUT_TYPE" in --header) H_FILE="$OUTPUT_FILE" C_FILE="${OUTPUT_FILE%\.h}.c" ;; --code) H_FILE="${OUTPUT_FILE%\.c}.h" C_FILE="$OUTPUT_FILE" ;; esac to_upper() { echo "$1" | tr '[a-z]' '[A-Z]' } to_pascal() { echo "$1" | sed 's/[^_]\+/\L\u&/g' | tr -d '_' } to_hyphened() { echo "$1" | tr '_' '-' } SNAKE="${PREF}_${NAME}" MACRO_PREF="$(to_upper "${PREF}")" MACRO_NAME="$(to_upper "${NAME}")" MACRO="${MACRO_PREF}_${MACRO_NAME}" TYPE="${MACRO_PREF}_TYPE_${MACRO_NAME}" PASCAL="$(to_pascal "${SNAKE}")" HYPHEN_NAME="$(to_hyphened "${NAME}")" HYPHEN="$(to_hyphened "${PREF}")-${HYPHEN_NAME}" PAR_SNAKE="${PAR_PREF}_${PAR_NAME}" PAR_MACRO_PREF="$(to_upper "${PAR_PREF}")" PAR_MACRO_NAME="$(to_upper "${PAR_NAME}")" PAR_MACRO="${PAR_MACRO_PREF}_${PAR_MACRO_NAME}" PAR_TYPE="${PAR_MACRO_PREF}_TYPE_${PAR_MACRO_NAME}" PAR_PASCAL="$(to_pascal "${PAR_SNAKE}")" PAR_HYPHEN_NAME="$(to_hyphened "${PAR_NAME}")" PAR_HYPHEN="$(to_hyphened "${PAR_PREF}")-${PAR_HYPHEN_NAME}" YEAR="$(date +'%Y')" print_enums () { HEADER="$1" [ -z "$ENUMS" ] && return if [ "$HEADER" = header ]; then while IFS= read -r line; do set -- $line LOC_PREF="$1" LOC_NAME="$2" LOC_SNAKE="${LOC_PREF}_${LOC_NAME}" LOC_SNAKE_UPPER="$(to_upper "$LOC_SNAKE")" LOC_TYPE="$(to_upper "$LOC_PREF")_TYPE_$(to_upper "$LOC_NAME")" LOC_PASCAL="$(to_pascal "${LOC_SNAKE}")" shift 2 printf 'typedef enum\n{\n' for enum in "$@"; do LOC_ENUM_SYMBOL="${LOC_SNAKE_UPPER}_$(to_upper "$enum")" printf ' %s,\n' "$LOC_ENUM_SYMBOL" done printf '} %s;\n' "$LOC_PASCAL" printf 'GType %s_get_type (void);\n' "$LOC_SNAKE" printf '#define %s (%s_get_type ())\n\n' "$LOC_TYPE" "$LOC_SNAKE" done <%s, ' "${LOC_NAME}" if [ -n "$LOC_FREE" ]; then printf "$LOC_FREE" else case "$LOC_PTYPE" in string) printf 'g_free' ;; *) printf 'g_object_unref' ;; esac fi printf ');\n' ;; esac done <%s;\n' "$LOC_NAME" printf '}\n\n' fi done <%s' "$LOC_NAME" "$LOC_NAME" ;; string) printf '%s == self->%s || (%s != NULL && self->%s != NULL && g_strcmp0(%s, self->%s) == 0)' "$LOC_NAME" "$LOC_NAME" "$LOC_NAME" "$LOC_NAME" "$LOC_NAME" "$LOC_NAME";; *) printf '%s == self->%s' "$LOC_NAME" "$LOC_NAME" ;; esac printf ')\n return;\n\n' case "$LOC_PTYPE" in char|uchar|boolean|int|uint|long|ulong|int64|uint64|unichar|enum|flags|float|double) ;; *) printf ' g_clear_pointer (&self->%s, ' "$LOC_NAME" if [ -n "$LOC_FREE" ]; then printf "$LOC_FREE" else case "$LOC_PTYPE" in string) printf 'g_free' ;; *) printf 'g_object_unref' ;; esac fi printf ');\n' printf ' if (%s != NULL)\n ' "$LOC_NAME" ;; esac printf ' self->%s = ' "$LOC_NAME" if [ -n "$LOC_REF" ]; then printf '%s (%s)' "$LOC_REF" "$LOC_NAME" else case "$LOC_PTYPE" in char|uchar|boolean|int|uint|long|ulong|int64|uint64|unichar|enum|flags|float|double) printf '%s' "$LOC_NAME" ;; string) printf 'g_strdup (%s)' "$LOC_NAME" ;; *) printf 'g_object_ref (%s)' "$LOC_NAME" ;; esac fi printf ';\n\n' printf ' g_object_notify_by_pspec (G_OBJECT (self), props[PROP_%s]);\n' "$(to_upper $LOC_NAME)" printf '}\n\n' fi done < "$H_FILE" <. * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include $INCLUDES G_BEGIN_DECLS $(print_enums header) #define $TYPE (${SNAKE}_get_type ()) G_DECLARE_FINAL_TYPE ($PASCAL, $SNAKE, $MACRO_PREF, $MACRO_NAME, $PAR_PASCAL) $(print_functions header) $(print_get_property_methods header) $(print_set_property_methods header) G_END_DECLS /* End of $H_FILE */ EOF [ "$OUTPUT_TYPE" = --code ] && cat > "$C_FILE" <. * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "$H_FILE" $(print_enums) struct _${PASCAL} { $PAR_PASCAL parent_instance; $(print_struct) }; G_DEFINE_FINAL_TYPE ($PASCAL, $SNAKE, $PAR_TYPE); enum { $(print_prop_enums) }; static GParamSpec *props[LAST_PROP] = { 0 }; static void ${SNAKE}_dispose (GObject *object) { $PASCAL *self = $MACRO (object); $(print_dispose) G_OBJECT_CLASS (${SNAKE}_parent_class)->dispose (object); } static void ${SNAKE}_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { $PASCAL *self = $MACRO (object); switch (prop_id) { $(print_get_property) default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ${SNAKE}_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { $PASCAL *self = $MACRO (object); switch (prop_id) { $(print_set_property) default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ${SNAKE}_class_init (${PASCAL}Class *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); $ENSURES object_class->set_property = ${SNAKE}_set_property; object_class->get_property = ${SNAKE}_get_property; object_class->dispose = ${SNAKE}_dispose; $(print_init_properties) g_object_class_install_properties (object_class, LAST_PROP, props); } static void ${SNAKE}_init (${PASCAL} *self) { } $(print_functions) $(print_get_property_methods) $(print_set_property_methods) /* End of $C_FILE */ EOF exit 0 kolunmi-bazaar-7b9c8e1/src/gtk/000077500000000000000000000000001514314607700164365ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/gtk/shortcuts-dialog.blp000066400000000000000000000016351514314607700224350ustar00rootroot00000000000000using Gtk 4.0; using Adw 1; Adw.ShortcutsDialog shortcuts_dialog { Adw.ShortcutsSection general_section { title: C_("shortcut window", "General"); Adw.ShortcutsItem { title: C_("shortcut window", "Open Search Dialog"); action-name: "app.search('')"; } Adw.ShortcutsItem { title: C_("shortcut window", "Open Preferences"); action-name: "app.preferences"; } Adw.ShortcutsItem { title: C_("shortcut window", "Synchronize Remotes"); action-name: "app.sync-remotes"; } Adw.ShortcutsItem { title: C_("shortcut window", "Open Library"); action-name: "window.open-library"; accelerator: "d"; } Adw.ShortcutsItem { title: C_("shortcut window", "Show Shortcuts"); action-name: "app.shortcuts"; } Adw.ShortcutsItem { title: C_("shortcut window", "Quit"); action-name: "app.quit"; } } } kolunmi-bazaar-7b9c8e1/src/gtk/style.css000066400000000000000000000453241514314607700203200ustar00rootroot00000000000000.bz-monospace { font-family: monospace; } .bz-debug { background-color: darkorange; color: black; } .bz-donations-dialog { background: linear-gradient(to bottom left, #1f2d8f, #159eff); color: white; } .bz-donations-banner { --banner-color: #159eff; } .updates-amount { background-color: white; color: var(--accent-bg-color); font-size: 0.60em; border-radius: 9999px; font-weight: 900; } .updates-amount-border { background-color: var(--accent-bg-color); border-radius: 9999px; } .search-box { outline: 0 solid transparent; outline-offset: 6px; transition-property: outline, outline-offset; transition-duration: 200ms; padding: 8px 12px; border-radius: 9999px; background-color: var(--card-bg-color); } .search-box:focus-within { outline-color: color-mix(in srgb, var(--accent-color), transparent); outline-offset: 0; outline-width: 2px; } .rich-screenshot-box { background-color: var(--sidebar-bg-color); } @media (prefers-color-scheme: light) { .search-box { background-color: var(--shade-color); } .rich-screenshot-box { background-color: var(--sidebar-bg-color); } } .search-box > text placeholder { opacity: 0.55; } .clear-button { min-height: 24px; } .search-grid { background-color: var(--window-bg-color); } .search-grid > child { padding: 0; margin: 6px 6px; border-radius: 12px; transition: background-color 200ms; } .narrow .search-grid > child { margin: 6px 12px; } .card-row-btn { border-radius: 0; } .screenshot { border-radius: 20px; } .browser-banner { border-radius: 25px; background-color: transparent; } .browser-banner-title { font-size: 3.2em; font-weight: bolder; } .browser-banner-subtitle { font-size: 2.0em; font-weight: bold; } .browser-banner-description { font-size: 1.33em; font-weight: normal; } .installed-size { font-weight: 500; } .verified { color: @blue_2; } .support { --accent-fg-color : #f06292; --accent-bg-color : alpha(#f06292, 0.25); --accent-color : #f06292; } .favorite { --accent-fg-color: @accent_bg_color; --accent-bg-color : alpha(@accent_bg_color, 0.25); --accent-color: @accent_color; } .favorite * { --accent-fg-color: @accent_fg_color; --accent-bg-color: @accent_bg_color; --accent-color: @accent_color; } .orange { --accent-fg-color: @orange_5; --accent-color: alpha(@orange_5, 0.25); --accent-bg-color: @orange_5; } .green { --accent-fg-color : #8ff0a4; --accent-bg-color : alpha(#2ec27e, 0.25); --accent-color : #8ff0a4; } .blue { --accent-fg-color : #99c1f1; --accent-bg-color : alpha(#1a5fb4, 0.25); --accent-color : #99c1f1; } .dark-blue { --accent-fg-color : #99c1f1; --accent-bg-color : #1a5fb4; --accent-color : #99c1f1; } @media (prefers-color-scheme: light) { .green { --accent-fg-color : #2ec27e; --accent-bg-color : alpha(#8ff0a4, 0.25); --accent-color : #2ec27e; } .blue { --accent-fg-color : #1a5fb4; --accent-bg-color : alpha(#99c1f1, 0.25); --accent-color : #1a5fb4; } .dark-blue { --accent-fg-color : #1C71D8; --accent-bg-color : #1C71D8; --accent-color : #1C71D8; } } .grey { --accent-color: alpha(@window_fg_color,0.75); --accent-bg-color: @window_fg_color; } .grey.colored { --accent-fg-color : @window_fg_color; --accent-bg-color : alpha(@window_fg_color,0.05); --accent-color : alpha(@window_fg_color,0.75); } .circular-lozenge.green, .lozenge.green { color: @green_5; background-color: alpha(@green_3, .25); } .circular-lozenge.yellow, .lozenge.yellow { color: #ae7b03; background: alpha(@yellow_5, .25); } .circular-lozenge.orange, .lozenge.orange { color: @orange_5; background-color: alpha(@orange_4, .25); } .circular-lozenge.red, .lozenge.red { color: @red_4; background-color: alpha(@red_2, .25); } .circular-lozenge.grey, .lozenge.grey { color: @window_fg_color; background-color: alpha(@dark_3, .25); } @media (prefers-color-scheme: dark) { .circular-lozenge.green, .lozenge.green { color: @green_1; background-color: alpha(@green_4, .25); } .circular-lozenge.yellow, .lozenge.yellow { color: @yellow_2; background: alpha(#cd9309, .25); } .circular-lozenge.orange, .lozenge.orange { color: @orange_1; } .circular-lozenge.red, .lozenge.red { color: #ff7b63; } .circular-lozenge.grey, .lozenge.grey { background-color: alpha(@light_5, .25); } } .floating-tooltip { background-color: var(--dialog-bg-color); } .floating-tooltip .monospace { font-size: 1em; } .flathub { --accent-color: alpha(@window_fg_color,0.75); --accent-bg-color: @window_fg_color; } @media (prefers-color-scheme: dark) { .flathub { --accent-color: alpha(#fafafa,0.75); --accent-bg-color: #7847b8; } } global-progress { color: var(--accent-bg-color); } global-progress > *:first-child { background: var(--flag-gradient, var(--accent-bg-color)); } global-progress image { color: var(--window-fg-color); } .global-progress-button { padding: 5px; } .lozenge { font-size: 18px; font-weight: bold; border-radius: 99999px; padding: 5px 11px; min-width: 18px; min-height: 22px; color: var(--accent-color); background-color: alpha(var(--accent-bg-color),0.15); transition: background-color 150ms ease; } .lozenge.small { padding: 1px 9px; font-size: 12px; font-weight: bold; } .lozenge-ring-button { padding: 0; border-radius: 999999px; background: transparent; } .circular-lozenge { font-weight: bold; border-radius: 99999px; padding: 9px 11px; min-width: 18px; min-height: 22px; color: var(--accent-color); background-color: alpha(var(--accent-bg-color),0.15); } .circular-lozenge.large { font-size: 24px; padding: 15px 18px; min-width: 24px; min-height: 30px; } button.context-tile:hover .lozenge { background-color: alpha(var(--accent-bg-color),0.25); } button.context-tile:active .lozenge { background-color: alpha(var(--accent-bg-color),0.35); } .small-pill { padding: 2px 12px; border-radius: 99999px; } .medium-pill { border-radius: 99999px; } .colored { background-color: var(--accent-bg-color); color: var(--accent-color); } .card.colored { background-color: alpha(var(--accent-bg-color),0.15); color: var(--accent-color); } .small-pill.dimmed { background-color: alpha(@theme_fg_color, 0.15); } .small-pill.error { background-color: alpha(@error_bg_color, 0.15); } .installed-pill { background-color: alpha(@success_bg_color, 0.15); color: @success_color; font-weight: 500; font-size: 0.9em; padding: 2px 7px 2px 4.5px; } .sp-section .installed-pill { background-color: alpha(@window_fg_color, 0.10); color: alpha(@window_fg_color, 0.75); } .download-size-pill{ padding: 2px 8px; } .flathub-page-section { border-radius: 10px; } .transaction-list-view row { margin: 0; padding: 0; } window.narrow .app-title { font-size: 16pt; } .developer-badge > button { padding: 0; background-color: transparent; } .developer-badge:focus > button { border-radius: 5px; } window.narrow .app-developer { font-size: small; } .context-tile { box-shadow: none; padding: 4px; } button.context-tile { background-color: transparent; } .context-tile-text { font-size: 10pt; font-weight: 500; } .wide-image { margin-top: -28px; margin-bottom: -28px; } .screenshot-carousel.frame { border-width: 1px 0; } .screenshot-carousel button{ margin: 12px; } .carousel-box { background-color: var(--view-bg-color); } toggle-group.huge, toggle-group.huge * { border-radius: 9999px; } .huge > toggle { padding: 3px 12px; } .otg { background: linear-gradient(to right, #2f3d9f, #682889); } .wlg { background: linear-gradient(to right, #821756, #136673); } .sp-section .card:not(:hover):not(:active) { background: transparent; } .sp-section .card { box-shadow: none; } @media (prefers-color-scheme: light) { .otg { background: linear-gradient(to right, #c6eaf8, #c4f3c9); } .wlg { background: linear-gradient(to right, #fdcde0, #b0e5f0); } .sp-section .card:hover { background: rgba(255, 255, 255, 0.50); } .sp-section .card:active { background: rgba(255, 255, 255, 0.75); } } .sp-section-image { margin-top: -95px; margin-bottom: -95px; } .sp-section-title { font-size: 3.5em; } .decorated-screenshot { margin: 0; padding: 0; background-color: transparent; } .indicator-box button { margin: 0 4px 4px 0; } .pip-button.osd-box { padding: 0; } .pip-button > button { margin: 5px; } window, headerbar, .global-search { transition: background-color 0.2s ease; } .header-osd windowcontrols button image { background-color: rgba(0, 0, 0, 0.65); color: white; background-image: none; } .osd-box { border-radius: 12px; background-color: rgba(0, 0, 0, 0.65); padding: 6px; color: white; } .view-dark { background-color: black; color: white; } .header-osd box.horizontal:not(.end) { background-color: rgba(0, 0, 0, 0.65); border-radius: 10px; } .accent-button { border-radius: 9999px; padding: 3px; background: var(--flag-gradient, var(--accent-bg-color)); min-width: 32px; min-height: 32px; outline: none; background-clip: content-box; background-origin: content-box; box-shadow: none; transition: transform 0.3s ease; } .accent-button.horizontal { transform: rotate(-90deg); } .accent-button-box > flowboxchild { padding: 0; background-color: transparent; } .accent-button:checked { box-shadow: 0 0 0 3px var(--accent-bg-color); } .accent-button:focus:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-color) 30%, transparent); } .accent-button:checked:focus:focus-visible { box-shadow: 0 0 0 3px var(--accent-bg-color), 0 0 0 6px color-mix(in srgb, var(--accent-color) 30%, transparent); } /* Category buttons styling modified from GNOME Software*/ .category-tile { font-weight: 700; font-size: 13pt; color: white; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); padding-left: 32px; padding-right: 32px; } window.narrow .category-tile { font-size: 14pt; padding-left: 24px; padding-right: 24px; } /* All background gradients are at 135deg for consistency */ .category-tile.category-recently-updated { background: linear-gradient(135deg, #f9ef69, #26a269); color: #0c3020; text-shadow: 0 1px rgba(255, 255, 255, 0.35); } .category-tile.category-recently-updated:hover { background: linear-gradient(135deg, shade(#f9ef69, 1.1), shade(#26a269, 1.1)); } .category-tile.category-recently-updated:active { background: linear-gradient(135deg, shade(#f9ef69, 0.95), shade(#26a269, 0.95)); } .category-tile.category-recently-added { background: linear-gradient(135deg, #99a3eb, #495ade); } .category-tile.category-recently-added:hover { background: linear-gradient(135deg, shade(#99a3eb, 1.1), shade(#495ade, 1.1)); } .category-tile.category-recently-added:active { background: linear-gradient(135deg, shade(#99a3eb, .95), shade(#495ade, .95)); } .category-tile.category-trending { background: linear-gradient(135deg, #99c1f1, #3584e4); } .category-tile.category-trending:hover { background: linear-gradient(135deg, shade(#99c1f1, 1.1), shade(#3584e4, 1.1)); } .category-tile.category-trending:active { background: linear-gradient(135deg, shade(#99c1f1, .95), shade(#3584e4, .95)); } .category-tile.category-popular { background: linear-gradient(135deg, #f7ef74, #ffbf6f); color: rgba(0, 0, 0, 0.8); text-shadow: 0 1px rgba(255, 255, 255, 0.35); } .category-tile.category-popular:hover { background: linear-gradient(135deg, shade(#f7ef74, 1.1), shade(#ffbf6f, 1.1)); } .category-tile.category-popular:active { background: linear-gradient(135deg, shade(#f7ef74, .95), shade(#ffbf6f, .95)); } .category-tile.category-mobile { background: linear-gradient(135deg, #c6eaf8, #c4f3c9); color: rgba(0, 0, 0, 0.8); text-shadow: 0 1px rgba(255, 255, 255, 0.35); } .category-tile.category-mobile:hover { background: linear-gradient(135deg, shade(#c6eaf8, 1.1), shade(#c4f3c9, 1.1)); } .category-tile.category-mobile:active { background: linear-gradient(135deg, shade(#c6eaf8, .95), shade(#c4f3c9, .95)); } .category-tile.category-graphics { background: linear-gradient(135deg, #ce8cd7 0%, #2861c6 100%); } .category-tile.category-graphics:hover { background: linear-gradient(135deg, shade(#ce8cd7, 1.07) 0%, shade(#2861c6, 1.1) 100%); } .category-tile.category-graphics:active { background: linear-gradient(135deg, shade(#ce8cd7, .95) 0%, shade(#2861c6, .95) 100%); } .category-tile.category-development { background: linear-gradient(135deg, #444449 30%, #333337 100%); } .category-tile.category-development:hover { background: linear-gradient(135deg, shade(#444449, 1.06) 30%, shade(#333337, 1.06) 100%); } .category-tile.category-development:active { background: linear-gradient(135deg, shade(#444449, .95) 30%, shade(#333337, .95) 100%); } .category-tile.category-education { background: linear-gradient(135deg, #2ec27e 30%, #27a66c 100%); } .category-tile.category-education:hover { background: linear-gradient(135deg, shade(#2ec27e, 1.06) 30%, shade(#27a66c, 1.06) 100%); } .category-tile.category-education:active { background: linear-gradient(135deg, shade(#2ec27e, .95) 30%, shade(#27a66c, .95) 100%); } .category-tile.category-game { background: linear-gradient(135deg, #f9e2a7 0%, #eb5ec3 50%, #6d53e0 100%); color: #393484; text-shadow: 0 1px rgba(255, 255, 255, 0.35); } .category-tile.category-game:hover { background: linear-gradient(135deg, shade(#f9e2a7, 1.07) 0%, shade(#eb5ec3, 1.07) 50%, shade(#6d53e0, 1.07) 100%); } .category-tile.category-game:active { background: linear-gradient(135deg, shade(#f9e2a7, .97) 0%, shade(#eb5ec3, .95) 50%, shade(#6d53e0, 1.07) 100%); } .category-tile.category-network { background: linear-gradient(135deg, #ff6b35, #ed333b); } .category-tile.category-network:hover { background: linear-gradient(135deg, shade(#ff6b35, 1.1), shade(#ed333b, 1.1)); } .category-tile.category-network:active { background: linear-gradient(135deg, shade(#ff6b35, .95), shade(#ed333b, .95)); } .category-tile.category-office { padding: 1px; color: #1c71d8; text-shadow: 0 1px rgba(255, 255, 255, 0.35); background-color: #fdf8d7; background-image: linear-gradient(#deddda 1px, transparent 1px), linear-gradient(90deg, #deddda 1px, transparent 1px); background-size: 10px 10px, 10px 10px; background-position: -1px -4px, center -1px; } .category-tile.category-office:hover { background-color: shade(#fdf8d7, 1.03); background-image: linear-gradient(shade(#deddda, 1.04) 1px, transparent 1px), linear-gradient(90deg, shade(#deddda, 1.04) 1px, transparent 1px); } .category-tile.category-office:active { background-color: shade(#fdf8d7, .93); background-image: linear-gradient(shade(#deddda, .97) 1px, transparent 1px), linear-gradient(90deg, shade(#deddda, .97) 1px, transparent 1px); } .category-tile.category-audiovideo { background: linear-gradient(135deg, #ffcd3c 0%, #ff6b35 100%); } .category-tile.category-audiovideo:hover { background: linear-gradient(135deg, shade(#ffcd3c, 1.08) 0%, shade(#ff6b35, 1.08) 100%); } .category-tile.category-audiovideo:active { background: linear-gradient(135deg, shade(#ffcd3c, .95) 0%, shade(#ff6b35, .95) 100%); } .category-tile.category-science { background: linear-gradient(135deg, #8ff0a4 0%, #1c71d8 100%); } .category-tile.category-science:hover { background: linear-gradient(135deg, shade(#8ff0a4, 1.1) 0%, shade(#1c71d8, 1.1) 100%); } .category-tile.category-science:active { background: linear-gradient(135deg, shade(#8ff0a4, .95) 0%, shade(#1c71d8, .95) 100%); } .category-tile.category-system { background: linear-gradient(135deg, #6c757d 0%, #495057 100%); } .category-tile.category-system:hover { background: linear-gradient(135deg, shade(#6c757d, 1.15) 0%, shade(#495057, 1.15) 100%); } .category-tile.category-system:active { background: linear-gradient(135deg, shade(#6c757d, .95) 0%, shade(#495057, .95) 100%); } .category-tile.category-utility { color: #ee5f50; text-shadow: 0 1px rgba(255, 255, 255, 0.35); background: linear-gradient(135deg, #f6f5f4 0%, #deddda 100%); } .category-tile.category-utility:hover { background: linear-gradient(135deg, shade(#f6f5f4, 1.08) 0%, shade(#deddda, 1.08) 100%); } .category-tile.category-utility:active { background: linear-gradient(135deg, shade(#f6f5f4, .95) 0%, shade(#deddda, .95) 100%); } .category-tile.category-adwaita { text-shadow: 0 1px rgba(255, 255, 255, 0.35); background: linear-gradient(45deg, #1c71d8 0%, #57e289 100%); } .category-tile.category-adwaita:hover { background: linear-gradient(45deg, shade(#1c71d8, 1.08) 0%, shade(#57e289, 1.08) 100%); } .category-tile.category-adwaita:active { background: linear-gradient(45deg, shade(#1c71d8, .95) 0%, shade(#57e289, .95) 100%); } .category-tile.category-kde { text-shadow: 0 1px rgba(255, 255, 255, 0.35); background: linear-gradient(135deg, #3584e4 0%, #704dac 100%); } .category-tile.category-kde:hover { background: linear-gradient(135deg, shade(#3584e4, 1.08) 0%, shade(#704dac, 1.08) 100%); } .category-tile.category-kde:active { background: linear-gradient(135deg, shade(#3584e4, .95) 0%, shade(#704dac, .95) 100%); } .category-tile.category-adwaita image, .category-tile.category-kde image { -gtk-icon-shadow: none; } .installed-list-view > * { padding: 0; transition: background-color 200ms; min-height: 0; margin: 5px 4.5px; } .narrow .installed-list-view > * { margin: 4px 4.5px; } .no-vertical-margin > row.hidden { margin-top: 0px; margin-bottom: 0px; } .no-vertical-margin > row:not(.hidden) { margin-bottom: 6px; } .user-data-list-view > * { margin: 0; } .user-data-list-view row { min-height: 0; } .no-min-height { min-height: 0; } .transaction-tile-title { font-size: 1.05em; font-weight: 450; } .operations { background-color: rgba(0, 0, 0, 0.10); border-radius: 0px 0px 12px 12px; } @media (prefers-color-scheme: light) { .operations { background-color: rgba(0, 0, 0, 0.050); } } .ops-toggle { transition: transform 200ms ease; transform: rotate(90deg); } .ops-toggle:checked, .ops-toggle.rotated { transform: rotate(270deg); } .update-list { background-color: alpha(@card_bg_color, 0.8); border-radius: 0 0 12px 12px; } .update-toggle { border-radius: 0; } .update-card { border-radius: 12px; box-shadow: 0 0 0 1px rgba(0,0,6,0.03), 0 1px 3px 1px rgba(0,0,6,0.07), 0 2px 6px 2px rgba(0,0,6,0.03); } @media (prefers-color-scheme: dark) { separator { opacity: 0.5; } } .disable-adw-flow-box-styling { background-color: transparent; box-shadow: none; } curated-list-view, curated-list-view list { background: var(--bg-color); } .bz-popup { border-radius: 15px; background: var(--window-bg-color); /* box-shadow: 0 0 20px 1px black; */ } kolunmi-bazaar-7b9c8e1/src/icons/000077500000000000000000000000001514314607700167645ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Adwaita.svg000066400000000000000000000005621514314607700256250ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Audiovideo.svg000066400000000000000000000352101514314607700263410ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Create.svg000066400000000000000000000145341514314607700254620ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Develop.svg000066400000000000000000000053621514314607700256540ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Kde.svg000066400000000000000000000030641514314607700247560ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Learn.svg000066400000000000000000000225301514314607700253130ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Mobile.svg000066400000000000000000000255131514314607700254650ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Network.svg000066400000000000000000000057551514314607700257150ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.New.svg000066400000000000000000000050101514314607700247750ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Play.svg000066400000000000000000000141651514314607700251640ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Popular.svg000066400000000000000000000075121514314607700256770ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Science.svg000066400000000000000000000566261514314607700256400ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.System.svg000066400000000000000000000164001514314607700255350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Trending.svg000066400000000000000000000300621514314607700260230ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Updated.svg000066400000000000000000000032311514314607700256350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Utilities.svg000066400000000000000000000135561514314607700262350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolumni.Bazaar.Work.svg000066400000000000000000000204541514314607700251770ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolunmi.Bazaar.github.svg000066400000000000000000000027731514314607700255430ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolunmi.Bazaar.gitlab.svg000066400000000000000000000040351514314607700255140ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolunmi.Bazaar.gnome.svg000066400000000000000000000024111514314607700253530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolunmi.Bazaar.google.svg000066400000000000000000000026351514314607700255320ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/io.github.kolunmi.Bazaar.kde.svg000066400000000000000000000034171514314607700250200ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/000077500000000000000000000000001514314607700205325ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/000077500000000000000000000000001514314607700221725ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/app-installed-symbolic.svg000066400000000000000000000014351514314607700272720ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/app-safety-ok-symbolic.svg000066400000000000000000000012551514314607700272150ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/app-safety-unknown-symbolic.svg000066400000000000000000000025621514314607700303050ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/app-safety-unsafe-symbolic.svg000066400000000000000000000015611514314607700300650ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/auditable-code-symbolic.svg000066400000000000000000000024221514314607700273740ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/bookmark-filled-symbolic.svg000066400000000000000000000007471514314607700276040ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/bookmark-outline-symbolic.svg000066400000000000000000000012471514314607700300200ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/check-plain-symbolic.svg000066400000000000000000000013361514314607700267130ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/circle-filled-symbolic.svg000066400000000000000000000004051514314607700272270ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/code-symbolic.svg000066400000000000000000000014061514314607700254450ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/community-symbolic.svg000066400000000000000000000026251514314607700265630ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/connected-squares-x-symbolic.svg000066400000000000000000000022541514314607700304250ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/copy-symbolic.svg000066400000000000000000000013671514314607700255130ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/cross-large-circle-filled-symbolic.svg000066400000000000000000000016201514314607700314460ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/delay-symbolic.svg000066400000000000000000000021601514314607700256270ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/device-support-adaptive-symbolic.svg000066400000000000000000000015401514314607700312760ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/device-support-desktop-symbolic.svg000066400000000000000000000010371514314607700311530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/device-support-touch-symbolic.svg000066400000000000000000000021201514314607700306160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/device-supported-symbolic.svg000066400000000000000000000015501514314607700300150ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/download-plus-symbolic.svg000066400000000000000000000034401514314607700273230ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/drive-harddisk-symbolic.svg000066400000000000000000000012141514314607700274300ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/earth-symbolic.svg000066400000000000000000000043301514314607700256350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/edit-clear-all-symbolic.svg000066400000000000000000000023131514314607700273100ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/execute-to-symbolic.svg000066400000000000000000000006221514314607700266140ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/external-link-symbolic.svg000066400000000000000000000024241514314607700273110ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/eye-outline-filled-symbolic.svg000066400000000000000000000015401514314607700302260ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/flathub-symbolic.svg000066400000000000000000000037161514314607700261660ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/flatpak-symbolic.svg000066400000000000000000000013241514314607700261540ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/folder-download-symbolic.svg000066400000000000000000000011661514314607700276160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/globe-symbolic.svg000066400000000000000000000052701514314607700256260ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/go-previous-symbolic.svg000066400000000000000000000011761514314607700270160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/graph2-symbolic.svg000066400000000000000000000010761514314607700257210ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/hand-openyay-symbolic.svg000066400000000000000000000014161514314607700271300ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/heart-filled-symbolic.svg000066400000000000000000000011251514314607700270710ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/heart-outline-thick-symbolic.svg000066400000000000000000000023271514314607700304160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/horizontal-arrows-disabled-symbolic.svg000066400000000000000000000026451514314607700320120ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/image-missing-symbolic.svg000066400000000000000000000015221514314607700272630ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/left-large-symbolic.svg000066400000000000000000000007431514314607700265600ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/library-symbolic.svg000066400000000000000000000021101514314607700261700ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/license-symbolic.svg000066400000000000000000000056411514314607700261620ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/media-playback-pause-symbolic.svg000066400000000000000000000010071514314607700305060ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/media-playback-start-symbolic.svg000066400000000000000000000010521514314607700305260ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/media-playback-stop-symbolic.svg000066400000000000000000000005311514314607700303570ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/newspaper-symbolic.svg000066400000000000000000000015301514314607700265350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/on-the-go-symbolic.svg000066400000000000000000000062571514314607700263410ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/parent-symbolic.svg000066400000000000000000000025761514314607700260350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/people-symbolic.svg000066400000000000000000000015511514314607700260200ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-legacy-windowing-system-symbolic.svg000066400000000000000000000012521514314607700336740ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-microphone-symbolic.svg000066400000000000000000000007511514314607700312510ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-sandboxed-symbolic.svg000066400000000000000000000022121514314607700310470ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-screen-contents-symbolic.svg000066400000000000000000000010631514314607700322150ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-system-devices-symbolic.svg000066400000000000000000000021471514314607700320530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/permissions-warning-symbolic.svg000066400000000000000000000015611514314607700305530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/person-symbolic.svg000066400000000000000000000006021514314607700260360ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/pip-out-symbolic.svg000066400000000000000000000017071514314607700261340ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/power-profile-performance-symbolic.svg000066400000000000000000000022631514314607700316260ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/proprietary-code-symbolic.svg000066400000000000000000000024131514314607700300220ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/puzzle-piece-symbolic.svg000066400000000000000000000012031514314607700271420ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/000077500000000000000000000000001514314607700236415ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/advertising-none-symbolic.svg000066400000000000000000000015721514314607700314620ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/advertising-symbolic.svg000066400000000000000000000016051514314607700305220ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/alcohol-use-none-symbolic.svg000066400000000000000000000013371514314607700313550ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/alcohol-use-symbolic.svg000066400000000000000000000012471514314607700304200ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/audio-chat-none-symbolic.svg000066400000000000000000000011521514314607700311530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/audio-chat-symbolic.svg000066400000000000000000000007511514314607700302220ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/contacts-symbolic.svg000066400000000000000000000020201514314607700300110ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/drug-use-none-symbolic.svg000066400000000000000000000017011514314607700306700ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/drug-use-symbolic.svg000066400000000000000000000015261514314607700277400ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/gambling-none-symbolic.svg000066400000000000000000000010271514314607700307160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/gambling-symbolic.svg000066400000000000000000000007501514314607700277630ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/human-remains-symbolic.svg000066400000000000000000000006141514314607700307460ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/messaging-none-symbolic.svg000066400000000000000000000010051514314607700311070ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/messaging-symbolic.svg000066400000000000000000000006561514314607700301650ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/money-none-symbolic.svg000066400000000000000000000011461514314607700302670ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/money-symbolic.svg000066400000000000000000000007621514314607700273350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/nudity-none-symbolic.svg000066400000000000000000000013101514314607700304450ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/nudity-symbolic.svg000066400000000000000000000007601514314607700275200ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/smoking-none-symbolic.svg000066400000000000000000000007431514314607700306110ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/smoking-symbolic.svg000066400000000000000000000006551514314607700276560ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/social-info-symbolic.svg000066400000000000000000000017551514314607700304140ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/strong-language-none-symbolic.svg000066400000000000000000000006571514314607700322430ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/strong-language-symbolic.svg000066400000000000000000000005371514314607700313030ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/violence-none-symbolic.svg000066400000000000000000000010171514314607700307410ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/ratings/violence-symbolic.svg000066400000000000000000000005511514314607700300060ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/regex-symbolic.svg000066400000000000000000000011721514314607700256450ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/right-large-symbolic.svg000066400000000000000000000007441514314607700267440ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/sad-computer-symbolic.svg000066400000000000000000000022241514314607700271350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/server-pick-symbolic.svg000066400000000000000000000016521514314607700267700ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/share-alt-symbolic.svg000066400000000000000000000015711514314607700264160ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/share-symbolic.svg000066400000000000000000000021751514314607700256410ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/sidebar-show-symbolic.svg000066400000000000000000000011421514314607700271170ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/sliders-horizontal-symbolic.svg000066400000000000000000000017671514314607700304010ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/smartphone2-symbolic.svg000066400000000000000000000010161514314607700267720ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/software-update-available-symbolic.svg000066400000000000000000000021511514314607700315610ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/square-filled-symbolic.svg000066400000000000000000000004761514314607700272760ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/starred-symbolic.svg000066400000000000000000000013171514314607700262000ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/thumbs-up-outline-symbolic.svg000066400000000000000000000032701514314607700301350ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/timer-sand-symbolic.svg000066400000000000000000000010571514314607700266000ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/translations-symbolic.svg000066400000000000000000000012061514314607700272520ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/user-trash-symbolic.svg000066400000000000000000000020501514314607700266240ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/verified-checkmark-symbolic.svg000066400000000000000000000030611514314607700302550ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/view-more-horizontal-symbolic.svg000066400000000000000000000010271514314607700306330ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/view-more-symbolic.svg000066400000000000000000000007631514314607700264520ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/we-love-games-symbolic.svg000066400000000000000000000130211514314607700271770ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/zoom-minus-symbolic.svg000066400000000000000000000013371514314607700266530ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/icons/scalable/actions/zoom-plus-symbolic.svg000066400000000000000000000014031514314607700264750ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/main-config-schema.xml000066400000000000000000000007701514314607700220240ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/main.c000066400000000000000000000033211514314607700167400ustar00rootroot00000000000000/* main.c * * Copyright 2025 Adam Masciola * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "BAZAAR::MAIN" #include "config.h" #include #include #include "bz-application.h" int main (int argc, char *argv[]) { g_autoptr (BzApplication) app = NULL; int result = 0; if (argc > 1 && g_strcmp0 (argv[1], "--version") == 0) { g_print ("%s\n", PACKAGE_VERSION); return 0; } g_debug ("Initializing libdex..."); dex_init (); g_debug ("Configuring textdomain..."); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); g_debug ("Constructing main application object..."); app = g_object_new ( BZ_TYPE_APPLICATION, "application-id", "io.github.kolunmi.Bazaar", "flags", G_APPLICATION_HANDLES_COMMAND_LINE, "resource-base-path", "/io/github/kolunmi/Bazaar", NULL); g_debug ("Running!"); result = g_application_run (G_APPLICATION (app), argc, argv); return result; } kolunmi-bazaar-7b9c8e1/src/meson.build000066400000000000000000000202271514314607700200160ustar00rootroot00000000000000math = cc.find_library('m', required: false) gtk_dep = dependency('gtk4') libadwaita_dep = dependency('libadwaita-1', version: '>= 1.8') libdex_dep = dependency('libdex-1', version: '>= 1.0.0') flatpak_dep = dependency('flatpak', version: '>= 1.9') appstream_dep = dependency('appstream', version: '>= 1.0') xmlb_dep = dependency('xmlb', version: '>= 0.3.4') yaml_dep = dependency('yaml-0.1', version: '>= 0.2.5') libsoup_dep = dependency('libsoup-3.0', version: '>= 3.6.0') json_glib_dep = dependency('json-glib-1.0', version: '>= 1.10.0') glycin_dep = dependency('glycin-2', version: '>= 2.0') glycin_gtk4_dep = dependency('glycin-gtk4-2', version: '>= 2.0') md4c_dep = dependency('md4c', version: '>= 0.5.1') webkit_dep = dependency('webkitgtk-6.0', version: '>= 2.50.2') libsecret_dep = dependency('libsecret-1', version: '>= 0.20') dl_worker_sources = [ 'bz-env.c', 'bz-global-net.c', 'dl-worker.c', ] dl_worker_deps = [ math, libdex_dep, libsoup_dep, json_glib_dep, ] dl_worker_exe = executable(dl_worker_bin_name, dl_worker_sources, dependencies: dl_worker_deps, install: true, ) marshalers = gnome.genmarshal('bz-marshalers', sources: 'bz-marshalers.list', prefix: 'bz_marshal', valist_marshallers: true, ) gdbus_src = gnome.gdbus_codegen( 'gs-shell-search-provider-generated', 'shell-search-provider-dbus-interfaces.xml', interface_prefix : 'org.gnome.', namespace : 'Bz', ) bz_sources = files( 'bz-addons-dialog.c', 'bz-donations-dialog.c', 'bz-age-rating-dialog.c', 'bz-all-apps-page.c', 'bz-animation.c', 'bz-app-permissions.c', 'bz-app-size-dialog.c', 'bz-app-tile.c', 'bz-application-map-factory.c', 'bz-application.c', 'bz-apps-page.c', 'bz-appstream-description-render.c', 'bz-appstream-parser.c', 'bz-async-texture.c', 'bz-auth-state.c', 'bz-backend.c', 'bz-carousel-indicator-dots.c', 'bz-carousel.c', 'bz-category-tile.c', 'bz-comet-overlay.c', 'bz-content-provider.c', 'bz-context-row.c', 'bz-context-tile.c', 'bz-curated-app-tile.c', 'bz-curated-view.c', 'bz-data-graph.c', 'bz-decorated-screenshot.c', 'bz-developer-badge.c', 'bz-download-worker.c', 'bz-dynamic-list-view.c', 'bz-entry-cache-manager.c', 'bz-entry-group-util.c', 'bz-entry-group.c', 'bz-entry-inspector.c', 'bz-entry-selection-row.c', 'bz-entry.c', 'bz-env.c', 'bz-error.c', 'bz-fading-clamp.c', 'bz-favorite-button.c', 'bz-favorites-page.c', 'bz-favorites-tile.c', 'bz-featured-carousel.c', 'bz-featured-tile.c', 'bz-flathub-category-section.c', 'bz-flathub-category.c', 'bz-flathub-category.c', 'bz-flathub-page.c', 'bz-flathub-state.c', 'bz-flatpak-entry.c', 'bz-flatpak-instance.c', 'bz-full-view.c', 'bz-global-net.c', 'bz-global-progress.c', 'bz-gnome-shell-search-provider.c', 'bz-group-tile-css-watcher.c', 'bz-hardware-support-dialog.c', 'bz-inhibited-scrollable.c', 'bz-inspector.c', 'bz-installed-tile.c', 'bz-io.c', 'bz-lazy-async-texture-model.c', 'bz-library-page.c', 'bz-license-dialog.c', 'bz-list-tile.c', 'bz-login-page.c', 'bz-lozenge.c', 'bz-markdown-render.c', 'bz-newline-parser.c', 'bz-parser.c', 'bz-popup-overlay.c', 'bz-preferences-dialog.c', 'bz-progress-bar.c', 'bz-releases-list.c', 'bz-result.c', 'bz-rich-app-tile.c', 'bz-rounded-picture.c', 'bz-row-view.c', 'bz-safety-calculator.c', 'bz-safety-dialog.c', 'bz-screenshot-page.c', 'bz-screenshot.c', 'bz-screenshots-carousel.c', 'bz-search-engine.c', 'bz-search-widget.c', 'bz-section-view.c', 'bz-serializable.c', 'bz-share-list.c', 'bz-spdx.c', 'bz-stats-dialog.c', 'bz-subcategory-list.c', 'bz-tag-list.c', 'bz-template-callbacks.c', 'bz-themed-entry-group-rect.c', 'bz-transaction-dialog.c', 'bz-transaction-list-dialog.c', 'bz-transaction-manager.c', 'bz-transaction-tile.c', 'bz-transaction.c', 'bz-updates-card.c', 'bz-user-data-page.c', 'bz-user-data-tile.c', #'bz-view-switcher-button.c', #'bz-view-switcher.c', 'bz-window.c', 'bz-world-map-parser.c', 'bz-world-map.c', 'bz-yaml-parser.c', 'bz-zoom.c', 'main.c', ) subdir('progress-bar-designs') bz_deps = [ math, gtk_dep, libadwaita_dep, flatpak_dep, appstream_dep, xmlb_dep, yaml_dep, libsoup_dep, json_glib_dep, libdex_dep, glycin_dep, glycin_gtk4_dep, md4c_dep, webkit_dep, libsecret_dep, ] gen_gobject = find_program('./gen_gobject.sh') gen_gobject_header = generator( gen_gobject, output: '@BASENAME@.h', arguments: ['--header', '@INPUT@', '@OUTPUT@'], ) gen_gobject_code = generator( gen_gobject, output: '@BASENAME@.c', arguments: ['--code', '@INPUT@', '@OUTPUT@'], ) gobject_specs = files( 'bz-age-rating-attribute.txt', 'bz-backend-notification.txt', 'bz-backend-transaction-op-payload.txt', 'bz-backend-transaction-op-progress-payload.txt', 'bz-blocklist-condition-match-envvar.txt', 'bz-blocklist-condition-match-locale.txt', 'bz-blocklist-condition.txt', 'bz-blocklist.txt', 'bz-bulk-install-dialog-result.txt', 'bz-comet.txt', 'bz-country-data-point.txt', 'bz-country.txt', 'bz-curated-category-info.txt', 'bz-curated-image-info.txt', 'bz-curated-markdown-info.txt', 'bz-curated-row.txt', 'bz-curated-section.txt', 'bz-data-point.txt', 'bz-flathub-auth-provider.txt', 'bz-flathub-sub-category.txt', 'bz-hash-table-object.txt', 'bz-hook-dialog-option.txt', 'bz-hook-dialog.txt', 'bz-hook.txt', 'bz-main-config.txt', 'bz-pride-flag-config.txt', 'bz-pride-flag-spec.txt', 'bz-pride-flag-stripe-spec.txt', 'bz-release.txt', 'bz-repository.txt', 'bz-root-blocklist.txt', 'bz-root-curated-config.txt', 'bz-safety-row.txt', 'bz-search-result.txt', 'bz-state-info.txt', 'bz-transaction-dialog-result.txt', 'bz-transaction-entry-tracker.txt', 'bz-transaction-task.txt', 'bz-url.txt', 'bz-verification-status.txt', ) gen_gobject_srcs = [] foreach f : gobject_specs header = gen_gobject_header.process(f) code = gen_gobject_code.process(f) gen_gobject_srcs += [header, code] endforeach generated_gobjects = declare_dependency( sources: gen_gobject_srcs, ) bz_deps += [ generated_gobjects ] blueprints = custom_target('blueprints', input: files( 'bz-addons-dialog.blp', 'bz-donations-dialog.blp', 'bz-age-rating-dialog.blp', 'bz-all-apps-page.blp', 'bz-app-size-dialog.blp', 'bz-app-tile.blp', 'bz-apps-page.blp', 'bz-appstream-description-render.blp', 'bz-category-tile.blp', 'bz-context-tile.blp', 'bz-curated-app-tile.blp', 'bz-curated-view.blp', 'bz-decorated-screenshot.blp', 'bz-developer-badge.blp', 'bz-entry-inspector.blp', 'bz-entry-selection-row.blp', 'bz-favorite-button.blp', 'bz-favorites-page.blp', 'bz-favorites-tile.blp', 'bz-featured-carousel.blp', 'bz-featured-tile.blp', 'bz-flathub-category-section.blp', 'bz-flathub-page.blp', 'bz-full-view.blp', 'bz-hardware-support-dialog.blp', 'bz-inspector.blp', 'bz-installed-tile.blp', 'bz-library-page.blp', 'bz-license-dialog.blp', 'bz-login-page.blp', 'bz-markdown-render.blp', 'bz-preferences-dialog.blp', 'bz-progress-bar.blp', 'bz-releases-dialog.blp', 'bz-releases-list.blp', 'bz-rich-app-tile.blp', 'bz-row-view.blp', 'bz-safety-dialog.blp', 'bz-screenshot-page.blp', 'bz-screenshots-carousel.blp', 'bz-search-widget.blp', 'bz-section-view.blp', 'bz-stats-dialog.blp', 'bz-transaction-list-dialog.blp', 'bz-transaction-tile.blp', 'bz-updates-card.blp', 'bz-user-data-page.blp', 'bz-user-data-tile.blp', #'bz-view-switcher-button.blp', 'bz-window.blp', 'gtk/shortcuts-dialog.blp', ), output: '.', command: [ find_program('blueprint-compiler', version: '>= 0.18.0'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@' ], ) bz_sources += gnome.compile_resources('bz-resources', 'bazaar.gresource.xml', c_name: 'bz', dependencies: blueprints ) executable('bazaar', bz_sources, gdbus_src, marshalers, dependencies: bz_deps, install: true, ) kolunmi-bazaar-7b9c8e1/src/pride-flag-config-schema.xml000066400000000000000000000003201514314607700231010ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/000077500000000000000000000000001514314607700217115ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/common.h000066400000000000000000000014421514314607700233530ustar00rootroot00000000000000/* progress-bar-designs/common.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include "pride/pride.h" kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/meson.build000066400000000000000000000000201514314607700240430ustar00rootroot00000000000000subdir('pride') kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/pride/000077500000000000000000000000001514314607700230145ustar00rootroot00000000000000kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/pride/meson.build000066400000000000000000000000441514314607700251540ustar00rootroot00000000000000bz_sources += files( 'pride.c', ) kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/pride/pride-flags.yaml000066400000000000000000000162151514314607700261020ustar00rootroot00000000000000flag-specs: - # the internal ID of the flag; this should match the gsettings file at # /data/io.github.kolunmi.Bazaar.gschema.xml id: "pride-rainbow-flag" # the user-facing name name: "Pride Rainbow Flag" # (optional) set to true if the flag is homogeneous, or put more # shrimply(🦐) each stripe has the same vertical size homogeneous: true # the direction in which the stripes are drawn (css format) direction: to bottom # list of stripe specs stripes: &pride-rainbow-flag-stripes - # all stripes must provide the `rgba` field, which will is the color of # the stripe. Many formats are supported for this; here is a snippet # from the GDK source, listing the formats: # # - A standard name (Taken from the CSS specification). # - A hexadecimal value in the form “#rgb”, “#rrggbb”, # “#rrrgggbbb” or ”#rrrrggggbbbb” # - A hexadecimal value in the form “#rgba”, “#rrggbbaa”, # or ”#rrrrggggbbbbaaaa” # - A RGB color in the form “rgb(r,g,b)” (In this case the color # will have full opacity) # - A RGBA color in the form “rgba(r,g,b,a)” # - A HSL color in the form "hsl(hue, saturation, lightness)" # - A HSLA color in the form "hsla(hue, saturation, lightness, alpha)" # # for more information, see # https://docs.gtk.org/gdk4/method.RGBA.parse.html rgba: "#E40303" # if the above `homogeneous` field is set to `true`, then this field can # be omitted. otherwise, this value is a floating point number from 0.0 # to 1.0 representing the size of this stripe as a percentage of the # flag's pixel height in the UI. so if this strip should take up 20% of # the vertical space, put `0.2`, as shown here. Since the `homogeneous` # field was set to `true` on this flag, this is ignored size: 0.2 - rgba: "#FF8C00" - rgba: "#FFED00" - rgba: "#008026" - rgba: "#24408E" - rgba: "#732982" - id: "lesbian-pride-flag" name: "Lesbian Pride Flag" homogeneous: true direction: to bottom stripes: &lesbian-flag-stripes - rgba: "#D62800" - rgba: "#EF7627" - rgba: "#FF9B56" - rgba: "#FFFFFF" - rgba: "#D162A4" - rgba: "#B55690" - rgba: "#A30262" - id: "gay-pride-flag" name: "Gay Pride Flag" homogeneous: true direction: to bottom stripes: &gay-pride-flag-stripes - rgba: "#018E71" - rgba: "#21CFAC" - rgba: "#9AE9C3" - rgba: "#FFFFFF" - rgba: "#7CAFE4" - rgba: "#4F47CC" - rgba: "#3C1379" - id: "transgender-flag" name: "Transgender Flag" homogeneous: true direction: to bottom stripes: &transgender-flag-stripes - rgba: "#5BCEFA" - rgba: "#F5A9B8" - rgba: "#FFFFFF" - rgba: "#F5A9B8" - rgba: "#5BCEFA" - id: "nonbinary-flag" name: "Nonbinary Flag" homogeneous: true direction: to bottom stripes: &nonbinary-flag-stripes - rgba: "#FCF434" - rgba: "#FFFFFF" - rgba: "#9C59D1" - rgba: "#2C2C2C" - id: "bisexual-flag" name: "Bisexual Flag" direction: to bottom stripes: &bisexual-flag-stripes - rgba: "#D60270" size: 0.4 - rgba: "#9B4F96" size: 0.2 - rgba: "#0038A8" size: 0.4 - id: "asexual-flag" name: "Asexual Flag" homogeneous: true direction: to bottom stripes: &asexual-flag-stripes - rgba: "#000000" - rgba: "#A3A3A3" - rgba: "#FFFFFF" - rgba: "#810081" - id: "pansexual-flag" name: "Pansexual Flag" homogeneous: true direction: to bottom stripes: &pansexual-flag-stripes - rgba: "#FF218C" - rgba: "#FFD800" - rgba: "#21B1FF" - id: "aromantic-flag" name: "Aromantic Flag" homogeneous: true direction: to bottom stripes: &aromantic-flag-stripes - rgba: "#3DA542" - rgba: "#A7D379" - rgba: "#FFFFFF" - rgba: "#A9A9A9" - rgba: "#000000" - id: "genderfluid-flag" name: "Genderfluid Flag" homogeneous: true direction: to bottom stripes: &genderfluid-flag-stripes - rgba: "#FF76A4" - rgba: "#FFFFFF" - rgba: "#C011D7" - rgba: "#000000" - rgba: "#2F3CBE" - id: "polysexual-flag" name: "Polysexual Flag" homogeneous: true direction: to bottom stripes: &polysexual-flag-stripes - rgba: "#F61CB9" - rgba: "#07D569" - rgba: "#1C92F6" - id: "omnisexual-flag" name: "Omnisexual Flag" homogeneous: true direction: to bottom stripes: &omnisexual-flag-stripes - rgba: "#FF9CCE" - rgba: "#FF52BF" - rgba: "#200044" - rgba: "#675FFF" - rgba: "#8DA7FF" - id: "aroace-flag" name: "Aroace Flag" homogeneous: true direction: to bottom stripes: &aroace-flag-stripes - rgba: "#E28C00" - rgba: "#ECCD00" - rgba: "#FFFFFF" - rgba: "#62AEDC" - rgba: "#203856" - id: "agender-flag" name: "Agender Flag" homogeneous: true direction: to bottom stripes: &agender-flag-stripes - rgba: "#000000" - rgba: "#BCC4C7" - rgba: "#FFFFFF" - rgba: "#B7F684" - rgba: "#FFFFFF" - rgba: "#BCC4C7" - rgba: "#000000" - id: "genderqueer-flag" name: "Genderqueer Flag" homogeneous: true direction: to bottom stripes: &genderqueer-flag-stripes - rgba: "#B57EDC" - rgba: "#FFFFFF" - rgba: "#4A8123" - id: "intersex-flag" name: "Intersex Flag" direction: to bottom stripes: &intersex-flag-stripes - rgba: "#FFD800" size: 0.4 - rgba: "#7902AA" size: 0.2 - rgba: "#FFD800" size: 0.4 - id: "demigender-flag" name: "Demigender Flag" homogeneous: true direction: to bottom stripes: &demigender-flag-stripes - rgba: "#7F7F7F" - rgba: "#C3C3C3" - rgba: "#FBFF74" - rgba: "#FFFFFF" - rgba: "#FBFF74" - rgba: "#C3C3C3" - rgba: "#7F7F7F" - id: "biromantic-flag" name: "Biromantic Flag" homogeneous: true direction: to bottom stripes: &biromantic-flag-stripes - rgba: "#8869A5" - rgba: "#D8A7D8" - rgba: "#FFFFFF" - rgba: "#FDB18D" - rgba: "#151638" - id: "disability-flag" name: "Disability Flag" homogeneous: true direction: to bottom stripes: &disability-flag-stripes - rgba: "#595959" - rgba: "#CF7280" - rgba: "#EEDE77" - rgba: "#E8E8E8" - rgba: "#7BC2E0" - rgba: "#3BB07D" - rgba: "#595959" - id: "femboy-flag" name: "Femboy Flag" homogeneous: true direction: to bottom stripes: &femboy-flag-stripes - rgba: "#D460A7" - rgba: "#E4ADCD" - rgba: "#FFFFFF" - rgba: "#57CEF8" - rgba: "#FFFFFF" - rgba: "#E4ADCD" - rgba: "#D460A7" - id: "neutrois-flag" name: "Neutrois Flag" homogeneous: true direction: to bottom stripes: &neutrois-flag-stripes - rgba: "rgb(255,255,255)" - rgba: "rgb(31,159,0)" - rgba: "rgb(0,0,0)" kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/pride/pride.c000066400000000000000000000177731514314607700243020ustar00rootroot00000000000000/* progress-bar-designs/pride/pride.c * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "bz-parser.h" #include "bz-pride-flag-config.h" #include "bz-yaml-parser.h" #include "pride.h" static void generate_flag_css (GString *css, const char *id, const char *direction, gboolean homogeneous, GListModel *stripes); GtkStyleProvider * bz_get_pride_style_provider (void) { static GtkCssProvider *provider = NULL; if (g_once_init_enter_pointer (&provider)) { g_autoptr (GError) local_error = NULL; g_autoptr (GBytes) config_bytes = NULL; g_autoptr (BzYamlParser) parser = NULL; g_autoptr (GHashTable) parse_results = NULL; g_autoptr (BzPrideFlagConfig) config = NULL; g_autoptr (GtkCssProvider) tmp = NULL; config_bytes = g_resources_lookup_data ( "/io/github/kolunmi/Bazaar/pride-flags.yaml", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); g_assert (config_bytes != NULL); g_type_ensure (BZ_TYPE_PRIDE_FLAG_CONFIG); g_type_ensure (BZ_TYPE_PRIDE_FLAG_SPEC); g_type_ensure (BZ_TYPE_PRIDE_FLAG_STRIPE_SPEC); parser = bz_yaml_parser_new_for_resource_schema ( "/io/github/kolunmi/Bazaar/pride-flag-config-schema.xml"); parse_results = bz_parser_process_bytes ( BZ_PARSER (parser), config_bytes, &local_error); if (parse_results == NULL) g_critical ("Could not parse internal 'pride-flags.yaml': %s", local_error->message); g_assert (parse_results != NULL); config = g_value_dup_object (g_hash_table_lookup (parse_results, "/")); tmp = gtk_css_provider_new (); if (config != NULL) { GListModel *flag_specs = NULL; flag_specs = bz_pride_flag_config_get_flag_specs (config); if (flag_specs != NULL) { g_autoptr (GString) css = NULL; guint n_flag_specs = 0; css = g_string_new (NULL); n_flag_specs = g_list_model_get_n_items (flag_specs); for (guint i = 0; i < n_flag_specs; i++) { g_autoptr (BzPrideFlagSpec) flag_spec = NULL; const char *id = NULL; const char *name = NULL; gboolean homogeneous = FALSE; GListModel *stripes = NULL; const char *direction = NULL; flag_spec = g_list_model_get_item (flag_specs, i); id = bz_pride_flag_spec_get_id (flag_spec); name = bz_pride_flag_spec_get_name (flag_spec); homogeneous = bz_pride_flag_spec_get_homogeneous (flag_spec); stripes = bz_pride_flag_spec_get_stripes (flag_spec); direction = bz_pride_flag_spec_get_direction (flag_spec); if (id == NULL) { g_critical ("Flag spec with index %d lacks an id, skipping it", i); continue; } if (name == NULL) { g_critical ("Flag spec \"%s\" lacks an name, skipping it", id); continue; } if (stripes == NULL) { g_critical ("Flag spec \"%s\" lacks a strip list, skipping it", id); continue; } if (direction == NULL) direction = "to bottom"; generate_flag_css (css, id, direction, homogeneous, stripes); { g_autofree char *horizontal_id = NULL; const char *horizontal_direction = NULL; horizontal_id = g_strdup_printf ("%s-horizontal", id); if (g_strcmp0 (direction, "to bottom") == 0) horizontal_direction = "to right"; else if (g_strcmp0 (direction, "to top") == 0) horizontal_direction = "to left"; else if (g_strcmp0 (direction, "to left") == 0) horizontal_direction = "to top"; else if (g_strcmp0 (direction, "to right") == 0) horizontal_direction = "to bottom"; else horizontal_direction = "to right"; generate_flag_css (css, horizontal_id, horizontal_direction, homogeneous, stripes); } } if (css->len > 0) gtk_css_provider_load_from_string (tmp, css->str); } } g_once_init_leave_pointer (&provider, g_steal_pointer (&tmp)); } return GTK_STYLE_PROVIDER (provider); } char * bz_dup_css_class_for_pride_id (const char *id) { g_return_val_if_fail (id != NULL, NULL); return g_strdup_printf ("%s-theme", id); } static void generate_flag_css (GString *css, const char *id, const char *direction, gboolean homogeneous, GListModel *stripes) { g_autoptr (GString) stripe_css = NULL; guint n_stripes = 0; double cur_offset = 0.0; gboolean skip = FALSE; stripe_css = g_string_new (NULL); g_string_append_printf (stripe_css, ".%s-theme { ", id); g_string_append_printf (stripe_css, "--flag-gradient: linear-gradient(%s", direction); n_stripes = g_list_model_get_n_items (stripes); for (guint j = 0; j < n_stripes; j++) { g_autoptr (BzPrideFlagStripeSpec) stripe_spec = NULL; const char *rgba_spec = NULL; double size = 0.0; GdkRGBA rgba = { 0 }; stripe_spec = g_list_model_get_item (stripes, j); rgba_spec = bz_pride_flag_stripe_spec_get_rgba (stripe_spec); size = bz_pride_flag_stripe_spec_get_size (stripe_spec); if (rgba_spec == NULL) { g_critical ("Flag spec \"%s\" has a stripe spec which lacks an rgba spec, skipping it", id); skip = TRUE; break; } if (!gdk_rgba_parse (&rgba, rgba_spec)) { g_critical ("Flag spec \"%s\" has a stripe spec which has an invalid rgba spec, skipping it", id); skip = TRUE; break; } if (!homogeneous && (size <= 0.0 || size > 1.0)) { g_critical ("Flag spec \"%s\" has a stripe spec which has an out of bounds size, skipping it", id); skip = TRUE; break; } g_string_append_printf (stripe_css, ", %s %d%%", rgba_spec, (int) round (cur_offset * 100.0)); cur_offset += homogeneous ? 1.0 / (double) n_stripes : size; if (cur_offset > 1.0) { g_critical ("Flag spec \"%s\" has a stripe spec which exceeds the height of the flag, skipping it", id); skip = TRUE; break; } g_string_append_printf (stripe_css, ", %s %d%%", rgba_spec, (int) round (cur_offset * 100.0)); } if (skip) return; g_string_append (stripe_css, "); }\n"); g_string_append_len (css, stripe_css->str, stripe_css->len); } kolunmi-bazaar-7b9c8e1/src/progress-bar-designs/pride/pride.h000066400000000000000000000016571514314607700243010ustar00rootroot00000000000000/* progress-bar-designs/pride/pride.h * * Copyright 2025 Eva M * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS GtkStyleProvider * bz_get_pride_style_provider (void); char * bz_dup_css_class_for_pride_id (const char *id); G_END_DECLS kolunmi-bazaar-7b9c8e1/src/release-notes.xml000066400000000000000000000005651514314607700211470ustar00rootroot00000000000000

This release comes with the following improvements:

  • Better track installed versions of apps
  • Add `enable-bulk-install` key to curated sections
  • Introduce the app library page
  • Add donations dialog
  • Fix broken addon and runtime eol detection
  • Add `override-eol-markings` main config string list
kolunmi-bazaar-7b9c8e1/src/shell-search-provider-dbus-interfaces.xml000066400000000000000000000035031514314607700256520ustar00rootroot00000000000000 kolunmi-bazaar-7b9c8e1/translators.sh000077500000000000000000000074251514314607700200050ustar00rootroot00000000000000#!/usr/bin/env bash # Helper script that automates the preparation steps to translate Bazaar. # # The script will add the passed language code to the LINGUAS file to avoid # editing it manually. # also: # It will reorder the contents of the file alphabetically; # It will check if the code is already in the file; # It will show the contents of the LINGUAS file, allowing a visual check; # It won't really check if the locale code is valid but will inform you # that it is not in the list of codes inside /usr/share/locale; # It will generate a .backup inside /tmp before proceeding and a .tmp file # before overwriting LINGUAS. # translators_helper() { local lang_input local lang_f local po_d local build_d local system_langs local langs_in_file local temp_file lang_f="LINGUAS" po_d="po" build_d="build" mapfile -t system_langs < <(find /usr/share/locale/ -maxdepth 1 -type d -printf "%f\n") temp_file="$(mktemp --suffix=BAZAAR)" printf "Temporary file: %s\n" "${temp_file}" printf "Setting im_a_translator to true\n" meson setup build -Dim_a_translator=true || return 1 pushd "${po_d}" >/dev/null || return 1 langs_in_file="$(wc --lines "${lang_f}" | grep --only-matching --extended-regex "[0-9]{1,}")" printf "\nNumber of languages currently in file %s\n" "${langs_in_file}" unset langs_in_file printf "Language codes currently in %s file.\n" "${lang_f}" cat --squeeze-blank "${lang_f}" read -r -n 1 -p "Proceed? (Type y or Y to confirm)" YN case "$YN" in [Yy]) printf "\n%s\n" "Proceeding..." ;; *) printf "\n%s\n" "Leaving..." exit 3 ;; esac printf "\nCopying %s to /tmp/%s\n" "${lang_f}" "${lang_f}.backup" cp --verbose "${lang_f}" "/tmp/${lang_f}.backup" read -r -p "Type the language code you want to enable translation for. ex.: pt_BR or es: " lang_input if [[ "${system_langs[*]}" =~ ${lang_input} ]]; then printf "Found %s in the system's language code list.\n" "${lang_input}" sleep 2s else printf "Could not find \"%s\" in the system's language code list, but proceeding nonetheless.\n" "${lang_input}" sleep 2s fi if grep --only-matching "${lang_input}" "${lang_f}"; then printf "%s already in file\n" "${lang_input}" sleep 2s else printf "Language to be added: %s\n" "${lang_input}" printf "%s\n" "${lang_input}" | tee -p --append "${lang_f}" 2>&1 sleep 2s fi cat --squeeze-blank "${lang_f}" | ( sed --unbuffered 1q sort ) | tee -p "${temp_file}" cat --squeeze-blank "${temp_file}" >"${lang_f}" langs_in_file="$(wc --lines "${lang_f}" | grep --only-matching --extended-regex "[0-9]{1,}")" printf "Number of languages currently in file %s\n" "${langs_in_file}" unset langs_in_file cat --squeeze-blank "${temp_file}" cat --squeeze-blank "${lang_f}" # $EDITOR LINGUAS popd || return 1 pushd "${build_d}" || return 1 printf "Generating the main pot (Portable Object Template) file for lang %s...\n" "${lang_input}" meson compile bazaar-pot printf "Update and/or create the po (Portable Object) files for %s.\n" "${lang_input}" meson compile bazaar-update-po echo "--------------------------------" printf "\nConfiguration done. Now ready for you to open your \"po\" file in your text editor and begin translating.\n" printf "When you are done, commit your changes form your fork and submit a pull request on \n%s also, refer to TRANSLATORS.md if needed\e]8;;\e\\ \n\n" "https://github.com/kolunmi/bazaar/blob/master/TRANSLATORS.md" echo "--------------------------------" popd || return 1 return 0 } translators_helper || echo 'An error occurred; review the above output' 2>&1 kolunmi-bazaar-7b9c8e1/version.sh000077500000000000000000000007661514314607700171170ustar00rootroot00000000000000#!/bin/sh INSTR="$1" VERSION=0.7.8 case "$INSTR" in get-vcs) VCS_VERSION="$(git -C "$MESON_SOURCE_ROOT" describe --always --dirty)" if [ -n "$VCS_VERSION" ]; then echo "${VERSION} (vcs=${VCS_VERSION})" else echo "${VERSION}" fi ;; get-gh-release) TAG="v${VERSION}" echo "https://github.com/kolunmi/bazaar/releases/tag/${TAG}" ;; *) echo invalid arguments 1>&2 exit 1 ;; esac